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