2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
4#ifndef MUONREADOUTGEOMETRYR4_STGCREADOUTELEMENT_ICC
5#define MUONREADOUTGEOMETRYR4_STGCREADOUTELEMENT_ICC
9 template <> inline Amg::Transform3D
10 TransformCacheDetEle<MuonGMR4::sTgcReadoutElement>::fetchTransform(const DetectorAlignStore* store) const{
11 return m_parent->toStation(store) * m_parent->fromGapToChamOrigin(hash());
13 template <> inline Identifier
14 TransformCacheDetEle<MuonGMR4::sTgcReadoutElement>::identify() const {
15 using RE = MuonGMR4::sTgcReadoutElement;
16 return m_parent->measurementId(RE::createHash(RE::gasGapNumber(hash()) + 1,
17 RE::chType(hash()), 1));
23 namespace sTgcIdMeasHashFields {
24 constexpr unsigned minusOne = -1;
26 //// (wireInGrp) | (channel) [1-512] | IsWireInGrp (0,1) | (sTgcChannelType) [0-2] | (gasGap -1) [1-4]
27 constexpr unsigned gasGapShift = 0;
28 constexpr unsigned chTypeShift = 2;
29 constexpr unsigned wireInGrpBit = chTypeShift+ 2;
30 constexpr unsigned chanShift = chTypeShift + 3;
31 constexpr unsigned wireInGrpShift = chanShift + 9;
34inline double sTgcReadoutElement::chamberHeight() const { return 2.* m_pars.halfChamberHeight; }
35inline double sTgcReadoutElement::sChamberLength() const { return 2.* m_pars.sHalfChamberLength; }
36inline double sTgcReadoutElement::lChamberLength() const { return 2.* m_pars.lHalfChamberLength; }
37inline double sTgcReadoutElement::thickness() const { return 2.* m_pars.halfChamberTck; }
38inline double sTgcReadoutElement::sFrameWidth() const { return m_pars.sFrameWidth; }
39inline double sTgcReadoutElement::lFrameWidth() const { return m_pars.lFrameWidth; }
40inline int sTgcReadoutElement::multilayer() const { return m_multiLayer; }
42inline unsigned sTgcReadoutElement::numLayers() const { return m_pars.numLayers; }
43inline unsigned sTgcReadoutElement::nChTypes() const { return m_pars.nChTypes; }
44inline double sTgcReadoutElement::gasGapThickness() const { return m_pars.gasTck; }
45inline double sTgcReadoutElement::gasGapPitch() const { return m_gasGapPitch; }
47inline double sTgcReadoutElement::firstStripPitch(const IdentifierHash& measHash) const {
48 return m_pars.firstStripPitch[gasGapNumber(measHash)]; }
50inline unsigned sTgcReadoutElement::numChannels(const IdentifierHash& measHash) const {
51 switch (chType(measHash)) {
52 case ReadoutChannelType::Strip:
53 return stripDesign(measHash).numStrips();
54 case ReadoutChannelType::Pad:
55 return padDesign(measHash).numPads();
56 case ReadoutChannelType::Wire:
57 return wireDesign(measHash).numStrips();
58 case ReadoutChannelType::WireInGrp:
59 return wireDesign(measHash).nAllWires();
61 ATH_MSG_WARNING("Channel type "<<chType(measHash)<<" is unknown.");
66inline double sTgcReadoutElement::stripLength(const IdentifierHash& measHash) const {
67 return stripDesign(measHash).stripLength(channelNumber(measHash));
70inline unsigned sTgcReadoutElement::numPadEta(const IdentifierHash& measHash) const { return padDesign(measHash).numPadEta(); }
71inline unsigned sTgcReadoutElement::numPadPhi(const IdentifierHash& measHash) const { return padDesign(measHash).numPadPhi(); }
73inline double sTgcReadoutElement::padHeight(const IdentifierHash& measHash) const { return (padEta(measHash) == 1) ?
74 padDesign(measHash).firstPadHeight() : padDesign(measHash).padHeight(); }
76inline double sTgcReadoutElement::padPhiShift(const IdentifierHash& measHash) const { return padDesign(measHash).padPhiShift(); }
78inline double sTgcReadoutElement::anglePadPhi(const IdentifierHash& measHash) const { return padDesign(measHash).anglePadPhi(); }
79inline unsigned sTgcReadoutElement::maxPadEta(const IdentifierHash& measHash) const { return padDesign(measHash).anglePadPhi(); }
81inline unsigned sTgcReadoutElement::padNumberSeq(const IdentifierHash& measHash) const {
82 int padEta = padEtaPhi(measHash).first;
83 int padPhi = padEtaPhi(measHash).second;
84 int numPadEta = padDesign(measHash).numPadEta();
85 int numPadPhi = padDesign(measHash).numPadPhi();
86 if((padEta > numPadEta) || (padPhi > numPadPhi)) {
87 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Pad Channel: "<< idHelperSvc()->toString(measurementId(measHash))
88 << " resulted in invalid (eta, phi): ("<<padEta<< ", " <<padPhi <<"), (maxEta, maxPhi): "<<numPadEta<<", "<<numPadPhi
89 <<"). total pads available: "<<padDesign(measHash).numPads());
92 return (padPhi - 1) * numPadEta + padEta;
95inline std::pair<unsigned, unsigned> sTgcReadoutElement::padEtaPhi(const IdentifierHash& measHash) const { return padDesign(measHash).padEtaPhi(channelNumber(measHash)); }
96inline unsigned sTgcReadoutElement::padEta(const IdentifierHash& measHash) const { return padDesign(measHash).padEta(channelNumber(measHash)); }
97inline unsigned sTgcReadoutElement::padPhi(const IdentifierHash& measHash) const { return padDesign(measHash).padPhi(channelNumber(measHash)); }
98inline double sTgcReadoutElement::beamlineRadius(const IdentifierHash& measHash) const { return padDesign(measHash).beamlineRadius(); }
99inline sTgcReadoutElement::localCornerArray sTgcReadoutElement::localPadCorners(const IdentifierHash& measHash) const { return padDesign(measHash).padCorners(channelNumber(measHash)); }
100inline const StripDesign& sTgcReadoutElement::stripDesign(const IdentifierHash& measHash) const {
101 return m_pars.stripLayers[gasGapNumber(measHash)].design();
104inline const WireGroupDesign& sTgcReadoutElement::wireDesign(const IdentifierHash& measHash) const {
105 return static_cast<const WireGroupDesign&>(m_pars.stripLayers[gasGapNumber(measHash)].design(true));
107inline const PadDesign& sTgcReadoutElement::padDesign(const IdentifierHash& measHash) const {
108 return static_cast<const PadDesign&>(m_pars.padLayers[gasGapNumber(measHash)].design(true));
110inline IdentifierHash sTgcReadoutElement::measurementHash(const Identifier& measId) const {
111 if (idHelperSvc()->detElId(measId) != identify()) {
112 ATH_MSG_WARNING("The measurement " << idHelperSvc()->toString(measId)
113 << " picks the wrong readout element " << idHelperSvc()->toStringDetEl(identify()));
115 return createHash(m_idHelper.gasGap(measId),
116 m_idHelper.channelType(measId),
117 m_idHelper.channel(measId));
119inline IdentifierHash sTgcReadoutElement::createHash(const unsigned gasGap,
120 const unsigned channelType,
121 const unsigned channel,
122 const unsigned wireInGrp) {
123 using namespace sTgcIdMeasHashFields;
124 /// Construct the Hash such that (channel) | WireInGrpBit (0,1) | (channelType) | (gasGap -1)
125 if (channelType == ReadoutChannelType::WireInGrp) {
126 const unsigned readOutHash = static_cast<unsigned>(createHash(gasGap, ReadoutChannelType::Wire, channel));
127 return IdentifierHash {wireInGrp << wireInGrpShift | (1<<wireInGrpBit) | readOutHash};
129 return IdentifierHash{ channel << chanShift | channelType << chTypeShift | (gasGap -1) };
132inline IdentifierHash sTgcReadoutElement::layerHash(const IdentifierHash& measHash) {
133 return createHash(gasGapNumber(measHash)+1, ReadoutChannelType::Strip,0);
136inline unsigned sTgcReadoutElement::channelNumber(const IdentifierHash& measHash) {
137 using namespace sTgcIdMeasHashFields;
138 constexpr unsigned mask = (minusOne << wireInGrpShift);
139 const unsigned stripedHash = (~mask) & static_cast<unsigned>(measHash);
140 return stripedHash >> chanShift;
142inline unsigned sTgcReadoutElement::chType(const IdentifierHash& measHash) {
143 using namespace sTgcIdMeasHashFields;
144 constexpr unsigned mask = (minusOne << chanShift);
145 const unsigned stripedHash = (~mask) & static_cast<unsigned>(measHash);
146 return stripedHash >> chTypeShift;
149inline unsigned sTgcReadoutElement::gasGapNumber(const IdentifierHash& measHash) {
150 using namespace sTgcIdMeasHashFields;
151 constexpr unsigned mask = (minusOne << chTypeShift);
152 return (static_cast<unsigned>(measHash) &(~mask) );
154inline Identifier sTgcReadoutElement::measurementId(const IdentifierHash& measHash) const {
155 return m_idHelper.channelID(identify(), multilayer(), gasGapNumber(measHash) + 1, chType(measHash), channelNumber(measHash));
157inline IdentifierHash sTgcReadoutElement::layerHash(const Identifier& measId) const {
158 if (m_idHelper.elementID(measId) != m_idHelper.elementID(identify()) ) {
159 ATH_MSG_WARNING("The measurement " << idHelperSvc()->toString(measId)
160 << " picks the wrong readout element " << idHelperSvc()->toStringDetEl(identify()));
162 return createHash(m_idHelper.gasGap(measId), ReadoutChannelType::Strip, 0);
165inline const StripLayer& sTgcReadoutElement::stripLayer(const IdentifierHash& measHash) const {
166 unsigned gasGap = gasGapNumber(measHash);
167 switch (chType(measHash)) {
168 case ReadoutChannelType::Strip:
169 case ReadoutChannelType::Wire:
170 case ReadoutChannelType::WireInGrp:
171 return m_pars.stripLayers.at(gasGap);
172 case ReadoutChannelType::Pad:
173 return m_pars.padLayers.at(gasGap);
175 THROW_EXCEPTION("Invalid channel parsed");
176 return stripLayer(0);
179} // namespace MuonGMR4