ATLAS Offline Software
MmSensitiveDetector.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "MmSensitiveDetector.h"
7 #include "G4ThreeVector.hh"
8 #include "G4Trd.hh"
9 #include "G4Geantino.hh"
10 #include "G4ChargedGeantino.hh"
11 
12 #include "MCTruth/TrackHelper.h"
13 #include <sstream>
14 
17 #include "GeoModelKernel/throwExcept.h"
18 #include "GaudiKernel/SystemOfUnits.h"
19 
20 
21 using namespace MuonGMR4;
22 using namespace CxxUtils;
23 using namespace ActsTrk;
24 
25 namespace {
26  constexpr double tolerance = 10. * Gaudi::Units::micrometer;
27 }
28 
29 // construction/destruction
30 namespace MuonG4R4 {
31 
32 G4bool MmSensitiveDetector::ProcessHits(G4Step* aStep,G4TouchableHistory*) {
33 
34  if (!processStep(aStep)) {
35  return true;
36  }
37  const ActsGeometryContext gctx{getGeoContext()};
38 
39  const G4TouchableHistory* touchHist = static_cast<const G4TouchableHistory*>(aStep->GetPreStepPoint()->GetTouchable());
40  const MuonGMR4::MmReadoutElement* readOutEle = getReadoutElement(gctx, touchHist);
41 
42  const Amg::Transform3D localToGlobal = getTransform(touchHist, 0);
43  ATH_MSG_VERBOSE(" Track is inside volume "<< touchHist->GetHistory()->GetTopVolume()->GetName()
44  <<" transformation: "<<Amg::toString(localToGlobal));
45 
46  const Identifier hitID = getIdentifier(gctx, readOutEle, localToGlobal.translation());
47  if (!hitID.is_valid()) {
48  ATH_MSG_VERBOSE("No valid hit found");
49  return true;
50  }
52  const Amg::Transform3D toGasGap{readOutEle->globalToLocalTrans(gctx, hitID)};
53  propagateAndSaveStrip(hitID, toGasGap, aStep);
54  return true;
55 }
56 
57 Identifier MmSensitiveDetector::getIdentifier(const ActsGeometryContext& gctx,
58  const MuonGMR4::MmReadoutElement* readOutEle,
59  const Amg::Vector3D& hitAtGapPlane) const {
61  for (unsigned int gap = 1; gap <= readOutEle->nGasGaps(); ++gap){
62  const Amg::Vector3D gapCentre = readOutEle->center(gctx, MmReadoutElement::createHash(gap, 0));
63  ATH_MSG_VERBOSE("Try to match "<<Amg::toString(hitAtGapPlane)<<" to "<<Amg::toString(gapCentre)
64  <<" in "<<m_detMgr->idHelperSvc()->toStringDetEl(readOutEle->identify())<<" dZ: "
65  <<std::abs(gapCentre.z() - hitAtGapPlane.z()));
66  if (std::abs(gapCentre.z() - hitAtGapPlane.z()) < tolerance) {
67  ATH_MSG_VERBOSE("Assign hit "<<Amg::toString(hitAtGapPlane)<<" to "
68  <<m_detMgr->idHelperSvc()->toStringDetEl(readOutEle->identify())<<" gasGap: "<<gap);
69  return readOutEle->measurementId(MmReadoutElement::createHash(gap, 1));
70  }
71  }
72  THROW_EXCEPTION("Invalid gasgap matching for hit "<<Amg::toString(hitAtGapPlane)<<" and detector element "
73  <<m_detMgr->idHelperSvc()->toStringDetEl(readOutEle->identify()));
74  return Identifier{};
75 }
76 const MuonGMR4::MmReadoutElement* MmSensitiveDetector::getReadoutElement(const ActsGeometryContext& gctx,
77  const G4TouchableHistory* touchHist) const {
79  const std::string& stationVolume = touchHist->GetVolume(4)->GetName();
81  const std::vector<std::string> volumeTokens = tokenize(stationVolume.substr(stationVolume.rfind("NSW") + 4), "_");
82  ATH_MSG_VERBOSE("Name of the station volume is "<<volumeTokens);
83  if (volumeTokens.size() != 4) {
84  THROW_EXCEPTION(" Cannot deduce the station name from "<<stationVolume);
85  }
87  const std::string stName = volumeTokens[0][0] == 'S' ? "MMS" : "MML";
88  const int stationEta = atoi(volumeTokens[2]);
89  const int stationPhi = atoi(volumeTokens[3]);
90 
91  const MmIdHelper& idHelper{m_detMgr->idHelperSvc()->mmIdHelper()};
92  const Identifier detElIdMl1 = idHelper.channelID(idHelper.stationNameIndex(stName), stationEta, stationPhi, 1, 1, 1);
93  const Identifier detElIdMl2 = idHelper.multilayerID(detElIdMl1, 2);
94  const MmReadoutElement* readOutElemMl1 = m_detMgr->getMmReadoutElement(detElIdMl1);
95  const MmReadoutElement* readOutElemMl2 = m_detMgr->getMmReadoutElement(detElIdMl2);
96  if (!readOutElemMl1 || !readOutElemMl2) {
97  THROW_EXCEPTION(" Failed to retrieve a valid detector element from "
98  <<m_detMgr->idHelperSvc()->toStringDetEl(detElIdMl1)<<" "<<stationVolume);
99  }
101  const Amg::Vector3D transformCenter = getTransform(touchHist, 0).translation();
104  const Amg::Vector3D centerMl2 = readOutElemMl2->center(gctx, detElIdMl2);
105  ATH_MSG_VERBOSE("Local gap position "<<Amg::toString(centerMl2)<<" transform center "<<Amg::toString(transformCenter));
106  return std::abs(centerMl2.z()) - tolerance <= std::abs(transformCenter.z()) ? readOutElemMl2 : readOutElemMl1;
107 }
108 }
MuonGMR4::MmReadoutElement
Definition: MmReadoutElement.h:18
MuonGMR4::MmReadoutElement::createHash
static IdentifierHash createHash(const int gasGap, const int strip)
MuonGMR4::MmReadoutElement::nGasGaps
unsigned int nGasGaps() const
Returns the number of gas gaps.
MmSensitiveDetector.h
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
TrackHelper.h
Muon::MuonStationIndex::stName
const std::string & stName(StIndex index)
convert StIndex into a string
Definition: MuonStationIndex.cxx:104
MuonSimHitAuxContainer.h
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
CaloSwCorrections.gap
def gap(flags, cells_name, *args, **kw)
Definition: CaloSwCorrections.py:212
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
python.SystemOfUnits.micrometer
float micrometer
Definition: SystemOfUnits.py:80
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
CxxUtils
Definition: aligned_vector.h:29
MuonGMR4::MmReadoutElement::measurementId
Identifier measurementId(const IdentifierHash &measHash) const override final
Converts the measurement hash back to the full Identifier.
MuonGMR4::MuonReadoutElement::center
Amg::Vector3D center(const ActsGeometryContext &ctx) const
Returns the detector center (Which is the same as the detector center of the first measurement layer)
ActsGeometryContext
Include the GeoPrimitives which need to be put first.
Definition: ActsGeometryContext.h:27
CLHEPtoEigenConverter.h
tolerance
Definition: suep_shower.h:17
Utils.h
MuonGMR4::MuonReadoutElement::identify
Identifier identify() const override final
Return the athena identifier.
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
THROW_EXCEPTION
#define THROW_EXCEPTION(MESSAGE)
Definition: throwExcept.h:10
MmIdHelper
Definition: MmIdHelper.h:54
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: MSTrackingVolumeBuilder.cxx:25
Identifier
Definition: IdentifierFieldParser.cxx:14