6#include "CLHEP/Random/RandGaussZiggurat.h"
7#include "GaudiKernel/SystemOfUnits.h"
13constexpr double percentage(
unsigned int numerator,
unsigned int denom) {
14 return 100. * numerator / std::max(denom, 1u);
25 return StatusCode::SUCCESS;
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;
51 for (
const TimedHit &simHit : viewer) {
63 const bool digitizedEta =
digitizeHit(simHit,
false, efficiencyMap,
64 *digiColl, rndEngine, deadTimes);
66 const bool digitizedPhi =
digitizeHit(simHit,
true, efficiencyMap,
67 *digiColl, rndEngine, deadTimes);
69 if (digitizedEta || digitizedPhi) {
73 }
else if (
digitizeHitBI(simHit, efficiencyMap, *digiColl, rndEngine,
79 }
while (viewer.
next());
83 return StatusCode::SUCCESS;
88 CLHEP::HepRandomEngine *rndEngine,
91 ++(m_allHits[measuresPhi]);
95 m_detMgr->getRpcReadoutElement(gasGapId);
109 const double uncert = design.
stripPitch() / std::sqrt(12.);
111 locHitPos[measuresPhi] = CLHEP::RandGaussZiggurat::shoot(
112 rndEngine, locHitPos[measuresPhi], uncert);
114 const Amg::Vector2D locPos2D = layerDesign->to2D(locHitPos, measuresPhi);
118 <<
" is outside of the trapezoid bounds for "
126 <<
" cannot trigger any signal in a strip for "
139 <<
", eta strip " <<
strip <<
" & hit "
145 CLHEP::RandFlat::shoot(rndEngine, 0., 1.)) {
154 const double signalTime =
156 locHitPos, EdgeSide::readOut) /
158 const double digitTime = CLHEP::RandGaussZiggurat::shoot(
162 <<
", recorded time: " << digitTime);
163 outContainer.
push_back(std::make_unique<RpcDigit>(
165 ++(m_acceptedHits[measuresPhi]);
172 CLHEP::HepRandomEngine *rndEngine,
175 ++(m_allHits[
false]);
178 m_detMgr->getRpcReadoutElement(gasGapId);
189 ATH_MSG_DEBUG(
"RpcDigiTool::digitizeHitBI design.stripPitch() "
191 ATH_MSG_DEBUG(
"RpcDigiTool::digitizeHitBI design.stripWidth() "
193 ATH_MSG_DEBUG(
"RpcDigiTool::digitizeHitBI design.numStrips() "
195 ATH_MSG_DEBUG(
"RpcDigiTool::digitizeHitBI design.halfWidth() "
202 <<
" is outside of the trapezoid bounds for "
209 const double DistanceToReadOut =
211 const double DistanceToHV =
215 const double TotalChargeOnStrip =
228 <<
" cannot trigger any signal in a strip for "
237 if (clusterSize > 1) {
238 int halfCluster = clusterSize / 2;
239 minStrip =
strip - halfCluster;
240 if (clusterSize % 2 == 0) {
242 int side = (int)(CLHEP::RandFlat::shoot(rndEngine, 0., 1.) + 0.5);
245 maxStrip = minStrip + clusterSize - 1;
255 if (minStrip == maxStrip)
258 clusterSize = (maxStrip - minStrip) + 1;
262 const std::vector<double> StripCharges =
268 for (
int aStrip = minStrip; aStrip <= maxStrip; aStrip++) {
278 <<
", strip: " << aStrip);
287 const bool effiSignal1 =
289 CLHEP::RandFlat::shoot(rndEngine, 0., 1.);
290 const bool effiSignal2 =
292 CLHEP::RandFlat::shoot(rndEngine, 0., 1.);
294 outContainer.
push_back(std::make_unique<RpcDigit>(
296 hitTime(simHit) +
getTOA(StripCharges[aStrip], DistanceToHV / 1000.),
297 getTOT(StripCharges[aStrip])));
300 outContainer.
push_back(std::make_unique<RpcDigit>(
303 getTOA(StripCharges[aStrip], DistanceToReadOut / 1000.),
304 getTOT(StripCharges[aStrip]),
true));
306 if (effiSignal1 || effiSignal2) {
311 ++(m_acceptedHits[
false]);
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;
330 if (CLHEP::RandFlat::shoot(rndmEngine) < 0.75) {
331 thetot = CLHEP::RandGaussZiggurat::shoot(rndmEngine, tot_mean_narrow,
334 thetot = CLHEP::RandGaussZiggurat::shoot(rndmEngine, tot_mean_wide,
338 return std::max(thetot, 0.);
343 CLHEP::HepRandomEngine *rndmEngine)
const {
345 std::vector<double> charges;
350 charges.push_back(totalCharge);
356 double f = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.5, 0.15);
359 f = std::clamp(f, 0., 1.);
361 charges.push_back(f * totalCharge);
362 charges.push_back((1.0 - f) * totalCharge);
371 charges.push_back(0.20 * totalCharge);
372 charges.push_back(0.60 * totalCharge);
373 charges.push_back(0.20 * totalCharge);
382 charges.push_back(0.15 * totalCharge);
383 charges.push_back(0.35 * totalCharge);
384 charges.push_back(0.35 * totalCharge);
385 charges.push_back(0.15 * totalCharge);
397 CLHEP::HepRandomEngine *rndmEngine,
398 const double gasGapSize)
const {
401 constexpr double W_VALUE_EV = 30.0;
404 const double GAP_THICKNESS_M =
408 constexpr double ALPHA_PER_M = 5500.0;
411 const double energy_deposit_ev =
415 const double N0 = energy_deposit_ev / W_VALUE_EV;
418 const double z_hit_m =
419 CLHEP::RandFlat::shoot(rndmEngine, 0.0, GAP_THICKNESS_M);
422 const double z_drift_m = std::abs(GAP_THICKNESS_M - z_hit_m);
425 const double gas_gain = std::exp(ALPHA_PER_M * z_drift_m);
428 const double total_charge_c = N0 * gas_gain * Gaudi::Units::e_SI;
430 ATH_MSG_DEBUG(
"Charge on strip (fC): " << total_charge_c * 1e15);
432 return total_charge_c * 1e15;
436 const Identifier &idGasGap, CLHEP::HepRandomEngine *rndmEngine)
const {
440 ATH_MSG_DEBUG(
"RpcDigitizationTool::in determineClusterSize");
447 static constexpr std::array<double, 4> ClusterSizeProbabilities{0.642, 0.316,
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];
460 float rndmCS = CLHEP::RandFlat::shoot(rndmEngine, 1.);
462 unsigned ClusterSize{0};
463 while (ClusterSize < ClusterSizeProbabilities.size() &&
464 rndmCS > cumulative[ClusterSize])
467 if (ClusterSize >= ClusterSizeProbabilities.size())
468 ClusterSize = ClusterSizeProbabilities.size() - 1;
469 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 * 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.
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
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
GeoModel::TransientConstSharedPtr< StripLayer > StripLayerPtr
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.