Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
MdtSensitiveDetector.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 #include "MdtSensitiveDetector.h"
8 
9 
10 #include <MCTruth/TrackHelper.h>
11 
12 #include <limits>
13 #include <iostream>
15 #include <GeoModelKernel/throwExcept.h>
16 #include <GaudiKernel/SystemOfUnits.h>
17 #include <StoreGate/ReadHandle.h>
18 
19 using namespace MuonGMR4;
20 using namespace CxxUtils;
21 using namespace ActsTrk;
22 namespace MuonG4R4{
23 
24 const MuonGMR4::MdtReadoutElement* MdtSensitiveDetector::getReadoutElement(const G4TouchableHistory* touchHist) const {
26  const std::string stationVolume = touchHist->GetVolume(2)->GetName();
27  using namespace MuonGMR4;
28  const std::vector<std::string> volumeTokens = tokenize(stationVolume, "_");
29  ATH_MSG_VERBOSE("Name of the station volume is "<<stationVolume);
30  if (volumeTokens.size() != 5) {
31  THROW_EXCEPTION(" Cannot deduce the station name from "<<stationVolume);
32  }
34  const std::string stName = volumeTokens[0].substr(0,3);
35  const int stationEta = atoi(volumeTokens[2]);
36  const int stationPhi = atoi(volumeTokens[3]);
37  const int multiLayer = atoi(volumeTokens[4]);
38  const MdtIdHelper& idHelper{m_detMgr->idHelperSvc()->mdtIdHelper()};
40  const Identifier detElId = idHelper.multilayerID(idHelper.elementID(stName,stationEta, stationPhi), multiLayer);
42  const MdtReadoutElement* readOutEle = m_detMgr->getMdtReadoutElement(detElId);
43  if (!readOutEle) {
44  THROW_EXCEPTION(" Failed to retrieve a valid detector element from "
45  <<m_detMgr->idHelperSvc()->toStringDetEl(detElId)<<" "<<stationVolume);
46  }
47  return readOutEle;
48 }
49 
50 G4bool MdtSensitiveDetector::ProcessHits(G4Step* aStep,G4TouchableHistory* /*ROHist*/) {
51 
53  if (!processStep(aStep)) {
54  return true;
55  }
56  G4Track* currentTrack = aStep->GetTrack();
57  const G4StepPoint* preStep = aStep->GetPreStepPoint();
58  const G4TouchableHistory* touchHist = static_cast<const G4TouchableHistory*>(preStep->GetTouchable());
59  const MdtReadoutElement* reEle{getReadoutElement(touchHist)};
60 
61  const ActsGeometryContext gctx{getGeoContext()};
62 
63 
64  const Identifier HitID = getIdentifier(gctx, reEle, touchHist);
65  if (!HitID.is_valid()) {
66  ATH_MSG_VERBOSE("No valid hit found");
67  return true;
68  }
69 
70  const Amg::Transform3D globalToLocal{reEle->globalToLocalTrans(gctx, reEle->measurementHash(HitID))};
71 
72  // transform pre and post step positions to local positions
73  const Amg::Vector3D prePosition{Amg::Hep3VectorToEigen(preStep->GetPosition())};
74  const Amg::Vector3D postPosition{Amg::Hep3VectorToEigen(aStep->GetPostStepPoint()->GetPosition())};
75 
76  const Amg::Vector3D trackDirection{(postPosition - prePosition).unit()};
77 
78  const Amg::Vector3D trackLocPos{globalToLocal * prePosition};
79  const Amg::Vector3D trackLocDir{globalToLocal.linear()* trackDirection};
80 
84  double lambda = Amg::intersect<3>(Amg::Vector3D::Zero(), Amg::Vector3D::UnitZ(),
85  trackLocPos, trackLocDir).value_or(0);
86  if (std::abs(currentTrack->GetDefinition()->GetPDGEncoding()) == 11) {
87  lambda = std::clamp(lambda, 0., aStep->GetStepLength());
88  }
90  const Amg::Vector3D driftHit{trackLocPos + lambda * trackLocDir};
91 
92 
93  const double globalTime{preStep->GetGlobalTime() + lambda / currentTrack->GetVelocity()};
94 
95  if (std::abs(currentTrack->GetDefinition()->GetPDGEncoding()) == 11) {
96  const xAOD::MuonSimHit* lastRecord = lastSnapShot(HitID, aStep);
97  if (lastRecord && lastRecord->localPosition().perp() < driftHit.perp()) {
98  return true;
99  }
100  }
101 
102  TrackHelper trkHelp{currentTrack};
103 
104  ATH_MSG_VERBOSE(" Dumping of hit "<<m_detMgr->idHelperSvc()->toString(HitID)
105  <<", barcode: "<<trkHelp.GenerateParticleLink().barcode()
106  <<", "<<(*currentTrack) <<", driftCircle: "<<Amg::toString(driftHit, 4)
107  <<", direction "<<Amg::toString(trackLocDir, 4) <<" to SimHit container ahead. ");
108  saveHit(HitID, driftHit, trackLocDir, globalTime, aStep);
109  return true;
110 }
111 Identifier MdtSensitiveDetector::getIdentifier(const ActsGeometryContext& gctx,
112  const MuonGMR4::MdtReadoutElement* readOutEle,
113  const G4TouchableHistory* touchHist) const {
114  const Amg::Transform3D localToGlobal{getTransform(touchHist, 0)};
117  Amg::Vector3D refTubePos = (readOutEle->globalToLocalTrans(gctx, readOutEle->measurementHash(1,1)) * localToGlobal).translation();
118  ATH_MSG_VERBOSE("Position of the tube wire w.r.t. the first tube in the multi layer "<<Amg::toString(refTubePos, 2));
120  static const double layerPitch = 1./ std::sin(60*Gaudi::Units::deg);
121  const int layer = std::round(refTubePos.x() * layerPitch / readOutEle->tubePitch()) +1;
122  if (layer <= 0) {
123  THROW_EXCEPTION("Tube hit in nirvana -- It seems that the tube position "
124  <<Amg::toString(refTubePos, 2)<<", perp: "<<refTubePos.perp()
125  <<" is outside of the volume envelope "
126  <<m_detMgr->idHelperSvc()->toStringDetEl(readOutEle->identify())<<". ");
127  }
129  refTubePos = (readOutEle->globalToLocalTrans(gctx, readOutEle->measurementHash(layer,1)) * localToGlobal).translation();
130  const double tubePitches = refTubePos.y() / readOutEle->tubePitch();
131  unsigned int tube = std::round(tubePitches) + 1;
132  tube = std::max(1u, std::min(readOutEle->numTubesInLay(), tube));
135  const Amg::Transform3D closureCheck{readOutEle->globalToLocalTrans(gctx,
136  readOutEle->measurementHash(layer, tube))*localToGlobal};
137  if (!Amg::isIdentity(closureCheck)) {
138  ATH_MSG_WARNING("Correction needed "<<layer<<","<<tube<<" "<<Amg::toString(closureCheck));
139  if (closureCheck.translation().y() > 0) ++tube;
140  else --tube;
141  }
142 
143  const IdentifierHash tubeHash = readOutEle->measurementHash(layer, tube);
144  const Identifier tubeId = readOutEle->measurementId(tubeHash);
145  {
146  const Amg::Transform3D closureCheck{readOutEle->globalToLocalTrans(gctx, tubeHash)*localToGlobal};
147  if (!Amg::isIdentity(closureCheck)) {
148  THROW_EXCEPTION("Tube hit in Nirvana -- It seems that the tube position "
149  <<Amg::toString(refTubePos, 2)<<", perp: "<<refTubePos.perp()
150  <<" is outside of the volume envelope "
151  <<m_detMgr->idHelperSvc()->toStringDetEl(readOutEle->identify())<<". "
152  <<"Layer: "<<layer<<", tube: "<<tube<<" "
153  <<Amg::toString(closureCheck)
154  <<"tube volume : "<<touchHist->GetVolume(0)->GetName()
155  <<" mdt chamber: "<<touchHist->GetVolume(2)->GetName());
156  }
157  }
158  ATH_MSG_VERBOSE("Tube & layer number candidate "<<tube<<", "<<layer<<" back and forth transformation "
159  <<Amg::toString(closureCheck));
160  return tubeId;
161 }
162 
163 }
xAOD::MuonSimHit_v1
Definition: MuonSimHit_v1.h:18
MdtSensitiveDetector.h
MuonGMR4::MdtReadoutElement::numTubesInLay
unsigned int numTubesInLay() const
Returns the number of tubes per layer.
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
CxxUtils::tokenize
std::vector< std::string > tokenize(const std::string &the_str, std::string_view delimiters)
Splits the string into smaller substrings.
Definition: Control/CxxUtils/Root/StringUtils.cxx:15
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
MuonGMR4::MdtReadoutElement::measurementHash
static IdentifierHash measurementHash(unsigned int layerNumber, unsigned int tubeNumber)
Transform the layer and tube number to the measurementHash.
TrackHelper.h
MuonGM::round
float round(const float toRound, const unsigned int decimals)
Definition: Mdt.cxx:27
deg
#define deg
Definition: SbPolyhedron.cxx:17
MuonGMR4::MuonReadoutElement::globalToLocalTrans
Amg::Transform3D globalToLocalTrans(const ActsGeometryContext &ctx) const
Transformations to translate between local <-> global coordinates.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/MuonReadoutElement.cxx:78
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
Trk::u
@ u
Enums for curvilinear frames.
Definition: ParamDefs.h:77
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
MuonGMR4::MdtReadoutElement::measurementId
Identifier measurementId(const IdentifierHash &measHash) const override final
Converts the measurement hash back to the full Identifier.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/MdtReadoutElement.cxx:47
TrackHelper
Definition: TrackHelper.h:14
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
MuonGMR4
The ReadoutGeomCnvAlg converts the Run4 Readout geometry build from the GeoModelXML into the legacy M...
Definition: MdtCalibInput.h:19
POOLtoEI_tf.getTransform
def getTransform()
Definition: POOLtoEI_tf.py:103
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
CxxUtils
Definition: aligned_vector.h:29
MdtIdHelper
Definition: MdtIdHelper.h:61
Amg::isIdentity
bool isIdentity(const Amg::Transform3D &trans)
Checks whether the transformation is the Identity transformation.
Definition: GeoPrimitivesHelpers.h:393
ActsGeometryContext
Include the GeoPrimitives which need to be put first.
Definition: ActsGeometryContext.h:27
CLHEPtoEigenConverter.h
Utils.h
MuonGMR4::MdtReadoutElement
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MdtReadoutElement.h:22
MuonGMR4::MuonReadoutElement::identify
Identifier identify() const override final
Return the athena identifier.
MuonGMR4::MdtReadoutElement::tubePitch
double tubePitch() const
Returns the pitch between 2 tubes in a layer.
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
THROW_EXCEPTION
#define THROW_EXCEPTION(MESSAGE)
Definition: throwExcept.h:10
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
unit
const PlainObject unit() const
This is a plugin that makes Eigen look like CLHEP & defines some convenience methods.
Definition: AmgMatrixBasePlugin.h:21
xAOD::MuonSimHit_v1::localPosition
ConstVectorMap< 3 > localPosition() const
Returns the local postion of the traversing particle.
Definition: xAODMuonSimHit_V1.cxx:60
CxxUtils::atoi
int atoi(std::string_view str)
Helper functions to unpack numbers decoded in string into integers and doubles The strings are requir...
Definition: Control/CxxUtils/Root/StringUtils.cxx:85
ActsTrk
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
Definition: MuonDetectorBuilderTool.cxx:55
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
ReadHandle.h
Handle class for reading from StoreGate.
HitID
int HitID
Definition: GenericMuonSimHit.h:13
sTgcDigitEffiDump.multiLayer
int multiLayer
Definition: sTgcDigitEffiDump.py:36
NSWL1::globalToLocal
Polygon globalToLocal(const Polygon &pol, float z, const Trk::PlaneSurface &surf)
Definition: GeoUtils.cxx:103
calibdata.tube
tube
Definition: calibdata.py:31
generate::Zero
void Zero(TH1D *hin)
Definition: generate.cxx:32
Identifier
Definition: IdentifierFieldParser.cxx:14