REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestAxionBufferGas.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
88
89#include "TRestAxionBufferGas.h"
90using namespace std;
91
92#include "TRestSystemOfUnits.h"
93using namespace REST_Units;
94
95ClassImp(TRestAxionBufferGas);
96
101
116TRestAxionBufferGas::TRestAxionBufferGas(const char* cfgFileName, string name) : TRestMetadata(cfgFileName) {
117 RESTDebug << "Entering TRestAxionBufferGas constructor( cfgFileName, name )" << RESTendl;
118
119 Initialize();
120
122}
123
128
133 SetSectionName(this->ClassName());
134 SetLibraryVersion(LIBRARY_VERSION);
135}
136
137void TRestAxionBufferGas::Clear() {
138 fBufferGasName.clear();
139 fBufferGasDensity.clear();
140
141 fAbsEnergy.clear();
142 fGasAbsCoefficient.clear();
143
144 fFactorEnergy.clear();
145 fGasFormFactor.clear();
146}
147
152 this->Initialize();
153
154 auto gasDefinition = GetElement("gas");
155 while (gasDefinition) {
156 TString gasName = GetFieldValue("name", gasDefinition);
157 if (gasName.Contains("+")) {
158 TString gasDensity = GetFieldValue("density", gasDefinition);
159 SetGasMixture(gasName, gasDensity);
160 } else {
161 Double_t gasDensity = GetDblParameterWithUnits("density", gasDefinition);
162 SetGasDensity(gasName, gasDensity);
163 }
164 gasDefinition = GetNextElement(gasDefinition);
165 }
166
168}
169
175void TRestAxionBufferGas::SetGasDensity(TString gasName, Double_t density) {
176 Int_t gasIndex = FindGasIndex(gasName);
177
178 fBufferGasDensity[gasIndex] = density;
179}
180
192void TRestAxionBufferGas::SetGasMixture(TString gasMixture, TString gasDensities) {
193 Initialize();
194
195 std::vector<string> names = Split((string)gasMixture, "+");
196 std::vector<string> densities;
197 if (gasDensities == "0")
198 densities.clear();
199 else
200 densities = Split((string)gasDensities, "+");
201
202 if (!densities.empty() && names.size() == densities.size()) {
203 for (unsigned int n = 0; n < names.size(); n++) {
204 Double_t density = GetValueInRESTUnits(densities[n]);
205 SetGasDensity(names[n], density);
206 }
207 } else if (densities.empty()) {
208 for (unsigned int n = 0; n < names.size(); n++) {
209 SetGasDensity(names[n], 0);
210 }
211 } else {
212 this->SetError("SetGasMixture. Number of gases does not match the densities!");
213 }
214}
215
219Double_t TRestAxionBufferGas::GetGasDensity(TString gasName) {
220 Int_t gasIndex = FindGasIndex(gasName);
221
222 if (gasIndex < 0) {
223 RESTError << "TRestAxionBufferGas::GetGasDensity. Gas name : " << gasName << " not found!"
224 << RESTendl;
225 return 0;
226 }
227
228 return fBufferGasDensity[gasIndex];
229}
230
241void TRestAxionBufferGas::ReadGasData(TString gasName) {
242 TString factorFileName = SearchFile((string)gasName + ".nff");
243
244 RESTDebug << "TRestAxionBufferGas::ReadGasData. Reading factor file : " << factorFileName << RESTendl;
245
246 if (!TRestTools::fileExists((string)factorFileName)) {
247 RESTError << "TRestAxionBufferGas::ReadGasData( " << gasName << " )" << RESTendl;
248 RESTError << "Gas factor file not found : " << factorFileName << RESTendl;
249 exit(1);
250 }
251
252 /* {{{ Reading form factor values */
253 FILE* fin = fopen(factorFileName.Data(), "rt");
254
255 double en, value;
256
257 std::vector<Double_t> energyFactor;
258 std::vector<Double_t> factor;
259
260 // keV -- e/atom
261 while (fscanf(fin, "%lf\t%lf\n", &en, &value) != EOF) {
262 RESTDebug << "Energy : " << en << "keV -- Factor : " << value << RESTendl;
263
264 energyFactor.push_back(en);
265 factor.push_back(value);
266 }
267
268 RESTDebug << "Items read : " << energyFactor.size() << RESTendl;
269
270 fclose(fin);
271 /* }}} */
272
273 TString absFileName = SearchFile((string)gasName + ".abs");
274
275 RESTDebug << "TRestAxionBufferGas::ReadGasData. Reading factor file : " << absFileName << RESTendl;
276
277 if (!TRestTools::fileExists((string)absFileName)) {
278 RESTError << "TRestAxionBufferGas::ReadGasData( " << gasName << " )" << RESTendl;
279 RESTError << "Gas absorption file not found : " << absFileName << RESTendl;
280 exit(1);
281 }
282
283 /* {{{ Reading absorption values */
284 fin = fopen(absFileName.Data(), "rt");
285
286 std::vector<Double_t> energyAbs;
287 std::vector<Double_t> absorption;
288
289 // keV -- e/atom
290 while (fscanf(fin, "%lf\t%lf\n", &en, &value) != EOF) {
291 RESTDebug << "Energy : " << en << "keV -- Absorption : " << value << RESTendl;
292
293 energyAbs.push_back(en);
294 absorption.push_back(value);
295 }
296
297 RESTDebug << "Items read : " << energyAbs.size() << RESTendl;
298
299 fclose(fin);
300 /* }}} */
301
302 fBufferGasName.push_back(gasName);
303
304 fFactorEnergy.push_back(energyFactor);
305 fGasFormFactor.push_back(factor);
306
307 fAbsEnergy.push_back(energyAbs);
308 fGasAbsCoefficient.push_back(absorption);
309
310 fBufferGasDensity.push_back(0);
311}
312
318Double_t TRestAxionBufferGas::GetFormFactor(TString gasName, Double_t energy) {
319 // In case we are in vacuum
320 if (GetNumberOfGases() == 0) return 0;
321
322 Int_t gasIndex = FindGasIndex(gasName);
323 RESTDebug << "TRestAxionBufferGas::GetFormFactor. Gas index = " << gasIndex << RESTendl;
324
325 if (gasIndex == -1) {
326 ReadGasData(gasName);
327 gasIndex = FindGasIndex(gasName);
328 }
329
330 if (gasIndex == -1) {
331 RESTError << "TRestAxionBufferGas::GetFormFactor. Gas: " << gasName << " Not Found!" << RESTendl;
332 exit(1);
333 }
334
335 Int_t energyIndex = GetEnergyIndex(fFactorEnergy[gasIndex], energy);
336 RESTDebug << "Energy index : " << energyIndex << RESTendl;
337
338 if (energyIndex == -1) {
339 RESTError << "TRestAxionBufferGas::GetFormFactor. Energy (" << energy << " keV) out of range"
340 << RESTendl;
341 exit(1);
342 }
343
344 // Absorption coefficient
345 double y2 = fGasFormFactor[gasIndex][energyIndex + 1];
346 double y1 = fGasFormFactor[gasIndex][energyIndex];
347
348 // Normalized field
349 double x2 = fFactorEnergy[gasIndex][energyIndex + 1];
350 double x1 = fFactorEnergy[gasIndex][energyIndex];
351
352 double m = (y2 - y1) / (x2 - x1);
353 double n = y1 - m * x1;
354
355 if (m * energy + n < 0) {
356 RESTError << "TRestAxionBufferGas::GetAbsorptionCoefficient. Negative coefficient" << RESTendl;
357 cout << "y2 : " << y2 << " y1 : " << y1 << endl;
358 cout << "x2 : " << x2 << " x1 : " << x1 << endl;
359 cout << "m : " << m << " n : " << n << endl;
360 cout << "E : " << energy << " bin : " << energyIndex << endl;
361 GetChar();
362 }
363
364 return (m * energy + n);
365}
366
372 Double_t attLength = 0;
373 for (unsigned int n = 0; n < fBufferGasName.size(); n++)
374 attLength +=
376
377 return attLength;
378}
379
385 return cmToeV(GetPhotonAbsorptionLength(energy));
386}
387
391Double_t TRestAxionBufferGas::cmToeV(double l_Inv) // E in keV, P in bar ---> Gamma in cm-1
392{
393 return l_Inv / REST_Physics::PhMeterIneV / 0.01;
394}
395
401 Double_t photonMass = 0;
402
403 if (fBufferGasName.empty())
404 RESTError << "TRestAxionBufferGas::GetDensityForMass gas has not been defined!" << RESTendl;
405
406 for (unsigned int n = 0; n < fBufferGasName.size(); n++) {
407 Double_t W_value = 0;
408 if (fBufferGasName[n] == "H") W_value = 1.00794; // g/mol
409 if (fBufferGasName[n] == "He") W_value = 4.002; // g/mol
410 if (fBufferGasName[n] == "Ne") W_value = 20.179; // g/mol
411 if (fBufferGasName[n] == "Ar") W_value = 39.948; // g/mol
412 if (fBufferGasName[n] == "Xe") W_value = 131.293; // g/mol
413
414 if (W_value == 0) {
415 RESTError << "Gas name : " << fBufferGasName[n] << " is not implemented in TRestBufferGas!!"
416 << RESTendl;
417 RESTError << "W value must be defined in TRestAxionBufferGas::GetPhotonMass" << RESTendl;
418 RESTError << "This gas will not contribute to the calculation of the photon mass!" << RESTendl;
419 } else {
420 photonMass +=
421 fBufferGasDensity[n] * units("g/cm^3") * GetFormFactor(fBufferGasName[n], en) / W_value;
422 }
423 }
424
425 return 28.77 * TMath::Sqrt(photonMass);
426}
427
438Double_t TRestAxionBufferGas::GetDensityForMass(double m_gamma, double en) {
439 Double_t massDensity = 0;
440
441 if (fBufferGasName.empty())
442 RESTError << "TRestAxionBufferGas::GetDensityForMass gas has not been defined!" << RESTendl;
443
444 if (fBufferGasName.size() > 1)
445 RESTError << "TRestAxionBufferGas::GetDensityForMass gas this method is only for sinale gas mixtures!"
446 << RESTendl;
447
448 Double_t W_value = 0;
449 if (fBufferGasName[0] == "H") W_value = 1.00794; // g/mol
450 if (fBufferGasName[0] == "He") W_value = 4.002; // g/mol
451 if (fBufferGasName[0] == "Ne") W_value = 20.179; // g/mol
452 if (fBufferGasName[0] == "Ar") W_value = 39.948; // g/mol
453 if (fBufferGasName[0] == "Xe") W_value = 131.293; // g/mol
454
455 if (W_value == 0) {
456 RESTError << "Gas name : " << fBufferGasName[0] << " is not implemented in TRestAxionBufferGas!!"
457 << RESTendl;
458 RESTError << "W value must be defined in TRestAxionBufferGas::GetDensityForMass" << RESTendl;
459 RESTError << "This gas will not contribute to the calculation of the photon mass!" << RESTendl;
460
461 } else {
462 massDensity += pow(m_gamma, 2) * W_value / (GetFormFactor(fBufferGasName[0], en) * pow(28.77, 2));
463 }
464
465 return massDensity / units("g/cm^3");
466}
467
472Double_t TRestAxionBufferGas::GetAbsorptionCoefficient(TString gasName, Double_t energy) {
473 Int_t gasIndex = FindGasIndex(gasName);
474 RESTDebug << "TRestAxionBufferGas::GetAbsorptionCoefficient. Gas index = " << gasIndex << RESTendl;
475
476 if (gasIndex == -1) {
477 ReadGasData(gasName);
478 gasIndex = FindGasIndex(gasName);
479 }
480
481 if (gasIndex == -1) {
482 RESTError << "TRestAxionBufferGas::GetAbsorptionCoefficient. Gas: " << gasName << " Not Found!"
483 << RESTendl;
484 exit(1);
485 }
486
487 Int_t energyIndex = GetEnergyIndex(fAbsEnergy[gasIndex], energy);
488 RESTDebug << "Energy index : " << energyIndex << RESTendl;
489
490 if (energyIndex == -1) {
491 RESTError << "TRestAxionBufferGas::GetAbsorptionCoefficient. Energy out of range" << RESTendl;
492 exit(1);
493 }
494
495 // Absorption coefficient
496 double y2 = fGasAbsCoefficient[gasIndex][energyIndex + 1];
497 double y1 = fGasAbsCoefficient[gasIndex][energyIndex];
498
499 // Normalized field
500 double x2 = fAbsEnergy[gasIndex][energyIndex + 1];
501 double x1 = fAbsEnergy[gasIndex][energyIndex];
502
503 double m = (y2 - y1) / (x2 - x1);
504 double n = y1 - m * x1;
505
506 if (m * energy + n < 0) {
507 RESTError << "TRestAxionBufferGas::GetAbsorptionCoefficient. Negative coeffient" << RESTendl;
508 cout << "y2 : " << y2 << " y1 : " << y1 << endl;
509 cout << "x2 : " << x2 << " x1 : " << x1 << endl;
510 cout << "m : " << m << " n : " << n << endl;
511 cout << "E : " << energy << " bin : " << energyIndex << endl;
512 GetChar();
513 }
514
515 return (m * energy + n);
516}
517
521Int_t TRestAxionBufferGas::GetEnergyIndex(std::vector<Double_t> enVector, Double_t energy) {
522 for (unsigned int n = 0; n < enVector.size(); n++)
523 if (energy < enVector[n]) return n - 1;
524
525 return -1;
526}
527
531Int_t TRestAxionBufferGas::FindGasIndex(TString gasName) {
532 Int_t nGases = (Int_t)fBufferGasName.size();
533
534 for (int n = 0; n < nGases; n++)
535 if (fBufferGasName[n] == gasName) return n;
536
537 // If the gas is not found in the list we just force reading it from its gas datafile.
538 ReadGasData(gasName);
539
540 return FindGasIndex(gasName);
541}
542
548 Int_t gasIndex = FindGasIndex(gasName);
549
550 for (unsigned int n = 0; n < fAbsEnergy[gasIndex].size(); n++)
551 cout << "energy : " << fAbsEnergy[gasIndex][n]
552 << " -- abs coeff : " << fGasAbsCoefficient[gasIndex][n] << endl;
553}
554
560 Int_t gasIndex = FindGasIndex(gasName);
561
562 for (unsigned int n = 0; n < fAbsEnergy[gasIndex].size(); n++)
563 cout << "Energy : " << fFactorEnergy[gasIndex][n] << " -- Abs coeff : " << fGasFormFactor[gasIndex][n]
564 << endl;
565}
566
572
573 RESTMetadata << "Number of buffer gases defined : " << fBufferGasName.size() << RESTendl;
574 if (fBufferGasName.size() == 0) {
575 RESTMetadata << "Buffer medium is vacuum" << RESTendl;
576 } else {
577 RESTMetadata << "Photon mass at 4keV : " << this->GetPhotonMass(4.) << " eV" << RESTendl;
578 RESTMetadata << " " << RESTendl;
579 RESTMetadata << "Buffer gases inside mixture : " << RESTendl;
580 RESTMetadata << "---------------------------" << RESTendl;
581 for (unsigned int n = 0; n < fBufferGasName.size(); n++) {
582 RESTMetadata << " Gas name : " << fBufferGasName[n] << RESTendl;
583 RESTMetadata << " Gas density : " << fBufferGasDensity[n] * units("g/cm^3") << " g/cm3"
584 << RESTendl;
585 RESTMetadata << " Form factor energy range : ( " << fFactorEnergy[n][0] << ", "
586 << fFactorEnergy[n].back() << " ) keV" << RESTendl;
587 RESTMetadata << " Absorption energy range : ( " << fAbsEnergy[n][0] << ", "
588 << fAbsEnergy[n].back() << " ) keV" << RESTendl;
589 RESTMetadata << " " << RESTendl;
590 }
591 }
592
593 RESTMetadata << "+++++++++++++++++++++++++++++++++++++++++++++++++" << RESTendl;
594}
A metadata class to define the gas properties used in axion search calculations.
TRestAxionBufferGas()
Default constructor.
Int_t GetNumberOfGases()
It returns the number of gases in the mixture.
void Initialize()
Initialization of TRestAxionBufferGas members. It removes all gases.
void InitFromConfigFile()
Initialization of TRestAxionBufferGas field members through a RML file.
void PrintMetadata()
Prints on screen the information about the metadata members of TRestAxionBufferGas.
Double_t cmToeV(double l_Inv)
It transforms cm-1 to eV.
std::vector< std::vector< Double_t > > fGasFormFactor
Gas form factor.
void PrintFormFactorGasData(TString gasName)
Prints out the atomic form factors as function of the energy for the given gas component,...
std::vector< std::vector< Double_t > > fGasAbsCoefficient
Gas absorption coefficient in cm2/g.
Int_t GetEnergyIndex(std::vector< Double_t > enVector, Double_t energy)
It returns the vector element index, from enVector, that is just below the given input energy.
Double_t GetPhotonMass(double en)
It returns the equivalent photon mass (in eV) for the gas mixture at the given input energy expressed...
std::vector< std::vector< Double_t > > fFactorEnergy
Energy values for gas form factor in keV.
std::vector< Double_t > fBufferGasDensity
Gas density of the corresponding gasName in g/cm3.
Double_t GetGasDensity(TString gasName)
It returns the gas density - from the chosen gasName component - in g/cm3.
void ReadGasData(TString gasName)
It reads the data files from the corresponding gas component.
Double_t GetDensityForMass(double m_gamma, double en=4.2)
It returns the equivalent gas density for a given photon mass expressed in eV and a given axion energ...
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.
Int_t FindGasIndex(TString gName)
It returns the internal index of the gas component given by gasName.
std::vector< TString > fBufferGasName
Name of the buffer gas (He, Ne, Ar, Xe, ..., etc )
void PrintAbsorptionGasData(TString gasName)
Prints out the absorption coefficients as function of the energy for the given gas component,...
Double_t GetPhotonAbsorptionLengthIneV(Double_t energy)
It returns the inverse of the absorption lenght, for the gas mixture, in eV, for the given energy in ...
void SetGasMixture(TString gasMixture, TString gasDensities="0")
It re-initializes the gas mixture to the one provided by argument.
std::vector< std::vector< Double_t > > fAbsEnergy
Energy values for gas absorption coefficient in keV.
Double_t GetAbsorptionCoefficient(TString gasName, Double_t energy)
It returns the absorption coefficient, in cm2/g, for the given gas component and energy in keV.
Double_t GetFormFactor(TString gasName, Double_t energy)
It returns the atomic form factor of the gasName component at the given energy.
Double_t GetPhotonAbsorptionLength(Double_t energy)
It returns the inverse of the absorption lenght, for the gas mixture, in cm-1, for the given energy i...
~TRestAxionBufferGas()
Default destructor.
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.
void SetLibraryVersion(TString version)
Set the library version of this metadata class.
TRestStringOutput::REST_Verbose_Level GetVerboseLevel()
returns the verboselevel in type of REST_Verbose_Level enumerator
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 SearchFile(std::string filename)
Search files in current directory and directories specified in "searchPath" section.
std::string fConfigFileName
Full name of the rml file.
void SetError(std::string message="", bool print=true, int maxPrint=5)
A metadata class may use this method to signal that something went wrong.
TiXmlElement * GetNextElement(TiXmlElement *e)
Get the next sibling xml element of this element, with same eleDeclare.
@ REST_Info
+show most of the information for each steps
static bool fileExists(const std::string &filename)
Returns true if the file (or directory) with path filename exists.
Definition: TRestTools.cxx:728
constexpr double PhMeterIneV
A meter in eV.
Definition: TRestPhysics.h:52
Int_t GetChar(std::string hint="Press a KEY to continue ...")
Helps to pause the program, printing a message before pausing.
std::vector< std::string > Split(std::string in, std::string separator, bool allowBlankString=false, bool removeWhiteSpaces=false, int startPos=-1)
Split the input string according to the given separator. Returning a vector of fragments.
This namespace defines the unit conversion for different units which are understood by REST.
Double_t GetValueInRESTUnits(std::string in)
It scales a physics measurement with its units into a REST default units value.