Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
MuonSensitiveDetector.cxx
Go to the documentation of this file.
1 
2 /*
3  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
4 */
5 
7 
10 #include <GeoModelKernel/throwExcept.h>
12 
13 #include <MCTruth/TrackHelper.h>
14 #include <G4Geantino.hh>
15 #include <G4ChargedGeantino.hh>
16 
18 
19 using namespace ActsTrk;
20 
21 namespace {
22  static const SG::Decorator<int> dec_G4TrkId{"MuonSim_G4TrkId"};
23 }
24 
25 namespace MuonG4R4 {
26  MuonSensitiveDetector::MuonSensitiveDetector(const std::string& name,
27  const std::string& output_key,
28  const std::string& trfStore_key,
29  const MuonGMR4::MuonDetectorManager* detMgr):
30  G4VSensitiveDetector{name},
32  m_writeHandle{output_key},
33  m_trfCacheKey{trfStore_key},
34  m_detMgr{detMgr} {
35  m_trfCacheKey.initialize().ignore();
36  }
37  void MuonSensitiveDetector::Initialize(G4HCofThisEvent*) {
38  if (m_writeHandle.isValid()) {
39  ATH_MSG_VERBOSE("Simulation hit container "<<m_writeHandle.fullKey()<<" is already written");
40  return;
41  }
42  if (!m_writeHandle.recordNonConst(std::make_unique<xAOD::MuonSimHitContainer>(),
43  std::make_unique<xAOD::MuonSimHitAuxContainer>()).isSuccess()) {
44  THROW_EXCEPTION(" Failed to record "<<m_writeHandle.fullKey());
45  }
46  ATH_MSG_DEBUG("Output container "<<m_writeHandle.fullKey()<<" has been successfully created");
47  }
49  ActsGeometryContext gctx{};
50  SG::ReadHandle trfStoreHandle{m_trfCacheKey};
51  if (!trfStoreHandle.isValid()) {
52  THROW_EXCEPTION("Failed to retrieve "<<m_trfCacheKey.fullKey()<<".");
53  }
54  gctx.setStore(std::make_unique<DetectorAlignStore>(*trfStoreHandle));
55  return gctx;
56  }
57  bool MuonSensitiveDetector::processStep(const G4Step* aStep) const {
58  const G4Track* currentTrack = aStep->GetTrack();
59  ATH_MSG_VERBOSE("Check whether step pdgId: "<<(*currentTrack)<<" will be processed.");
61  constexpr double velCutOff = 10.*Gaudi::Units::micrometer / Gaudi::Units::second;
62  if (aStep->GetStepLength() < std::numeric_limits<float>::epsilon() || currentTrack->GetVelocity() < velCutOff) {
63  ATH_MSG_VERBOSE("Step length is too short ");
64  return false;
65  }
67  if (currentTrack->GetDefinition()->GetPDGCharge() == 0.0) {
68  ATH_MSG_VERBOSE("Particle is neutral");
69  return currentTrack->GetDefinition() == G4Geantino::GeantinoDefinition() ||
70  currentTrack->GetDefinition() == G4ChargedGeantino::ChargedGeantinoDefinition();
71  }
72  return true;
73  }
75  const Amg::Transform3D& toGasGap,
76  const G4Step* aStep) {
77 
78  const G4Track* currentTrack = aStep->GetTrack();
80  const Amg::Vector3D locPostStep{toGasGap*Amg::Hep3VectorToEigen(aStep->GetPostStepPoint()->GetPosition())};
81  Amg::Vector3D locPreStep{toGasGap*Amg::Hep3VectorToEigen(aStep->GetPreStepPoint()->GetPosition())};
82 
84  Amg::Vector3D locHitDir = toGasGap.linear() * Amg::Hep3VectorToEigen(currentTrack->GetMomentumDirection());
85 
88  xAOD::MuonSimHit* prevHit = lastSnapShot(hitID, aStep);
89  if (std::abs(currentTrack->GetParticleDefinition()->GetPDGEncoding()) == 11 && prevHit) {
90  locPreStep = xAOD::toEigen(prevHit->localPosition()) - 0.5* prevHit->stepLength() *
91  xAOD::toEigen(prevHit->localDirection());
92 
93  locHitDir = (locPostStep - locPreStep).unit();
94  }
95  const Amg::Vector3D locHitPos = 0.5* (locPreStep + locPostStep);
96  ATH_MSG_VERBOSE( m_detMgr->idHelperSvc()->toStringGasGap(hitID)<<" - track: "<<(*currentTrack)
97  <<", deposit: "<<aStep->GetTotalEnergyDeposit()<<", -- local coords: "
98  <<"prestep: "<<Amg::toString(locPreStep)<<", post step: "<<Amg::toString(locPostStep)
99  <<" mid point: "<< Amg::toString(locHitPos)<<", direction: "<<Amg::toString(locHitDir)
100  <<", deposit: "<<aStep->GetTotalEnergyDeposit());
101 
102  const double globalTime = currentTrack->GetGlobalTime() + locHitDir.dot(locPostStep - locHitPos) / currentTrack->GetVelocity();
103 
104  xAOD::MuonSimHit* newHit = saveHit(hitID, locHitPos, locHitDir, globalTime, aStep);
105  if (prevHit) {
106  newHit->setStepLength((locPostStep - locPreStep).mag());
107  }
108  return newHit;
109  }
111  const Amg::Vector3D& hitPos,
112  const Amg::Vector3D& hitDir,
113  const double globTime,
114  const G4Step* aStep) {
115  const G4Track* currentTrack = aStep->GetTrack();
116  TrackHelper trHelper{currentTrack};
117  // If Geant4 propagates the same track through the same volume just update the last hit and don't write a new one
118  xAOD::MuonSimHit* hit = lastSnapShot(hitId, aStep);
119  bool newHit{false};
120  if (!hit) {
121  hit = m_writeHandle->push_back(std::make_unique<xAOD::MuonSimHit>());
122  newHit = true;
123  }
124  dec_G4TrkId(*hit) = currentTrack->GetTrackID();
125  hit->setIdentifier(hitId);
126  hit->setLocalPosition(xAOD::toStorage(hitPos));
127  hit->setLocalDirection(xAOD::toStorage(hitDir));
128  hit->setMass(currentTrack->GetDefinition()->GetPDGMass());
129  hit->setGlobalTime(globTime);
130  hit->setPdgId(currentTrack->GetDefinition()->GetPDGEncoding());
131  hit->setEnergyDeposit(aStep->GetTotalEnergyDeposit() + (newHit ? 0. : hit->energyDeposit()));
132  hit->setKineticEnergy(currentTrack->GetKineticEnergy());
133  hit->setGenParticleLink(trHelper.GenerateParticleLink());
134  hit->setStepLength(aStep->GetStepLength());
135 
136  ATH_MSG_VERBOSE("Save new hit "<<m_detMgr->idHelperSvc()->toString(hitId)
137  <<", pdgId: "<<hit->pdgId()
138  <<", "<<hit->genParticleLink()
139  <<", trackId: "<<currentTrack->GetTrackID()<<", "
140  <<", "<<hit->genParticleLink().cptr()<<std::endl
141  <<"pos: "<<Amg::toString(hitPos)<<", dir: "<<Amg::toString(hitDir)<<", time: "<<globTime
142  <<", energy: "<<hit->kineticEnergy()<<", stepLength: "<<hit->stepLength()<<", "
143  <<", deposit energy: "<<hit->energyDeposit());
144  return hit;
145  }
147  const G4Step* hitStep) {
148  TrackHelper trkHelper{hitStep->GetTrack()};
151  if (m_writeHandle->empty() ||
152  m_writeHandle->back()->identify() != hitId ||
153  trkHelper.GenerateParticleLink() != m_writeHandle->back()->genParticleLink() ||
154  dec_G4TrkId(*m_writeHandle->back()) != hitStep->GetTrack()->GetTrackID()) {
155  return nullptr;
156  }
157  return m_writeHandle->back();
158  }
159 }
python.SystemOfUnits.second
int second
Definition: SystemOfUnits.py:120
xAOD::MuonSimHit_v1
Definition: MuonSimHit_v1.h:18
xAOD::MuonSimHit_v1::setIdentifier
void setIdentifier(const Identifier &id)
Sets the global ATLAS identifier.
Definition: xAODMuonSimHit_V1.cxx:43
MuonG4R4::MuonSensitiveDetector::m_writeHandle
SG::WriteHandle< xAOD::MuonSimHitContainer > m_writeHandle
Definition: MuonSensitiveDetector.h:42
xAOD::MuonSimHit_v1::stepLength
float stepLength() const
Returns the path length of the G4 step.
MuonGMR4::MuonDetectorManager
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MuonDetectorManager.h:62
MuonG4R4::MuonSensitiveDetector::m_detMgr
const MuonGMR4::MuonDetectorManager * m_detMgr
Pointer to the underlying detector manager.
Definition: MuonSensitiveDetector.h:81
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:67
MuonG4R4::MuonSensitiveDetector::processStep
bool processStep(const G4Step *step) const
Checks whether the current step shall be processed at all.
Definition: MuonSensitiveDetector.cxx:57
xAOD::MuonSimHit_v1::setPdgId
void setPdgId(int id)
Sets the pdgID of the traversing particle.
MuonG4R4::MuonSensitiveDetector::saveHit
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.
Definition: MuonSensitiveDetector.cxx:110
TrackHelper.h
MuonG4R4::MuonSensitiveDetector::m_trfCacheKey
SG::ReadHandleKey< ActsTrk::DetectorAlignStore > m_trfCacheKey
ReadHandleKey to the DetectorAlignmentStore caching the relevant transformations needed in this event...
Definition: MuonSensitiveDetector.h:45
xAOD::toStorage
MeasVector< N > toStorage(const AmgVector(N)&amgVec)
Converts the double precision of the AmgVector into the floating point storage precision of the MeasV...
Definition: MeasurementDefs.h:69
MuonG4R4::MuonSensitiveDetector::Initialize
virtual void Initialize(G4HCofThisEvent *HCE) override final
Create the output container at the beginning of the event.
Definition: MuonSensitiveDetector.cxx:37
MuonSimHitAuxContainer.h
xAOD::MuonSimHit_v1::setLocalPosition
void setLocalPosition(MeasVector< 3 > vec)
Sets the local position of the traversing particle.
Definition: xAODMuonSimHit_V1.cxx:56
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
xAOD::MuonSimHit_v1::setGenParticleLink
void setGenParticleLink(const HepMcParticleLink &link)
Sets the link to the HepMC particle producing this hit.
Definition: xAODMuonSimHit_V1.cxx:78
xAOD::MuonSimHit_v1::pdgId
int pdgId() const
Returns the pdgID of the traversing particle.
MuonG4R4::MuonSensitiveDetector::propagateAndSaveStrip
xAOD::MuonSimHit * propagateAndSaveStrip(const Identifier &hitId, const Amg::Transform3D &toGasGap, const G4Step *hitStep)
Definition: MuonSensitiveDetector.cxx:74
xAOD::MuonSimHit_v1::setMass
void setMass(const float m)
set the rest-mass of the traversing particle
Amg::Hep3VectorToEigen
Amg::Vector3D Hep3VectorToEigen(const CLHEP::Hep3Vector &CLHEPvector)
Converts a CLHEP-based CLHEP::Hep3Vector into an Eigen-based Amg::Vector3D.
Definition: CLHEPtoEigenConverter.h:137
TrackHelper
Definition: TrackHelper.h:14
xAOD::MuonSimHit_v1::kineticEnergy
float kineticEnergy() const
Returns the kinetic energy of the traversing particle.
xAOD::MuonSimHit_v1::setKineticEnergy
void setKineticEnergy(const float energy)
Sets the kinetic energy of the traversing particle.
MuonG4R4
Include the common definitions from the MuonReadoutGeometry.
Definition: MuonSpectrometer/MuonPhaseII/MuonG4/MuonSensitiveDetectorsR4/MuonSensitiveDetectorsR4/Utils.h:14
Amg::toString
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Definition: GeoPrimitivesToStringConverter.h:40
SG::Decorator< int >
xAOD::MuonSimHit_v1::genParticleLink
const HepMcParticleLink & genParticleLink() const
Returns the link to the HepMC particle producing this hit.
Definition: xAODMuonSimHit_V1.cxx:68
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
Muon::IMuonIdHelperSvc::toStringGasGap
virtual std::string toStringGasGap(const Identifier &id) const =0
print all fields up to gas gap to string
AthMessaging
Class to provide easy MsgStream access and capabilities.
Definition: AthMessaging.h:55
xAOD::MuonSimHit_v1::localDirection
ConstVectorMap< 3 > localDirection() const
Returns the local direction of the traversing particle.
Definition: xAODMuonSimHit_V1.cxx:66
python.SystemOfUnits.micrometer
int micrometer
Definition: SystemOfUnits.py:71
xAOD::MuonSimHit_v1::setStepLength
void setStepLength(const float length)
Set the path length of the G4 step.
ActsGeometryContext
Include the GeoPrimitives which need to be put first.
Definition: ActsGeometryContext.h:27
CLHEPtoEigenConverter.h
Utils.h
xAOD::MuonSimHit_v1::setEnergyDeposit
void setEnergyDeposit(const float deposit)
Sets the energy deposited by the traversing particle inside the gas volume.
MuonSensitiveDetector.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
TrackInformation.h
xAOD::MuonSimHit_v1::setLocalDirection
void setLocalDirection(MeasVector< 3 > vec)
Sets the local direction of the traversing particle.
Definition: xAODMuonSimHit_V1.cxx:62
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
THROW_EXCEPTION
#define THROW_EXCEPTION(MESSAGE)
Definition: throwExcept.h:10
MuonG4R4::MuonSensitiveDetector::lastSnapShot
xAOD::MuonSimHit * lastSnapShot(const Identifier &gasGapId, const G4Step *hitStep)
Returns the last snap shot of the traversing particle.
Definition: MuonSensitiveDetector.cxx:146
Muon::IMuonIdHelperSvc::toString
virtual std::string toString(const Identifier &id) const =0
print all fields to string
unit
const PlainObject unit() const
This is a plugin that makes Eigen look like CLHEP & defines some convenience methods.
Definition: AmgMatrixBasePlugin.h:21
MuonGMR4::MuonDetectorManager::idHelperSvc
const Muon::IMuonIdHelperSvc * idHelperSvc() const
Returns a pointer to the central MuonIdHelperSvc.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/MuonDetectorManager.cxx:140
xAOD::MuonSimHit_v1::localPosition
ConstVectorMap< 3 > localPosition() const
Returns the local postion of the traversing particle.
Definition: xAODMuonSimHit_V1.cxx:60
xAOD::MuonSimHit_v1::energyDeposit
float energyDeposit() const
Returns the energy deposited by the traversing particle inside the gas volume.
ActsTrk
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
Definition: MuonDetectorBuilderTool.cxx:55
mag
Scalar mag() const
mag method
Definition: AmgMatrixBasePlugin.h:26
xAOD::MuonSimHit_v1::setGlobalTime
void setGlobalTime(const float time)
Sets the time of the traversing particle.
MuonG4R4::MuonSensitiveDetector::getGeoContext
ActsGeometryContext getGeoContext() const
Returns the current geometry context in the event.
Definition: MuonSensitiveDetector.cxx:48
Identifier
Definition: IdentifierFieldParser.cxx:14