ATLAS Offline Software
Loading...
Searching...
No Matches
MuonPhaseII/MuonDetDescr/MuonGeoModelTestR4/src/GeoModelsTgcTest.cxx
Go to the documentation of this file.
1
2/*
3 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
4*/
5#include "GeoModelsTgcTest.h"
9#include <fstream>
10
11using namespace ActsTrk;
12namespace MuonGMR4{
13
15 ATH_CHECK(m_idHelperSvc.retrieve());
16 ATH_CHECK(m_geoCtxKey.initialize());
18 ATH_CHECK(m_tree.init(this));
19
20 const sTgcIdHelper& idHelper{m_idHelperSvc->stgcIdHelper()};
21 auto translateTokenList = [this, &idHelper](const std::vector<std::string>& chNames){
22
23 std::set<Identifier> transcriptedIds{};
24 for (const std::string& token : chNames) {
25 if (token.size() != 6) {
26 ATH_MSG_WARNING("Wrong format given for "<<token<<". Expecting 6 characters");
27 continue;
28 }
30 const std::string statName = token.substr(0, 3);
31 const unsigned statEta = std::atoi(token.substr(3, 1).c_str()) * (token[4] == 'A' ? 1 : -1);
32 const unsigned statPhi = std::atoi(token.substr(5, 1).c_str());
33 bool isValid{false};
34 const Identifier eleId = idHelper.elementID(statName, statEta, statPhi, isValid);
35 if (!isValid) {
36 ATH_MSG_WARNING("Failed to deduce a station name for " << token);
37 continue;
38 }
39 transcriptedIds.insert(eleId);
40 const Identifier secMlId = idHelper.multilayerID(eleId, 2, isValid);
41 if (isValid){
42 transcriptedIds.insert(secMlId);
43 }
44 }
45 return transcriptedIds;
46 };
47
48 std::vector <std::string>& selectedSt = m_selectStat.value();
49 const std::vector <std::string>& excludedSt = m_excludeStat.value();
50 selectedSt.erase(std::remove_if(selectedSt.begin(), selectedSt.end(),
51 [&excludedSt](const std::string& token){
52 return std::ranges::find(excludedSt, token) != excludedSt.end();
53 }), selectedSt.end());
54
55 if (selectedSt.size()) {
56 m_testStations = translateTokenList(selectedSt);
57 std::stringstream sstr{};
58 for (const Identifier& id : m_testStations) {
59 sstr<<" *** "<<m_idHelperSvc->toString(id)<<std::endl;
60 }
61 ATH_MSG_INFO("Test only the following stations "<<std::endl<<sstr.str());
62 } else {
63 const std::set<Identifier> excluded = translateTokenList(excludedSt);
65 for(auto itr = idHelper.detectorElement_begin();
66 itr!= idHelper.detectorElement_end();++itr){
67 if (!excluded.count(*itr)) {
68 m_testStations.insert(*itr);
69 }
70 }
72 if (!excluded.empty()) {
73 std::stringstream excluded_report{};
74 for (const Identifier& id : excluded){
75 excluded_report << " *** " << m_idHelperSvc->toStringDetEl(id) << std::endl;
76 }
77 ATH_MSG_INFO("Test all station except the following excluded ones " << std::endl << excluded_report.str());
78 }
79 }
80 ATH_CHECK(detStore()->retrieve(m_detMgr));
81 return StatusCode::SUCCESS;
82}
84 ATH_CHECK(m_tree.write());
85 return StatusCode::SUCCESS;
86}
88 const EventContext& ctx{Gaudi::Hive::currentContext()};
89
90 const ActsTrk::GeometryContext* geoContextHandle{nullptr};
91 ATH_CHECK(SG::get(geoContextHandle, m_geoCtxKey, ctx));
92 const ActsTrk::GeometryContext& gctx{*geoContextHandle};
93
94
95 for (const Identifier& test_me : m_testStations) {
96 ATH_MSG_DEBUG("Test retrieval of sTgc detector element "<<m_idHelperSvc->toStringDetEl(test_me));
97 const sTgcReadoutElement* reElement = m_detMgr->getsTgcReadoutElement(test_me);
98 if (!reElement) {
99 continue;
100 }
102 if (m_idHelperSvc->stgcIdHelper().elementID(reElement->identify()) != m_idHelperSvc->stgcIdHelper().elementID(test_me)) {
103 ATH_MSG_FATAL("Expected to retrieve "<<m_idHelperSvc->toString(test_me)
104 <<". But got instead "<<m_idHelperSvc->toString(reElement->identify()));
105 return StatusCode::FAILURE;
106 }
107 ATH_CHECK(dumpToTree(ctx,gctx,reElement));
108 const Amg::Transform3D globToLocal{reElement->globalToLocalTrans(gctx)};
109 const Amg::Transform3D& localToGlob{reElement->localToGlobalTrans(gctx)};
111 const Amg::Transform3D transClosure = globToLocal * localToGlob;
112 for (Amg::Vector3D axis :{Amg::Vector3D::UnitX(),Amg::Vector3D::UnitY(),Amg::Vector3D::UnitZ()}) {
113 const double closure_mag = std::abs( (transClosure*axis).dot(axis) - 1.);
114 if (closure_mag > std::numeric_limits<float>::epsilon() ) {
115 ATH_MSG_FATAL("Closure test failed for "<<m_idHelperSvc->toStringDetEl(test_me)<<" and axis "<<Amg::toString(axis, 0)
116 <<". Ended up with "<< Amg::toString(transClosure*axis) );
117 return StatusCode::FAILURE;
118 }
119 }
120 const sTgcIdHelper& id_helper{m_idHelperSvc->stgcIdHelper()};
121 for (unsigned int layer = 1; layer <= reElement->numLayers(); ++layer) {
123 bool isValidLay{false};
124 const Identifier layID = id_helper.channelID(reElement->identify(),
125 reElement->multilayer(),
126 layer, chType, 1, isValidLay);
127 if (!isValidLay) {
128 continue;
129 }
130 const unsigned int numChannel = reElement->numChannels(layID);
131
132 for (unsigned int channel = 1; channel < numChannel ; ++channel) {
133 bool isValidCh{false};
134 const Identifier chID = id_helper.channelID(reElement->identify(),
135 reElement->multilayer(),
136 layer, chType, channel, isValidCh);
137 if (!isValidCh) {
138 continue;
139 }
141 const IdentifierHash measHash = reElement->measurementHash(chID);
142 const IdentifierHash layHash = reElement->layerHash(chID);
143 ATH_MSG_VERBOSE("layer: "<<layer<<", chType: "<<chType
144 <<" --> layerHash: "<<static_cast<unsigned>(layHash));
145 const Identifier backCnv = reElement->measurementId(measHash);
146 if (backCnv != chID) {
147 ATH_MSG_FATAL("The back and forth conversion of "<<m_idHelperSvc->toString(chID)
148 <<" failed. Got "<<m_idHelperSvc->toString(backCnv));
149 return StatusCode::FAILURE;
150 }
151 if (layHash != reElement->layerHash(measHash)) {
152 ATH_MSG_FATAL("Constructing the layer hash from the identifier "<<
153 m_idHelperSvc->toString(chID)<<" leads to different layer hashes "<<
154 layHash<<" vs. "<< reElement->layerHash(measHash));
155 return StatusCode::FAILURE;
156 }
158 ATH_MSG_VERBOSE("Channel "<<m_idHelperSvc->toString(chID)<<" strip position "
159 <<Amg::toString(reElement->globalChannelPosition(gctx, measHash)));
160 }
162 ATH_MSG_VERBOSE("Channel "<<m_idHelperSvc->toString(chID)<<" wireGroup position "
163 <<Amg::toString(reElement->globalChannelPosition(gctx, measHash)));
164 }
166 ATH_MSG_VERBOSE("Channel "<<m_idHelperSvc->toString(chID)<<" Pad position "
167 <<Amg::toString(reElement->globalChannelPosition(gctx, measHash)));
168 }
169 }
170 }
171 }
172
173 }
174 return StatusCode::SUCCESS;
175}
176
177StatusCode GeoModelsTgcTest::dumpToTree(const EventContext& ctx,
178 const ActsTrk::GeometryContext& gctx,
179 const sTgcReadoutElement* reElement){
180
181 m_stIndex = reElement->stationName();
182 m_stEta = reElement->stationEta();
183 m_stPhi = reElement->stationPhi();
184 m_stML = reElement->multilayer();
185 m_chamberDesign = reElement->chamberDesign();
187 m_numLayers = reElement->numLayers();
188 m_gasTck = reElement->gasGapThickness();
190 m_sChamberLength = reElement->sChamberLength();
191 m_lChamberLength = reElement->lChamberLength();
192 m_chamberHeight = reElement->chamberHeight();
193
195 const Amg::Transform3D& transform{reElement->localToGlobalTrans(gctx)};
196 m_readoutTransform = transform;
197 m_alignableNode = reElement->alignableTransform()->getDefTransform();
198
199 const sTgcIdHelper& id_helper{m_idHelperSvc->stgcIdHelper()};
200 for (unsigned int layer = 1; layer <= reElement->numLayers(); ++layer) {
202 unsigned int numWireGroup = 0;
204 bool isValidLay{false};
205 const Identifier layID = id_helper.channelID(reElement->identify(),
206 reElement->multilayer(),
207 layer, chType, 1, isValidLay);
208 if (!isValidLay) {
209 continue;
210 }
212
213 m_sGapLength = 2.*reElement->stripDesign(layID).shortHalfHeight();
214 m_lGapLength = 2.*reElement->stripDesign(layID).longHalfHeight();
215 m_sPadLength = 2.*reElement->padDesign(layID).shortHalfHeight();
216 m_lPadLength = 2.*reElement->padDesign(layID).longHalfHeight();
217 m_gapHeight =2.*reElement->stripDesign(layID).halfWidth();
218 m_yCutout = reElement->stripDesign(layID).yCutout();
219
220 switch (chType) {
222 m_numPads.push_back(reElement->numChannels(layID));
223 m_numPadEta.push_back(reElement->numPadEta(layID));
224 m_numPadPhi.push_back(reElement->numPadPhi(layID));
225 m_padPhiShift.push_back(reElement->padPhiShift(layID));
226 m_firstPadPhiDiv.push_back(reElement->padDesign(layID).firstPadPhiDiv());
227 m_anglePadPhi = reElement->anglePadPhi(layID);
228 m_beamlineRadius = reElement->beamlineRadius(layID);
229
230 for (unsigned int phiIndex = 1; phiIndex <= reElement->numPadPhi(layID); ++phiIndex) {
231 for(unsigned int etaIndex = 1; etaIndex <= reElement->numPadEta(layID); ++etaIndex) {
232 bool isValidPad{false};
233 const Identifier padID = id_helper.padID(reElement->identify(),
234 reElement->multilayer(),
235 layer, chType, etaIndex, phiIndex, isValidPad);
236 if (!isValidPad) {
237 ATH_MSG_WARNING("Invalid Identifier detected for readout element "
238 <<m_idHelperSvc->toStringDetEl(reElement->identify())
239 <<" layer: "<<layer<<" pad: ("<<etaIndex << ", " << phiIndex<<") channelType: "<<chType);
240 continue;
241 }
242 if (etaIndex == 1 && phiIndex == 1) {
243 m_firstPadHeight.push_back(reElement->padHeight(padID));
244 }
245 else if (etaIndex == 2 && phiIndex == 1) {
246 m_padHeight.push_back(reElement->padHeight(padID));
247 }
248 Amg::Vector2D localPadPos(Amg::Vector2D::Zero());
249 std::array<Amg::Vector2D,4> localPadCorners{make_array<Amg::Vector2D, 4>(Amg::Vector2D::Zero())};
250 Amg::Vector3D globalPadPos(Amg::Vector3D::Zero());
251 std::array<Amg::Vector3D,4> globalPadCorners{make_array<Amg::Vector3D, 4>(Amg::Vector3D::Zero())};
252
253 localPadPos = reElement->localChannelPosition(padID);
254 localPadCorners = reElement->localPadCorners(padID);
255
256 m_localPadPos.push_back(localPadPos);
257 m_localPadCornerBL.push_back(localPadCorners[0]);
258 m_localPadCornerBR.push_back(localPadCorners[1]);
259 m_localPadCornerTL.push_back(localPadCorners[2]);
260 m_localPadCornerTR.push_back(localPadCorners[3]);
261
262 Amg::Vector2D hitCorrection{-.1, -.1};
263 Amg::Vector2D hitPos = localPadCorners[3] + hitCorrection;
264 m_hitPosition.push_back(hitPos);
265 m_padNumber.push_back(reElement->padNumber(hitPos, padID));
266
267 globalPadPos = reElement->globalChannelPosition(gctx, padID);
268 globalPadCorners = reElement->globalPadCorners(gctx, padID);
269
270 m_globalPadPos.push_back(globalPadPos);
271 m_globalPadCornerBR.push_back(globalPadCorners[0]);
272 m_globalPadCornerBL.push_back(globalPadCorners[1]);
273 m_globalPadCornerTR.push_back(globalPadCorners[2]);
274 m_globalPadCornerTL.push_back(globalPadCorners[3]);
275
276 m_padEta.push_back(reElement->padEta(padID));
277 m_padPhi.push_back(reElement->padPhi(padID));
278 m_padGasGap.push_back(layer);
279
280 if (!(etaIndex == 1 && phiIndex == 1)) continue;
281 const Amg::Transform3D locToGlob = reElement->localToGlobalTrans(gctx, padID);
282 ATH_MSG_DEBUG("The local to global transformation on layers is: " << Amg::toString(locToGlob));
283 m_padRot.push_back(locToGlob);
284 m_padRotGasGap.push_back(layer);
285 }
286 }
287 break;
288
290 const StripDesign& design{reElement->stripDesign(layID)};
291 m_numStrips = design.numStrips();
292 m_stripPitch = design.stripPitch();
293 m_stripWidth = design.stripWidth();
294 for (unsigned int strip = 1; strip <= reElement->numChannels(layID); ++strip) {
295 bool isValidStrip{false};
296 const Identifier stripID = id_helper.channelID(reElement->identify(),
297 reElement->multilayer(),
298 layer, chType, strip, isValidStrip);
299 if (!isValidStrip) {
300 ATH_MSG_WARNING("Invalid Identifier detected for readout element "
301 <<m_idHelperSvc->toStringDetEl(reElement->identify())
302 <<" layer: "<<layer<<" strip: "<<strip<<" channelType: "<<chType);
303 continue;
304 }
305 m_localStripPos.push_back((reElement->localChannelPosition(stripID)).block<2,1>(0,0));
306 m_globalStripPos.push_back(reElement->globalChannelPosition(gctx, stripID));
307 m_stripGasGap.push_back(layer);
308 m_stripNum.push_back(strip);
309 m_stripLengths.push_back(reElement->stripLength(stripID));
310
311 if (strip != 1) continue;
312 const Amg::Transform3D locToGlob = reElement->localToGlobalTrans(gctx, stripID);
313 ATH_MSG_DEBUG("The local to global transformation on layers is: " << Amg::toString(locToGlob));
314 m_stripRot.push_back(locToGlob);
315 m_stripRotGasGap.push_back(layer);
316
317 }
318 break;
320 const WireGroupDesign& design{reElement->wireDesign(layID)};
322 numWireGroup = design.numStrips();
323 m_wirePitch = design.stripPitch();
324 m_wireWidth = design.stripWidth();
325 m_numWires.push_back(design.nAllWires());
326 m_firstWireGroupWidth.push_back(design.numWiresInGroup(1));
327 m_numWireGroups.push_back(numWireGroup);
328 m_wireCutout.push_back(design.wireCutout());
329 for (unsigned int wireGroup = 1; wireGroup <= numWireGroup; ++wireGroup) {
330 bool isValidWire{false};
331 const Identifier wireGroupID = id_helper.channelID(reElement->identify(),
332 reElement->multilayer(),
333 layer, chType, wireGroup, isValidWire);
334 if (!isValidWire) {
335 ATH_MSG_WARNING("Invalid Identifier detected for readout element "
336 <<m_idHelperSvc->toStringDetEl(reElement->identify())
337 <<" layer: "<<layer<<" wireGroup: "<<wireGroup<<" channelType: "<<chType);
338 continue;
339 }
340 m_localWireGroupPos.push_back(reElement->localChannelPosition(wireGroupID));
341 m_globalWireGroupPos.push_back(reElement->globalChannelPosition(gctx, wireGroupID));
342 m_wireGroupGasGap.push_back(layer);
343 m_wireGroupNum.push_back(wireGroup);
344
345 if (wireGroup != 1) continue;
346 const Amg::Transform3D locToGlob = reElement->localToGlobalTrans(gctx, wireGroupID);
347 ATH_MSG_DEBUG("The local to global transformation on layers is: " << Amg::toString(locToGlob));
348 m_wireGroupRot.push_back(locToGlob);
349 m_wireGroupRotGasGap.push_back(layer);
350 }
351 break;
352 }
353 }
354 }
355 }
356 return m_tree.fill(ctx) ? StatusCode::SUCCESS : StatusCode::FAILURE;
357}
358
359}
360
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_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
bool isValid(const T &p)
Av: we implement here an ATLAS-sepcific convention: all particles which are 99xxxxx are fine.
Definition AtlasPID.h:878
const ServiceHandle< StoreGateSvc > & detStore() const
This is a "hash" representation of an Identifier.
Gaudi::Property< std::vector< std::string > > m_selectStat
String should be formated like <stationName><stationEta><A/C><stationPhi>
MuonVal::CoordSystemsBranch m_stripRot
Rotation matrix of the respective strip layers.
StatusCode dumpToTree(const EventContext &ctx, const ActsTrk::GeometryContext &gctx, const sTgcReadoutElement *readoutEle)
MuonVal::CoordTransformBranch m_readoutTransform
Transformation of the readout element (Translation, ColX, ColY, ColZ)
std::set< Identifier > m_testStations
Set of stations to be tested.
MuonVal::ScalarBranch< float > & m_sGapLength
GasGap Lengths for debug.
MuonVal::ScalarBranch< float > & m_sChamberLength
Chamber Length for debug.
MuonVal::CoordSystemsBranch m_wireGroupRot
Rotation matrix of the respective wireGroup layers.
MuonVal::CoordSystemsBranch m_padRot
Rotation matrix of the respective pad layers.
MuonVal::ScalarBranch< short > & m_stIndex
Identifier of the readout element.
int stationEta() const
Returns the stationEta (positive A site, negative O site)
const Amg::Transform3D & localToGlobalTrans(const ActsTrk::GeometryContext &ctx) const
Returns the local to global transformation into the ATLAS coordinate system.
const std::string & chamberDesign() const
The chamber design refers to the construction parameters of a readout element.
Identifier identify() const override final
Return the athena identifier.
int stationName() const
Returns the stationName (BIS, BOS, etc) encoded into the integer.
int stationPhi() const
Returns the stationPhi (1-8) -> sector (2*phi - (isSmall))
const GeoAlignableTransform * alignableTransform() const
Returnsthe alignable transform of the readout element.
Amg::Transform3D globalToLocalTrans(const ActsTrk::GeometryContext &ctx) const
Transformations to translate between local <-> global coordinates.
double firstPadPhiDiv() const
Returns the angle of the first pad outer edge w.r.t. the gasGap center from the beamline.
double halfWidth() const
Returns the half height of the strip panel.
double yCutout() const
Returns the cutout of the diamond.
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.
double longHalfHeight() const
Returns the longer half height of the panel.
virtual int numStrips() const
Number of strips on the panel.
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.
unsigned int nAllWires() const
Returns the number of all wires.
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
const WireGroupDesign & wireDesign(const Identifier &measId) const
Retrieves the readoutElement Layer given the Identifier/Hash.
double stripLength(const Identifier &measId) const
Length of each strip.
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
double gasGapThickness() const
Returns the thickness of the gas gap.
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.
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.
unsigned int numPadPhi(const Identifier &measId) const
Returns the number of pads in the Phi direction in the given gasGap layer.
unsigned int numPadEta(const Identifier &measId) const
Returns the number of pads in the eta direction in the given layer.
double sChamberLength() const
Length of the chamber on the short side.
unsigned int numLayers() const
Returns the number of gas gap layers.
double padPhiShift(const Identifier &measId) const
Returns the staggering shift of inner pad edges in the phi direction.
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.
double chamberHeight() const
Height of the chamber.
double padHeight(const Identifier &measId) const
Returns the height of all the pads that are not adjacent to the bottom edge of the trapezoid active a...
double lChamberLength() const
Length of the chamber on the long side.
double anglePadPhi(const Identifier &measId) const
Returns the angular pitch of the pads in the phi direction.
unsigned int numChannels(const Identifier &measId) const
Returns the number of strips / wires / pads in a given gasGap.
double beamlineRadius(const Identifier &measId) const
Returns the distance between the gasGap center and the beamline.
const_id_iterator detectorElement_begin() const
Iterators over full set of ids.
const_id_iterator detectorElement_end() const
Identifier elementID(int stationName, int stationEta, int stationPhi) const
Identifier padID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int channelType, int padEta, int padPhi) const
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int channelType, int channel) const
Identifier multilayerID(const Identifier &channeldID) 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...
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
Definition dot.py:1
DataModel_detail::iterator< DVL > remove_if(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end, Predicate pred)
Specialization of remove_if for DataVector/List.