ATLAS Offline Software
RpcFastDigiTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 #include "RpcFastDigiTool.h"
5 #include "CLHEP/Random/RandGaussZiggurat.h"
6 #include "CLHEP/Random/RandFlat.h"
7 namespace {
8  constexpr double percentage(unsigned int numerator, unsigned int denom) {
9  return 100. * numerator / std::max(denom, 1u);
10  }
11 
12 }
13 namespace MuonR4 {
14 
15  RpcFastDigiTool::RpcFastDigiTool(const std::string& type, const std::string& name, const IInterface* pIID):
17 
22  m_stIdxBIL = m_idHelperSvc->rpcIdHelper().stationNameIndex("BIL");
23  return StatusCode::SUCCESS;
24  }
26  ATH_MSG_INFO("Tried to convert "<<m_allHits[0]<<"/"<<m_allHits[1]<<" hits. In, "
27  <<percentage(m_acceptedHits[0], m_allHits[0]) <<"/"
28  <<percentage(m_acceptedHits[1], m_allHits[1]) <<"% of the cases, the conversion was successful");
29  return StatusCode::SUCCESS;
30  }
31  StatusCode RpcFastDigiTool::digitize(const EventContext& ctx,
32  const TimedHits& hitsToDigit,
33  xAOD::MuonSimHitContainer* sdoContainer) const {
34  const RpcIdHelper& idHelper{m_idHelperSvc->rpcIdHelper()};
35  // Prepare the temporary cache
36  DigiCache digitCache{};
38  const Muon::DigitEffiData* efficiencyMap{nullptr};
39  ATH_CHECK(retrieveConditions(ctx, m_effiDataKey, efficiencyMap));
40 
41  CLHEP::HepRandomEngine* rndEngine = getRandomEngine(ctx);
42  for (const TimedHit& simHit : hitsToDigit) {
43  const Identifier hitId{simHit->identify()};
45  if (std::abs(simHit->pdgId()) != 13) continue;
46 
47  const MuonGMR4::RpcReadoutElement* readOutEle = m_detMgr->getRpcReadoutElement(hitId);
48  const Amg::Vector3D locPos{xAOD::toEigen(simHit->localPosition())};
49  RpcDigitCollection* digiColl = fetchCollection(hitId, digitCache);
50  if (m_idHelperSvc->stationName(hitId) != m_stIdxBIL) {
52  bool digitized = digitizeHit(hitId, false, readOutEle->getParameters().etaDesign,
53  hitTime(simHit), locPos.x(),
54  efficiencyMap, *digiColl, rndEngine);
55  digitized |= digitizeHit(hitId, true, readOutEle->getParameters().phiDesign,
56  hitTime(simHit), locPos.y(),
57  efficiencyMap, *digiColl, rndEngine);
58  if (digitized) {
59  addSDO(simHit, sdoContainer);
60  }
61  } else if (digitizeHit(hitId, readOutEle->getParameters().etaDesign,
62  hitTime(simHit), locPos.block<2,1>(0,0),
63  efficiencyMap, *digiColl, rndEngine)) {
64  addSDO(simHit, sdoContainer);
65  }
66  }
68  ATH_CHECK(writeDigitContainer(ctx, m_writeKey, std::move(digitCache), idHelper.module_hash_max()));
69  return StatusCode::SUCCESS;
70  }
72  const bool measuresPhi,
73  const MuonGMR4::StripDesignPtr& designPtr,
74  const double hitTime,
75  const double locPosOnStrip,
76  const Muon::DigitEffiData* effiMap,
77  RpcDigitCollection& outContainer,
78  CLHEP::HepRandomEngine* rndEngine) const {
79 
81  if (!designPtr){
82  return false;
83  }
84  ++(m_allHits[measuresPhi]);
85  const MuonGMR4::StripDesign& design{*designPtr};
86 
87  const double uncert = design.stripPitch() / std::sqrt(12.);
88  const double smearedX = CLHEP::RandGaussZiggurat::shoot(rndEngine, locPosOnStrip, uncert);
89  const Amg::Vector2D locHitPos{smearedX * Amg::Vector2D::UnitX()};
90 
91  if (!design.insideTrapezoid(locHitPos)) {
92  ATH_MSG_VERBOSE("The hit "<<Amg::toString(locHitPos)<<" is outside of the trapezoid bounds for "
93  <<m_idHelperSvc->toStringGasGap(gasGapId)<<", measuresPhi: "<<(measuresPhi ? "yay" : "nay"));
94  return false;
95  }
96  const int strip = design.stripNumber(locHitPos);
97  if (strip < 0) {
98  ATH_MSG_VERBOSE("Hit " << Amg::toString(locHitPos) << " cannot trigger any signal in a strip for "
99  << m_idHelperSvc->toStringGasGap(gasGapId) <<std::endl<<design<<
100  std::endl<<", measuresPhi: "<<(measuresPhi ? "yay" : "nay"));
101  return false;
102  }
103 
104  const RpcIdHelper& id_helper{m_idHelperSvc->rpcIdHelper()};
105 
106  bool isValid{false};
107  const Identifier digitId{id_helper.channelID(gasGapId,
108  id_helper.doubletZ(gasGapId),
109  id_helper.doubletPhi(gasGapId),
110  id_helper.gasGap(gasGapId),
111  measuresPhi, strip, isValid)};
112 
113  if (!isValid) {
114  ATH_MSG_WARNING("Invalid hit identifier obtained for "<<m_idHelperSvc->toStringGasGap(gasGapId)
115  <<", eta strip "<<strip<<" & hit "<<Amg::toString(locHitPos,2 )
116  <<" /// "<<design);
117  return false;
118  }
120  if (effiMap && effiMap->getEfficiency(digitId) < CLHEP::RandFlat::shoot(rndEngine,0.,1.)) {
121  ATH_MSG_VERBOSE("Hit is marked as inefficient");
122  return false;
123  }
124  outContainer.push_back(std::make_unique<RpcDigit>(digitId, hitTime, timeOverThreshold(rndEngine)));
125  ++(m_acceptedHits[measuresPhi]);
126  return true;
127  }
129  const MuonGMR4::StripDesignPtr& designPtr,
130  const double hitTime,
131  const Amg::Vector2D& locPos,
132  const Muon::DigitEffiData* effiMap,
133  RpcDigitCollection& outContainer,
134  CLHEP::HepRandomEngine* rndEngine) const {
135 
136  ++(m_allHits[false]);
137  const MuonGMR4::StripDesign& design{*designPtr};
138  const RpcIdHelper& id_helper{m_idHelperSvc->rpcIdHelper()};
139 
140 
142  const double uncert = design.stripPitch() / std::sqrt(12.);
143  const double smearedX = CLHEP::RandGaussZiggurat::shoot(rndEngine, locPos.x(), uncert);
144 
146  const double stripLength = design.stripLength(1); // in mm, assuming lenLeftEdge() == lenRightEdge() i.e. rectangular strip
147 
148  // Distance in mm along strip to y=-stripLength/2 (L) and y=stripLength/2 (R)
149  const double stripLeft = -(stripLength / 2);
150  const double stripRight = (stripLength / 2);
151  const double distToL = std::abs(stripLeft - locPos.y());
152  const double distToR = std::abs(stripRight - locPos.y());
153 
154  // True propagation time in nanoseconds along strip to y=-stripLength/2 (L) and y=stripLength/2 (R)
155  const double propagationTimeL = distToL / m_propagationVelocity;
156  const double propagationTimeR = distToR / m_propagationVelocity;
157 
159  const double smearedTimeL = CLHEP::RandGaussZiggurat::shoot(rndEngine, propagationTimeL, m_stripTimeResolution);
160  const double smearedTimeR = CLHEP::RandGaussZiggurat::shoot(rndEngine, propagationTimeR, m_stripTimeResolution);
161 
162  const double smearedDeltaT = smearedTimeR - smearedTimeL;
163 
164  /*
165  |--- d1, t1 ---||--- d1, t1 ---||-- d --| For t2 > t1:
166  ||||||||||||||||X|||||||||||||||||||||||| <- RPC strip, deltaT = t2 - t1, d1 = v_prop * t1 (likewise for d2),
167  |-------- d2, t2 -------| X is a hit l = d1 + d2, d = d2 - d1 -> d = l - 2d1 = v_prop * deltaT
168  |----------------- l -------------------|
169  Hence, d1 = 0.5 * (l - d) = 0.5 * (l - v_prop * deltaT)
170 
171  Then converting to coordinate system where 0 -> -0.5*l to match strip local coordinates
172  d1 -> d1 = -0.5*l + 0.5* (l-d) = -0.5*d = -0.5 * v_pro*deltaT
173  */
174  const double smearedY = -0.5 * m_propagationVelocity * smearedDeltaT; //in mm
175  //If smearedDeltaT == 0 position is in the centre of the strip (0).
176 
177  const Amg::Vector2D locHitPos{smearedX, smearedY};
178 
179  if (!design.insideTrapezoid(locHitPos)) {
180  ATH_MSG_VERBOSE("The hit "<<Amg::toString(locHitPos)<<" is outside of the trapezoid bounds for "
181  <<m_idHelperSvc->toStringGasGap(gasGapId));
182  return false;
183  }
184 
185  const int strip = design.stripNumber(locHitPos);
186  if (strip < 0) {
187  ATH_MSG_VERBOSE("Hit " << Amg::toString(locHitPos) << " cannot trigger any signal in a strip for "
188  << m_idHelperSvc->toStringGasGap(gasGapId) <<std::endl<<design);
189  return false;
190  }
191 
192 
193  bool isValid{false};
194  const Identifier digitId{id_helper.channelID(gasGapId,
195  id_helper.doubletZ(gasGapId),
196  id_helper.doubletPhi(gasGapId),
197  id_helper.gasGap(gasGapId),
198  false, strip, isValid)};
199  if (!isValid) {
200  ATH_MSG_WARNING("Failed to create a valid strip "<<m_idHelperSvc->toStringGasGap(gasGapId)
201  <<", strip: "<<strip);
202  return false;
203  }
204 
206  const bool effiSignal1 = !effiMap || effiMap->getEfficiency(gasGapId) >= CLHEP::RandFlat::shoot(rndEngine,0.,1.);
207  const bool effiSignal2 = !effiMap || effiMap->getEfficiency(gasGapId) >= CLHEP::RandFlat::shoot(rndEngine,0., 1.);
208  if (effiSignal1) {
209  outContainer.push_back(std::make_unique<RpcDigit>(digitId, hitTime + smearedTimeR, timeOverThreshold(rndEngine)));
210  }
211  if (effiSignal2) {
212  outContainer.push_back(std::make_unique<RpcDigit>(digitId, hitTime + smearedTimeL, timeOverThreshold(rndEngine), true));
213  }
214  if (effiSignal1 || effiSignal2) {
215  ++(m_acceptedHits[false]);
216  return true;
217  }
218  return false;
219  }
220  double RpcFastDigiTool::timeOverThreshold(CLHEP::HepRandomEngine* rndmEngine) {
221  //mn Time-over-threshold modeled as a narrow and a wide gaussian
222  //mn based on the fit documented in https://its.cern.ch/jira/browse/ATLASRECTS-7820
223  constexpr double tot_mean_narrow = 16.;
224  constexpr double tot_sigma_narrow = 2.;
225  constexpr double tot_mean_wide = 15.;
226  constexpr double tot_sigma_wide = 4.5;
227 
228  double thetot = 0.;
229 
230  if (CLHEP::RandFlat::shoot(rndmEngine)<0.75) {
231  thetot = CLHEP::RandGaussZiggurat::shoot(rndmEngine, tot_mean_narrow, tot_sigma_narrow);
232  } else {
233  thetot = CLHEP::RandGaussZiggurat::shoot(rndmEngine, tot_mean_wide, tot_sigma_wide);
234  }
235 
236  return std::max(thetot, 0.);
237  }
238 
239 }
GeoModel::TransientConstSharedPtr< StripDesign >
MuonGMR4::StripDesign
Definition: StripDesign.h:30
MuonR4::RpcFastDigiTool::m_effiDataKey
SG::ReadCondHandleKey< Muon::DigitEffiData > m_effiDataKey
Definition: RpcFastDigiTool.h:72
MuonR4::RpcFastDigiTool::m_stripTimeResolution
Gaudi::Property< double > m_stripTimeResolution
Definition: RpcFastDigiTool.h:81
max
#define max(a, b)
Definition: cfImp.cxx:41
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
Amg::Vector2D
Eigen::Matrix< double, 2, 1 > Vector2D
Definition: GeoPrimitives.h:48
RpcDigitCollection
Definition: RpcDigitCollection.h:17
MuonR4::RpcFastDigiTool::m_stIdxBIL
int m_stIdxBIL
Definition: RpcFastDigiTool.h:28
MuonGMR4::RpcReadoutElement::parameterBook::etaDesign
StripDesignPtr etaDesign
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/RpcReadoutElement.h:40
MuonR4::RpcFastDigiTool::initialize
StatusCode initialize() override final
Definition: RpcFastDigiTool.cxx:18
TimedHitPtr< xAOD::MuonSimHit >
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
isValid
bool isValid(const T &p)
Definition: AtlasPID.h:214
SG::VarHandleKey::empty
bool empty() const
Test if the key is blank.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:150
MuonR4::RpcFastDigiTool::DigiCache
OutDigitCache_t< RpcDigitCollection > DigiCache
Definition: RpcFastDigiTool.h:69
MuonGMR4::RpcReadoutElement
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/RpcReadoutElement.h:18
RpcIdHelper
Definition: RpcIdHelper.h:51
MuonR4::MuonDigitizationTool::retrieveConditions
StatusCode retrieveConditions(const EventContext &ctx, const SG::ReadCondHandleKey< Container > &key, const Container *&contPtr) const
Helper function to access the conditions data.
Trk::u
@ u
Enums for curvilinear frames.
Definition: ParamDefs.h:83
MuonGMR4::RpcReadoutElement::getParameters
const parameterBook & getParameters() const
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/RpcReadoutElement.cxx:34
RpcFastDigiTool.h
MuonR4::RpcFastDigiTool::RpcFastDigiTool
RpcFastDigiTool(const std::string &type, const std::string &name, const IInterface *pIID)
Definition: RpcFastDigiTool.cxx:15
MuonR4::MuonDigitizationTool::addSDO
void addSDO(const TimedHit &hit, xAOD::MuonSimHitContainer *sdoContainer) const
Adds the timed simHit to the output SDO container.
Definition: MuonDigitizationTool.cxx:148
Amg::toString
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Definition: GeoPrimitivesToStringConverter.h:40
MuonGMR4::RpcReadoutElement::parameterBook::phiDesign
StripDesignPtr phiDesign
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/RpcReadoutElement.h:39
Identifier
Definition: DetectorDescription/Identifier/Identifier/Identifier.h:32
MuonR4::MuonDigitizationTool::getRandomEngine
CLHEP::HepRandomEngine * getRandomEngine(const EventContext &ctx) const
Definition: MuonDigitizationTool.cxx:135
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
MuonR4::RpcFastDigiTool::m_writeKey
SG::WriteHandleKey< RpcDigitContainer > m_writeKey
Definition: RpcFastDigiTool.h:70
Muon::DigitEffiData::getEfficiency
double getEfficiency(const Identifier &channelId, bool isInnerQ1=false) const
Returns the signal generation efficiency of the sTgc channel.
Definition: DigitEffiData.cxx:36
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
MuonR4::RpcFastDigiTool::digitize
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...
Definition: RpcFastDigiTool.cxx:31
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
compute_lumi.denom
denom
Definition: compute_lumi.py:76
MuonR4::RpcFastDigiTool::m_propagationVelocity
Gaudi::Property< double > m_propagationVelocity
Definition: RpcFastDigiTool.h:78
Muon::DigitEffiData
Definition: DigitEffiData.h:23
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
MuonR4::MuonDigitizationTool::writeDigitContainer
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.
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
MuonR4::MuonDigitizationTool::hitTime
static double hitTime(const TimedHit &hit)
Returns the global time of the hit which is the sum of eventTime & individual hit time.
Definition: MuonDigitizationTool.cxx:69
MuonR4
The CsvMuonSimHitDumper reads a Simulation Hit container for muons and dumps information to csv files...
Definition: MuonSpacePoint.h:11
MuonR4::MuonDigitizationTool::initialize
StatusCode initialize() override
Definition: MuonDigitizationTool.cxx:17
MuonR4::MuonDigitizationTool
Barebone implementation of the I/O infrastructure for all MuonDigitizationTools.
Definition: MuonDigitizationTool.h:30
MuonR4::MuonDigitizationTool::TimedHits
std::vector< TimedHitPtr< xAOD::MuonSimHit > > TimedHits
Definition: MuonDigitizationTool.h:60
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
MuonR4::RpcFastDigiTool::finalize
StatusCode finalize() override final
Definition: RpcFastDigiTool.cxx:25
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
MuonR4::MuonDigitizationTool::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: MuonDigitizationTool.h:122
MuonR4::MuonDigitizationTool::m_detMgr
const MuonGMR4::MuonDetectorManager * m_detMgr
Definition: MuonDigitizationTool.h:120
hitTime
float hitTime(const AFP_SIDSimHit &hit)
Definition: AFP_SIDSimHit.h:39
MuonR4::RpcFastDigiTool::digitizeHit
bool digitizeHit(const Identifier &gasGapId, const bool measuresPhi, const MuonGMR4::StripDesignPtr &designPtr, const double hitTime, const double locPos, const Muon::DigitEffiData *effiMap, RpcDigitCollection &outContainer, CLHEP::HepRandomEngine *rndEngine) const
Digitize the sim hit as Rpc strip 1D hit.
Definition: RpcFastDigiTool.cxx:71
MuonR4::MuonDigitizationTool::fetchCollection
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 ...
MuonR4::RpcFastDigiTool::timeOverThreshold
static double timeOverThreshold(CLHEP::HepRandomEngine *rndmEngine)
Roll the time over threshold for each signal digit.
Definition: RpcFastDigiTool.cxx:220