ATLAS Offline Software
Loading...
Searching...
No Matches
MuonPatternCalibration.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include <iostream>
8#include <set>
9#include <sstream>
10
20namespace Muon {
21
22MuonPatternCalibration::MuonPatternCalibration(const std::string& t, const std::string& n, const IInterface* p)
23 : base_class(t, n, p) {}
24
25StatusCode
27{
28 ATH_MSG_VERBOSE("MuonPatternCalibration::Initializing");
29 ATH_CHECK(m_mdtCreator.retrieve());
30 ATH_CHECK(m_printer.retrieve());
31 ATH_CHECK(m_idHelperSvc.retrieve());
32 ATH_CHECK(m_keyRpc.initialize(!m_keyRpc.empty()));
33 ATH_CHECK(m_keyTgc.initialize(!m_keyTgc.empty()));
34 ATH_CHECK(m_clusterCreator.retrieve(EnableTool{!m_keyRpc.empty() || !m_keyTgc.empty()}));
35 return StatusCode::SUCCESS;
36}
37
38
39
40StatusCode MuonPatternCalibration::calibrate(const EventContext& ctx, const MuonPatternCombination& pattern, ROTsPerRegion& hitsPerRegion) const {
42 bool hasPhiMeasurements = checkForPhiMeasurements(pattern);
43 ATH_CHECK(createRegionMap(ctx, pattern, regionMap, hasPhiMeasurements));
44 // calibrate hits
45 calibrateRegionMap(regionMap, hitsPerRegion);
46 return StatusCode::SUCCESS;
47}
48
49
51
52 // simple division of MuonSpectrometer in regions using barrel/endcap seperation plus
53 // inner/middle/outer seperation
54 using namespace MuonStationIndex;
55 return toInt(m_idHelperSvc->stationIndex(id)) * (m_idHelperSvc->stationEta(id) > 0 ? 1 : -1);
56}
57
58
59bool
61
62 for (const MuonPatternChamberIntersect& intersect : pat.chamberData()) {
63 for (const Trk::PrepRawData* prd : intersect.prepRawDataVec()){
64 const Identifier id = prd->identify();
66 if (!m_idHelperSvc->issTgc(id) &&
67 m_idHelperSvc->measuresPhi(id)) return true;
68 }
69 }
70 return false;
71}
72
73StatusCode
75 RegionMap& regionMap, bool hasPhiMeasurements ) const
76{
77 if (hasPhiMeasurements)
78 ATH_MSG_DEBUG("pattern has phi measurements using extrapolation to determine second coordinate");
79 else
80 ATH_MSG_DEBUG("No phi measurements using center tubes");
81
82
83 const TgcPrepDataContainer* tgcPrdCont{nullptr};
84 const RpcPrepDataContainer* rpcPrdCont{nullptr};
85 ATH_CHECK(loadFromStoreGate(ctx, m_keyRpc, rpcPrdCont));
86 ATH_CHECK(loadFromStoreGate(ctx, m_keyTgc, tgcPrdCont));
87
88 for (const MuonPatternChamberIntersect& isect : pat.chamberData()) {
89
90 if (isect.prepRawDataVec().empty()) continue;
91
92 const Amg::Vector3D& patpose = isect.intersectPosition();
93 const Amg::Vector3D patdire = isect.intersectDirection().unit();
94
100 std::map<int, EtaPhiHits> etaPhiHitsPerChamber;
101 std::set<Identifier> clusterIds;
102
103
104 const Trk::PrepRawData* prd = isect.prepRawDataVec().front();
105 const Identifier id = prd->identify();
106
107 // apply cut on the opening angle between pattern and chamber phi
108 // do some magic to avoid problems at phi = 0 and 2*pi
109 double phiStart = patdire.phi();
110 double chPhi = prd->detectorElement()->center().phi();
111 constexpr double phiRange = 0.75 * M_PI;
112 constexpr double phiRange2 = 0.25 * M_PI;
113 double phiOffset = 0.;
114 if (phiStart > phiRange || phiStart < -phiRange)
115 phiOffset = 2 * M_PI;
116 else if (phiStart > -phiRange2 && phiStart < phiRange2)
117 phiOffset = M_PI;
118
119 if (phiOffset > 1.5 * M_PI) {
120 if (phiStart < 0) phiStart += phiOffset;
121 if (chPhi < 0) chPhi += phiOffset;
122 } else if (phiOffset > 0.) {
123 phiStart += phiOffset;
124 chPhi += phiOffset;
125 }
126 double dphi = std::abs(phiStart - chPhi);
127
128 if (dphi > m_phiAngleCut) {
129 ATH_MSG_DEBUG("Large angular phi difference between pattern and chamber, phi pattern "
130 << patdire.phi() << " phi chamber " << prd->detectorElement()->center().phi());
131 continue;
132 }
133
134 // map to find duplicate hits in the chamber
135 std::map<Identifier, const MdtPrepData*> idMdtMap{};
136
137 for (const Trk::PrepRawData* isect_prd : isect.prepRawDataVec()) {
138
139 if (isect_prd->type(Trk::PrepRawDataType::MdtPrepData)) {
140 const MdtPrepData* mdt = dynamic_cast<const MdtPrepData*>(isect_prd);
142 const MdtPrepData*& previousMdt = idMdtMap[mdt->identify()];
143 if (!previousMdt || previousMdt->tdc() > mdt->tdc())
144 previousMdt = mdt;
145 else
146 continue;
147 }
148 insertMdt(*mdt, regionMap, patpose, patdire, hasPhiMeasurements);
149 continue;
150 }
151 else if (isect_prd->type(Trk::PrepRawDataType::MMPrepData) || isect_prd->type(Trk::PrepRawDataType::sTgcPrepData)){
152 continue;
153 }
154 const MuonCluster* clus = dynamic_cast<const MuonCluster*>(isect_prd);
155 if (!clus) continue;
156 const Identifier id = clus->identify();
157 if (!clusterIds.insert(id).second) continue;
158
160 bool measuresPhi = m_idHelperSvc->measuresPhi(id);
161 int colHash = clus->collectionHash();
162 EtaPhiHits& hitsPerChamber = etaPhiHitsPerChamber[colHash];
163 if (measuresPhi)
164 ++hitsPerChamber.nphi;
165 else
166 ++hitsPerChamber.neta;
167 }
168 insertCluster(*clus, regionMap, patpose, patdire, hasPhiMeasurements);
169 }
170 for (const auto& [coll_hash, hits] : etaPhiHitsPerChamber) {
171 if ((hits.neta > 0 && hits.nphi == 0) || (hits.nphi > 0 && hits.neta == 0)) {
172 if (m_idHelperSvc->isRpc(id) && rpcPrdCont) {
173
174 const RpcPrepDataCollection* prd_coll = rpcPrdCont->indexFindPtr(coll_hash);
175 if (!prd_coll) {
176 ATH_MSG_VERBOSE("RpcPrepDataCollection not found in container!!"<< m_keyRpc);
177 continue;
178 }
179 for (const RpcPrepData* rpc_prd : *prd_coll) {
180 if (!clusterIds.insert(rpc_prd->identify()).second) continue;
181 insertCluster(*rpc_prd, regionMap, patpose, patdire, hasPhiMeasurements);
182 }
183 } else if (m_idHelperSvc->isTgc(id) && tgcPrdCont) {
184 const TgcPrepDataCollection* prd_coll = tgcPrdCont->indexFindPtr(coll_hash);
185 if (!prd_coll) {
186 ATH_MSG_DEBUG("TgcPrepDataCollection not found in container!! "<< m_keyTgc);
187 continue;
188 }
189
190 for (const TgcPrepData* tgc_prd : *prd_coll) {
191 if (!clusterIds.insert(tgc_prd->identify()).second) continue;
192 insertCluster(*tgc_prd, regionMap, patpose, patdire, hasPhiMeasurements);
193 }
194 }
195 }
196 }
197 }
198 return StatusCode::SUCCESS;
199}
200
201void
203 const Amg::Vector3D& patdire, bool hasPhiMeasurements) const
204{
205
206 const Identifier id = clus.identify();
207 // check whether we are measuring phi or eta
208 const bool measuresPhi = m_idHelperSvc->measuresPhi(id);
209
210 Amg::Vector3D globalpos = clus.globalPosition();
211 Amg::Vector3D intersect{Amg::Vector3D::Zero()};
212
213 if (hasPhiMeasurements) {
214 // if there is a phi measurement in the pattern use the global direction to calculate the intersect with
215 // measurement plane and use the intersect to calculate the position along the strip
216
217 // calculate intersect pattern measurement plane
218 const Trk::Surface& surf = clus.detectorElement()->surface(id);
219 Amg::Vector3D planepostion = surf.center();
220 Amg::Vector3D planenormal = surf.normal();
221 double denom = patdire.dot(planenormal);
222 double u = (planenormal.dot(planepostion - patpose)) / (denom);
223 Amg::Vector3D piOnPlane = (patpose + u * patdire);
224
225 // transform to local plane coordiantes
226 const Amg::Transform3D gToLocal = clus.detectorElement()->surface().transform().inverse();
227 Amg::Vector3D ilpos = gToLocal * piOnPlane;
228 Amg::Vector3D glpos = gToLocal * globalpos;
229
230 // strip length
231 double striplen(0.);
232
233 // projective strips
234 bool hasPointingPhiStrips = false;
235
236 // detector specific stuff
237 const RpcPrepData* rpc = dynamic_cast<const RpcPrepData*>(&clus);
238 if (rpc) {
239 striplen = rpc->detectorElement()->StripLength(measuresPhi);
240 } else {
241 const TgcPrepData* tgc = dynamic_cast<const TgcPrepData*>(&clus);
242 if (!tgc) return;
243
244 int gasGap = m_idHelperSvc->tgcIdHelper().gasGap(id);
245 if (measuresPhi) {
246 hasPointingPhiStrips = true;
247 striplen = tgc->detectorElement()->stripLength();
248 } else {
249 int wire = m_idHelperSvc->tgcIdHelper().channel(id);
250 striplen = tgc->detectorElement()->gangCentralWidth(gasGap, wire);
251 }
252 }
253
254 // set the position along the strip
255 if (!measuresPhi) {
256 glpos[0] = ilpos.x();
257 } else {
258 if (hasPointingPhiStrips) {
259 // do some special for tgcs
260 glpos[1] = ilpos.y();
261 } else {
262 glpos[1] = ilpos.y();
263 }
264 }
265
266 // transform back to global coordinates
267 intersect = gToLocal.inverse() * glpos;
268 Amg::Vector3D dif = globalpos - intersect;
269 if ((intersect - piOnPlane).mag() > m_dropDistance || dif.mag() > 0.5 * striplen + m_dropDistance) {
270
271 ATH_MSG_VERBOSE(">>>> extrapolated position far outside volume, dropping hit "
272 << m_idHelperSvc->toString(id) << ". dist along strip " << dif.mag() << " 1/2 strip len "
273 << 0.5 * striplen << " dist measurement plane " << (intersect - piOnPlane).mag());
274 return;
275 }
276 if (dif.mag() > 0.5 * striplen) {
277 Amg::Vector3D newpos = globalpos - dif * (0.5 * striplen / dif.mag());
278
279 ATH_MSG_VERBOSE(">>>> extrapolated position outside volume, shifting position "
280 << m_idHelperSvc->toString(id) << ". position along strip " << dif.mag() << " 1/2 tube len "
281 << 0.5 * striplen << " dist To strip " << (intersect - piOnPlane).mag()
282 << ". dist to newpos " << (newpos - globalpos).mag() << " pos " << newpos);
283
284 intersect = newpos;
285 }
286 } else {
287 // no phi measurements, use strip center
288 intersect = globalpos;
289 }
290
291 // enter hit in map
292 int regionId = getRegionId(id);
293
294 Region& region = regionMap[regionId];
295 if (!region.init) {
296 region.regionDir = patdire;
297 region.regionPos = patpose;
298 region.init = true;
299 }
300 region.triggerPrds.emplace_back(intersect, &clus);
301}
302
303
304void
306 const Amg::Vector3D& patdire, bool hasPhiMeasurements) const
307{
308
309 Amg::Vector3D intersect{Amg::Vector3D::Zero()};
310 const Identifier& id = mdt.identify();
311
312 const MuonGM::MdtReadoutElement* detEl = mdt.detectorElement();
313 const Amg::Vector3D& tubePos = mdt.globalPosition();
314
315 if (hasPhiMeasurements) {
316 // if there is a phi measurement in the pattern use the global direction to calculate the intersect with the
317 // tube use the intersect to calculate the second coordinate
318
319 const Amg::Transform3D amdbToGlobal = detEl->AmdbLRSToGlobalTransform();
320
321
322 // calculate intersect pattern measurement plane
323 const Amg::Vector3D& planepostion = tubePos;
324
325 // always project on plane with normal in radial direction
326 Amg::Vector3D planenormal = m_idHelperSvc->mdtIdHelper().isBarrel(id)
327 ? amdbToGlobal.linear() * Amg::Vector3D(0., 0., 1.)
328 : amdbToGlobal.linear() * Amg::Vector3D(0., 1., 0.);
329
330 double denom = patdire.dot(planenormal);
331 double u = (planenormal.dot(planepostion - patpose)) / (denom);
332 Amg::Vector3D piOnPlane = (patpose + u * patdire);
333
334 Amg::Vector3D lpiOnPlane = amdbToGlobal.inverse() * piOnPlane;
335 Amg::Vector3D ltubePos = amdbToGlobal.inverse() * tubePos;
336
337 intersect = amdbToGlobal * Amg::Vector3D(lpiOnPlane.x(), ltubePos.y(), ltubePos.z());
338
339 Amg::Vector3D dif = tubePos - intersect;
340 double tubelen = detEl->getActiveTubeLength(m_idHelperSvc->mdtIdHelper().tubeLayer(id),
341 m_idHelperSvc->mdtIdHelper().tube(id));
342
343 if (dif.mag() > 0.5 * tubelen) {
344 Amg::Vector3D newpos = tubePos - dif * (0.5 * tubelen / dif.mag());
345
346 ATH_MSG_VERBOSE(">>>> extrapolated position outside volume, shifting position "
347 << m_idHelperSvc->toString(id) << ". position along strip " << dif.mag() << " 1/2 tube len "
348 << 0.5 * tubelen << " dist To Wire " << (piOnPlane - intersect).mag() << ". dist to newpos "
349 << (newpos - tubePos).mag() << " pos " << newpos);
350
351 intersect = newpos;
352 }
353 } else {
354 // not phi measurement, use tube center
355 intersect = tubePos;
356 }
357
358 // enter hit in map
359 Identifier elId = m_idHelperSvc->mdtIdHelper().elementID(id);
360
362 ChIndex chIndex = m_idHelperSvc->chamberIndex(elId);
363 int chFlag = elId.get_identifier32().get_compact();
364 if (m_doMultiAnalysis) {
365 if (isSmall(chIndex)) {
366 ATH_MSG_VERBOSE(" Small chamber " << m_idHelperSvc->toString(elId));
367 chFlag = 0;
368 if (chIndex == ChIndex::BIS && std::abs(m_idHelperSvc->stationEta(elId)) == 8) {
369 ATH_MSG_VERBOSE(" BIS8 chamber " << m_idHelperSvc->toString(elId));
370 chFlag = 3;
371 }
372 } else {
373 ATH_MSG_VERBOSE(" Large chamber " << m_idHelperSvc->toString(elId));
374 chFlag = 1;
375 if (chIndex == ChIndex::BIL && m_idHelperSvc->stationNameString(id)[2] == 'R') {
376 ATH_MSG_VERBOSE(" BIR chamber " << m_idHelperSvc->toString(elId));
377 chFlag = 2;
378 } else if (chIndex == ChIndex::BOL && std::abs(m_idHelperSvc->stationEta(id)) == 7) {
379 ATH_MSG_VERBOSE(" BOE chamber " << m_idHelperSvc->toString(elId));
380 chFlag = 4;
381 }
382 }
383 int phi = m_idHelperSvc->stationPhi(id);
384
385 chFlag += 10 * phi;
386 }
387 // use center tube for region assignment
388 int regionId = getRegionId(id);
389
390 Region& region = regionMap[regionId];
391 if (!region.init) {
392 region.regionPos = patpose;
393 region.regionDir = patdire;
394 region.init = true;
395 }
396 region.mdtPrdsPerChamber[chFlag].emplace_back(intersect, &mdt);
397}
398
399void
401{
402
403 ATH_MSG_INFO("Summarizing input");
404
405 for (const auto& [detRegionId, chamberData] : regionMap) {
406 ATH_MSG_INFO("new region " << detRegionId << " trigger " << chamberData.triggerPrds.size() << " mdt ch "
407 << chamberData.mdtPrdsPerChamber.size());
408 if (!chamberData.triggerPrds.empty()) ATH_MSG_INFO("trigger hits " << chamberData.triggerPrds.size());
409
410 for (const auto& [globalPos, prd] : chamberData.triggerPrds) {
411 ATH_MSG_INFO(" " << m_printer->print(*prd)<<" "<<globalPos);
412 }
413 for (const auto& [statId, MdtChamHits]: chamberData.mdtPrdsPerChamber) {
414 ATH_MSG_INFO("new MDT chamber with " << MdtChamHits.size() << " hits");
415 for (const auto& [globalPos, prd] : MdtChamHits) {
416 ATH_MSG_INFO(" " << m_printer->print(*prd)<<" "<<globalPos);
417 }
418 }
419 }
420}
421
422void
424 IMuonPatternCalibration::ROTsPerRegion& hitsPerRegion) const {
425
426
427 for (const auto& [regionId, regMeasColl] : regionMap) {
428
429 ROTRegion rotRegion{};
430 rotRegion.regionId = regionId;
431 rotRegion.regionPos = regMeasColl.regionPos;
432 rotRegion.regionDir = regMeasColl.regionDir;
433 for (const auto& [globalPos, prd] : regMeasColl.triggerPrds) {
434 std::unique_ptr<const MuonClusterOnTrack> cluster{m_clusterCreator->createRIO_OnTrack(*prd, globalPos)};
435 if (!cluster) continue;
436 rotRegion.push_back(std::move(cluster));
437 }
438 for (const auto& [regionId, MdtsWithIsect] :regMeasColl.mdtPrdsPerChamber) {
439 ATH_MSG_VERBOSE("Run over region id "<<regionId);
440 MdtVec mdtROTs{};
441 for (const auto& [globalPos, prd] : MdtsWithIsect) {
442 ATH_MSG_VERBOSE("Calibrate prd"<<m_idHelperSvc->toString(prd->identify())
443 <<",tdc: "<<prd->tdc()<<",adc: "<<prd->adc()<<" at "<<Amg::toString(globalPos));
444 const MdtDriftCircleOnTrack* mdt = m_mdtCreator->createRIO_OnTrack(*prd, globalPos, &globalPos);
445 if (!mdt) {
446 ATH_MSG_VERBOSE("Failed to calibrate " << m_idHelperSvc->toString(prd->identify()));
447 continue;
448 }
449 mdtROTs.push_back(mdt);
450 }
451 if (!mdtROTs.empty()) rotRegion.push_back(std::move(mdtROTs));
452 }
453 hitsPerRegion.push_back(std::move(rotRegion));
454 }
455}
456
457template <class ContType> StatusCode MuonPatternCalibration::loadFromStoreGate(const EventContext& ctx,
459 const ContType* & cont_ptr) const {
460 if (key.empty()){
461 ATH_MSG_VERBOSE("Empty key given for "<<typeid(ContType).name()<<".");
462 cont_ptr = nullptr;
463 return StatusCode::SUCCESS;
464 }
465 SG::ReadHandle<ContType> readHandle{key, ctx};
466 if (!readHandle.isValid()) {
467 ATH_MSG_FATAL("Failed to retrieve "<<key.fullKey()<<" from store gate");
468 return StatusCode::FAILURE;
469 }
470 cont_ptr = readHandle.cptr();
471 return StatusCode::SUCCESS;
472}
473
474} // namespace Muon
#define M_PI
Scalar phi() const
phi method
Scalar mag() const
mag method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
virtual const T * indexFindPtr(IdentifierHash hashId) const override final
return pointer on the found entry or null if out of range using hashed index - fast version,...
value_type get_compact() const
Get the compact id.
Identifier32 get_identifier32() const
Get the 32-bit version Identifier, will be invalid if >32 bits needed.
double getActiveTubeLength(const int tubeLayer, const int tube) const
double StripLength(bool measphi) const
returns the strip length for the phi or eta plane
double stripLength() const
Returns the length of each strip which is equal to the height of the chamber.
double gangCentralWidth(int gasGap, int gang) const
Returns the length of the central wire in the gang.
std::vector< ROTRegion > ROTsPerRegion
This class represents the corrected MDT measurements, where the corrections include the effects of wi...
Class to represent measurements from the Monitored Drift Tubes.
Definition MdtPrepData.h:33
virtual const MuonGM::MdtReadoutElement * detectorElement() const override
Returns the detector element corresponding to this PRD.
virtual const Amg::Vector3D & globalPosition() const
Returns the global position of the CENTER of the drift tube (i.e.
int tdc() const
Returns the TDC (typically range is 0 to 2500).
virtual IdentifierHash collectionHash() const
Returns the IdentifierHash corresponding to the PRD collection in the PRD container.
virtual const Amg::Vector3D & globalPosition() const =0
Returns the global position of the measurement (calculated on the fly)
Gaudi::Property< double > m_dropDistance
int getRegionId(const Identifier &id) const override
void printRegionMap(const RegionMap &regionMap) const
StatusCode loadFromStoreGate(const EventContext &ctx, const SG::ReadHandleKey< ContType > &key, const ContType *&cont_ptr) const
load the container from storegate given a ReadHandleKey.
SG::ReadHandleKey< Muon::TgcPrepDataContainer > m_keyTgc
void insertCluster(const MuonCluster &mdt, RegionMap &regionMap, const Amg::Vector3D &patpose, const Amg::Vector3D &patdire, bool hasPhiMeasurements) const
ToolHandle< IMdtDriftCircleOnTrackCreator > m_mdtCreator
StatusCode createRegionMap(const EventContext &ctx, const MuonPatternCombination &pat, RegionMap &regionMap, bool hasPhiMeasurements) const
Gaudi::Property< bool > m_doMultiAnalysis
virtual StatusCode initialize() override
bool checkForPhiMeasurements(const MuonPatternCombination &pat) const override
StatusCode calibrate(const EventContext &ctx, const MuonPatternCombination &pat, ROTsPerRegion &hitsPerRegion) const override
PublicToolHandle< MuonEDMPrinterTool > m_printer
SG::ReadHandleKey< Muon::RpcPrepDataContainer > m_keyRpc
Gaudi::Property< double > m_phiAngleCut
std::map< int, Region > RegionMap
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Gaudi::Property< bool > m_removeDoubleMdtHits
MuonPatternCalibration(const std::string &, const std::string &, const IInterface *)
void calibrateRegionMap(const RegionMap &regionMap, IMuonPatternCalibration::ROTsPerRegion &hitsPerRegion) const
Gaudi::Property< bool > m_recoverTriggerHits
ToolHandle< IMuonClusterOnTrackCreator > m_clusterCreator
void insertMdt(const MdtPrepData &clus, RegionMap &regionMap, const Amg::Vector3D &patpose, const Amg::Vector3D &patdire, bool hasPhiMeasurements) const
This class holds information needed for the Moore and MoMu pattern recognition for a muon chamber.
The MuonPatternCombination class provides the means to store the output of the initial global pattern...
Class to represent RPC measurements.
Definition RpcPrepData.h:35
virtual const MuonGM::RpcReadoutElement * detectorElement() const override final
Returns the detector element corresponding to this PRD.
Class to represent TGC measurements.
Definition TgcPrepData.h:32
virtual const MuonGM::TgcReadoutElement * detectorElement() const override final
Returns the detector element corresponding to this PRD The pointer will be zero if the det el is not ...
Property holding a SG store/key/clid from which a ReadHandle is made.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
virtual const TrkDetElementBase * detectorElement() const =0
return the detector element corresponding to this PRD The pointer will be zero if the det el is not d...
Identifier identify() const
return the identifier
Abstract Base Class for tracking surfaces.
virtual const Amg::Vector3D & normal() const
Returns the normal vector of the Surface (i.e.
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
const Amg::Vector3D & center() const
Returns the center position of the Surface.
virtual const Amg::Vector3D & center() const =0
Return the center of the element.
virtual const Surface & surface() const =0
Return surface associated with this detector element.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
ChIndex chIndex(const std::string &index)
convert ChIndex name string to enum
bool isSmall(const ChIndex index)
Returns true if the chamber index is in a small sector.
constexpr int toInt(const EnumType enumVal)
ChIndex
enum to classify the different chamber layers in the muon spectrometer
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
MuonPrepDataCollection< TgcPrepData > TgcPrepDataCollection
MuonPrepDataContainerT< RpcPrepData > RpcPrepDataContainer
MuonPrepDataContainerT< TgcPrepData > TgcPrepDataContainer
MuonPrepDataCollection< RpcPrepData > RpcPrepDataCollection