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