ATLAS Offline Software
Loading...
Searching...
No Matches
MdtSensitiveDetector.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
8
10
11#include <limits>
12#include <iostream>
14#include <GeoModelKernel/throwExcept.h>
15#include <GaudiKernel/SystemOfUnits.h>
16
17using namespace MuonGMR4;
18using namespace CxxUtils;
19using namespace ActsTrk;
20namespace MuonG4R4{
21
22const MuonGMR4::MdtReadoutElement* MdtSensitiveDetector::getReadoutElement(const G4TouchableHistory* touchHist) const {
24 const std::string stationVolume = touchHist->GetVolume(2)->GetName();
25 using namespace MuonGMR4;
26 const std::vector<std::string> volumeTokens = tokenize(stationVolume, "_");
27 ATH_MSG_VERBOSE("Name of the station volume is "<<stationVolume);
28 if (volumeTokens.size() != 5) {
29 THROW_EXCEPTION(" Cannot deduce the station name from "<<stationVolume);
30 }
32 const std::string stName = volumeTokens[0].substr(0,3);
33 const int stationEta = atoi(volumeTokens[2]);
34 const int stationPhi = atoi(volumeTokens[3]);
35 const int multiLayer = atoi(volumeTokens[4]);
36 const MdtIdHelper& idHelper{m_detMgr->idHelperSvc()->mdtIdHelper()};
38 const Identifier detElId = idHelper.multilayerID(idHelper.elementID(stName,stationEta, stationPhi), multiLayer);
40 const MdtReadoutElement* readOutEle = m_detMgr->getMdtReadoutElement(detElId);
41 if (!readOutEle) {
42 THROW_EXCEPTION(" Failed to retrieve a valid detector element from "
43 <<m_detMgr->idHelperSvc()->toStringDetEl(detElId)<<" "<<stationVolume);
44 }
45 return readOutEle;
46}
47
48G4bool MdtSensitiveDetector::ProcessHits(G4Step* aStep,G4TouchableHistory* /*ROHist*/) {
49
51 if (!processStep(aStep)) {
52 return true;
53 }
54 G4Track* currentTrack = aStep->GetTrack();
55 const G4StepPoint* preStep = aStep->GetPreStepPoint();
56 const G4TouchableHistory* touchHist = static_cast<const G4TouchableHistory*>(preStep->GetTouchable());
57 const MdtReadoutElement* reEle{getReadoutElement(touchHist)};
58
60
61 const Identifier HitID = getIdentifier(gctx, reEle, touchHist);
62 if (!HitID.is_valid()) {
63 ATH_MSG_VERBOSE("No valid hit found");
64 return true;
65 }
66
67 const Amg::Transform3D globalToLocal{reEle->globalToLocalTransform(gctx, reEle->measurementHash(HitID))};
68
69 // transform pre and post step positions to local positions
70 const Amg::Vector3D prePosition{Amg::Hep3VectorToEigen(preStep->GetPosition())};
71 const Amg::Vector3D postPosition{Amg::Hep3VectorToEigen(aStep->GetPostStepPoint()->GetPosition())};
72
73 const Amg::Vector3D trackDirection{(postPosition - prePosition).unit()};
74
75 const Amg::Vector3D trackLocPos{globalToLocal * prePosition};
76 const Amg::Vector3D trackLocDir{globalToLocal.linear()* trackDirection};
77
81 double lambda = Amg::intersect<3>(Amg::Vector3D::Zero(), Amg::Vector3D::UnitZ(),
82 trackLocPos, trackLocDir).value_or(0);
83 if (std::abs(currentTrack->GetDefinition()->GetPDGEncoding()) == 11) {
84 lambda = std::clamp(lambda, 0., aStep->GetStepLength());
85 }
87 const Amg::Vector3D driftHit{trackLocPos + lambda * trackLocDir};
88
89
90 const double globalTime{preStep->GetGlobalTime() + lambda / currentTrack->GetVelocity()};
91
92 if (std::abs(currentTrack->GetDefinition()->GetPDGEncoding()) == 11) {
93 const xAOD::MuonSimHit* lastRecord = lastSnapShot(HitID, aStep);
94 if (lastRecord && lastRecord->localPosition().perp() < driftHit.perp()) {
95 return true;
96 }
97 }
98
99 ATH_MSG_VERBOSE(" Dumping of hit "<<m_detMgr->idHelperSvc()->toString(HitID)
100 <<", barcode: "<<genParticleLink(currentTrack).barcode()
101 <<", "<<(*currentTrack) <<", driftCircle: "<<Amg::toString(driftHit, 4)
102 <<", direction "<<Amg::toString(trackLocDir, 4) <<" to SimHit container ahead. ");
103 saveHit(HitID, driftHit, trackLocDir, globalTime, aStep);
104 return true;
105}
107 const MuonGMR4::MdtReadoutElement* readOutEle,
108 const G4TouchableHistory* touchHist) const {
109 const Amg::Transform3D localToGlobal{getTransform(touchHist, 0)};
112 Amg::Vector3D refTubePos = (readOutEle->globalToLocalTransform(gctx, readOutEle->measurementHash(1,1)) * localToGlobal).translation();
113 ATH_MSG_VERBOSE("Position of the tube wire w.r.t. the first tube in the multi layer "<<Amg::toString(refTubePos, 2));
115 static const double layerPitch = 1./ std::sin(60*Gaudi::Units::deg);
116 const int layer = std::round(refTubePos.x() * layerPitch / readOutEle->tubePitch()) +1;
117 if (layer <= 0) {
118 THROW_EXCEPTION("Tube hit in nirvana -- It seems that the tube position "
119 <<Amg::toString(refTubePos, 2)<<", perp: "<<refTubePos.perp()
120 <<" is outside of the volume envelope "
121 <<m_detMgr->idHelperSvc()->toStringDetEl(readOutEle->identify())<<". ");
122 }
124 refTubePos = (readOutEle->globalToLocalTransform(gctx, readOutEle->measurementHash(layer,1)) * localToGlobal).translation();
125 const double tubePitches = refTubePos.y() / readOutEle->tubePitch();
126 unsigned int tube = std::round(tubePitches) + 1;
127 tube = std::max(1u, std::min(readOutEle->numTubesInLay(), tube));
130 const Amg::Transform3D closureCheck{readOutEle->globalToLocalTransform(gctx,
131 readOutEle->measurementHash(layer, tube))*localToGlobal};
132 if (!Amg::isIdentity(closureCheck)) {
133 ATH_MSG_WARNING("Correction needed "<<layer<<","<<tube<<" "<<Amg::toString(closureCheck));
134 if (closureCheck.translation().y() > 0) ++tube;
135 else --tube;
136 }
137
138 const IdentifierHash tubeHash = readOutEle->measurementHash(layer, tube);
139 const Identifier tubeId = readOutEle->measurementId(tubeHash);
140 {
141 const Amg::Transform3D closureCheck{readOutEle->globalToLocalTransform(gctx, tubeHash)*localToGlobal};
142 if (!Amg::isIdentity(closureCheck)) {
143 THROW_EXCEPTION("Tube hit in Nirvana -- It seems that the tube position "
144 <<Amg::toString(refTubePos, 2)<<", perp: "<<refTubePos.perp()
145 <<" is outside of the volume envelope "
146 <<m_detMgr->idHelperSvc()->toStringDetEl(readOutEle->identify())<<". "
147 <<"Layer: "<<layer<<", tube: "<<tube<<" "
148 <<Amg::toString(closureCheck)
149 <<"tube volume : "<<touchHist->GetVolume(0)->GetName()
150 <<" mdt chamber: "<<touchHist->GetVolume(2)->GetName());
151 }
152 }
153 ATH_MSG_VERBOSE("Tube & layer number candidate "<<tube<<", "<<layer<<" back and forth transformation "
154 <<Amg::toString(closureCheck));
155 return tubeId;
156}
157
158}
const PlainObject unit() const
This is a plugin that makes Eigen look like CLHEP & defines some convenience methods.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
int HitID
Utility helpers used by Run-4 muon sensitive detector implementations.
This is a "hash" representation of an Identifier.
Identifier multilayerID(const Identifier &channeldID) const
Identifier elementID(int stationName, int stationEta, int stationPhi) const
virtual G4bool ProcessHits(G4Step *aStep, G4TouchableHistory *ROhist) override final
Identifier getIdentifier(const ActsTrk::GeometryContext &gctx, const MuonGMR4::MdtReadoutElement *reElement, const G4TouchableHistory *touchHist) const
Constructs the identifier of the actual tube where the energy deposit is taking place.
const MuonGMR4::MdtReadoutElement * getReadoutElement(const G4TouchableHistory *touchHist) const
Retrieves the MuonReadoutElement associated to the multilayer in which the energy deposit is taking p...
const MuonGMR4::MuonDetectorManager * m_detMgr
Pointer to the underlying detector manager.
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.
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::MuonSimHit * lastSnapShot(const Identifier &gasGapId, const G4Step *hitStep, const HepMcParticleLink &particleLink)
Returns the last snap shot matching an already generated HepMcParticleLink.
Readout element to describe the Monitored Drift Tube (Mdt) chambers Mdt chambers usually comrpise out...
unsigned numTubesInLay() const
Returns the number of tubes in a layer.
static IdentifierHash measurementHash(unsigned layerNumber, unsigned tubeNumber)
Constructs a Measurement hash from layer && tube number.
Identifier measurementId(const IdentifierHash &measHash) const override final
Back conversion of the measurement hash towards a full identifier Tube & layer number are extracted f...
double tubePitch() const
Returns the pitch between 2 tubes in a layer.
Amg::Transform3D globalToLocalTransform(const ActsTrk::GeometryContext &ctx) const
Returns the transformation from the global ATLAS coordinate system into the local coordinate system o...
Identifier identify() const override final
Return the ATLAS identifier.
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::optional< double > intersect(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
Calculates the point B' along the line B that's closest to a second line A.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
bool isIdentity(const Amg::Transform3D &trans)
Checks whether the transformation is the Identity transformation.
Amg::Vector3D Hep3VectorToEigen(const CLHEP::Hep3Vector &CLHEPvector)
Converts a CLHEP-based CLHEP::Hep3Vector into an Eigen-based Amg::Vector3D.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
std::vector< std::string > tokenize(std::string_view the_str, std::string_view delimiters)
Splits the string into smaller substrings.
int atoi(std::string_view str)
Helper functions to unpack numbers decoded in string into integers and doubles The strings are requir...
Include the common definitions from the MuonReadoutGeometry.
Amg::Transform3D getTransform(const G4VTouchable *history, unsigned int level)
Extracts the local -> global transformation from a TouchableHistory at a given level.
The ReadoutGeomCnvAlg converts the Run4 Readout geometry build from the GeoModelXML into the legacy M...
MuonSimHit_v1 MuonSimHit
Defined the version of the MuonSimHit.
Definition MuonSimHit.h:12
#define THROW_EXCEPTION(MESSAGE)
Definition throwExcept.h:10