2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
4 #ifndef MUONREADOUTGEOMETRYR4_RPCREADOUTELEMENT_ICC
5 #define MUONREADOUTGEOMETRYR4_RPCREADOUTELEMENT_ICC
9 template <> inline Amg::Transform3D
10 TransformCacheDetEle<MuonGMR4::RpcReadoutElement>::fetchTransform(const DetectorAlignStore* store) const{
11 return m_parent->toStation(store) * m_parent->fromGapToChamOrigin(hash());
13 template <> inline Identifier
14 TransformCacheDetEle<MuonGMR4::RpcReadoutElement>::identify() const {
15 using RE = MuonGMR4::RpcReadoutElement;
16 return m_parent->measurementId(RE::createHash(1,
17 RE::gasGapNumber(hash()) +1,
18 RE::doubletPhiNumber(hash()) + 1,
19 RE::measuresPhi(hash())));
24 namespace RpcIdMeasHashFields{
25 constexpr unsigned minOne = -1;
26 /// Bitwise layout of the measurement hash
27 /// ( strip | meashPhi | doubletPhi [1-2]| gasGap [1-3])
29 constexpr unsigned gasGapShift = 0;
30 /// @brief gasGap ranges from 1-3 -> 2 bits
31 constexpr unsigned doubletPhiShift = 2;
32 /// @brief doubletPhi ranges from 1-2 -> 1 bit
33 constexpr unsigned measPhiShift = doubletPhiShift + 1;
34 /// @brief measPhi is one bit
35 constexpr unsigned channelShift = measPhiShift + 1;
37 inline double RpcReadoutElement::thickness() const { return 2.* m_pars.halfThickness; }
38 inline double RpcReadoutElement::gasGapPitch() const {return m_gasThickness; }
39 inline int RpcReadoutElement::doubletZ() const{ return m_doubletZ; }
40 inline int RpcReadoutElement::doubletR() const{ return m_doubletR; }
41 inline int RpcReadoutElement::doubletPhi() const{ return m_doubletPhi; }
42 inline unsigned RpcReadoutElement::nGasGaps() const { return m_pars.nGasGaps; }
43 inline int RpcReadoutElement::nPhiPanels() const { return m_pars.nPanelsInPhi; }
44 inline int RpcReadoutElement::doubletPhiMax() const {return std::max(nPhiPanels(), doubletPhi()); }
45 inline unsigned RpcReadoutElement::nEtaStrips() const { return (m_pars.etaDesign ? m_pars.etaDesign->numStrips(): 0u); }
46 inline unsigned RpcReadoutElement::nPhiStrips() const { return (m_pars.phiDesign ? m_pars.phiDesign->numStrips(): 0u); }
47 inline unsigned RpcReadoutElement::nStrips(const IdentifierHash& hash) const { return measuresPhi(hash) ? nPhiStrips() : nEtaStrips(); }
48 inline double RpcReadoutElement::stripEtaPitch() const { return (m_pars.etaDesign ? m_pars.etaDesign->stripPitch() : 0.); }
49 inline double RpcReadoutElement::stripPhiPitch() const { return (m_pars.phiDesign ? m_pars.phiDesign->stripPitch() : 0.); }
50 inline double RpcReadoutElement::stripEtaWidth() const { return (m_pars.etaDesign ? m_pars.etaDesign->stripWidth() : 0.); }
51 inline double RpcReadoutElement::stripPhiWidth() const { return (m_pars.phiDesign ? m_pars.phiDesign->stripWidth() : 0.); }
52 inline double RpcReadoutElement::stripEtaLength() const { return (m_pars.etaDesign ? m_pars.etaDesign->longHalfHeight()*2. : 0.);}
53 inline double RpcReadoutElement::stripPhiLength() const { return (m_pars.phiDesign ? m_pars.phiDesign->longHalfHeight()*2. : 0.);}
54 inline IdentifierHash RpcReadoutElement::measurementHash(const Identifier& measId) const {
55 if (m_idHelper.doubletZ(measId) != doubletZ() ||
56 (doubletPhi() != 1 && m_idHelper.doubletPhi(measId) == 1) ||
57 m_idHelper.elementID(measId) != m_idHelper.elementID(identify()) ) {
58 ATH_MSG_WARNING("The measurement " << idHelperSvc()->toString(measId)
59 << " picks the wrong readout element " << idHelperSvc()->toStringDetEl(identify()));
61 return createHash(m_idHelper.strip(measId),
62 m_idHelper.gasGap(measId),
63 m_idHelper.doubletPhi(measId),
64 m_idHelper.measuresPhi(measId));
66 inline IdentifierHash RpcReadoutElement::layerHash(const Identifier& measId) const {
67 if (m_idHelper.doubletZ(measId) != doubletZ() ||
68 (doubletPhi() != 1 && m_idHelper.doubletPhi(measId) == 1) ||
69 m_idHelper.elementID(measId) != m_idHelper.elementID(identify()) ) {
70 ATH_MSG_WARNING("The measurement " << idHelperSvc()->toString(measId)
71 << " picks the wrong readout element " << idHelperSvc()->toStringDetEl(identify()));
73 return createHash(0, m_idHelper.gasGap(measId),
74 m_idHelper.doubletPhi(measId),
75 m_idHelper.measuresPhi(measId));
77 inline const StripDesign& RpcReadoutElement::stripDesign(const IdentifierHash& measHash) const {
78 return measuresPhi(measHash) ? *m_pars.phiDesign : *m_pars.etaDesign;
80 inline IdentifierHash RpcReadoutElement::layerHash(const IdentifierHash& measHash) const {
81 using namespace RpcIdMeasHashFields;
82 constexpr unsigned mask = minOne << channelShift;
83 return IdentifierHash{static_cast<unsigned>(measHash) & (~mask)};
85 inline IdentifierHash RpcReadoutElement::createHash(const unsigned strip,
86 const unsigned gasGap,
87 const unsigned doubPhi,
89 using namespace RpcIdMeasHashFields;
90 const IdentifierHash hash{ strip << channelShift | measPhi << measPhiShift |
91 (doubPhi -1) << doubletPhiShift | (gasGap -1) << gasGapShift };
94 inline unsigned RpcReadoutElement::stripNumber(const IdentifierHash& measHash) {
95 using namespace RpcIdMeasHashFields;
96 return static_cast<unsigned>(measHash) >> channelShift;
98 inline unsigned RpcReadoutElement::gasGapNumber(const IdentifierHash& measHash) {
99 using namespace RpcIdMeasHashFields;
100 constexpr unsigned mask = minOne << doubletPhiShift;
101 const unsigned stripedHash = (~mask) & static_cast<unsigned>(measHash);
102 return ( stripedHash >> gasGapShift);
104 inline unsigned RpcReadoutElement::doubletPhiNumber(const IdentifierHash& measHash) {
105 using namespace RpcIdMeasHashFields;
106 constexpr unsigned mask = minOne << measPhiShift;
107 const unsigned stripedMask = (~mask) & static_cast<unsigned>(measHash);
108 return (stripedMask >> doubletPhiShift);
110 inline bool RpcReadoutElement::measuresPhi(const IdentifierHash& measHash) {
111 using namespace RpcIdMeasHashFields;
112 constexpr unsigned mask = minOne << channelShift;
113 const unsigned stripedMask = (~mask) & static_cast<unsigned>(measHash);
114 return (stripedMask >> measPhiShift);
116 inline const StripLayer& RpcReadoutElement::sensorLayout(const IdentifierHash& measHash) const {
117 const unsigned layIdx{static_cast<unsigned>(layerHash(measHash))};
118 if (layIdx >= m_pars.layers.size() || !m_pars.layers[layIdx]) {
119 ATH_MSG_FATAL("The sensorLayout does not exist for "<<idHelperSvc()->toStringDetEl(identify())
120 <<" gasGap "<<(gasGapNumber(measHash) +1)
121 <<" doubletPhi: "<<(doubletPhiNumber(measHash) + 1)
122 <<" isPhiChannel: "<<measuresPhi(measHash)
123 <<" strip: "<<stripNumber(measHash) );
124 throw std::runtime_error("Invalid sensor layout");
126 return (*m_pars.layers[layIdx]);
128 inline Identifier RpcReadoutElement::measurementId(const IdentifierHash& measHash) const {
129 return m_idHelper.channelID(identify(), doubletZ(), doubletPhiNumber(measHash) + 1,
130 gasGapNumber(measHash) + 1, measuresPhi(measHash), stripNumber(measHash));
132 inline Amg::Vector3D RpcReadoutElement::stripPosition(const ActsGeometryContext& ctx, const Identifier& measId) const {
133 return stripPosition(ctx, measurementHash(measId));
135 inline Amg::Vector3D RpcReadoutElement::rightStripEdge(const ActsGeometryContext& ctx, const Identifier& measId) const{
136 return rightStripEdge(ctx, measurementHash(measId));
138 inline Amg::Vector3D RpcReadoutElement::leftStripEdge(const ActsGeometryContext& ctx, const Identifier& measId) const{
139 return leftStripEdge(ctx, measurementHash(measId));
141 } // namespace MuonGMR4