66#include "TRestGeant4VetoAnalysisProcess.h"
69#include <TObjString.h>
73#include <unordered_map>
79int findMostFrequent(
const vector<int>& nums) {
84 unordered_map<int, int> freqMap;
87 for (
int num : nums) {
91 int mostFrequent = nums[0];
95 for (
const auto& entry : freqMap) {
96 if (entry.second > maxFrequency) {
97 mostFrequent = entry.first;
98 maxFrequency = entry.second;
105Veto TRestGeant4VetoAnalysisProcess::GetVetoFromString(
const string& input) {
112 TObjArray* parts = TString(input).Tokenize(
"_");
114 if (parts->GetEntries() >= 5) {
115 TString group = ((TObjString*)parts->At(1))->GetString();
117 if (group.Index(
"vetoSystem") == 0) {
118 group = group(10, group.Length() - 10);
121 TString layer = ((TObjString*)parts->At(2))->GetString();
123 layer = layer(layer.Length() - 1, 1);
125 TString numberAndRest = ((TObjString*)parts->At(parts->GetEntries() - 2))->GetString();
126 Ssiz_t vetoPos = numberAndRest.Index(
"veto");
127 if (vetoPos != kNPOS) {
128 TString number = numberAndRest(vetoPos + 4, numberAndRest.Length() - vetoPos - 4);
130 TString lengthAndRest = ((TObjString*)parts->At(parts->GetEntries() - 1))->GetString();
131 Ssiz_t mmPos = lengthAndRest.Index(
"mm");
132 if (mmPos != kNPOS) {
133 TString length = lengthAndRest(0, mmPos);
135 if (length.Index(
"scintillatorVolume") == 0) {
136 length = length(19, length.Length() - 19);
139 veto.group = group.Data();
140 veto.layer = layer.Atoi();
141 veto.number = number.Atoi();
142 veto.length = length.Atof();
145 cout <<
"No match found." << endl;
148 cout <<
"No match found." << endl;
151 cout <<
"No match found." << endl;
156 veto.alias = veto.group +
"_L" + veto.layer +
"_N" + veto.number;
160TRestGeant4VetoAnalysisProcess::TRestGeant4VetoAnalysisProcess() {
Initialize(); }
162TRestGeant4VetoAnalysisProcess::TRestGeant4VetoAnalysisProcess(
const char* configFilename) {
169TRestGeant4VetoAnalysisProcess::~TRestGeant4VetoAnalysisProcess() {
delete fOutputEvent; }
210 fVetoVolumes.clear();
212 if (fGeant4Metadata ==
nullptr) {
214 fGeant4Metadata = GetMetadata<TRestGeant4Metadata>();
216 if (fGeant4Metadata ==
nullptr) {
217 cerr <<
"TRestGeant4VetoAnalysisProcess::InitProcess: Geant4 metadata not found" << endl;
221 RESTDebug <<
"Expression: " << fVetoVolumesExpression <<
RESTendl;
224 auto vetoVolumes = geometryInfo.GetAllPhysicalVolumesMatchingExpression(fVetoVolumesExpression);
225 if (vetoVolumes.empty()) {
226 const auto logicalVolumes =
227 geometryInfo.GetAllLogicalVolumesMatchingExpression(fVetoVolumesExpression);
228 for (
const auto& logicalVolume : logicalVolumes) {
229 for (
const auto& physicalVolume : geometryInfo.GetAllPhysicalVolumesFromLogical(logicalVolume)) {
231 geometryInfo.GetAlternativeNameFromGeant4PhysicalName(physicalVolume).Data();
232 Veto veto = GetVetoFromString(name);
233 veto.position = geometryInfo.GetPosition(name);
234 fVetoVolumes.push_back(veto);
249 map<string, double> vetoEnergyMap;
250 map<string, double> vetoGroupEnergyMap;
251 map<pair<string, int>,
double> vetoGroupLayerEnergyMap;
252 double totalVetoEnergy = 0;
254 for (
const auto& veto : fVetoVolumes) {
255 const double energy = fInputEvent->GetEnergyInVolume(veto.name);
257 totalVetoEnergy += energy;
258 vetoEnergyMap[veto.name] = energy;
259 vetoGroupEnergyMap[veto.group] += energy;
260 vetoGroupLayerEnergyMap[make_pair(veto.group, veto.layer)] += energy;
265 for (
const auto& [group, energy] : vetoGroupEnergyMap) {
269 for (
const auto& [groupLayer, energy] : vetoGroupLayerEnergyMap) {
270 SetObservableValue(
"EnergyGroupLayer_" + groupLayer.first +
"_" + to_string(groupLayer.second),
277 double maxEnergy = 0;
278 for (
const auto& [name, energy] : vetoEnergyMap) {
279 if (energy > maxEnergy) {
286 map<string, double> vetoGroupMaxEnergyMap;
287 for (
const auto& [name, energy] : vetoEnergyMap) {
288 const auto veto = GetVetoFromString(name);
289 if (vetoGroupMaxEnergyMap[veto.group] < energy) {
290 vetoGroupMaxEnergyMap[veto.group] = energy;
293 for (
const auto& [group, energy] : vetoGroupMaxEnergyMap) {
298 map<pair<string, int>,
double> vetoGroupLayerMaxEnergyMap;
299 for (
const auto& [name, energy] : vetoEnergyMap) {
300 const auto veto = GetVetoFromString(name);
301 if (vetoGroupLayerMaxEnergyMap[make_pair(veto.group, veto.layer)] < energy) {
302 vetoGroupLayerMaxEnergyMap[make_pair(veto.group, veto.layer)] = energy;
306 for (
const auto& [groupLayer, energy] : vetoGroupLayerMaxEnergyMap) {
307 SetObservableValue(
"EnergyGroupLayerMax_" + groupLayer.first +
"_" + to_string(groupLayer.second),
312 map<int, double> vetoLayerMaxEnergyMap;
313 for (
const auto& [name, energy] : vetoEnergyMap) {
314 const auto veto = GetVetoFromString(name);
315 if (vetoLayerMaxEnergyMap[veto.layer] < energy) {
316 vetoLayerMaxEnergyMap[veto.layer] = energy;
319 for (
const auto& [layer, energy] : vetoLayerMaxEnergyMap) {
325 int nCapturesInCaptureVolumes = 0;
326 int nCapturesInVetoVolumes = 0;
328 vector<float> nCapturesInCaptureVolumesTimes;
329 vector<vector<float>> nCapturesInCaptureVolumesChildGammaEnergies;
331 vector<float> nCapturesInCaptureVolumesChildGammasEnergyInVetos;
332 vector<vector<float>> nCapturesInCaptureVolumesEnergyInVetoesForCapture;
334 set<int> nCapturesInCaptureVolumesNeutronTrackIds;
336 vector<float> nCapturesInCaptureVolumesPositionX;
337 vector<float> nCapturesInCaptureVolumesPositionY;
338 vector<float> nCapturesInCaptureVolumesPositionZ;
340 for (
const auto& track : fInputEvent->GetTracks()) {
341 if (track.GetParticleName() ==
"neutron") {
342 const auto hits = track.GetHits();
343 for (
size_t hitIndex = 0; hitIndex < hits.GetNumberOfHits(); hitIndex++) {
344 const auto processName = hits.GetProcessName(hitIndex);
345 if (processName !=
"nCapture") {
349 const string volumeName = hits.GetVolumeName(hitIndex).Data();
350 const double time = hits.GetTime(hitIndex);
352 if (volumeName.find(
"captureLayerVolume") != string::npos) {
353 nCapturesInCaptureVolumes++;
354 nCapturesInCaptureVolumesNeutronTrackIds.insert(track.GetTrackID());
355 nCapturesInCaptureVolumesTimes.push_back(time);
356 const TVector3& position = hits.GetPosition(hitIndex);
357 nCapturesInCaptureVolumesPositionX.push_back(position.X());
358 nCapturesInCaptureVolumesPositionY.push_back(position.Y());
359 nCapturesInCaptureVolumesPositionZ.push_back(position.Z());
360 vector<float> childrenEnergy;
361 const auto children = track.GetChildrenTracks();
362 for (
const auto& child : children) {
363 if (child->GetParticleName() !=
"gamma") {
366 if (child->GetCreatorProcess() !=
"nCapture") {
369 childrenEnergy.push_back(child->GetInitialKineticEnergy());
370 double energyInVeto = 0;
371 for (
const auto& veto : fVetoVolumes) {
372 energyInVeto += child->GetEnergyInVolume(veto.name,
true);
374 nCapturesInCaptureVolumesChildGammasEnergyInVetos.push_back(energyInVeto);
376 nCapturesInCaptureVolumesChildGammaEnergies.push_back(childrenEnergy);
378 vector<float> energyInVetoesForCapture;
379 for (
const auto& veto : fVetoVolumes) {
380 const double energyInVeto = track.GetEnergyInVolume(veto.name,
true);
381 if (energyInVeto > 0) {
382 energyInVetoesForCapture.push_back(energyInVeto);
385 nCapturesInCaptureVolumesEnergyInVetoesForCapture.push_back(energyInVetoesForCapture);
387 if (volumeName.find(
"scintillatorVolume") != string::npos) {
388 nCapturesInVetoVolumes++;
394 SetObservableValue(
"nCapturesInCaptureVolumesPositionX", nCapturesInCaptureVolumesPositionX);
395 SetObservableValue(
"nCapturesInCaptureVolumesPositionY", nCapturesInCaptureVolumesPositionY);
396 SetObservableValue(
"nCapturesInCaptureVolumesPositionZ", nCapturesInCaptureVolumesPositionZ);
398 vector<float> nCapturesInCaptureVolumesPositionOriginX;
399 vector<float> nCapturesInCaptureVolumesPositionOriginY;
400 vector<float> nCapturesInCaptureVolumesPositionOriginZ;
403 vector<double> nCapturesInCaptureVolumesNeutronInitialEnergy;
404 vector<int> nCapturesInCaptureVolumesNeutronGeneration;
406 for (
const auto& neutronCaptureTrackId : nCapturesInCaptureVolumesNeutronTrackIds) {
407 auto track = fInputEvent->GetTrackByID(neutronCaptureTrackId);
408 if (track->GetParticleName() !=
"neutron") {
409 cerr <<
"TRestGeant4VetoAnalysisProcess::ProcessEvent: track is not a neutron" << endl;
414 double energy = track->GetInitialKineticEnergy();
416 while (track->GetParentTrack() !=
nullptr) {
417 track = track->GetParentTrack();
418 if (track->GetParticleName() ==
"neutron") {
423 const TVector3& origin = track->GetTrackOrigin();
424 nCapturesInCaptureVolumesPositionOriginX.push_back(origin.X());
425 nCapturesInCaptureVolumesPositionOriginY.push_back(origin.Y());
426 nCapturesInCaptureVolumesPositionOriginZ.push_back(origin.Z());
428 nCapturesInCaptureVolumesNeutronInitialEnergy.push_back(energy);
429 nCapturesInCaptureVolumesNeutronGeneration.push_back(generation);
432 SetObservableValue(
"nCapturesInCaptureVolumesPositionOriginX", nCapturesInCaptureVolumesPositionOriginX);
433 SetObservableValue(
"nCapturesInCaptureVolumesPositionOriginY", nCapturesInCaptureVolumesPositionOriginY);
434 SetObservableValue(
"nCapturesInCaptureVolumesPositionOriginZ", nCapturesInCaptureVolumesPositionOriginZ);
437 nCapturesInCaptureVolumesNeutronInitialEnergy);
439 nCapturesInCaptureVolumesNeutronGeneration);
449 vector<float> nCapturesInCaptureVolumesChildGammaEnergiesFlat;
450 vector<int> nCapturesInCaptureVolumesChildGammaCount;
451 for (
const auto& v : nCapturesInCaptureVolumesChildGammaEnergies) {
452 nCapturesInCaptureVolumesChildGammaEnergiesFlat.insert(
453 nCapturesInCaptureVolumesChildGammaEnergiesFlat.end(), v.begin(), v.end());
454 nCapturesInCaptureVolumesChildGammaCount.push_back(v.size());
457 float nCapturesInCaptureVolumesChildGammaCountAverage = 0;
458 for (
const auto& v : nCapturesInCaptureVolumesChildGammaCount) {
459 nCapturesInCaptureVolumesChildGammaCountAverage +=
460 float(v) / nCapturesInCaptureVolumesChildGammaCount.size();
464 nCapturesInCaptureVolumesChildGammaEnergiesFlat);
465 SetObservableValue(
"nCapturesInCaptureVolumesChildGammaCount", nCapturesInCaptureVolumesChildGammaCount);
467 nCapturesInCaptureVolumesChildGammaCountAverage);
469 findMostFrequent(nCapturesInCaptureVolumesChildGammaCount));
471 nCapturesInCaptureVolumesChildGammaEnergiesFlat.size());
474 nCapturesInCaptureVolumesChildGammasEnergyInVetos);
476 auto nCapturesInCaptureVolumesChildGammasEnergyInVetosTotal = 0;
477 for (
const auto& energy : nCapturesInCaptureVolumesChildGammasEnergyInVetos) {
478 nCapturesInCaptureVolumesChildGammasEnergyInVetosTotal += energy;
482 nCapturesInCaptureVolumesChildGammasEnergyInVetosTotal);
485 nCapturesInCaptureVolumesEnergyInVetoesForCapture);
487 const vector<float> energyInVetoesThresholds = {0, 100, 250, 500, 1000, 1500};
488 for (
const auto& threshold : energyInVetoesThresholds) {
489 vector<vector<int>> nCapturesInCaptureVolumesEnergyInVetoesForCaptureThreshold;
490 for (
const auto& captureForNeutronEnergies : nCapturesInCaptureVolumesEnergyInVetoesForCapture) {
491 int nCapturesInCaptureVolumesVetoesAboveThresholdForCapture = 0;
492 for (
const auto& energy : captureForNeutronEnergies) {
493 if (energy > threshold) {
494 nCapturesInCaptureVolumesVetoesAboveThresholdForCapture++;
497 nCapturesInCaptureVolumesEnergyInVetoesForCaptureThreshold.push_back(
498 {nCapturesInCaptureVolumesVetoesAboveThresholdForCapture});
501 "nCapturesInCaptureVolumesVetoesAboveThresholdForCapture" + to_string(
int(threshold)) +
"keV",
502 nCapturesInCaptureVolumesEnergyInVetoesForCaptureThreshold);
525 fVetoVolumesExpression =
GetParameter(
"vetoVolumesExpression", fVetoVolumesExpression);
531 cout <<
"Number of veto volumes: " << fVetoVolumes.size() << endl;
532 for (
const auto& veto : fVetoVolumes) {
533 cout <<
"Veto: " << veto.name << endl;
534 cout <<
" - Alias: " << veto.alias << endl;
535 cout <<
" - Group: " << veto.group << endl;
536 cout <<
" - Layer: " << veto.layer << endl;
537 cout <<
" - Number: " << veto.number << endl;
538 cout <<
" - Position: (" << veto.position.x() <<
", " << veto.position.y() <<
", "
539 << veto.position.z() <<
")" << endl;
540 cout <<
" - Length: " << veto.length << endl;
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.
An event class to store geant4 generated event information.
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 PrintMetadata() override
Implemented it in the derived metadata class to print out specific metadata information.
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.
void InitFromConfigFile() override
Function to read input parameters from the RML TRestGeant4VetoAnalysisProcess metadata section.
void Initialize() override
Function to initialize input/output event members and define the section name.
void InitProcess() override
Process initialization.