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 - 2023.
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 Flush();
44}
45
46template <class U>
48 samplerName(samplerNameIn)
49{
50 Flush();
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{
264 n = 0;
265 energy.clear();
266 x.clear();
267 y.clear();
268 z = 0.0;
269 xp.clear();
270 yp.clear();
271 zp.clear();
272 p.clear();
273 T.clear();
274 weight.clear();
275 partID.clear();
276 parentID.clear();
277 trackID.clear();
278 modelID = -1;
279 turnNumber.clear();
280
281 S = 0.0;
282
283 r.clear();
284 rp.clear();
285 phi.clear();
286 phip.clear();
287 theta.clear();
288
289 charge.clear();
290 kineticEnergy.clear();
291 mass.clear();
292 rigidity.clear();
293 isIon.clear();
294 ionA.clear();
295 ionZ.clear();
296 nElectrons.clear();
297}
298
299template <class U>
301{
302 std::vector<U> result((unsigned long)n);
303 if (!particleTable)
304 {return result;}
305 for (int i = 0; i < n; ++i)
306 {result[i] = (U)particleTable->KineticEnergy(partID[i], energy[i]);}
307 return result;
308}
309
310template <class U>
312{
313 std::vector<U> result((unsigned long)n);
314 if (!particleTable)
315 {return result;}
316 for (int i = 0; i < n; ++i)
317 {result[i] = (U)particleTable->Mass(partID[i]);}
318 return result;
319}
320
321template <class U>
323{
324 std::vector<U> result((unsigned long)n);
325 if (!particleTable)
326 {return result;}
327 for (int i = 0; i < n; ++i)
328 {result[i] = (U)particleTable->Rigidity(partID[i], energy[i]);}
329 return result;
330}
331
332template <class U>
334{
335 bool useNElectrons = !nElectrons.empty();
336 std::vector<bool> result((unsigned long)n);
337 if (!particleTable)
338 {return result;}
339 for (int i = 0; i < n; ++i)
340 {
341 result[i] = particleTable->IsIon(partID[i]);
342 if (useNElectrons)
343 {result[i] = result[i] || nElectrons[i] > 0;}
344 }
345 return result;
346}
347
348template <class U>
350{
351 std::vector<int> result((unsigned long)n);
352 if (!particleTable)
353 {return result;}
354 for (int i = 0; i < n; ++i)
355 {result[i] = (int)particleTable->IonA(partID[i]);}
356 return result;
357}
358
359template <class U>
361{
362 std::vector<int> result((unsigned long)n);
363 if (!particleTable)
364 {return result;}
365 for (int i = 0; i < n; ++i)
366 {result[i] = (int)particleTable->IonZ(partID[i]);}
367 return result;
368}
369
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.
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.
virtual void Flush()
Clear maps.
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.