BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
HistogramDefSet.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2022.
4
5This file is part of BDSIM.
6
7BDSIM is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published
9by the Free Software Foundation version 3 of the License.
10
11BDSIM is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
18*/
19#include "HistogramDef.hh"
20#include "HistogramDefSet.hh"
21#include "RBDSException.hh"
22#include "SpectraParticles.hh"
23
24#include <map>
25#include <regex>
26#include <set>
27#include <stdexcept>
28#include <string>
29
30HistogramDefSet::HistogramDefSet(const std::string& branchNameIn,
31 const HistogramDef* baseDefinitionIn,
32 const std::set<ParticleSpec>& particlesSpecs,
33 const std::string& particleSpecificationIn):
34 branchName(branchNameIn),
35 dynamicallyStoreIons(false),
36 dynamicallyStoreParticles(particlesSpecs.empty()),
37 what(writewhat::all),
38 topN(1)
39{
40 if (!baseDefinitionIn)
41 {throw std::invalid_argument("invalid histogram definition");}
42
43 baseDefinition = baseDefinitionIn->Clone();
44
45 if (!particlesSpecs.empty())
46 {
47 for (const auto& particleSpec : particlesSpecs)
48 {
49 HistogramDef* h = baseDefinitionIn->Clone();
50 h->histName = "Spectra_" + h->histName + "_" + std::to_string(particleSpec.first);
51 std::string suffix;
52 switch (particleSpec.second)
53 {
54 case RBDS::SpectraParticles::primary:
55 {suffix = "_Primary"; break;}
56 case RBDS::SpectraParticles::secondary:
57 {suffix = "_Secondary"; break;}
58 default:
59 {break;}
60 }
61 h->histName += suffix;
62 h->selection = AddPDGFilterToSelection(particleSpec, h->selection, branchName);
63 definitions[particleSpec] = h;
64 definitionsV.push_back(h);
65 }
66 }
67 else
68 {
69 std::string spec = particleSpecificationIn;
70 std::transform(spec.begin(), spec.end(), spec.begin(), ::tolower);
71 spec = RemoveSubString(spec, "{");
72 spec = RemoveSubString(spec, "}");
73
74 if (spec.find("all") != std::string::npos || spec.find("ions") != std::string::npos)
75 {dynamicallyStoreIons = true;}
76 if (spec.find("all") != std::string::npos || spec.find("particles") != std::string::npos)
77 {dynamicallyStoreParticles = true;}
78
79 std::map<std::string, writewhat> keys = {{"all", writewhat::all},
80 {"particles", writewhat::particles},
81 {"ions", writewhat::ions}};
82
83 auto search = keys.find(spec);
84 if (search != keys.end())
85 {what = search->second;}
86 else
87 {
88 std::regex topNR("top(\\d+)(?:particles|ions)*");
89 std::smatch match;
90 if (std::regex_search(spec, match, topNR))
91 {
92 try
93 {topN = std::stoi(match[1]);}
94 catch (...)
95 {topN = 1;}
96 if (spec.find("particles") != std::string::npos)
97 {what = writewhat::topNParticles;}
98 else if (spec.find("ions") != std::string::npos)
99 {what = writewhat::topNIons;}
100 else
101 {what = writewhat::topN;}
102 }
103 else // this will happen if 'top' isn't in the specification or it generally doesn't match
104 {throw RBDSException("Invalid particle specifier \"" + particleSpecificationIn + "\"");}
105 }
106 }
107}
108
109HistogramDefSet::~HistogramDefSet()
110{
111 delete baseDefinition;
112 for (auto kv : definitions)
113 {delete kv.second;}
114}
115
116std::string HistogramDefSet::RemoveSubString(const std::string& stringIn,
117 const std::string& wordToRemove) const
118{
119 std::string result = stringIn;
120 while (result.find(wordToRemove) != std::string::npos)
121 {
122 size_t pos = result.find(wordToRemove);
123 result.erase(pos, wordToRemove.size());
124 }
125 return result;
126}
127
128std::string HistogramDefSet::AddPDGFilterToSelection(const ParticleSpec& particleSpec,
129 const std::string& selection,
130 const std::string& branchName)
131{
132 long long int pdgID = particleSpec.first;
133 RBDS::SpectraParticles flag = particleSpec.second;
134 std::string flagFilter;
135 switch (flag)
136 {
137 case RBDS::SpectraParticles::primary:
138 {flagFilter = "&&" + branchName + ".parentID==0"; break;}
139 case RBDS::SpectraParticles::secondary:
140 {flagFilter = "&&" + branchName + ".parentID>0"; break;}
141 default:
142 {break;}
143 }
144 std::string filter = branchName+".partID=="+std::to_string(pdgID) + flagFilter;
145 // check if it has a boolean expression already in it
146 std::string result;
147 std::regex boolOperator("&&|[<>!=]=|[<>]|\\|\\|");
148 std::smatch match;
149 if (std::regex_search(selection, match, boolOperator))
150 {// has boolean operator somewhere in it
151 std::string afterBool = match.suffix();
152 std::size_t bracketPos = afterBool.find(")");
153 result = selection; // copy it
154 result.insert(match.position() + match.length() + bracketPos, "&&"+filter);
155 }
156 else if (selection.empty())
157 {result = filter;}
158 else
159 {result = selection + "*("+filter+")";}
160 return result;
161}
std::string RemoveSubString(const std::string &stringIn, const std::string &wordToRemove) const
Remove a substring from a string.
Common specification for a histogram.
Definition: HistogramDef.hh:33
virtual HistogramDef * Clone() const
Copy this instance. Virtual to be overridden in derived classes.
Definition: HistogramDef.hh:48
General exception with possible name of object and message.