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 
46 
47 #include "TRestGeant4QuenchingProcess.h"
48 
49 using namespace std;
50 
52 
57 
71  Initialize();
72 
73  if (LoadConfigFromFile(configFilename)) {
74  LoadDefaultConfig();
75  }
76 }
77 
82 
86 void TRestGeant4QuenchingProcess::LoadDefaultConfig() { SetTitle("Default config"); }
87 
93  fGeant4Metadata = nullptr;
94  SetSectionName(this->ClassName());
95  SetLibraryVersion(LIBRARY_VERSION);
96 
97  fInputG4Event = nullptr;
98  fOutputG4Event = new TRestGeant4Event();
99 }
100 
113 void TRestGeant4QuenchingProcess::LoadConfig(const string& configFilename, const string& name) {
114  if (LoadConfigFromFile(configFilename, name)) {
115  LoadDefaultConfig();
116  }
117 }
118 
120  TiXmlElement* volumeElement = GetElement("volume");
121  while (volumeElement) {
122  TiXmlElement* particleElement = GetElement("particle", volumeElement);
123  const string volumeName = GetParameter("name", volumeElement, "");
124  if (volumeName.empty()) {
125  cerr << "TRestGeant4QuenchingProcess: No volume expression specified" << endl;
126  exit(1);
127  }
128  while (particleElement) {
129  const string particleName = GetParameter("name", particleElement, "");
130  if (particleName.empty()) {
131  cerr << "TRestGeant4QuenchingProcess: No particle name specified" << endl;
132  exit(1);
133  }
134  const auto quenchingFactor = stof(GetParameter("quenchingFactor", particleElement, -1.0));
135  // if no value is specified, give error
136  if (quenchingFactor < 0.0 || quenchingFactor > 1.0) {
137  cerr << "TRestGeant4QuenchingProcess: Quenching factor must be between 0 and 1" << endl;
138  exit(1);
139  }
140  fUserVolumeParticleQuenchingFactor[volumeName][particleName] = quenchingFactor;
141  particleElement = GetNextElement(particleElement);
142  }
143  volumeElement = GetNextElement(volumeElement);
144  }
145 }
146 
150  fGeant4Metadata = GetMetadata<TRestGeant4Metadata>();
151  if (fGeant4Metadata == nullptr) {
152  cerr << "TRestGeant4QuenchingProcess: No TRestGeant4Metadata found" << endl;
153  exit(1);
154  }
155 
156  const auto geometryInfo = fGeant4Metadata->GetGeant4GeometryInfo();
157  // check all the user volume expressions are valid and correspond to at least a volume
158  for (const auto& [userVolume, particleToQuenchingMap] : fUserVolumeParticleQuenchingFactor) {
159  set<string> physicalVolumes = {};
160  for (const auto& volume : geometryInfo.GetAllPhysicalVolumesMatchingExpression(userVolume)) {
161  physicalVolumes.insert(volume.Data());
162  }
163  if (!physicalVolumes.empty()) {
164  continue;
165  }
166  // maybe it refers to a logical volume
167  for (const auto& logicalVolume : geometryInfo.GetAllLogicalVolumesMatchingExpression(userVolume)) {
168  for (const auto& volume : geometryInfo.GetAllPhysicalVolumesFromLogical(logicalVolume.Data())) {
169  physicalVolumes.insert(volume.Data());
170  }
171  }
172 
173  if (physicalVolumes.empty()) {
174  cerr << "TRestGeant4QuenchingProcess: No volume found matching expression " << userVolume << endl;
175  exit(1);
176  }
177 
178  for (const auto& physicalVolume : physicalVolumes) {
179  const auto volumeName = geometryInfo.GetAlternativeNameFromGeant4PhysicalName(physicalVolume);
180  fVolumeParticleQuenchingFactor[volumeName.Data()] = particleToQuenchingMap;
181  }
182  }
183 
184  RESTDebug << "TRestGeant4QuenchingProcess initialized with volumes" << RESTendl;
185  for (const auto& [volume, particleToQuenchingMap] : fVolumeParticleQuenchingFactor) {
186  RESTDebug << volume << RESTendl;
187  for (const auto& [particle, quenchingFactor] : particleToQuenchingMap) {
188  RESTDebug << "\t" << particle << " " << quenchingFactor << RESTendl;
189  }
190  }
191 }
192 
197  fInputG4Event = (TRestGeant4Event*)inputEvent;
198  *fOutputG4Event = *((TRestGeant4Event*)inputEvent);
199 
200  fOutputG4Event->InitializeReferences(GetRunInfo());
201  fOutputG4Event->fEnergyInVolumePerParticlePerProcess.clear();
202 
203  // loop over all tracks
204  for (int trackIndex = 0; trackIndex < int(fOutputG4Event->GetNumberOfTracks()); trackIndex++) {
205  // get the track
206  TRestGeant4Track* track = fOutputG4Event->GetTrackPointer(trackIndex);
207  const auto& particleName = track->GetParticleName();
208 
209  auto hits = track->GetHitsPointer();
210  auto& energy = hits->GetEnergyRef();
211  for (int hitIndex = 0; hitIndex < int(hits->GetNumberOfHits()); hitIndex++) {
212  const auto& volumeName = hits->GetVolumeName(hitIndex);
213  const float_t quenchingFactor =
214  GetQuenchingFactorForVolumeAndParticle(volumeName.Data(), particleName.Data());
215  // default is 1.0, so no quenching
216  energy[hitIndex] *= quenchingFactor;
217 
218  // cout << "TRestGeant4QuenchingProcess: Quenching " << particleName << " in " << volumeName
219  // << " by " << quenchingFactor << endl;
220 
221  const string processName = hits->GetProcessName(hitIndex).Data();
222 
223  if (energy[hitIndex] > 0) {
224  fOutputG4Event->fEnergyInVolumePerParticlePerProcess[volumeName.Data()][particleName.Data()]
225  [processName] += energy[hitIndex];
226  }
227  }
228  }
229 
230  // Update the stores for energy in volumes (this should be automatic and not duplicated)
231 
232  return fOutputG4Event;
233 }
234 
238 
239 vector<string> TRestGeant4QuenchingProcess::GetUserVolumeExpressions() const {
240  vector<string> userVolumeExpressions;
241  userVolumeExpressions.reserve(fUserVolumeParticleQuenchingFactor.size());
242  for (auto const& x : fUserVolumeParticleQuenchingFactor) {
243  userVolumeExpressions.push_back(x.first);
244  }
245  return userVolumeExpressions;
246 }
247 
248 float_t TRestGeant4QuenchingProcess::GetQuenchingFactorForVolumeAndParticle(
249  const string& volumeName, const string& particleName) const {
250  float_t quenchingFactor = 1.0;
251  // check if the volume is in the map
252  if (fVolumeParticleQuenchingFactor.find(volumeName) != fVolumeParticleQuenchingFactor.end()) {
253  // check if the particle is in the map
254  if (fVolumeParticleQuenchingFactor.at(volumeName).find(particleName) !=
255  fVolumeParticleQuenchingFactor.at(volumeName).end()) {
256  quenchingFactor = fVolumeParticleQuenchingFactor.at(volumeName).at(particleName);
257  }
258  }
259  return quenchingFactor;
260 }
261 
263  BeginPrintProcess();
264  cout << "Printing TRestGeant4QuenchingProcess user configuration" << endl;
265  for (auto const& [volume, particleQuenchingFactorMap] : fUserVolumeParticleQuenchingFactor) {
266  cout << "Volume: " << volume << endl;
267  for (auto const& [particle, quenchingFactor] : particleQuenchingFactorMap) {
268  cout << " - Particle: " << particle << " Quenching factor: " << quenchingFactor << endl;
269  }
270  }
271 
272  if (!fVolumeParticleQuenchingFactor.empty()) {
273  cout << "Printing TRestGeant4QuenchingProcess configuration with actual volumes" << endl;
274  for (auto const& [volume, particleQuenchingFactorMap] : fVolumeParticleQuenchingFactor) {
275  cout << "Volume: " << volume << endl;
276  for (auto const& [particle, quenchingFactor] : particleQuenchingFactorMap) {
277  cout << " - Particle: " << particle << " Quenching factor: " << quenchingFactor << endl;
278  }
279  }
280  }
281  EndPrintProcess();
282 }
A base class for any REST event.
Definition: TRestEvent.h:38
virtual void InitializeReferences(TRestRun *run)
Initialize dynamical references when loading the event from a root file.
Definition: TRestEvent.cxx:175
An event class to store geant4 generated event information.
Recomputes the energy of every hit based on quenching factor for each particle and volume.
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.
void PrintMetadata() override
Implemented it in the derived metadata class to print out specific metadata information.
void EndProcess() override
Function to include required actions after all events have been processed.
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.