BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSOutputROOTEventSampler.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2024.
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 "BDSOutputROOTEventSampler.hh"
20#include "BDSOutputROOTParticleData.hh"
21
22#include "TTree.h"
23
25
26#ifndef __ROOTBUILD__
27#include "BDSHitSampler.hh"
28#include "BDSParticleCoordsFull.hh"
29#include "BDSPhysicalConstants.hh"
30#include "BDSPrimaryVertexInformationV.hh"
31
32#include "globals.hh"
33#include "CLHEP/Units/SystemOfUnits.h"
34#include <cmath>
35#endif
36
37templateClassImp(BDSOutputROOTEventSampler)
38
39template <class U>
41 samplerName("sampler")
42{
43 FlushLocal();
44}
45
46template <class U>
48 samplerName(samplerNameIn)
49{
50 FlushLocal();
51}
52
53template
55{;}
56
57#ifndef __ROOTBUILD__
58template <class U>
60 G4bool storeMass,
61 G4bool storeCharge,
62 G4bool storePolarCoords,
63 G4bool storeElectrons,
64 G4bool storeRigidity,
65 G4bool storeKineticEnergy)
66{
67 // get single values
68 n++;
69 z = (U) (hit->coords.z / CLHEP::m);
70 S = (U) (hit->coords.s / CLHEP::m);
71
72 energy.push_back((U) (hit->coords.totalEnergy / CLHEP::GeV));
73 x.push_back((U) (hit->coords.x / CLHEP::m));
74 y.push_back((U) (hit->coords.y / CLHEP::m));
75
76 xp.push_back((U) (hit->coords.xp));
77 yp.push_back((U) (hit->coords.yp));
78 zp.push_back((U) (hit->coords.zp));
79 p.push_back((U) (hit->momentum / CLHEP::GeV));
80 T.push_back((U) (hit->coords.T / CLHEP::ns));
81
82 modelID = hit->beamlineIndex;
83
84 weight.push_back((U) (hit->coords.weight));
85 partID.push_back(hit->pdgID);
86 parentID.push_back(hit->parentID);
87 trackID.push_back(hit->trackID);
88 turnNumber.push_back(hit->turnsTaken);
90 if (storeMass)
91 {mass.push_back((U)(hit->mass / CLHEP::GeV));}
93 if (storeCharge)
94 {charge.push_back((int)(hit->charge / (G4double)CLHEP::eplus));}
95
96 if (storeKineticEnergy)
97 {kineticEnergy.push_back((U)(hit->coords.totalEnergy - hit->mass) / CLHEP::GeV);}
98
99 if (storeRigidity)
100 {rigidity.push_back((U)hit->rigidity/(CLHEP::tesla*CLHEP::m));}
101
102 if (storePolarCoords)
103 {FillPolarCoords(hit->coords);}
104
105 if (storeElectrons)
106 {nElectrons.push_back((int)hit->nElectrons);}
107}
108
109template <class U>
111 G4double momentumIn,
112 G4double chargeIn,
113 G4int pdgID,
114 G4int turnsTaken,
115 G4int beamlineIndex,
116 G4int nElectronsIn,
117 G4double massIn,
118 G4double rigidityIn,
119 G4bool fillIon,
120 G4bool* isIonIn,
121 G4int* ionAIn,
122 G4int* ionZIn)
124 trackID.push_back(n); // we assume multiple primaries are linearly increasing in track number
125 n++;
126 energy.push_back((U) (coords.totalEnergy / CLHEP::GeV));
127 x.push_back((U) (coords.x / CLHEP::m));
128 y.push_back((U) (coords.y / CLHEP::m));
129 z = (U) (coords.z / CLHEP::m);
130 xp.push_back((U) (coords.xp));
131 yp.push_back((U) (coords.yp));
132 zp.push_back((U) (coords.zp));
133 p.push_back((U) (momentumIn / CLHEP::GeV));
134 T.push_back((U) (coords.T / CLHEP::ns));
135 weight.push_back((U) coords.weight);
136 partID.push_back(pdgID);
137 parentID.push_back(0);
138 modelID = beamlineIndex;
139 turnNumber.push_back(turnsTaken);
140 S = (U) (coords.s / CLHEP::GeV);
141
142 // always store optional bits for primary
143 charge.push_back((int)(chargeIn / (G4double)CLHEP::eplus));
144 mass.push_back((U)(massIn / CLHEP::GeV));
145 rigidity.push_back((U)rigidityIn /(CLHEP::tesla*CLHEP::m));
146 nElectrons.push_back((int)nElectronsIn);
147 kineticEnergy.push_back((U)(coords.totalEnergy - massIn) / CLHEP::GeV);
148 FillPolarCoords(coords);
149 if (isIonIn && ionAIn && ionZIn)
150 {
151 isIon.push_back((int) *isIonIn);
152 ionA.push_back((int) *ionAIn);
153 ionZ.push_back((int) *ionZIn);
154 }
155 else if (fillIon)
156 {FillIon();}
157}
158
159template <class U>
161{
162 double xCoord = coords.x / CLHEP::m;
163 double yCoord = coords.y / CLHEP::m;
164 double xpCoord = coords.xp;
165 double ypCoord = coords.yp;
166 double zpCoord = coords.zp;
167
168 // nans or infinite numbers can be set to -1
169 auto isntSafe = [](double a){return std::isnan(a) || std::isinf(a);};
170
171 double rValue = std::hypot(xCoord, yCoord);
172 if (isntSafe(rValue))
173 {rValue = 0;}
174 r.push_back(static_cast<U>(rValue));
175
176 double rpValue = std::hypot(xpCoord, ypCoord);
177 if (isntSafe(rpValue))
178 {rpValue = 0;}
179 rp.push_back(static_cast<U>(rpValue));
180
181 double thetapValue = std::atan2(rpValue, zpCoord);
182 if (isntSafe(thetapValue))
183 {thetapValue = -1;}
184 theta.push_back(static_cast<U>(thetapValue));
185
186 double phiValue = std::atan2(xCoord, yCoord);
187 if (isntSafe(phiValue))
188 {phiValue = -1;}
189 phi.push_back(static_cast<U>(phiValue));
190
191 double phipValue = std::atan2(xpCoord, ypCoord);
192 if (isntSafe(phipValue))
193 {phipValue = -1;}
194 phip.push_back(static_cast<U>(phipValue));
195}
196
197template <class U>
199 const G4int turnsTaken)
200{
201 for (const auto& vertexInfo : vertexInfos->vertices)
202 {
203 Fill(vertexInfo.primaryVertex.local,
204 vertexInfo.momentum,
205 vertexInfo.charge,
206 vertexInfo.pdgID,
207 turnsTaken,
208 vertexInfo.primaryVertex.beamlineIndex,
209 vertexInfo.nElectrons,
210 vertexInfo.mass,
211 vertexInfo.rigidity,
212 false);
213 }
214 FillIon();
215}
216#endif
217
218template <class U>
220{
221 if (!other)
222 {return;}
223 n = other->n;
224 energy = other->energy;
225 x = other->x;
226 y = other->y;
227 z = other->z;
228 xp = other->xp;
229 yp = other->yp;
230 zp = other->zp;
231 p = other->p;
232 T = other->T;
233
234 weight = other->weight;
235 partID = other->partID;
236 parentID = other->parentID;
237 trackID = other->trackID;
238 modelID = other->modelID;
239 turnNumber = other->turnNumber;
240 S = other->S;
241
242 r = other->r;
243 rp = other->rp;
244 phi = other->phi;
245 phip = other->phip;
246 theta = other->theta;
247
248 charge = other->charge;
249 kineticEnergy = other->kineticEnergy;
250 mass = other->mass;
251 rigidity = other->rigidity;
252
253 isIon = other->isIon;
254 ionA = other->ionA;
255 ionZ = other->ionZ;
256 nElectrons = other->nElectrons;
257}
258
259template <class U> void BDSOutputROOTEventSampler<U>::SetBranchAddress(TTree *)
260{;}
261
262template <class U> void BDSOutputROOTEventSampler<U>::Flush()
263{FlushLocal();}
264
266{
267 n = 0;
268 energy.clear();
269 x.clear();
270 y.clear();
271 z = 0.0;
272 xp.clear();
273 yp.clear();
274 zp.clear();
275 p.clear();
276 T.clear();
277 weight.clear();
278 partID.clear();
279 parentID.clear();
280 trackID.clear();
281 modelID = -1;
282 turnNumber.clear();
283
284 S = 0.0;
285
286 r.clear();
287 rp.clear();
288 phi.clear();
289 phip.clear();
290 theta.clear();
291
292 charge.clear();
293 kineticEnergy.clear();
294 mass.clear();
295 rigidity.clear();
296 isIon.clear();
297 ionA.clear();
298 ionZ.clear();
299 nElectrons.clear();
300}
301
302template <class U>
304{
305 std::vector<U> result((unsigned long)n);
306 if (!particleTable)
307 {return result;}
308 for (int i = 0; i < n; ++i)
309 {result[i] = (U)particleTable->KineticEnergy(partID[i], energy[i]);}
310 return result;
311}
312
313template <class U>
315{
316 std::vector<U> result((unsigned long)n);
317 if (!particleTable)
318 {return result;}
319 for (int i = 0; i < n; ++i)
320 {result[i] = (U)particleTable->Mass(partID[i]);}
321 return result;
322}
323
324template <class U>
326{
327 std::vector<U> result((unsigned long)n);
328 if (!particleTable)
329 {return result;}
330 for (int i = 0; i < n; ++i)
331 {result[i] = (U)particleTable->Rigidity(partID[i], energy[i]);}
332 return result;
333}
334
335template <class U>
337{
338 bool useNElectrons = !nElectrons.empty();
339 std::vector<bool> result((unsigned long)n);
340 if (!particleTable)
341 {return result;}
342 for (int i = 0; i < n; ++i)
343 {
344 result[i] = particleTable->IsIon(partID[i]);
345 if (useNElectrons)
346 {result[i] = result[i] || nElectrons[i] > 0;}
347 }
348 return result;
349}
350
351template <class U>
353{
354 std::vector<int> result((unsigned long)n);
355 if (!particleTable)
356 {return result;}
357 for (int i = 0; i < n; ++i)
358 {result[i] = (int)particleTable->IonA(partID[i]);}
359 return result;
360}
361
362template <class U>
364{
365 std::vector<int> result((unsigned long)n);
366 if (!particleTable)
367 {return result;}
368 for (int i = 0; i < n; ++i)
369 {result[i] = (int)particleTable->IonZ(partID[i]);}
370 return result;
371}
372
The information recorded from a particle impacting a sampler.
G4int nElectrons
Can only get this at inspection time so include here.
G4double charge
Double as g4 uses charge as a double.
Information stored per sampler per event.
std::vector< int > getIonA()
Function to calculate on the fly the parameters.
std::vector< bool > isIon
These are not filled by default.
std::vector< int > getIonZ()
Function to calculate on the fly the parameters.
std::vector< int > nElectrons
These are not filled by default.
std::vector< int > ionA
These are not filled by default.
void FlushLocal()
Actual flush that is non virtual function to use in constructor.
std::vector< U > getRigidity()
Function to calculate on the fly the parameters.
std::vector< U > getMass()
Function to calculate on the fly the parameters.
std::vector< U > rigidity
These are not filled by default.
std::vector< bool > getIsIon()
Function to calculate on the fly the parameters.
std::vector< int > charge
These are not filled by default.
virtual void Flush()
Clean Sampler.
std::vector< U > kineticEnergy
These are not filled by default.
void FillPolarCoords(const BDSParticleCoordsFull &coords)
Calculate polar coords and fill.
std::vector< U > mass
These are not filled by default.
std::vector< int > ionZ
These are not filled by default.
std::vector< U > getKineticEnergy()
Function to calculate on the fly the parameters.
Geant4 particle data for particles used in simulation.
void Fill(G4bool fillIons)
Fill maps of particle information from Geant4.
A set of particle coordinates including energy and weight.
G4double s
TODO - remove this. Unused. S (global) is calculated from S0 + z.
Full set of coordinates for association with primary vertex. Vector version.
std::vector< BDSPrimaryVertexInformation > vertices
Full set of coordinates.