gsd
Loading...
Searching...
No Matches
gsd.cc
Go to the documentation of this file.
1// gemc
2#include "gsd.h"
3
4// geant4
5#include "G4SDManager.hh"
6
7// Thread-local sensitive detector instance.
8// Constructor: initializes base logging, Geant4 SD name, and the hits collection name used for this detector.
9GSensitiveDetector::GSensitiveDetector(const std::string& sdName,
10 const std::shared_ptr<GOptions>& goptions) :
12 G4VSensitiveDetector(sdName) {
13 log->info(2, FUNCTION_NAME, " for " + sdName);
14
15 // collectionName is a G4VSensitiveDetector G4CollectionNameVector.
16 // GEMC uses its own handling of hits; this is set primarily for compatibility with Geant4 conventions/examples.
17 std::string hitCollectionName = sdName + "__HitCollection";
18 collectionName.insert(hitCollectionName);
19
20 log->debug(CONSTRUCTOR, FUNCTION_NAME, " for " + sdName);
21}
22
23
24// Thread-local; called at the beginning of each event.
25// Allocates and registers the per-event hits collection and resets per-event caches.
26void GSensitiveDetector::Initialize(G4HCofThisEvent* g4hc) {
27 std::string sdName = GetName();
28 log->info(1, FUNCTION_NAME, sdName);
29
30 // Hit content definition is read once per event from the digitization routine.
31 gHitBitSet = digitization_routine->readoutSpecs->getHitBitSet();
32
33 // Clearing touchableVector at the start of the event (per-event hit identity cache).
34 touchableVector.clear();
36
37 // Initializing gHitsCollection using the Geant4 G4THitsCollection constructor (expects detector and collection names).
38 gHitsCollection = new GHitsCollection(sdName, collectionName[0]);
39
40 // Add hits collection to the Geant4 event container.
41 // hcID is assigned by Geant4 and can be retrieved later by collection name.
42 auto hcID = G4SDManager::GetSDMpointer()->GetCollectionID(collectionName[0]);
43 g4hc->AddHitsCollection(hcID, gHitsCollection);
44
45 log->info(2, "Added collection id ", hcID, " to G4HCofThisEvent");
46}
47
48
49// Thread-local; called for each step in sensitive volumes.
50// Applies plugin filtering and touchable transformation, then creates new hits or updates existing hits.
51G4bool GSensitiveDetector::ProcessHits(G4Step* thisStep, [[maybe_unused]] G4TouchableHistory* g4th) {
52 // If there is a decision to skip this hit based on deposited energy, return immediately.
53
54 double depe = thisStep->GetTotalEnergyDeposit();
55
56 if (digitization_routine->decisionToSkipHit(depe)) { return true; }
57
58 // The hits collection should have been created in Initialize().
59 if (gHitsCollection == nullptr) { log->error(ERR_NOCOLLECTION, "No hit collection found"); }
60
61 // Get the vector of processed touchables returned by the digitization routine.
62 // If not overridden by the plugin, the base implementation typically returns a vector with the input touchable only.
63 std::vector<std::shared_ptr<GTouchable>> thisStepProcessedTouchables =
64 digitization_routine->processTouchable(getGTouchable(thisStep), thisStep);
65
66 auto hcsize = gHitsCollection->GetSize();
67
68 log->info(2, FUNCTION_NAME, " for ", GetName(),
69 " with ", std::to_string(thisStepProcessedTouchables.size()), " touchable(s), edep: ",
70 std::to_string(depe), ", Hit collection size: ", hcsize);
71
72 // If a new touchable is created, create a new GHit.
73 // Otherwise, retrieve the existing hit and append step information according to gHitBitSet.
74 for (auto thisGTouchable : thisStepProcessedTouchables) {
75 // Track id is attached to the touchable to keep hit identity consistent across updates.
76 thisGTouchable->assignTrackId(thisStep->GetTrack()->GetTrackID());
77 thisGTouchable->assignPId(thisStep->GetTrack()->GetDefinition()->GetPDGEncoding());
78
79 if (isThisANewTouchable(thisGTouchable)) {
80 // New hit: constructor fills initial step information based on gHitBitSet.
81 gHitsCollection->insert(new GHit(thisGTouchable, gHitBitSet, thisStep));
82 }
83 else {
84 // Existing hit: locate it and add additional information from this step according to gHitBitSet.
85 GHit* existingHit = getHitInHitCollectionUsingTouchable(thisGTouchable);
86 if (existingHit != nullptr) {
87 existingHit->addHitInfosForBitset(gHitBitSet, thisStep);
88 }
89 }
90 }
91
92 return true;
93}
94
95
96// Checks whether a touchable has already been seen in this event.
97// If not present, it is appended to the per-event cache.
98bool GSensitiveDetector::isThisANewTouchable(const std::shared_ptr<GTouchable>& thisTouchable) {
99 log->info(2, "GSensitiveDetector::isThisANewTouchable for " + GetName(),
100 " with touchable: " + thisTouchable->getIdentityString());
101
102 if (thisTouchable->exists_in_vector(touchableVector)) {
103 log->info(2, " ❌ not a new GTouchable, it is found, retrieving hit...");
104 return false; // Not a new touchable.
105 }
106 else {
107 log->info(2, " ✅ yes, new GTouchable. Adding it to touchableVector.");
108 touchableVector.push_back(*thisTouchable);
109 return true; // It's a new touchable.
110 }
111}
112
113
114// Linear search for the hit matching the provided touchable.
115// The collection is expected to contain a matching entry when called from ProcessHits().
116GHit* GSensitiveDetector::getHitInHitCollectionUsingTouchable(const std::shared_ptr<GTouchable>& gtouchable) {
117 for (unsigned int i = 0; i < gHitsCollection->GetSize(); i++) {
118 GHit* thisHit = (*gHitsCollection)[i];
119 const std::shared_ptr<GTouchable>& thisHitGTouchable = thisHit->getGTouchable();
120
121 if (*gtouchable == *thisHitGTouchable) {
122 log->info(2, "GSensitiveDetector::getHitInHitCollectionUsingTouchable for " + GetName() +
123 " found existing hit in collection for touchable: " + gtouchable->getIdentityString() +
124 " at index: " + std::to_string(i));
125 return thisHit;
126 }
127 }
128
130 "GHit not found in hit collection for touchable: " + gtouchable->getIdentityString(),
131 "in ", GetName());
132}
133
134
135// Thread-local end-of-event hook.
136// At this stage, Geant4 owns the event hit container that references the hits collection.
137void GSensitiveDetector::EndOfEvent([[maybe_unused]] G4HCofThisEvent* g4hc) {
138 log->info(1, "GSensitiveDetector::EndOfEvent for " + GetName());
139}
std::shared_ptr< GLogger > log
std::vector< std::shared_ptr< GTouchable > > processTouchable(std::shared_ptr< GTouchable > gtouchable, G4Step *thisStep)
std::shared_ptr< const GReadoutSpecs > readoutSpecs
virtual bool decisionToSkipHit(double energy)
void addHitInfosForBitset(HitBitSet hbs, const G4Step *thisStep)
static void clearTrackVertexCache()
std::shared_ptr< GTouchable > getGTouchable() const
void debug(debug_type type, Args &&... args) const
void info(int level, Args &&... args) const
void error(int exit_code, Args &&... args) const
HitBitSet getHitBitSet() const
GSensitiveDetector(const std::string &sdName, const std::shared_ptr< GOptions > &goptions)
Constructs a sensitive detector instance for a given detector name.
Definition gsd.cc:9
void EndOfEvent(G4HCofThisEvent *g4HitCollection) override
End-of-event hook called by Geant4.
Definition gsd.cc:137
void Initialize(G4HCofThisEvent *g4hc) override
Per-event initialization hook called by Geant4.
Definition gsd.cc:26
G4bool ProcessHits(G4Step *thisStep, G4TouchableHistory *g4th) override
Processes a Geant4 step and creates or updates hits in the current hits collection.
Definition gsd.cc:51
#define FUNCTION_NAME
CONSTRUCTOR
G4THitsCollection< GHit > GHitsCollection
Convenience alias for the Geant4 hits collection used by this module.
Definition gsd.h:73
Declares the GSensitiveDetector class and module-level constants.
constexpr int ERR_NOCOLLECTION
Error code used when the Geant4 hits collection is unexpectedly missing.
Definition gsd.h:40
constexpr int ERR_HITNOTFOUNDINCOLLECTION
Error code used when a hit is expected to exist but cannot be found in the current hit collection.
Definition gsd.h:35
constexpr const char * GSENSITIVE_LOGGER
Logger name used by this module.
Definition gsd.h:47