ghit
Loading...
Searching...
No Matches
ghit.cc
Go to the documentation of this file.
1// ghit
2#include "ghit.h"
3
4// glibrary
5#include "gutsConventions.h"
6
7// geant4
8#include "G4VVisManager.hh"
9#include "G4Circle.hh"
10#include "G4VisAttributes.hh"
11#include "Randomize.hh"
12
13// c++
14#include <algorithm>
15#include <set>
16
17using std::string;
18using std::vector;
19
20namespace {
21
22constexpr int opticalPhotonPid = -22; // Geant4 optical-photon PDG encoding.
23
24} // namespace
25
26std::atomic<int> GHit::globalHitCounter{0};
27thread_local std::map<int, G4ThreeVector> GHit::trackVertexById;
28thread_local std::map<int, int> GHit::pdgById;
29
30// MT definitions, as from:
31// https://twiki.cern.ch/twiki/bin/view/Geant4/QuickMigrationGuideForGeant4V10
32G4ThreadLocal G4Allocator<GHit>* GHitAllocator = nullptr;
33
34// See header for API docs.
35
36GHit::GHit(std::shared_ptr<GTouchable> gt,
37 const G4Step* thisStep,
38 const string& cScheme) :
39 G4VHit(),
40 colorSchema(cScheme),
41 gtouchable(gt) {
42 // Initialize per-step vectors if a step is provided.
43 if (thisStep) { addHitInfos(thisStep); }
44}
45
46bool GHit::is_same_hit(const GHit* hit) const {
47 if (!hit) // guard against nullptr
48 return false;
49
50 return *gtouchable == *(hit->getGTouchable());
51}
52
53vector<int> GHit::getTTID() const {
54 vector<int> ttid;
55 // Retrieve the identity vector from the associated GTouchable.
56 vector<GIdentifier> gids = getGID();
57 ttid.reserve(gids.size());
58 for (auto& gid : gids) {
59 // Push back the integer value of each identifier.
60 ttid.push_back(gid.getValue());
61 }
62 return ttid;
63}
64
65void GHit::Draw() {
66 auto visManager = G4VVisManager::GetConcreteInstance();
67 if (!visManager) return;
68
69 // Only care about schema if we are interactive.
70 setColorSchema();
71
72 // Check that globalPositions is not empty before accessing the first element.
73 if (globalPositions.empty()) return;
74
75 G4Circle circle(globalPositions[0]);
76 circle.SetFillStyle(G4Circle::filled);
77
78 double etot = getTotalEnergyDeposited();
79 const bool opticalPhotonHit = !pids.empty() && pids.front() == opticalPhotonPid;
80
81 if (opticalPhotonHit) {
82 circle.SetScreenSize(15);
83 circle.SetVisAttributes(G4VisAttributes(colour_passby));
84 }
85 else if (etot > 0) {
86 circle.SetScreenSize(50);
87 circle.SetVisAttributes(G4VisAttributes(colour_hit));
88 }
89 else if (etot == 0) {
90 circle.SetScreenSize(15);
91 circle.SetVisAttributes(G4VisAttributes(colour_passby));
92 circle.SetFillStyle(G4Circle::hashed);
93 }
94
95 visManager->Draw(circle);
96}
97
99 std::set<int> photonTrackIds;
100 const size_t entries = std::min(pids.size(), tids.size());
101
102 for (size_t index = 0; index < entries; ++index) {
103 if (pids[index] == opticalPhotonPid) { photonTrackIds.insert(tids[index]); }
104 }
105
106 return photonTrackIds.size();
107}
108
109bool GHit::setColorSchema() {
110 // For now, hard-code the color schema.
111 colour_hit = G4Colour(1.0, 0.0, 0.0); // Red for hits with energy.
112 colour_passby = G4Colour(0.0, 1.0, 0.0); // Green for pass-by.
113 return false;
114}
115
117 trackVertexById.clear();
118 pdgById.clear();
119}
120
122 // This function is for testing purposes only.
123 // It randomizes the hit's global position and energy deposition.
124 // It should not be used in production code.
125
126 invalidateCalculatedState();
127
128 // Generate nsteps+1 entries to preserve the existing behavior exactly.
129 for (int i = 0; i < nsteps + 1; ++i) {
130 globalPositions.emplace_back(G4UniformRand() * 100, G4UniformRand() * 100, G4UniformRand() * 100);
131 localPositions.emplace_back(G4UniformRand() * 10, G4UniformRand() * 10, G4UniformRand() * 10);
132 trackVertexPositions.emplace_back(G4UniformRand() * 100, G4UniformRand() * 100, G4UniformRand() * 100);
133 motherInfos.push_back({0, std::nullopt, std::nullopt});
134 times.emplace_back(G4UniformRand() * 100);
135 edeps.emplace_back(G4UniformRand() * 10);
136 pids.emplace_back(11);
137 tids.emplace_back(i);
138 momenta.emplace_back(G4UniformRand() * 100, G4UniformRand() * 100, G4UniformRand() * 100);
139 trackEs.emplace_back(G4UniformRand() * 1000);
140 processNames.emplace_back("placeholder");
141 }
142}
static void clearTrackVertexCache()
Clear the per-thread track vertex cache.
Definition ghit.cc:116
double getTotalEnergyDeposited() const
Get the total deposited energy across all recorded steps.
size_t nsteps() const
Number of recorded steps.
Definition ghit.h:355
std::vector< GIdentifier > getGID() const
Get the detector element identity.
Definition ghit.h:419
std::vector< int > getTTID() const
Get the touchable identity values as integers.
Definition ghit.cc:53
bool is_same_hit(const GHit *hit) const
Compare this hit against another hit by sensitive-element identity.
Definition ghit.cc:46
void randomizeHitForTesting(int nsteps)
Randomize internal vectors for test-only usage.
Definition ghit.cc:121
GHit(std::shared_ptr< GTouchable > gt, const G4Step *thisStep=nullptr, const std::string &cScheme="default")
Construct a hit container and optionally seed it from a step.
Definition ghit.cc:36
void Draw() override
Visualize the hit using Geant4 visualization primitives.
Definition ghit.cc:65
std::shared_ptr< GTouchable > getGTouchable() const
Get the associated sensitive-element descriptor.
Definition ghit.h:411
size_t getNumberOfOpticalPhotons() const
Count distinct optical-photon tracks recorded in this hit.
Definition ghit.cc:98
void addHitInfos(const G4Step *thisStep)
Append per-step information from a G4Step.
Definition addHitInfos.cc:9
G4ThreadLocal G4Allocator< GHit > * GHitAllocator
Definition ghit.cc:32