ATLAS Offline Software
Loading...
Searching...
No Matches
MuonPhaseII/MuonDigitization/sTgcDigitizationR4/src/sTgcDigitizationTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
8#include "CLHEP/Random/RandGaussZiggurat.h"
9#include "GaudiKernel/PhysicalConstants.h"
10
11namespace {
12 using ChVec_t = std::vector<std::uint16_t>;
14 static const SG::Decorator<ChVec_t> dec_stripCh{"SDO_etaChannels"};
15 static const SG::Decorator<ChVec_t> dec_wireCh{"SDO_phiChannels"};
16 static const SG::Decorator<ChVec_t> dec_padCh{"SDO_padChannels"};
17}
18
19namespace MuonR4 {
21 ATH_MSG_DEBUG("sTgcDigitizationTool::initialize()");
22 ATH_MSG_DEBUG ( "Configuration sTgcDigitizationTool" );
23 ATH_MSG_DEBUG ( "doSmearing "<< m_doSmearing);
24 ATH_MSG_DEBUG("OutputObjectName " << m_writeKey.key());
25 ATH_MSG_DEBUG ( "HV " << m_runVoltage);
26 ATH_MSG_DEBUG ( "threshold " << m_chargeThreshold);
27 ATH_MSG_DEBUG ( "useCondThresholds " << m_useCondThresholds);
28
30 ATH_CHECK(m_writeKey.initialize());
31 ATH_CHECK(m_effiDataKey.initialize(!m_effiDataKey.empty()));
33 ATH_CHECK(m_smearingTool.retrieve());
34 ATH_CHECK(m_calibrationTool.retrieve());
35
36 if (m_doSmearing) {
37 ATH_MSG_INFO("Running in smeared mode!");
38 }
39
45 ATH_MSG_WARNING("STGC run voltage must be within fit domain of 2.3 kV to 3.2 kV");
46 return StatusCode::FAILURE;
47 }
48 double meanGasGain = 2.15 * 1E-4 * std::exp(6.88*m_runVoltage);
50 m_digitizer = std::make_unique<sTgcDigitMaker>(m_detMgr, mode, meanGasGain, m_doPadSharing);
51 ATH_CHECK(m_digitizer->initialize());
52
53 return StatusCode::SUCCESS;
54 }
55
56 uint16_t sTgcDigitizationTool::bcTagging(const double digitTime) const {
57 uint16_t bctag = 0;
58 int bunchInteger = (digitTime > 0) ? static_cast<int>(std::abs(digitTime / 25.0))
59 : static_cast<int>(std::abs(digitTime / 25.0)) + 1;
60 bctag = (bctag | bunchInteger);
61 if (digitTime < 0) bctag = ~bctag;
62 return bctag;
63 }
64
65 double sTgcDigitizationTool::getChannelThreshold(const EventContext& ctx,
66 const Identifier& channelID,
67 const NswCalibDbThresholdData& thresholdData) const {
69 std::optional<float> elecThreshold = thresholdData.getThreshold(channelID);
70 if (!elecThreshold) {
71 THROW_EXCEPTION("Cannot retrieve VMM threshold from conditions database!");
72 }
73
74 if (!m_calibrationTool->pdoToCharge(ctx, true, *elecThreshold, channelID, threshold)) {
75 THROW_EXCEPTION("Cannot convert VMM charge threshold via conditions data!");
76 }
77
78 return threshold;
79 }
80
81 StatusCode sTgcDigitizationTool::digitize(const EventContext& ctx,
82 const TimedHits& hitsToDigit,
83 xAOD::MuonSimHitContainer* sdoContainer) const {
84 const sTgcIdHelper& idHelper{m_idHelperSvc->stgcIdHelper()};
85 CLHEP::HepRandomEngine* rndEngine = getRandomEngine(ctx);
86 const ActsTrk::GeometryContext &gctx{getGeoCtx(ctx)};
87
88 const Muon::DigitEffiData* efficiencyMap{nullptr};
89 ATH_CHECK(SG::get(efficiencyMap, m_effiDataKey, ctx));
90 const NswCalibDbThresholdData* thresholdData{nullptr};
91 ATH_CHECK(SG::get(thresholdData, m_condThrshldsKey, ctx));
92
93 DigiConditions digiCond{efficiencyMap, thresholdData, rndEngine};
94 DigiCache digitCache{};
95
96 double earliestEventTime = std::numeric_limits<double>::max();
97 xAOD::ChamberViewer viewer{hitsToDigit, m_idHelperSvc.get()};
98 const double angular_tolerance = 1e-3; // ~0.057 degrees
99
100 do {
101 if (viewer.size() == 0) {
102 ATH_MSG_VERBOSE("No hits to digitize — skipping sTGC digitization.");
103 continue;
104 }
105 std::array<sTgcSimDigitVec , 3> simDigitsByChType{};
106 for (const TimedHit& hit : viewer) {
107
108 if (m_digitizeMuonOnly && !MC::isMuon(hit)) {
109 ATH_MSG_VERBOSE("Hit is not from a muon - skipping ");
110 continue;
111 }
112 ATH_MSG_VERBOSE("Hit Particle ID : " << hit->pdgId() );
113 double eventTime = hit.eventTime();
114 earliestEventTime = std::min(earliestEventTime, eventTime);
115 if (hit->energyDeposit() < m_energyDepositThreshold){
116 ATH_MSG_VERBOSE("Hit with Energy Deposit of " << hit->energyDeposit()
117 << " less than " << m_energyDepositThreshold << ". Skip this hit." );
118 continue;
119 }
120
122 const Amg::Vector3D locHitPos = xAOD::toEigen(hit->localPosition());
123 const Amg::Vector3D locHitDir = xAOD::toEigen(hit->localDirection());
124
125 const double hitKineticEnergy = hit->kineticEnergy();
126 if (hitKineticEnergy < m_limitElectronKineticEnergy && MC::isElectron(hit)) {
127 ATH_MSG_DEBUG("Skip electron hit with kinetic energy " << hitKineticEnergy
128 << ", which is less than the lower limit of " << m_limitElectronKineticEnergy);
129 continue;
130 }
131
132 // No support for particles with direction perpendicular to the beam line, since such particles
133 // can deposit energy on a lot of strips and pads of the gas gap.
134 const double theta = std::acos(locHitDir.z()); // polar angle from Z axis
135 const double ninetyDegrees = std::numbers::pi / 2;
136 // Reject hits that are too close to 90 degrees (i.e., perpendicular to Z)
137 if (std::abs(theta - ninetyDegrees) < angular_tolerance) {
138 ATH_MSG_VERBOSE("Skipping hit nearly perpendicular to Z-axis (angle: " << theta << ")");
139 continue;
140 }
141 if (std::abs(locHitDir.z()) < 0.00001) {
142 ATH_MSG_VERBOSE("Skipping hit nearly perpendicular to Z-axis.");
143 continue;
144 }
145 if(eventTime != 0){
146 ATH_MSG_DEBUG("Updated hit global time to include off set of " << eventTime << " ns from OOT bunch.");
147 }
148 else {
149 ATH_MSG_DEBUG("This hit came from the in time bunch.");
150 }
151
152 const Identifier hitId = hit->identify();
155 if (m_doSmearing) {
156 bool acceptHit = true;
157 ATH_CHECK(m_smearingTool->isAccepted(hitId, acceptHit, rndEngine));
158 if ( !acceptHit ) {
159 ATH_MSG_DEBUG("Dropping the hit - smearing tool");
160 continue;
161 }
162 }
163 const MuonGMR4::sTgcReadoutElement* readoutElement = m_detMgr->getsTgcReadoutElement(hitId);
164 const Amg::Vector3D globalHitPos = readoutElement->localToGlobalTransform(gctx, hitId) * locHitPos;
165 double globalHitTime = hit->globalTime() + eventTime;
166 double tofCorrection = globalHitPos.mag() / Gaudi::Units::c_light;
167 double bunchTime = globalHitTime - tofCorrection;
168
169 const HepMcParticleLink particleLink = hit->genParticleLink();
170 // Print some information about the sTGC hit
171 ATH_MSG_VERBOSE("hitID " << m_idHelperSvc->toString(hitId) << " Hit bunch time " << bunchTime << " tof/G4 hit time " << globalHitTime
172 << " globalHitPosition " << Amg::toString(globalHitPos) << " hit: r " << globalHitPos.perp() << " z " << globalHitPos.z()
173 << " mclink " << particleLink << "Kinetic energy " << hitKineticEnergy);
174 ATH_MSG_VERBOSE("Total hits passed to digitize: " << hitsToDigit.size());
175 sTgcDigitVec digitizedHits = m_digitizer->executeDigi(digiCond, hit);
176 if(digitizedHits.empty()) {
177 continue;
178 }
179 ATH_MSG_VERBOSE("Hit produced " << digitizedHits.size() << " digits." );
180
181 for (std::unique_ptr<sTgcDigit>& digit : digitizedHits) {
182 /*
183 NOTE:
184 -----
185 Since not every hit might end up resulting in a
186 digit, this construction might take place after the hit loop
187 in a loop of its own!
188 */
189 // make new sTgcDigit
190 const Identifier digitId = digit->identify();
191 double digitTime = digit->time();
192 int digitChType = idHelper.channelType(digitId);
193
194 if(digitChType == ReadoutChannelType::Strip) {
195 digitTime += CLHEP::RandGaussZiggurat::shoot(rndEngine, 0, m_timeJitterElectronicsStrip);
196 }
197 else {
198 digitTime += CLHEP::RandGaussZiggurat::shoot(rndEngine, 0, m_timeJitterElectronicsPad);
199 }
200
201 uint16_t digitBCTag = bcTagging(digitTime + bunchTime);
202 digitTime += m_doToFCorrection ? bunchTime : globalHitTime;
203
204 double digitCharge = digit->charge();
205 // Create a new digit with updated time and BCTag
206 int eventId = hit.eventId();
207 bool isDead{false}, isPileup{eventId != 0};
208 ATH_MSG_VERBOSE("Hit is from the main signal subevent if eventId is zero, eventId = "
209 << eventId << " newDigit time: " << digitTime);
210 auto newDigitPtr = std::make_unique<sTgcDigit>(digitId, digitBCTag, digitTime, digitCharge, isDead, isPileup);
211 if (digitChType == ReadoutChannelType::Strip) {
212 ATH_MSG_VERBOSE("Finalizing Digit "<<m_idHelperSvc->toString(digitId)
213 <<" BC tag = " << newDigitPtr->bcTag()
214 <<" digitTime = " << newDigitPtr->time()
215 <<" charge = " << newDigitPtr->charge());
216 }
217 simDigitsByChType[digitChType].emplace_back(hit, std::move(newDigitPtr));
218 }
219 }
220 SdoIdMap_t sdoIdMap{};
221 sTgcDigitCollection* outColl = fetchCollection(viewer.at(0)->identify(), digitCache);
222
223 ATH_CHECK(processDigitsWithVMM(ctx, digiCond, std::move(simDigitsByChType[ReadoutChannelType::Strip]),
224 m_deadtimeStrip, m_doNeighborOn, *outColl, sdoIdMap));
225 ATH_CHECK(processDigitsWithVMM(ctx, digiCond, std::move(simDigitsByChType[ReadoutChannelType::Pad]),
226 m_deadtimePad, false, *outColl, sdoIdMap));
227 ATH_CHECK(processDigitsWithVMM(ctx, digiCond, std::move(simDigitsByChType[ReadoutChannelType::Wire]),
228 m_deadtimeWire, false, *outColl, sdoIdMap));
229 for (auto& [simHit, assocIds]: sdoIdMap) {
231 xAOD::MuonSimHit* sdoHit = addSDO(simHit, sdoContainer);
232 if (!sdoHit) {
233 continue;
234 }
235 std::ranges::sort(assocIds, [&](const Identifier& a, const Identifier& b){
236 const int typeA = idHelper.channelType(a);
237 const int typeB = idHelper.channelType(b);
238 if (typeA != typeB) {
240 return true;
241 } else if (typeB == sTgcIdHelper::sTgcChannelTypes::Strip) {
242 return false;
243 }
244 return typeA > typeB;
245 }
246 return idHelper.channel(a) < idHelper.channel(b);
247 });
248 const double globalHitTime = sdoHit->globalTime() + simHit.eventTime();
249 sdoHit->setGlobalTime(globalHitTime);
250
251 sdoHit->setIdentifier(assocIds.front());
252 assocIds.erase(assocIds.begin());
253
254 ChVec_t& stripCh{dec_stripCh(*sdoHit)}, wireCh{dec_wireCh(*sdoHit)}, padCh{dec_padCh(*sdoHit)};
255
256 std::ranges::for_each(assocIds,[&](const Identifier& secId){
257 const int ch = idHelper.channel(secId);
258 switch(idHelper.channelType(secId)){
260 case Strip: {
261 stripCh.push_back(ch);
262 break;
263 }case Wire: {
264 wireCh.push_back(ch);
265 break;
266 }case Pad: {
267 padCh.push_back(ch);
268 break;
269 }
270 }
271 });
272
273
274 }
275 } while (viewer.next());
277 ATH_CHECK(writeDigitContainer(ctx, m_writeKey, std::move(digitCache), idHelper.module_hash_max()));
278
279 return StatusCode::SUCCESS;
280 }
281
282 StatusCode sTgcDigitizationTool::processDigitsWithVMM(const EventContext& ctx,
283 const DigiConditions& digiCond,
284 sTgcSimDigitVec&& digitsInChamber,
285 const double vmmDeadTime,
286 const bool isNeighbourOn,
287 sTgcDigitCollection& outColl,
288 SdoIdMap_t& sdoIdMap) const {
289
290 if (digitsInChamber.empty()) {
291 ATH_MSG_DEBUG("Empty hits from VMM Simulation" );
292 return StatusCode::SUCCESS;
293 }
294 const sTgcIdHelper& idHelper{m_idHelperSvc->stgcIdHelper()};
295
297 sTgcSimDigitVec mergedDigits = mergeDigitsVMM(ctx, digiCond, vmmDeadTime,
298 isNeighbourOn, std::move(digitsInChamber));
300 if (mergedDigits.empty()) {
301 return StatusCode::SUCCESS;
302 }
303
304 for (sTgcSimDigitHit& merged : mergedDigits) {
305
307 bool acceptDigit{true};
308 float chargeAfterSmearing = merged.getDigit().charge();
309 if (m_doSmearing) {
310 ATH_CHECK(m_smearingTool->smearCharge(merged.identify(), chargeAfterSmearing, acceptDigit,
311 digiCond.rndEngine));
312 }
313 if (!acceptDigit) {
314 continue;
315 }
318 if (idHelper.channelType(merged.identify()) == ReadoutChannelType::Strip &&
319 chargeAfterSmearing < 0.001) {
320 continue;
321 }
322 auto finalDigit = merged.releaseDigit();
323 if (m_doSmearing) {
324 finalDigit->set_charge(chargeAfterSmearing);
325 }
326 ATH_MSG_VERBOSE("Final Digit "<<m_idHelperSvc->toString(finalDigit->identify())<<
327 " BC tag = " << finalDigit->bcTag()<<
328 " digitTime = " << finalDigit->time() <<
329 " charge = " << finalDigit->charge());
330
332 sdoIdMap[merged.getSimHit()].push_back(finalDigit->identify());
334 outColl.push_back(std::move(finalDigit));
335 }
336 return StatusCode::SUCCESS;
337 }
338
341 const DigiConditions& digiCond,
342 const double vmmDeadTime,
343 const bool isNeighbourOn,
344 sTgcSimDigitVec&& unmergedDigits) const {
345
346 const sTgcIdHelper& idHelper{m_idHelperSvc->stgcIdHelper()};
348 std::ranges::stable_sort(unmergedDigits,
349 [&idHelper](const sTgcSimDigitHit& a, const sTgcSimDigitHit& b) {
350 const int layA = idHelper.gasGap(a.identify());
351 const int layB = idHelper.gasGap(b.identify());
352 if (layA != layB) {
353 return layA < layB;
354 }
355 const int chA = idHelper.channel(a.identify());
356 const int chB = idHelper.channel(b.identify());
357 if (chA != chB) {
358 return chA < chB;
359 }
360 return a.time() < b.time();
361 }
362 );
363 sTgcSimDigitVec savedDigits{}, premerged{};
364
365 premerged.reserve(unmergedDigits.size());
366 savedDigits.reserve(premerged.capacity());
367
368 auto passNeigbourLogic = [&](const sTgcSimDigitHit& candidate) {
369 if (!isNeighbourOn || savedDigits.empty()) {
370 return false;
371 }
372 if (savedDigits.back().identify() == candidate.identify() &&
373 std::abs(savedDigits.back().time() - candidate.time()) < vmmDeadTime) {
374 ATH_MSG_VERBOSE("Digits are too close in time ");
375 return false;
376 }
377 const Identifier digitId = candidate.identify();
378 const int channel = idHelper.channel(digitId);
379 const MuonGMR4::sTgcReadoutElement* reEle = m_detMgr->getsTgcReadoutElement(digitId);
380 const IdentifierHash hitHash = reEle->measurementHash(digitId);
381 const int maxChannel = reEle->numChannels(hitHash);
382 for (int neighbour : {std::max(1, channel -1), std::min(maxChannel, channel+1)}) {
384 if (neighbour == channel) {
385 continue;
386 }
387 const Identifier neighbourId = idHelper.channelID(digitId,
388 reEle->multilayer(),
389 idHelper.gasGap(digitId),
390 idHelper.channelType(digitId), neighbour);
391 const double threshold = m_useCondThresholds ? getChannelThreshold(ctx, neighbourId, *digiCond.thresholdData)
392 : m_chargeThreshold.value();
393 if (std::ranges::any_of(savedDigits, [&](const sTgcSimDigitHit& known){
394 return known.identify() == neighbourId &&
395 known.getDigit().charge() > threshold &&
396 std::abs(known.time() - candidate.time()) < m_hitTimeMergeThreshold;
397 })) {
398 return true;
399 }
400 }
401 return false;
402 };
403 // Sort digits on every channel by earliest to latest time
404 // Also do hit merging to help with neighborOn logic
406 for (sTgcSimDigitVec::iterator merge_me = unmergedDigits.begin(); merge_me!= unmergedDigits.end(); ++merge_me) {
408 threshold = getChannelThreshold(ctx, (*merge_me).identify(), *digiCond.thresholdData);
409 }
412 sTgcDigit& digit1{(*merge_me).getDigit()};
413 double totalCharge = digit1.charge();
414 double weightedTime = digit1.time();
415
416 sTgcSimDigitVec::iterator merge_with = merge_me + 1;
417 for ( ; merge_with!= unmergedDigits.end(); ++merge_with) {
419 if ((*merge_with).identify() != (*merge_me).identify()) {
420 break;
421 }
422 const sTgcDigit& mergeDigit{(*merge_with).getDigit()};
423 // If future digits are within window, digit1 absorbs its charge
424 if (mergeDigit.time() - digit1.time() > m_hitTimeMergeThreshold) break;
425 // If digit1 is not above threshold prior to merging, the new time is
426 // a weighted average. Do it for every merging pair.
427 if (totalCharge < threshold) {
428 weightedTime = (weightedTime * totalCharge + mergeDigit.time() * mergeDigit.charge())
429 / (totalCharge + mergeDigit.charge());
430 }
431 totalCharge += mergeDigit.charge();
432 }
433 digit1.set_charge(totalCharge);
434 digit1.set_time(weightedTime);
435 sTgcSimDigitHit& mergedHit{*merge_me};
436 if (!savedDigits.empty() &&
437 savedDigits.back().identify() == digit1.identify() &&
438 std::abs(savedDigits.back().time() - digit1.time()) <= vmmDeadTime) continue;
439 if (digit1.charge() > threshold || passNeigbourLogic(mergedHit)){
440 savedDigits.emplace_back(std::move(mergedHit));
441 } else if (isNeighbourOn) {
442 premerged.emplace_back(std::move(mergedHit));
443 }
444 } // end of time-ordering and hit merging loop
445 std::copy_if(std::make_move_iterator(premerged.begin()),
446 std::make_move_iterator(premerged.end()),
447 std::back_inserter(savedDigits), passNeigbourLogic);
448 return savedDigits;
449 }
450}
Scalar theta() const
theta method
#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.
static Double_t a
value_type push_back(value_type pElem)
Add an element to the end of the collection.
This is a "hash" representation of an Identifier.
Identifier identify() const
Definition MuonDigit.h:30
const Amg::Transform3D & localToGlobalTransform(const ActsTrk::GeometryContext &ctx) const
Returns the transformation from the local coordinate system of the readout element into the global AT...
unsigned numChannels(const IdentifierHash &measHash) const
Returns the number of strips / wires / pads in a given gasGap.
IdentifierHash measurementHash(const Identifier &measId) const override final
Constructs the identifier hash from the full measurement Identifier.
int multilayer() const
Returns the multilayer of the sTgcReadoutElement.
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
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.
const ActsTrk::GeometryContext & getGeoCtx(const EventContext &ctx) const
Returns the reference to the ActsTrk::GeometryContext needed to fetch global positions from the Reado...
StatusCode processDigitsWithVMM(const EventContext &ctx, const DigiConditions &digiCond, sTgcSimDigitVec &&digitsInChamber, const double vmmDeadTime, const bool isNeighbourOn, sTgcDigitCollection &outColl, SdoIdMap_t &sdoIdMap) const
sTgcSimDigitVec mergeDigitsVMM(const EventContext &ctx, const DigiConditions &digiCond, const double vmmDeadTime, const bool isNeighbourOn, sTgcSimDigitVec &&unmergedDigits) const
double getChannelThreshold(const EventContext &ctx, const Identifier &channelID, const NswCalibDbThresholdData &thresholdData) const
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::map< const TimedHit, std::vector< Identifier >, SimHitSorter > SdoIdMap_t
Conditions data to model a channel dependent energy deposit threshold such that the electronics retur...
std::optional< float > getThreshold(const Identifier &channelId) const
Definition Pad.h:10
Helper class to provide type-safe access to aux data.
Definition Decorator.h:59
void set_time(float newTime)
Definition sTgcDigit.cxx:76
float time() const
Definition sTgcDigit.cxx:61
float charge() const
Definition sTgcDigit.cxx:46
void set_charge(float newCharge)
Definition sTgcDigit.cxx:71
int channelType(const Identifier &id) const
int channel(const Identifier &id) const override
int gasGap(const Identifier &id) const override
get the hashes
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int channelType, int channel) const
bool next() noexcept
Loads the hits from the next chamber.
std::size_t size() const noexcept
Returns how many hits are in the current chamber.
void setGlobalTime(const float time)
Sets the time of the traversing particle.
void setIdentifier(const Identifier &id)
Sets the global ATLAS identifier.
float globalTime() const
Returns the time ellapsed since the collision of the traversing particle.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Matrix< double, 3, 1 > Vector3D
bool isElectron(const T &p)
bool isMuon(const T &p)
This header ties the generic definitions in this package.
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
MuonSimHit_v1 MuonSimHit
Defined the version of the MuonSimHit.
Definition MuonSimHit.h:12
MuonSimHitContainer_v1 MuonSimHitContainer
Define the version of the pixel cluster container.
#define THROW_EXCEPTION(MESSAGE)
Definition throwExcept.h:10