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) 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 "BDSOutputROOTEventSampler.hh"
19#include "BDSOutputROOTParticleData.hh"
20
21#include "TTree.h"
22
24
25#ifndef __ROOTBUILD__
26#include "BDSHitSampler.hh"
27#include "BDSParticleCoordsFull.hh"
28#include "BDSPhysicalConstants.hh"
29#include "BDSPrimaryVertexInformationV.hh"
30
31#include "globals.hh"
32#include "CLHEP/Units/SystemOfUnits.h"
33#include <cmath>
34#endif
35
36templateClassImp(BDSOutputROOTEventSampler)
37
38template <class U>
40 samplerName("sampler")
41{
42 FlushLocal();
43}
44
45template <class U>
47 samplerName(samplerNameIn)
48{
49 FlushLocal();
50}
51
52template
54{;}
55
56#ifndef __ROOTBUILD__
57template <class U>
59 G4bool storeMass,
60 G4bool storeCharge,
61 G4bool storePolarCoords,
62 G4bool storeElectrons,
63 G4bool storeRigidity,
64 G4bool storeKineticEnergy)
65{
66 // get single values
67 n++;
68 z = (U) (hit->coords.z / CLHEP::m);
69 S = (U) (hit->coords.s / CLHEP::m);
70
71 energy.push_back((U) (hit->coords.totalEnergy / CLHEP::GeV));
72 x.push_back((U) (hit->coords.x / CLHEP::m));
73 y.push_back((U) (hit->coords.y / CLHEP::m));
74
75 xp.push_back((U) (hit->coords.xp));
76 yp.push_back((U) (hit->coords.yp));
77 zp.push_back((U) (hit->coords.zp));
78 p.push_back((U) (hit->momentum / CLHEP::GeV));
79 T.push_back((U) (hit->coords.T / CLHEP::ns));
80
81 modelID = hit->beamlineIndex;
82
83 weight.push_back((U) (hit->coords.weight));
84 partID.push_back(hit->pdgID);
85 parentID.push_back(hit->parentID);
86 trackID.push_back(hit->trackID);
87 turnNumber.push_back(hit->turnsTaken);
89 if (storeMass)
90 {mass.push_back((U)(hit->mass / CLHEP::GeV));}
92 if (storeCharge)
93 {charge.push_back((int)(hit->charge / (G4double)CLHEP::eplus));}
94
95 if (storeKineticEnergy)
96 {kineticEnergy.push_back((U)(hit->coords.totalEnergy - hit->mass) / CLHEP::GeV);}
97
98 if (storeRigidity)
99 {rigidity.push_back((U)hit->rigidity/(CLHEP::tesla*CLHEP::m));}
100
101 if (storePolarCoords)
102 {FillPolarCoords(hit->coords);}
103
104 if (storeElectrons)
105 {nElectrons.push_back((int)hit->nElectrons);}
106}
107
108template <class U>
110 G4double momentumIn,
111 G4double chargeIn,
112 G4int pdgID,
113 G4int turnsTaken,
114 G4int beamlineIndex,
115 G4int nElectronsIn,
116 G4double massIn,
117 G4double rigidityIn,
118 G4bool fillIon,
119 G4bool* isIonIn,
120 G4int* ionAIn,
121 G4int* ionZIn)
123 trackID.push_back(n); // we assume multiple primaries are linearly increasing in track number
124 n++;
125 energy.push_back((U) (coords.totalEnergy / CLHEP::GeV));
126 x.push_back((U) (coords.x / CLHEP::m));
127 y.push_back((U) (coords.y / CLHEP::m));
128 z = (U) (coords.z / CLHEP::m);
129 xp.push_back((U) (coords.xp));
130 yp.push_back((U) (coords.yp));
131 zp.push_back((U) (coords.zp));
132 p.push_back((U) (momentumIn / CLHEP::GeV));
133 T.push_back((U) (coords.T / CLHEP::ns));
134 weight.push_back((U) coords.weight);
135 partID.push_back(pdgID);
136 parentID.push_back(0);
137 modelID = beamlineIndex;
138 turnNumber.push_back(turnsTaken);
139 S = (U) (coords.s / CLHEP::GeV);
140
141 // always store optional bits for primary
142 charge.push_back((int)(chargeIn / (G4double)CLHEP::eplus));
143 mass.push_back((U)(massIn / CLHEP::GeV));
144 rigidity.push_back((U)rigidityIn /(CLHEP::tesla*CLHEP::m));
145 nElectrons.push_back((int)nElectronsIn);
146 kineticEnergy.push_back((U)(coords.totalEnergy - massIn) / CLHEP::GeV);
147 FillPolarCoords(coords);
148 if (isIonIn && ionAIn && ionZIn)
149 {
150 isIon.push_back((int) *isIonIn);
151 ionA.push_back((int) *ionAIn);
152 ionZ.push_back((int) *ionZIn);
153 }
154 else if (fillIon)
155 {FillIon();}
156}
157
158template <class U>
160{
161 double xCoord = coords.x / CLHEP::m;
162 double yCoord = coords.y / CLHEP::m;
163 double xpCoord = coords.xp;
164 double ypCoord = coords.yp;
165 double zpCoord = coords.zp;
166
167 // nans or infinite numbers can be set to -1
168 auto isntSafe = [](double a){return std::isnan(a) || std::isinf(a);};
169
170 double rValue = std::hypot(xCoord, yCoord);
171 if (isntSafe(rValue))
172 {rValue = 0;}
173 r.push_back(static_cast<U>(rValue));
174
175 double rpValue = std::hypot(xpCoord, ypCoord);
176 if (isntSafe(rpValue))
177 {rpValue = 0;}
178 rp.push_back(static_cast<U>(rpValue));
179
180 double thetapValue = std::atan2(rpValue, zpCoord);
181 if (isntSafe(thetapValue))
182 {thetapValue = -1;}
183 theta.push_back(static_cast<U>(thetapValue));
184
185 double phiValue = std::atan2(xCoord, yCoord);
186 if (isntSafe(phiValue))
187 {phiValue = -1;}
188 phi.push_back(static_cast<U>(phiValue));
189
190 double phipValue = std::atan2(xpCoord, ypCoord);
191 if (isntSafe(phipValue))
192 {phipValue = -1;}
193 phip.push_back(static_cast<U>(phipValue));
194}
195
196template <class U>
198 const G4int turnsTaken)
199{
200 for (const auto& vertexInfo : vertexInfos->vertices)
201 {
202 Fill(vertexInfo.primaryVertex.local,
203 vertexInfo.momentum,
204 vertexInfo.charge,
205 vertexInfo.pdgID,
206 turnsTaken,
207 vertexInfo.primaryVertex.beamlineIndex,
208 vertexInfo.nElectrons,
209 vertexInfo.mass,
210 vertexInfo.rigidity,
211 false);
212 }
213 FillIon();
214}
215#endif
216
217template <class U>
219{
220 if (!other)
221 {return;}
222 n = other->n;
223 energy = other->energy;
224 x = other->x;
225 y = other->y;
226 z = other->z;
227 xp = other->xp;
228 yp = other->yp;
229 zp = other->zp;
230 p = other->p;
231 T = other->T;
232
233 weight = other->weight;
234 partID = other->partID;
235 parentID = other->parentID;
236 trackID = other->trackID;
237 modelID = other->modelID;
238 turnNumber = other->turnNumber;
239 S = other->S;
240
241 r = other->r;
242 rp = other->rp;
243 phi = other->phi;
244 phip = other->phip;
245 theta = other->theta;
246
247 charge = other->charge;
248 kineticEnergy = other->kineticEnergy;
249 mass = other->mass;
250 rigidity = other->rigidity;
251
252 isIon = other->isIon;
253 ionA = other->ionA;
254 ionZ = other->ionZ;
255 nElectrons = other->nElectrons;
256}
257
258template <class U> void BDSOutputROOTEventSampler<U>::SetBranchAddress(TTree *)
259{;}
260
261template <class U> void BDSOutputROOTEventSampler<U>::Flush()
262{FlushLocal();}
263
265{
266 n = 0;
267 energy.clear();
268 x.clear();
269 y.clear();
270 z = 0.0;
271 xp.clear();
272 yp.clear();
273 zp.clear();
274 p.clear();
275 T.clear();
276 weight.clear();
277 partID.clear();
278 parentID.clear();
279 trackID.clear();
280 modelID = -1;
281 turnNumber.clear();
282
283 S = 0.0;
284
285 r.clear();
286 rp.clear();
287 phi.clear();
288 phip.clear();
289 theta.clear();
290
291 charge.clear();
292 kineticEnergy.clear();
293 mass.clear();
294 rigidity.clear();
295 isIon.clear();
296 ionA.clear();
297 ionZ.clear();
298 nElectrons.clear();
299}
300
301template <class U>
303{
304 std::vector<U> result((unsigned long)n);
305 if (!particleTable)
306 {return result;}
307 for (int i = 0; i < n; ++i)
308 {result[i] = (U)particleTable->KineticEnergy(partID[i], energy[i]);}
309 return result;
310}
311
312template <class U>
314{
315 std::vector<U> result((unsigned long)n);
316 if (!particleTable)
317 {return result;}
318 for (int i = 0; i < n; ++i)
319 {result[i] = (U)particleTable->Mass(partID[i]);}
320 return result;
321}
322
323template <class U>
325{
326 std::vector<U> result((unsigned long)n);
327 if (!particleTable)
328 {return result;}
329 for (int i = 0; i < n; ++i)
330 {result[i] = (U)particleTable->Rigidity(partID[i], energy[i]);}
331 return result;
332}
333
334template <class U>
336{
337 bool useNElectrons = !nElectrons.empty();
338 std::vector<bool> result((unsigned long)n);
339 if (!particleTable)
340 {return result;}
341 for (int i = 0; i < n; ++i)
342 {
343 result[i] = particleTable->IsIon(partID[i]);
344 if (useNElectrons)
345 {result[i] = result[i] || nElectrons[i] > 0;}
346 }
347 return result;
348}
349
350template <class U>
352{
353 std::vector<int> result((unsigned long)n);
354 if (!particleTable)
355 {return result;}
356 for (int i = 0; i < n; ++i)
357 {result[i] = (int)particleTable->IonA(partID[i]);}
358 return result;
359}
360
361template <class U>
363{
364 std::vector<int> result((unsigned long)n);
365 if (!particleTable)
366 {return result;}
367 for (int i = 0; i < n; ++i)
368 {result[i] = (int)particleTable->IonZ(partID[i]);}
369 return result;
370}
371
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.