REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
src/TRestWimpSensitivity.cxx
1 /*************************************************************************
2  * This file is part of the REST software framework. *
3  * *
4  * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) *
5  * For more information see http://gifna.unizar.es/trex *
6  * *
7  * REST is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * REST is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have a copy of the GNU General Public License along with *
18  * REST in $REST_PATH/LICENSE. *
19  * If not, see http://www.gnu.org/licenses/. *
20  * For the list of contributors see $REST_PATH/CREDITS. *
21  *************************************************************************/
22 
113 
114 #include "TRestWimpSensitivity.h"
115 #include "TRestWimpUtils.h"
116 
117 ClassImp(TRestWimpSensitivity);
118 
119 using namespace std;
120 
128 TRestWimpSensitivity::TRestWimpSensitivity(const char* configFilename, const string& name)
129  : TRestMetadata(configFilename) {
130  Initialize();
131 
133 }
138 
143  SetSectionName(this->ClassName());
144  SetLibraryVersion(LIBRARY_VERSION);
145 }
146 
152  this->Initialize();
154  ReadNuclei();
155 }
156 
162  fNuclei.clear();
163 
164  TiXmlElement* ElementDef = GetElement("addElement");
165  while (ElementDef) {
166  TRestWimpNucleus nucleus;
167  nucleus.fNucleusName = GetFieldValue("nucleusName", ElementDef);
168  nucleus.fAnum = StringToDouble(GetFieldValue("anum", ElementDef));
169  nucleus.fZnum = StringToInteger(GetFieldValue("znum", ElementDef));
170  nucleus.fAbundance = StringToDouble(GetFieldValue("abundance", ElementDef));
171  fNuclei.emplace_back(nucleus);
172  ElementDef = GetNextElement(ElementDef);
173  }
174 }
175 
180 std::map<std::string, TH1D*> TRestWimpSensitivity::GetRecoilSpectra(const double wimpMass,
181  const double crossSection) {
182  std::map<std::string, TH1D*> recoilMap;
183 
184  const int nBins = (fEnergySpectra.Y() - fEnergySpectra.X()) / fEnergySpectraStep;
185 
186  for (auto& nucl : fNuclei) {
187  std::string histName = "RecoilSpc_" + std::string(nucl.fNucleusName);
188  TH1D* recoilSpc =
189  new TH1D(histName.c_str(), histName.c_str(), nBins, fEnergySpectra.X(), fEnergySpectra.Y());
190  for (int i = 1; i < recoilSpc->GetNbinsX(); i++) {
191  const double recoilEnergy = recoilSpc->GetBinCenter(i);
192  const double recoilRate =
193  TRestWimpUtils::GetRecoilRate(wimpMass, crossSection, recoilEnergy, nucl.fAnum, fLabVelocity,
194  fRmsVelocity, fEscapeVelocity, fWimpDensity, nucl.fAbundance);
195  recoilSpc->SetBinContent(i, recoilRate);
196  }
197  recoilMap[std::string(nucl.fNucleusName)] = recoilSpc;
198  }
199 
200  return recoilMap;
201 }
202 
206 const Double_t TRestWimpSensitivity::GetSensitivity(const double wimpMass) {
207  if (fNuclei.empty()) {
208  RESTError << "Please add at least one element to the rml file" << RESTendl;
209  }
210 
212 
213  const int nBins = (fEnergySpectra.Y() - fEnergySpectra.X()) / fEnergySpectraStep;
214 
215  TH1D recoilSpc("recoilSpc", "recoilSpc", nBins, fEnergySpectra.X(), fEnergySpectra.Y());
216 
217  double bckCounts = 0;
218 
219  for (int i = 1; i < recoilSpc.GetNbinsX(); i++) {
220  const double en = recoilSpc.GetBinCenter(i);
221  if (en < fEnergyRange.X() || en > fEnergyRange.Y()) continue;
222  bckCounts += fBackground * fEnergySpectraStep;
223  }
224  bckCounts *= fExposure;
225 
226  double signalCounts = 0, prob = 0;
227 
228  do {
229  prob = 0;
230  for (int mu = signalCounts; mu < (signalCounts + bckCounts + 10000); mu++) {
231  if (bckCounts <= 1.e3)
232  prob += TMath::Poisson(mu + bckCounts, bckCounts);
233  else if (bckCounts > 1.e3)
234  prob += TMath::Gaus(mu + bckCounts, bckCounts, TMath::Sqrt(bckCounts), true);
235  }
236  signalCounts++;
237  } while (fabs(prob - 0.1) > 0.01 && signalCounts < 1E6);
238 
239  double nMeas = 0;
240  const double crossSection = 1E-45;
241 
242  for (auto& nucl : fNuclei) {
243  recoilSpc.Reset();
244 
245  for (int i = 1; i < recoilSpc.GetNbinsX(); i++) {
246  const double recoilEnergy = recoilSpc.GetBinCenter(i);
247  const double recoilRate =
248  TRestWimpUtils::GetRecoilRate(wimpMass, crossSection, recoilEnergy, nucl.fAnum, fLabVelocity,
249  fRmsVelocity, fEscapeVelocity, fWimpDensity, nucl.fAbundance);
250  recoilSpc.SetBinContent(i, recoilRate);
251  }
252 
253  for (int i = 1; i < recoilSpc.GetNbinsX(); i++) {
254  double recoilEnergy = recoilSpc.GetBinCenter(i);
255  // const double recoilRate = recoilSpc.GetBinContent(i);
257  recoilEnergy *= quenchingFactor[std::string(nucl.fNucleusName)]->GetBinContent(i);
258 
259  if (recoilEnergy < fEnergyRange.X() || recoilEnergy > fEnergyRange.Y()) continue;
260  nMeas += recoilSpc.GetBinContent(i) * fEnergySpectraStep;
261  }
262  }
263 
264  if (nMeas == 0) return 0;
265 
266  const double sensitivity = signalCounts * 1E-45 / (nMeas * fExposure);
267 
268  return sensitivity;
269 }
270 
276  if (!quenchingFactor.empty()) return;
277 
278  std::cout << "Calculating quenching factor " << std::endl;
279 
280  const int nBins = (fEnergySpectra.Y() - fEnergySpectra.X()) / fEnergySpectraStep;
281 
282  for (auto& nucl : fNuclei) {
283  std::string histName = "QF_" + std::string(nucl.fNucleusName);
284  TH1D* QF =
285  new TH1D(histName.c_str(), histName.c_str(), nBins, fEnergySpectra.X(), fEnergySpectra.Y());
286  for (int i = 1; i < QF->GetNbinsX(); i++) {
287  const double recoilEnergy = QF->GetBinCenter(i);
288  const double qF = TRestWimpUtils::GetQuenchingFactor(recoilEnergy, nucl.fAnum, nucl.fZnum);
289  if (!isnan(qF) && qF > 0)
290  QF->SetBinContent(i, 1. / qF);
291  else
292  QF->SetBinContent(i, 0);
293  }
294  quenchingFactor[std::string(nucl.fNucleusName)] = QF;
295  }
296 }
297 
302 const std::string TRestWimpSensitivity::BuildOutputFileName(const std::string& extension) {
303  std::stringstream ss;
304  ss << "WimpSensitivity_";
305 
306  for (auto& nucl : fNuclei) ss << nucl.fNucleusName << "_" << nucl.fAbundance << "_";
307 
308  ss << "WD_" << fWimpDensity << "_";
309  ss << "Vel_" << fLabVelocity << "_" << fRmsVelocity << "_" << fEscapeVelocity << "_";
310  ss << "Bck_" << fBackground << "_";
311  ss << "RecEn_" << fEnergySpectra.X() << "_" << fEnergySpectra.Y() << "_" << fEnergySpectraStep << "_";
312  ss << "EnRange_" << fEnergyRange.X() << "_" << fEnergyRange.Y() << "_";
313 
315  ss << "usingQF";
316  else
317  ss << "noQF";
318 
319  ss << extension;
320 
321  std::cout << "Output File " << ss.str() << std::endl;
322 
323  return ss.str();
324 }
325 
330 std::map<std::string, TH1D*> TRestWimpSensitivity::GetFormFactor() {
331  std::map<std::string, TH1D*> formFactor;
332 
333  const int nBins = (fEnergySpectra.Y() - fEnergySpectra.X()) / fEnergySpectraStep;
334 
335  for (auto& nucl : fNuclei) {
336  std::string histName = "FF_" + std::string(nucl.fNucleusName);
337  TH1D* FF =
338  new TH1D(histName.c_str(), histName.c_str(), nBins, fEnergySpectra.X(), fEnergySpectra.Y());
339  for (int i = 1; i < FF->GetNbinsX(); i++) {
340  const double recoilEnergy = FF->GetBinCenter(i);
341  const double helmFF = TRestWimpUtils::GetHelmFormFactor(recoilEnergy, nucl.fAnum);
342  FF->SetBinContent(i, helmFF * helmFF);
343  }
344  formFactor[std::string(nucl.fNucleusName)] = FF;
345  }
346 
347  return formFactor;
348 }
349 
356 
357  for (auto& nucl : fNuclei) nucl.PrintNucleus();
358 
359  RESTMetadata << "WimpDensity: " << fWimpDensity << " GeV/cm3" << RESTendl;
360  RESTMetadata << "WimpVelocity; VLab: " << fLabVelocity << " VRMS: " << fRmsVelocity
361  << " VEscape: " << fEscapeVelocity << " km/s" << RESTendl;
362  RESTMetadata << "Exposure: " << fExposure << " kg*day" << RESTendl;
363  RESTMetadata << "Background Level: " << fBackground << " c/keV/day" << RESTendl;
364  RESTMetadata << "Recoil energy range: (" << fEnergySpectra.X() << ", " << fEnergySpectra.Y()
365  << ") Step: " << fEnergySpectraStep << " keV" << RESTendl;
366  RESTMetadata << "Sensitivity energy range: (" << fEnergyRange.X() << ", " << fEnergyRange.Y() << ") keV"
367  << RESTendl;
368  RESTMetadata << "Use quenching factor: " << fUseQuenchingFactor << RESTendl;
369  RESTMetadata << "+++++" << RESTendl;
370 }
A base class for any REST metadata class.
Definition: TRestMetadata.h:74
virtual void PrintMetadata()
Implemented it in the derived metadata class to print out specific metadata information.
endl_t RESTendl
Termination flag object for TRestStringOutput.
TiXmlElement * GetElement(std::string eleDeclare, TiXmlElement *e=nullptr)
Get an xml element from a given parent element, according to its declaration.
Int_t LoadConfigFromFile(const std::string &configFilename, const std::string &sectionName="")
Give the file name, find out the corresponding section. Then call the main starter.
virtual void InitFromConfigFile()
To make settings from rml file. This method must be implemented in the derived class.
void SetLibraryVersion(TString version)
Set the library version of this metadata class.
std::string GetFieldValue(std::string parName, TiXmlElement *e)
Returns the field value of an xml element which has the specified name.
void SetSectionName(std::string sName)
set the section name, clear the section content
std::string fConfigFileName
Full name of the rml file.
TiXmlElement * GetNextElement(TiXmlElement *e)
Get the next sibling xml element of this element, with same eleDeclare.
A class to store different nucleus parameters.
Double_t fAnum
Atomic number in amus.
TString fNucleusName
Nucleus name.
Double_t fAbundance
Abundance, in mass percentage.
Int_t fZnum
Number of protons.
void Initialize() override
Initialization of TRestWimpSensitivity members.
Double_t fExposure
Detector exposure in kg*day.
~TRestWimpSensitivity()
Default destructor.
void InitFromConfigFile() override
Initialization of TRestWimpSensitivity members through a RML file.
std::map< std::string, TH1D * > GetRecoilSpectra(const double wimpMass, const double crossSection)
Get recoil spectra for a given WIMP mass and cross section.
Double_t fEscapeVelocity
WIMP escape velocity (km/s)
TVector2 fEnergySpectra
Energy range for the recoil spectra in keV.
Double_t fEnergySpectraStep
Energy step for the recoil spectra in keV.
void PrintMetadata() override
Prints on screen the details about WIMP parameters, stored in TRestWimpSensitivity.
const Double_t GetSensitivity(const double wimpMass)
Get sensitivity for a give WIMP mass.
TVector2 fEnergyRange
Energy range for the sensitivity prospects in keV.
Double_t fBackground
Detector background level in c/keV/day.
std::map< std::string, TH1D * > quenchingFactor
Map containing quenching factor for a nucleus.
void CalculateQuenchingFactor()
Calculate Quenching factor and stores in a map.
Bool_t fUseQuenchingFactor
Use or not quenching factor.
Double_t fRmsVelocity
WIMP RMS velocity (km/s)
Double_t fWimpDensity
WIMP density in GeV/cm3.
Double_t fLabVelocity
WIMP velocity in the lab (Earth) frame reference in km/s.
void ReadNuclei()
Initialization of TRestWimpSensitivity members through a RML file.
TRestWimpSensitivity(const char *configFilename, const std::string &name="")
Constructor loading data from a config file.
std::map< std::string, TH1D * > GetFormFactor()
Return a map of histograms with the Form Factor of the different elements.
const std::string BuildOutputFileName(const std::string &extension=".txt")
Return output file format with different parameters used in the calculation.
std::vector< TRestWimpNucleus > fNuclei
A vector containing TRestWimpNucleus with different nucleus parameters.
Double_t StringToDouble(std::string in)
Gets a double from a string.
Int_t StringToInteger(std::string in)
Gets an integer from a string.