LDMX Software
TrackMap.cxx
1#include "SimCore/TrackMap.h"
2
3// Geant4
4#include "G4Event.hh"
5#include "G4EventManager.hh"
6
7namespace simcore {
8
9bool TrackMap::isDescendant(int trackID, int ancestorID,
10 int maximum_depth) const {
11 int current_depth{0};
12 int current_track{trackID};
13 // Walk the tree until we either no longer have a parent or we reach the
14 // desired depth
15 while (current_depth < maximum_depth &&
16 (ancestry_.find(current_track) != ancestry_.end())) {
17 // See if we have encountered the parent of the current track
18 //
19 // operator[] is not const, so we need to use at()
20 current_track = ancestry_.at(current_track).first;
21 if (current_track == ancestorID) {
22 // If one of the parents is the track of interest, we are done!
23 return true;
24 }
25 current_depth++;
26 }
27 return false;
28}
29void TrackMap::insert(const G4Track* track) {
30 ancestry_[track->GetTrackID()] =
31 std::make_pair(track->GetParentID(), isInCalorimeterRegion(track));
32 descendents_[track->GetParentID()].push_back(track->GetTrackID());
33}
34
35int TrackMap::findIncident(G4int trackID) const {
36 int currTrackID = trackID;
37 bool foundIncident{false};
38 while (not foundIncident) {
39 auto& [parentID, inCalRegion] = ancestry_.at(currTrackID);
40 if (not inCalRegion or parentID == 0) {
41 // current track ID is nearest ancestor
42 // originating outside cal region
43 // or is a primary particle
44 foundIncident = true;
45 } else {
46 // still in cal region, keep going
47 currTrackID = parentID;
48 }
49 }
50 return currTrackID;
51}
52
53void TrackMap::save(const G4Track* track) {
54 // create sim particle in map, keep reference to the newly created particle
55 ldmx::SimParticle& particle{particle_map_[track->GetTrackID()]};
56
57 // TODO: default gen status?
58 particle.setGenStatus(0);
59
60 // Update the gen status from the primary particle.
61 if (track->GetDynamicParticle()->GetPrimaryParticle() != nullptr) {
62 G4VUserPrimaryParticleInformation* primaryInfo =
63 track->GetDynamicParticle()->GetPrimaryParticle()->GetUserInformation();
64 if (primaryInfo != nullptr) {
65 particle.setGenStatus(
66 ((UserPrimaryParticleInformation*)primaryInfo)->getHepEvtStatus());
67 }
68 }
69
70 auto particle_def{track->GetDefinition()};
71
72 particle.setPdgID(particle_def->GetPDGEncoding());
73 particle.setCharge(particle_def->GetPDGCharge());
74 particle.setMass(track->GetDynamicParticle()->GetMass());
75 particle.setEnergy(track->GetVertexKineticEnergy() +
76 track->GetDynamicParticle()->GetMass());
77
78 auto track_info{UserTrackInformation::get(track)};
79 particle.setVertexVolume(track_info->getVertexVolume());
80
81 auto vert{track->GetVertexPosition()};
82 particle.setVertex(vert.x(), vert.y(), vert.z());
83 particle.setTime(track_info->getVertexTime());
84
85 auto init_momentum{track_info->getInitialMomentum()};
86 particle.setMomentum(init_momentum.x(), init_momentum.y(), init_momentum.z());
87
88 const G4VProcess* process{track->GetCreatorProcess()};
89 if (process) {
90 const G4String& name{process->GetProcessName()};
91 particle.setProcessType(ldmx::SimParticle::findProcessType(name));
92 } else {
93 if (track->GetParentID() == 0) {
94 particle.setProcessType(ldmx::SimParticle::ProcessType::Primary);
95 } else {
96 particle.setProcessType(ldmx::SimParticle::ProcessType::unknown);
97 }
98 }
99
100 // track's current kinematics is its end point kinematics
101 // because we are assuming this track is being stopped/killed
102
103 auto momentum{track->GetMomentum()};
104 particle.setEndPointMomentum(momentum.x(), momentum.y(), momentum.z());
105
106 auto end_pt{track->GetPosition()};
107 particle.setEndPoint(end_pt.x(), end_pt.y(), end_pt.z());
108}
109
111 for (auto& [id, particle] : particle_map_) {
112 particle.addParent(ancestry_.at(id).first);
113
120 for (auto& child : descendents_[id]) {
121 particle.addDaughter(child);
122 }
123 }
124}
125
127 ancestry_.clear();
128 descendents_.clear();
129 particle_map_.clear();
130}
131
132bool TrackMap::isInCalorimeterRegion(const G4Track* track) const {
133 auto region{track->GetLogicalVolumeAtVertex()->GetRegion()->GetName()};
134 return region.contains("Calorimeter");
135}
136
137} // namespace simcore
Class representing a simulated particle.
Definition SimParticle.h:23
void setGenStatus(const int &genStatus)
Set the generator status of this particle.
static ProcessType findProcessType(std::string processName)
Get the process type enum from a G4VProcess name.
void clear()
Clear the internal maps.
Definition TrackMap.cxx:126
std::unordered_map< int, std::pair< int, bool > > ancestry_
ancestry map of particles in event (child -> parent)
Definition TrackMap.h:132
std::unordered_map< int, std::vector< int > > descendents_
descendents map of particles in event (parent -> children)
Definition TrackMap.h:135
bool isDescendant(int trackID, int ancestorID, int maximum_depth) const
Check if the track with the given ID is a descendant of the track with the given ancestor ID up to a ...
Definition TrackMap.cxx:9
void save(const G4Track *track)
Add a track to be stored into output map.
Definition TrackMap.cxx:53
std::map< int, ldmx::SimParticle > particle_map_
map of SimParticles that will be stored
Definition TrackMap.h:138
bool isInCalorimeterRegion(const G4Track *track) const
Was the input track generated inside the calorimeter region?
Definition TrackMap.cxx:132
void traceAncestry()
Trace the ancestry for the particles that will be stored.
Definition TrackMap.cxx:110
void insert(const G4Track *track)
Add a record in the map for the input track.
Definition TrackMap.cxx:29
int findIncident(int trackID) const
Find a trajectory's nearest parent that is incident on the calorimeter region.
Definition TrackMap.cxx:35
Defines extra information attached to a Geant4 primary particle.
static UserTrackInformation * get(const G4Track *track)
get
const G4ThreeVector & getInitialMomentum() const
Get the initial momentum 3-vector of the track [MeV].