ATLAS Offline Software
Loading...
Searching...
No Matches
Geant4TruthIncident.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// class header
7
8// package includes
10
11#include "MCTruth/TrackHelper.h"
14
15// Units
16#include "GaudiKernel/PhysicalConstants.h"
17
18// HepMC includes
21
22// Geant4 includes
23#include "G4Step.hh"
24#include "G4Track.hh"
25#include "G4VProcess.hh"
26
27#include "G4TrackStatus.hh"
28#include "G4DynamicParticle.hh"
29#include "G4PrimaryParticle.hh"
30
31#include <limits>
32
33namespace {
34 HepMC::GenParticlePtr primaryGenParticle(const G4Track* track)
35 {
36 if (HepMC::GenParticlePtr primary = TrackHelper(track).GetPrimaryGenParticle()) {
37 return primary;
38 }
39
40 const G4DynamicParticle* dynamicParticle = track ? track->GetDynamicParticle() : nullptr;
41 G4PrimaryParticle* primaryParticle = dynamicParticle ? dynamicParticle->GetPrimaryParticle() : nullptr;
42 auto* primaryPartInfo = primaryParticle ?
43 dynamic_cast<PrimaryParticleInformation*>(primaryParticle->GetUserInformation()) : nullptr;
44 return primaryPartInfo ? primaryPartInfo->GetHepMCParticle() : nullptr;
45 }
46}
47
48/*
49 Comments:
50 what about parent particle surviving (e.g. bremstrahlung)
51
52
53 Existing code:
54 Simulation/G4Sim/SimHelpers/src/StepHelper.cxx
55 - provids convenient information of a G4Step
56 Simulation/G4Utilities/G4TruthStrategies/src/BremsstrahlungStrategy.cxx
57 - retrieves information from a G4Step (via StepHelper)
58 Simulation/G4Sim/MCTruth/MCTruth/TruthStrategy.h
59 - common base for different truth strategies
60 Simulation/G4Sim/MCTruth/src/TrackInformation.cxx
61 Simulation/G4Sim/MCTruth/src/TrackHelper.cxx
62 - store/manage barcode
63*/
64
65
68 ITruthIncident(geoID, step->GetSecondaryInCurrentStep()->size()), // switch to G4Step::GetNumberOfSecondariesInCurrentStep() once we're using G4 10.2 or later
69 m_positionSet(false),
70 m_position(),
71 m_step(step)
72{
73 // prepare children:
75
76 // calculate position:
77 const G4StepPoint *postStepPoint = m_step->GetPostStepPoint();
78 const G4ThreeVector &pos = postStepPoint->GetPosition();
79 const G4double time = postStepPoint->GetGlobalTime()*Gaudi::Units::c_light;
80 m_position.set( pos.x(), pos.y(), pos.z(), time );
81}
82
86
88 const G4VProcess *process = m_step->GetPostStepPoint()->GetProcessDefinedStep();
89 // TODO: need to check that G4ProcessSubTypes Match int
90 return process->GetProcessType();
91}
92
94 const G4VProcess *process = m_step->GetPostStepPoint()->GetProcessDefinedStep();
95 // TODO: need to check that G4ProcessSubTypes Match int
96 return process->GetProcessSubType();
97}
98
100 const G4ThreeVector & mom= m_step->GetPreStepPoint()->GetMomentum();
101 return mom.mag2();
102}
103
105 const G4ThreeVector & mom= m_step->GetPreStepPoint()->GetMomentum();
106 return mom.perp2();
107}
108
110 return (m_step->GetPreStepPoint()->GetKineticEnergy()/CLHEP::MeV);
111}
112
114 return m_step->GetTrack()->GetDefinition()->GetPDGEncoding();
115}
116
117int iGeant4::Geant4TruthIncident::parentBarcode() { // TODO Remove this method
118 auto parent = parentParticle();
119
120 return (parent) ? HepMC::barcode(parent) : HepMC::UNDEFINED_ID;
121}
122
124 auto parent = parentParticle();
125
126 return (parent) ? HepMC::uniqueID(parent) : HepMC::UNDEFINED_ID;
127}
128
130 auto parent = parentParticle();
131
132 return (parent) ? parent->status() : 0;
133}
134
136 TrackHelper tHelper(m_step->GetTrack());
137 TrackInformation *tInfo = tHelper.GetTrackInformation();
138 return tInfo ? tInfo->GetCurrentGenParticle() : nullptr;
139}
140
142 const G4Track *track = m_step->GetTrack();
143
144 // check if particle is a alive in G4 or in ISF
145 if ( particleAlive(track) ) {
146 return true;
147 } else {
148 return false;
149 }
150}
151
153 const G4Track *track = m_step->GetTrack();
154
155 // check if particle is a alive in G4 or in ISF
156 if ( !parentSurvivesIncident() ) {
157 return nullptr;
158 }
159
160 // internally cache the HepMC representation of the parent particle
161 // (to allow multiple calls to this method on the same instance)
163 // create new HepMC particle, using momentum and energy
164 // from G4DynamicParticle (which should be equivalent to postStep)
165 m_parentParticleAfterIncident = convert(track, newBarcode, false);
166
167 // store (new) hepmc particle in track's UserInformation
168 TrackHelper tHelper(track);
169 TrackInformation *tInfo = tHelper.GetTrackInformation();
170 if (tInfo) {
172 int regenerationNr = tInfo->GetRegenerationNr();
173 regenerationNr++;
174 tInfo->SetRegenerationNr(regenerationNr);
175 if ( tHelper.IsPrimary() ) {
177 }
178 }
179
180 } // <-- end if m_parentParticleAfterIncident is not filled
181
182
183 // return the HepMC particle representation of the parent
185}
186
187double iGeant4::Geant4TruthIncident::childP2(unsigned short i) const {
188 const G4ThreeVector & mom= m_children[i]->GetMomentum();
189 return mom.mag2();
190}
191
192const G4ThreeVector iGeant4::Geant4TruthIncident::childP(unsigned short i) const {
193 const G4ThreeVector & mom= m_children[i]->GetMomentum();
194 return mom;
195}
196
197double iGeant4::Geant4TruthIncident::childPt2(unsigned short i) const {
198 const G4ThreeVector & mom= m_children[i]->GetMomentum();
199 return mom.perp2();
200}
201
202double iGeant4::Geant4TruthIncident::childEkin(unsigned short i) const {
203 return (m_children[i]->GetKineticEnergy()/CLHEP::MeV);
204}
205
207 return m_children[i]->GetDefinition()->GetPDGEncoding();
208}
209
211 // the G4Track instance for the current child particle
212 const G4Track* track = m_children[index];
213 // This should be a *secondary* track. If it has a primary, it was a decay and
214 // we are running with quasi-stable particle simulation. Note that if the primary
215 // track is passed in as a secondary that survived the interaction, then this was
216 // *not* a decay and we should not treat it in this way
217 if (track->GetDynamicParticle() &&
218 track->GetDynamicParticle()->GetPrimaryParticle() &&
219 track->GetDynamicParticle()->GetPrimaryParticle()->GetUserInformation()){
220 // Then the new particle should use the same barcode as the old one!!
221 PrimaryParticleInformation* primaryPartInfo = dynamic_cast<PrimaryParticleInformation*>( track->GetDynamicParticle()->GetPrimaryParticle()->GetUserInformation() );
222 return primaryPartInfo->GetParticleBarcode();
223 }
224 return 0;
225}
226
228 int newBarcode) {
229 // the G4Track instance for the current child particle
230 const G4Track* thisChildTrack = m_children[i];
231
232 // NB: NOT checking if secondary is actually alive. Even with zero momentum,
233 // secondary could decay right away and create further particles which pass the
234 // truth strategies.
235
236 HepMC::GenParticlePtr hepParticle = convert( thisChildTrack, newBarcode, true );
237 TrackHelper tHelper(thisChildTrack);
239
240 // needed to make AtlasG4 work with ISF TruthService
241 if (trackInfo==nullptr) {
242 trackInfo = new TrackInformation( hepParticle );
243 thisChildTrack->SetUserInformation( trackInfo );
244 }
245
246 if (HepMC::GenParticlePtr primary = primaryGenParticle(m_step->GetTrack())) {
247 trackInfo->SetPrimaryGenParticle(primary);
248 }
249 trackInfo->SetGenerationZeroGenParticle(hepParticle);
250 trackInfo->SetCurrentGenParticle(hepParticle);
252 trackInfo->SetRegenerationNr(0);
253
254 return hepParticle;
255}
256
257
258bool iGeant4::Geant4TruthIncident::particleAlive(const G4Track *track) const {
259 G4TrackStatus trackStatus = track->GetTrackStatus();
260
261 if ( trackStatus != fAlive && trackStatus != fStopButAlive ) {
262 // parent does not exist in G4 anymore after this step
263
264 // check whether the particle was returned to ISF
265 auto* trackInfo = ISFG4Helper::getISFTrackInfo( *track );
266 bool returnedToISF = trackInfo ? trackInfo->GetReturnedToISF() : false;
267 if ( !returnedToISF ) {
268 // particle was not sent to ISF either
269 return false;
270 }
271 }
272
273 return true;
274}
275
276HepMC::GenParticlePtr iGeant4::Geant4TruthIncident::convert(const G4Track *track, const int, const bool secondary) const {
277
278 const G4ThreeVector & mom = track->GetMomentum();
279 const double energy = track->GetTotalEnergy();
280 const int pdgCode = track->GetDefinition()->GetPDGEncoding();
281 const HepMC::FourVector fourMomentum( mom.x(), mom.y(), mom.z(), energy);
282
283 TrackHelper tHelper(m_step->GetTrack());
285 const HepMC::GenParticlePtr parent = trackInfo ? trackInfo->GetCurrentGenParticle() : nullptr;
286 int status = (secondary) ? 1 + HepMC::SIM_STATUS_THRESHOLD : parent->status() + HepMC::SIM_STATUS_INCREMENT;
287 // Treat child particles of pre-defined decays differently
289 const G4DynamicParticle* dynPart = track->GetDynamicParticle();
290 bool hasPredefinedDecay = (dynPart && (nullptr!=(dynPart->GetPreAssignedDecayProducts())));
291 status = (hasPredefinedDecay)? 2 : 1;
292 }
293 // Treat particles with a pre-defined decay which have survived an
294 // interaction differently for now.
296 status = status%HepMC::SIM_STATUS_INCREMENT;
297 // Such particles were previously assigned barcodes below
298 // HepMC::SIM_BARCODE_OFFSET and therefore
299 // HepMC::is_simulation_particle(barcode) would return false. Not
300 // applying HepMC::SIM_STATUS_INCREMENT means that
301 // HepMC::is_simulation_particle(status) will also return false.
302 // TODO This should be revisited in the future should we decide
303 // that we want to be able to easily identify such particles.
304 }
305 HepMC::GenParticlePtr newParticle = HepMC::newGenParticlePtr(fourMomentum, pdgCode, status);
306
307 return newParticle;
308}
309
310
312
313 const std::vector<const G4Track*>* tracks = m_step->GetSecondaryInCurrentStep();
314 const int iSize = tracks->size();
315 const int iLast = iSize - numberOfChildren() - 1; //NB can be -1.
316 for(int i=iSize-1;i>iLast;i--) {
317 m_children.push_back((*tracks)[i]);
318 }
319}
320
329 G4Track* track=m_step->GetTrack();
330 const G4DynamicParticle* dynPart = track->GetDynamicParticle();
331 const double preAsgnDecPropTime = dynPart->GetPreAssignedDecayProperTime();
332 const double trackPropTime = track->GetProperTime();
333 bool parentIsQuasiStable = (nullptr!=(dynPart->GetPreAssignedDecayProducts()));
334 const G4VProcess *process = m_step->GetPostStepPoint()->GetProcessDefinedStep();
335 const int processType = process->GetProcessType();
337 if(parentIsQuasiStable) {
338 if(this->parentSurvivesIncident()) {
339 classification = ISF::QS_SURV_VTX;
340 }
341 else if(processType==6 && (trackPropTime-preAsgnDecPropTime) < -std::numeric_limits<double>::epsilon()) {
342 // Particle decayed before its expected pre-defined decay time
343 classification = ISF::QS_DEST_VTX;
344 }
345 else {
346 classification = ISF::QS_PREDEF_VTX;
347 }
348 }
349 return classification;
350 // end of code to determine interaction type
351}
size_t size() const
Number of registered mappings.
unsigned short numberOfChildren() const
Return total number of child particles.
AtlasDetDescr::AtlasRegion geoID()
Return the SimGeoID corresponding to the vertex of the truth incident.
ITruthIncident(AtlasDetDescr::AtlasRegion geoID, unsigned short numChildren)
This class is attached to G4PrimaryParticle objects as UserInformation.
TrackInformation * GetTrackInformation()
Return concrete TrackInformation when callers need fields that are not part of the VTrackInformation ...
bool IsPrimary() const
Implementation of VTrackInformation.
virtual HepMC::ConstGenParticlePtr GetCurrentGenParticle() const override
return a pointer to the GenParticle corresponding to the current G4Track (if there is one).
int GetRegenerationNr() const
return the number of times the particle represented by the G4Track has undergone a non-destructive in...
void SetRegenerationNr(int i)
update the number of times the particle represented by the G4Track has undergone a non-destructive in...
virtual void SetCurrentGenParticle(HepMC::GenParticlePtr) override
set m_currentGenParticle, the pointer to the GenParticle corresponding to the current G4Track.
void SetClassification(TrackClassification tc)
update the classification of the currently tracked particle, usually called when a new G4Track is cre...
int physicsProcessCode() const override final
Return specific physics process code of the truth incident (eg ionisation, bremsstrahlung,...
double childEkin(unsigned short index) const override final
Return Ekin of the i-th child particle.
int parentBarcode() override final
Return the barcode of the parent particle.
HepMC::GenParticlePtr m_parentParticleAfterIncident
double parentPt2() const override final
Return pT^2 of the parent particle.
bool particleAlive(const G4Track *track) const
check if the given G4Track represents a particle that is alive in ISF or ISF-G4
int childBarcode(unsigned short index) const override final
Return the barcode of the i-th child particle (if defined as part of the TruthIncident) otherwise ret...
double childP2(unsigned short index) const override final
Return p^2 of the i-th child particle.
int parentStatus() override final
Return the status of the parent particle.
HepMC::GenParticlePtr parentParticleAfterIncident(int newBC) override final
Return the parent particle after the TruthIncident vertex (and give it a new barcode).
ISF::InteractionClass_t interactionClassification() const override final
The interaction classifications are described as follows: STD_VTX: interaction of a particle without ...
int physicsProcessCategory() const override final
Return category of the physics process represented by the truth incident (eg hadronic,...
const HepMC::FourVector & position() const override final
Return HepMC position of the truth vertex.
bool parentSurvivesIncident() const override final
Return a boolean whether or not the parent particle survives the incident.
int parentPdgCode() const override final
Return the PDG Code of the parent particle.
HepMC::GenParticlePtr childParticle(unsigned short index, int bc) override final
Return the i-th child as a HepMC particle type and assign the given Barcode to the simulator particle...
int childPdgCode(unsigned short index) const override final
Return the PDG Code of the i-th child particle.
int parentUniqueID() override final
Return the unique ID of the parent particle.
void prepareChildren()
prepare the child particles
double parentP2() const override final
Return p^2 of the parent particle.
std::vector< const G4Track * > m_children
double childPt2(unsigned short index) const override final
Return pT^2 of the i-th child particle.
double parentEkin() const override final
Return Ekin of the parent particle.
HepMC::GenParticlePtr parentParticle() override final
Return the parent particle as a HepMC particle type.
const G4ThreeVector childP(unsigned short index) const
Return p of the i-th child particle.
HepMC::GenParticlePtr convert(const G4Track *particle, const int barcode, const bool secondary) const
static VTrackInformation * getISFTrackInfo(const G4Track &aTrack)
return a valid UserInformation object of the G4Track for use within the ISF
const std::string process
AtlasRegion
A simple enum of ATLAS regions and sub-detectors.
Definition AtlasRegion.h:21
int barcode(const T *p)
Definition Barcode.h:15
HepMC3::FourVector FourVector
int uniqueID(const T &p)
constexpr int UNDEFINED_ID
GenParticlePtr newGenParticlePtr(const HepMC3::FourVector &mom=HepMC3::FourVector::ZERO_VECTOR(), int pid=0, int status=0)
Definition GenParticle.h:21
constexpr int SIM_STATUS_INCREMENT
Constant defining the barcode threshold for regenerated particles, i.e. particles surviving an intera...
constexpr int SIM_STATUS_THRESHOLD
Constant definiting the status threshold for simulated particles, eg. can be used to separate generat...
HepMC3::GenParticlePtr GenParticlePtr
Definition GenParticle.h:19
InteractionClass_t
The interaction classifications are described as follows: STD_VTX: interaction of a particle without ...
@ QS_SURV_VTX
@ QS_PREDEF_VTX
@ QS_DEST_VTX
Definition index.py:1