88 #include "TRestGeant4NeutronTaggingProcess.h"
94 TRestGeant4NeutronTaggingProcess::TRestGeant4NeutronTaggingProcess() { Initialize(); }
96 TRestGeant4NeutronTaggingProcess::TRestGeant4NeutronTaggingProcess(
const char* configFilename) {
98 if (LoadConfigFromFile(configFilename)) LoadDefaultConfig();
116 fG4Metadata =
nullptr;
118 SetSectionName(this->ClassName());
119 SetLibraryVersion(LIBRARY_VERSION);
121 fInputG4Event =
nullptr;
138 if (LoadConfigFromFile(configFilename, name)) LoadDefaultConfig();
145 fG4Metadata = GetMetadata<TRestGeant4Metadata>();
151 if (fVetoVolumeIds.empty()) {
152 for (
unsigned int i = 0; i < fG4Metadata->GetNumberOfActiveVolumes(); i++) {
153 string volume_name = (string)fG4Metadata->GetActiveVolumeName(i);
155 if (volume_name.find(
TrimAndLower(fVetoKeyword)) != string::npos) {
156 fVetoVolumeIds.push_back(i);
157 }
else if (volume_name.find(
TrimAndLower(fCaptureKeyword)) != string::npos) {
158 fCaptureVolumeIds.push_back(i);
159 }
else if (volume_name.find(
TrimAndLower(fShieldingKeyword)) != string::npos) {
160 fShieldingVolumeIds.push_back(i);
165 for (
unsigned int i = 0; i < fVetoGroupKeywords.size(); i++) {
166 string veto_group_keyword =
TrimAndLower(fVetoGroupKeywords[i]);
167 fVetoGroupVolumeNames[veto_group_keyword] = std::vector<string>{};
168 for (
int&
id : fVetoVolumeIds) {
169 string volume_name = (string)fG4Metadata->GetActiveVolumeName(
id);
171 if (volume_name.find(veto_group_keyword) != string::npos) {
172 fVetoGroupVolumeNames[veto_group_keyword].push_back(
173 (
string)fG4Metadata->GetActiveVolumeName(
id));
182 void TRestGeant4NeutronTaggingProcess::Reset() {
188 fNeutronsCapturedNumber = 0;
189 fNeutronsCapturedPosX.clear();
190 fNeutronsCapturedPosY.clear();
191 fNeutronsCapturedPosZ.clear();
192 fNeutronsCapturedIsCaptureVolume.clear();
193 fNeutronsCapturedProductionE.clear();
194 fNeutronsCapturedEDepByNeutron.clear();
195 fNeutronsCapturedEDepByNeutronAndChildren.clear();
196 fNeutronsCapturedEDepByNeutronInVeto.clear();
197 fNeutronsCapturedEDepByNeutronAndChildrenInVeto.clear();
198 fNeutronsCapturedEDepByNeutronAndChildrenInVetoMax.clear();
199 fNeutronsCapturedEDepByNeutronAndChildrenInVetoMin.clear();
201 fGammasNeutronCaptureNumber = 0;
202 fGammasNeutronCapturePosX.clear();
203 fGammasNeutronCapturePosY.clear();
204 fGammasNeutronCapturePosZ.clear();
205 fGammasNeutronCaptureIsCaptureVolume.clear();
206 fGammasNeutronCaptureProductionE.clear();
208 fSecondaryNeutronsShieldingNumber = 0;
209 fSecondaryNeutronsShieldingExitPosX.clear();
210 fSecondaryNeutronsShieldingExitPosY.clear();
211 fSecondaryNeutronsShieldingExitPosZ.clear();
212 fSecondaryNeutronsShieldingIsCaptured.clear();
213 fSecondaryNeutronsShieldingIsCapturedInCaptureVolume.clear();
214 fSecondaryNeutronsShieldingProductionE.clear();
215 fSecondaryNeutronsShieldingExitE.clear();
225 std::map<string, Double_t> volume_energy_map;
227 for (
unsigned int i = 0; i < fVetoVolumeIds.size(); i++) {
228 int id = fVetoVolumeIds[i];
229 string volume_name = (string)fG4Metadata->GetActiveVolumeName(
id);
231 Double_t energy = fOutputG4Event->GetEnergyInVolume(volume_name);
232 volume_energy_map[volume_name] = energy;
235 Double_t energy_veto_max = 0;
236 for (
const auto& pair : volume_energy_map) {
237 Double_t veto_energy = pair.second;
238 SetObservableValue(pair.first +
"VolumeEDep", veto_energy);
239 if (veto_energy > energy_veto_max) {
240 energy_veto_max = veto_energy;
243 SetObservableValue(
"vetoAllEVetoMax", energy_veto_max);
246 for (
const auto& pair : fVetoGroupVolumeNames) {
247 Double_t energy_veto_max_group = 0;
248 for (
unsigned int i = 0; i < pair.second.size(); i++) {
249 string volume_name = pair.second[i];
250 Double_t veto_energy = volume_energy_map[volume_name];
251 if (veto_energy > energy_veto_max_group) {
252 energy_veto_max_group = veto_energy;
257 for (
auto it = pair.first.cbegin(); it != pair.first.cend(); ++it) {
258 if (it == pair.first.cbegin()) {
259 group_name += std::toupper(*it);
261 group_name += std::tolower(*it);
264 SetObservableValue(
"vetoGroup" + group_name +
"EVetoMax", energy_veto_max_group);
269 for (
const auto& quenching_factor : fQuenchingFactors) {
270 string quenching_factor_string = std::to_string(quenching_factor);
272 quenching_factor_string =
273 quenching_factor_string.replace(quenching_factor_string.find(
"."),
sizeof(
".") - 1,
"_");
274 volume_energy_map.clear();
275 for (
unsigned int i = 0; i < fOutputG4Event->GetNumberOfTracks(); i++) {
276 const auto& track = fOutputG4Event->GetTrack(i);
277 string particle_name = (string)track.GetParticleName();
278 for (
const auto&
id : fVetoVolumeIds) {
279 string volume_name = (string)fG4Metadata->GetActiveVolumeName(
id);
281 if (particle_name ==
"e-" || particle_name ==
"e+" || particle_name ==
"gamma") {
283 volume_energy_map[volume_name] += track.GetEnergyInVolume(
id);
286 volume_energy_map[volume_name] += quenching_factor * track.GetEnergyInVolume(
id);
291 Double_t energy_veto_max = 0;
292 for (
const auto& pair : volume_energy_map) {
293 Double_t veto_energy = pair.second;
294 SetObservableValue(pair.first +
"VolumeEDep" +
"Qf" + quenching_factor_string, veto_energy);
295 if (veto_energy > energy_veto_max) {
296 energy_veto_max = veto_energy;
299 SetObservableValue(
string(
"vetoAllEVetoMax") +
"Qf" + quenching_factor_string, energy_veto_max);
302 for (
const auto& pair : fVetoGroupVolumeNames) {
303 Double_t energy_veto_max_group = 0;
304 for (
unsigned int i = 0; i < pair.second.size(); i++) {
305 string volume_name = pair.second[i];
306 Double_t veto_energy = volume_energy_map[volume_name];
307 if (veto_energy > energy_veto_max_group) {
308 energy_veto_max_group = veto_energy;
313 for (
auto it = pair.first.cbegin(); it != pair.first.cend(); ++it) {
314 if (it == pair.first.cbegin()) {
315 group_name += std::toupper(*it);
317 group_name += std::tolower(*it);
320 SetObservableValue(
"vetoGroup" + group_name +
"EVetoMax" +
"Qf" + quenching_factor_string,
321 energy_veto_max_group);
325 std::set<int> neutronsCaptured = {};
326 for (
unsigned int i = 0; i < fOutputG4Event->GetNumberOfTracks(); i++) {
327 auto track = fOutputG4Event->GetTrack(i);
328 string particle_name = (string)track.GetParticleName();
329 if (particle_name ==
"neutron") {
330 auto hits = track.GetHits();
331 for (
unsigned int j = 0; j < hits.GetNumberOfHits(); j++) {
332 string process_name = (string)track.GetProcessName(hits.GetProcess(j));
333 if (process_name ==
"nCapture") {
339 neutronsCaptured.insert(track.GetTrackID());
341 fNeutronsCapturedNumber += 1;
342 fNeutronsCapturedPosX.push_back(hits.GetX(j));
343 fNeutronsCapturedPosY.push_back(hits.GetY(j));
344 fNeutronsCapturedPosZ.push_back(hits.GetZ(j));
346 Int_t volumeId = hits.GetVolumeId(j);
347 Int_t isCaptureVolume = 0;
348 for (
const auto&
id : fCaptureVolumeIds) {
349 if (volumeId ==
id) {
354 fNeutronsCapturedIsCaptureVolume.push_back(isCaptureVolume);
355 fNeutronsCapturedProductionE.push_back(track.GetInitialKineticEnergy());
358 double neutronsCapturedEDepByNeutron = 0;
359 double neutronsCapturedEDepByNeutronAndChildren = 0;
360 double neutronsCapturedEDepByNeutronInVeto = 0;
361 double neutronsCapturedEDepByNeutronAndChildrenInVeto = 0;
363 std::set<int> parents = {track.GetTrackID()};
364 std::map<int, double> energyInVeto;
365 for (
unsigned int child = 0; child < fOutputG4Event->GetNumberOfTracks(); child++) {
366 const auto& trackChild = fOutputG4Event->GetTrack(child);
367 if ((parents.count(trackChild.GetParentID()) > 0) ||
368 parents.count(trackChild.GetTrackID()) > 0) {
370 parents.insert(trackChild.GetTrackID());
371 neutronsCapturedEDepByNeutronAndChildren += trackChild.GetTotalEnergy();
372 if (trackChild.GetTrackID() == track.GetTrackID()) {
373 neutronsCapturedEDepByNeutron += trackChild.GetTotalEnergy();
375 for (
const auto& vetoId : fVetoVolumeIds) {
376 neutronsCapturedEDepByNeutronAndChildrenInVeto +=
377 trackChild.GetEnergyInVolume(vetoId);
378 energyInVeto[vetoId] += trackChild.GetEnergyInVolume(vetoId);
379 if (trackChild.GetTrackID() == track.GetTrackID()) {
380 neutronsCapturedEDepByNeutronInVeto +=
381 trackChild.GetEnergyInVolume(vetoId);
387 fNeutronsCapturedEDepByNeutron.push_back(neutronsCapturedEDepByNeutron);
388 fNeutronsCapturedEDepByNeutronAndChildren.push_back(
389 neutronsCapturedEDepByNeutronAndChildren);
390 fNeutronsCapturedEDepByNeutronInVeto.push_back(neutronsCapturedEDepByNeutronInVeto);
391 fNeutronsCapturedEDepByNeutronAndChildrenInVeto.push_back(
392 neutronsCapturedEDepByNeutronAndChildrenInVeto);
395 double energyMaxVeto = 0;
396 double energyMinVeto = -1;
397 for (
const auto& pair : energyInVeto) {
398 auto E = pair.second;
399 if (E > energyMaxVeto) energyMaxVeto = E;
400 if (E < energyMaxVeto || energyMinVeto == -1) energyMinVeto = E;
403 fNeutronsCapturedEDepByNeutronAndChildrenInVetoMax.push_back(energyMaxVeto);
404 fNeutronsCapturedEDepByNeutronAndChildrenInVetoMin.push_back(energyMinVeto);
410 SetObservableValue(
"neutronsCapturedNumber", fNeutronsCapturedNumber);
411 SetObservableValue(
"neutronsCapturedPosX", fNeutronsCapturedPosX);
412 SetObservableValue(
"neutronsCapturedPosY", fNeutronsCapturedPosY);
413 SetObservableValue(
"neutronsCapturedPosZ", fNeutronsCapturedPosZ);
414 SetObservableValue(
"neutronsCapturedIsCaptureVolume", fNeutronsCapturedIsCaptureVolume);
415 SetObservableValue(
"neutronsCapturedProductionE", fNeutronsCapturedProductionE);
416 SetObservableValue(
"neutronsCapturedEDepByNeutron", fNeutronsCapturedEDepByNeutron);
417 SetObservableValue(
"neutronsCapturedEDepByNeutronAndChildren", fNeutronsCapturedEDepByNeutronAndChildren);
418 SetObservableValue(
"neutronsCapturedEDepByNeutronInVeto", fNeutronsCapturedEDepByNeutronInVeto);
419 SetObservableValue(
"neutronsCapturedEDepByNeutronAndChildrenInVeto",
420 fNeutronsCapturedEDepByNeutronAndChildrenInVeto);
421 SetObservableValue(
"neutronsCapturedEDepByNeutronAndChildrenInVetoMax",
422 fNeutronsCapturedEDepByNeutronAndChildrenInVetoMax);
423 SetObservableValue(
"neutronsCapturedEDepByNeutronAndChildrenInVetoMin",
424 fNeutronsCapturedEDepByNeutronAndChildrenInVetoMin);
425 for (
unsigned int i = 0; i < fOutputG4Event->GetNumberOfTracks(); i++) {
426 auto track = fOutputG4Event->GetTrack(i);
427 string particle_name = (string)track.GetParticleName();
428 if (particle_name ==
"gamma") {
430 Int_t parent = track.GetParentID();
431 if (neutronsCaptured.count(parent) > 0) {
432 const auto& hits = track.GetHits();
434 fGammasNeutronCaptureNumber += 1;
435 fGammasNeutronCapturePosX.push_back(hits.GetX(0));
436 fGammasNeutronCapturePosY.push_back(hits.GetY(0));
437 fGammasNeutronCapturePosZ.push_back(hits.GetZ(0));
439 Int_t volumeId = hits.GetVolumeId(0);
440 Int_t isCaptureVolume = 0;
441 for (
const auto&
id : fCaptureVolumeIds) {
442 if (volumeId ==
id) {
447 fGammasNeutronCaptureIsCaptureVolume.push_back(isCaptureVolume);
448 fGammasNeutronCaptureProductionE.push_back(track.GetInitialKineticEnergy());
457 SetObservableValue(
"gammasNeutronCaptureNumber", fGammasNeutronCaptureNumber);
458 SetObservableValue(
"gammasNeutronCapturePosX", fGammasNeutronCapturePosX);
459 SetObservableValue(
"gammasNeutronCapturePosY", fGammasNeutronCapturePosY);
460 SetObservableValue(
"gammasNeutronCapturePosZ", fGammasNeutronCapturePosZ);
461 SetObservableValue(
"gammasNeutronCaptureIsCaptureVolume", fGammasNeutronCaptureIsCaptureVolume);
462 SetObservableValue(
"gammasNeutronCaptureProductionE", fGammasNeutronCaptureProductionE);
464 std::set<int> secondaryNeutrons = {};
465 for (
unsigned int i = 0; i < fOutputG4Event->GetNumberOfTracks(); i++) {
466 auto track = fOutputG4Event->GetTrack(i);
467 string particle_name = (string)track.GetParticleName();
468 if (particle_name ==
"neutron" && track.GetParentID() != 0) {
470 auto hits = track.GetHits();
471 for (
unsigned int j = 0; j < hits.GetNumberOfHits(); j++) {
472 string process_name = (string)track.GetProcessName(hits.GetProcess(j));
473 if (process_name ==
"Transportation") {
474 for (
const auto&
id : fShieldingVolumeIds) {
475 if (hits.GetVolumeId(j) == id) {
477 if (secondaryNeutrons.count(track.GetTrackID()) == 0) {
479 secondaryNeutrons.insert(track.GetTrackID());
483 fSecondaryNeutronsShieldingNumber += 1;
484 fSecondaryNeutronsShieldingExitPosX.push_back(hits.GetX(j));
485 fSecondaryNeutronsShieldingExitPosY.push_back(hits.GetY(j));
486 fSecondaryNeutronsShieldingExitPosZ.push_back(hits.GetZ(j));
488 Int_t volumeId = hits.GetVolumeId(j);
489 Int_t isCaptureVolume = 0;
490 for (
const auto&
id : fCaptureVolumeIds) {
491 if (volumeId ==
id) {
496 Int_t isCaptured = 0;
497 if (neutronsCaptured.count(track.GetTrackID()) > 0) {
500 fSecondaryNeutronsShieldingIsCaptured.push_back(isCaptured);
502 fSecondaryNeutronsShieldingIsCapturedInCaptureVolume.push_back(
505 fSecondaryNeutronsShieldingIsCapturedInCaptureVolume.push_back(0);
508 fSecondaryNeutronsShieldingProductionE.push_back(track.GetInitialKineticEnergy());
509 fSecondaryNeutronsShieldingExitE.push_back(hits.GetKineticEnergy(j));
517 SetObservableValue(
"secondaryNeutronsShieldingNumber", fSecondaryNeutronsShieldingNumber);
518 SetObservableValue(
"secondaryNeutronsShieldingExitPosX", fSecondaryNeutronsShieldingExitPosX);
519 SetObservableValue(
"secondaryNeutronsShieldingExitPosY", fSecondaryNeutronsShieldingExitPosY);
520 SetObservableValue(
"secondaryNeutronsShieldingExitPosZ", fSecondaryNeutronsShieldingExitPosZ);
521 SetObservableValue(
"secondaryNeutronsShieldingIsCaptured", fSecondaryNeutronsShieldingIsCaptured);
522 SetObservableValue(
"secondaryNeutronsShieldingIsCapturedInCaptureVolume",
523 fSecondaryNeutronsShieldingIsCapturedInCaptureVolume);
524 SetObservableValue(
"secondaryNeutronsShieldingProductionE", fSecondaryNeutronsShieldingProductionE);
525 SetObservableValue(
"secondaryNeutronsShieldingExitE", fSecondaryNeutronsShieldingExitE);
527 return fOutputG4Event;
549 string veto_keyword = GetParameter(
"vetoKeyword",
"veto");
552 string veto_group_keywords = GetParameter(
"vetoGroupKeywords",
"");
553 stringstream ss(veto_group_keywords);
556 getline(ss, substr,
',');
562 string capture_keyword = GetParameter(
"captureKeyword",
"sheet");
567 string shielding_keyword = GetParameter(
"shieldingKeyword",
"shielding");
571 string quenching_factors = GetParameter(
"vetoQuenchingFactors",
"-1");
572 stringstream ss_qf(quenching_factors);
573 while (ss_qf.good()) {
575 getline(ss_qf, substr,
',');
577 Float_t quenching_factor = (Float_t)std::atof(substr.c_str());
578 if (quenching_factor > 1 || quenching_factor < 0) {
579 cout <<
"ERROR: quenching factor must be between 0 and 1" << endl;
582 fQuenchingFactors.push_back(quenching_factor);
A base class for any REST event.
An event class to store geant4 generated event information.
void InitProcess() override
Process initialization.
void Initialize() override
Function to initialize input/output event members and define the section name.
void LoadConfig(const std::string &configFilename, const std::string &name="")
Function to load the configuration from an external configuration file.
TRestEvent * ProcessEvent(TRestEvent *inputEvent) override
The main processing event function.
void InitFromConfigFile() override
Function to read input parameters from the RML TRestGeant4NeutronTaggingProcess metadata section.
void LoadDefaultConfig()
Function to load the default config in absence of RML input.
void EndProcess() override
Function to include required actions after all events have been processed.
~TRestGeant4NeutronTaggingProcess()
Default destructor.
std::string TrimAndLower(std::string s)
It trims and lowers the string.