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