LDMX Software
EcalSD.cxx
2
3// Geant4
4#include "G4Polyhedron.hh"
5#include "G4Step.hh"
6#include "G4StepPoint.hh"
7#include "G4VSolid.hh"
8
9/*~~~~~~~~~~~~~~*/
10/* DetDescr */
11/*~~~~~~~~~~~~~~*/
13#include "DetDescr/EcalID.h"
14
15namespace simcore {
16
17const std::string EcalSD::COLLECTION_NAME = "EcalSimHits";
18
19EcalSD::EcalSD(const std::string& name, simcore::ConditionsInterface& ci,
21 : SensitiveDetector(name, ci, p) {
22 enableHitContribs_ = p.getParameter<bool>("enableHitContribs");
23 compressHitContribs_ = p.getParameter<bool>("compressHitContribs");
24}
25
26G4bool EcalSD::ProcessHits(G4Step* aStep, G4TouchableHistory*) {
27 static const int layer_depth = 2; // index depends on GDML implementation
28 const auto& geometry = getCondition<ldmx::EcalGeometry>(
29 ldmx::EcalGeometry::CONDITIONS_OBJECT_NAME);
30
31 // Get the edep from the step.
32 G4double edep = aStep->GetTotalEnergyDeposit();
33
34 // Skip steps with no energy dep which come from non-Geantino particles.
35 if (edep == 0.0 and not isGeantino(aStep)) {
36 if (verboseLevel > 2) {
37 G4cout << "CalorimeterSD skipping step with zero edep." << G4endl
38 << G4endl;
39 }
40 return false;
41 }
42
43 // Compute the hit position
44 G4StepPoint* prePoint = aStep->GetPreStepPoint();
45 G4StepPoint* postPoint = aStep->GetPostStepPoint();
46 G4ThreeVector position =
47 0.5 * (prePoint->GetPosition() + postPoint->GetPosition());
48
49 // Create the ID for the hit.
50 int cpynum{0}; // Initialize cpynum to 0
51
52 auto preStepPoint = aStep->GetPreStepPoint();
53 if (preStepPoint) {
54 auto touchableHandle = preStepPoint->GetTouchableHandle();
55 if (touchableHandle) {
56 auto history = touchableHandle->GetHistory();
57 if (history) {
58 auto volume = history->GetVolume(layer_depth);
59 if (volume) {
60 cpynum = volume->GetCopyNo();
61 }
62 }
63 }
64 }
65 int layerNumber;
66 layerNumber = cpynum / 7;
67 int module_position = cpynum % 7;
79 // fastest, but need to trust module number between GDML and EcalGeometry
80 // match
81 ldmx::EcalID id =
82 geometry.getID(position[0], position[1], layerNumber, module_position);
83
84 // medium, only need to trust z-layer positions in GDML and EcalGeometry match
85 // helpful for debugging any issues where transverse position is not
86 // matching between the GDML and EcalGeometry
87 // ldmx::EcalID id = geometry.getID(position[0], position[1], layerNumber);
88
89 // slowest, completely rely on EcalGeometry
90 // this is helpful for validating the EcalGeometry implementation and
91 // configuration since this will be called with any hit position that
92 // is inside of the configured SD volumes from Geant4's point of view
93 // ldmx::EcalID id = geometry.getID(position[0], position[1], position[2]);
94
95 if (hits_.find(id) == hits_.end()) {
96 // hit in empty cell
97 auto& hit = hits_[id];
98 hit.setID(id.raw());
108 auto [x, y, z] = geometry.getPosition(id);
109 hit.setPosition(x, y, z);
110 }
111
112 auto& hit = hits_[id];
113
114 // hit variables
115 auto track = aStep->GetTrack();
116 auto time = track->GetGlobalTime();
117 auto track_id = track->GetTrackID();
118 auto pdg = track->GetParticleDefinition()->GetPDGEncoding();
119
120 if (enableHitContribs_) {
121 int contrib_i = hit.findContribIndex(track_id, pdg);
122 if (compressHitContribs_ and contrib_i != -1) {
123 hit.updateContrib(contrib_i, edep, time);
124 } else {
125 hit.addContrib(getTrackMap().findIncident(track_id), track_id, pdg, edep,
126 time);
127 }
128 } else {
129 // no hit contribs and hit already exists
130 hit.setEdep(hit.getEdep() + edep);
131 if (time < hit.getTime() or hit.getTime() == 0) {
132 hit.setTime(time);
133 }
134 }
135
136 return true;
137}
138
140 // squash hits into list
141 std::vector<ldmx::SimCalorimeterHit> hits;
142 hits.reserve(hits_.size());
143 for (const auto& [id, hit] : hits_) hits.push_back(hit);
144 event.add(COLLECTION_NAME, hits);
145}
146
147} // namespace simcore
148
149DECLARE_SENSITIVEDETECTOR(simcore::EcalSD)
Class that translates raw positions of ECal module hits into cells in a hexagonal readout.
Class that defines an ECal detector ID with a cell number.
Class defining an ECal sensitive detector using an EcalHexReadout to create the hits.
Implements an event buffer system for storing event data.
Definition Event.h:41
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:27
T getParameter(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:89
Extension of DetectorID providing access to ECal layers and cell numbers in a hex grid.
Definition EcalID.h:20
Handle to the conditions system, provided at construction to classes which require it.
ECal sensitive detector that uses an EcalHexReadout to create the hits.
Definition EcalSD.h:30
static const std::string COLLECTION_NAME
Name of output collection of hits.
Definition EcalSD.h:33
bool compressHitContribs_
compress hit contribs
Definition EcalSD.h:85
std::map< ldmx::EcalID, ldmx::SimCalorimeterHit > hits_
map of hits to add to the event (will be squashed)
Definition EcalSD.h:81
EcalSD(const std::string &name, simcore::ConditionsInterface &ci, const framework::config::Parameters &p)
Class constructor.
Definition EcalSD.cxx:19
virtual void saveHits(framework::Event &event) override
Add our hits to the event bus.
Definition EcalSD.cxx:139
bool enableHitContribs_
enable hit contribs
Definition EcalSD.h:83
G4bool ProcessHits(G4Step *aStep, G4TouchableHistory *ROhist) override
Process steps to create hits.
Definition EcalSD.cxx:26
Dynamically loaded Geant4 SensitiveDetector for saving hits in specific volumes within the simulation...
bool isGeantino(const G4Step *step) const
Check if the passed step is a step of a geantino.
const TrackMap & getTrackMap() const
Get a handle to the current track map.
int findIncident(int trackID) const
Find a trajectory's nearest parent that is incident on the calorimeter region.
Definition TrackMap.cxx:35