LDMX Software
TargetBremFilter.cxx
1/*~~~~~~~~~~~~~*/
2/* Biasing */
3/*~~~~~~~~~~~~~*/
4#include "Biasing/TargetBremFilter.h"
5
6/*~~~~~~~~~~~~*/
7/* Geant4 */
8/*~~~~~~~~~~~~*/
9#include "G4Electron.hh"
10#include "G4EventManager.hh"
11#include "G4RunManager.hh"
12
13/*~~~~~~~~~~~~~*/
14/* SimCore */
15/*~~~~~~~~~~~~~*/
16#include "SimCore/G4User/PtrRetrieval.h"
17#include "SimCore/UserEventInformation.h"
18#include "SimCore/UserTrackInformation.h"
19
20namespace biasing {
21
22TargetBremFilter::TargetBremFilter(const std::string& name,
24 : simcore::UserAction(name, parameters) {
26 parameters.getParameter<double>("recoil_max_p_threshold");
28 parameters.getParameter<double>("brem_min_energy_threshold");
29 killRecoil_ = parameters.getParameter<bool>("kill_recoil_track");
30}
31
33
34G4ClassificationOfNewTrack TargetBremFilter::ClassifyNewTrack(
35 const G4Track* track, const G4ClassificationOfNewTrack& currentTrackClass) {
36 // get the PDGID of the track.
37 G4int pdgID = track->GetParticleDefinition()->GetPDGEncoding();
38
39 // Get the particle type.
40 G4String particleName = track->GetParticleDefinition()->GetParticleName();
41
42 // Use current classification by default so values from other plugins are not
43 // overridden.
44 G4ClassificationOfNewTrack classification = currentTrackClass;
45
46 if (track->GetTrackID() == 1 && pdgID == 11) {
47 return fWaiting;
48 }
49
50 return classification;
51}
52
53void TargetBremFilter::stepping(const G4Step* step) {
54 // Get the track associated with this step.
55 auto track{step->GetTrack()};
56
57 // Only process the primary electron track
58 if (track->GetParentID() != 0) return;
59
60 // Get the PDG ID of the track and make sure it's an electron. If
61 // another particle type is found, thrown an exception.
62 if (auto pdgID{track->GetParticleDefinition()->GetPDGEncoding()}; pdgID != 11)
63 return;
64
65 // Get the region the particle is currently in. Continue processing
66 // the particle only if it's in the target region.
67 static auto target_region =
68 simcore::g4user::ptrretrieval::getRegion("target");
69 if (!target_region) {
70 ldmx_log(warn) << "Region 'target' not found in Geant4 region store";
71 }
72 auto phy_vol{track->GetVolume()};
73 auto log_vol{phy_vol ? phy_vol->GetLogicalVolume() : nullptr};
74 auto track_region{log_vol ? log_vol->GetRegion() : nullptr};
75 if (track_region != target_region) return;
76
77 /*
78 std::cout << "[TargetBremFilter] : Stepping primary electron in 'target'
79 region into "
80 << track->GetNextVolume()->GetName()
81 << std::endl;
82 */
83
96 auto recoil_physical_volume =
97 simcore::g4user::ptrretrieval::getPhysicalVolume("recoil_PV");
98 auto world_physical_volume =
99 simcore::g4user::ptrretrieval::getPhysicalVolume("World_PV");
100 if (!recoil_physical_volume) {
101 ldmx_log(warn) << "Volume 'recoil_PV' not found in Geant4 volume store";
102 }
103 if (!world_physical_volume) {
104 ldmx_log(warn) << "Volume 'World_PV' not found in Geant4 volume store";
105 }
106 auto track_volume = track->GetNextVolume();
107 if (track_volume == recoil_physical_volume or
108 track_volume == world_physical_volume) {
109 // If the recoil electron
110 if (track->GetMomentum().mag() >= recoilMaxPThreshold_) {
111 track->SetTrackStatus(fKillTrackAndSecondaries);
112 G4RunManager::GetRunManager()->AbortEvent();
113 return;
114 }
115
116 // Get the electron secondries
117 bool hasBremCandidate = false;
118 if (auto secondaries = step->GetSecondary(); secondaries->size() == 0) {
119 track->SetTrackStatus(fKillTrackAndSecondaries);
120 G4RunManager::GetRunManager()->AbortEvent();
121 return;
122 } else {
123 for (auto& secondary_track : *secondaries) {
124 auto electron = G4Electron::Definition();
125 auto ebrem_process =
126 simcore::g4user::ptrretrieval::getProcess(electron, "eBrem");
127 if (!ebrem_process) {
128 ldmx_log(warn) << "Process 'eBrem' not found in Geant4 process store";
129 }
130
131 if (ebrem_process &&
132 secondary_track->GetKineticEnergy() > bremEnergyThreshold_) {
133 auto trackInfo{simcore::UserTrackInformation::get(secondary_track)};
134 trackInfo->tagBremCandidate();
135
137
138 hasBremCandidate = true;
139 }
140 }
141 }
142
143 if (!hasBremCandidate) {
144 track->SetTrackStatus(fKillTrackAndSecondaries);
145 G4RunManager::GetRunManager()->AbortEvent();
146 return;
147 }
148
149 /*
150 std::cout << "[TargetBremFilter] : Found brem candidate" << std::endl;
151 */
152
153 // Check if the recoil electron should be killed. If not, postpone
154 // its processing until the brem gamma has been processed.
155 if (killRecoil_)
156 track->SetTrackStatus(fStopAndKill);
157 else
158 track->SetTrackStatus(fSuspend);
159
160 } else if (step->GetPostStepPoint()->GetKineticEnergy() == 0) {
161 track->SetTrackStatus(fKillTrackAndSecondaries);
162 G4RunManager::GetRunManager()->AbortEvent();
163 return;
164 }
165}
166
168} // namespace biasing
169
170DECLARE_ACTION(biasing, TargetBremFilter)
bool killRecoil_
Flag indicating if the recoil electron track should be killed.
void EndOfEventAction(const G4Event *) override
Method called at the end of every event.
TargetBremFilter(const std::string &name, framework::config::Parameters &parameters)
Constructor.
void stepping(const G4Step *step) override
Implement the stepping action which performs the target volume biasing.
G4ClassificationOfNewTrack ClassifyNewTrack(const G4Track *aTrack, const G4ClassificationOfNewTrack &currentTrackClass) override
Classify a new track which postpones track processing.
double recoilMaxPThreshold_
Recoil electron threshold.
double bremEnergyThreshold_
Brem gamma energy treshold.
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:29
UserEventInformation * getEventInfo() const
Get a handle to the event information.
void incBremCandidateCount()
Increment the number of brem candidates in an event.
static UserTrackInformation * get(const G4Track *track)
get