ATLAS Offline Software
Loading...
Searching...
No Matches
RpcDigiTool.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 "RpcDigiTool.h"
5
6#include "CLHEP/Random/RandGaussZiggurat.h"
7#include "GaudiKernel/SystemOfUnits.h"
11
12namespace {
13 constexpr double percentage(unsigned int numerator, unsigned int denom) {
14 return 100. * numerator / std::max(denom, 1u);
15 }
16 using ChVec_t = std::vector<std::uint16_t>;
18 static const SG::Decorator<ChVec_t> dec_phiChannel{"SDO_phiChannels"};
19 static const SG::Decorator<ChVec_t> dec_etaChannel{"SDO_etaChannels"};
20
21} // namespace
22namespace MuonR4 {
23
26 ATH_CHECK(m_writeKey.initialize());
27 ATH_CHECK(m_effiDataKey.initialize(!m_effiDataKey.empty()));
28 return StatusCode::SUCCESS;
29}
30
32 ATH_MSG_INFO("Tried to convert "
33 << m_allHits[0] << "/" << m_allHits[1] << " hits. In, "
34 << percentage(m_acceptedHits[0], m_allHits[0]) << "/"
35 << percentage(m_acceptedHits[1], m_allHits[1])
36 << "% of the cases, the conversion was successful");
37 return StatusCode::SUCCESS;
38}
39
40
41 double RpcDigiTool::getTOT(const double aCharge) const {
42 // This is a parameterization of BIRPC TOT (ns) values corresponding to
43 // a charge (fC), it was obtained from a detailed model for
44 // RPC signal emulation.
45 constexpr std::array<double, 3> coeffs{19.9587, 0.10081, -0.00017};
46 using namespace Acts::detail;
47
48 return polynomialSum(aCharge, coeffs);
49 }
50 double RpcDigiTool::getTOA(const double aCharge, const double aDistance) const {
51 // This is a parameterization of BIRPC TOA (ns) values corresponding to
52 // a charge (fC) and a distance (m), it was obtained from a
53 // detailed model for RPC signal emulation.
54 constexpr std::array<double, 3> distCoeffs{0., 5.00311, 0.00006};
55 constexpr std::array<double, 3> chargeCoeffs{2.02843, -0.00641, 0.00001};
56 using namespace Acts::detail;
57
58 return polynomialSum(aDistance/1000., distCoeffs) + // In this parameterization the distance is in m while athena standard is mm
59 polynomialSum(aCharge, chargeCoeffs);
60 }
61
62StatusCode
63RpcDigiTool::digitize(const EventContext &ctx, const TimedHits &hitsToDigit,
64 xAOD::MuonSimHitContainer *sdoContainer) const {
65 const RpcIdHelper &idHelper{m_idHelperSvc->rpcIdHelper()};
66 // Prepare the temporary cache
67 DigiCache digitCache{};
69 const Muon::DigitEffiData *efficiencyMap{nullptr};
70 ATH_CHECK(SG::get(efficiencyMap, m_effiDataKey, ctx));
71
72 CLHEP::HepRandomEngine *rndEngine = getRandomEngine(ctx);
73 xAOD::ChamberViewer viewer{hitsToDigit, m_idHelperSvc.get()};
74 do {
75 DeadTimeMap deadTimes{};
76 for (const TimedHit &simHit : viewer) {
77 if (m_digitizeMuonOnly && !MC::isMuon(simHit)) {
78 continue;
79 }
80 const Identifier hitId{simHit->identify()};
81 RpcDigitCollection *digiColl = fetchCollection(hitId, digitCache);
82 const std::size_t beforeDigiSize = digiColl->size();
83 xAOD::MuonSimHit* sdo{nullptr};
84 if (m_detMgr->getRpcReadoutElement(hitId)->nPhiStrips() > 0) {
86
87 const bool digitizedPhi = digitizeHit(simHit, true, efficiencyMap,
88 *digiColl, rndEngine, deadTimes);
89 const bool digitizedEta = digitizeHit(simHit, false, efficiencyMap,
90 *digiColl, rndEngine, deadTimes);
91 if (digitizedEta || digitizedPhi) {
92 sdo = addSDO(simHit, sdoContainer);
93 }
94 } else if (digitizeHitBI(simHit, efficiencyMap, *digiColl, rndEngine,
95 deadTimes)) {
96 sdo = addSDO(simHit, sdoContainer);
97 }
98 if (sdo) {
99 sdo->setIdentifier(digiColl->back()->identify());
100 dec_etaChannel(*sdo).clear();
101 dec_phiChannel(*sdo).clear();
102 for (std::size_t newDigit = beforeDigiSize; newDigit< digiColl->size(); ++newDigit) {
103 const Identifier id = digiColl->at(newDigit)->identify();
104 ChVec_t& ch{idHelper.measuresPhi(id)? dec_phiChannel(*sdo) : dec_etaChannel(*sdo)};
105 ch.push_back(idHelper.channel(id));
106 }
107 }
108 }
109 } while (viewer.next());
111 ATH_CHECK(writeDigitContainer(ctx, m_writeKey, std::move(digitCache),
112 idHelper.module_hash_max()));
113 return StatusCode::SUCCESS;
114}
115bool RpcDigiTool::digitizeHit(const TimedHit &simHit, const bool measuresPhi,
116 const Muon::DigitEffiData *effiMap,
117 RpcDigitCollection &outContainer,
118 CLHEP::HepRandomEngine *rndEngine,
119 DeadTimeMap &deadTimes) const {
120
121 ++(m_allHits[measuresPhi]); // Count all hits separately for eta and phi ([0] and [1], respectively)
122
123 const Identifier gasGapId = simHit->identify();
124 const MuonGMR4::RpcReadoutElement *reEle =
125 m_detMgr->getRpcReadoutElement(gasGapId);
126
127 const RpcIdHelper &idHelper{m_idHelperSvc->rpcIdHelper()};
128
129 bool isValid{false};
130
131 const Identifier layerId = idHelper.channelID(
132 gasGapId, idHelper.doubletZ(gasGapId), idHelper.doubletPhi(gasGapId),
133 idHelper.gasGap(gasGapId), measuresPhi, 1, isValid);
134 const IdentifierHash layHash = reEle->layerHash(gasGapId);
135
136 const MuonGMR4::StripLayerPtr &layerDesign =
137 reEle->sensorLayout(reEle->layerHash(layerId));
138
139 const MuonGMR4::StripDesign &design{layerDesign->design(measuresPhi)};
140
141 Amg::Vector3D locHitPos{xAOD::toEigen(simHit->localPosition())};
142
143 const Amg::Vector2D locPos2D = layerDesign->to2D(locHitPos, measuresPhi);
144 if (!design.insideTrapezoid(locPos2D)) {
145 ATH_MSG_VERBOSE("The hit " << Amg::toString(locHitPos) << " / "
146 << Amg::toString(locPos2D)
147 << " is outside of the trapezoid bounds for "
148 << m_idHelperSvc->toString(layerId));
149 return false;
150 }
151 const int strip = design.stripNumber(locPos2D);
152 if (strip < 0) {
153 ATH_MSG_VERBOSE("Hit " << Amg::toString(locHitPos) << " / "
154 << Amg::toString(locPos2D)
155 << " cannot trigger any signal in a strip for "
156 << m_idHelperSvc->toString(layerId) << std::endl
157 << design);
158 return false;
159 }
160
161 // Check whether the digit is actually efficient
162 const bool effiSignal =
163 !effiMap || effiMap->getEfficiency(gasGapId) >=
164 CLHEP::RandFlat::shoot(rndEngine, 0., 1.);
165 if (!effiSignal) return false;
166
167 // Calculate distance from readout
168 const double DistanceToEdge =
169 reEle->distanceToEdge(layHash, locHitPos, EdgeSide::readOut); // mm
170
171 // Calculate charge deposited
172 const double TotalChargeOnStrip =
173 calculateChargeOnStrip(simHit, rndEngine, 2.0); // 2 mm gap for BM/BO chambers
174 ATH_MSG_VERBOSE(" total charge (fC): " << TotalChargeOnStrip);
175
176 // Calculate cluster size (number of strips)
177 int clusterSize = determineClusterSize(gasGapId, rndEngine, false);
178 ATH_MSG_VERBOSE(" cluster size: " << clusterSize);
179
180 // Get min and max strips
181 int minStrip{strip}, maxStrip{strip}; // case strip number is 1
182 if (clusterSize > 1) {
183 int halfCluster = clusterSize / 2; // half cluster size (int)
184 minStrip = strip - halfCluster; // min strip number
185 if (clusterSize % 2 == 0) { // if clusterSize is even, we have to randomly
186 // assign one strip on left or right side
187 int side = Acts::copySign(1,CLHEP::RandFlat::shoot(rndEngine, 0., 1.) + 0.5);
188 minStrip += side; // if side==1 move the min strip to right
189 }
190 maxStrip = minStrip + clusterSize - 1;
191 // Check design strip boundaries
192 minStrip = std::max(minStrip, design.firstStripNumber());
193 maxStrip = std::min(design.firstStripNumber() + design.numStrips() - 1, maxStrip);
194 }
195
196 // Recalculate cluster size with minStrip and maxStrip
197 clusterSize = (maxStrip - minStrip) + 1;
198
199 // Divide charge on N strips
200 const std::vector<double> StripCharges =
201 divideChargeOnStrips(TotalChargeOnStrip, clusterSize, rndEngine);
202
203 // Digitize each strip
204 bool hasAcceptedStrip=false;
205 for (int aStrip = minStrip; aStrip <= maxStrip; aStrip++) {
206
207 bool isValid{false};
208 const Identifier digitId{idHelper.channelID(
209 gasGapId, idHelper.doubletZ(gasGapId), idHelper.doubletPhi(gasGapId),
210 idHelper.gasGap(gasGapId), measuresPhi, aStrip, isValid)};
211
212 // Check digitID is valid
213 if (!isValid) {
214 ATH_MSG_WARNING("Failed to create a valid strip "
215 << m_idHelperSvc->toStringGasGap(gasGapId)
216 << ", strip: " << aStrip);
217 return false;
218 }
219 // Check is not dead time
220 if (!passDeadTime(digitId, hitTime(simHit), m_deadTime, deadTimes)) {
221 ATH_MSG_VERBOSE("Reject hit due to dead map constraint");
222 return false;
223 }
224
225 outContainer.push_back(std::make_unique<RpcDigit>(
226 digitId,
227 hitTime(simHit) + getTOA(StripCharges[aStrip-minStrip], DistanceToEdge),
228 getTOT(StripCharges[aStrip-minStrip])));
229
230 ATH_MSG_VERBOSE("Digitize hit "
231 << m_idHelperSvc->toString(digitId)
232 << " located at: " << Amg::toString(locHitPos) );
233 ++(m_acceptedHits[measuresPhi]); // Count accepted hits for eta ([0]) or phi ([1])
234 hasAcceptedStrip=true;
235 }
236
237 return hasAcceptedStrip;
238}
239
240
242 const Muon::DigitEffiData *effiMap,
243 RpcDigitCollection &outContainer,
244 CLHEP::HepRandomEngine *rndEngine,
245 DeadTimeMap &deadTimes) const {
246
247 ++(m_allHits[false]); // Count all hits for eta ([0]) since there are no phi strips in BI chambers
248 const Identifier gasGapId = simHit->identify();
249 const MuonGMR4::RpcReadoutElement *reEle =
250 m_detMgr->getRpcReadoutElement(gasGapId);
251 const Amg::Vector3D locHitPos = xAOD::toEigen(simHit->localPosition());
252 const MuonGMR4::StripDesign &design{*reEle->getParameters().etaDesign};
253 const RpcIdHelper &idHelper{m_idHelperSvc->rpcIdHelper()};
254
255 /* with RpcReadoutElement reEle you can access infor about the readout like */
256 ATH_MSG_VERBOSE("RpcDigiTool::digitizeHitBI reEle->nGasGaps "<< reEle->nGasGaps());
257 /* with StripDesign you can access the strip information of the readout
258 * element for instance: */
259 ATH_MSG_VERBOSE("RpcDigiTool::digitizeHitBI design: "<< design);
260
261 // Check the correctness of the local hit position
262 const Amg::Vector2D locHitPosition{locHitPos.x(), locHitPos.y()};
263 if (!design.insideTrapezoid(locHitPosition)) {
264 ATH_MSG_VERBOSE("The hit " << Amg::toString(locHitPosition)
265 << " is outside of the trapezoid bounds for "
266 << m_idHelperSvc->toStringGasGap(gasGapId));
267 return false;
268 }
269
270 // Calculate distance to strip edges (mm)
271 const IdentifierHash layHash = reEle->layerHash(gasGapId);
272 const double DistanceToReadOut =
273 reEle->distanceToEdge(layHash, locHitPos, EdgeSide::readOut); // mm
274 const double DistanceToHV =
275 reEle->distanceToEdge(layHash, locHitPos, EdgeSide::highVoltage); // mm
276
277 // Calculate charge deposited
278 const double TotalChargeOnStrip =
279 calculateChargeOnStrip(simHit, rndEngine, 1.0); // 1 mm gap for BI chambers
280//mn calculateChargeOnStrip(simHit, rndEngine, reEle->thickness());
281 ATH_MSG_VERBOSE(" total charge (fC): " << TotalChargeOnStrip);
282
283 // Calculate cluster size (number of strips)
284 int clusterSize = determineClusterSize(gasGapId, rndEngine, true);
285 ATH_MSG_VERBOSE(" cluster size: " << clusterSize);
286
287 // Get corresponding strip number and apply checks
288 const int strip = design.stripNumber(locHitPosition);
289 if (strip < 0) {
290 ATH_MSG_VERBOSE("Hit " << Amg::toString(locHitPosition)
291 << " cannot trigger any signal in a strip for "
292 << m_idHelperSvc->toStringGasGap(gasGapId)
293 << std::endl
294 << design);
295 return false;
296 }
297
298 // Check whether the digit is actually efficient
299 const bool effiSignal1 =
300 !effiMap || effiMap->getEfficiency(gasGapId) >=
301 CLHEP::RandFlat::shoot(rndEngine, 0., 1.);
302 const bool effiSignal2 =
303 !effiMap || effiMap->getEfficiency(gasGapId) >=
304 CLHEP::RandFlat::shoot(rndEngine, 0., 1.);
305 if (!effiSignal1 && !effiSignal2) return false;
306
307 // Get min and max strips
308 int minStrip{strip}, maxStrip{strip}; // case strip number is 1
309 if (clusterSize > 1) {
310 int halfCluster = clusterSize / 2; // half cluster size (int)
311 minStrip = strip - halfCluster; // min strip number
312 if (clusterSize % 2 == 0) { // if clusterSize is even, we have to randomly
313 // assign one strip on left or right side
314 int side = Acts::copySign(1,CLHEP::RandFlat::shoot(rndEngine, 0., 1.) + 0.5);
315 minStrip += side; // if side==1 move the min strip to right
316 }
317 maxStrip = minStrip + clusterSize - 1;
318 // Check design strip boundaries
319 minStrip = std::max(minStrip, design.firstStripNumber());
320 maxStrip = std::min(design.firstStripNumber() + design.numStrips() - 1, maxStrip);
321 }
322
323 // Recalculate cluster size with minStrip and maxStrip
324 clusterSize = (maxStrip - minStrip) + 1;
325
326 // Divide charge on N strips
327 const std::vector<double> StripCharges =
328 divideChargeOnStrips(TotalChargeOnStrip, clusterSize, rndEngine);
329
330 // Digitize each strip
331 bool hasAcceptedStrip=false;
332 for (int aStrip = minStrip; aStrip <= maxStrip; aStrip++) {
333 bool isValid{false};
334 const Identifier digitId{idHelper.channelID(
335 gasGapId, idHelper.doubletZ(gasGapId), idHelper.doubletPhi(gasGapId),
336 idHelper.gasGap(gasGapId), false, aStrip, isValid)};
337
338 // Check digitID is valid
339 if (!isValid) {
340 ATH_MSG_WARNING("Failed to create a valid strip "
341 << m_idHelperSvc->toStringGasGap(gasGapId)
342 << ", strip: " << aStrip);
343 return false;
344 }
345 // Check is not dead time
346 if (!passDeadTime(digitId, hitTime(simHit), m_deadTime, deadTimes)) {
347 ATH_MSG_VERBOSE("Reject hit due to dead map constraint");
348 return false;
349 }
350
351 if (effiSignal1) {
352 outContainer.push_back(std::make_unique<RpcDigit>(
353 digitId,
354 hitTime(simHit) + getTOA(StripCharges[aStrip-minStrip], DistanceToHV),
355 getTOT(StripCharges[aStrip-minStrip])));
356 }
357 if (effiSignal2) {
358 outContainer.push_back(std::make_unique<RpcDigit>(
359 digitId,
360 hitTime(simHit) +
361 getTOA(StripCharges[aStrip-minStrip], DistanceToReadOut),
362 getTOT(StripCharges[aStrip-minStrip]), true));
363 }
364 if (effiSignal1 || effiSignal2) {
365 ATH_MSG_VERBOSE("Digitize hit "
366 << m_idHelperSvc->toString(digitId)
367 << " located at: " << Amg::toString(locHitPos)
368 << ", SDO: " << Amg::toString(locHitPosition));
369 ++(m_acceptedHits[false]); // Count accepted hits for eta ([0]) since there are no phi strips in BI chambers
370 hasAcceptedStrip=true;
371 }
372 }
373
374 return hasAcceptedStrip;
375}
376
377std::vector<double>
378RpcDigiTool::divideChargeOnStrips(double totalCharge, int n_strips,
379 CLHEP::HepRandomEngine *rndmEngine) const {
380
381 std::vector<double> charges;
382
383 switch (n_strips) {
384 case 1: {
385 // Trivial case, all charge on a single strip
386 charges.push_back(totalCharge);
387 break;
388 }
389 case 2: {
390 // We use a Gaussian distribution centered over 0.5 to simulate
391 // a charge sharing that is on average 50/50 but includes fluctuations
392 double f = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.5, 0.15);
393
394 // Make sure fraction is bounded between 0 and 1
395 f = std::clamp(f, 0., 1.);
396
397 charges.push_back(f * totalCharge);
398 charges.push_back((1.0 - f) * totalCharge);
399 break;
400 }
401 case 3: {
402 // These fractions are guesses on a reasonable charge
403 // sharing when three strips are activated.
404 // These fractions must be updated once the final
405 // distributions of TOT from Phase-II BI RPCs
406 // are available.
407 charges.push_back(0.20 * totalCharge); // left strip
408 charges.push_back(0.60 * totalCharge); // center strip
409 charges.push_back(0.20 * totalCharge); // right strip
410 break;
411 }
412 case 4: {
413 // These fractions are guesses on a reasonable charge
414 // sharing when four strips are activated.
415 // These fractions must be updated once the final
416 // distributions of TOT from Phase-II BI RPCs
417 // are available.
418 charges.push_back(0.15 * totalCharge); // left external strip
419 charges.push_back(0.35 * totalCharge); // left internal strip
420 charges.push_back(0.35 * totalCharge); // right internal strip
421 charges.push_back(0.15 * totalCharge); // right external strip
422 break;
423 }
424 default: {
425 // return empy vector
426 break;
427 }
428 }
429
430 return charges;
431}
432
434 CLHEP::HepRandomEngine *rndmEngine,
435 const double gasGapSize) const {
436
437 // Average energy to create an electron-ion pair inside RPC gas
438 constexpr double W_VALUE_EV = 30.0; // Unit: [eV/pair]
439
440 // RPC BI gas gap thickness
441 const double GAP_THICKNESS_MM = gasGapSize; // Unit: [mm] (1 mm for Phase-II BI RPCs, 2 mm for BM/BO RPCs))
442
443 // Townsend coefficient for gas mixture and operational voltage
444 constexpr double ALPHA_PER_MM = 5.5; // Unit: [1/mm]
445
446 // Energy deposited by Geant4
447 const double energy_deposit_ev = simHit->energyDeposit() / Gaudi::Units::eV;
448
449 // Number of electron-ion pairs created
450 const double N0 = energy_deposit_ev / W_VALUE_EV;
451
452 // Primary ionization poistion inside gas gap
453 const double z_hit_mm =
454 CLHEP::RandFlat::shoot(rndmEngine, 0.0, GAP_THICKNESS_MM); // Unit: [mm]
455
456 // Distance to anode
457 const double z_drift_mm = std::abs(GAP_THICKNESS_MM - z_hit_mm); // Unit: [mm]
458
459 // Avalanche gain
460 const double gas_gain = std::exp(ALPHA_PER_MM * z_drift_mm);
461
462 // Total charge
463 const double total_charge_c = N0 * gas_gain * Gaudi::Units::e_SI; // Unit: [C]
464
465 ATH_MSG_DEBUG(__func__<<"() - "<<__LINE__<<" GAP_THICKNESS_MM: "<<GAP_THICKNESS_MM<<
466 ", "<<energy_deposit_ev<<", z_hit_mm: "<<z_hit_mm<<", N0: "<<N0<<", z_drift_mm: "<<z_drift_mm
467 <<", gas_gain: "<<gas_gain<< "---> Charge on strip (fC): " << total_charge_c * 1e15);
468
469 return total_charge_c * 1e15; // charge in fC
470}
471
473 const Identifier &idGasGap, CLHEP::HepRandomEngine *rndmEngine, bool isBIRPC) const {
474
475 const RpcIdHelper &id_helper{m_idHelperSvc->rpcIdHelper()};
476
477 ATH_MSG_DEBUG("RpcDigitizationTool::in determineClusterSize");
478
479 ATH_MSG_DEBUG("Digit Id = " << id_helper.show_to_string(idGasGap));
480
481 // These cluster size probabilities were taken from the legacy RPC code.
482 // MuonSpectrometer/MuonConfig/python/RPC_DigitizationConfig.py
483 static constexpr std::array<double, 4> ClusterSizeProbabilities{0.610, 0.260,
484 0.083, 0.047};
485 // Compile-time calculation of the cumulative array
486 // Used empty capture list [] since variables are static constexpr
487 static constexpr std::array<double, 4> cumulative = []() {
488 std::array<double, 4> acumulative{};
489 acumulative[0] = ClusterSizeProbabilities[0];
490 for (size_t i = 1; i < ClusterSizeProbabilities.size(); ++i) {
491 acumulative[i] = acumulative[i - 1] + ClusterSizeProbabilities[i];
492 }
493 return acumulative;
494 }();
495
496 // These cluster size probabilities were taken from preliminary
497 // results from the BI RPC Upgrade work in 2025 at BB5.
498 // They could be updated if new results for BI RPCs become available.
499 static constexpr std::array<double, 4> ClusterSizeProbabilitiesBI{0.642, 0.316,
500 0.032, 0.010};
501 // Compile-time calculation of the cumulative array
502 // Used empty capture list [] since variables are static constexpr
503 static constexpr std::array<double, 4> cumulativeBI = []() {
504 std::array<double, 4> acumulative{};
505 acumulative[0] = ClusterSizeProbabilitiesBI[0];
506 for (size_t i = 1; i < ClusterSizeProbabilitiesBI.size(); ++i) {
507 acumulative[i] = acumulative[i - 1] + ClusterSizeProbabilitiesBI[i];
508 }
509 return acumulative;
510 }();
511
512 std::array<double, 4> theCumulative{};
513 if (isBIRPC) {
514 theCumulative=cumulativeBI;
515 } else {
516 theCumulative=cumulative;
517 }
518
519 float rndmCS = CLHEP::RandFlat::shoot(rndmEngine, 1.);
520
521 unsigned ClusterSize{1};
522 while (ClusterSize < theCumulative.size() &&
523 rndmCS > theCumulative[ClusterSize-1])
524 ++ClusterSize;
525
526 if (ClusterSize > theCumulative.size())
527 ClusterSize = theCumulative.size();
528 return ClusterSize;
529}
530
531
532} // namespace MuonR4
#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)
#define ATH_MSG_DEBUG(x)
ATLAS-specific HepMC functions.
std::string show_to_string(Identifier id, const IdContext *context=0, char sep='.') const
or provide the printout in string form
const T * back() const
Access the last element in the collection as an rvalue.
const T * at(size_type n) const
Access an element, as an rvalue.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
This is a "hash" representation of an Identifier.
Identifier identify() const
Definition MuonDigit.h:30
double distanceToEdge(const IdentifierHash &measHash, const Amg::Vector3D &posInStripPlane, const EdgeSide side) const
Returns the disance to the readout.
IdentifierHash layerHash(const Identifier &measId) const override final
The layer hash removes the bits from the IdentifierHash corresponding to the measurement's channel nu...
const StripLayerPtr & sensorLayout(const IdentifierHash &measHash) const
Access to the StripLayer associated to a given measurement Hash.
unsigned nGasGaps() const
Returns the number of gasgaps described by this ReadOutElement (usally 2 or 3).
int firstStripNumber() const
Returns the number of the first strip.
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.
virtual int numStrips() const
Number of strips on the panel.
size_type module_hash_max() const
the maximum hash value
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
StatusCode initialize() override final
double getTOT(const double aCharge) const
Returns Time Over Threshold (ns) for a signal on a strip.
bool digitizeHit(const TimedHit &simHit, const bool measuresPhi, const Muon::DigitEffiData *effiMap, RpcDigitCollection &outContainer, CLHEP::HepRandomEngine *rndEngine, DeadTimeMap &deadTimes) const
Digitize the sim hit as Rpc strip 1D hit.
Gaudi::Property< bool > m_digitizeMuonOnly
Definition RpcDigiTool.h:81
Gaudi::Property< double > m_deadTime
Definition RpcDigiTool.h:78
double getTOA(const double aCharge, const double aDistance) const
Returns Time Of Arrival (ns) for a signal on a strip.
SG::ReadCondHandleKey< Muon::DigitEffiData > m_effiDataKey
Definition RpcDigiTool.h:62
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...
std::vector< double > divideChargeOnStrips(double totalCharge, int n_strips, CLHEP::HepRandomEngine *rndmEngine) const
Returns a vector with chages (fC) divided on strips.
SG::WriteHandleKey< RpcDigitContainer > m_writeKey
Definition RpcDigiTool.h:59
int determineClusterSize(const Identifier &id, CLHEP::HepRandomEngine *rndmEngine, bool isBIRPC) const
Returns cluster strip molteplicity.
StatusCode finalize() override final
OutDigitCache_t< RpcDigitCollection > DigiCache
Definition RpcDigiTool.h:58
double calculateChargeOnStrip(const TimedHit &simHit, CLHEP::HepRandomEngine *rndmEngine, const double gasGapSize) const
Returns the charge (fC) after the amplification in gas.
bool digitizeHitBI(const TimedHit &simHit, const Muon::DigitEffiData *effiMap, RpcDigitCollection &outContainer, CLHEP::HepRandomEngine *rndEngine, DeadTimeMap &deadTimes) const
Digitize the sim hit as Rpc strip 2D hit.
double getEfficiency(const Identifier &channelId, bool isInnerQ1=false) const
Returns the signal generation efficiency of the sTgc channel.
Identifier channelID(int stationName, int stationEta, int stationPhi, int doubletR, int doubletZ, int doubletPhi, int gasGap, int measuresPhi, int strip) const
int gasGap(const Identifier &id) const override
get the hashes
int channel(const Identifier &id) const override
int doubletPhi(const Identifier &id) const
bool measuresPhi(const Identifier &id) const override
int doubletZ(const Identifier &id) const
bool next()
Loads the hits from the next chamber.
void setIdentifier(const Identifier &id)
Sets the global ATLAS identifier.
Identifier identify() const
Returns the global ATLAS identifier of the SimHit.
float energyDeposit() const
Returns the energy deposited by the traversing particle inside the gas volume.
ConstVectorMap< 3 > localPosition() const
Returns the local postion of the traversing particle.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
bool isMuon(const T &p)
GeoModel::TransientConstSharedPtr< StripLayer > StripLayerPtr
Definition StripLayer.h:100
This header ties the generic definitions in this package.
SG::Decorator< T, ALLOC > Decorator
Helper class to provide type-safe access to aux data, specialized for JaggedVecElt.
Definition AuxElement.h:576
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.
MuonSimHit_v1 MuonSimHit
Defined the version of the MuonSimHit.
Definition MuonSimHit.h:12