ATLAS Offline Software
Loading...
Searching...
No Matches
MuonSensitiveDetector.cxx
Go to the documentation of this file.
1
2/*
3 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
4*/
5
7
10#include "GeoModelKernel/throwExcept.h"
13
14#include "G4Geantino.hh"
15#include "G4ChargedGeantino.hh"
16
17#include "MCTruth/TrackHelper.h"
21
22using namespace ActsTrk;
23
24namespace {
25 static const SG::Decorator<int> dec_G4TrkId{"MuonSim_G4TrkId"};
26}
27
28namespace MuonG4R4 {
30 const std::string& output_key,
31 const std::string& trfStore_key,
32 const MuonGMR4::MuonDetectorManager* detMgr):
33 G4VSensitiveDetector{name},
34 AthMessaging{name},
35 m_writeKey{output_key},
36 m_trfCacheKey{trfStore_key},
37 m_detMgr{detMgr} {
38 m_trfCacheKey.initialize().ignore();
39 }
40 void MuonSensitiveDetector::Initialize(G4HCofThisEvent*) {
43 auto* hitVec = m_g4UserEventInfo->GetHitCollectionMap()->Find<MuonSimHitsVec>(m_writeKey);
44 if (!hitVec) {
45 THROW_EXCEPTION("The event does not contain a MuonSimHit container called '"<<m_writeKey<<"'");
46 }
47 m_outContainer = hitVec->container.get();
48 ATH_MSG_DEBUG(__func__<<"() "<<__LINE__<<" - Retrieved '"<<m_writeKey<<"'.");
49 } else {
50 m_outContainer = nullptr;
51 }
52 }
56 const EventContext& MuonSensitiveDetector::eventContext() const {
57 AtlasG4EventUserInfo* g4EventInfo = eventInfo();
58 if (!g4EventInfo) {
59 THROW_EXCEPTION("No AtlasG4EventUserInfo available");
60 }
61 return g4EventInfo->GetEventContext();
62 }
65 const ActsTrk::DetectorAlignStore* alignment{nullptr};
66 if (!SG::get(alignment, m_trfCacheKey, eventContext()).isSuccess()) {
67 THROW_EXCEPTION("Failed to retrieve "<<m_trfCacheKey.fullKey()<<".");
68 }
69 gctx.setStore(std::make_unique<DetectorAlignStore>(*alignment));
70 return gctx;
71 }
72 bool MuonSensitiveDetector::processStep(const G4Step* aStep) const {
73 const G4Track* currentTrack = aStep->GetTrack();
74 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Check whether step pdgId: "<<(*currentTrack)<<" will be processed.");
76 constexpr double velCutOff = 10.*Gaudi::Units::micrometer / Gaudi::Units::second;
77 if (aStep->GetStepLength() < std::numeric_limits<float>::epsilon() || currentTrack->GetVelocity() < velCutOff) {
78 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Step length is too short ");
79 return false;
80 }
82 if (currentTrack->GetDefinition()->GetPDGCharge() == 0.0) {
83 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Particle is neutral");
84 return currentTrack->GetDefinition() == G4Geantino::GeantinoDefinition() ||
85 currentTrack->GetDefinition() == G4ChargedGeantino::ChargedGeantinoDefinition();
86 }
87 return true;
88 }
90 TrackHelper trHelper{track};
91 AtlasG4EventUserInfo* g4EventInfo = eventInfo();
92 return trHelper.GenerateParticleLink(g4EventInfo ? g4EventInfo->GetEventStore() : nullptr);
93 }
95 const Acts::Transform3& toGasGap,
96 const G4Step* aStep) {
97
98 const G4Track* currentTrack = aStep->GetTrack();
100 const Amg::Vector3D locPostStep{toGasGap*Amg::Hep3VectorToEigen(aStep->GetPostStepPoint()->GetPosition())};
101 Amg::Vector3D locPreStep{toGasGap*Amg::Hep3VectorToEigen(aStep->GetPreStepPoint()->GetPosition())};
102
104 Amg::Vector3D locHitDir = toGasGap.linear() * Amg::Hep3VectorToEigen(currentTrack->GetMomentumDirection());
105
108 xAOD::MuonSimHit* prevHit = lastSnapShot(hitID, aStep);
109 if (MC::isElectron(currentTrack->GetParticleDefinition()->GetPDGEncoding()) && prevHit) {
110 locPreStep = xAOD::toEigen(prevHit->localPosition())
111 - 0.5* prevHit->stepLength() * xAOD::toEigen(prevHit->localDirection());
112
113 locHitDir = (locPostStep - locPreStep).unit();
114 }
115 const Amg::Vector3D locHitPos = 0.5* (locPreStep + locPostStep);
116 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - "<<m_detMgr->idHelperSvc()->toStringGasGap(hitID)
117 <<" - track: "<<(*currentTrack) <<", deposit: "<<aStep->GetTotalEnergyDeposit()
118 <<", -- local coords -- prestep: "<<Amg::toString(locPreStep)
119 <<", post step: "<<Amg::toString(locPostStep)
120 <<" mid point: "<< Amg::toString(locHitPos)<<", direction: "<<Amg::toString(locHitDir)
121 <<", deposit: "<<aStep->GetTotalEnergyDeposit());
122
123 const double globalTime = currentTrack->GetGlobalTime() + locHitDir.dot(locPostStep - locHitPos) / currentTrack->GetVelocity();
124
125 xAOD::MuonSimHit* newHit = saveHit(hitID, locHitPos, locHitDir, globalTime, aStep);
126 if (newHit && prevHit) {
127 newHit->setStepLength((locPostStep - locPreStep).mag());
128 }
129 return newHit;
130 }
132 const Amg::Vector3D& hitPos,
133 const Amg::Vector3D& hitDir,
134 const double globTime,
135 const G4Step* aStep) {
136 const G4Track* currentTrack = aStep->GetTrack();
137 const HepMcParticleLink particleLink{genParticleLink(currentTrack)};
138 // If Geant4 propagates the same track through the same volume just update the last hit and don't write a new one
139 xAOD::MuonSimHit* hit = lastSnapShot(hitId, aStep, particleLink);
140 bool newHit{false};
141 if (!hit) {
142 if (!m_outContainer) {
143 THROW_EXCEPTION("Cannot find container '"<<m_writeKey<<"'.");
144 }
145 hit = m_outContainer->push_back(std::make_unique<xAOD::MuonSimHit>());
146 newHit = true;
147 }
148 dec_G4TrkId(*hit) = currentTrack->GetTrackID();
149 hit->setIdentifier(hitId);
150 hit->setLocalPosition(xAOD::toStorage(hitPos));
151 hit->setLocalDirection(xAOD::toStorage(hitDir));
152 hit->setMass(currentTrack->GetDefinition()->GetPDGMass());
153 hit->setGlobalTime(globTime);
154 int pdgId = currentTrack->GetDefinition()->GetPDGEncoding();
156 if (pdgId ==0) {
157 if (currentTrack->GetDefinition() == G4ChargedGeantino::ChargedGeantinoDefinition()){
158 pdgId = std::copysign(MC::GEANTINOPLUS, currentTrack->GetDynamicParticle()->GetCharge());
159 } else if (currentTrack->GetDefinition() == G4Geantino::GeantinoDefinition()) {
160 pdgId = MC::GEANTINO0;
161 } else {
162 ATH_MSG_WARNING(__func__<<"() "<<__LINE__<<" - The track has an undefined pdgId "<<aStep);
163 m_outContainer->pop_back();
164 return nullptr;
165 }
166 }
167 hit->setPdgId(pdgId);
168 hit->setEnergyDeposit(aStep->GetTotalEnergyDeposit() + (newHit ? 0. : hit->energyDeposit()));
169 hit->setKineticEnergy(currentTrack->GetKineticEnergy());
170 hit->setGenParticleLink(particleLink);
171 hit->setStepLength(aStep->GetStepLength());
172
173 ATH_MSG_VERBOSE(__func__<<"() "<<__LINE__<<" - Save new hit "<<m_detMgr->idHelperSvc()->toString(hitId)
174 <<", pdgId: "<<hit->pdgId()<<", "<<particleLink
175 <<", trackId: "<<currentTrack->GetTrackID()
176 <<", "<<particleLink.cptr()<<std::endl
177 <<"pos: "<<Amg::toString(hitPos)<<", dir: "<<Amg::toString(hitDir)<<", time: "<<globTime
178 <<", energy: "<<hit->kineticEnergy()<<", stepLength: "<<hit->stepLength()<<", "
179 <<", deposit energy: "<<hit->energyDeposit());
180 return hit;
181 }
183 const G4Step* hitStep) {
184 const HepMcParticleLink particleLink{genParticleLink(hitStep->GetTrack())};
185 return lastSnapShot(hitId, hitStep, particleLink);
186 }
188 const G4Step* hitStep,
189 const HepMcParticleLink& particleLink) {
192 if (m_outContainer->empty() ||
193 m_outContainer->back()->identify() != hitId ||
194 particleLink != m_outContainer->back()->genParticleLink() ||
195 dec_G4TrkId(*m_outContainer->back()) != hitStep->GetTrack()->GetTrackID()) {
196 return nullptr;
197 }
198 return m_outContainer->back();
199 }
200}
Scalar mag() const
mag method
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
detray::unit< scalar_t > unit
ATLAS-specific HepMC functions.
bool hit(const Container &ids, int pdgId)
Utility helpers used by Run-4 muon sensitive detector implementations.
Handle class for reading from StoreGate.
void setStore(AlignmentStorePtr store)
Adds the store to the Geometry context.
AthMessaging(IMessageSvc *msgSvc, const std::string &name)
Constructor.
This class is attached to G4Event objects as UserInformation.
static AtlasG4EventUserInfo * GetEventUserInfo()
const EventContext & GetEventContext() const
const MuonGMR4::MuonDetectorManager * m_detMgr
Pointer to the underlying detector manager.
AtlasG4EventUserInfo * eventInfo() const
Returns the event user info for the current G4 event, if available.
const EventContext & eventContext() const
Returns the current event context recorded in the G4 event info.
virtual void Initialize(G4HCofThisEvent *HCE) override final
Create the output container at the beginning of the event.
MuonSensitiveDetector(const std::string &name, const std::string &output_key, const std::string &trf_storeKey, const MuonGMR4::MuonDetectorManager *detMgr)
Constructor.
SG::ReadHandleKey< ActsTrk::DetectorAlignStore > m_trfCacheKey
ReadHandleKey to the DetectorAlignmentStore caching the relevant transformations needed in this event...
HepMcParticleLink genParticleLink(const G4Track *track) const
Generates a HepMcParticleLink for the Geant4 track using the current event store.
bool processStep(const G4Step *step) const
Checks whether the current step shall be processed at all.
AtlasG4EventUserInfo * m_g4UserEventInfo
G4 event user information holding the current event store/context.
std::string m_writeKey
Key under which the output container is stored in the G4 event.
xAOD::MuonSimHit * saveHit(const Identifier &hitId, const Amg::Vector3D &hitPos, const Amg::Vector3D &hitDir, const double globTime, const G4Step *hitStep)
Saves the current Step as a xAOD::MuonSimHit snapshot.
ActsTrk::GeometryContext getGeoContext() const
Returns the current geometry context in the event.
xAOD::MuonSimHitContainer * m_outContainer
Pointer to the MuonSimHit output container.
xAOD::MuonSimHit * lastSnapShot(const Identifier &gasGapId, const G4Step *hitStep, const HepMcParticleLink &particleLink)
Returns the last snap shot matching an already generated HepMcParticleLink.
xAOD::MuonSimHit * propagateAndSaveStrip(const Identifier &hitId, const Acts::Transform3 &toGasGap, const G4Step *hitStep)
Records the G4Step in the sim hit.
HepMcParticleLink GenerateParticleLink()
Generates a new HepMcParticleLink object on the stack based on the generation-zero unique id,...
Definition TrackHelper.h:75
ConstVectorMap< 3 > localDirection() const
Returns the local direction of the traversing particle.
float stepLength() const
Returns the path length of the G4 step.
void setStepLength(const float length)
Set the path length of the G4 step.
ConstVectorMap< 3 > localPosition() const
Returns the local postion of the traversing particle.
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Amg::Vector3D Hep3VectorToEigen(const CLHEP::Hep3Vector &CLHEPvector)
Converts a CLHEP-based CLHEP::Hep3Vector into an Eigen-based Amg::Vector3D.
Eigen::Matrix< double, 3, 1 > Vector3D
static const int GEANTINOPLUS
PDG rule 10: Codes 81–100 are reserved for generator-specific pseudoparticles and concepts.
bool isElectron(const T &p)
static const int GEANTINO0
Include the common definitions from the MuonReadoutGeometry.
AthHitVec::AuxStoreHitCollection< xAOD::MuonSimHitContainer, xAOD::MuonSimHitAuxContainer > MuonSimHitsVec
Helper type which can be filled into the HitCollectionMap storing the event content in the event.
SG::Decorator< T, ALLOC > Decorator
Helper class to provide type-safe access to aux data, specialized for JaggedVecElt.
Definition AuxElement.h:576
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
MuonSimHit_v1 MuonSimHit
Defined the version of the MuonSimHit.
Definition MuonSimHit.h:12
MeasVector< N > toStorage(const AmgVector(N)&amgVec)
Converts the double precision of the AmgVector into the floating point storage precision of the MeasV...
#define THROW_EXCEPTION(MESSAGE)
Definition throwExcept.h:10