BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
PerEntryHistogramSet.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) BDSIM Collaboration, 2001 - 2026.
3
4This file is part of BDSIM.
5
6BDSIM is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published
8by the Free Software Foundation version 3 of the License.
9
10BDSIM is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
17*/
18#include "Event.hh"
19#include "HistogramDef.hh"
20#include "HistogramDefSet.hh"
21#include "PerEntryHistogram.hh"
22#include "PerEntryHistogramSet.hh"
23#include "SpectraParticles.hh"
24
25#include "BDSOutputROOTEventSampler.hh"
26#include "RBDSException.hh"
27
28#include <algorithm>
29#include <iterator>
30#include <map>
31#include <set>
32#include <string>
33#include <vector>
34
35//ClassImp(PerEntryHistogramSet)
36
37PerEntryHistogramSet::PerEntryHistogramSet(const HistogramDefSet* definitionIn,
38 Event* eventIn,
39 TChain* chainIn):
40 baseDefinition(definitionIn->baseDefinition),
41 event(eventIn),
42 chain(chainIn),
43 branchName(definitionIn->branchName),
44 dynamicallyStoreParticles(definitionIn->dynamicallyStoreParticles),
45 dynamicallyStoreIons(definitionIn->dynamicallyStoreIons),
46 nEntries(0),
47 what(definitionIn->what),
48 topN(definitionIn->topN),
49 sampler(nullptr)
50{
51 for (const auto& pSpecDef : definitionIn->definitions)
52 {
53 auto pSpec = pSpecDef.first;
54 auto def = pSpecDef.second;
55 PerEntryHistogram* hist = new PerEntryHistogram(def, chainIn);
56 histograms[pSpec] = hist;
57 histogramsByPDGID[pSpec.first] = hist;
58 allPerEntryHistograms.push_back(hist); // keep vector for quick iteration each Accumulate() call
59 if (pSpec.second == RBDS::SpectraParticles::all)
60 {
61 if (IsIon(pSpec.first))
62 {ions.insert(pSpec.first);}
63 else
64 {nonIons.insert(pSpec.first);}
65 }
66 }
67}
68
69void PerEntryHistogramSet::CreatePerEntryHistogram(long long int pdgID)
70{
71 allPDGIDs.insert(pdgID);
72 if (IsIon(pdgID))
73 {ions.insert(pdgID);}
74 else
75 {nonIons.insert(pdgID);}
76 // copy base definition
77 HistogramDef* def = baseDefinition->Clone();
78 def->histName = "Top" + std::to_string(topN) + "_Spectra_" + def->histName + "_" + std::to_string(pdgID);
79 def->selection = HistogramDefSet::AddPDGFilterToSelection(ParticleSpec(pdgID,RBDS::SpectraParticles::all),
80 def->selection,
81 branchName);
82
83 PerEntryHistogram* hist = new PerEntryHistogram(def, chain);
84 hist->AddNEmptyEntries(nEntries); // update to current number of events
85 histograms[ParticleSpec(pdgID, RBDS::SpectraParticles::all)] = hist;
86 histogramsByPDGID[pdgID] = hist;
87 allPerEntryHistograms.push_back(hist);
88}
89
90PerEntryHistogramSet::~PerEntryHistogramSet()
91{
92 delete baseDefinition;
93 for (auto kv : allPerEntryHistograms)
94 {delete kv;}
95}
96
98{
100
101 if (dynamicallyStoreParticles || dynamicallyStoreIons)
102 {
103 // for this event, form a set of pdgIDs and
104 // then ensure we have all prepare histograms
105 std::set<long long int> pdgIDSet;
106 GetPDGIDSetFromSampler(pdgIDSet);
107
108 // use vector because set cannot be appended to for set_difference
109 std::vector<long long int> missing;
110 std::set_difference(pdgIDSet.begin(), pdgIDSet.end(),
111 allPDGIDs.begin(), allPDGIDs.end(),
112 std::back_inserter(missing));
113 if (!missing.empty())
114 {
115 for (auto pdgID : missing)
116 {
117 bool isIon = IsIon(pdgID);
118 if ((isIon && dynamicallyStoreIons) || (!isIon && dynamicallyStoreParticles))
119 {CreatePerEntryHistogram(pdgID);}
120 }
121 }
122 }
123 nEntries += 1;
124 for (auto hist : allPerEntryHistograms)
125 {hist->AccumulateCurrentEntry(entryNumber);}
126}
127
129{
130 for (auto hist : allPerEntryHistograms)
131 {hist->Terminate();}
132}
133
134void PerEntryHistogramSet::Write(TDirectory* dir)
135{
136 if (what == HistogramDefSet::writewhat::all)
137 {
138 for (auto hist : allPerEntryHistograms)
139 {hist->Write(dir);}
140 }
141 else
142 {
143 // form a (sorted) vector of desired pdgIDs
144 std::vector<long long int> desiredPDGIDs;
145 switch (what)
146 {
147 case HistogramDefSet::writewhat::all:
148 {std::copy(allPDGIDs.begin(), allPDGIDs.end(), std::back_inserter(desiredPDGIDs)); break;}
149 case HistogramDefSet::writewhat::topN:
150 {desiredPDGIDs = TopN(topN); break;}
151 case HistogramDefSet::writewhat::ions:
152 {std::copy(ions.begin(), ions.end(), std::back_inserter(desiredPDGIDs)); break;}
153 case HistogramDefSet::writewhat::topNIons:
154 {desiredPDGIDs = TopNIons(topN); break;}
155 case HistogramDefSet::writewhat::particles:
156 {std::copy(nonIons.begin(), nonIons.end(), std::back_inserter(desiredPDGIDs)); break;}
157 case HistogramDefSet::writewhat::topNParticles:
158 {desiredPDGIDs = TopNNonIons(topN); break;}
159 }
160
161 for (auto pdgID : desiredPDGIDs)
162 {histogramsByPDGID.at(pdgID)->Write(dir);}
163 }
164}
165
166std::vector<long long int> PerEntryHistogramSet::TopUtility(const std::set<long long int>& s,
167 size_t n) const
168{
169 // map the pdg id to the total number (inc weight) of that particle histogrammed (per event)
170 std::map<long long int, double> integrals;
171 for (auto id : s)
172 {integrals[id] = histogramsByPDGID.at(id)->Integral();}
173
174 // reverse the mapping so the pdg ids are sorted by the integral, whilst tolerating
175 // multiple integrals of the same value (ie same rate)
176 std::multimap<double, long long int> sorted = BDS::flip_map(integrals);
177
178 // take advantage of a multimap being (by definition) ordered - therefore, the integrals
179 // are ordered low to high, so reverse iterate to get in decreasing order.
180 std::vector<long long int> topResult;
181 int i = 0;
182 int nInt = (int)n;
183 // reverse iterate up to the end of the result or n, whichever is smaller
184 for (auto it = sorted.rbegin(); it != sorted.rend() && i < nInt; it++, i++)
185 {topResult.push_back(it->second);}
186 return topResult;
187}
188
189std::vector<long long int> PerEntryHistogramSet::TopNNonIons(int n) const
190{
191 return TopUtility(nonIons, (size_t)n);
192}
193
194std::vector<long long int> PerEntryHistogramSet::TopNIons(int n) const
195{
196 return TopUtility(ions, (size_t)n);
197}
198
199std::vector<long long int> PerEntryHistogramSet::TopN(int n) const
200{
201 return TopUtility(allPDGIDs, (size_t)n);
202}
Event loader.
Definition Event.hh:49
Specification for a set of histograms.
Common specification for a histogram.
virtual HistogramDef * Clone() const =0
Copy this instance. Virtual to be overridden in derived classes.
virtual void Write(TDirectory *dir=nullptr)
virtual void AccumulateCurrentEntry(long int entryNumber)
std::vector< long long int > TopN(int n) const
Get top part of set. Sorted in descending order of integral.
std::vector< long long int > TopNIons(int n) const
Get top part of set. Sorted in descending order of integral.
virtual void GetPDGIDSetFromSampler(std::set< long long int > &setIn) const =0
virtual void CheckSampler()=0
virtual void Terminate()
Terminate the accumulator and save the result to the result member variable.
std::vector< long long int > TopNNonIons(int n) const
Get top part of set. Sorted in descending order of integral.
std::vector< long long int > TopUtility(const std::set< long long int > &s, size_t n) const
Utility function to find top N in set s. Sorted in descending order of integral.
Holder for information to calculate per entry histograms.
virtual void Terminate()
Terminate the accumulator and save the result to the result member variable.
PerEntryHistogram()
Public constructor only for compatibility with ROOT - not intended for use.
virtual void Write(TDirectory *dir=nullptr)
virtual void AccumulateCurrentEntry(long int entryNumber)
void AddNEmptyEntries(unsigned long i)
G4bool IsIon(const G4ParticleDefinition *particle)
Whether a particle is an ion. A proton is counted NOT as an ion.