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#include "G4Track.hh"
7
8// Thread-local sensitive detector instance.
9// Constructor: initializes base logging, Geant4 SD name, and the hits collection name used for this detector.
11 const std::shared_ptr<GOptions>& goptions) :
13 G4VSensitiveDetector(sdName),
14 gHitsCollection(nullptr) {
15 log->info(2, FUNCTION_NAME, " for " + sdName);
16
17 // collectionName is a G4VSensitiveDetector G4CollectionNameVector.
18 // GEMC uses its own handling of hits; this is set primarily for compatibility with Geant4 conventions/examples.
19 std::string hitCollectionName = sdName + "__HitCollection";
20 collectionName.insert(hitCollectionName);
21
22 log->debug(CONSTRUCTOR, FUNCTION_NAME, " for " + sdName);
23}
24
25
26// Thread-local; called at the beginning of each event.
27// Allocates and registers the per-event hits collection and resets per-event caches.
28void GSensitiveDetector::Initialize(G4HCofThisEvent* g4hc) {
29 std::string sdName = GetName();
30 log->info(1, FUNCTION_NAME, sdName);
31
32 // Clearing the per-event hit-cell map (per-event hit identity cache).
33 hitsByCellKey.clear();
35
36 // Initializing gHitsCollection using the Geant4 G4THitsCollection constructor (expects detector and collection names).
37 gHitsCollection = new GHitsCollection(sdName, collectionName[0]);
38
39 // Add hits collection to the Geant4 event container.
40 // hcID is assigned by Geant4 and can be retrieved later by collection name.
41 auto hcID = G4SDManager::GetSDMpointer()->GetCollectionID(collectionName[0]);
42 g4hc->AddHitsCollection(hcID, gHitsCollection);
43
44 log->info(2, "Added collection id ", hcID, " to G4HCofThisEvent");
45}
46
47
48// Thread-local; called for each step in sensitive volumes.
49// Applies plugin filtering and touchable transformation, then creates new hits or updates existing hits.
50G4bool GSensitiveDetector::ProcessHits(G4Step* thisStep, [[maybe_unused]] G4TouchableHistory* g4th) {
51 // If there is a decision to skip this hit based on deposited energy, return immediately.
52
53 double depe = thisStep->GetTotalEnergyDeposit();
54
55 if (digitization_routine->decisionToSkipHit(depe, thisStep)) { return true; }
56
57 // The hits collection should have been created in Initialize().
58 if (gHitsCollection == nullptr) { log->error(ERR_NOCOLLECTION, "No hit collection found"); }
59
60 // Get the vector of processed touchables returned by the digitization routine.
61 // If not overridden by the plugin, the base implementation typically returns a vector with the input touchable only.
62 std::vector<std::shared_ptr<GTouchable>> thisStepProcessedTouchables =
63 digitization_routine->processTouchable(getGTouchable(thisStep), thisStep);
64
65 auto hcsize = gHitsCollection->GetSize();
66
67 log->info(2, FUNCTION_NAME, " for ", GetName(),
68 " with ", std::to_string(thisStepProcessedTouchables.size()), " touchable(s), edep: ",
69 std::to_string(depe), ", Hit collection size: ", hcsize);
70
71 for (auto thisGTouchable : thisStepProcessedTouchables) {
72 // Track id is attached to the touchable to keep hit identity consistent across updates.
73 thisGTouchable->assignTrackId(thisStep->GetTrack()->GetTrackID());
74 thisGTouchable->assignPId(thisStep->GetTrack()->GetDefinition()->GetPDGEncoding());
75
76 // Create-or-update through the per-event hit-cell map: the key has the same
77 // semantics as GTouchable::operator== (identity + type discriminator).
78 auto [it, isNewCell] = hitsByCellKey.try_emplace(thisGTouchable->cellKey(), nullptr);
79 if (isNewCell) {
80 log->info(2, " ✅ new GTouchable for ", GetName(), ": ", thisGTouchable->getIdentityString());
81 it->second = new GHit(thisGTouchable, thisStep);
82 gHitsCollection->insert(it->second);
83 }
84 else {
85 log->info(2, " ❌ existing GTouchable for ", GetName(), ": ", thisGTouchable->getIdentityString());
86 it->second->addHitInfos(thisStep);
87 }
88 }
89
90 // Plugins may mark a sensitive element as terminal. Apply the status only after every
91 // processed touchable has stored this step, so terminating a track never drops its hit.
92 if (digitization_routine->shouldStopTrackAfterHit(thisStep)) {
93 thisStep->GetTrack()->SetTrackStatus(fStopAndKill);
94 }
95
96 return true;
97}
98
99
100// Thread-local end-of-event hook.
101// At this stage, Geant4 owns the event hit container that references the hits collection.
102void GSensitiveDetector::EndOfEvent([[maybe_unused]] G4HCofThisEvent* g4hc) {
103 log->info(1, "GSensitiveDetector::EndOfEvent for " + GetName());
104}
GBase(const std::shared_ptr< GOptions > &gopt, std::string logger_name="")
std::shared_ptr< GLogger > log
static void clearTrackVertexCache()
GSensitiveDetector(const std::string &sdName, const std::shared_ptr< GOptions > &goptions)
Constructs a sensitive detector instance for a given detector name.
Definition gsd.cc:10
void EndOfEvent(G4HCofThisEvent *g4HitCollection) override
End-of-event hook called by Geant4.
Definition gsd.cc:102
void Initialize(G4HCofThisEvent *g4hc) override
Per-event initialization hook called by Geant4.
Definition gsd.cc:28
G4bool ProcessHits(G4Step *thisStep, G4TouchableHistory *g4th) override
Processes a Geant4 step and creates or updates hits in the current hits collection.
Definition gsd.cc:50
#define FUNCTION_NAME
CONSTRUCTOR
G4THitsCollection< GHit > GHitsCollection
Convenience alias for the Geant4 hits collection used by this module.
Definition gsd.h:76
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:43
constexpr const char * GSENSITIVE_LOGGER
Logger name used by this module.
Definition gsd.h:50