ATLAS Offline Software
Loading...
Searching...
No Matches
MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/sTgcReadoutElement.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
5
7#include <GaudiKernel/SystemOfUnits.h>
8
9#ifndef SIMULATIONBASE
10# include "Acts/Surfaces/TrapezoidBounds.hpp"
11# include "Acts/Surfaces/Surface.hpp"
12#endif
13
14using namespace ActsTrk;
15
16namespace MuonGMR4 {
18std::ostream& operator<<(std::ostream& ostr, const parameterBook& pars) {
19 if (pars.stripDesign) ostr<<"Strips: "<<(*pars.stripDesign)<<std::endl;
20 if (pars.wireGroupDesign) ostr<<"Wire Groups: "<<(*pars.wireGroupDesign)<<std::endl;
21 if (pars.padDesign) ostr<<"Pads: "<<(*pars.padDesign)<<std::endl;
22 return ostr;
23}
29
31
33 ATH_MSG_DEBUG("Parameter book "<<parameterBook());
34
36#ifndef SIMULATIONBASE
37
39 m_pars.layerBounds->makeBounds<Acts::TrapezoidBounds>(m_pars.sHalfChamberLength,
40 m_pars.lHalfChamberLength,
41 m_pars.halfChamberHeight)));
42#endif
43
44 if (m_pars.stripLayers.empty() || m_pars.wireGroupLayers.empty()) {
45 ATH_MSG_FATAL("The readout element "<<idHelperSvc()->toStringDetEl(identify())<<" doesn't have any layers defined");
46 return StatusCode::FAILURE;
47 }
48 for (unsigned int layer = 0; layer < m_pars.stripLayers.size(); ++layer) {
49 IdentifierHash layHash{layer};
50 if (gasGapNumber(m_pars.stripLayers[layer].hash()) != layHash) {
51 ATH_MSG_FATAL("Layer "<<m_pars.stripLayers[layer]<<" has a very strange hash. Expect "<<layer);
52 return StatusCode::FAILURE;
53 }
54 ATH_CHECK(insertTransform<sTgcReadoutElement>(m_pars.stripLayers[layer].hash()));
55
56#ifndef SIMULATIONBASE
57 const StripDesign& design{m_pars.stripLayers[layer].design()};
58 ATH_CHECK(planeSurfaceFactory(m_pars.stripLayers[layer].hash(),
59 m_pars.layerBounds->makeBounds<Acts::TrapezoidBounds>(design.shortHalfHeight(),
60 design.longHalfHeight(),
61 design.halfWidth(),
62 90.*Gaudi::Units::deg)));
63#endif
64
65 }
66 for (unsigned int layer = 0; layer < m_pars.wireGroupLayers.size(); ++layer) {
67 IdentifierHash layHash{layer};
68 if (gasGapNumber(m_pars.wireGroupLayers[layer].hash()) != layHash) {
69 ATH_MSG_FATAL("Layer "<<m_pars.wireGroupLayers[layer]<<" has a very strange hash. Expect "<<layer);
70 return StatusCode::FAILURE;
71 }
72 ATH_CHECK(insertTransform<sTgcReadoutElement>(m_pars.wireGroupLayers[layer].hash()));
73#ifndef SIMULATIONBASE
74 const StripDesign& design{m_pars.wireGroupLayers[layer].design()};
75 ATH_CHECK(planeSurfaceFactory(m_pars.wireGroupLayers[layer].hash(),
76 m_pars.layerBounds->makeBounds<Acts::TrapezoidBounds>(design.shortHalfHeight(),
77 design.longHalfHeight(),
78 design.halfWidth())));
79#endif
80 }
81 for (unsigned int layer = 0; layer < m_pars.padLayers.size(); ++layer) {
82 IdentifierHash layHash{layer};
83 if (gasGapNumber(m_pars.padLayers[layer].hash()) != layHash) {
84 ATH_MSG_FATAL("Layer "<<m_pars.padLayers[layer]<<" has a very strange hash. Expect "<<layer);
85 return StatusCode::FAILURE;
86 }
88#ifndef SIMULATIONBASE
89 const StripDesign& design{m_pars.padLayers[layer].design()};
90 ATH_CHECK(planeSurfaceFactory(m_pars.padLayers[layer].hash(),
91 m_pars.layerBounds->makeBounds<Acts::TrapezoidBounds>(design.shortHalfHeight(),
92 design.longHalfHeight(),
93 design.halfWidth())));
94#endif
95
96 }
100 return StatusCode::SUCCESS;
101}
102
106
108 if (chType(measHash) == ReadoutChannelType::Strip) {
109 Amg::Vector2D stripCenter{Amg::Vector2D::Zero()};
110 const StripDesign& design{stripDesign(measHash)};
111 const int ch = channelNumber(measHash);
112
113 std::optional<Amg::Vector2D> stripCenterOpt = design.center(ch);
114 if (!stripCenterOpt) {
115 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" The strip " << ch << " doesn't intersect with the edges of the trapezoid.");
116 return stripCenter;
117 }
118 ATH_MSG_VERBOSE("Fetch local strip position "<<idHelperSvc()->toString(measurementId(measHash))<<" "
119 <<" "<<Amg::toString(*stripCenterOpt)<<" "<<design);
120 stripCenter = std::move(*stripCenterOpt);
121 if (ch == 1 && firstStripPitch(measHash) < 0.75 * design.stripPitch()) {
122 stripCenter.x() += 0.25 * design.stripWidth();
123 }
124 if (ch == design.numStrips() && firstStripPitch(measHash) > 0.75 * design.stripPitch()) {
125 stripCenter.x() -= 0.25 * design.stripWidth();
126 }
127 return stripCenter;
128 } else if (chType(measHash) == ReadoutChannelType::Wire) {
129 Amg::Vector2D wireGroupCenter{Amg::Vector2D::Zero()};
130 const WireGroupDesign& design{wireDesign(measHash)};
131 const int ch = channelNumber(measHash);
132 std::optional<Amg::Vector2D> wireGroupCenterOpt = design.center(ch);
133 if (!wireGroupCenterOpt) {
134 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" The wireGroup" << ch << "doesn't intersect with the edges of the trapezoid.");
135 return wireGroupCenter;
136 }
137 wireGroupCenter = std::move(*wireGroupCenterOpt);
138 ATH_MSG_VERBOSE("Fetch local wire position "<<idHelperSvc()->toString(measurementId(measHash))<<" "
139 <<" "<<Amg::toString(wireGroupCenter)<<" "<<design);
140 if (ch == 1) {
141 ATH_MSG_DEBUG("The first wiregroup width is " <<design.numWiresInGroup(ch) << " firstWirePos: " << design.firstStripPos());
142 ATH_MSG_DEBUG("The last wire pos is: " << wireGroupCenter.x() + (0.5 * (design.numWiresInGroup(ch) + 1) - 1) * design.stripPitch() );
144 wireGroupCenter.x() = wireGroupCenter.x() + (0.5 * (design.numWiresInGroup(ch) + 1) - 1) * design.stripPitch();
147 wireGroupCenter.x() = 0.5 * (wireGroupCenter.x() - design.longHalfHeight());
148 } else if (ch == design.numStrips()) {
149 ATH_MSG_VERBOSE("The actual center of the last wire group is: " << wireGroupCenter.x());
151 wireGroupCenter.x() = wireGroupCenter.x() - 0.5 * (design.numWiresInGroup(ch) + 1) * design.stripPitch();
152 ATH_MSG_VERBOSE("The last wire of the last second group is at: " << wireGroupCenter.x());
155 wireGroupCenter.x() = 0.5 * (wireGroupCenter.x() + design.longHalfHeight());
156 }
159 return wireGroupCenter;
160 }
161 else if (chType(measHash) == ReadoutChannelType::Pad) {
162 Amg::Vector2D padCenter{Amg::Vector2D::Zero()};
163 std::optional<Amg::Vector2D> padCenterOpt = padDesign(measHash).stripPosition(channelNumber(measHash));
164 if (!padCenterOpt) {
165 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" The pad" << channelNumber(measHash) << "doesn't is not a valid pad number.");
166 return padCenter;
167 }
168 padCenter = std::move(*padCenterOpt);
169 return padCenter;
170 }
171 else {
172 ATH_MSG_FATAL(__FILE__<<":"<<__LINE__<<"Invalid channel type: " << chType(measHash));
173 return Amg::Vector2D::Zero();
174 }
175}
176
178 const IdentifierHash lHash = layerHash(measHash);
179 unsigned int layIdx = static_cast<unsigned int>(lHash);
180 unsigned int gasGap = gasGapNumber(measHash);
181 if((chType(measHash) < ReadoutChannelType::Pad || chType(measHash) > ReadoutChannelType::Wire) && gasGap < m_pars.padLayers.size()) {
182 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" The channel type "<<chType(measHash)
183 <<"with the layer hash "<<layIdx<<" is invalid. Maximum range "<<m_pars.stripLayers.size());
184 return Amg::Vector3D::Zero();
185 }
186 Amg::Vector3D channelPos{Amg::Vector3D::Zero()};
187 Amg::Vector2D localChannel = localChannelPosition(measHash);
188 channelPos.block<2,1>(0,0) = std::move(localChannel);
189 return localToGlobalTrans(ctx, lHash) * channelPos;
190}
191
192using localCornerArray = std::array<Amg::Vector2D, 4>;
193using globalCornerArray = std::array<Amg::Vector3D, 4>;
195 const IdentifierHash lHash = layerHash(measHash);
196 unsigned int layIdx = static_cast<unsigned int>(lHash);
197 unsigned int gasGap = gasGapNumber(measHash);
198 globalCornerArray gPadCorners{make_array<Amg::Vector3D, 4>(Amg::Vector3D::Zero())};
199 if (chType(measHash) == ReadoutChannelType::Pad && gasGap < m_pars.padLayers.size()) {
200 localCornerArray lPadCorners = localPadCorners(measHash);
201 for (unsigned int corner = 0; corner < lPadCorners.size(); ++corner) {
202 gPadCorners[corner].block<2,1>(0,0) = std::move(lPadCorners[corner]);
203 gPadCorners[corner] = localToGlobalTrans(ctx, lHash) * gPadCorners[corner];
204 }
205 return gPadCorners;
206 }
207 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" The layer hash "<<layIdx
208 <<" is out of range. Maximum range "<<m_pars.padLayers.size());
209 return gPadCorners;
210}
211
213 const IdentifierHash lHash = layerHash(measHash);
214 unsigned int layIdx = static_cast<unsigned int>(lHash);
215 if (layIdx < m_pars.stripLayers.size()) {
216 const StripLayer& layout{m_pars.stripLayers[layIdx]};
217 return layout.toOrigin() * layout.localStripPosition(channelNumber(measHash));
218 }
219 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" The layer hash "<<layIdx
220 <<" is out of range. Maximum range "<<m_pars.stripLayers.size());
221 return Amg::Vector3D::Zero();
222}
223int sTgcReadoutElement::padNumber(const Amg::Vector2D& hitPos, const IdentifierHash& measHash) const {
224 int padEta = padDesign(measHash).channelNumber(hitPos).first;
225 int padPhi = padDesign(measHash).channelNumber(hitPos).second;
226 bool is_valid{true};
227 const Identifier padID = m_idHelper.padID(identify(), multilayer(), gasGapNumber(measHash) + 1, chType(measHash),
228 padEta, padPhi, is_valid);
229 int channel = m_idHelper.channel(padID);
230 return channel;
231}
232
234 const IdentifierHash lHash = layerHash(measHash);
235 unsigned int gasGap = gasGapNumber(measHash);
236 unsigned int layIdx = static_cast<unsigned int>(lHash);
237
238 if(chType(measHash) == ReadoutChannelType::Strip){
239 if(gasGap > m_pars.stripLayers.size()){
240 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" The layer hash "<<layIdx
241 <<" is out of range. Maximum range "<<m_pars.stripLayers.size());
242 return Amg::Vector3D::Zero();
243 }
244 Amg::Vector3D stripleftEdge{Amg::Vector3D::Zero()};
245 Amg::Vector2D localstripleftEdge{Amg::Vector2D::Zero()};
246 std::optional<Amg::Vector2D> stripleftEdgeOpt = stripDesign(measHash).leftEdge(channelNumber(measHash));
247 localstripleftEdge = std::move(*stripleftEdgeOpt);
248 stripleftEdge.block<2,1>(0,0) = std::move(localstripleftEdge);
249
250 return localToGlobalTrans(ctx, lHash)*stripleftEdge;
251
252 }else if(chType(measHash) == ReadoutChannelType::Wire){
253 if(gasGap > m_pars.wireGroupLayers.size()){
254 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" The layer hash "<<layIdx
255 <<" is out of range. Maximum range "<<m_pars.wireGroupLayers.size());
256 return Amg::Vector3D::Zero();
257
258 }
259
260 Amg::Vector3D wireleftEdge{Amg::Vector3D::Zero()};
261 Amg::Vector2D localwireleftEdge{Amg::Vector2D::Zero()};
262 std::optional<Amg::Vector2D> wireleftedgeOpt = wireDesign(measHash).leftEdge(channelNumber(measHash));
263 localwireleftEdge = std::move(*wireleftedgeOpt);
264 wireleftEdge.block<2,1>(0,0) = std::move(localwireleftEdge);
265
266 return localToGlobalTrans(ctx, lHash)*wireleftEdge;
267
268 }
269
270 ATH_MSG_FATAL(__FILE__<<":"<<__LINE__<<" The layer hash "<<layIdx
271 <<" is not valid Type "<< chType(measHash));
272 return Amg::Vector3D::Zero();
273
274}
275
276
278 const IdentifierHash lHash = layerHash(measHash);
279 unsigned int gasGap = gasGapNumber(measHash);
280 unsigned int layIdx = static_cast<unsigned int>(lHash);
281
282 if(chType(measHash) == ReadoutChannelType::Strip){
283 if(gasGap > m_pars.stripLayers.size()){
284 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" The layer hash "<<layIdx
285 <<" is out of range. Maximum range "<<m_pars.stripLayers.size());
286 return Amg::Vector3D::Zero();
287 }
288 Amg::Vector3D striprightEdge{Amg::Vector3D::Zero()};
289 Amg::Vector2D localstriprightEdge{Amg::Vector2D::Zero()};
290 std::optional<Amg::Vector2D> striprightEdgeOpt = stripDesign(measHash).rightEdge(channelNumber(measHash));
291 localstriprightEdge = std::move(*striprightEdgeOpt);
292 striprightEdge.block<2,1>(0,0) = std::move(localstriprightEdge);
293
294 return localToGlobalTrans(ctx, lHash)*striprightEdge;
295
296 }else if(chType(measHash) == ReadoutChannelType::Wire){
297 if(gasGap > m_pars.wireGroupLayers.size()){
298 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" The layer hash "<<layIdx
299 <<" is out of range. Maximum range "<<m_pars.wireGroupLayers.size());
300 return Amg::Vector3D::Zero();
301
302 }
303
304 Amg::Vector3D wirerightEdge{Amg::Vector3D::Zero()};
305 Amg::Vector2D localwirerightEdge{Amg::Vector2D::Zero()};
306 std::optional<Amg::Vector2D> wirerightedgeOpt = wireDesign(measHash).rightEdge(channelNumber(measHash));
307 localwirerightEdge = std::move(*wirerightedgeOpt);
308 wirerightEdge.block<2,1>(0,0) = std::move(localwirerightEdge);
309
310 return localToGlobalTrans(ctx, lHash)*wirerightEdge;
311
312 }
313
314 ATH_MSG_FATAL(__FILE__<<":"<<__LINE__<<" The layer hash "<<layIdx
315 <<" is not valid Type "<< chType(measHash));
316 return Amg::Vector3D::Zero();
317
318
319}
320
322 if(std::abs(m_idHelper.stationEta(identify())) != 1 ) return false; // if we are not in a Q1 ro element we do not have to check further
323 const WireGroupDesign& design = wireDesign(measurementHash); // function is not checking for channel type so we just use its gas gap info
324
325 double lpos = (chType(measurementHash) == ReadoutChannelType::Strip ? localPosition.x() : localPosition.y() );
326 if (lpos < design.halfWidth() - design.wireCutout()) return true;
327 return false;
328}
329
330
331} // namespace MuonGMR4
Scalar mag() const
mag method
constexpr std::array< T, N > make_array(const T &def_val)
Helper function to initialize in-place arrays with non-zero values.
Definition ArrayHelper.h:10
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
This is a "hash" representation of an Identifier.
Amg::Vector3D center(const ActsTrk::GeometryContext &ctx) const
Returns the detector center (Which is the same as the detector center of the first measurement layer)
const Amg::Transform3D & localToGlobalTrans(const ActsTrk::GeometryContext &ctx) const
Returns the local to global transformation into the ATLAS coordinate system.
StatusCode planeSurfaceFactory(const IdentifierHash &hash, std::shared_ptr< const Acts::PlanarBounds > pBounds)
Identifier identify() const override final
Return the athena identifier.
const Muon::IMuonIdHelperSvc * idHelperSvc() const
Returns the pointer to the muonIdHelperSvc.
StatusCode insertTransform(const IdentifierHash &hash)
Inserts a transfomration for caching.
static IdentifierHash geoTransformHash()
Returns the hash that is associated with the surface cache holding the transformation that is placing...
std::pair< int, int > channelNumber(const Amg::Vector2D &hitPos) const
Function to retrieve the pad eta and phi given a local position coordinate.
Amg::Vector2D stripPosition(int stripNum) const override final
Override from stripDesign. This function will give the center of the pad by taking the sequential cha...
double halfWidth() const
Returns the half height of the strip panel.
CheckVector2D center(int stripNumb) const
Returns the bisector of the strip (Global numbering scheme)
CheckVector2D leftEdge(int stripNumb) const
Returns the left edge of the strip (Global numbering scheme)
const Amg::Vector2D & firstStripPos() const
Vector indicating the first strip position.
double stripPitch() const
Distance between two adjacent strips.
double stripWidth() const
Width of a strip.
double shortHalfHeight() const
Returns the shorter half height of the panel.
CheckVector2D rightEdge(int stripNumb) const
Returns the right edge of the strip (Global numbering scheme)
double longHalfHeight() const
Returns the longer half height of the panel.
virtual int numStrips() const
Number of strips on the panel.
The StripLayer interfaces the 2D description of the strip plane layout with the 3D description of the...
Definition StripLayer.h:19
const Amg::Transform3D & toOrigin() const
Returns the transformation to go from the strip layer center to the origin of the Strip chamber.
unsigned int numWiresInGroup(unsigned int groupNum) const
Returns the number of wires in a given group.
double wireCutout() const
Extract the wireCutout for a wireGroup layer.
Amg::Vector2D localChannelPosition(const Identifier &measId) const
Returns the local pad/strip/wireGroup position.
Amg::Vector3D globalChannelPosition(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the global pad/strip/wireGroup position.
IdentifierHash measurementHash(const Identifier &measId) const override final
Constructs the identifier hash from the full measurement Identifier.
localCornerArray localPadCorners(const Identifier &measId) const
Amg::Vector3D leftStripEdge(const ActsTrk::GeometryContext &ctx, const IdentifierHash &measHash) const
const StripLayer & stripLayer(const Identifier &measId) const
const WireGroupDesign & wireDesign(const Identifier &measId) const
Retrieves the readoutElement Layer given the Identifier/Hash.
double firstStripPitch(const Identifier &measId) const
Gas Gaps.
static IdentifierHash createHash(const unsigned int gasGap, const unsigned int channelType, const unsigned int channel, const unsigned int wireInGrp=0)
Create a measurement hash from the Identifier fields.
const PadDesign & padDesign(const Identifier &measId) const
Retrieves the readoutElement Layer given the Identifier/Hash.
globalCornerArray globalPadCorners(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
unsigned int padPhi(const Identifier &measId) const
Returns the Phi index of the pad for the given pad identifier.
int multilayer() const
Returns the multilayer of the sTgcReadoutElement.
static unsigned int gasGapNumber(const IdentifierHash &measHash)
Returns the gasGap (0 to 3) for a given identifierHash.
std::array< Amg::Vector3D, 4 > globalCornerArray
Returns an array of four 3D vectors representing corner positions of the pads.
std::array< Amg::Vector2D, 4 > localCornerArray
Returns an array of four 2D vectors representing corner positions of the pads.
static unsigned int channelNumber(const IdentifierHash &measHash)
Returns channel position for a given identifierHash.
Identifier measurementId(const IdentifierHash &measHash) const override final
Converts the measurement hash back to the full Identifier.
const StripDesign & stripDesign(const Identifier &measId) const
Retrieves the readoutElement Layer given the Identifier/Hash.
Amg::Vector3D rightStripEdge(const ActsTrk::GeometryContext &ctx, const IdentifierHash &measHash) const
bool isEtaZero(const IdentifierHash &measurementHash, const Amg::Vector2D &localPosition) const
int padNumber(const Amg::Vector2D &hitPos, const Identifier &measId) const
Returns the pad Number given local position of hit and Identifier/Hash.
IdentifierHash layerHash(const Identifier &measId) const override final
Transforms the Identifier into a layer hash.
unsigned int padEta(const Identifier &measId) const
Returns the Eta index of the pad for the given pad identifier.
Amg::Transform3D fromGapToChamOrigin(const IdentifierHash &layerHash) const
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
The ReadoutGeomCnvAlg converts the Run4 Readout geometry build from the GeoModelXML into the legacy M...
std::ostream & operator<<(std::ostream &ostr, const Chamber::defineArgs &args)
Definition Chamber.cxx:14
std::string toString(const MuonGMR4::MuonReadoutElement *re)
MmReadoutElement::parameterBook parameterBook
STL namespace.