ATLAS Offline Software
TgcSensitiveDetector.cxx
Go to the documentation of this file.
1 
2 /*
3  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
4 */
5 #include "TgcSensitiveDetector.h"
7 
8 #include "G4ThreeVector.hh"
9 #include "G4Trd.hh"
10 #include "G4Geantino.hh"
11 #include "G4ChargedGeantino.hh"
12 
13 #include "MCTruth/TrackHelper.h"
14 #include <sstream>
15 
18 #include "GaudiKernel/SystemOfUnits.h"
19 #include "GeoModelHelpers/throwExcept.h"
20 
21 using namespace ActsTrk;
22 
23 namespace {
24  constexpr double tolerance = 10. * Gaudi::Units::micrometer;
25 }
26 // construction/destruction
27 namespace MuonG4R4 {
28 
29 TgcSensitiveDetector::TgcSensitiveDetector(const std::string& name,
30  const std::string& output_key,
31  const std::string& trf_storeKey,
32  const MuonGMR4::MuonDetectorManager* detMgr):
33  G4VSensitiveDetector{name},
35  m_writeHandle{output_key},
36  m_trfCacheKey{trf_storeKey},
37  m_detMgr{detMgr} {
38  m_trfCacheKey.initialize().ignore();
39 }
40 
41 void TgcSensitiveDetector::Initialize(G4HCofThisEvent*) {
42  if (m_writeHandle.isValid()) {
43  ATH_MSG_VERBOSE("Simulation hit container "<<m_writeHandle.fullKey()<<" is already written");
44  return;
45  }
46  if (!m_writeHandle.recordNonConst(std::make_unique<xAOD::MuonSimHitContainer>(),
47  std::make_unique<xAOD::MuonSimHitAuxContainer>()).isSuccess()) {
48  THROW_EXCEPTION("Failed to record "<<m_writeHandle.fullKey());
49  }
50  ATH_MSG_DEBUG("Output container "<<m_writeHandle.fullKey()<<" has been successfully created");
51 }
52 
53 G4bool TgcSensitiveDetector::ProcessHits(G4Step* aStep, G4TouchableHistory*) {
54 
55  G4Track* currentTrack = aStep->GetTrack();
56 
57  // TGC sensitive to charged particle only
58  if (currentTrack->GetDefinition()->GetPDGCharge() == 0.0) {
59  if (currentTrack->GetDefinition()!= G4Geantino::GeantinoDefinition()) return true;
60  else if (currentTrack->GetDefinition()==G4ChargedGeantino::ChargedGeantinoDefinition()) return true;
61  }
62 
64  constexpr double velCutOff = 10.*Gaudi::Units::micrometer / Gaudi::Units::second;
65  if (currentTrack->GetVelocity() < velCutOff) return true;
66 
67  const G4TouchableHistory* touchHist = static_cast<const G4TouchableHistory*>(currentTrack->GetTouchable());
68 
69  const MuonGMR4::TgcReadoutElement* readOutEle = getReadoutElement(touchHist);
70  if (!readOutEle) {
71  return false;
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  const Amg::Transform3D globalToLocal = getTransform(currentTrack->GetTouchable(), 0).inverse();
83  ATH_MSG_VERBOSE(" Track is inside volume "
84  <<currentTrack->GetTouchable()->GetHistory()->GetTopVolume()->GetName()
85  <<" transformation: "<<Amg::toString(globalToLocal));
86  const Amg::Vector3D locPos{globalToLocal*Amg::Hep3VectorToEigen(currentTrack->GetPosition())};
87  const Amg::Vector3D locDir{globalToLocal.linear()*Amg::Hep3VectorToEigen(currentTrack->GetMomentumDirection())};
88  ATH_MSG_VERBOSE("Track is located in "<<m_detMgr->idHelperSvc()->toStringDetEl(readOutEle->identify())
89  <<" at "<<Amg::toString(locPos)<<" pointing towards "<<Amg::toString(locDir, 3));
90 
92  std::optional<double> travelDist = Amg::intersect<3>(locPos, locDir, Amg::Vector3D::UnitX(), 0);
93  if (!travelDist) {
94  ATH_MSG_VERBOSE("Hit cannot be extrapolated into the gas gap origin");
95  return true;
96  }
97  const Amg::Vector3D lPosAtGap = locPos + (*travelDist) * locDir;
98  ATH_MSG_VERBOSE("Extrpolated by "<<(*travelDist)<<" mm to the gasGap center "<<Amg::toString(lPosAtGap, 2));
99 
100  const Amg::Vector3D gapCenterCross = globalToLocal.inverse() * lPosAtGap;
101  const Identifier etaHitID = getIdentifier(gctx, readOutEle, gapCenterCross, false);
102  if (!etaHitID.is_valid()) {
103  ATH_MSG_VERBOSE("No valid hit found");
104  return true;
105  }
106 
107  const double globalTime = currentTrack->GetGlobalTime() + (*travelDist) / currentTrack->GetVelocity();
108  const Amg::Transform3D gapTrans{readOutEle->globalToLocalTrans(gctx, etaHitID)};
109  const Amg::Vector3D locHitDir = gapTrans.linear() * Amg::Hep3VectorToEigen(currentTrack->GetMomentumDirection());
110  const Amg::Vector3D locHitPos = gapTrans * gapCenterCross;
111 
113  if (std::abs(locHitPos.z()) > tolerance) {
114  ATH_MSG_FATAL("The hit "<<Amg::toString(locHitPos)<<" doest not match "<<m_detMgr->idHelperSvc()->toString(etaHitID));
115  throw std::runtime_error("Picked wrong gas gap");
116  }
117 
119  readOutEle->releaseUnAlignedTrfs();
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 const MuonGMR4::TgcReadoutElement* TgcSensitiveDetector::getReadoutElement(const G4TouchableHistory* touchHist) const {
139  const std::string stationVolume = touchHist->GetVolume(2)->GetName();
140  const std::vector<std::string> volumeTokens = CxxUtils::tokenize(stationVolume, "_");
144  const size_t nTokens{volumeTokens.size()};
145  const TgcIdHelper& idHelper{m_detMgr->idHelperSvc()->tgcIdHelper()};
146  const std::string stationName{volumeTokens[nTokens-4].substr(0,3)};
147  const int stationEta = CxxUtils::atoi(volumeTokens[nTokens-2]);
148  const int stationPhi = CxxUtils::atoi(volumeTokens[nTokens-1]);
149  bool isValid{false};
150  const Identifier stationId = idHelper.elementID(stationName, stationEta, stationPhi, isValid);
151  if (!isValid) {
152  THROW_EXCEPTION("Failed to deduce station name from "+stationVolume);
153  }
154  return m_detMgr->getTgcReadoutElement(stationId);
155 }
156 
158  const MuonGMR4::TgcReadoutElement* readOutEle,
159  const Amg::Vector3D& hitAtGapPlane, bool phiGap) const {
160  const TgcIdHelper& idHelper{m_detMgr->idHelperSvc()->tgcIdHelper()};
161  const Identifier firstChan = idHelper.channelID(readOutEle->identify(), 1, phiGap, 1);
162 
163  const Amg::Vector3D locHitPos{readOutEle->globalToLocalTrans(gctx, firstChan) * hitAtGapPlane};
164 
165  const int gasGap = std::round(std::abs(locHitPos.z()) / readOutEle->gasGapPitch()) + 1;
166  ATH_MSG_VERBOSE("Detector element: "<<m_detMgr->idHelperSvc()->toStringDetEl(firstChan)
167  <<" locPos: "<<Amg::toString(locHitPos, 2)
168  <<" gap thickness: "<<readOutEle->gasGapPitch()
169  <<" gasGap: "<<gasGap);
170 
171  return idHelper.channelID(readOutEle->identify(), gasGap, phiGap, 1);
172 }
173 
174 }
python.SystemOfUnits.second
int second
Definition: SystemOfUnits.py:120
xAOD::MuonSimHit_v1
Definition: MuonSimHit_v1.h:18
dumpTgcDigiDeadChambers.gasGap
list gasGap
Definition: dumpTgcDigiDeadChambers.py:33
MuonG4R4::TgcSensitiveDetector::m_detMgr
const MuonGMR4::MuonDetectorManager * m_detMgr
Pointer to the underlying detector manager.
Definition: TgcSensitiveDetector.h:60
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
xAOD::MuonSimHit_v1::setIdentifier
void setIdentifier(const Identifier &id)
Sets the global ATLAS identifier.
Definition: xAODMuonSimHit_V1.cxx:43
MuonG4R4::TgcSensitiveDetector::m_writeHandle
SG::WriteHandle< xAOD::MuonSimHitContainer > m_writeHandle
Definition: TgcSensitiveDetector.h:50
MuonGMR4::MuonDetectorManager
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MuonDetectorManager.h:61
dumpTgcDigiDeadChambers.stationName
dictionary stationName
Definition: dumpTgcDigiDeadChambers.py:30
TgcIdHelper
Definition: TgcIdHelper.h:50
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
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
MuonGM::round
float round(const float toRound, const unsigned int decimals)
Definition: Mdt.cxx:27
MuonG4R4::TgcSensitiveDetector::m_trfCacheKey
SG::ReadHandleKey< ActsTrk::DetectorAlignStore > m_trfCacheKey
Definition: TgcSensitiveDetector.h:55
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
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
isValid
bool isValid(const T &p)
Definition: AtlasPID.h:214
THROW_EXCEPTION
#define THROW_EXCEPTION(MSG)
Definition: MMReadoutElement.cxx:48
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
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
AthMessaging
Class to provide easy MsgStream access and capabilities.
Definition: AthMessaging.h:55
MuonGMR4::TgcReadoutElement::gasGapPitch
double gasGapPitch() const
Returns the thickness of the gasGap.
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::TgcSensitiveDetector::getIdentifier
Identifier getIdentifier(const ActsGeometryContext &gctx, const MuonGMR4::TgcReadoutElement *readOutEle, const Amg::Vector3D &hitAtGapPlane, bool phiGap) const
Definition: TgcSensitiveDetector.cxx:157
xAOD::MuonSimHit_v1::setLocalDirection
void setLocalDirection(MeasVector< 3 > vec)
Sets the local direction of the traversing particle.
Definition: xAODMuonSimHit_V1.cxx:61
MuonGMR4::MuonReadoutElement::identify
Identifier identify() const override final
Return the athena identifier.
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
TgcSensitiveDetector.h
python.copyTCTOutput.locDir
locDir
Definition: copyTCTOutput.py:113
Muon::IMuonIdHelperSvc::tgcIdHelper
virtual const TgcIdHelper & tgcIdHelper() const =0
access to TgcIdHelper
Muon::IMuonIdHelperSvc::toString
virtual std::string toString(const Identifier &id) const =0
print all fields to string
MuonGMR4::MuonReadoutElement::releaseUnAlignedTrfs
void releaseUnAlignedTrfs() const
Releases all cached transforms that are not connected with alignment.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/MuonReadoutElement.cxx:62
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
TgcIdHelper::channelID
Identifier channelID(int stationName, int stationEta, int stationPhi, int gasGap, int isStrip, int channel) const
Definition: TgcIdHelper.cxx:583
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
MuonG4R4::TgcSensitiveDetector::Initialize
void Initialize(G4HCofThisEvent *HCE) override final
member functions
Definition: TgcSensitiveDetector.cxx:41
MuonG4R4::TgcSensitiveDetector::getReadoutElement
const MuonGMR4::TgcReadoutElement * getReadoutElement(const G4TouchableHistory *touchHist) const
Retrieves the matching readout element to a G4 hit.
Definition: TgcSensitiveDetector.cxx:137
NSWL1::globalToLocal
Polygon globalToLocal(const Polygon &pol, float z, const Trk::PlaneSurface &surf)
Definition: GeoUtils.cxx:103
MuonGMR4::TgcReadoutElement
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/TgcReadoutElement.h:20
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
MuonG4R4::TgcSensitiveDetector::ProcessHits
G4bool ProcessHits(G4Step *aStep, G4TouchableHistory *ROhist) override final
Definition: TgcSensitiveDetector.cxx:53