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