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"
53using namespace std;
54
55ClassImp(TRestAxionLikelihood);
56//______________________________________________________________________________
57TRestAxionLikelihood::TRestAxionLikelihood() : TRestMetadata() {
58 // TRestAxionLikelihood default constructor
59 Initialize();
60}
61
62//______________________________________________________________________________
63TRestAxionLikelihood::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//______________________________________________________________________________
75TRestAxionLikelihood::~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
97void 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
188void 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
282Double_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
312Double_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:70
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.