ATLAS Offline Software
Loading...
Searching...
No Matches
MmFastDigiTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4#include "MmFastDigiTool.h"
7#include "CLHEP/Random/RandGaussZiggurat.h"
8#include "CLHEP/Random/RandFlat.h"
9
10namespace {
11 constexpr double percentage(unsigned int numerator, unsigned int denom) {
12 return 100. * numerator / std::max(denom, 1u);
13 }
14}
15namespace MuonR4 {
16
17 MmFastDigiTool::MmFastDigiTool(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_uncertCalibKey.initialize());
24 ATH_CHECK(m_effiDataKey.initialize(!m_effiDataKey.empty()));
25 return StatusCode::SUCCESS;
26 }
28 std::stringstream statstr{};
29 unsigned allHits{0};
30 for (unsigned int g = 0; g < m_allHits.size(); ++g) {
31 allHits += m_allHits[g];
32 statstr<<" *** Layer "<<(g+1)<<" "<<percentage(m_acceptedHits[g],m_allHits[g])
33 <<"% of "<<m_allHits[g]<<std::endl;
34 }
35 if(!allHits) return StatusCode::SUCCESS;
36 ATH_MSG_INFO("Tried to convert "<<allHits<<" hits. Successes rate per layer "<<std::endl<<statstr.str());
37 return StatusCode::SUCCESS;
38 }
39 StatusCode MmFastDigiTool::digitize(const EventContext& ctx,
40 const TimedHits& hitsToDigit,
41 xAOD::MuonSimHitContainer* sdoContainer) const {
42 const MmIdHelper& idHelper{m_idHelperSvc->mmIdHelper()};
43 // Prepare the temporary cache
44 DigiCache digitCache{};
46 const Muon::DigitEffiData* efficiencyMap{nullptr};
47 ATH_CHECK(SG::get(efficiencyMap, m_effiDataKey, ctx));
48 const NswErrorCalibData* errorCalibDB{nullptr};
49 ATH_CHECK(SG::get(errorCalibDB, m_uncertCalibKey, ctx));
50
51 CLHEP::HepRandomEngine* rndEngine = getRandomEngine(ctx);
52 xAOD::ChamberViewer viewer{hitsToDigit, m_idHelperSvc.get()};
53 do {
54 DeadTimeMap deadTimes{};
55 for (const TimedHit& simHit : viewer) {
56 if (m_digitizeMuonOnly && !MC::isMuon(simHit)){
57 continue;
58 }
59
60 const double hitKineticEnergy = simHit->kineticEnergy();
61 // Don't consider electron hits below m_energyThreshold.
62 // Electrons aren't consider for now in any case due to the cut above.
63 // But this may change.
64 if (hitKineticEnergy < m_energyThreshold && MC::isElectron(simHit)) {
65 continue;
66 }
67
68 const Identifier hitId{simHit->identify()};
69
70 const MuonGMR4::MmReadoutElement* readOutEle = m_detMgr->getMmReadoutElement(hitId);
71 const Amg::Vector2D locPos{xAOD::toEigen(simHit->localPosition()).block<2,1>(0,0)};
72
74 const unsigned int hitGapInNsw = (idHelper.multilayer(hitId) -1) * 4 + idHelper.gasGap(hitId) -1;
75 ++m_allHits[hitGapInNsw];
76
77 const MuonGMR4::StripDesign& design{readOutEle->stripLayer(hitId).design()};
78 bool isValid{false};
79
80 int channelNumber = design.stripNumber(locPos);
81 if(channelNumber<0){
82 if (!design.insideTrapezoid(locPos)) {
83 ATH_MSG_WARNING("Hit "<<m_idHelperSvc->toString(hitId)<<" "<<Amg::toString(locPos)
84 <<" is outside bounds "<<std::endl<<design<<" rejecting it");
85 }
86 continue;
87 }
88 const Identifier clusId = idHelper.channelID(hitId,
89 idHelper.multilayer(hitId),
90 idHelper.gasGap(hitId),
91 channelNumber, isValid);
92
93 if(!isValid) {
94 ATH_MSG_WARNING("Invalid strip identifier for layer " << m_idHelperSvc->toStringGasGap(hitId)
95 << " channel " << channelNumber << " locPos " << Amg::toString(locPos));
96 continue;
97 }
98
99 if(efficiencyMap && efficiencyMap->getEfficiency(clusId) < CLHEP::RandFlat::shoot(rndEngine, 0., 1.)){
100 continue;
101 }
102 if (!passDeadTime(clusId, hitTime(simHit), m_deadTime, deadTimes)) {
104 continue;
105 }
106 NswErrorCalibData::Input errorCalibInput{};
107 errorCalibInput.stripId = clusId;
108 errorCalibInput.locTheta = M_PI- simHit->localDirection().theta();
109 errorCalibInput.clusterAuthor=66; // cluster time projection method
110 const double uncert = errorCalibDB->clusterUncertainty(errorCalibInput);
111 ATH_MSG_VERBOSE("mm hit has theta " << errorCalibInput.locTheta / Gaudi::Units::deg << " and uncertainty " << uncert);
112
113
116 constexpr int dummyResponseTime = 100;
117 constexpr float dummyDepositedCharge = 666666;
118
119 const double newLocalX = CLHEP::RandGaussZiggurat::shoot(rndEngine, locPos.x(), uncert);
120 const int newChannel = design.stripNumber(newLocalX * Amg::Vector2D::UnitX());
121 if (newChannel < 0) {
122 continue;
123 }
124
125 const Identifier digitId = idHelper.channelID(hitId,
126 idHelper.multilayer(hitId),
127 idHelper.gasGap(hitId),
128 newChannel, isValid);
129
130 if(!isValid) {
131 ATH_MSG_WARNING("Invalid strip identifier for layer " << m_idHelperSvc->toStringGasGap(hitId)
132 << " channel " << newChannel << " locPos " << Amg::toString(locPos));
133 continue;
134 }
148
157 const double pull = (newLocalX - (*design.center(newChannel)).x()) / (design.stripPitch() * std::cos(design.stereoAngle()));
158 const double w1 = CLHEP::RandFlat::shoot(rndEngine, 0., 0.5 *(1. - pull));
159 const double w2 = 1 - pull -2*w1;
160 const double w3 = pull + w1;
161 MmDigitCollection* outColl = fetchCollection(hitId, digitCache);
162
163 const Identifier digitIdB = idHelper.channelID(hitId,
164 idHelper.multilayer(hitId),
165 idHelper.gasGap(hitId),
166 newChannel - 1, isValid);
167
168 if (isValid) {
169 outColl->push_back(std::make_unique<MmDigit>(digitIdB, dummyResponseTime, w1 * dummyDepositedCharge));
170 }
171 outColl->push_back(std::make_unique<MmDigit>(digitId,dummyResponseTime, w2 * dummyDepositedCharge));
172
173 const Identifier digitIdA = idHelper.channelID(hitId,
174 idHelper.multilayer(hitId),
175 idHelper.gasGap(hitId),
176 newChannel + 1, isValid);
177 if (isValid) {
178 outColl->push_back(std::make_unique<MmDigit>(digitIdA, dummyResponseTime, w3 * dummyDepositedCharge));
179 }
180
181 xAOD::MuonSimHit* sdoHit = addSDO(simHit, sdoContainer);
182 sdoHit->setIdentifier(clusId);
183 ++m_acceptedHits[hitGapInNsw];
184 }
185 } while(viewer.next());
187 ATH_CHECK(writeDigitContainer(ctx, m_writeKey, std::move(digitCache), idHelper.module_hash_max()));
188 return StatusCode::SUCCESS;
189 }
190}
#define M_PI
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
bool isValid(const T &p)
Av: we implement here an ATLAS-sepcific convention: all particles which are 99xxxxx are fine.
Definition AtlasPID.h:878
ATLAS-specific HepMC functions.
#define x
value_type push_back(value_type pElem)
Add an element to the end of the collection.
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int channel) const
int gasGap(const Identifier &id) const override
get the hashes
int multilayer(const Identifier &id) const
const StripLayer & stripLayer(const Identifier &measId) const
double stereoAngle() const
Returns the value of the stereo angle.
CheckVector2D center(int stripNumb) const
Returns the bisector of the strip (Global numbering scheme)
double stripPitch() const
Distance between two adjacent strips.
bool insideTrapezoid(const Amg::Vector2D &extPos) const
Checks whether an external point is inside the trapezoidal area.
virtual int stripNumber(const Amg::Vector2D &pos) const
Calculates the number of the strip whose center is closest to the given point.
const StripDesign & design(bool phiView=false) const
Returns the underlying strip design.
size_type module_hash_max() const
the maximum hash value
SG::ReadCondHandleKey< NswErrorCalibData > m_uncertCalibKey
SG::ReadCondHandleKey< Muon::DigitEffiData > m_effiDataKey
Gaudi::Property< double > m_deadTime
Gaudi::Property< bool > m_digitizeMuonOnly
Gaudi::Property< double > m_energyThreshold
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...
StatusCode finalize() override final
SG::WriteHandleKey< MmDigitContainer > m_writeKey
StatusCode initialize() override final
OutDigitCache_t< MmDigitCollection > DigiCache
MmFastDigiTool(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
static bool passDeadTime(const Identifier &channelId, const double hitTime, const double deadTimeWindow, DeadTimeMap &deadTimeMap)
Returns whether the new digit is within the dead time window.
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.
static double hitTime(const TimedHit &hit)
Returns the global time of the hit which is the sum of eventTime & individual hit time.
std::unordered_map< Identifier, double > DeadTimeMap
double getEfficiency(const Identifier &channelId, bool isInnerQ1=false) const
Returns the signal generation efficiency of the sTgc channel.
double clusterUncertainty(const Input &clustInfo) const
bool next() noexcept
Loads the hits from the next chamber.
void setIdentifier(const Identifier &id)
Sets the global ATLAS identifier.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Matrix< double, 2, 1 > Vector2D
bool isElectron(const T &p)
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.
MuonSimHit_v1 MuonSimHit
Defined the version of the MuonSimHit.
Definition MuonSimHit.h:12
MuonSimHitContainer_v1 MuonSimHitContainer
Define the version of the pixel cluster container.
Helper struct to be parsed to the object to derive the specific error of the cluster.
double locTheta
Direction of the muon in the local coordinate frame.
Identifier stripId
Identifier of the strip.
uint8_t clusterAuthor
Author of the cluster.