REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestGeant4QuenchingProcess.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
54
55#include "TRestGeant4QuenchingProcess.h"
56
57#include <TMath.h>
58
59#include <algorithm>
60#include <cctype>
61#include <cmath>
62#include <limits>
63#include <stdexcept>
64
65using namespace std;
66
68
69namespace {
70string ToLower(string value) {
71 transform(value.begin(), value.end(), value.begin(),
72 [](unsigned char c) { return static_cast<char>(tolower(c)); });
73 return value;
74}
75
76string NormalizeQuenchingModel(const string& model) {
77 const auto normalized = ToLower(model);
78 if (normalized == "auto" || normalized == "lindhard" || normalized == "birks" ||
79 normalized == "lindhard-stopped-recoil") {
80 return normalized;
81 }
82
83 RESTWarning << "TRestGeant4QuenchingProcess: Unknown quenching model '" << model
84 << "'. Falling back to auto." << RESTendl;
85 return "auto";
86}
87
88string InferQuenchingModel(const string& requestedModel, const string& userVolumeExpression,
89 const string& volumeName) {
90 if (requestedModel != "auto") {
91 return requestedModel;
92 }
93
94 const auto haystack = ToLower(userVolumeExpression + " " + volumeName);
95 if (haystack.find("scintillator") != string::npos || haystack.find("veto") != string::npos) {
96 return "birks";
97 }
98 return "lindhard";
99}
100
101double Clamp01(double value) {
102 if (value < 0) {
103 return 0;
104 }
105 if (value > 1) {
106 return 1;
107 }
108 return value;
109}
110
111double LindhardQuenchingFactor(double recoilEnergy, int A, int Z) {
112 if (recoilEnergy <= 0 || A <= 0 || Z <= 0) {
113 return 1.0;
114 }
115
116 const double gamma = 11.5 * recoilEnergy * TMath::Power(Z, -7.0 / 3.0);
117 const double g = 3 * TMath::Power(gamma, 0.15) + 0.7 * TMath::Power(gamma, 0.6) + gamma;
118 const double k = 0.133 * TMath::Power(Z, 2.0 / 3.0) * TMath::Power(A, -1.0 / 2.0);
119 return Clamp01(k * g / (1 + k * g));
120}
121
122// Unlike historical Lindhard, A and Z describe the recoil track, never the hadronic target.
123bool GetRecoilIsotope(const TRestGeant4Track& track, const TRestGeant4PhysicsInfo& physicsInfo, int& A,
124 int& Z) {
125 const string name = track.GetParticleName().Data();
126 const auto pdg = physicsInfo.GetParticleID(track.GetParticleName());
127 if (pdg == 2212 || (pdg == 0 && name == "proton")) {
128 A = Z = 1;
129 return true;
130 }
131 if (pdg >= 1000000000) {
132 // Geant4 ground-state nuclear code 10LZZZAAAI. Excited/hypernuclear tracks are unsupported.
133 Z = (pdg / 10000) % 1000;
134 A = (pdg / 10) % 1000;
135 if (pdg / 100000000 != 10 || (pdg / 10000000) % 10 != 0 || pdg % 10 != 0 || Z <= 0 || A < Z) {
136 throw runtime_error("unsupported nuclear PDG code " + to_string(pdg));
137 }
138 return true;
139 }
140 if (pdg != 0) {
141 return false;
142 }
143 // Common non-recoil names remain unquenched even in old files lacking their PDG mapping.
144 const auto lowerName = ToLower(name);
145 if (lowerName == "e-" || lowerName == "e+" || lowerName == "gamma" || lowerName == "opticalphoton" ||
146 lowerName == "neutron" || lowerName == "mu-" || lowerName == "mu+" || lowerName == "geantino" ||
147 lowerName == "chargedgeantino" || lowerName.find("neutrino") != string::npos) {
148 return false;
149 }
150 throw runtime_error("missing recoil identity in the particle-name/PDG map for '" + name + "'");
151}
152
153double StoppedRecoilQuenchingFactor(const TRestGeant4Track& track, const TRestGeant4Event& event,
154 int volumeId, int A, int Z) {
155 const auto& hits = track.GetHits();
156 const double initialEnergy = track.GetInitialKineticEnergy();
157 if (!isfinite(initialEnergy) || initialEnergy <= 0 || hits.GetNumberOfHits() < 2) {
158 throw runtime_error("missing positive initial kinetic energy or complete Init/step history");
159 }
160 const double tolerance = 8 * numeric_limits<float>::epsilon() * initialEnergy;
161 if (hits.GetProcessId(0) != 0 || hits.GetEnergy(0) != 0 || !isfinite(hits.GetKineticEnergy(0)) ||
162 abs(hits.GetKineticEnergy(0) - initialEnergy) > tolerance) {
163 throw runtime_error("first saved hit is not the unmodified track Init state");
164 }
165 if (!track.GetSecondaryTrackIDs().empty()) {
166 throw runtime_error("explicit secondary track IDs are present");
167 }
168 for (const auto& other : event.GetTracks()) {
169 if (other.GetParentID() == track.GetTrackID()) {
170 throw runtime_error("an explicit child track is present in the event");
171 }
172 }
173 double previousEnergy = initialEnergy;
174 double totalDeposit = 0;
175 for (size_t hit = 0; hit < hits.GetNumberOfHits(); ++hit) {
176 if (hits.GetVolumeId(hit) != volumeId) {
177 throw runtime_error("recoil is born outside, leaves, or spans the selected physical volume");
178 }
179 const double deposit = hits.GetEnergy(hit);
180 const double remainingEnergy = hits.GetKineticEnergy(hit);
181 if (!isfinite(deposit) || deposit < 0 || !isfinite(remainingEnergy) || remainingEnergy < 0 ||
182 remainingEnergy > previousEnergy + tolerance ||
183 abs(previousEnergy - remainingEnergy - deposit) > tolerance) {
184 throw runtime_error("saved kinetic-energy loss does not close with the local deposited energy");
185 }
186 totalDeposit += deposit;
187 previousEnergy = remainingEnergy;
188 }
189 if (previousEnergy != 0 || abs(totalDeposit - initialEnergy) > tolerance) {
190 throw runtime_error("recoil is not stopped with its initial kinetic energy deposited locally");
191 }
192 return LindhardQuenchingFactor(initialEnergy, A, Z);
193}
194
195bool IsNeutralParticleWithoutBirksQuenching(const string& particleName) {
196 const auto name = ToLower(particleName);
197 return name == "gamma" || name == "opticalphoton" || name == "geantino" || name == "chargedgeantino" ||
198 name.find("neutrino") != string::npos;
199}
200
201double EstimateStepLength(const TRestGeant4Hits& hits, int hitIndex, double fallbackStepLength) {
202 const auto nHits = static_cast<int>(hits.GetNumberOfHits());
203 if (nHits <= 1) {
204 return fallbackStepLength;
205 }
206
207 const auto volumeId = hits.GetVolumeId(hitIndex);
208 const auto position = hits.GetPosition(hitIndex);
209 double stepLength = numeric_limits<double>::max();
210
211 if (hitIndex > 0 && hits.GetVolumeId(hitIndex - 1) == volumeId) {
212 stepLength = min(stepLength, (position - hits.GetPosition(hitIndex - 1)).Mag());
213 }
214 if (hitIndex + 1 < nHits && hits.GetVolumeId(hitIndex + 1) == volumeId) {
215 stepLength = min(stepLength, (hits.GetPosition(hitIndex + 1) - position).Mag());
216 }
217
218 if (!std::isfinite(stepLength) || stepLength <= 0 || stepLength == numeric_limits<double>::max()) {
219 return fallbackStepLength;
220 }
221 return stepLength;
222}
223
224double BirksQuenchingFactor(double energy, double stepLength, double birksConstant) {
225 if (energy <= 0 || stepLength <= 0 || birksConstant <= 0) {
226 return 1.0;
227 }
228
229 const double dEdx = energy / stepLength;
230 return Clamp01(1.0 / (1.0 + birksConstant * dEdx));
231}
232} // namespace
233
238
252 Initialize();
253
254 if (LoadConfigFromFile(configFilename)) {
256 }
257}
258
263
267void TRestGeant4QuenchingProcess::LoadDefaultConfig() { SetTitle("Default config"); }
268
274 fGeant4Metadata = nullptr;
275 SetSectionName(this->ClassName());
276 SetLibraryVersion(LIBRARY_VERSION);
277
278 fInputG4Event = nullptr;
280
281 fBirksConstant = 0.000126; // 0.126 mm/MeV in REST units, mm/keV
282 fBirksFallbackStepLength = 0.5; // mm
283 fApplyToHitEnergies = true;
284}
285
298void TRestGeant4QuenchingProcess::LoadConfig(const string& configFilename, const string& name) {
299 if (LoadConfigFromFile(configFilename, name)) {
301 }
302}
303
305 fUserVolumeExpressions.clear();
306 fUserVolumeModels.clear();
307 fUserVolumeBirksConstants.clear();
308 fUserVolumeBirksFallbackStepLengths.clear();
309
310 fApplyToHitEnergies = StringToBool(GetParameter("applyToHitEnergies", fApplyToHitEnergies));
311 fBirksConstant = GetDblParameterWithUnits("birksConstant", fBirksConstant);
312 fBirksFallbackStepLength = GetDblParameterWithUnits("birksFallbackStepLength", fBirksFallbackStepLength);
313
314 TiXmlElement* volumeElement = GetElement("volume");
315 while (volumeElement) {
316 const string volumeName = GetParameter("name", volumeElement, "");
317 if (volumeName.empty()) {
318 cerr << "TRestGeant4QuenchingProcess: No volume expression specified" << endl;
319 exit(1);
320 }
321 fUserVolumeExpressions.insert(volumeName);
322 fUserVolumeModels[volumeName] =
323 NormalizeQuenchingModel(GetParameter("model", volumeElement, string("auto")));
324 fUserVolumeBirksConstants[volumeName] =
325 GetDblParameterWithUnits("birksConstant", volumeElement, fBirksConstant);
326 fUserVolumeBirksFallbackStepLengths[volumeName] =
327 GetDblParameterWithUnits("birksFallbackStepLength", volumeElement, fBirksFallbackStepLength);
328 volumeElement = GetNextElement(volumeElement);
329 }
330}
331
335 fGeant4Metadata = GetMetadata<TRestGeant4Metadata>();
336 if (fGeant4Metadata == nullptr) {
337 cerr << "TRestGeant4QuenchingProcess: No TRestGeant4Metadata found" << endl;
338 exit(1);
339 }
340
341 fVolumes.clear();
342 fVolumeModels.clear();
343 fVolumeBirksConstants.clear();
344 fVolumeBirksFallbackStepLengths.clear();
345
346 const auto geometryInfo = fGeant4Metadata->GetGeant4GeometryInfo();
347 // check all the user volume expressions are valid and correspond to at least a volume
348 for (const auto& userVolume : fUserVolumeExpressions) {
349 set<string> physicalVolumes = {};
350 for (const auto& volume : geometryInfo.GetAllPhysicalVolumesMatchingExpression(userVolume)) {
351 physicalVolumes.insert(volume.Data());
352 }
353 if (physicalVolumes.empty()) {
354 // maybe it refers to a logical volume
355 for (const auto& logicalVolume :
356 geometryInfo.GetAllLogicalVolumesMatchingExpression(userVolume)) {
357 for (const auto& volume :
358 geometryInfo.GetAllPhysicalVolumesFromLogical(logicalVolume.Data())) {
359 physicalVolumes.insert(volume.Data());
360 }
361 }
362 }
363
364 if (physicalVolumes.empty()) {
365 if (fUserVolumeModels[userVolume] == "lindhard-stopped-recoil") {
366 throw runtime_error("TRestGeant4QuenchingProcess: No volume matches stopped-recoil " +
367 userVolume);
368 }
369 RESTWarning << "TRestGeant4QuenchingProcess: No volume found matching expression: " << userVolume
370 << RESTendl;
371 continue;
372 }
373
374 for (const auto& physicalVolume : physicalVolumes) {
375 const auto volumeName = geometryInfo.GetAlternativeNameFromGeant4PhysicalName(physicalVolume);
376 const string volumeNameString = volumeName.Data();
377 fVolumes.insert(volumeNameString);
378 fVolumeModels[volumeNameString] =
379 InferQuenchingModel(fUserVolumeModels[userVolume], userVolume, volumeNameString);
380 fVolumeBirksConstants[volumeNameString] = fUserVolumeBirksConstants[userVolume];
381 fVolumeBirksFallbackStepLengths[volumeNameString] =
382 fUserVolumeBirksFallbackStepLengths[userVolume];
383 }
384 }
385
386 for (const auto& volume : fVolumes) {
387 if (fVolumeModels[volume] != "lindhard-stopped-recoil") {
388 continue;
389 }
390 if (!fGeant4Metadata->GetStoreTracks() || !fGeant4Metadata->RegisterEmptyTracks() ||
391 fGeant4Metadata->GetRemoveUnwantedTracks() || !fGeant4Metadata->GetKillVolumes().empty() ||
392 fGeant4Metadata->GetStorageChance(volume) != 1.0) {
393 throw runtime_error(
394 "TRestGeant4QuenchingProcess: lindhard-stopped-recoil requires storeTracks=true, "
395 "registerEmptyTracks=true, removeUnwantedTracks=false, no kill volumes, and "
396 "storage chance=1 for " +
397 volume);
398 }
399 // Otherwise a lossless exit/re-entry through an unrecorded volume can look contained.
400 for (const auto& physical : geometryInfo.GetAllPhysicalVolumes()) {
401 auto names = geometryInfo.GetAlternativeNamesFromGeant4PhysicalName(physical);
402 if (names.empty()) {
403 names.insert(physical);
404 }
405 for (const auto& stored : names) {
406 if (fGeant4Metadata->GetStorageChance(stored) != 1.0) {
407 throw runtime_error(
408 "TRestGeant4QuenchingProcess: lindhard-stopped-recoil requires "
409 "complete geometry-volume storage; incomplete volume " +
410 string(stored.Data()));
411 }
412 }
413 }
414 }
415
416 RESTDebug << "TRestGeant4QuenchingProcess initialized with volumes" << RESTendl;
417 for (const auto& volume : fVolumes) {
418 RESTDebug << " " << volume << " (" << fVolumeModels[volume] << ")" << RESTendl;
419 }
420}
421
426 fInputG4Event = (TRestGeant4Event*)inputEvent;
427 *fOutputG4Event = *((TRestGeant4Event*)inputEvent);
428
429 const string sensitiveVolumeName = fGeant4Metadata->GetSensitiveVolume().Data();
430 const double sensitiveVolumeEnergyBefore = fOutputG4Event->GetEnergyInVolume(sensitiveVolumeName);
431
433
434 // Validate the original saved history before modifying any energies. This also rejects applying
435 // this option a second time: visible deposits no longer close with the original kinetic losses.
436 map<int, double> stoppedRecoilFactors;
437 const bool hasStoppedRecoilModel =
438 any_of(fVolumeModels.begin(), fVolumeModels.end(),
439 [](const auto& model) { return model.second == "lindhard-stopped-recoil"; });
440 for (size_t trackIndex = 0; trackIndex < fOutputG4Event->GetNumberOfTracks(); ++trackIndex) {
441 if (!hasStoppedRecoilModel) {
442 break;
443 }
444 const auto& track = fOutputG4Event->GetTrack(trackIndex);
445 const auto& hits = track.GetHits();
446 if (!hits.HasCompleteStepInfo()) {
447 throw runtime_error(
448 "TRestGeant4QuenchingProcess: lindhard-stopped-recoil missing step "
449 "metadata event=" +
450 to_string(fOutputG4Event->GetID()) + " track=" + to_string(track.GetTrackID()));
451 }
452 for (size_t hit = 0; hit < hits.GetNumberOfHits(); ++hit) {
453 const string volume = hits.GetVolumeName(hit).Data();
454 if (hits.GetEnergy(hit) <= 0 || fVolumeModels.count(volume) == 0 ||
455 fVolumeModels.at(volume) != "lindhard-stopped-recoil") {
456 continue;
457 }
458 try {
459 int A = 0, Z = 0;
460 if (GetRecoilIsotope(track, fGeant4Metadata->GetGeant4PhysicsInfo(), A, Z)) {
461 stoppedRecoilFactors[trackIndex] =
462 StoppedRecoilQuenchingFactor(track, *fOutputG4Event, hits.GetVolumeId(hit), A, Z);
463 }
464 } catch (const runtime_error& error) {
465 throw runtime_error(
466 "TRestGeant4QuenchingProcess: lindhard-stopped-recoil unsupported "
467 "event=" +
468 to_string(fOutputG4Event->GetID()) + " track=" + to_string(track.GetTrackID()) +
469 " volume=" + volume + ": " + error.what());
470 }
471 break;
472 }
473 }
474 fOutputG4Event->fEnergyInVolumePerParticlePerProcess.clear();
475 fOutputG4Event->fTotalDepositedEnergy = 0;
476 fOutputG4Event->SetSensitiveVolumeEnergy(0);
477 fill(fOutputG4Event->fVolumeDepositedEnergy.begin(), fOutputG4Event->fVolumeDepositedEnergy.end(), 0.0);
478
479 bool missingHadronicInfoWarningPrinted = false;
480
481 // loop over all tracks
482 for (int trackIndex = 0; trackIndex < int(fOutputG4Event->GetNumberOfTracks()); trackIndex++) {
483 // get the track
484 TRestGeant4Track* track = fOutputG4Event->GetTrackPointer(trackIndex);
485 const string particleName = track->GetParticleName().Data();
486
487 auto hits = track->GetHitsPointer();
488 auto& energy = hits->GetEnergyRef();
489 for (int hitIndex = 0; hitIndex < int(hits->GetNumberOfHits()); hitIndex++) {
490 const string volumeName = hits->GetVolumeName(hitIndex).Data();
491 const double depositedEnergy = hits->GetEnergy(hitIndex);
492 double quenchingFactor = 1.0;
493
494 if (fVolumes.count(volumeName) && depositedEnergy > 0) {
495 const auto model =
496 fVolumeModels.count(volumeName) ? fVolumeModels[volumeName] : string("lindhard");
497 if (model == "birks") {
498 if (!IsNeutralParticleWithoutBirksQuenching(particleName)) {
499 const double stepLength =
500 EstimateStepLength(*hits, hitIndex, fVolumeBirksFallbackStepLengths[volumeName]);
501 quenchingFactor = BirksQuenchingFactor(depositedEnergy, stepLength,
502 fVolumeBirksConstants[volumeName]);
503 }
504 } else if (model == "lindhard-stopped-recoil") {
505 if (stoppedRecoilFactors.count(trackIndex)) {
506 quenchingFactor = stoppedRecoilFactors.at(trackIndex);
507 }
508 } else if (model == "lindhard") {
509 if (hits->GetHadronicOk()) {
510 const string isotopeName = hits->GetHadronicTargetIsotopeName(hitIndex);
511 const int isotopeA = hits->GetHadronicTargetIsotopeA(hitIndex);
512 const int isotopeZ = hits->GetHadronicTargetIsotopeZ(hitIndex);
513 if (!isotopeName.empty()) {
514 quenchingFactor = LindhardQuenchingFactor(depositedEnergy, isotopeA, isotopeZ);
515 }
516 } else if (!missingHadronicInfoWarningPrinted) {
517 RESTWarning
518 << "TRestGeant4QuenchingProcess: Lindhard quenching requested but "
519 "hadronic target information is not available. Unquenched hit energies "
520 "will be used for those hits. Enable storeHadronicTargetInfo in restG4 "
521 "to apply this model."
522 << RESTendl;
523 missingHadronicInfoWarningPrinted = true;
524 }
525 }
526 }
527
528 const auto visibleEnergy = depositedEnergy * quenchingFactor;
529 if (fApplyToHitEnergies) {
530 energy[hitIndex] = visibleEnergy;
531 }
532
533 const auto processName = hits->GetProcessName(hitIndex);
534
535 if (visibleEnergy > 0) {
536 fOutputG4Event->AddEnergyInVolumeForParticleForProcess(visibleEnergy, volumeName,
537 particleName, processName.Data());
538 const auto volumeId = hits->GetVolumeId(hitIndex);
539 if (volumeId >= 0 && volumeId < int(fOutputG4Event->fVolumeDepositedEnergy.size())) {
540 fOutputG4Event->fVolumeDepositedEnergy[volumeId] += visibleEnergy;
541 }
542 }
543 }
544 }
545
546 const double sensitiveVolumeEnergyAfter = fOutputG4Event->GetEnergyInVolume(sensitiveVolumeName);
547 fOutputG4Event->SetSensitiveVolumeEnergy(sensitiveVolumeEnergyAfter);
548
549 bool sensitiveQuenched = TMath::Abs(sensitiveVolumeEnergyAfter - sensitiveVolumeEnergyBefore) > 1e-2;
550 SetObservableValue("sensitiveQuenched", sensitiveQuenched);
551 SetObservableValue("sensitiveVolumeEnergyBefore", sensitiveVolumeEnergyBefore);
552 SetObservableValue("sensitiveVolumeEnergyAfter", sensitiveVolumeEnergyAfter);
553
554 return fOutputG4Event;
555}
556
558
561 RESTMetadata << "Apply to hit energies: " << (fApplyToHitEnergies ? "true" : "false") << RESTendl;
562 RESTMetadata << "Default Birks constant: " << fBirksConstant << " mm/keV" << RESTendl;
563 RESTMetadata << "Default Birks fallback step length: " << fBirksFallbackStepLength << " mm" << RESTendl;
564 for (auto const& volume : fVolumes) {
565 RESTMetadata << "Volume: " << volume << " model=" << fVolumeModels[volume] << RESTendl;
566 }
567 EndPrintProcess();
568}
569
570std::set<std::string> TRestGeant4QuenchingProcess::GetVolumes() const { return fVolumes; }
571
572std::set<std::string> TRestGeant4QuenchingProcess::GetUserVolumeExpressions() const {
573 return fUserVolumeExpressions;
574}
TRestRun * GetRunInfo() const
Return the pointer of the hosting TRestRun object.
void BeginPrintProcess()
[name, cut range]
void SetObservableValue(const std::string &name, const T &value)
Set observable value for AnalysisTree.
A base class for any REST event.
Definition: TRestEvent.h:38
An event class to store geant4 generated event information.
void InitializeReferences(TRestRun *run) override
Initialize dynamical references when loading the event from a root file.
bool HasCompleteStepInfo() const
True when the saved process, volume, and post-step kinetic-energy arrays cover every hit.
const TRestGeant4PhysicsInfo & GetGeant4PhysicsInfo() const
Returns an immutable reference to the physics info.
TString GetSensitiveVolume(int n=0) const
Returns a std::string with the name of the sensitive volume.
Bool_t RegisterEmptyTracks() const
It returns false if registerEmptyTracks parameter was set to false.
const TRestGeant4GeometryInfo & GetGeant4GeometryInfo() const
Returns an immutable reference to the geometry info.
Double_t GetStorageChance(Int_t n) const
Returns the probability per event to register (write to disk) hits in the storage volume with index n...
Recomputes visible hit energies using hit/contained-recoil Lindhard and Birks quenching models.
TRestGeant4Event * fOutputG4Event
A pointer to the specific TRestGeant4Event output.
void InitFromConfigFile() override
To make settings from rml file. This method must be implemented in the derived class.
TRestEvent * ProcessEvent(TRestEvent *inputEvent) override
The main processing event function.
TRestGeant4Metadata * fGeant4Metadata
A pointer to the simulation metadata information accessible to TRestRun.
void PrintMetadata() override
Implemented it in the derived metadata class to print out specific metadata information.
TRestGeant4Event * fInputG4Event
A pointer to the specific TRestGeant4Event input.
void EndProcess() override
To be executed at the end of the run (outside event loop)
void LoadDefaultConfig()
Function to load the default config in absence of RML input.
void LoadConfig(const std::string &configFilename, const std::string &name="")
Function to load the configuration from an external configuration file.
TRestGeant4QuenchingProcess()
Default constructor.
void Initialize() override
Function to initialize input/output event members and define the section name.
~TRestGeant4QuenchingProcess() override
Default destructor.
void InitProcess() override
Process initialization. User volume expressions are matched to physical volumes.
TVector3 GetPosition(int n) const
It returns the position of hit number n.
Definition: TRestHits.cxx:515
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.
void SetSectionName(std::string sName)
set the section name, clear the section content
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.
std::string ToLower(std::string in)
Convert string to its lower case. Alternative of TString::ToLower.