BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSOutputROOTEventTrajectory.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 <algorithm>
19#include <bitset>
20#include <iostream>
21#include <iomanip>
22
23#include "BDSOutputROOTEventTrajectory.hh"
24
25#ifndef __ROOTBUILD__
26#include "G4VPhysicalVolume.hh"
27
28#include "BDSHitEnergyDeposition.hh"
29#include "BDSAuxiliaryNavigator.hh"
30#include "BDSPhysicalVolumeInfoRegistry.hh"
31#include "BDSPhysicalVolumeInfo.hh"
32#include "BDSTrajectory.hh"
33#include "BDSTrajectoryOptions.hh"
34
35#include <cmath>
36#include <map>
37#endif
38
40BDSOutputROOTEventTrajectory::BDSOutputROOTEventTrajectory():
41 auxNavigator(nullptr),
42 n(0)
43{
44 FlushLocal();
45}
46
47BDSOutputROOTEventTrajectory::~BDSOutputROOTEventTrajectory()
48{
49#ifndef __ROOTBUILD__
50 delete auxNavigator;
51#endif
52}
53
54#ifndef __ROOTBUILD__
55int findPrimaryStepIndex(BDSTrajectory* traj)
56{
57 if (!traj->GetParent())
58 {return -1;}
59
60 if (traj->GetParent()->GetTrackID() == 1)
61 {return traj->GetParentStepIndex();}
62 else
63 {return findPrimaryStepIndex(traj->GetParent());}
64}
65
66void BDSOutputROOTEventTrajectory::Fill(const BDSTrajectoriesToStore* trajectories,
67 int storeStepPointsN,
68 bool storeStepPointLast,
69 const BDS::TrajectoryOptions& storageOptions,
70 const std::map<G4Material*, short int>& materialToID)
71{
72 if (!auxNavigator)
73 {// navigator for converting coordinates to curvilinear coordinate system
75 }
76
77 G4bool stEK = storageOptions.storeLinks || storageOptions.storeKineticEnergy;
78 G4bool stMo = storageOptions.storeMomentumVector;
79 G4bool stPr = storageOptions.storeProcesses;
80 G4bool stTi = storageOptions.storeTime;
81 G4bool stMa = storageOptions.storeMaterial;
82
83 // assign trajectory indices
84 int idx = 0;
85 for (auto trajFlag : trajectories->trajectories)
86 {
87 BDSTrajectory* traj = trajFlag.first;
88 if (trajFlag.second) // ie we want to save this trajectory
89 {
90 traj->SetTrajIndex(idx);
91 idx++;
92 }
93 else // we don't want to save it
94 {traj->SetTrajIndex(-1);}
95 }
96
97 // assign parent (and step) indices
98 for (auto trajFlag : trajectories->trajectories)
99 {
100 BDSTrajectory* traj = trajFlag.first;
101 BDSTrajectory* parent = traj->GetParent();
102 if (trajFlag.second && parent)
103 { // to store and not primary
104 traj->SetParentIndex(parent->GetTrajIndex());
105
106 // search for parent step index
107 if (parent->GetTrajIndex() != -1)
108 {
109 auto trajStartPos = traj->GetPoint(0)->GetPosition();
110 traj->SetParentStepIndex(-1);
111 for (int i = 0; i < parent->GetPointEntries(); ++i)
112 {
113 if(parent->GetPoint(i)->GetPosition() == trajStartPos)
114 {
115 traj->SetParentStepIndex(i);
116 break;
117 }
118 }
119 }
120 else
121 {parent->SetParentStepIndex(-1);}
122 }
123 else
124 {traj->SetParentIndex(-1);}
125 }
126
127 n = 0;
128 for (auto trajFlag : trajectories->trajectories)
129 {
130 BDSTrajectory* traj = trajFlag.first;
131
132 // check if the trajectory is to be stored
133 if (!trajFlag.second) // ie false, then continue and don't store
134 {continue;}
135
136 partID.push_back((int) traj->GetPDGEncoding());
137 trackID.push_back((unsigned int) std::abs(traj->GetTrackID()));
138 parentID.push_back((unsigned int) std::abs(traj->GetParentID()));
139 parentIndex.push_back((unsigned int) std::abs(traj->GetParentIndex()));
140 parentStepIndex.push_back((unsigned int) std::abs(traj->GetParentStepIndex()));
141 depth.push_back((int) traj->GetDepth());
142
143 // now we convert the geant4 type based BDSTrajectory information into
144 // basic C++ and ROOT types for the output
145 IndividualTrajectory itj;
146 if (storeStepPointsN > 0)
147 {// store specific number of step points along the trajectory
148 G4int nSteps = traj->GetPointEntries();
149 G4int nPoints = std::min(nSteps, storeStepPointsN);
150 for (int i = 0; i < nPoints; ++i)
151 {FillIndividualTrajectory(itj, traj, i, materialToID);}
152 // optionally include the last point if required and not already stored
153 if (storeStepPointLast && (nPoints < nSteps))
154 {FillIndividualTrajectory(itj, traj, nSteps-1, materialToID);}
155 }
156 else
157 {// store all points as usual
158 for (int i = 0; i < traj->GetPointEntries(); ++i)
159 {FillIndividualTrajectory(itj, traj, i, materialToID);}
160 }
161
162 // record the filters that were matched for this trajectory
163 filters.push_back(trajectories->filtersMatched.at(traj));
164
165 XYZ.push_back(itj.XYZ);
166 modelIndicies.push_back(itj.modelIndex);
167
168 if (stMo)
169 {PXPYPZ.push_back(itj.PXPYPZ);}
170
171 S.push_back(itj.S);
172
173 if (stPr)
174 {
175 preProcessTypes.push_back(itj.preProcessType);
176 preProcessSubTypes.push_back(itj.preProcessSubType);
177 postProcessTypes.push_back(itj.postProcessType);
178 postProcessSubTypes.push_back(itj.postProcessSubType);
179 }
180
181 preWeights.push_back(itj.preWeight);
182 postWeights.push_back(itj.postWeight);
183 energyDeposit.push_back(itj.energyDeposit);
184
185 if (stTi)
186 {T.push_back(itj.T);}
187
188 if (stEK)
189 {kineticEnergy.push_back(itj.kineticEnergy);}
190
191 if (stMa)
192 {materialID.push_back(itj.materialID);}
193
194 if (!itj.xyz.empty())
195 {
196 xyz.push_back(itj.xyz);
197 pxpypz.push_back(itj.pxpypz);
198 }
199
200 if (!itj.charge.empty())
201 {
202 charge.push_back(itj.charge);
203 turnsTaken.push_back(itj.turn);
204 mass.push_back(itj.mass);
205 rigidity.push_back(itj.rigidity);
206 }
207
208 if (!itj.isIon.empty())
209 {
210 isIon.push_back(itj.isIon);
211 ionA.push_back(itj.ionA);
212 ionZ.push_back(itj.ionZ);
213 nElectrons.push_back(itj.nElectrons);
214 }
215
216 // recursively search for primary interaction step
217 primaryStepIndex.push_back(findPrimaryStepIndex(traj));
218
219 // geant4 trackID to trackIndex in this table
220 trackID_trackIndex.insert(std::pair<int,int>(traj->GetTrackID(),n));
221
222 n++;
223 }
224
225#if 0
226 // Fill maps for later analysis
227 int trackIndex = 0;
228 for (auto iT = trajVec.begin(); iT != trajVec.end(); ++iT)
229 {
230 BDSTrajectory* traj = *iT;
231
232 // map of trackID to trackIndex
233 trackID_trackIndex.insert(std::pair<int, int>(traj->GetTrackID(),trackIndex));
234
235 std::cout << trajVec.size() << " " << parentID.size() << " " << parentIndex.size() << " "
236 << traj->GetTrackID() << " " << traj->GetParentID() << " " << trackIndex << std::endl;
237
238 // map of trackIndex to trackProcess
239 auto processPair = findParentProcess(trackIndex);
240 trackIndex_trackProcess.insert(std::pair<int,std::pair<int,int>>(trackIndex,processPair));
241
242 // map of modelIndex to trackProcess
243 if(processPair.first != -1)
244 {
245 int mi = modelIndicies[processPair.first][processPair.second];
246 trackIndex_modelIndex.insert(std::pair<int,int>(trackIndex, mi));
247 try
248 {modelIndex_trackIndex.at(mi).push_back(trackIndex);}
249 catch(const std::exception&)
250 {
251 modelIndex_trackIndex.insert(std::pair<int,std::vector<int>>(mi,std::vector<int>()));
252 modelIndex_trackIndex.at(mi).push_back(trackIndex);
253 }
254 }
255
256 ++trackIndex;
257 }
258#endif
259}
260
262 BDSTrajectory* traj,
263 int i,
264 const std::map<G4Material*, short int>& materialToID) const
265{
266 BDSTrajectoryPoint* point = dynamic_cast<BDSTrajectoryPoint*>(traj->GetPoint(i));
267 if (!point)
268 {return;}
269
270 // Position
271 G4ThreeVector pos = point->GetPosition();
272 itj.XYZ.emplace_back(pos.getX() / CLHEP::m, pos.getY() / CLHEP::m, pos.getZ() / CLHEP::m);
273
274 G4VPhysicalVolume* vol = auxNavigator->LocateGlobalPointAndSetup(pos,nullptr,true,true,true);
276 if (theInfo)
277 {itj.modelIndex.push_back(theInfo->GetBeamlineIndex());}
278 else
279 {itj.modelIndex.push_back(-1);}
280
281 // Process types
282 itj.preProcessType.push_back(point->GetPreProcessType());
283 itj.preProcessSubType.push_back(point->GetPreProcessSubType());
284 itj.postProcessType.push_back(point->GetPostProcessType());
285 itj.postProcessSubType.push_back(point->GetPostProcessSubType());
286
287 itj.preWeight.push_back(point->GetPreWeight());
288 itj.postWeight.push_back(point->GetPostWeight());
289 itj.energyDeposit.push_back(point->GetEnergyDeposit() / CLHEP::GeV);
290 G4ThreeVector mom = point->GetPreMomentum() / CLHEP::GeV;
291 itj.PXPYPZ.emplace_back(mom.getX(), mom.getY(), mom.getZ());
292 itj.S.push_back(point->GetPreS() / CLHEP::m);
293 itj.T.push_back(point->GetPreGlobalTime() / CLHEP::ns);
294 itj.kineticEnergy.push_back(point->GetKineticEnergy() / CLHEP::GeV);
295
296 itj.materialID.push_back(materialToID.at(point->GetMaterial()));
297
298 if (point->extraLocal)
299 {
300 G4ThreeVector localPos = point->GetPositionLocal() / CLHEP::m;
301 G4ThreeVector localMom = point->GetMomentumLocal() / CLHEP::GeV;
302 itj.xyz.emplace_back(localPos.getX(), localPos.getY(), localPos.getZ());
303 itj.pxpypz.emplace_back(localMom.getX(), localMom.getY(), localMom.getZ());
304 }
305
306 if (point->extraLink)
307 {
308 itj.charge.push_back((int) (point->GetCharge() / (G4double)CLHEP::eplus));
309 itj.turn.push_back(point->GetTurnsTaken());
310 itj.mass.push_back(point->GetMass() / CLHEP::GeV);
311 itj.rigidity.push_back(point->GetRigidity() / (CLHEP::tesla*CLHEP::m));
312 }
313
314 if (point->extraIon)
315 {
316 itj.isIon.push_back(point->GetIsIon());
317 itj.ionA.push_back(point->GetIonA());
318 itj.ionZ.push_back(point->GetIonZ());
319 itj.nElectrons.push_back(point->GetNElectrons());
320 }
321}
322
323void BDSOutputROOTEventTrajectory::Fill(const BDSHitsCollectionEnergyDeposition* phc)
324{
325 G4cout << phc->GetSize() << G4endl;
326}
327
328#endif
329
334
336{
337 n = 0;
338 filters.clear();
339 partID.clear();
340 trackID.clear();
341 parentID.clear();
342 parentIndex.clear();
343 parentStepIndex.clear();
344 primaryStepIndex.clear();
345 depth.clear();
346
347 preProcessTypes.clear();
348 preProcessSubTypes.clear();
349 postProcessTypes.clear();
350 postProcessSubTypes.clear();
351
352 preWeights.clear();
353 postWeights.clear();
354 energyDeposit.clear();
355
356 XYZ.clear();
357 S.clear();
358 PXPYPZ.clear();
359 T.clear();
360
361 xyz.clear();
362 pxpypz.clear();
363
364 charge.clear();
365 kineticEnergy.clear();
366 turnsTaken.clear();
367 mass.clear();
368 rigidity.clear();
369
370 isIon.clear();
371 ionA.clear();
372 ionZ.clear();
373 nElectrons.clear();
374
375 materialID.clear();
376 modelIndicies.clear();
377 trackID_trackIndex.clear();
378
379 // trackIndex_trackProcess.clear();
380 // trackIndex_modelIndex.clear();
381 // modelIndex_trackIndex.clear();
382}
383
384void BDSOutputROOTEventTrajectory::Fill(const BDSOutputROOTEventTrajectory* other)
385{
386 if (!other)
387 {return;}
388
389 n = 0;
390 filters = other->filters;
391 partID = other->partID;
392 trackID = other->trackID;
393 parentID = other->parentID;
394 parentIndex = other->parentIndex;
395 parentStepIndex = other->parentStepIndex;
396 primaryStepIndex = other->primaryStepIndex;
397 depth = other->depth;
398
399 preProcessTypes = other->preProcessTypes;
400 preProcessSubTypes = other->preProcessSubTypes;
401 postProcessTypes = other->postProcessTypes;
402 postProcessSubTypes = other->postProcessSubTypes;
403
404 preWeights = other->preWeights;
405 postWeights = other->postWeights;
406 energyDeposit = other->energyDeposit;
407
408 XYZ = other->XYZ;
409 S = other->S;
410 PXPYPZ = other->PXPYPZ;
411 T = other->T;
412
413 xyz = other->xyz;
414 pxpypz = other->pxpypz;
415 charge = other->charge;
417 turnsTaken = other->turnsTaken;
418 mass = other->mass;
419 rigidity = other->rigidity;
420
421 isIon = other->isIon;
422 ionA = other->ionA;
423 ionZ = other->ionZ;
424 nElectrons = other->nElectrons;
425
426 materialID = other->materialID;
427 modelIndicies = other->modelIndicies;
428 trackID_trackIndex = other->trackID_trackIndex;
429
430}
431
432#if 0
433std::pair<int,int> BDSOutputROOTEventTrajectory::findParentProcess(int trackIndex)
434{
435 std::cout << "BDSOutputROOTEventTrajectory::findParentProcess> "
436 << trackIndex << " " << parentID.size() << " " << parentIndex.size() << std::endl;
437 int tid = trackIndex;
438 int pid = parentID.at(tid);
439 std::cout << pid << std::endl;
440 int pin = parentIndex.at(tid);
441 std::cout << pin << std::endl;
442
443 if (pin == -1)
444 {return std::pair<int,int>(-1,-1);}
445 int sin = parentStepIndex.at(tid);
446 std::cout << sin << std::endl;
447
448 while (pid > 0)
449 {
450 if(pin == 0)
451 {break;}
452 tid = pin;
453 pid = parentID.at(tid);
454 pin = parentIndex.at(tid);
455 sin = parentStepIndex.at(tid);
456
457 std::cout << tid << " " << pid << " " << pin << " " << sin << " " << std::endl;
458 }
459
460 return std::pair<int,int>(pin,sin);
461}
462#endif
463
464std::vector<BDSOutputROOTEventTrajectoryPoint> BDSOutputROOTEventTrajectory::trackInteractions(int trackIDIn) const
465{
466 // prevent a bad access
467 if (trackID_trackIndex.find(trackIDIn) == trackID_trackIndex.end())
468 {
469 std::cout << "No such track ID" << std::endl;
470 return std::vector<BDSOutputROOTEventTrajectoryPoint>();
471 }
472
473 int ti = trackID_trackIndex.at(trackIDIn); // get track index
474
475 std::vector<BDSOutputROOTEventTrajectoryPoint> tpv; // trajectory point vector - result
476
477 int nstep = (int)XYZ[ti].size();
478 if (nstep == 0) // no points or it wasn't stored
479 {return std::vector<BDSOutputROOTEventTrajectoryPoint>();}
480
481 if (postProcessTypes[ti].empty()) // and implicitly nstep>0
482 {// we require processes for this function
483 std::cout << "Processes not stored for this file - not possible." << std::endl;
484 return std::vector<BDSOutputROOTEventTrajectoryPoint>();
485 }
486
487 bool usePXPYPZ = !PXPYPZ[ti].empty();
488 bool useT = !T.empty();
489 bool useIon = !isIon.empty();
490 bool useLocal = !xyz.empty();
491 bool useLinks = !charge.empty();
492 bool useEK = !kineticEnergy.empty();
493 bool useMat = !materialID.empty();
494
495 for (int i = 0; i < nstep; ++i)
496 {
497 int ppt = postProcessTypes[ti][i];
498 int ppst = postProcessSubTypes[ti][i];
499 // this is a hard coded version of BDSTrajectoryPoint::IsScatteringPoint which is
500 // only available if we link to Geant4 for the enums (we don't here).
501 // -1 = undefined, 1 = G4ProcessType::fTransportation, 10 = G4ProcessTypes::fParallel
502 // 0 = G4ProcessType::fNotDefined for crystal channeling (exclude the thousands of points)
503 // 401 = G4TransportationProcessSubType::STEP_LIMITER which is categorised under G4ProcessType::fGeneral
504 bool notGeneral = ppt != 7 && ppst != 401;
505 bool changeInEnergy = energyDeposit[ti][i] > 1e-9;
506 if ( (ppt != -1 && ppt != 1 && ppt != 10 && ppt != 0 && notGeneral) || changeInEnergy)
507 {
509 trackID[ti],
510 parentID[ti],
511 parentIndex[ti],
512 postProcessTypes[ti][i],
513 postProcessSubTypes[ti][i],
514 postWeights[ti][i],
515 energyDeposit[ti][i],
516 XYZ[ti][i],
517 usePXPYPZ ? PXPYPZ[ti][i] : TVector3(),
518 modelIndicies[ti][i],
519 useT ? T[ti][i] : 0,
520 useLocal ? xyz[ti][i] : TVector3(),
521 useLocal ? pxpypz[ti][i] : TVector3(),
522 useLinks ? charge[ti][i] : 0,
523 useEK ? kineticEnergy[ti][i] : 0,
524 useLinks ? turnsTaken[ti][i] : 0,
525 useLinks ? rigidity[ti][i] : 0,
526 useLinks ? mass[ti][i] : 0,
527 useIon ? isIon[ti][i] : false,
528 useIon ? ionA[ti][i] : 0,
529 useIon ? ionZ[ti][i] : 0,
530 useIon ? nElectrons[ti][i] : 0,
531 useMat ? materialID[ti][i] : -1,
532 i);
533 tpv.push_back(p);
534 }
535 }
536 return tpv;
537}
538
539BDSOutputROOTEventTrajectoryPoint BDSOutputROOTEventTrajectory::primaryProcessPoint(int trackIDIn) const
540{
541 // prevent a bad access
542 if (trackID_trackIndex.find(trackIDIn) == trackID_trackIndex.end())
543 {
544 std::cout << "No such track ID" << std::endl;
546 }
547 int ti = trackID_trackIndex.at(trackIDIn); // get track index
548 int pid = (int)parentID[ti]; // parent trackID
549 int chosenTrackID = trackIDIn;
550 while (pid != 0)
551 {
552 if (parentID[trackID_trackIndex.at(pid)] > 0)
553 {chosenTrackID = pid;}
554 ti = trackID_trackIndex.at(pid);
555 pid = (int)parentID[ti];
556 }
557 return parentProcessPoint(chosenTrackID);
558}
559
560BDSOutputROOTEventTrajectoryPoint BDSOutputROOTEventTrajectory::parentProcessPoint(int trackIDIn) const
561{
562 // prevent a bad access
563 if (trackID_trackIndex.find(trackIDIn) == trackID_trackIndex.end())
564 {
565 std::cout << "No such track ID" << std::endl;
567 }
568
569 int ti = trackID_trackIndex.at(trackIDIn); // get track index
570 int pti = (int)parentID[ti]; // parent trackID
571
572 if (pti == 0)
573 {
574 std::cout << "Track is a parent" << std::endl;
576 }
577
578 int si = (int)parentStepIndex.at(ti); // get primary index
579 int pi = 0;
580 if (pti > 0)
581 {pi = trackID_trackIndex.at(pti);} // parent track storage index
582 else
583 {pi = ti;}
584
585 if (si > (int)XYZ[pi].size())
586 {// evidently not all step points are stored
587 std::cout << "Not all step points are stored. Parent step index is outside points stored." << std::endl;
589 }
590
591 bool usePXPYPZ = !PXPYPZ[ti].empty();
592 bool useT = !T.empty();
593 bool useIon = !isIon.empty();
594 bool useLocal = !xyz.empty();
595 bool useLinks = !charge.empty();
596 bool useEK = !kineticEnergy.empty();
597 bool useMat = !materialID.empty();
598
600 trackID[pi],
601 parentID[pi],
602 parentIndex[pi],
603 postProcessTypes[pi][si],
604 postProcessSubTypes[pi][si],
605 postWeights[pi][si],
606 energyDeposit[pi][si],
607 XYZ[pi][si],
608 usePXPYPZ ? PXPYPZ[pi][si] : TVector3(),
609 modelIndicies[pi][si],
610 useT ? T[pi][si] : 0,
611 useLocal ? xyz[pi][si] : TVector3(),
612 useLocal ? pxpypz[pi][si] : TVector3(),
613 useLinks ? charge[pi][si] : 0,
614 useEK ? kineticEnergy[pi][si] : 0,
615 useLinks ? turnsTaken[pi][si] : 0,
616 useLinks ? rigidity[pi][si] : 0,
617 useLinks ? mass[pi][si] : 0,
618 useIon ? isIon[pi][si] : false,
619 useIon ? ionA[pi][si] : 0,
620 useIon ? ionZ[pi][si] : 0,
621 useIon ? nElectrons[pi][si] : 0,
622 useMat ? materialID[pi][si] : -1,
623 si);
624 return p;
625}
626
627std::vector<BDSOutputROOTEventTrajectoryPoint> BDSOutputROOTEventTrajectory::processHistory(int trackIDIn) const
628{
629 // prevent a bad access
630 if (trackID_trackIndex.find(trackIDIn) == trackID_trackIndex.end())
631 {
632 std::cout << "No such track ID" << std::endl;
633 return std::vector<BDSOutputROOTEventTrajectoryPoint>();
634 }
635
636 if (postProcessTypes.empty())
637 {
638 std::cout << "Processes not stored for this file - not possible." << std::endl;
639 return std::vector<BDSOutputROOTEventTrajectoryPoint>();
640 }
641
642 int ti = trackID_trackIndex.at(trackIDIn);
643
644 bool usePXPYPZ = !PXPYPZ.empty();
645 bool useT = !T.empty();
646 bool useIon = !isIon.empty();
647 bool useLocal = !xyz.empty();
648 bool useLinks = !charge.empty();
649 bool useEK = !kineticEnergy.empty();
650 bool useMat = !materialID.empty();
651
652 std::vector<BDSOutputROOTEventTrajectoryPoint> tpv; // trajectory point vector
653 while (ti != 0)
654 {
655 unsigned int pi = parentIndex.at(ti);
656 unsigned int psi = parentStepIndex.at(ti);
657 if (psi > (unsigned int)XYZ[pi].size())
658 {
659 std::cout << "Not all points stored - defaulting to creation point." << std::endl;
660 psi = 0;
661 }
662
664 trackID[pi],
665 parentID[pi],
666 parentIndex[pi],
667 postProcessTypes[pi][psi],
668 postProcessSubTypes[pi][psi],
669 postWeights[pi][psi],
670 energyDeposit[pi][psi],
671 XYZ[pi][psi],
672 usePXPYPZ ? PXPYPZ[ti][psi] : TVector3(),
673 modelIndicies[ti][psi],
674 useT ? T[ti][psi] : 0,
675 useLocal ? xyz[ti][psi] : TVector3(),
676 useLocal ? pxpypz[ti][psi] : TVector3(),
677 useLinks ? charge[ti][psi] : 0,
678 useEK ? kineticEnergy[ti][psi] : 0,
679 useLinks ? turnsTaken[ti][psi] : 0,
680 useLinks ? rigidity[ti][psi] : 0,
681 useLinks ? mass[ti][psi] : 0,
682 useIon ? isIon[ti][psi] : false,
683 useIon ? ionA[ti][psi] : 0,
684 useIon ? ionZ[ti][psi] : 0,
685 useIon ? nElectrons[ti][psi] : 0,
686 useMat ? materialID[ti][psi] : -1,
687 (int)psi);
688 tpv.push_back(p);
689 ti = (int)pi;
690 }
691 std::reverse(tpv.begin(),tpv.end());
692 return tpv;
693}
694
695void BDSOutputROOTEventTrajectory::printTrajectoryInfoByTrackID(int trackIDIn) const
696{
697 // prevent a bad access
698 int storageIndex = 0;
699 auto search = trackID_trackIndex.find(trackIDIn);
700 if (search == trackID_trackIndex.end())
701 {
702 std::cout << "No such track ID" << std::endl;
703 return;
704 }
705 else
706 {storageIndex = search->second;}
707 printTrajectoryInfo(storageIndex);
708}
709
710void BDSOutputROOTEventTrajectory::printTrajectoryInfo(int storageIndex) const
711{
712 int i = storageIndex; // shortcut
713 int wdt = 11; // width of columns for print out
714
715 if (i > (int)partID.size() || i < 0)
716 {std::cout << "Invalid index" << std::endl; return;}
717
718 if (i+1 > n) // safety
719 {std::cout << "Index chosen is greater than maximum index of: " << n-1 << std::endl; return;}
720
721 // print out regarding the trajectory generally
722 std::cout << "Storage index " << std::setw(wdt) << i
723 << ", PDG ID " << std::setw(wdt) << partID[i]
724 << ", Track ID " << std::setw(wdt) << trackID[i]
725 << ", Parent ID " << std::setw(wdt) << parentID[i] << std::endl;
726 std::cout << "Created by Track ID " << parentID[i] << ", with storage index " << parentIndex[i] << ", and at step index " << parentStepIndex[i] << std::endl;
727
728 // print out regarding each step of the trajectory
729 std::cout << std::setw(wdt) << "step ind" << " "
730 << std::setw(wdt) << "prePrcT" << " " << std::setw(wdt) << "prePrcST" << " "
731 << std::setw(wdt) << "pstPrcT" << " " << std::setw(wdt) << "pstPrcST" << " "
732 << std::setw(wdt) << "X" << " " << std::setw(wdt) << "Y" << " "
733 << std::setw(wdt) << "Z" << " " << std::setw(wdt) << "E" << " "
734 << std::setw(wdt) << "p" << " " << std::setw(wdt) << "p_x" << " "
735 << std::setw(wdt) << "p_y" << " " << std::setw(wdt) << "p_z" << " "
736 << std::setw(wdt) << "t" << std::endl;
737
738 for (size_t j=0; j<XYZ[i].size(); ++j)
739 {
740 std::cout << std::setw(wdt) << j << " "
741 << std::setw(wdt) << preProcessTypes[i][j] << " " << std::setw(wdt) << preProcessSubTypes[i][j] << " "
742 << std::setw(wdt) << postProcessTypes[i][j] << " " << std::setw(wdt) << postProcessSubTypes[i][j] << " "
743 << std::setw(wdt) << XYZ[i][j].X() << " " << std::setw(wdt) << XYZ[i][j].Y() << " "
744 << std::setw(wdt) << XYZ[i][j].Z() << " " << std::setw(wdt) << energyDeposit[i][j] << " "
745 << std::setw(wdt) << PXPYPZ[i][j].Mag() << " " << std::setw(wdt) << PXPYPZ[i][j].X() << " "
746 << std::setw(wdt) << PXPYPZ[i][j].Y() << " " << std::setw(wdt) << PXPYPZ[i][j].Z() << " "
747 << std::setw(wdt) << T[i][j] << std::endl;
748 }
749}
750
751bool BDSOutputROOTEventTrajectory::parentIsPrimary(int trackIDIn) const
752{
753 // prevent a bad access
754 if (trackID_trackIndex.find(trackIDIn) == trackID_trackIndex.end())
755 {
756 std::cout << "No such track ID" << std::endl;
757 return false;
758 }
759
760 unsigned int storageIndex = (unsigned int)trackID_trackIndex.at(trackIDIn);
761 unsigned int parentStorageIndex = parentIndex[storageIndex];
762 return parentID[parentStorageIndex] == 0;
763}
764
765std::ostream& operator<< (std::ostream& out, BDSOutputROOTEventTrajectory const &t)
766{
767 for (int i=0; i< (int)t.preProcessTypes.size();++i)
768 {
769 for (int j=0; j< (int)t.preProcessTypes[i].size(); ++j)
770 {
771 //if(t.preProcessTypes[i][j] != 1 && t.preProcessTypes[i][j] != 7)
772 //{
773 out << i << " " << j
774 << " " << t.preProcessTypes[i][j] << " " << t.preProcessSubTypes[i][j]
775 << " " << t.postProcessTypes[i][j] << " " << t.postProcessSubTypes[i][j]
776 << " " << t.preWeights[i][j] << " " << t.postWeights[i][j]
777 << " " << t.energyDeposit[i][j] << " " << t.T[i][j]
778 << std::endl;
779 //}
780 }
781 }
782 return out;
783}
Extra G4Navigator to get coordinate transforms.
G4VPhysicalVolume * LocateGlobalPointAndSetup(const G4ThreeVector &point, const G4ThreeVector *direction=nullptr, const G4bool pRelativeSearch=true, const G4bool ignoreDirection=true, G4bool useCurvilinear=true) const
A wrapper for the underlying static navigator instance located within this class.
Structure to record a trajectory point.
Structure to record a trajectory.
std::vector< std::vector< int > > nElectrons
Ion trajectory information.
std::vector< std::vector< int > > charge
Link trajectory information.
std::vector< std::vector< TVector3 > > pxpypz
Local coordinates.
std::vector< std::vector< bool > > isIon
Ion trajectory information.
virtual void Flush()
add comment to avoid warning (no need to make persistent, see issue #191)
void FlushLocal()
Non-virtual version for initialising members.
void FillIndividualTrajectory(IndividualTrajectory &itj, BDSTrajectory *traj, int i, const std::map< G4Material *, short int > &materialToID) const
BDSAuxiliaryNavigator * auxNavigator
Required to find beamline index careful including in streamer.
std::vector< std::vector< double > > mass
Link trajectory information.
std::vector< std::vector< int > > ionZ
Ion trajectory information.
std::vector< std::vector< TVector3 > > xyz
Local coordinates.
std::vector< std::vector< int > > turnsTaken
Link trajectory information.
std::vector< std::vector< double > > rigidity
Link trajectory information.
std::vector< std::vector< int > > ionA
Ion trajectory information.
std::vector< std::vector< double > > kineticEnergy
Link trajectory information.
BDSPhysicalVolumeInfo * GetInfo(G4VPhysicalVolume *logicalVolume, G4bool isTunnel=false)
static BDSPhysicalVolumeInfoRegistry * Instance()
Singleton accessor.
A class holding any information pertaining to a particular physical volume in a BDSIM geant4 model.
G4int GetBeamlineIndex() const
Accessor.
Double map of trajectories to bitset of which filters matched whether to store them.
A Point in a trajectory with extra information.
G4double GetKineticEnergy() const
Accessor for the extra information links.
G4int GetCharge() const
Accessor for the extra information links.
G4double GetPreGlobalTime() const
Accessor.
G4int GetPostProcessType() const
Accessor.
G4ThreeVector GetMomentumLocal() const
Accessor.
G4int GetPreProcessSubType() const
Accessor.
G4bool GetIsIon() const
Accessor for the extra information ions.
G4double GetPreWeight() const
Accessor.
G4double GetRigidity() const
Accessor for the extra information links.
G4int GetTurnsTaken() const
Accessor for the extra information links.
G4double GetEnergyDeposit() const
Accessor.
G4double GetMass() const
Accessor for the extra information links.
G4double GetPreS() const
Accessor.
G4int GetPreProcessType() const
Accessor.
G4int GetIonZ() const
Accessor for the extra information ions.
G4ThreeVector GetPositionLocal() const
Accessor for the extra information local.
G4double GetPostWeight() const
Accessor.
G4int GetPostProcessSubType() const
Accessor.
G4int GetNElectrons() const
Accessor for the extra information ions.
G4int GetIonA() const
Accessor for the extra information ions.
G4Material * GetMaterial() const
Accessor.
G4ThreeVector GetPreMomentum() const
Accessor.
Trajectory information from track including last scatter etc.
virtual int GetPointEntries() const
Get number of trajectory points in this trajectory.
void SetTrajIndex(G4int trajIndexIn)
void SetParentStepIndex(G4int parentStepIndexIn)
The index of the step along the parent trajectory from which this one was created.
virtual G4VTrajectoryPoint * GetPoint(G4int i) const
Access a point - use this class's container.
void SetParentIndex(G4int parentIndexIn)
G4int GetDepth() const
Depth in the tree. Will be filled later once all trajectories are created and sorted.
Temporary structure for an individual trajectory used to convert types.