ATLAS Offline Software
MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/RpcReadoutElement.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 #ifndef MUONREADOUTGEOMETRYR4_RPCREADOUTELEMENT_ICC
5 #define MUONREADOUTGEOMETRYR4_RPCREADOUTELEMENT_ICC
6 
7 
8 namespace ActsTrk{
9  template <> inline Amg::Transform3D
10  TransformCacheDetEle<MuonGMR4::RpcReadoutElement>::fetchTransform(const DetectorAlignStore* store) const{
11  return m_parent->toStation(store) * m_parent->fromGapToChamOrigin(hash());
12  }
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())));
20  }
21 }
22 
23 namespace MuonGMR4 {
24  namespace RpcIdMeasHashFields{
25  constexpr unsigned minOne = -1;
26  /// Bitwise layout of the measurement hash
27  /// ( strip | meashPhi | doubletPhi [1-2]| gasGap [1-3])
28  /// 1 bit 1 bit
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;
36  }
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()));
60  }
61  return createHash(m_idHelper.strip(measId),
62  m_idHelper.gasGap(measId),
63  m_idHelper.doubletPhi(measId),
64  m_idHelper.measuresPhi(measId));
65  }
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()));
72  }
73  return createHash(0, m_idHelper.gasGap(measId),
74  m_idHelper.doubletPhi(measId), 0);
75  }
76  inline const StripDesign& RpcReadoutElement::stripDesign(const IdentifierHash& measHash) const {
77  return measuresPhi(measHash) ? *m_pars.phiDesign : *m_pars.etaDesign;
78  }
79  inline IdentifierHash RpcReadoutElement::layerHash(const IdentifierHash& measHash) const {
80  return createHash(0, gasGapNumber(measHash) + 1, doubletPhiNumber(measHash) + 1, false);
81  }
82  inline IdentifierHash RpcReadoutElement::createHash(const unsigned strip,
83  const unsigned gasGap,
84  const unsigned doubPhi,
85  const bool measPhi) {
86  using namespace RpcIdMeasHashFields;
87  const IdentifierHash hash{ strip << channelShift | measPhi << measPhiShift |
88  (doubPhi -1) << doubletPhiShift | (gasGap -1) << gasGapShift };
89  return hash;
90  }
91  inline unsigned RpcReadoutElement::stripNumber(const IdentifierHash& measHash) {
92  using namespace RpcIdMeasHashFields;
93  return static_cast<unsigned>(measHash) >> channelShift;
94  }
95  inline unsigned RpcReadoutElement::gasGapNumber(const IdentifierHash& measHash) {
96  using namespace RpcIdMeasHashFields;
97  constexpr unsigned mask = minOne << doubletPhiShift;
98  const unsigned stripedHash = (~mask) & static_cast<unsigned>(measHash);
99  return ( stripedHash >> gasGapShift);
100  }
101  inline unsigned RpcReadoutElement::doubletPhiNumber(const IdentifierHash& measHash) {
102  using namespace RpcIdMeasHashFields;
103  constexpr unsigned mask = minOne << measPhiShift;
104  const unsigned stripedMask = (~mask) & static_cast<unsigned>(measHash);
105  return (stripedMask >> doubletPhiShift);
106  }
107  inline bool RpcReadoutElement::measuresPhi(const IdentifierHash& measHash) {
108  using namespace RpcIdMeasHashFields;
109  constexpr unsigned mask = minOne << channelShift;
110  const unsigned stripedMask = (~mask) & static_cast<unsigned>(measHash);
111  return (stripedMask >> measPhiShift);
112  }
113  inline const StripLayerPtr& RpcReadoutElement::sensorLayout(const IdentifierHash& measHash) const {
114  const auto layIdx{static_cast<unsigned>(layerHash(measHash))};
115  if (layIdx >= m_pars.layers.size() || !m_pars.layers[layIdx]) {
116  ATH_MSG_FATAL("The sensorLayout does not exist for "<<idHelperSvc()->toStringDetEl(identify())
117  <<" gasGap "<<(gasGapNumber(measHash) +1)
118  <<" doubletPhi: "<<(doubletPhiNumber(measHash) + 1)
119  <<" isPhiChannel: "<<measuresPhi(measHash)
120  <<" strip: "<<stripNumber(measHash) );
121  throw std::runtime_error("Invalid sensor layout");
122  }
123  return m_pars.layers[layIdx];
124  }
125  inline Identifier RpcReadoutElement::measurementId(const IdentifierHash& measHash) const {
126  return m_idHelper.channelID(identify(), doubletZ(), doubletPhiNumber(measHash) + 1,
127  gasGapNumber(measHash) + 1, measuresPhi(measHash), stripNumber(measHash));
128  }
129  inline Amg::Vector3D RpcReadoutElement::stripPosition(const ActsTrk::GeometryContext& ctx, const Identifier& measId) const {
130  return stripPosition(ctx, measurementHash(measId));
131  }
132  inline Amg::Vector3D RpcReadoutElement::rightStripEdge(const ActsTrk::GeometryContext& ctx, const Identifier& measId) const{
133  return rightStripEdge(ctx, measurementHash(measId));
134  }
135  inline Amg::Vector3D RpcReadoutElement::leftStripEdge(const ActsTrk::GeometryContext& ctx, const Identifier& measId) const{
136  return leftStripEdge(ctx, measurementHash(measId));
137  }
138 } // namespace MuonGMR4
139 #endif