6#include "CLHEP/Random/RandGaussZiggurat.h"
7#include "GaudiKernel/SystemOfUnits.h"
13 constexpr double percentage(
unsigned int numerator,
unsigned int denom) {
14 return 100. * numerator / std::max(denom, 1u);
16 using ChVec_t = std::vector<std::uint16_t>;
28 return StatusCode::SUCCESS;
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;
45 constexpr std::array<double, 3> coeffs{19.9587, 0.10081, -0.00017};
48 return polynomialSum(aCharge, coeffs);
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};
58 return polynomialSum(aDistance/1000., distCoeffs) +
59 polynomialSum(aCharge, chargeCoeffs);
76 for (
const TimedHit &simHit : viewer) {
82 const std::size_t beforeDigiSize = digiColl->
size();
84 if (
m_detMgr->getRpcReadoutElement(hitId)->nPhiStrips() > 0) {
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);
94 }
else if (
digitizeHitBI(simHit, efficiencyMap, *digiColl, rndEngine,
96 sdo =
addSDO(simHit, sdoContainer);
100 dec_etaChannel(*sdo).clear();
101 dec_phiChannel(*sdo).clear();
102 for (std::size_t newDigit = beforeDigiSize; newDigit< digiColl->
size(); ++newDigit) {
104 ChVec_t& ch{idHelper.
measuresPhi(
id)? dec_phiChannel(*sdo) : dec_etaChannel(*sdo)};
105 ch.push_back(idHelper.
channel(
id));
109 }
while (viewer.
next());
113 return StatusCode::SUCCESS;
118 CLHEP::HepRandomEngine *rndEngine,
121 ++(m_allHits[measuresPhi]);
125 m_detMgr->getRpcReadoutElement(gasGapId);
143 const Amg::Vector2D locPos2D = layerDesign->to2D(locHitPos, measuresPhi);
147 <<
" is outside of the trapezoid bounds for "
155 <<
" cannot trigger any signal in a strip for "
162 const bool effiSignal =
164 CLHEP::RandFlat::shoot(rndEngine, 0., 1.);
165 if (!effiSignal)
return false;
168 const double DistanceToEdge =
172 const double TotalChargeOnStrip =
182 if (clusterSize > 1) {
183 int halfCluster = clusterSize / 2;
184 minStrip =
strip - halfCluster;
185 if (clusterSize % 2 == 0) {
187 int side = Acts::copySign(1,CLHEP::RandFlat::shoot(rndEngine, 0., 1.) + 0.5);
190 maxStrip = minStrip + clusterSize - 1;
197 clusterSize = (maxStrip - minStrip) + 1;
200 const std::vector<double> StripCharges =
204 bool hasAcceptedStrip=
false;
205 for (
int aStrip = minStrip; aStrip <= maxStrip; aStrip++) {
216 <<
", strip: " << aStrip);
225 outContainer.
push_back(std::make_unique<RpcDigit>(
227 hitTime(simHit) +
getTOA(StripCharges[aStrip-minStrip], DistanceToEdge),
228 getTOT(StripCharges[aStrip-minStrip])));
233 ++(m_acceptedHits[measuresPhi]);
234 hasAcceptedStrip=
true;
237 return hasAcceptedStrip;
244 CLHEP::HepRandomEngine *rndEngine,
247 ++(m_allHits[
false]);
250 m_detMgr->getRpcReadoutElement(gasGapId);
262 const Amg::Vector2D locHitPosition{locHitPos.x(), locHitPos.y()};
265 <<
" is outside of the trapezoid bounds for "
272 const double DistanceToReadOut =
274 const double DistanceToHV =
278 const double TotalChargeOnStrip =
291 <<
" cannot trigger any signal in a strip for "
299 const bool effiSignal1 =
301 CLHEP::RandFlat::shoot(rndEngine, 0., 1.);
302 const bool effiSignal2 =
304 CLHEP::RandFlat::shoot(rndEngine, 0., 1.);
305 if (!effiSignal1 && !effiSignal2)
return false;
309 if (clusterSize > 1) {
310 int halfCluster = clusterSize / 2;
311 minStrip =
strip - halfCluster;
312 if (clusterSize % 2 == 0) {
314 int side = Acts::copySign(1,CLHEP::RandFlat::shoot(rndEngine, 0., 1.) + 0.5);
317 maxStrip = minStrip + clusterSize - 1;
324 clusterSize = (maxStrip - minStrip) + 1;
327 const std::vector<double> StripCharges =
331 bool hasAcceptedStrip=
false;
332 for (
int aStrip = minStrip; aStrip <= maxStrip; aStrip++) {
342 <<
", strip: " << aStrip);
352 outContainer.
push_back(std::make_unique<RpcDigit>(
354 hitTime(simHit) +
getTOA(StripCharges[aStrip-minStrip], DistanceToHV),
355 getTOT(StripCharges[aStrip-minStrip])));
358 outContainer.
push_back(std::make_unique<RpcDigit>(
361 getTOA(StripCharges[aStrip-minStrip], DistanceToReadOut),
362 getTOT(StripCharges[aStrip-minStrip]),
true));
364 if (effiSignal1 || effiSignal2) {
369 ++(m_acceptedHits[
false]);
370 hasAcceptedStrip=
true;
374 return hasAcceptedStrip;
379 CLHEP::HepRandomEngine *rndmEngine)
const {
381 std::vector<double> charges;
386 charges.push_back(totalCharge);
392 double f = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.5, 0.15);
395 f = std::clamp(f, 0., 1.);
397 charges.push_back(f * totalCharge);
398 charges.push_back((1.0 - f) * totalCharge);
407 charges.push_back(0.20 * totalCharge);
408 charges.push_back(0.60 * totalCharge);
409 charges.push_back(0.20 * totalCharge);
418 charges.push_back(0.15 * totalCharge);
419 charges.push_back(0.35 * totalCharge);
420 charges.push_back(0.35 * totalCharge);
421 charges.push_back(0.15 * totalCharge);
434 CLHEP::HepRandomEngine *rndmEngine,
435 const double gasGapSize)
const {
438 constexpr double W_VALUE_EV = 30.0;
441 const double GAP_THICKNESS_MM = gasGapSize;
444 constexpr double ALPHA_PER_MM = 5.5;
447 const double energy_deposit_ev = simHit->
energyDeposit() / Gaudi::Units::eV;
450 const double N0 = energy_deposit_ev / W_VALUE_EV;
453 const double z_hit_mm =
454 CLHEP::RandFlat::shoot(rndmEngine, 0.0, GAP_THICKNESS_MM);
457 const double z_drift_mm = std::abs(GAP_THICKNESS_MM - z_hit_mm);
460 const double gas_gain = std::exp(ALPHA_PER_MM * z_drift_mm);
463 const double total_charge_c = N0 * gas_gain * Gaudi::Units::e_SI;
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);
469 return total_charge_c * 1e15;
473 const Identifier &idGasGap, CLHEP::HepRandomEngine *rndmEngine,
bool isBIRPC)
const {
477 ATH_MSG_DEBUG(
"RpcDigitizationTool::in determineClusterSize");
483 static constexpr std::array<double, 4> ClusterSizeProbabilities{0.610, 0.260,
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];
499 static constexpr std::array<double, 4> ClusterSizeProbabilitiesBI{0.642, 0.316,
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];
512 std::array<double, 4> theCumulative{};
514 theCumulative=cumulativeBI;
516 theCumulative=cumulative;
519 float rndmCS = CLHEP::RandFlat::shoot(rndmEngine, 1.);
521 unsigned ClusterSize{1};
522 while (ClusterSize < theCumulative.size() &&
523 rndmCS > theCumulative[ClusterSize-1])
526 if (ClusterSize > theCumulative.size())
527 ClusterSize = theCumulative.size();
#define ATH_CHECK
Evaluate an expression and check for errors.
bool isValid() const
Test to see if the link can be dereferenced.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(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
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.
const parameterBook & getParameters() const
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
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
GeoModel::TransientConstSharedPtr< StripLayer > StripLayerPtr
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.
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.