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 return polynomialSum(aCharge, coeffs);
48 }
49 double RpcDigiTool::getTOA(const double aCharge, const double aDistance) const {
50 // This is a parameterization of BIRPC TOA (ns) values corresponding to
51 // a charge (fC) and a distance (m), it was obtained from a
52 // detailed model for RPC signal emulation.
53 constexpr std::array<double, 3> distCoeffs{0., 5.00311, 0.00006};
54 constexpr std::array<double, 3> chargeCoeffs{2.02843, -0.00641, 0.00001};
55 using namespace Acts::detail;
56 return polynomialSum(aDistance, distCoeffs) +
57 polynomialSum(aCharge, chargeCoeffs);
58 }
59
60StatusCode
61RpcDigiTool::digitize(const EventContext &ctx, const TimedHits &hitsToDigit,
62 xAOD::MuonSimHitContainer *sdoContainer) const {
63 const RpcIdHelper &idHelper{m_idHelperSvc->rpcIdHelper()};
64 // Prepare the temporary cache
65 DigiCache digitCache{};
67 const Muon::DigitEffiData *efficiencyMap{nullptr};
68 ATH_CHECK(SG::get(efficiencyMap, m_effiDataKey, ctx));
69
70 CLHEP::HepRandomEngine *rndEngine = getRandomEngine(ctx);
71 xAOD::ChamberViewer viewer{hitsToDigit, m_idHelperSvc.get()};
72 do {
73 DeadTimeMap deadTimes{};
74 for (const TimedHit &simHit : viewer) {
75 if (m_digitizeMuonOnly && !MC::isMuon(simHit)) {
76 continue;
77 }
78 const Identifier hitId{simHit->identify()};
79 RpcDigitCollection *digiColl = fetchCollection(hitId, digitCache);
80 const std::size_t beforeDigiSize = digiColl->size();
81 xAOD::MuonSimHit* sdo{nullptr};
82 if (m_detMgr->getRpcReadoutElement(hitId)->nPhiStrips() > 0) {
84
85 const bool digitizedPhi = digitizeHit(simHit, true, efficiencyMap,
86 *digiColl, rndEngine, deadTimes);
87 const bool digitizedEta = digitizeHit(simHit, false, efficiencyMap,
88 *digiColl, rndEngine, deadTimes);
89 if (digitizedEta || digitizedPhi) {
90 sdo = addSDO(simHit, sdoContainer);
91 }
92 } else if (digitizeHitBI(simHit, efficiencyMap, *digiColl, rndEngine,
93 deadTimes)) {
94 sdo = addSDO(simHit, sdoContainer);
95 }
96 if (sdo) {
97 sdo->setIdentifier(digiColl->back()->identify());
98 dec_etaChannel(*sdo).clear();
99 dec_phiChannel(*sdo).clear();
100 for (std::size_t newDigit = beforeDigiSize; newDigit< digiColl->size(); ++newDigit) {
101 const Identifier id = digiColl->at(newDigit)->identify();
102 ChVec_t& ch{idHelper.measuresPhi(id)? dec_phiChannel(*sdo) : dec_etaChannel(*sdo)};
103 ch.push_back(idHelper.channel(id));
104 }
105 }
106 }
107 } while (viewer.next());
109 ATH_CHECK(writeDigitContainer(ctx, m_writeKey, std::move(digitCache),
110 idHelper.module_hash_max()));
111 return StatusCode::SUCCESS;
112}
113bool RpcDigiTool::digitizeHit(const TimedHit &hit, const bool measuresPhi,
114 const Muon::DigitEffiData *effiMap,
115 RpcDigitCollection &outContainer,
116 CLHEP::HepRandomEngine *rndEngine,
117 DeadTimeMap &deadTimes) const {
118
119 ++(m_allHits[measuresPhi]);
120
121 const Identifier gasGapId = hit->identify();
122 const MuonGMR4::RpcReadoutElement *reEle =
123 m_detMgr->getRpcReadoutElement(gasGapId);
124
125 const RpcIdHelper &idHelper{m_idHelperSvc->rpcIdHelper()};
126
127 bool isValid{false};
128 const Identifier layerId = idHelper.channelID(
129 gasGapId, idHelper.doubletZ(gasGapId), idHelper.doubletPhi(gasGapId),
130 idHelper.gasGap(gasGapId), measuresPhi, 1, isValid);
131
132 const MuonGMR4::StripLayerPtr &layerDesign =
133 reEle->sensorLayout(reEle->layerHash(layerId));
134
135 const MuonGMR4::StripDesign &design{layerDesign->design(measuresPhi)};
136
137 const double uncert = design.stripPitch() / std::sqrt(12.);
138 Amg::Vector3D locHitPos{xAOD::toEigen(hit->localPosition())};
139 locHitPos[measuresPhi] = CLHEP::RandGaussZiggurat::shoot(
140 rndEngine, locHitPos[measuresPhi], uncert);
141
142 const Amg::Vector2D locPos2D = layerDesign->to2D(locHitPos, measuresPhi);
143 if (!design.insideTrapezoid(locPos2D)) {
144 ATH_MSG_VERBOSE("The hit " << Amg::toString(locHitPos) << " / "
145 << Amg::toString(locPos2D)
146 << " is outside of the trapezoid bounds for "
147 << m_idHelperSvc->toString(layerId));
148 return false;
149 }
150 const int strip = design.stripNumber(locPos2D);
151 if (strip < 0) {
152 ATH_MSG_VERBOSE("Hit " << Amg::toString(locHitPos) << " / "
153 << Amg::toString(locPos2D)
154 << " cannot trigger any signal in a strip for "
155 << m_idHelperSvc->toString(layerId) << std::endl
156 << design);
157 return false;
158 }
159
160 const Identifier digitId{idHelper.channelID(
161 gasGapId, idHelper.doubletZ(gasGapId), idHelper.doubletPhi(gasGapId),
162 idHelper.gasGap(gasGapId), measuresPhi, strip, isValid)};
163
164 if (!isValid) {
165 ATH_MSG_WARNING("Invalid hit identifier obtained for "
166 << m_idHelperSvc->toStringGasGap(gasGapId)
167 << ", eta strip " << strip << " & hit "
168 << Amg::toString(locHitPos, 2) << " /// " << design);
169 return false;
170 }
172 if (effiMap && effiMap->getEfficiency(digitId) <
173 CLHEP::RandFlat::shoot(rndEngine, 0., 1.)) {
174 ATH_MSG_VERBOSE("Hit is marked as inefficient");
175 return false;
176 }
177 if (!passDeadTime(digitId, hitTime(hit), m_deadTime, deadTimes)) {
178 ATH_MSG_VERBOSE("Reject hit due to dead map constraint");
179 return false;
180 }
182 const double signalTime =
183 hitTime(hit) + reEle->distanceToEdge(reEle->measurementHash(digitId),
184 locHitPos, EdgeSide::readOut) /
186 const double digitTime = CLHEP::RandGaussZiggurat::shoot(
187 rndEngine, signalTime, m_stripTimeResolution);
188 ATH_MSG_VERBOSE("Created new digit " << m_idHelperSvc->toString(digitId)
189 << ", @ " << Amg::toString(locPos2D)
190 << ", recorded time: " << digitTime);
191 outContainer.push_back(std::make_unique<RpcDigit>(
192 digitId, digitTime, timeOverThreshold(rndEngine)));
193 ++(m_acceptedHits[measuresPhi]);
194 return true;
195}
196
198 const Muon::DigitEffiData *effiMap,
199 RpcDigitCollection &outContainer,
200 CLHEP::HepRandomEngine *rndEngine,
201 DeadTimeMap &deadTimes) const {
202
203 ++(m_allHits[false]);
204 const Identifier gasGapId = simHit->identify();
205 const MuonGMR4::RpcReadoutElement *reEle =
206 m_detMgr->getRpcReadoutElement(gasGapId);
207 const Amg::Vector3D locPos = xAOD::toEigen(simHit->localPosition());
208 const MuonGMR4::StripDesign &design{*reEle->getParameters().etaDesign};
209 const RpcIdHelper &idHelper{m_idHelperSvc->rpcIdHelper()};
210
211 /* with RpcReadoutElement reEle you can access infor about the readout like */
212 ATH_MSG_VERBOSE("RpcDigiTool::digitizeHitBI reEle->nGasGaps "<< reEle->nGasGaps());
213 /* with StripDesign you can access the strip information of the readout
214 * element for instance: */
215 ATH_MSG_VERBOSE("RpcDigiTool::digitizeHitBI design: "<< design);
216
217 // Check the correctness of the local hit position
218 const Amg::Vector2D locHitPosition{locPos.x(), locPos.y()};
219 if (!design.insideTrapezoid(locHitPosition)) {
220 ATH_MSG_VERBOSE("The hit " << Amg::toString(locHitPosition)
221 << " is outside of the trapezoid bounds for "
222 << m_idHelperSvc->toStringGasGap(gasGapId));
223 return false;
224 }
225
226 // Calculate distance to strip edges (mm)
227 const IdentifierHash layHash = reEle->layerHash(gasGapId);
228 const double DistanceToReadOut =
229 reEle->distanceToEdge(layHash, locPos, EdgeSide::readOut); // mm
230 const double DistanceToHV =
231 reEle->distanceToEdge(layHash, locPos, EdgeSide::highVoltage); // mm
232
233 // Calculate charge deposited
234 const double TotalChargeOnStrip =
235 calculateChargeOnStrip(simHit, rndEngine, reEle->gasGapPitch());
236 ATH_MSG_VERBOSE(" total charge (fC): " << TotalChargeOnStrip);
237
238 // Calculate cluster size (number of strips)
239 int clusterSize = determineClusterSizeBI(gasGapId, rndEngine);
240 ATH_MSG_VERBOSE(" cluster size: " << clusterSize);
241
242 // Get corresponding strip number and apply checks
243 const int strip = design.stripNumber(locHitPosition);
244 if (strip < 0) {
245 ATH_MSG_VERBOSE("Hit " << Amg::toString(locHitPosition)
246 << " cannot trigger any signal in a strip for "
247 << m_idHelperSvc->toStringGasGap(gasGapId)
248 << std::endl
249 << design);
250 return false;
251 }
252
253 // Get min and max strips
254 int minStrip{strip}, maxStrip{strip}; // case strip number is 1
255 if (clusterSize > 1) {
256 int halfCluster = clusterSize / 2; // half cluster size (int)
257 minStrip = strip - halfCluster; // min strip number
258 if (clusterSize % 2 == 0) { // if clusterSize is even, we have to randomly
259 // assign one strip on left or right side
260 int side = Acts::copySign(1,CLHEP::RandFlat::shoot(rndEngine, 0., 1.) + 0.5);
261 minStrip += side; // if side==1 move the min strip to right
262 }
263 maxStrip = minStrip + clusterSize - 1;
264 // Check design strip boundaries
265 minStrip = std::max(minStrip, design.firstStripNumber());
266 maxStrip = std::min(design.firstStripNumber() + design.numStrips() - 1, maxStrip);
267 }
268
269 // Recalculate cluster size with minStrip and maxStrip
270 clusterSize = (maxStrip - minStrip) + 1;
271
272 // Divide charge on N strips
273 const std::vector<double> StripCharges =
274 divideChargeOnStrips(TotalChargeOnStrip, clusterSize, rndEngine);
275
276 // Digitize each strip
277 for (int aStrip = minStrip; aStrip <= maxStrip; aStrip++) {
278 bool isValid{false};
279 const Identifier digitId{idHelper.channelID(
280 gasGapId, idHelper.doubletZ(gasGapId), idHelper.doubletPhi(gasGapId),
281 idHelper.gasGap(gasGapId), false, aStrip, isValid)};
282
283 // Check digitID is valid
284 if (!isValid) {
285 ATH_MSG_WARNING("Failed to create a valid strip "
286 << m_idHelperSvc->toStringGasGap(gasGapId)
287 << ", strip: " << aStrip);
288 return false;
289 }
290 // Check is not dead time
291 if (!passDeadTime(digitId, hitTime(simHit), m_deadTime, deadTimes)) {
292 ATH_MSG_VERBOSE("Reject hit due to dead map constraint");
293 return false;
294 }
295 // Check whether the digit is actually efficient
296 const bool effiSignal1 =
297 !effiMap || effiMap->getEfficiency(gasGapId) >=
298 CLHEP::RandFlat::shoot(rndEngine, 0., 1.);
299 const bool effiSignal2 =
300 !effiMap || effiMap->getEfficiency(gasGapId) >=
301 CLHEP::RandFlat::shoot(rndEngine, 0., 1.);
302 if (effiSignal1) {
303 outContainer.push_back(std::make_unique<RpcDigit>(
304 digitId,
305 hitTime(simHit) + getTOA(StripCharges[aStrip], DistanceToHV / 1000.),
306 getTOT(StripCharges[aStrip])));
307 }
308 if (effiSignal2) {
309 outContainer.push_back(std::make_unique<RpcDigit>(
310 digitId,
311 hitTime(simHit) +
312 getTOA(StripCharges[aStrip], DistanceToReadOut / 1000.),
313 getTOT(StripCharges[aStrip]), true));
314 }
315 if (effiSignal1 || effiSignal2) {
316 ATH_MSG_VERBOSE("Digitize hit "
317 << m_idHelperSvc->toString(digitId)
318 << " located at: " << Amg::toString(locPos)
319 << ", SDO: " << Amg::toString(locHitPosition));
320 ++(m_acceptedHits[false]);
321 return true;
322 }
323 }
324
325 return false;
326}
327
328double RpcDigiTool::timeOverThreshold(CLHEP::HepRandomEngine *rndmEngine) {
329 // mn Time-over-threshold modeled as a narrow and a wide gaussian
330 // mn based on the fit documented in
331 // https://its.cern.ch/jira/browse/ATLASRECTS-7820
332 constexpr double tot_mean_narrow = 16.;
333 constexpr double tot_sigma_narrow = 2.;
334 constexpr double tot_mean_wide = 15.;
335 constexpr double tot_sigma_wide = 4.5;
336
337 double thetot = 0.;
338
339 if (CLHEP::RandFlat::shoot(rndmEngine) < 0.75) {
340 thetot = CLHEP::RandGaussZiggurat::shoot(rndmEngine, tot_mean_narrow,
341 tot_sigma_narrow);
342 } else {
343 thetot = CLHEP::RandGaussZiggurat::shoot(rndmEngine, tot_mean_wide,
344 tot_sigma_wide);
345 }
346
347 return std::max(thetot, 0.);
348}
349
350std::vector<double>
351RpcDigiTool::divideChargeOnStrips(double totalCharge, int n_strips,
352 CLHEP::HepRandomEngine *rndmEngine) const {
353
354 std::vector<double> charges;
355
356 switch (n_strips) {
357 case 1: {
358 // Trivial case, all charge on a single strip
359 charges.push_back(totalCharge);
360 break;
361 }
362 case 2: {
363 // We use a Gaussian distribution centered over 0.5 to simulate
364 // a charge sharing that is on average 50/50 but includes fluctuations
365 double f = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.5, 0.15);
366
367 // Make sure fraction is bounded between 0 and 1
368 f = std::clamp(f, 0., 1.);
369
370 charges.push_back(f * totalCharge);
371 charges.push_back((1.0 - f) * totalCharge);
372 break;
373 }
374 case 3: {
375 // These fractions are guesses on a reasonable charge
376 // sharing when three strips are activated.
377 // These fractions must be updated once the final
378 // distributions of TOT from Phase-II BI RPCs
379 // are available.
380 charges.push_back(0.20 * totalCharge); // left strip
381 charges.push_back(0.60 * totalCharge); // center strip
382 charges.push_back(0.20 * totalCharge); // right strip
383 break;
384 }
385 case 4: {
386 // These fractions are guesses on a reasonable charge
387 // sharing when four strips are activated.
388 // These fractions must be updated once the final
389 // distributions of TOT from Phase-II BI RPCs
390 // are available.
391 charges.push_back(0.15 * totalCharge); // left external strip
392 charges.push_back(0.35 * totalCharge); // left internal strip
393 charges.push_back(0.35 * totalCharge); // right internal strip
394 charges.push_back(0.15 * totalCharge); // right external strip
395 break;
396 }
397 default: {
398 // return empy vector
399 break;
400 }
401 }
402 return charges;
403}
404
406 CLHEP::HepRandomEngine *rndmEngine,
407 const double gasGapSize) const {
408
409 // Average energy to create an electron-ion pair inside RPC gas
410 constexpr double W_VALUE_EV = 30.0; // Unit: [eV/pair]
411
412 // RPC BI gas gap thickness
413 const double GAP_THICKNESS_M = gasGapSize; // Unit: [m] (2 mm for Phase-II BI RPCs))
414
415 // Townsend coefficient for gas mixture and operational voltage
416 constexpr double ALPHA_PER_M = 5500.0 / Gaudi::Units::m; // Unit: [1/m]
417
418 // Energy deposited by Geant4
419 const double energy_deposit_ev = simHit->energyDeposit() / Gaudi::Units::eV;
420
421 // Number of electron-ion pairs created
422 const double N0 = energy_deposit_ev / W_VALUE_EV;
423
424 // Primary ionization poistion inside gas gap
425 const double z_hit_m =
426 CLHEP::RandFlat::shoot(rndmEngine, 0.0, GAP_THICKNESS_M); // Unit: [m]
427
428 // Distance to anode
429 const double z_drift_m = std::abs(GAP_THICKNESS_M - z_hit_m); // Unit: [m]
430
431 // Avalanche gain
432 const double gas_gain = std::exp(ALPHA_PER_M * z_drift_m);
433
434 // Total charge
435 const double total_charge_c = N0 * gas_gain * Gaudi::Units::e_SI; // Unit: [C]
436
437 ATH_MSG_DEBUG(__func__<<"() - "<<__LINE__<<" GAP_THICKNESS_M: "<<GAP_THICKNESS_M<<
438 ", "<<energy_deposit_ev<<", z_hit_m: "<<z_hit_m<<", N0: "<<N0<<", z_drift_m: "<<z_drift_m
439 <<", gas_gain: "<<gas_gain<< "---> Charge on strip (fC): " << total_charge_c * 1e15);
440
441 return total_charge_c * 1e15; // charge in fC
442}
443
445 const Identifier &idGasGap, CLHEP::HepRandomEngine *rndmEngine) const {
446
447 const RpcIdHelper &id_helper{m_idHelperSvc->rpcIdHelper()};
448
449 ATH_MSG_DEBUG("RpcDigitizationTool::in determineClusterSize");
450
451 ATH_MSG_DEBUG("Digit Id = " << id_helper.show_to_string(idGasGap));
452
453 // These cluster size probabilities were taken from preliminary
454 // results from the BI RPC Upgrade work in 2025 at BB5.
455 // They could be updated if new results for BI RPCs become available.
456 static constexpr std::array<double, 4> ClusterSizeProbabilities{0.642, 0.316,
457 0.032, 0.010};
458 // Compile-time calculation of the cumulative array
459 // Used empty capture list [] since variables are static constexpr
460 static constexpr std::array<double, 4> cumulative = []() {
461 std::array<double, 4> acumulative{};
462 acumulative[0] = ClusterSizeProbabilities[0];
463 for (size_t i = 1; i < ClusterSizeProbabilities.size(); ++i) {
464 acumulative[i] = acumulative[i - 1] + ClusterSizeProbabilities[i];
465 }
466 return acumulative;
467 }();
468
469 float rndmCS = CLHEP::RandFlat::shoot(rndmEngine, 1.);
470
471 unsigned ClusterSize{0};
472 while (ClusterSize < ClusterSizeProbabilities.size() &&
473 rndmCS > cumulative[ClusterSize])
474 ++ClusterSize;
475
476 if (ClusterSize >= ClusterSizeProbabilities.size())
477 ClusterSize = ClusterSizeProbabilities.size() - 1;
478 return ClusterSize + 1;
479}
480
481} // 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
IdentifierHash measurementHash(const Identifier &measId) const override final
Constructs the identifier hash from the full measurement Identifier.
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).
double gasGapPitch() const
Returns the thickness of a RPC gasgap.
int firstStripNumber() const
Returns the number of the first strip.
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.
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
Gaudi::Property< double > m_stripTimeResolution
Definition RpcDigiTool.h:77
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:84
Gaudi::Property< double > m_deadTime
Definition RpcDigiTool.h:81
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:65
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.
int determineClusterSizeBI(const Identifier &id, CLHEP::HepRandomEngine *rndmEngine) const
Returns BI cluster strip molteplicity.
SG::WriteHandleKey< RpcDigitContainer > m_writeKey
Definition RpcDigiTool.h:62
StatusCode finalize() override final
Gaudi::Property< double > m_propagationVelocity
Definition RpcDigiTool.h:73
OutDigitCache_t< RpcDigitCollection > DigiCache
Definition RpcDigiTool.h:61
static double timeOverThreshold(CLHEP::HepRandomEngine *rndmEngine)
Roll the time over threshold for each signal digit.
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