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};
47 return polynomialSum(aCharge, coeffs);
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};
56 return polynomialSum(aDistance, distCoeffs) +
57 polynomialSum(aCharge, chargeCoeffs);
74 for (
const TimedHit &simHit : viewer) {
80 const std::size_t beforeDigiSize = digiColl->
size();
82 if (
m_detMgr->getRpcReadoutElement(hitId)->nPhiStrips() > 0) {
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);
92 }
else if (
digitizeHitBI(simHit, efficiencyMap, *digiColl, rndEngine,
94 sdo =
addSDO(simHit, sdoContainer);
98 dec_etaChannel(*sdo).clear();
99 dec_phiChannel(*sdo).clear();
100 for (std::size_t newDigit = beforeDigiSize; newDigit< digiColl->
size(); ++newDigit) {
102 ChVec_t& ch{idHelper.
measuresPhi(
id)? dec_phiChannel(*sdo) : dec_etaChannel(*sdo)};
103 ch.push_back(idHelper.
channel(
id));
107 }
while (viewer.
next());
111 return StatusCode::SUCCESS;
116 CLHEP::HepRandomEngine *rndEngine,
119 ++(m_allHits[measuresPhi]);
123 m_detMgr->getRpcReadoutElement(gasGapId);
137 const double uncert = design.
stripPitch() / std::sqrt(12.);
139 locHitPos[measuresPhi] = CLHEP::RandGaussZiggurat::shoot(
140 rndEngine, locHitPos[measuresPhi], uncert);
142 const Amg::Vector2D locPos2D = layerDesign->to2D(locHitPos, measuresPhi);
146 <<
" is outside of the trapezoid bounds for "
154 <<
" cannot trigger any signal in a strip for "
167 <<
", eta strip " <<
strip <<
" & hit "
173 CLHEP::RandFlat::shoot(rndEngine, 0., 1.)) {
182 const double signalTime =
184 locHitPos, EdgeSide::readOut) /
186 const double digitTime = CLHEP::RandGaussZiggurat::shoot(
190 <<
", recorded time: " << digitTime);
191 outContainer.
push_back(std::make_unique<RpcDigit>(
193 ++(m_acceptedHits[measuresPhi]);
200 CLHEP::HepRandomEngine *rndEngine,
203 ++(m_allHits[
false]);
206 m_detMgr->getRpcReadoutElement(gasGapId);
221 <<
" is outside of the trapezoid bounds for "
228 const double DistanceToReadOut =
230 const double DistanceToHV =
234 const double TotalChargeOnStrip =
246 <<
" cannot trigger any signal in a strip for "
255 if (clusterSize > 1) {
256 int halfCluster = clusterSize / 2;
257 minStrip =
strip - halfCluster;
258 if (clusterSize % 2 == 0) {
260 int side = Acts::copySign(1,CLHEP::RandFlat::shoot(rndEngine, 0., 1.) + 0.5);
263 maxStrip = minStrip + clusterSize - 1;
270 clusterSize = (maxStrip - minStrip) + 1;
273 const std::vector<double> StripCharges =
277 for (
int aStrip = minStrip; aStrip <= maxStrip; aStrip++) {
287 <<
", strip: " << aStrip);
296 const bool effiSignal1 =
298 CLHEP::RandFlat::shoot(rndEngine, 0., 1.);
299 const bool effiSignal2 =
301 CLHEP::RandFlat::shoot(rndEngine, 0., 1.);
303 outContainer.
push_back(std::make_unique<RpcDigit>(
305 hitTime(simHit) +
getTOA(StripCharges[aStrip], DistanceToHV / 1000.),
306 getTOT(StripCharges[aStrip])));
309 outContainer.
push_back(std::make_unique<RpcDigit>(
312 getTOA(StripCharges[aStrip], DistanceToReadOut / 1000.),
313 getTOT(StripCharges[aStrip]),
true));
315 if (effiSignal1 || effiSignal2) {
320 ++(m_acceptedHits[
false]);
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;
339 if (CLHEP::RandFlat::shoot(rndmEngine) < 0.75) {
340 thetot = CLHEP::RandGaussZiggurat::shoot(rndmEngine, tot_mean_narrow,
343 thetot = CLHEP::RandGaussZiggurat::shoot(rndmEngine, tot_mean_wide,
347 return std::max(thetot, 0.);
352 CLHEP::HepRandomEngine *rndmEngine)
const {
354 std::vector<double> charges;
359 charges.push_back(totalCharge);
365 double f = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.5, 0.15);
368 f = std::clamp(f, 0., 1.);
370 charges.push_back(f * totalCharge);
371 charges.push_back((1.0 - f) * totalCharge);
380 charges.push_back(0.20 * totalCharge);
381 charges.push_back(0.60 * totalCharge);
382 charges.push_back(0.20 * totalCharge);
391 charges.push_back(0.15 * totalCharge);
392 charges.push_back(0.35 * totalCharge);
393 charges.push_back(0.35 * totalCharge);
394 charges.push_back(0.15 * totalCharge);
406 CLHEP::HepRandomEngine *rndmEngine,
407 const double gasGapSize)
const {
410 constexpr double W_VALUE_EV = 30.0;
413 const double GAP_THICKNESS_M = gasGapSize;
416 constexpr double ALPHA_PER_M = 5500.0 / Gaudi::Units::m;
419 const double energy_deposit_ev = simHit->
energyDeposit() / Gaudi::Units::eV;
422 const double N0 = energy_deposit_ev / W_VALUE_EV;
425 const double z_hit_m =
426 CLHEP::RandFlat::shoot(rndmEngine, 0.0, GAP_THICKNESS_M);
429 const double z_drift_m = std::abs(GAP_THICKNESS_M - z_hit_m);
432 const double gas_gain = std::exp(ALPHA_PER_M * z_drift_m);
435 const double total_charge_c = N0 * gas_gain * Gaudi::Units::e_SI;
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);
441 return total_charge_c * 1e15;
445 const Identifier &idGasGap, CLHEP::HepRandomEngine *rndmEngine)
const {
449 ATH_MSG_DEBUG(
"RpcDigitizationTool::in determineClusterSize");
456 static constexpr std::array<double, 4> ClusterSizeProbabilities{0.642, 0.316,
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];
469 float rndmCS = CLHEP::RandFlat::shoot(rndmEngine, 1.);
471 unsigned ClusterSize{0};
472 while (ClusterSize < ClusterSizeProbabilities.size() &&
473 rndmCS > cumulative[ClusterSize])
476 if (ClusterSize >= ClusterSizeProbabilities.size())
477 ClusterSize = ClusterSizeProbabilities.size() - 1;
478 return ClusterSize + 1;
#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
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.
const parameterBook & getParameters() const
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
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.