REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestAxionLikelihood.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 
51 
52 #include "TRestAxionLikelihood.h"
53 using namespace std;
54 
55 ClassImp(TRestAxionLikelihood);
56 //______________________________________________________________________________
57 TRestAxionLikelihood::TRestAxionLikelihood() : TRestMetadata() {
58  // TRestAxionLikelihood default constructor
59  Initialize();
60 }
61 
62 //______________________________________________________________________________
63 TRestAxionLikelihood::TRestAxionLikelihood(const char* cfgFileName, string name)
64  : TRestMetadata(cfgFileName) {
65  cout << "Entering TRestAxionLikelihood constructor( cfgFileName, name )" << endl;
66 
67  Initialize();
68 
69  LoadConfigFromFile(fConfigFileName, name);
70 
71  PrintMetadata();
72 }
73 
74 //______________________________________________________________________________
75 TRestAxionLikelihood::~TRestAxionLikelihood() {
76  // TRestAxionLikelihood destructor
77 }
78 
80  SetSectionName(this->ClassName());
81  SetLibraryVersion(LIBRARY_VERSION);
82 
83  // Buffer gas properties definition (e.g. equivalent photon mass, absorption, etc)
84  fBufferGas = new TRestAxionBufferGas();
85 
86  // Conversion probabilities as defined by van Bibber paper
87  fAxionField = new TRestAxionField();
88 
89  fAxionField->AssignBufferGas(fBufferGas);
90 
91  // Solar axion flux on earth
92  fAxionSpectrum = new TRestAxionSpectrum(fConfigFileName.c_str());
93 
94  fRandom = new TRandom3(0);
95 }
96 
97 void TRestAxionLikelihood::GenerateMonteCarlo() {
99  Double_t expTimeInSeconds = fTExpVacuum * 3600.;
100  Double_t energyRange = fErange.Y() - fErange.X();
101 
102  RESTDebug << "Energy range : " << energyRange << RESTendl;
103 
104  Double_t mean = fBackgroundLevel * fSpotArea * expTimeInSeconds * energyRange;
105 
106  fMeasuredCountsVacuum = fRandom->Poisson(mean);
107  RESTDebug << "Vacuum phase. Mean counts : " << mean << RESTendl;
108  RESTDebug << "Vacuum phase. Measured counts : " << fMeasuredCountsVacuum << RESTendl;
109 
111 
112  fMeasuredCountsPerStep.clear();
113 
114  if (fTExpPerStep >= 0) {
115  for (int n = 0; n < fNSteps; n++) {
116  // Time
117  Double_t exposureTime = fTExpPerStep;
118  if (n < 3) exposureTime = 0;
119  fExposureTimePerStep.push_back(exposureTime);
120 
121  // Density
122  Double_t rho = fLastStepDensity * (n + 1) / fNSteps;
123  fDensityInStep.push_back(rho);
124  }
125  } else if (fTExpPerStep == -2) // TODO KSVZ exclusion
126  {
127  Double_t totalDays = 0;
128  for (int n = 0; n < fNSteps; n++) {
129  // Density
130  Double_t rho = fLastStepDensity * (n + 1) / fNSteps;
131  // Double_t rho = fLastStepDensity*(n+1)/fNSteps;
132 
133  fDensityInStep.push_back(rho);
134 
135  // Time
136  fBufferGas->SetGasDensity("He", rho);
137 
138  Double_t mgamma = fBufferGas->GetPhotonMass(3.5);
139  Double_t nGamma = GetSignal(mgamma, 1., rho, 1.);
140 
141  Double_t ksvzFactor = 3.75523 * mgamma;
142  Double_t exposureTime = TMath::Log(20.) / TMath::Power(ksvzFactor, 4) / nGamma; // in hours
143 
144  if (mgamma < 0.0475) exposureTime = 0;
145  totalDays += exposureTime;
146 
147  fExposureTimePerStep.push_back(exposureTime);
148  }
149 
150  for (int n = 0; n < fNSteps; n++) {
151  cout << "Step : " << n << " Time : " << fExposureTimePerStep[n] / 12 << endl;
152  }
153 
154  Double_t shareTime =
155  (fExposureTimePerStep[4] + fExposureTimePerStep[5] + fExposureTimePerStep[6]) / 7.;
156  cout << "Share time : " << shareTime / 12. << endl;
157  for (int n = 0; n < 7; n++) fExposureTimePerStep[n] = shareTime;
158 
160 
161  Double_t totalTime = 0;
162  for (int n = 0; n < fNSteps; n++) {
163  cout << "Step : " << n << " Time : " << fExposureTimePerStep[n] / 12 << endl;
164  totalTime += fExposureTimePerStep[n] / 12.;
165  }
166 
167  GetChar();
168  }
169 
170  /*
171  debug << "Gas phase. Mean counts : " << mean << endl;
172  GetChar();
173  */
174 
175  for (int n = 0; n < fNSteps; n++) {
176  mean = fBackgroundLevel * fSpotArea * fExposureTimePerStep[n] * 3600. * energyRange;
177  Int_t counts = fRandom->Poisson(mean);
178  fMeasuredCountsPerStep.push_back(counts);
179 
180  RESTDebug << "Step : " << n << " measured : " << counts << " :: " << fMeasuredCountsPerStep.back()
181  << " counts" << RESTendl;
182  RESTDebug << "Time : " << fExposureTimePerStep[n] / 12 << " days" << RESTendl;
183  }
184 
185  RESTDebug << "Number of steps : " << fNSteps << " :: " << fMeasuredCountsPerStep.size() << RESTendl;
186 }
187 
188 void TRestAxionLikelihood::LikelihoodTest(const string& fname) {
189  FILE* f = fopen(fname.c_str(), "wt");
190 
191  for (Double_t m = 0.008; m < 10; m = m * 1.04) {
192  Double_t integral = 0;
193  Double_t gBef = 0.;
194 
195  cout << "Calculating mass : " << m << " eV" << endl;
196  cout << "-------------------------------_" << endl;
197  for (Double_t g4 = 1.e-12; g4 < 1.e10; g4 = g4 * 1.02) {
198  double l = LogLikelihood(m, g4, fMeasuredCountsVacuum, 0.0, fTExpVacuum);
199  if (l == 0) break;
200 
201  // cout << "N steps : " << fNSteps << endl;
202  for (int n = 0; n < fNSteps; n++) {
203  Double_t rho = fDensityInStep[n];
204 
205  fBufferGas->SetGasDensity("He", rho);
206 
207  // We consider only neighbout steps
208  if (fBufferGas->GetPhotonMass(3.5) - m > 0.004 || m - fBufferGas->GetPhotonMass(3.5) > 0.004)
209  continue;
210 
211  // cout << "Step n : " << n << endl;
212 
213  if (g4 == 1.e-12) cout << "Calculating Lhood for step " << n << endl;
214  if (g4 == 1.e-12) cout << "step time " << fExposureTimePerStep[n] / 12. << " days" << endl;
215  l = l * LogLikelihood(m, g4, fMeasuredCountsPerStep[n], rho, fExposureTimePerStep[n]);
216  // cout << "n : " << n << " lH : " << l << endl;
217 
218  if (l == 0) break;
219  }
220 
221  if (l == 0) break;
222  // GetChar();
223 
224  integral += l * (g4 - gBef);
225  gBef = g4;
226 
227  // cout << "g4 : " << g4 << " l : " << l << endl;
228  // fprintf( f, "%e\t%e\n", g4, l );
229  }
230  // GetChar();
231  // fclose( f );
232 
233  Double_t int95 = 0;
234  Double_t gLimit = 0;
235  gBef = 0;
236  for (Double_t g4 = 1.e-12; g4 < 1.e10; g4 = g4 * 1.02) {
237  double l = LogLikelihood(m, g4, fMeasuredCountsVacuum, 0.0, fTExpVacuum);
238  // double l = LogLikelihoodAverage( m, g4 , 0.0, fTExpVacuum );
239  if (l == 0) break;
240 
241  // cout << "N steps : " << fNSteps << endl;
242  for (int n = 0; n < fNSteps; n++) {
243  Double_t rho = fDensityInStep[n];
244  fBufferGas->SetGasDensity("He", rho);
245 
246  // We consider only neighbout steps
247  if (fBufferGas->GetPhotonMass(3.5) - m > 0.004 || m - fBufferGas->GetPhotonMass(3.5) > 0.004)
248  continue;
249 
250  l = l * LogLikelihood(m, g4, fMeasuredCountsPerStep[n], rho, fExposureTimePerStep[n]);
251  // l = l * LogLikelihoodAverage( m, g4, rho, fExposureTimePerStep[n] );
252  // cout << "n : " << n << " lH : " << l << endl;
253 
254  if (l == 0) break;
255  }
256 
257  if (l == 0) break;
258 
259  int95 += l * (g4 - gBef);
260  gBef = g4;
261 
262  // cout << "g4 : " << g4 << " l : " << l << endl;
263  // cout << "Int95 : " << int95 << " integral : " << integral << endl;
264  if (int95 / integral > 0.95) {
265  gLimit = g4;
266  cout << "gLimit : " << g4 << endl;
267  break;
268  }
269 
270  // fprintf( f, "%e\t%e\n", g4, l );
271  }
272 
273  printf("ma : %e\t gL %e\n", m, sqrt(sqrt(gLimit)) * 1.e-10);
274  // GetChar();
275  fprintf(f, "%lf\t%e\n", m, sqrt(sqrt(gLimit)) * 1.e-10);
276  fflush(f);
277  }
278 
279  fclose(f);
280 }
281 
282 Double_t TRestAxionLikelihood::GetSignal(Double_t ma, Double_t g10_4, Double_t rho, Double_t tExp) {
283  fBufferGas->SetGasDensity("He", rho);
284 
285  Double_t magnetArea = fNbores * TMath::Pi() * TMath::Power(fRmag * REST_Units::cm, 2);
286 
287  Double_t signal = 0;
288  Double_t dE = 0.01;
289  for (Double_t en = fErange.X(); en < fErange.Y(); en = en + dE) {
290  Double_t Phi_a = fAxionSpectrum->GetDifferentialSolarAxionFlux(en);
291  // TODO Needs to be readapted to the new TRestAxionField implementation
292  // Double_t Pa_g = fField->GammaTransmissionProbability(en, fBmag, ma);
293 
294  Double_t Pa_g = 0; // Just dummy 0 probability!!
295  Double_t nGamma = Pa_g * Phi_a;
296 
297  signal += nGamma;
298 
299  /*
300  cout << "Energy : " << en << endl;
301  cout << "Phi_a : " << Phi_a << endl;
302  cout << "Pa_g : " << Pa_g << endl;
303  cout << "Efficiency : " << fEfficiency << endl;
304  cout << "Area magnet : " << magnetArea/10000 << endl;
305  cout << "tExp : " << tExp << endl;
306  */
307  }
308 
309  return signal * dE * tExp * 3600. * magnetArea * fEfficiency * g10_4;
310 }
311 
312 Double_t TRestAxionLikelihood::LogLikelihood(Double_t ma, Double_t g10_4, Double_t Nmeas, Double_t rho,
313  Double_t tExp) {
314  Double_t signal = GetSignal(ma, g10_4, rho, tExp);
315 
316  // cout << "Texp : " << tExp << endl;
317  // cout << "g10_4 : " << g10_4 << " signal " << signal << " time : " << endl;
318 
319  // debug << "Ngamma vacuum : " << signal << endl;
320 
321  Double_t bckMean = fBackgroundLevel * (tExp * 3600.) * fSpotArea * (fErange.Y() - fErange.X());
322  Double_t mu = signal + bckMean;
323 
324  Double_t lhood = TMath::Exp(-mu + Nmeas);
325  if (Nmeas > 0) lhood += TMath::Exp(-mu + Nmeas) * pow(mu / Nmeas, Nmeas);
326 
327  // cout << "g10_4 : " << g10_4 << " signal " << signal << " Lh : " << lhood << endl;
328 
329  /*
330  if( lhood == 0 )
331  GetChar();
332 
333  */
334  if (isinf(lhood) || isnan(lhood)) {
335  cout << "IS INF" << endl;
336  GetChar();
337  }
338 
339  /*
340  cout << "mu : " << mu << endl;
341  cout << "Nmeas : " << Nmeas << endl;
342  cout << "signal : " << signal << endl;
343  cout << "----------------" << endl;
344  cout << "lhood : " << lhood << endl;
345  */
346 
347  // Double_t Ngamma = solarFluxG10 * magnetArea * (fTExpVacuum * 3600.) * fEfficiency;
348 
349  // Double_t nGammaVacuum =
350  // fField->SetAxionMass( Double_t m ) { fAxionMass = m; }
351 
352  return lhood;
353 }
354 
355 //______________________________________________________________________________
357  this->Initialize();
358 
359  // Initialize the metadata members from a configfile
360  fBmag = GetDblParameterWithUnits("Bmag", 4.5);
361  fRmag = GetDblParameterWithUnits("Rmag", 300);
362  fLmag = GetDblParameterWithUnits("Lmag", 4500.);
363 
365  // fField->SetCoherenceLength(fLmag);
366  // fField->SetMagneticField(fBmag);
367 
368  fEfficiency = StringToDouble(GetParameter("efficiency", "1"));
369 
370  fBackgroundLevel = StringToDouble(GetParameter("bckLevel", "1.e-8")); // cpd keV-1 s-1
371 
372  fErange = StringTo2DVector(GetParameter("energyRange", "(1,8)")); // keV
373 
374  fTExpVacuum = StringToDouble(GetParameter("expTimeVacuum", "12000")); // In hours (vacuum phase)
375 
376  fTExpPerStep =
377  StringToDouble(GetParameter("expTimePerStep", "54")); // In hours (gas phase, time at each step)
378 
379  fSpotArea = StringToDouble(GetParameter("spotArea", "0.2")); // in cm2
380 
381  fNSteps = StringToInteger(GetParameter("pressureSteps", "100"));
382 
383  fNbores = StringToInteger(GetParameter("bores", "2"));
384 
385  fLastStepDensity = StringToDouble(GetParameter("lastStepDensity", "0.1786e-3")); // in g/cm3
386 }
387 
390 
391  RESTMetadata << " Number of magnet bores : " << fNbores << RESTendl;
392 
393  RESTMetadata << " Magnetic field : " << fBmag << " T" << RESTendl;
394  RESTMetadata << " Magnet length : " << fLmag << " mm" << RESTendl;
395 
396  RESTMetadata << " Magnet radius : " << fRmag << " mm" << RESTendl;
397  RESTMetadata << " Signal overall efficiency : " << fEfficiency << RESTendl;
398 
399  RESTMetadata << " Background level : " << fBackgroundLevel << " cpd keV-1 s-1" << RESTendl;
400  RESTMetadata << " Energy range : (" << fErange.X() << ", " << fErange.Y() << ")" << RESTendl;
401 
402  RESTMetadata << " Vacuum phase exposure time : " << fTExpVacuum << " hours" << RESTendl;
403  RESTMetadata << " Gas phase exposure time per step : " << fTExpPerStep << RESTendl;
404  RESTMetadata << " Total number of steps : " << fNSteps << RESTendl;
405  RESTMetadata << " Last step Helium density : " << fLastStepDensity << " g/cm3" << RESTendl;
406 
407  RESTMetadata << "+++++++++++++++++++++++++++++++++++++++++++++++++" << RESTendl;
408 }
A metadata class to define the gas properties used in axion search calculations.
Double_t GetPhotonMass(double en)
It returns the equivalent photon mass (in eV) for the gas mixture at the given input energy expressed...
void SetGasDensity(TString gasName, Double_t density)
It adds a new gas component to the mixture. If it already exists it will update its density.
A basic class to define analytical axion-photon conversion calculations for axion helioscopes.
void AssignBufferGas(TRestAxionBufferGas *buffGas)
It assigns a gas buffer medium to the calculation.
void Initialize()
Making default settings.
TRandom3 * fRandom
Random number generator.
void PrintMetadata()
Implemented it in the derived metadata class to print out specific metadata information.
void InitFromConfigFile()
To make settings from rml file. This method must be implemented in the derived class.
A metadata class to define a solar axion spectrum and functions to evaluate it.
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.
void SetLibraryVersion(TString version)
Set the library version of this metadata class.
void SetSectionName(std::string sName)
set the section name, clear the section content
std::string fConfigFileName
Full name of the rml file.
std::string GetParameter(std::string parName, TiXmlElement *e, TString defaultValue=PARAMETER_NOT_FOUND_STR)
Returns the value for the parameter named parName in the given section.
Int_t GetChar(std::string hint="Press a KEY to continue ...")
Helps to pause the program, printing a message before pausing.
Double_t StringToDouble(std::string in)
Gets a double from a string.
Int_t StringToInteger(std::string in)
Gets an integer from a string.
TVector2 StringTo2DVector(std::string in)
Gets a 2D-vector from a string.