ATLAS Offline Software
sTgcSensitiveDetector.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
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 "GaudiKernel/SystemOfUnits.h"
18 #include "GeoModelHelpers/throwExcept.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 sTgcSensitiveDetector::sTgcSensitiveDetector(const std::string& name,
33  const std::string& output_key,
34  const std::string& trf_storeKey,
35  const MuonGMR4::MuonDetectorManager* detMgr):
36  G4VSensitiveDetector{name},
38  m_writeHandle{output_key},
39  m_trfCacheKey{trf_storeKey},
40  m_detMgr{detMgr} {
41  m_trfCacheKey.initialize().ignore();
42 }
43 
44 void sTgcSensitiveDetector::Initialize(G4HCofThisEvent*) {
45  if (m_writeHandle.isValid()) {
46  ATH_MSG_VERBOSE("Simulation hit container "<<m_writeHandle.fullKey()<<" is already written");
47  return;
48  }
49  if (!m_writeHandle.recordNonConst(std::make_unique<xAOD::MuonSimHitContainer>(),
50  std::make_unique<xAOD::MuonSimHitAuxContainer>()).isSuccess()) {
51  THROW_EXCEPTION(" Failed to record "<<m_writeHandle.fullKey());
52  }
53  ATH_MSG_DEBUG("Output container "<<m_writeHandle.fullKey()<<" has been successfully created");
54 }
55 
56 G4bool sTgcSensitiveDetector::ProcessHits(G4Step* aStep,G4TouchableHistory*) {
57 
58 
59  G4Track* currentTrack = aStep->GetTrack();
60 
61  // MDTs sensitive to charged particle only
62  if (currentTrack->GetDefinition()->GetPDGCharge() == 0.0) {
63  if (currentTrack->GetDefinition()!= G4Geantino::GeantinoDefinition()) return true;
64  else if (currentTrack->GetDefinition()==G4ChargedGeantino::ChargedGeantinoDefinition()) return true;
65  }
66 
68  constexpr double velCutOff = 10.*Gaudi::Units::micrometer / Gaudi::Units::second;
69  if (currentTrack->GetVelocity() < velCutOff) return true;
70 
71  const G4TouchableHistory* touchHist = static_cast<const G4TouchableHistory*>(currentTrack->GetTouchable());
72 
73  ActsGeometryContext gctx{};
74 
76  if (!trfStoreHandle.isValid()) {
77  ATH_MSG_FATAL("Failed to retrieve "<<m_trfCacheKey.fullKey()<<".");
78  return false;
79  }
80  gctx.setStore(std::make_unique<DetectorAlignStore>(*trfStoreHandle));
81 
82 
83  const MuonGMR4::sTgcReadoutElement* readOutEle = getReadoutElement(gctx, touchHist);
84 
85 
86 
87  const Amg::Transform3D globalToLocal = getTransform(touchHist, 0).inverse();
88  ATH_MSG_VERBOSE(" Track is inside volume "
89  << touchHist->GetHistory()->GetTopVolume()->GetName()
90  <<" transformation: "<<Amg::toString(globalToLocal));
91  // transform pre and post step positions to local positions
92 
93  const Amg::Vector3D localPos{globalToLocal*Amg::Hep3VectorToEigen(currentTrack->GetPosition())};
94  const Amg::Vector3D localDir{globalToLocal.linear()*Amg::Hep3VectorToEigen(currentTrack->GetMomentumDirection())};
95  ATH_MSG_VERBOSE("Entry / exit point in "<<m_detMgr->idHelperSvc()->toStringDetEl(readOutEle->identify())
96  <<" "<<Amg::toString(localPos, 2)<<" / "<<Amg::toString(localDir, 2));
97 
98 
99  // The middle of the gas gap is at X= 0
100  std::optional<double> travelDist = Amg::intersect<3>(localPos, localDir, Amg::Vector3D::UnitZ(), 0.);
101  if (!travelDist) return true;
102  const Amg::Vector3D locGapCross = localPos + (*travelDist) * localDir;
103  ATH_MSG_VERBOSE("Propagation to the gas gap center: "<<Amg::toString(locGapCross, 2));
104  const Amg::Vector3D gapCenterCross = globalToLocal.inverse() * locGapCross;
105 
106  const Identifier etaHitID = getIdentifier(gctx, readOutEle,
107  gapCenterCross, sTgcIdHelper::Strip);
108  if (!etaHitID.is_valid()) {
109  ATH_MSG_VERBOSE("No valid hit found");
110  return true;
111  }
112  const double globalTime = currentTrack->GetGlobalTime() + (*travelDist) / currentTrack->GetVelocity();
113  const Amg::Transform3D gapTrans{readOutEle->globalToLocalTrans(gctx, etaHitID)};
114  const Amg::Vector3D locHitDir = gapTrans.linear() * Amg::Hep3VectorToEigen(currentTrack->GetMomentumDirection());
115  const Amg::Vector3D locHitPos = gapTrans * gapCenterCross;
117  if (std::abs(locHitPos.z()) > tolerance) {
118  THROW_EXCEPTION("The hit "<<Amg::toString(locHitPos)<<" doest not match "<<m_detMgr->idHelperSvc()->toString(etaHitID)
119  <<"Wrong gas gap picked");
120  }
121 
122  xAOD::MuonSimHit* hit = new xAOD::MuonSimHit();
123  m_writeHandle->push_back(hit);
124 
125  TrackHelper trHelp(aStep->GetTrack());
126  hit->setIdentifier(etaHitID);
127  hit->setLocalPosition(xAOD::toStorage(locHitPos));
128  hit->setLocalDirection(xAOD::toStorage(locHitDir));
129  hit->setMass(currentTrack->GetDefinition()->GetPDGMass());
130  hit->setGlobalTime(globalTime);
131  hit->setPdgId(currentTrack->GetDefinition()->GetPDGEncoding());
132  hit->setEnergyDeposit(aStep->GetTotalEnergyDeposit());
133  hit->setKineticEnergy(currentTrack->GetKineticEnergy());
135  return true;
136 }
137 
139  const MuonGMR4::sTgcReadoutElement* readOutEle,
140  const Amg::Vector3D& hitAtGapPlane,
142 
143  const sTgcIdHelper& idHelper{m_detMgr->idHelperSvc()->stgcIdHelper()};
144  const Identifier firstChan = idHelper.channelID(readOutEle->identify(),
145  readOutEle->multilayer(), 1, chType, 1);
146 
147  const Amg::Vector3D locHitPos{readOutEle->globalToLocalTrans(gctx, firstChan) * hitAtGapPlane};
148  ATH_MSG_VERBOSE("Detector element: "<<m_detMgr->idHelperSvc()->toStringDetEl(firstChan)
149  <<" locPos: "<<Amg::toString(locHitPos, 2)
150  <<" gap thickness "<<readOutEle->gasGapPitch()
151  <<" gasGap: "<< (std::abs(locHitPos.z()) / readOutEle->gasGapPitch()) + 1);
152 
153  const int gasGap = std::round(std::abs(locHitPos.z()) / readOutEle->gasGapPitch()) + 1;
154  return idHelper.channelID(readOutEle->identify(),readOutEle->multilayer(), gasGap, chType, 1);
155 }
157  const G4TouchableHistory* touchHist) const {
158 
159 
161  const std::string& stationVolume = touchHist->GetVolume(3)->GetName();
163  const std::vector<std::string> volumeTokens = tokenize(stationVolume.substr(stationVolume.rfind("Q")), "_");
164  ATH_MSG_VERBOSE("Name of the station volume is "<<volumeTokens);
165  if (volumeTokens.size() != 4) {
166  THROW_EXCEPTION("Cannot deduce the station name from "<<stationVolume);
167  }
169  const std::string stName = volumeTokens[0][1] == 'S' ? "STS" : "STL";
170  const int stationEta = atoi(volumeTokens[2]);
171  const int stationPhi = atoi(volumeTokens[3]);
172 
173  const sTgcIdHelper& idHelper{m_detMgr->idHelperSvc()->stgcIdHelper()};
174  const Identifier detElIdMl1 = idHelper.channelID(idHelper.stationNameIndex(stName), stationEta, stationPhi, 1, 1,
175  sTgcIdHelper::sTgcChannelTypes::Strip, 1);
176  const Identifier detElIdMl2 = idHelper.multilayerID(detElIdMl1, 2);
177  const sTgcReadoutElement* readOutElemMl1 = m_detMgr->getsTgcReadoutElement(detElIdMl1);
178  const sTgcReadoutElement* readOutElemMl2 = m_detMgr->getsTgcReadoutElement(detElIdMl2);
179  if (!readOutElemMl1 || !readOutElemMl2) {
180  THROW_EXCEPTION("Failed to retrieve a valid detector element from "
181  <<m_detMgr->idHelperSvc()->toStringDetEl(detElIdMl1)<<" "<<stationVolume);
182  }
184  const Amg::Vector3D transformCenter = getTransform(touchHist, 0).translation();
187  const Amg::Vector3D centerMl2 = readOutElemMl2->center(gctx, detElIdMl2);
188  return std::abs(centerMl2.z()) - tolerance <= std::abs(transformCenter.z()) ? readOutElemMl2 : readOutElemMl1;
189 }
190 }
python.SystemOfUnits.second
int second
Definition: SystemOfUnits.py:120
xAOD::MuonSimHit_v1
Definition: MuonSimHit_v1.h:18
MuonG4R4::sTgcSensitiveDetector::getIdentifier
Identifier getIdentifier(const ActsGeometryContext &gctx, const MuonGMR4::sTgcReadoutElement *readOutEle, const Amg::Vector3D &hitAtGapPlane, sTgcIdHelper::sTgcChannelTypes chType) const
Definition: sTgcSensitiveDetector.cxx:138
MuonGMR4::sTgcReadoutElement::multilayer
int multilayer() const
Returns the multilayer of the sTgcReadoutElement.
dumpTgcDigiDeadChambers.gasGap
list gasGap
Definition: dumpTgcDigiDeadChambers.py:33
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
Muon::IMuonIdHelperSvc::stgcIdHelper
virtual const sTgcIdHelper & stgcIdHelper() const =0
access to TgcIdHelper
xAOD::MuonSimHit_v1::setIdentifier
void setIdentifier(const Identifier &id)
Sets the global ATLAS identifier.
Definition: xAODMuonSimHit_V1.cxx:43
MuonGMR4::MuonDetectorManager
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MuonDetectorManager.h:61
MuonG4R4::sTgcSensitiveDetector::m_writeHandle
SG::WriteHandle< xAOD::MuonSimHitContainer > m_writeHandle
Definition: sTgcSensitiveDetector.h:128
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
sTgcIdHelper::channelID
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int channelType, int channel) const
Definition: sTgcIdHelper.cxx:886
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
xAOD::MuonSimHit_v1::setPdgId
void setPdgId(int id)
Sets the pdgID of the traversing particle.
MuonG4R4::getTransform
Amg::Transform3D getTransform(const G4VTouchable *history, unsigned int level)
Extracts the local -> global transformation from a TouchableHistory at a given level.
Definition: MuonSpectrometer/MuonPhaseII/MuonG4/MuonSensitiveDetectorsR4/MuonSensitiveDetectorsR4/Utils.h:24
TrackHelper.h
MuonGMR4::sTgcReadoutElement::gasGapPitch
double gasGapPitch() const
Distance between 2 gas gaps.
MuonGM::round
float round(const float toRound, const unsigned int decimals)
Definition: Mdt.cxx:27
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:68
sTgcIdHelper::Strip
@ Strip
Definition: sTgcIdHelper.h:190
Muon::IMuonIdHelperSvc::toStringDetEl
virtual std::string toStringDetEl(const Identifier &id) const =0
print all fields up to detector element to string
MuonSimHitAuxContainer.h
xAOD::MuonSimHit_v1::setLocalPosition
void setLocalPosition(MeasVector< 3 > vec)
Sets the local position of the traversing particle.
Definition: xAODMuonSimHit_V1.cxx:55
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
xAOD::MuonSimHit_v1::setGenParticleLink
void setGenParticleLink(const HepMcParticleLink &link)
Sets the link to the HepMC particle producing this hit.
Definition: xAODMuonSimHit_V1.cxx:82
THROW_EXCEPTION
#define THROW_EXCEPTION(MSG)
Definition: MMReadoutElement.cxx:48
sTgcIdHelper::sTgcChannelTypes
sTgcChannelTypes
Definition: sTgcIdHelper.h:190
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::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
MuonGMR4
Definition: ChamberAssembleTool.h:16
MuonG4R4::sTgcSensitiveDetector::m_detMgr
const MuonGMR4::MuonDetectorManager * m_detMgr
Pointer to the underlying detector manager.
Definition: sTgcSensitiveDetector.h:136
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
CxxUtils
Definition: aligned_vector.h:29
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)
AthMessaging
Class to provide easy MsgStream access and capabilities.
Definition: AthMessaging.h:55
python.SystemOfUnits.micrometer
int micrometer
Definition: SystemOfUnits.py:71
ActsGeometryContext
Include the GeoPrimitives which need to be put first.
Definition: ActsGeometryContext.h:27
CLHEPtoEigenConverter.h
tolerance
Definition: suep_shower.h:17
Utils.h
xAOD::MuonSimHit_v1::setEnergyDeposit
void setEnergyDeposit(const float deposit)
Sets the energy deposited by the traversing particle inside the gas volume.
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
MuonG4R4::sTgcSensitiveDetector::ProcessHits
G4bool ProcessHits(G4Step *aStep, G4TouchableHistory *ROhist) override final
Definition: sTgcSensitiveDetector.cxx:56
xAOD::MuonSimHit_v1::setLocalDirection
void setLocalDirection(MeasVector< 3 > vec)
Sets the local direction of the traversing particle.
Definition: xAODMuonSimHit_V1.cxx:61
sTgcIdHelper
Definition: sTgcIdHelper.h:55
MuonGMR4::MuonReadoutElement::identify
Identifier identify() const override final
Return the athena identifier.
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
MuonGMR4::sTgcReadoutElement
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/sTgcReadoutElement.h:21
MuonG4R4::sTgcSensitiveDetector::getReadoutElement
const MuonGMR4::sTgcReadoutElement * getReadoutElement(const ActsGeometryContext &gctx, const G4TouchableHistory *touchHist) const
Retrieves the matching readout element to a G4 hit.
Definition: sTgcSensitiveDetector.cxx:156
sTgcSensitiveDetector.h
MuonG4R4::sTgcSensitiveDetector::Initialize
void Initialize(G4HCofThisEvent *HCE) override final
member functions
Definition: sTgcSensitiveDetector.cxx:44
MuonG4R4::sTgcSensitiveDetector::m_trfCacheKey
SG::ReadHandleKey< ActsTrk::DetectorAlignStore > m_trfCacheKey
Definition: sTgcSensitiveDetector.h:133
Muon::IMuonIdHelperSvc::toString
virtual std::string toString(const Identifier &id) const =0
print all fields to string
MuonGMR4::MuonDetectorManager::idHelperSvc
const Muon::IMuonIdHelperSvc * idHelperSvc() const
Returns a pointer to the central MuonIdHelperSvc.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/MuonDetectorManager.cxx:132
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:34
TrackHelper::GenerateParticleLink
HepMcParticleLink GenerateParticleLink()
Generates a creates new HepMcParticleLink object on the stack based on GetUniqueID(),...
Definition: TrackHelper.h:35
NSWL1::globalToLocal
Polygon globalToLocal(const Polygon &pol, float z, const Trk::PlaneSurface &surf)
Definition: GeoUtils.cxx:103
xAOD::MuonSimHit_v1::setGlobalTime
void setGlobalTime(const float time)
Sets the time of the traversing particle.
xAOD::MuonSimHit
MuonSimHit_v1 MuonSimHit
Defined the version of the MuonSimHit.
Definition: MuonSimHit.h:12