ATLAS Offline Software
Loading...
Searching...
No Matches
MuonPhaseII/MuonDigitization/MdtDigitizationR4/src/MdtDigitizationTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
10#include "CLHEP/Random/RandGaussZiggurat.h"
11namespace{
12 constexpr double timeToTdcCnv = 1. / IMdtCalibrationTool::tdcBinSize;
13}
14
15namespace MuonR4 {
16
17 MdtDigitizationTool::MdtDigitizationTool(const std::string& type, const std::string& name, const IInterface* pIID):
18 MuonDigitizationTool{type,name, pIID} {}
19
22 ATH_CHECK(m_writeKey.initialize());
23 ATH_CHECK(m_calibDbKey.initialize());
24 ATH_CHECK(m_badTubeKey.initialize());
26 return StatusCode::SUCCESS;
27 }
28 StatusCode MdtDigitizationTool::digitize(const EventContext& ctx,
29 const TimedHits& hitsToDigit,
30 xAOD::MuonSimHitContainer* sdoContainer) const {
31
32
33 const MdtIdHelper& idHelper{m_idHelperSvc->mdtIdHelper()};
34 // Prepare the temporary cache
35
36 using DigitSDOPair = std::pair<std::unique_ptr<MdtDigit>, TimedHit>;
38 const MuonCalib::MdtCalibDataContainer* calibData{nullptr};
39 ATH_CHECK(SG::get(calibData, m_calibDbKey, ctx));
40 const MdtCondDbData* badTubes{nullptr};
41 ATH_CHECK(SG::get(badTubes, m_badTubeKey, ctx));
42 const Muon::TwinTubeMap* twinTubes{nullptr};
43 ATH_CHECK(SG::get(twinTubes, m_twinTubeKey, ctx));
44 CLHEP::HepRandomEngine* rndEngine = getRandomEngine(ctx);
45
46 DigiCache digitCache{};
47
48 xAOD::ChamberViewer viewer{hitsToDigit, m_idHelperSvc.get()};
49 do {
50 Identifier lastTube{};
51 double deadTime{0.};
52 std::vector<DigitSDOPair> digitsInChamber{};
53
54 for (const TimedHitPtr<xAOD::MuonSimHit>& simHit : viewer) {
55 const Identifier hitId{simHit->identify()};
57 if (!badTubes->isGood(hitId)) {
58 ATH_MSG_VERBOSE("Hit "<<m_idHelperSvc->toString(hitId)<<" is rejected due to masking in DB.");
59 continue;
60 }
61 ATH_MSG_VERBOSE("Process sim hit "<<m_idHelperSvc->toString(hitId) <<", pdgId: "<<simHit->pdgId()<<", "
62 <<Amg::toString(xAOD::toEigen(simHit->localPosition()))<<" + "<<Amg::toString(xAOD::toEigen(simHit->localDirection()))
63 <<", time: "<<simHit->globalTime()<<", energy: "<<simHit->kineticEnergy() / Gaudi::Units::GeV
64 <<" [GeV], mass: "<<simHit->mass()<<", deposited energy: "<<simHit->energyDeposit() / Gaudi::Units::eV
65 <<" [eV], genLink: "<<simHit->genParticleLink());
66 const MuonGMR4::MdtReadoutElement* readOutEle = m_detMgr->getMdtReadoutElement(hitId);
67 const IdentifierHash measHash{readOutEle->measurementHash(hitId)};
68 if (m_digitizeMuonOnly && !MC::isMuon(simHit)) {
69 ATH_MSG_VERBOSE("Hit is not from a muon");
70 continue;
71 }
72
73 const Amg::Vector3D locPos{xAOD::toEigen(simHit->localPosition())};
74 const double distRO = readOutEle->distanceToReadout(measHash, locPos);
75
76 const MdtDigiToolInput digiInput(std::abs(locPos.perp()), distRO, 0., 0., 0., 0., hitId);
77 const MdtDigiToolOutput digiOutput(m_digiTool->digitize(ctx, digiInput, rndEngine));
78 if (!digiOutput.wasEfficient()) {
79 ATH_MSG_VERBOSE("Hit "<<m_idHelperSvc->toString(hitId)<<" is rejected due to inefficiency modelling.");
80 continue;
81 }
82 const double arrivalTime{simHit->globalTime()};
83
84 const MuonCalib::MdtFullCalibData* tubeConstants = calibData->getCalibData(hitId, msgStream());
85 assert(tubeConstants != nullptr);
86 assert(tubeConstants->tubeCalib.get() != nullptr);
87 assert(tubeConstants->tubeCalib->getCalib(hitId) != nullptr);
88
89 const MuonCalib::MdtTubeCalibContainer::SingleTubeCalib& tubeCalib{*tubeConstants->tubeCalib->getCalib(hitId)};
90
91 const double sigPropTime = calibData->inversePropSpeed()*distRO;
92 ATH_MSG_VERBOSE(m_idHelperSvc->toString(hitId)<<" "<<Amg::toString(locPos)<<" distance to readout: "<<distRO<<" --> "<<sigPropTime);
95 const double totalTdcTime = digiOutput.driftTime() + arrivalTime + tubeCalib.t0 + sigPropTime;
96 if (lastTube != hitId || deadTime < totalTdcTime) {
97 lastTube = hitId;
98 deadTime = totalTdcTime + m_deadTime;
99 } else {
100 ATH_MSG_VERBOSE("Hit "<<m_idHelperSvc->toString(hitId)<<" has been produced within dead time");
101 continue;
102 }
104
105 const bool hasHPTdc = m_idHelperSvc->hasHPTDC(hitId);
107 const uint16_t tdcCounts = timeToTdcCnv*(hasHPTdc ? 4 : 1)*CLHEP::RandGaussZiggurat::shoot(rndEngine, totalTdcTime, m_timeResTDC);
108 const uint16_t adcCounts = (hasHPTdc ? 4 : 1) *CLHEP::RandGaussZiggurat::shoot(rndEngine, digiOutput.adc(), m_timeResADC);
109
110 auto digit = std::make_unique<MdtDigit>(hitId, tdcCounts, adcCounts, false);
111 ATH_MSG_VERBOSE("Add digit "<<m_idHelperSvc->toString(digit->identify())<<", tdc: "<<digit->tdc()<<", adc: "<<digit->adc());
112 digitsInChamber.push_back(std::make_pair(std::move(digit), simHit));
114 if (!twinTubes || !twinTubes->isTwinTubeLayer(hitId)) {
115 continue;
116 }
117 const Identifier twinId{twinTubes->twinId(hitId)};
118 if (twinId == hitId) {
119 ATH_MSG_VERBOSE("The hit "<<m_idHelperSvc->toString(hitId)<<" has no twins.");
120 continue;
121 }
122 const IdentifierHash twinHash{readOutEle->measurementHash(twinId)};
123 if (!readOutEle->isValid(twinHash)) {
124 ATH_MSG_VERBOSE("Reject "<<m_idHelperSvc->toString(twinId)<<" as there's no tube ");
125 continue;
126 }
128 const double twinDist = readOutEle->activeTubeLength(measHash) - distRO +
129 readOutEle->activeTubeLength(twinHash);
130
131 ATH_MSG_VERBOSE("Twin hit :"<<m_idHelperSvc->toString(twinId)<< ", local Z: "<<simHit->localPosition().z()
132 <<", tube length: "<<readOutEle->activeTubeLength(measHash)<<", distRO: "<<distRO
133 <<", twin length: "<<readOutEle->activeTubeLength(twinHash)
134 <<", twin distance: "<<twinDist);
135 const MuonCalib::MdtTubeCalibContainer::SingleTubeCalib& twinCalib{*tubeConstants->tubeCalib->getCalib(twinId)};
136
137 const double twinPropTime = calibData->inversePropSpeed()*twinDist;
140 const double twinTdcTime = digiOutput.driftTime() + arrivalTime + twinPropTime
141 + twinCalib.t0 + twinTubes->hvDelayTime(twinId);
142
143 const uint16_t twinTdcCounts = timeToTdcCnv*(hasHPTdc ? 4 : 1)*CLHEP::RandGaussZiggurat::shoot(rndEngine, twinTdcTime, m_resTwin);
144 const uint16_t twinAdcCoutns = (hasHPTdc ? 4 : 1) *CLHEP::RandGaussZiggurat::shoot(rndEngine, digiOutput.adc(), m_timeResADC);
145 digit = std::make_unique<MdtDigit>(twinId, twinTdcCounts, twinAdcCoutns, false);
146 ATH_MSG_VERBOSE("Add twin digit "<<m_idHelperSvc->toString(digit->identify())<<", tdc: "<<digit->tdc()
147 <<", adc: "<<digit->adc()<<", local z: "<<simHit->localPosition().z());
148 digitsInChamber.push_back(std::make_pair(std::move(digit), simHit));
149 }
152 std::ranges::sort(digitsInChamber,[](const DigitSDOPair&a, const DigitSDOPair& b){
153 if (a.first->identify() != b.first->identify()) {
154 return a.first->identify() < b.first->identify();
155 }
156 return a.first->tdc() < b.first->tdc();
157 });
158
159 for (std::vector<DigitSDOPair>::iterator saveMe = digitsInChamber.begin(); saveMe != digitsInChamber.end() ; ) {
160 addSDO(saveMe->second, sdoContainer);
161 const MdtDigit* saved = fetchCollection(saveMe->first->identify(), digitCache)->push_back(std::move(saveMe->first));
162 const uint16_t deadInterval = saved->tdc() + timeToTdcCnv*(m_idHelperSvc->hasHPTDC(saved->identify()) ?4 : 1)*m_deadTime;
164 saveMe = std::find_if(saveMe +1, digitsInChamber.end(),
165 [deadInterval, saved](const DigitSDOPair& digitized) {
166 return saved->identify() != digitized.first->identify() || deadInterval < digitized.first->tdc();
167 });
168 }
169 } while (viewer.next());
171 ATH_CHECK(writeDigitContainer(ctx, m_writeKey, std::move(digitCache), idHelper.module_hash_max()));
172 return StatusCode::SUCCESS;
173 }
174}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
ATLAS-specific HepMC functions.
static Double_t a
Handle class for recording to StoreGate.
Obj * get()
Get (non-const) access to the underlying object.
static constexpr double tdcBinSize
Conversion to go from tdc counts -> drift Time.
This is a "hash" representation of an Identifier.
bool isGood(const Identifier &Id) const
Returns if the identifier (tube/multiLayer/chamber) is masked in the conditions database.
double driftTime() const
double wasEfficient() const
int16_t tdc() const
Definition MdtDigit.h:26
const MdtFullCalibData * getCalibData(const Identifier &measId, MsgStream &msg) const
Returns the calibration data associated with this station.
Identifier identify() const
Definition MuonDigit.h:30
static IdentifierHash measurementHash(unsigned int layerNumber, unsigned int tubeNumber)
Transform the layer and tube number to the measurementHash.
double distanceToReadout(const ActsTrk::GeometryContext &ctx, const Identifier &measId, const Amg::Vector3D &globPoint) const
Returns the distance along the wire from the readout card The distance is given as the delta z of the...
bool isValid(const IdentifierHash &measHash) const
size_type module_hash_max() const
the maximum hash value
Gaudi::Property< bool > m_useTwinTube
Properties to model the Twin tube signals.
SG::ReadCondHandleKey< MuonCalib::MdtCalibDataContainer > m_calibDbKey
StatusCode digitize(const EventContext &ctx, const TimedHits &hitsToDigit, xAOD::MuonSimHitContainer *sdoContainer) const override final
Digitize the time ordered hits and write them to the digit format specific for the detector technolog...
MdtDigitizationTool(const std::string &type, const std::string &name, const IInterface *pIID)
Barebone implementation of the I/O infrastructure for all MuonDigitizationTools.
xAOD::MuonSimHit * addSDO(const TimedHit &hit, xAOD::MuonSimHitContainer *sdoContainer) const
Adds the timed simHit to the output SDO container.
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
std::vector< TimedHitPtr< xAOD::MuonSimHit > > TimedHits
CLHEP::HepRandomEngine * getRandomEngine(const EventContext &ctx) const
TimedHitPtr< xAOD::MuonSimHit > TimedHit
DigitColl * fetchCollection(const Identifier &hitId, OutDigitCache_t< DigitColl > &digitCache) const
Helper function that provides fetches the proper DigitCollection from the DigitCache for a given hit ...
const MuonGMR4::MuonDetectorManager * m_detMgr
StatusCode writeDigitContainer(const EventContext &ctx, const SG::WriteHandleKey< DigitCont > &key, OutDigitCache_t< DigitColl > &&digitCache, unsigned int hashMax) const
Helper function to move the collected digits into the final DigitContainer.
double hvDelayTime(const Identifier &channelId) const
Returns the HV time delay for a given twin tube pair.
bool isTwinTubeLayer(const Identifier &channelId) const
Returns whether the multilayer is equipped with twin-tubes or not.
Identifier twinId(const Identifier &channelId) const
Returns the Identifier of the mapped twin tube.
a smart pointer to a hit that also provides access to the extended timing info of the host event.
Definition TimedHitPtr.h:18
bool next() noexcept
Loads the hits from the next chamber.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Matrix< double, 3, 1 > Vector3D
bool isMuon(const T &p)
This header ties the generic definitions in this package.
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
MuonSimHitContainer_v1 MuonSimHitContainer
Define the version of the pixel cluster container.
class which holds the full set of calibration constants for a given tube