ATLAS Offline Software
Loading...
Searching...
No Matches
TrackProcessorUserActionPassBack.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
5// class header
7
8// ISF includes
12
14
15// ISF Geant4 includes
17
18// Athena includes
22
23// MCTruth includes
24#include "MCTruth/TrackHelper.h"
27
28// Geant4 includes
29#include "G4ParticleDefinition.hh"
30#include "G4DynamicParticle.hh"
31#include "G4TouchableHistory.hh"
32#include "G4Step.hh"
33#include "G4TransportationManager.hh"
34#include "G4LogicalVolumeStore.hh"
35//#include "G4VPhysicalVolume.hh"
36
37#include <iostream>
38
39namespace G4UA {
40
41 namespace iGeant4{
42
44 : m_config(config)
45 {
46 if(4<m_config.verboseLevel)
47 {
48 G4cout << "Initializing TrackProcessorUserActionPassBack" << G4endl;
49 }
50
51 if ( !m_config.particleBroker.empty() ) {
52 if (m_config.particleBroker.retrieve().isFailure()) {
53 G4ExceptionDescription description;
54 description << G4String("TrackProcessorUserActionPassBack: ") + "Could not retrieve ISF Particle Broker: " << m_config.particleBroker;
55 G4Exception("iGeant4::TrackProcessorUserActionPassBack", "NoISFParticleBroker", FatalException, description);
56 return; //The G4Exception call above should abort the job, but Coverity does not seem to pick this up.
57 }
58 m_particleBrokerQuick = &(*m_config.particleBroker);
59 }
60
61 if ( !m_config.geoIDSvc.empty() ) {
62 if (m_config.geoIDSvc.retrieve().isFailure()) {
63 G4ExceptionDescription description;
64 description << G4String("TrackProcessorUserActionPassBack: ") + "Could not retrieve ISF GeoID Svc: " << m_config.geoIDSvc;
65 G4Exception("iGeant4::TrackProcessorUserActionPassBack", "NoISFGeoIDSvc", FatalException, description);
66 return; //The G4Exception call above should abort the job, but Coverity does not seem to pick this up.
67 }
68
69 m_geoIDSvcQuick = &(*m_config.geoIDSvc);
70 }
71
72 return;
73
74 }
75
77 ISF::ISFParticle *curISP)
78 {
79 G4Track* aTrack = aStep->GetTrack();
80 G4TrackStatus aTrackStatus = aTrack->GetTrackStatus();
81
82 //const G4StepPoint *preStep = aStep->GetPreStepPoint(); // Only used for DEBUG messages
83 const G4StepPoint *postStep = aStep->GetPostStepPoint();
84
85 // get geoID from parent
86 AtlasDetDescr::AtlasRegion curGeoID = curISP->nextGeoID();
87
88 //std::cout<<"retrieved isp "<<curISP<<" for trackID "<<curISP<<std::endl;
89
90 // check geoID of postStep
91 const G4ThreeVector &postPos = postStep->GetPosition();
92 //const G4ThreeVector &postMom = postStep->GetMomentum();
93 //AtlasDetDescr::AtlasRegion nextGeoID = m_geoIDSvcQuick->identifyNextGeoID( postPos.x(),
94 // postPos.y(),
95 // postPos.z(),
96 // postMom.x(),
97 // postMom.y(),
98 // postMom.z() );
99 AtlasDetDescr::AtlasRegion nextGeoID = m_geoIDSvcQuick->identifyGeoID( postPos.x(),
100 postPos.y(),
101 postPos.z() );
102
103 //ATH_MSG_DEBUG("PostStep point resolved to geoID = "<<nextGeoID);
104
105 // return if particle did NOT cross boundary
106 if ( nextGeoID==curGeoID ) {
107 //ATH_MSG_DEBUG(" -> G4Track stays inside geoID = "<<curGeoID);
108
109 // //
110 // // for debugging:
111 // //
112 // if ( msgLvl(MSG::DEBUG) ) {
113 // const G4ThreeVector &prePos = preStep->GetPosition();
114 // AtlasDetDescr::AtlasRegion preStepGeoID = m_geoIDSvcQuick->identifyGeoID( prePos.x(),
115 // prePos.y(),
116 // prePos.z() );
117 // AtlasDetDescr::AtlasRegion postStepGeoID = m_geoIDSvcQuick->identifyGeoID( postPos.x(),
118 // postPos.y(),
119 // postPos.z() );
120
121 // if( preStepGeoID!=postStepGeoID ) {
122 // const G4VPhysicalVolume *preVol = preStep->GetPhysicalVolume();
123 // const G4VPhysicalVolume *postVol = postStep->GetPhysicalVolume();
124 // const G4ThreeVector &preMom = preStep->GetMomentum();
125 // const G4ThreeVector &postMom = postStep->GetMomentum();
126 // const G4TrackVector *secondaryVector = aStep->GetSecondary();
127 // const G4ThreeVector& aTrack_pos = aTrack->GetPosition();
128 // const G4ThreeVector& aTrack_mom = aTrack->GetMomentum();
129 // int pdgID=aTrack->GetDefinition()->GetPDGEncoding();
130 // int aTrackID = aTrack->GetTrackID();
131 // ATH_MSG_WARNING("pre "<<preVol->GetName()<<" x="<<prePos.x()<<" y="<<prePos.y()<<" z="<<prePos.z()<<" p="<<preMom.mag()<<" geoID="<<preStepGeoID<<"; post "<<postVol->GetName()<<" x="<<postPos.x()<<" y="<<postPos.y()<<" z="<<postPos.z()<<" p="<<postMom.mag()<<" geoID="<<nextGeoID<<"; length="<<aStep->GetStepLength()<<"; n2nd="<<secondaryVector->size()<<" track x="<<aTrack_pos.x()<<" y="<<aTrack_pos.y()<<" z="<<aTrack_pos.z()<<" p="<<aTrack_mom.mag()<<" curgeoID="<<curGeoID<<" pdgid="<<pdgID<<" trackID="<<aTrackID<<" ISF="<<curISP<<"; ploss="<<(postMom-preMom).mag());
132 // }
133 // }
134
135 return;
136 }
137
138
139 //
140 // this point is only reached if particle has crossed
141 // a sub-det boundary in the non-Geant4-only mode
142 //
143
144 if ( aTrack->GetKineticEnergy() < m_config.passBackEkinThreshold ) {
145 // kinetic energy of primary particle below threshold
146 // ATH_MSG_DEBUG(" -> G4Track enters geoID = " << nextGeoID <<
147 // " but is below Ekin threshold. Not returned to ISF.");
148 if ( m_config.killBoundaryParticlesBelowThreshold ) {
149 aTrack->SetTrackStatus( fStopAndKill );
150 } else {
151 // TODO: link G4Track to ISF particle with the new GeoID
152 }
153 } else if ( aTrackStatus!=fAlive && aTrackStatus != fStopButAlive ) {
154 // particle is killed by G4 in this step
155 // TODO: do we need to handle this case specifically?
156 // ATH_MSG_DEBUG(" -> G4Track enters geoID = " << nextGeoID <<
157 // " but is destroyed in this step. Not returned to ISF.");
158
159 } else {
160 // particle is above kinetic energy threshold and alive after this step
161 // -> push new ISFParticle back to ISF particle broker
162 // ATH_MSG_DEBUG(" -> G4Track enters geoID = " << nextGeoID <<
163 // " and is returned to ISF.");
164
165 const ISF::ISFParticle* parent = curISP;
167 HepMC::GenParticlePtr currentGenParticle = trackInfo ? trackInfo->GetCurrentGenParticle() : nullptr;
168 this->returnParticleToISF(aTrack, parent, currentGenParticle, nextGeoID); // TODO CHECK THIS LOGIC
169 }
170
171 //
172 // handle secondaries that were created in this G4Step
173 //
174 const std::vector<const G4Track*> *secondaryVector = aStep->GetSecondaryInCurrentStep();
175 // loop over new secondaries
176 if (secondaryVector && !secondaryVector->empty()) {
177 for ( auto* aConstTrack_2nd : *secondaryVector ) {
178 // get a non-const G4Track for current secondary (nasty!)
179 G4Track *aTrack_2nd ATLAS_THREAD_SAFE = const_cast<G4Track*>( aConstTrack_2nd ); // imposed by Geant4 interface
180
181 // check if new secondary position is behind boundary
182 const G4ThreeVector& pos_2nd = aTrack_2nd->GetPosition();
183 AtlasDetDescr::AtlasRegion nextGeoID_2nd = m_geoIDSvcQuick->identifyGeoID( pos_2nd.x(),
184 pos_2nd.y(),
185 pos_2nd.z() );
186 if( nextGeoID_2nd!=curGeoID ) {
187 // secondary was generated in this step and has
188 // a different geoID than the currently tracked one
189
190 if ( aTrack_2nd->GetKineticEnergy() < m_config.passBackEkinThreshold ) {
191 // kinetic energy of secondary particle below threshold
192 // ATH_MSG_DEBUG(" -> Secondary particle generated in this G4Step does not pass Ekin cut." <<
193 // " Not returned to ISF.");
194 if ( m_config.killBoundaryParticlesBelowThreshold ) {
195 // TODO: should we use fKillTrackAndSecondaries instead?
196 aTrack_2nd->SetTrackStatus( fStopAndKill );
197 } else {
198 // TODO: link G4Track to ISF particle with the new GeoID
199 }
200 } else {
201 // secondary particle is above kinetic energy threshold
202 // -> return it to ISF
203 // ATH_MSG_DEBUG(" -> Secondary particle generated in this G4Step is returned to ISF.");
204
205 // attach TrackInformation instance to the new secondary G4Track
206 ISF::ISFParticle *parent = curISP;
207 HepMC::GenParticlePtr generationZeroGenParticle = nullptr;
209 *parent,
211 generationZeroGenParticle );
212
213 HepMC::GenParticlePtr currentGenParticle{};
214 returnParticleToISF(aTrack_2nd, parent, currentGenParticle, nextGeoID_2nd); // TODO CHECK THIS LOGIC
215 }
216 }
217
218 } // <-- end loop over new secondaries
219 } // <-- end if secondary vector has entries
220
221 return;
222 }
223
225 {
227 if (!trackInfo) {
228 G4ExceptionDescription description;
229 description << G4String("newTruthBinding: ") + "No TrackInformation associated with G4Track (trackID: "
230 << aTrack->GetTrackID() << ", track pos: "<<aTrack->GetPosition() << ", mom: "<<aTrack->GetMomentum()
231 << ", parentID " << aTrack->GetParentID() << ")";
232 G4Exception("iGeant4::TrackProcessorUserActionPassBack", "NoTrackInformation", FatalException, description);
233 return nullptr; //The G4Exception call above should abort the job, but Coverity does not seem to pick this up.
234 }
235
236 HepMC::GenParticlePtr primaryGenParticle = trackInfo->GetPrimaryGenParticle();
237 HepMC::GenParticlePtr generationZeroGenParticle = trackInfo->GetGenerationZeroGenParticle();
238
239 ISF::TruthBinding* tBinding = new ISF::TruthBinding(currentGenParticle, primaryGenParticle, generationZeroGenParticle);
240
241 return tBinding;
242 }
243
245 const ISF::ISFParticle* parentISP,
246 HepMC::GenParticlePtr currentGenParticle,
248 {
249 ISF::TruthBinding* tBinding = newTruthBinding(aTrack, currentGenParticle);
250
252 *parentISP,
253 tBinding );
254
256 isp->setNextGeoID( AtlasDetDescr::AtlasRegion(nextGeoID) );
257 isp->setNextSimID( parentISP->nextSimID() );
258 }
259
260 return isp;
261 }
262
264 const ISF::ISFParticle* parentISP,
265 HepMC::GenParticlePtr currentGenParticle,
267 {
268 // kill track inside G4
269 aTrack->SetTrackStatus( fStopAndKill );
270
271 // create new ISFParticle and attach it to current G4Track
272 ISF::ISFParticle *newISP = newISFParticle( aTrack, parentISP, currentGenParticle, nextGeoID );
273
274 // update TrackInformation
276 trackInfo->SetReturnedToISF( true );
277 trackInfo->SetBaseISFParticle( newISP );
278
279 // push the particle back to ISF via the particle broker
281 {
282 [&] ATLAS_NOT_THREAD_SAFE () { // suppress checker warning, in MT mode there is no broker
283 m_particleBrokerQuick->push(newISP, parentISP);
284 }();
285 }
286 else
287 {
288 // store the particle for retrieval in MT mode
289 //parentISP must be non-null by here, it has already been deeferenced
290 if (!newISP->getTruthBinding()) newISP->setTruthBinding(new ISF::TruthBinding(*parentISP->getTruthBinding()));
291 m_storedSecondaries.push_back( newISP );
292 }
293
294 return;
295 }
296
297 } // iGeant4
298
299
300} // G4UA
if(pathvar)
Define macros for attributes used to control the static checker.
#define ATLAS_NOT_THREAD_SAFE
getNoisyStrip() Find noisy strips from hitmaps and write out into xml/db formats
#define ATLAS_THREAD_SAFE
ISF::IParticleBroker * m_particleBrokerQuick
quick access avoiding gaudi overhead
ISF::ISFParticle * newISFParticle(G4Track *aTrack, const ISF::ISFParticle *parent, HepMC::GenParticlePtr currentGenParticle, AtlasDetDescr::AtlasRegion nextGeoID)
ISF::TruthBinding * newTruthBinding(const G4Track *aTrack, HepMC::GenParticlePtr currentGenParticle) const
create a new TruthBinding object for the given G4Track (may return 0 if unable)
void ISFSteppingAction(const G4Step *, ISF::ISFParticle *curISP) override final
Called by the base class after the G4Track->ISFParticle association has been established.
ISF::IGeoIDSvc * m_geoIDSvcQuick
quick access avoiding gaudi overhead
void returnParticleToISF(G4Track *aTrack, const ISF::ISFParticle *parentISP, HepMC::GenParticlePtr currentGenParticle, AtlasDetDescr::AtlasRegion nextGeoID)
kills the given G4Track, converts it into an ISFParticle and returns it to the ISF particle broker
The generic ISF particle definition,.
Definition ISFParticle.h:42
const TruthBinding * getTruthBinding() const
pointer to the simulation truth - optional, can be 0
void setNextSimID(SimSvcID simID)
register the next SimSvcID
SimSvcID nextSimID() const
the next simulation service the particle will be sent to
void setNextGeoID(AtlasDetDescr::AtlasRegion geoID)
register the next AtlasDetDescr::AtlasRegion
AtlasDetDescr::AtlasRegion nextGeoID() const
next geoID the particle will be simulated in
void setTruthBinding(TruthBinding *truth)
static VTrackInformation * getISFTrackInfo(const G4Track &aTrack)
return a valid UserInformation object of the G4Track for use within the ISF
static ISF::ISFParticle * convertG4TrackToISFParticle(const G4Track &aTrack, const ISF::ISFParticle &parent, ISF::TruthBinding *truth=nullptr)
convert the given G4Track into an ISFParticle
static TrackInformation * attachTrackInfoToNewG4Track(G4Track &aTrack, ISF::ISFParticle &baseIsp, VTrackInformation::TrackClassification classification, HepMC::GenParticlePtr generationZeroGenParticle=nullptr)
attach a new TrackInformation object to the given new (!) G4Track (the G4Track must not have a UserIn...
std::string description
glabal timer - how long have I taken so far?
Definition hcg.cxx:93
AtlasRegion
A simple enum of ATLAS regions and sub-detectors.
Definition AtlasRegion.h:21
HepMC3::GenParticlePtr GenParticlePtr
Definition GenParticle.h:19