REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
src/TRestDetectorGas.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 
215 
216 #include "TRestDetectorGas.h"
217 
218 #include <TRestDataBase.h>
219 
220 #include <algorithm>
221 
222 using namespace std;
223 
224 ClassImp(TRestDetectorGas);
225 
226 // const char* defaultServer = "https://sultan.unizar.es/gasFiles/";
227 
232  Initialize();
233 
234  fGasGeneration = false;
235 }
236 
249 TRestDetectorGas::TRestDetectorGas(const char* configFilename, string name, bool gasGeneration, bool test)
251  Initialize();
252  fGasGeneration = gasGeneration;
253 
254  fTest = test;
255 
256  if (strcmp(configFilename, "server") == 0) {
257  LoadConfigFromElement(StringToElement("<TRestDetectorGas name=\"" + name + "\" file=\"server\"/>"),
258  nullptr);
259  } else {
260  fConfigFileName = configFilename;
262  }
263 
264  // if ( fStatus == RESTGAS_CFG_LOADED ) LoadGasFile( );
265 }
266 
271  RESTDebug << "Entering ... TRestDetectorGas() destructor." << RESTendl;
272 
273 #if defined USE_Garfield
274  delete fGasMedium;
275 #endif
276 }
277 
283  RESTDebug << "TRestDetectorGas. Entering ... Initialize()." << RESTendl;
284 
285  SetSectionName(this->ClassName());
286  SetLibraryVersion(LIBRARY_VERSION);
287 
288  fPressureInAtm = 1;
289  fTemperatureInK = 300;
290 
291  fNofGases = 0;
292 
293  fGasComponentName.clear();
294  fGasComponentFraction.clear();
295 
296  fStatus = RESTGAS_INTITIALIZED;
297 
298  fGasFilename = "";
299  fGasFileContent = "";
300 
301 #if defined USE_Garfield
302  fGasMedium = new Garfield::MediumMagboltz();
303 #else
304  fGasMedium = nullptr;
305 #endif
306 
308  // This must be commented. If not when we specify gasGeneration=true on the
309  // constructor, it will be overriden inside LoadConfigFromFile
310  //
311  // fGasGeneration = false;
313 
314  fEmin = 10;
315  fEmax = 1000;
316  fEnodes = 20;
317 }
318 
328  RESTDebug << "Entering ... TRestDetectorGas::LoadGasFile()." << RESTendl;
329 
330 #if defined USE_Garfield
331  RESTDebug << "fGasFilename = " << fGasFilename << RESTendl;
332  if (!TRestTools::fileExists((string)(fGasFilename))) {
333  RESTError << __PRETTY_FUNCTION__ << RESTendl;
334  RESTError << "The gas file does not exist. (name:" << fGasFilename << ")" << RESTendl;
335  fStatus = RESTGAS_ERROR;
336  return;
337  }
338 
339  fGasMedium->LoadGasFile((string)(fGasFilename));
340 
341  fEFields.clear();
342  fBFields.clear();
343  fAngles.clear();
344  fGasMedium->GetFieldGrid(fEFields, fBFields, fAngles);
345 
346  fStatus = RESTGAS_GASFILE_LOADED;
347  RESTInfo << "TRestDetectorGas. Gas file loaded!" << RESTendl;
348 
349  for (unsigned int i = 0; i < fEFields.size(); i++)
350  RESTDebug << "node " << i << " Field : " << fEFields[i] << " V/cm" << RESTendl;
351 
352  if (fGasMedium && fGasMedium->GetW() == 0.) {
353  fGasMedium->SetW(GetWvalue());
354  } // as it is probably not computed by Magboltz
355 #else
356  cout << "This REST is not complied with garfield, it cannot load any gas file!" << endl;
357 #endif
358 }
359 
360 void TRestDetectorGas::CalcGarField(double Emin, double Emax, int n) {
361  RESTDebug << "Entering ... TRestDetectorGas::CalcGarField( Emin=" << Emin << " , Emax=" << Emax << " )"
362  << RESTendl;
363 
364 #if defined USE_Garfield
365  if (fEnodes <= 0) {
366  cout << "REST ERROR : The number of nodes is not a positive number!!. Gas "
367  "file generation cancelled."
368  << endl;
369  fStatus = RESTGAS_ERROR;
370  return;
371  }
372  if (fEmin >= fEmax) {
373  cout << "REST ERROR : The Electric field grid boundaries are not properly "
374  "defined."
375  << endl;
376  fStatus = RESTGAS_ERROR;
377  return;
378  }
379 
380  string gasStr[3];
381  for (int i = 0; i < fNofGases; i++) {
382  gasStr[i] = (string)fGasComponentName[i];
383  if (i == 2) break;
384  }
385 
386  if (fNofGases == 1) fGasMedium->SetComposition(gasStr[0], fGasComponentFraction[0] * 100.);
387 
388  if (fNofGases == 2)
389  fGasMedium->SetComposition(gasStr[0], fGasComponentFraction[0] * 100., gasStr[1],
390  fGasComponentFraction[1] * 100.);
391 
392  if (fNofGases == 3)
393  fGasMedium->SetComposition(gasStr[0], fGasComponentFraction[0] * 100., gasStr[1],
394  fGasComponentFraction[1] * 100., gasStr[2],
395  fGasComponentFraction[2] * 100.);
396 
397  if (fNofGases > 3) {
398  cout << "REST ERROR : Number of gas components higher than 3 not allowed" << endl;
399  fStatus = RESTGAS_ERROR;
400  return;
401  }
402 
403  fGasMedium->SetTemperature(fTemperatureInK);
404 
405  if (fPressureInAtm != 1)
406  RESTWarning << "-- Warning : The gas will be generated for gas pressure = 1atm" << RESTendl;
407 
408  fGasMedium->SetPressure(1 * REST_Units::torr);
409 
410  fGasMedium->SetFieldGrid(Emin, Emax, n, n > 1);
411 
412  fGasMedium->SetMaxElectronEnergy(fMaxElectronEnergy);
413 
414  cout << "Garfield: calculating..." << endl;
415 
416  if (fVerboseLevel >= TRestStringOutput::REST_Verbose_Level::REST_Info) fGasMedium->EnableDebugging();
417  fGasMedium->Initialise();
418  if (fVerboseLevel >= TRestStringOutput::REST_Verbose_Level::REST_Info) fGasMedium->DisableDebugging();
419 
420  fGasMedium->GenerateGasTable(fNCollisions, true);
421  if (fPressureInAtm != 1) {
422  RESTWarning << "-- Warning : Restoring the gas pressure" << RESTendl;
423  fGasMedium->SetPressure(fPressureInAtm * 760.);
424  }
425 #else
426  cout << "This REST is not complied with garfield, it cannot calculate "
427  "garfield!"
428  << endl;
429 #endif
430 }
431 
441 void TRestDetectorGas::AddGasComponent(string gasName, Double_t fraction) {
442  RESTDebug << "Entering ... TRestDetectorGas::AddGasComponent( gasName=" << gasName
443  << " , fraction=" << fraction << " )" << RESTendl;
444 
445  fGasComponentName.push_back(gasName);
446  fGasComponentFraction.push_back(fraction);
447  fNofGases++;
448 }
449 
450 // This was just a test to try to Get the calculated W for the gas definition.
451 // However, I tested with Xe+TMA and I got an error message that TMA
452 // photoncrossection database is not available
453 void TRestDetectorGas::GetGasWorkFunction() {
454 #if defined USE_Garfield
455  RESTEssential << __PRETTY_FUNCTION__ << RESTendl;
456  RESTEssential << "This method has never been validated to operate properly" << RESTendl;
457  RESTEssential << "If we manage to make it work we could use this method to "
458  "obtain the calculated W of the gas"
459  << RESTendl;
460 
461  // Gas gap [cm].
462  const double width = 1.;
463  SolidBox* box = new SolidBox(width / 2., 0., 0., width / 2., 10., 10.);
464  GeometrySimple* geo = new GeometrySimple();
465  geo->AddSolid(box, fGasMedium);
466 
467  ComponentConstant* cmp = new ComponentConstant();
468  cmp->SetGeometry(geo);
469  cmp->SetElectricField(100., 0., 0.);
470 
471  Sensor* sensor = new Sensor();
472  sensor->AddComponent(cmp);
473 
474  TrackHeed* heed = new TrackHeed();
475  heed->SetSensor(sensor);
476  // Set the particle type.
477  heed->SetParticle("pi");
478  // Set the particle momentum (in eV/c).
479  heed->SetMomentum(120.e9);
480 
481  // Switch on debugging to print out some information (stopping power, W value,
482  // ...)
483  heed->EnableDebugging();
484  // Initial position
485  double x0 = 0., y0 = 0., z0 = 0., t0 = 0.;
486  // Direction of the track (perpendicular incidence)
487  double dx0 = 1., dy0 = 0., dz0 = 0.;
488  heed->NewTrack(x0, y0, z0, t0, dx0, dy0, dz0);
489  cout << "W : " << heed->GetW() << endl;
490 #else
491  cout << "This REST is not complied with garfield, it cannot calculate "
492  "garfield!"
493  << endl;
494 #endif
495 }
496 
506  // if (GetVerboseLevel() <= REST_Info) fVerboseLevel = REST_Info;
507 
508  RESTDebug << "Entering ... TRestDetectorGas::InitFromConfigFile()" << RESTendl;
509 
510  // read config parameters of base class
512  if (fW == -1) {
513  fW = 21.9;
514  cout << "Setting default W-value : " << fW << endl;
515  }
516 
517  // match the database, id=0(any), type="GAS_SERVER"
518  string _gasServer = gDataBase->query_data(DBEntry(0, "GAS_SERVER")).value;
519  if (_gasServer == "") _gasServer = "none";
520  fGasServer = GetParameter("gasServer", _gasServer);
521 
522  // add gas component
523  TiXmlElement* gasComponentDefinition = GetElement("gasComponent");
524  while (gasComponentDefinition != nullptr) {
525  string gasName = GetFieldValue("name", gasComponentDefinition);
526  Double_t gasFraction = StringToDouble(GetFieldValue("fraction", gasComponentDefinition));
527  AddGasComponent(gasName, gasFraction);
528  gasComponentDefinition = GetNextElement(gasComponentDefinition);
529  }
530  if (fNofGases == 0 && fMaterial != "") {
531  vector<string> componentsdef = Split(fMaterial, " ");
532  for (auto componentdef : componentsdef) {
533  vector<string> componentdefpair = Split(componentdef, ":");
534  if (componentdefpair.size() != 2) {
535  continue;
536  }
537  AddGasComponent(componentdefpair[0], StringToDouble(componentdefpair[1]));
538  }
539  }
540  if (fNofGases == 0) {
541  RESTError << "TRestDetectorGas: No gas components added!" << RESTendl;
542  }
543  double sum = 0;
544  for (int i = 0; i < fNofGases; i++) sum += GetGasComponentFraction(i);
545  if (sum - 1 < 1.e12)
546  fStatus = RESTGAS_CFG_LOADED;
547  else {
548  RESTWarning << "TRestDetectorGas : The total gas fractions is NOT 1." << RESTendl;
549  fStatus = RESTGAS_ERROR;
550  return;
551  }
552 
553  // setup e-field calculation range and gas file generation parameters
554  TiXmlElement* eFieldDefinition = GetElement("eField");
555  fEmax = StringToDouble(GetFieldValue("Emax", eFieldDefinition));
556  fEmin = StringToDouble(GetFieldValue("Emin", eFieldDefinition));
557  fEnodes = StringToInteger(GetFieldValue("nodes", eFieldDefinition));
558  fNCollisions = StringToInteger(GetParameter("nCollisions"));
559  fMaxElectronEnergy = StringToDouble(GetParameter("maxElectronEnergy", "40"));
560  if (ToUpper(GetParameter("generate")) == "ON" || ToUpper(GetParameter("generate")) == "TRUE")
561  fGasGeneration = true;
562  fGasOutputPath = GetParameter("gasOutputPath", "./");
564  RESTWarning << "-- Warning : The specified gasOutputPath is not writable!" << RESTendl;
565  RESTWarning << "-- Warning : The output path will be changed to ./" << RESTendl;
566  fGasOutputPath = "./";
567  }
568  fGDMLMaterialRef = GetParameter("GDMLMaterialRef", "");
569 
570  // construct the gas file name and try to find it, either locally or from gas server
571  fGasFilename = ConstructFilename();
572  RESTDebug << "TRestDetectorGas::InitFromConfigFile. ConstructFilename. fGasFilename = " << fGasFilename
573  << RESTendl;
574  fGasFilename = FindGasFile((string)fGasFilename);
575  RESTDebug << "TRestDetectorGas::InitFromConfigFile. FindGasFile. fGasFilename = " << fGasFilename
576  << RESTendl;
577 
578  // If we found the gasFile then obviously we disable the gas generation
579  if (fGasGeneration && TRestTools::fileExists((string)fGasFilename)) {
580  fGasGeneration = false;
581 
582  RESTWarning << "TRestDetectorGas gasFile generation is enabled, but the "
583  "gasFile already exists!!"
584  << RESTendl;
585  RESTWarning << "Filename : " << fGasFilename << RESTendl;
586  RESTWarning << "fGasGeneration should be disabled to remove this "
587  "warning."
588  << RESTendl;
589  RESTWarning << "If you really want to re-generate the gas file you "
590  "will need to disable the gasServer."
591  << RESTendl;
592  RESTWarning << "And/or remove any local copies that are found by "
593  "SearchPath."
594  << RESTendl;
595  }
596  fStatus = RESTGAS_CFG_LOADED;
597 
598 #if defined USE_Garfield
599  // calling garfield, either to generate gas file or load existing gas file
600  if (fGasGeneration) {
601  RESTEssential << "Starting gas generation" << RESTendl;
602 
603  CalcGarField(fEmin, fEmax, fEnodes);
604  GenerateGasFile();
605  fStatus = RESTGAS_GASFILE_LOADED;
606  } else {
607  LoadGasFile();
608  fGasMedium->SetPressure(fPressureInAtm * REST_Units::torr);
609  }
610  if (fGasMedium && fGasMedium->GetW() == 0.)
611  fGasMedium->SetW(fW); // as it is probably not computed by Magboltz
612 #endif
613 
615 }
616 
618  RESTDebug << "Entering ... TRestDetectorGas::InitFromRootFile()" << RESTendl;
620  if (fGasFileContent != "") // use gas file content by default
621  {
622  fGasFilename = "/tmp/restGasFile_" + REST_USER + ".gas";
623  ofstream outf;
624  outf.open(fGasFilename, ios::ate);
625  outf << fGasFileContent << endl;
626  outf.close();
627  LoadGasFile();
628  int z = system("rm " + fGasFilename);
629  if (z != 0) RESTError << "Problem removing gas file: " << fGasFilename << RESTendl;
630  } else {
631  fGasFilename = FindGasFile((string)fGasFilename);
632  if (fGasFilename != "") {
633  LoadGasFile();
634  }
635  }
636 }
637 
638 void TRestDetectorGas::UploadGasToServer(string absoluteGasFilename) {
639  RESTEssential << "uploading gas file and gas definition rmls" << RESTendl;
640 
641  if (!fTest && (fMaxElectronEnergy < 400 || fNCollisions < 10 || fEnodes < 20)) {
642  RESTWarning << "-- Warning : The gas file does not fulfill the requirements "
643  "for being uploaded to the gasServer"
644  << RESTendl;
645  RESTWarning << "-- Warning : maxElectronEnergy >= 400. Number of collisions >= "
646  "10. Number of E nodes >= 20."
647  << RESTendl;
648  RESTWarning << "-- Warning : The generated file will NOT be uploaded to the "
649  "server but preserved locally."
650  << RESTendl;
651  return;
652  }
653 
655  // We add the gas definition we used to generate the gas file and prepare it
656  // to upload/update in the gasServer
657  string cmd;
658  int a;
659  // We download (probably again) the original version
660  string url = gDataBase->query_data(DBEntry(0, "META_RML", "TRestDetectorGas")).value;
661  string fname = TRestTools::DownloadRemoteFile(url);
662 
663 // We remove the last line. I.e. the enclosing </gases> in the original file
664 #ifdef __APPLE__
665  cmd = "sed -i '' -e '$ d' " + fname;
666 #else
667  cmd = "sed -i '$ d' " + fname;
668 #endif
669 
670  a = system(cmd.c_str());
671 
672  if (a != 0) {
673  RESTError << "-- Error : " << __PRETTY_FUNCTION__ << RESTendl;
674  RESTError << "-- Error : problem removing last line from " << fname << RESTendl;
675  return;
676  }
677 
678  // We add some header before the gas definition. We might add also date an
679  // other information essential to identify the gasFile submission
680  ofstream outf;
681  outf.open(fname, ios::app);
682  outf << endl;
683  outf << "//------- User : " << REST_USER << " ---- REST version : " << REST_RELEASE
684  << " ---------------------------" << endl;
685  outf.close();
686 
687  // We write the TRestDetectorGas section
688  this->WriteConfigBuffer(fname);
689 
690  // We re-write the enclosing </gases> tag
691  outf.open(fname, ios::app);
692  outf << "\n" << endl;
693  outf << "</gases>" << endl;
694  outf.close();
696 
697  // We transfer the new gas definitions to the gasServer
698  TRestTools::UploadToServer(fname, (string)fGasServer, "ssh://gasUser@:22");
699 
700  // We transfer the gasFile to the gasServer
701  TRestTools::UploadToServer(absoluteGasFilename, (string)fGasServer, "ssh://gasUser@:22");
702 
703  // We remove the local file (afterwards, the remote copy will be used)
704  // cmd = "rm " + _name;
705  // a = system(cmd.c_str());
706 
707  // if (a != 0) {
708  // ferr << "-- Error : " << __PRETTY_FUNCTION__ << endl;
709  // ferr << "-- Error : problem removing the locally generated gas file" << endl;
710  // ferr << "-- Error : Please report this problem at "
711  // "http://gifna.unizar.es/rest-forum/"
712  // << endl;
713  // return;
714  //}
715 
716  RESTSuccess << "-- Success : Gasfile server database was updated successfully!" << RESTendl;
717 }
718 
733 string TRestDetectorGas::FindGasFile(string name) {
734  RESTDebug << "Entering ... TRestDetectorGas::FindGasFile( name=" << name << " )" << RESTendl;
735 
736  string absoluteName = "";
737 
738  if (!fGasGeneration && fGasServer != "none") {
739  absoluteName = TRestTools::DownloadRemoteFile((string)fGasServer + "/" + name);
740  }
741 
742  if (absoluteName == "") {
743  RESTInfo << "Trying to find the gasFile locally" << RESTendl;
744  absoluteName = SearchFile(name);
745  if (absoluteName == "") {
746  RESTWarning << "-- Warning : No sucess finding local gas file definition." << RESTendl;
747  RESTWarning << "-- Warning : Gas file definition does not exist." << RESTendl;
748  RESTInfo << "To generate a new gasFile enable gas generation in TRestDetectorGas "
749  "constructor"
750  << RESTendl;
751  RESTInfo << "TRestDetectorGas ( \"gasDefinition.rml\", \"gas Name\", true );" << RESTendl;
752  RESTInfo << "Further details can be found at TRestDetectorGas class definition and "
753  "tutorial."
754  << RESTendl;
755 
756  absoluteName = name;
757  }
758  }
759 
760  return absoluteName;
761 }
762 
767  RESTDebug << "Entering ... TRestDetectorGas::GetGasMixture( )" << RESTendl;
768 
769  TString gasMixture;
770  char tmpStr[64];
771  for (int n = 0; n < fNofGases; n++) {
772  if (n > 0) gasMixture += "-";
773  gasMixture += GetGasComponentName(n) + "_";
774  sprintf(tmpStr, "%03.1lf", GetGasComponentFraction(n) * 100.);
775  gasMixture += (TString)tmpStr;
776  }
777  return gasMixture;
778 }
779 
787  RESTDebug << "Entering ... TRestDetectorGas::ConstructFilename( )" << RESTendl;
788 
789  string name = "";
790  char tmpStr[256];
791  for (int n = 0; n < fNofGases; n++) {
792  if (n > 0) name += "-";
793  name += GetGasComponentName(n) + "_";
794  if (GetGasComponentFraction(n) >= 0.001)
795  sprintf(tmpStr, "%03.1lf", GetGasComponentFraction(n) * 100.);
796  else
797  sprintf(tmpStr, "%03.1lfppm", GetGasComponentFraction(n) * 1.e6);
798 
799  name += (TString)tmpStr;
800  }
801 
802  // The filename is constructed always at 1 atm pressure.
803  // We keep E_vs_P to remind the field calculation range will
804  // depend on pressure.
805 
806  name += "-E_vs_P_";
807  sprintf(tmpStr, "%03.1lf", fEmin);
808  name += (TString)tmpStr;
809 
810  name += "_";
811  sprintf(tmpStr, "%03.1lf", fEmax);
812  name += (TString)tmpStr;
813 
814  name += "_nodes_";
815  sprintf(tmpStr, "%02d", fEnodes);
816  name += (TString)tmpStr;
817 
818  name += "-nCol_";
819  sprintf(tmpStr, "%02d", fNCollisions);
820  name += (TString)tmpStr;
821 
822  name += "-maxE_";
823  sprintf(tmpStr, "%03d", (Int_t)fMaxElectronEnergy);
824  name += (TString)tmpStr;
825 
826  name += ".gas";
827 
828  RESTDebug << "Constructed filename : " << name << RESTendl;
829  return name;
830 }
831 
835  RESTDebug << "Entering ... TRestDetectorGas::GenerateGasFile( )" << RESTendl;
836 
837 #if defined USE_Garfield
838 
839  fGasFilename = ConstructFilename();
840  RESTDebug << " TRestDetectorGas::GenerateGasFile. fGasFilename = " << fGasFilename << RESTendl;
841 
843  cout << endl;
844  RESTWarning << "-- Warning: REST ERROR. TRestDetectorGas. Path is not writtable." << RESTendl;
845  RESTWarning << "-- Warning: Path : " << fGasOutputPath << RESTendl;
846  RESTWarning << "-- Warning: Make sure the final data path is writtable before "
847  "proceed to gas generation."
848  << RESTendl;
849  RESTWarning << "-- Warning: or change the gas data path ... " << RESTendl;
850  RESTWarning << RESTendl;
851  GetChar();
852  return;
853  }
854 
855  cout << "Writing gas file : " << endl;
856  cout << "-----------------" << endl;
857  cout << "Path : " << fGasOutputPath << endl;
858  cout << "Filename : " << fGasFilename << endl;
859 
860  fGasMedium->WriteGasFile((string)(fGasOutputPath + "/" + fGasFilename));
861 
862  if (fGasServer != "none") UploadGasToServer((string)(fGasOutputPath + "/" + fGasFilename));
863 
864 #else
865  cout << "This REST is not complied with garfield, it cannot save any gas file!" << endl;
866 #endif
867 }
868 
878 void TRestDetectorGas::SetPressure(Double_t pressure) {
879  RESTDebug << "Entering ... TRestDetectorGas::SetPressure( pressure=" << pressure << " )" << RESTendl;
880 
881  fPressureInAtm = pressure;
882 #if defined USE_Garfield
883  fGasMedium->SetPressure(fPressureInAtm * REST_Units::torr);
884 #endif
885 }
886 
889 void TRestDetectorGas::SetTemperature(Double_t temperature) {
890  RESTDebug << "Entering ... TRestDetectorGas::SetPressure( temperature=" << temperature << " )"
891  << RESTendl;
892 
893  fTemperatureInK = temperature;
894 #if defined USE_Garfield
895  fGasMedium->SetTemperature(temperature);
896 #endif
897 }
898 
907 void TRestDetectorGas::PlotDriftVelocity(Double_t eMin, Double_t eMax, Int_t nSteps) {
908  RESTDebug << "Entering ... TRestDetectorGas::PlotDriftVelocity( eMin=" << eMin << " , eMax=" << eMax
909  << ", nSteps=" << nSteps << " )" << RESTendl;
910 
911  vector<Double_t> eField(nSteps), driftVel(nSteps);
912 
913  for (int i = 0; i < nSteps; i++) {
914  eField[i] = (eMin + (double)i * (eMax - eMin) / nSteps);
915 
916  this->SetElectricField(eField[i] / units("V/cm"));
917  driftVel[i] = GetDriftVelocity() * units("cm/us");
918  }
919 
920  TCanvas* c = new TCanvas("Drift velocity", " ");
921  TGraph* fDriftVel = new TGraph(nSteps, &eField[0], &driftVel[0]);
922  TString str;
923  str.Form("Drift Velocity for %s (Pressure: %3.1lf bar)", GetName(), this->GetPressure());
924  fDriftVel->SetTitle(str);
925  fDriftVel->GetXaxis()->SetTitle("E [V/cm]");
926  fDriftVel->GetYaxis()->SetTitle("Drift velocity [cm/#mus]");
927  fDriftVel->GetYaxis()->SetTitleOffset(2);
928  fDriftVel->Draw("");
929  c->Update();
930 }
931 
940 void TRestDetectorGas::PlotLongitudinalDiffusion(Double_t eMin, Double_t eMax, Int_t nSteps) {
941  RESTDebug << "Entering ... TRestDetectorGas::PlotLongitudinalDiffusion( eMin=" << eMin
942  << " , eMax=" << eMax << ", nSteps=" << nSteps << " )" << RESTendl;
943 
944  vector<Double_t> eField(nSteps), longDiff(nSteps);
945 
946  for (int i = 0; i < nSteps; i++) {
947  eField[i] = eMin + (double)i * (eMax - eMin) / nSteps;
948 
949  this->SetElectricField(eField[i] / units("V/cm"));
950  longDiff[i] = 10. * GetLongitudinalDiffusion(); // to express it in mm/sqrt(cm)
951  }
952 
953  TCanvas* c = new TCanvas("Longitudinal diffusion", " ");
954  TGraph* fLongDiff = new TGraph(nSteps, &eField[0], &longDiff[0]);
955  TString str;
956  str.Form("Longitudinal diffusion for %s (Pressure: %3.1lf bar)", GetName(), this->GetPressure());
957  fLongDiff->SetTitle(str);
958  fLongDiff->GetXaxis()->SetTitle("E [V/cm]");
959  fLongDiff->GetYaxis()->SetTitle("Longitudinal diffusion [mm/#sqrt{cm}]");
960  fLongDiff->GetYaxis()->SetTitleOffset(2);
961  fLongDiff->Draw("");
962  c->Update();
963 }
964 
973 void TRestDetectorGas::PlotTransversalDiffusion(Double_t eMin, Double_t eMax, Int_t nSteps) {
974  RESTDebug << "Entering ... TRestDetectorGas::PlotTransversalDiffusion( eMin=" << eMin
975  << " , eMax=" << eMax << ", nSteps=" << nSteps << " )" << RESTendl;
976 
977  vector<Double_t> eField(nSteps), transDiff(nSteps);
978 
979  for (int i = 0; i < nSteps; i++) {
980  eField[i] = eMin + (double)i * (eMax - eMin) / nSteps;
981 
982  this->SetElectricField(eField[i] / units("V/cm"));
983  transDiff[i] = 10. * GetTransversalDiffusion(); // to express it in mm/sqrt(cm)
984  }
985 
986  TCanvas* c = new TCanvas("Transitudinal diffusion", " ");
987  TGraph* fTransDiff = new TGraph(nSteps, &eField[0], &transDiff[0]);
988  TString str;
989  str.Form("Transversal diffusion for %s (Pressure: %3.1lf bar)", GetName(), this->GetPressure());
990  fTransDiff->SetTitle(str);
991  fTransDiff->GetXaxis()->SetTitle("E [V/cm]");
992  fTransDiff->GetYaxis()->SetTitle("Transversal diffusion [mm/#sqrt{cm}]");
993  fTransDiff->GetYaxis()->SetTitleOffset(2);
994  fTransDiff->Draw("");
995  c->Update();
996 }
997 
1006 void TRestDetectorGas::PlotTownsendCoefficient(Double_t eMin, Double_t eMax, Int_t nSteps) {
1007  RESTDebug << "Entering ... TRestDetectorGas::PlotTownsendCoefficient( eMin=" << eMin << " , eMax=" << eMax
1008  << ", nSteps=" << nSteps << " )" << RESTendl;
1009 
1010  vector<Double_t> eField(nSteps), townsendCoeff(nSteps);
1011 
1012  for (int i = 0; i < nSteps; i++) {
1013  eField[i] = eMin + (double)i * (eMax - eMin) / nSteps;
1014 
1015  townsendCoeff[i] = GetTownsendCoefficient(eField[i]);
1016  }
1017 
1018  TCanvas* c = new TCanvas("Townsend coefficient", " ");
1019  TGraph* fTownsend = new TGraph(nSteps, &eField[0], &townsendCoeff[0]);
1020  TString str;
1021  str.Form("Townsend coefficient for %s", GetName());
1022  fTownsend->SetTitle(str);
1023  fTownsend->GetXaxis()->SetTitle("E [V/cm]");
1024  fTownsend->GetYaxis()->SetTitle("Townsend coefficient [1/cm]");
1025  fTownsend->GetYaxis()->SetTitleOffset(2);
1026  fTownsend->Draw("");
1027  c->Update();
1028 }
1029 
1035  RESTDebug << "Entering ... TRestDetectorGas::GetDriftVelocity( E=" << E << " )" << RESTendl;
1036 
1037  SetPressure(fPressureInAtm);
1038 
1039 #if defined USE_Garfield
1040  if (fStatus != RESTGAS_GASFILE_LOADED) {
1041  RESTDebug << "-- Error : " << __PRETTY_FUNCTION__ << RESTendl;
1042  RESTDebug << "-- Error : Gas file was not loaded!" << RESTendl;
1043  return 0;
1044  }
1045 
1046  RESTInfo << "Calling Garfield directly. Please be aware that the unit is different "
1047  << "from REST standard unit. E is V/cm. The return is cm/us" << RESTendl;
1048 
1049  Double_t vx, vy, vz;
1050  fGasMedium->ElectronVelocity(0., 0, -E, 0, 0, 0, vx, vy, vz);
1051  return vz * 1000.;
1052 #else
1053  std::cout << "This REST is not complied with garfield, Do not use Drift Velocity "
1054  "from TRestDetectorGas!"
1055  << std::endl;
1056  std::cout << "Please define the Drift Velocity in each process!" << std::endl;
1057  return 0.001;
1058 #endif
1059 }
1060 
1066  RESTDebug << "Entering ... TRestDetectorGas::GetLongitudinalDiffusion( E=" << E << " )" << RESTendl;
1067 
1068  SetPressure(fPressureInAtm);
1069 
1070 #if defined USE_Garfield
1071  if (fStatus != RESTGAS_GASFILE_LOADED) {
1072  RESTDebug << "-- Error : " << __PRETTY_FUNCTION__ << RESTendl;
1073  RESTDebug << "-- Error : Gas file was not loaded!" << RESTendl;
1074  return 0;
1075  }
1076 
1077  RESTInfo << "Calling Garfield directly. Please be aware that the unit is different "
1078  << "from REST standard unit. E is V/cm. The return is cm^1/2" << RESTendl;
1079 
1080  Double_t dl, dt;
1081  fGasMedium->ElectronDiffusion(0., 0, -E, 0, 0, 0, dl, dt);
1082  return dl;
1083 #else
1084  std::cout << "This REST is not compiled with garfield, Do not use Longitudinal "
1085  "Diffusion from TRestDetectorGas!"
1086  << std::endl;
1087  std::cout << "Please define the Longitudinal Diffusion in each process!" << std::endl;
1088  return 0;
1089 #endif
1090 }
1091 
1097  RESTDebug << "Entering ... TRestDetectorGas::GetTransversalDiffusion( E=" << E << " )" << RESTendl;
1098 
1099  SetPressure(fPressureInAtm);
1100 #if defined USE_Garfield
1101  if (fStatus != RESTGAS_GASFILE_LOADED) {
1102  RESTDebug << "-- Error : " << __PRETTY_FUNCTION__ << RESTendl;
1103  RESTDebug << "-- Error : Gas file was not loaded!" << RESTendl;
1104  return 0;
1105  }
1106 
1107  RESTInfo << "Calling Garfield directly. Please be aware that the unit is different "
1108  << "from REST standard unit. E is V/cm. The return is cm^1/2" << RESTendl;
1109 
1110  Double_t dl, dt;
1111  fGasMedium->ElectronDiffusion(0., 0, -E, 0, 0, 0, dl, dt);
1112  return dt;
1113 #else
1114  std::cout << "This REST is not complied with garfield, Do not use Transversal "
1115  "Diffusion from TRestDetectorGas!"
1116  << std::endl;
1117  std::cout << "Please define the Transversal Diffusion in each process!" << std::endl;
1118  return 0;
1119 #endif
1120 }
1121 
1127  RESTDebug << "Entering ... TRestDetectorGas::GetTownsendCoefficient( E=" << E << " )" << RESTendl;
1128 
1129  SetPressure(fPressureInAtm);
1130 #if defined USE_Garfield
1131  if (fStatus != RESTGAS_GASFILE_LOADED) {
1132  RESTDebug << "-- Error : " << __PRETTY_FUNCTION__ << RESTendl;
1133  RESTDebug << "-- Error : Gas file was not loaded!" << RESTendl;
1134  return 0;
1135  }
1136 
1137  RESTInfo << "Calling Garfield directly. Please be aware that the unit is different "
1138  << "from REST standard unit. E is V/cm. The return is V/cm" << RESTendl;
1139 
1140  Double_t alpha;
1141  fGasMedium->ElectronTownsend(0., 0, -E, 0, 0, 0, alpha);
1142  return alpha;
1143 #else
1144  std::cout << "This REST is not complied with garfield, Do not use Townsend "
1145  "Coefficient from TRestDetectorGas!"
1146  << std::endl;
1147  std::cout << "Please define the Townsend Coefficient in each process!" << std::endl;
1148  return 0;
1149 #endif
1150 }
1151 
1157  RESTDebug << "Entering ... TRestDetectorGas::GetAttachmentCoefficient( E=" << E << " )" << RESTendl;
1158 
1159  SetPressure(fPressureInAtm);
1160 #if defined USE_Garfield
1161  if (fStatus != RESTGAS_GASFILE_LOADED) {
1162  RESTDebug << "-- Error : " << __PRETTY_FUNCTION__ << RESTendl;
1163  RESTDebug << "-- Error : Gas file was not loaded!" << RESTendl;
1164  return 0;
1165  }
1166 
1167  RESTInfo << "Calling Garfield directly. Please be aware that the unit is different "
1168  << "from REST standard unit. E is V/cm. The return is V/cm" << RESTendl;
1169 
1170  Double_t eta;
1171  fGasMedium->ElectronAttachment(0., 0, -E, 0, 0, 0, eta);
1172  return eta;
1173 #else
1174  std::cout << "This REST is not complied with garfield, Do not use Attachment "
1175  "Coefficient from TRestDetectorGas!"
1176  << std::endl;
1177  std::cout << "Please define the Attachment Coefficient in each process!" << std::endl;
1178  return 0;
1179 #endif
1180 }
1181 
1186  RESTDebug << "Entering ... TRestDetectorGas::PrintGasInfo( )" << RESTendl;
1187 
1189 
1190  RESTMetadata << "Status : ";
1191  if (fStatus == RESTGAS_INTITIALIZED) RESTMetadata << "Initialized";
1192  if (fStatus == RESTGAS_CFG_LOADED) RESTMetadata << "Configuration loaded";
1193  if (fStatus == RESTGAS_GASFILE_LOADED) RESTMetadata << "Gasfile loaded";
1194  if (fStatus == RESTGAS_ERROR) RESTMetadata << "Error";
1195  RESTMetadata << RESTendl;
1196 
1197  RESTMetadata << "Gas filename : " << TRestTools::GetPureFileName((string)fGasFilename) << RESTendl;
1198  RESTMetadata << "Pressure : " << fPressureInAtm << " atm" << RESTendl;
1199  RESTMetadata << "Temperature : " << fTemperatureInK << " K" << RESTendl;
1200  RESTMetadata << "Electric Field : " << fElectricField * units("V/cm") << " V/cm " << RESTendl;
1201  RESTMetadata << "W-value : " << fW << " eV" << RESTendl;
1202  RESTMetadata << "Drift velocity : " << GetDriftVelocity(fElectricField * units("V/cm")) / units("cm/us")
1203  << " mm/us " << RESTendl;
1204  RESTMetadata << "Max. Electron energy : " << fMaxElectronEnergy << " eV" << RESTendl;
1205  RESTMetadata << "Field grid nodes : " << fEnodes << RESTendl;
1206  RESTMetadata << "Efield range : ( " << fEmin << " , " << fEmax << " ) V/cm " << RESTendl;
1207  RESTMetadata << "Number of Gases : " << fNofGases << RESTendl;
1208  for (int i = 0; i < fNofGases; i++)
1209  RESTMetadata << "Gas id : " << i << ", Name : " << fGasComponentName[i]
1210  << ", Fraction : " << fGasComponentFraction[i] << RESTendl;
1211  RESTMetadata << "******************************************" << RESTendl;
1212  RESTMetadata << RESTendl;
1213  RESTMetadata << RESTendl;
1214 }
1215 
1216 Int_t TRestDetectorGas::Write(const char* name, Int_t option, Int_t bufsize) {
1217  RESTDebug << "Entering ... TRestDetectorGas::Write( name=" << name << " option=" << option
1218  << " bufsize=" << bufsize << " )" << RESTendl;
1219 
1220  if (fGasFileContent == "" && GasFileLoaded()) {
1221  ifstream infile;
1222  infile.open(fGasFilename);
1223  if (!infile) {
1224  cout << "TRestDetectorGas: error reading gas file, gas file content won't be "
1225  "saved!"
1226  << endl;
1227  } else {
1228  string str;
1229  while (getline(infile, str)) {
1230  fGasFileContent += str + "\n";
1231  }
1232  }
1233  }
1234  return TRestMetadata::Write();
1235 }
virtual DBEntry query_data(DBEntry info)
void InitFromConfigFile() override
To make settings from rml file. This method must be implemented in the derived class.
virtual void SetElectricField(double value)
Sets the electric field. Must be given in V/mm.
std::string ConstructFilename()
Constructs the filename of the pre-generated gas file using the members defined in the RML file.
void InitFromConfigFile() override
Loads the gas parameters that define the gas calculation and properties.
void InitFromRootFile() override
Method called after the object is retrieved from root file.
TString GetGasComponentName(Int_t n)
Returns the gas component n.
void PrintGasInfo()
Prints the metadata information from the gas.
void PlotTransversalDiffusion(Double_t eMin, Double_t eMax, Int_t nSteps)
It creates a TCanvas where it plots the transversal diffusion as a function of the electric field.
bool GasFileLoaded() const
Returns true if the gas file has been properly loaded. False otherwise.
Double_t GetAttachmentCoefficient(Double_t E)
It returns the attachment coefficient for a given electric field in V/cm.
Double_t GetTransversalDiffusion() override
Returns the transversal diffusion in (cm)^1/2.
TString GetGasMixture()
Returns a string defining the gas components and fractions.
void SetPressure(Double_t pressure) override
Defines the pressure of the gas.
~TRestDetectorGas()
TRestDetectorGas default destructor.
void PlotTownsendCoefficient(Double_t eMin, Double_t eMax, Int_t nSteps)
It creates a TCanvas where it plots the townsend coefficient as a function of the electric field.
TRestDetectorGas()
TRestDetectorGas default constructor.
Double_t GetDriftVelocity() override
Returns the drift velocity in mm/us.
Double_t GetTownsendCoefficient(Double_t E)
It returns the townsend coefficient for a given electric field in V/cm.
void SetTemperature(Double_t temperature) override
Defines the temperature of the gas.
Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0) override
overwriting the write() method with fStore considered
void LoadGasFile()
It loads a pre-generated gas file corresponding to the gas defined using the RML TRestDetectorGas sec...
void Initialize() override
Defines the metadata section name and initalizes the TRestDetectorGas members.
void AddGasComponent(std::string gasName, Double_t fraction)
Adds a new element/compound to the gas.
std::string FindGasFile(std::string name)
This method tries to find the gas filename given in the argument.
void PlotDriftVelocity(Double_t eMin, Double_t eMax, Int_t nSteps)
It creates a TCanvas where it plots the drift velocity as a function of the electric field.
void PlotLongitudinalDiffusion(Double_t eMin, Double_t eMax, Int_t nSteps)
It creates a TCanvas where it plots the longitudinal diffusion as a function of the electric field.
void GenerateGasFile()
Save a gas file with a structured file name.
Double_t GetGasComponentFraction(Int_t n)
Returns the gas fraction in volume for component n.
Double_t GetLongitudinalDiffusion() override
Returns the longitudinal diffusion in (cm)^1/2.
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.
TRestStringOutput::REST_Verbose_Level fVerboseLevel
Verbose level used to print debug info.
TiXmlElement * StringToElement(std::string definition)
Parsing a string into TiXmlElement object.
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.
virtual void InitFromRootFile()
Method called after the object is retrieved from root file.
Int_t LoadConfigFromElement(TiXmlElement *eSectional, TiXmlElement *eGlobal, std::map< std::string, std::string > envs={})
Main starter method.
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.
void WriteConfigBuffer(std::string fName)
Writes the config buffer to a file in append mode.
std::string fConfigFileName
Full name of the rml file.
virtual Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0)
overwriting the write() method with fStore considered
TiXmlElement * GetNextElement(TiXmlElement *e)
Get the next sibling xml element of this element, with same eleDeclare.
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.
@ REST_Info
+show most of the information for each steps
static std::string GetPureFileName(const std::string &fullPathFileName)
Removes all directories in the full path filename description given in the argument.
Definition: TRestTools.cxx:863
static bool fileExists(const std::string &filename)
Returns true if the file (or directory) with path filename exists.
Definition: TRestTools.cxx:728
static std::string DownloadRemoteFile(const std::string &remoteFile, bool pidPrefix=false)
download the remote file automatically, returns the downloaded file name.
static bool isPathWritable(const std::string &path)
Returns true if the path given by argument is writable.
Definition: TRestTools.cxx:778
static int UploadToServer(std::string localFile, std::string remoteFile, std::string methodUrl="")
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.
Double_t StringToDouble(std::string in)
Gets a double from a string.
std::string ToUpper(std::string in)
Convert string to its upper case. Alternative of TString::ToUpper.
Int_t StringToInteger(std::string in)
Gets an integer from a string.