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