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