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 const sTgcIdHelper& id_helper{m_idHelperSvc->stgcIdHelper()};
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 (id_helper.elementID(reElement->identify()) != id_helper.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->globalToLocalTransform(gctx)};
109 const Amg::Transform3D& localToGlob{reElement->localToGlobalTransform(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
121 for (unsigned int layer = 1; layer <= reElement->numLayers(); ++layer) {
125 bool isValidLay{false};
126 const Identifier layID = id_helper.channelID(reElement->identify(),
127 reElement->multilayer(),
128 layer, chType, 1, isValidLay);
129 if (!isValidLay) {
130 continue;
131 }
132 const unsigned int numChannel = reElement->numChannels(reElement->measurementHash(layID));
133
134 for (unsigned int channel = 1; channel < numChannel ; ++channel) {
135 bool isValidCh{false};
136 const Identifier chID = id_helper.channelID(reElement->identify(),
137 reElement->multilayer(),
138 layer, chType, channel, isValidCh);
139 if (!isValidCh) {
140 continue;
141 }
143 const IdentifierHash measHash = reElement->measurementHash(chID);
144 const IdentifierHash layHash = reElement->layerHash(chID);
145 ATH_MSG_VERBOSE("layer: "<<layer<<", chType: "<<chType
146 <<" --> layerHash: "<<static_cast<unsigned>(layHash));
147 const Identifier backCnv = reElement->measurementId(measHash);
148 if (backCnv != chID) {
149 ATH_MSG_FATAL("The back and forth conversion of "<<m_idHelperSvc->toString(chID)
150 <<" failed. Got "<<m_idHelperSvc->toString(backCnv));
151 return StatusCode::FAILURE;
152 }
153 if (layHash != reElement->layerHash(measHash)) {
154 ATH_MSG_FATAL("Constructing the layer hash from the identifier "<<
155 m_idHelperSvc->toString(chID)<<" leads to different layer hashes "<<
156 layHash<<" vs. "<< reElement->layerHash(measHash));
157 return StatusCode::FAILURE;
158 }
159 ATH_MSG_VERBOSE("Channel "<<m_idHelperSvc->toString(chID)<<" channel position "
160 <<Amg::toString(reElement->globalChannelPosition(gctx, measHash)));
161 }
162 }
163 }
164 }
165 return StatusCode::SUCCESS;
166}
167
168StatusCode GeoModelsTgcTest::dumpToTree(const EventContext& ctx,
169 const ActsTrk::GeometryContext& gctx,
170 const sTgcReadoutElement* reElement){
171
172 m_stIndex = reElement->stationName();
173 m_stEta = reElement->stationEta();
174 m_stPhi = reElement->stationPhi();
175 m_stML = reElement->multilayer();
176 m_chamberDesign = reElement->chamberDesign();
178 m_numLayers = reElement->numLayers();
179 m_gasTck = reElement->gasGapThickness();
181 m_sChamberLength = reElement->sChamberLength();
182 m_lChamberLength = reElement->lChamberLength();
183 m_chamberHeight = reElement->chamberHeight();
184
186 const Amg::Transform3D& transform{reElement->localToGlobalTransform(gctx)};
187 m_readoutTransform = transform;
188 m_alignableNode = reElement->alignableTransform()->getDefTransform();
189
190 const sTgcIdHelper& id_helper{m_idHelperSvc->stgcIdHelper()};
191 for (unsigned int layer = 1; layer <= reElement->numLayers(); ++layer) {
195 unsigned int numWireGroup = 0;
197 bool isValidLay{false};
198 const Identifier layID = id_helper.channelID(reElement->identify(),
199 reElement->multilayer(),
200 layer, chType, 1, isValidLay);
201 if (!isValidLay) {
202 continue;
203 }
205 const IdentifierHash layHash = reElement->measurementHash(layID);
206 m_sGapLength = 2.*reElement->stripDesign(layHash).shortHalfHeight();
207 m_lGapLength = 2.*reElement->stripDesign(layHash).longHalfHeight();
208 m_sPadLength = 2.*reElement->padDesign(layHash).shortHalfHeight();
209 m_lPadLength = 2.*reElement->padDesign(layHash).longHalfHeight();
210 m_gapHeight =2.*reElement->stripDesign(layHash).halfWidth();
211 m_yCutout = reElement->stripDesign(layHash).yCutout();
212
213 switch (chType) {
215 m_numPads.push_back(reElement->numChannels(layHash));
216 m_numPadEta.push_back(reElement->numPadEta(layHash));
217 m_numPadPhi.push_back(reElement->numPadPhi(layHash));
218 m_padPhiShift.push_back(reElement->padPhiShift(layHash));
219 m_firstPadPhiDiv.push_back(reElement->padDesign(layHash).firstPadPhiDiv());
220 m_anglePadPhi = reElement->anglePadPhi(layHash);
221 m_beamlineRadius = reElement->beamlineRadius(layHash);
222
223 for (unsigned int phiIndex = 1; phiIndex <= reElement->numPadPhi(layHash); ++phiIndex) {
224 for(unsigned int etaIndex = 1; etaIndex <= reElement->numPadEta(layHash); ++etaIndex) {
225 bool isValidPad{false};
226 const Identifier padID = id_helper.padID(reElement->identify(),
227 reElement->multilayer(),
228 layer, chType, etaIndex, phiIndex, isValidPad);
229 if (!isValidPad) {
230 ATH_MSG_WARNING("Invalid Identifier detected for readout element "
231 <<m_idHelperSvc->toStringDetEl(reElement->identify())
232 <<" layer: "<<layer<<" pad: ("<<etaIndex << ", " << phiIndex<<") channelType: "<<chType);
233 continue;
234 }
235 const IdentifierHash padIDHash = reElement->measurementHash(padID);
236 if (etaIndex == 1 && phiIndex == 1) {
237 m_firstPadHeight.push_back(reElement->padHeight(padIDHash));
238 } else if (etaIndex == 2 && phiIndex == 1) {
239 m_padHeight.push_back(reElement->padHeight(padIDHash));
240 }
241 Amg::Vector2D localPadPos(Amg::Vector2D::Zero());
242 std::array<Amg::Vector2D,4> localPadCorners{make_array<Amg::Vector2D, 4>(Amg::Vector2D::Zero())};
243 Amg::Vector3D globalPadPos(Amg::Vector3D::Zero());
244 std::array<Amg::Vector3D,4> globalPadCorners{make_array<Amg::Vector3D, 4>(Amg::Vector3D::Zero())};
245
246 localPadPos = reElement->localChannelPosition(padIDHash);
247 localPadCorners = reElement->localPadCorners(padIDHash);
248
249 m_localPadPos.push_back(localPadPos);
250 m_localPadCornerBL.push_back(localPadCorners[0]);
251 m_localPadCornerBR.push_back(localPadCorners[1]);
252 m_localPadCornerTL.push_back(localPadCorners[2]);
253 m_localPadCornerTR.push_back(localPadCorners[3]);
254
255 Amg::Vector2D hitCorrection{-.1, -.1};
256 ATH_MSG_VERBOSE("BL: "<<Amg::toString(localPadCorners[0])
257 <<", BR: "<<Amg::toString(localPadCorners[1])
258 <<", UL: "<<Amg::toString(localPadCorners[2])
259 <<", UR: "<<Amg::toString(localPadCorners[3]));
260 Amg::Vector2D hitPos = localPadCorners[3] + hitCorrection;
261 m_hitPosition.push_back(hitPos);
262 m_padNumber.push_back(reElement->padNumber(hitPos, padIDHash));
263
264 globalPadPos = reElement->globalChannelPosition(gctx, padIDHash);
265 globalPadCorners = reElement->globalPadCorners(gctx, padIDHash);
266
267 m_globalPadPos.push_back(globalPadPos);
268 m_globalPadCornerBR.push_back(globalPadCorners[0]);
269 m_globalPadCornerBL.push_back(globalPadCorners[1]);
270 m_globalPadCornerTR.push_back(globalPadCorners[2]);
271 m_globalPadCornerTL.push_back(globalPadCorners[3]);
272
273 m_padEta.push_back(reElement->padEta(padIDHash));
274 m_padPhi.push_back(reElement->padPhi(padIDHash));
275 m_padGasGap.push_back(layer);
276
277 if (!(etaIndex == 1 && phiIndex == 1)) continue;
278 const Amg::Transform3D locToGlob = reElement->localToGlobalTransform(gctx,
279 reElement->layerHash(padIDHash));
280 ATH_MSG_DEBUG("The local to global transformation on layers is: " << Amg::toString(locToGlob));
281 m_padRot.push_back(locToGlob);
282 m_padRotGasGap.push_back(layer);
283 }
284 }
285 break;
287 const StripDesign& design{reElement->stripDesign(layHash)};
288 m_numStrips = design.numStrips();
289 m_stripPitch = design.stripPitch();
290 m_stripWidth = design.stripWidth();
291 for (unsigned int strip = 1; strip <= reElement->numChannels(layHash); ++strip) {
292 bool isValidStrip{false};
293 const Identifier stripID = id_helper.channelID(reElement->identify(),
294 reElement->multilayer(),
295 layer, chType, strip, isValidStrip);
296 if (!isValidStrip) {
297 ATH_MSG_WARNING("Invalid Identifier detected for readout element "
298 <<m_idHelperSvc->toStringDetEl(reElement->identify())
299 <<" layer: "<<layer<<" strip: "<<strip<<" channelType: "<<chType);
300 continue;
301 }
302 const IdentifierHash stripHash = reElement->measurementHash(stripID);
303 m_localStripPos.push_back(reElement->localChannelPosition(stripHash));
304 m_globalStripPos.push_back(reElement->globalChannelPosition(gctx, stripHash));
305 m_stripGasGap.push_back(layer);
306 m_stripNum.push_back(strip);
307 m_stripLengths.push_back(reElement->stripLength(stripHash));
308
309 if (strip != 1) continue;
310 const Amg::Transform3D locToGlob = reElement->localToGlobalTransform(gctx,
311 reElement->layerHash(stripHash));
312 ATH_MSG_DEBUG("The local to global transformation on layers is: " << Amg::toString(locToGlob));
313 m_stripRot.push_back(locToGlob);
314 m_stripRotGasGap.push_back(layer);
315
316 }
317 break;
319 const WireGroupDesign& design{reElement->wireDesign(layHash)};
321 numWireGroup = design.numStrips();
322 m_wirePitch = design.stripPitch();
323 m_wireWidth = design.stripWidth();
324 m_numWires.push_back(design.nAllWires());
325 m_firstWireGroupWidth.push_back(design.numWiresInGroup(1));
326 m_numWireGroups.push_back(numWireGroup);
327 m_wireCutout.push_back(design.wireCutout());
328 for (unsigned int wireGroup = 1; wireGroup <= numWireGroup; ++wireGroup) {
329 bool isValidWire{false};
330 const Identifier wireGroupID = id_helper.channelID(reElement->identify(),
331 reElement->multilayer(),
332 layer, chType, wireGroup, isValidWire);
333 if (!isValidWire) {
334 ATH_MSG_WARNING("Invalid Identifier detected for readout element "
335 <<m_idHelperSvc->toStringDetEl(reElement->identify())
336 <<" layer: "<<layer<<" wireGroup: "<<wireGroup<<" channelType: "<<chType);
337 continue;
338 }
339 const IdentifierHash wireGroupHash = reElement->measurementHash(wireGroupID);
340 m_localWireGroupPos.push_back(reElement->localChannelPosition(wireGroupHash));
341 m_globalWireGroupPos.push_back(reElement->globalChannelPosition(gctx, wireGroupHash));
342 m_wireGroupGasGap.push_back(layer);
343 m_wireGroupNum.push_back(wireGroup);
344
345 if (wireGroup != 1) continue;
346 const Amg::Transform3D locToGlob = reElement->localToGlobalTransform(gctx,
347 reElement->layerHash(wireGroupHash));
348 ATH_MSG_DEBUG("The local to global transformation on layers is: " << Amg::toString(locToGlob));
349 m_wireGroupRot.push_back(locToGlob);
350 m_wireGroupRotGasGap.push_back(layer);
351 }
352 break;
353 }
354 }
355 }
356 }
357 return m_tree.fill(ctx) ? StatusCode::SUCCESS : StatusCode::FAILURE;
358}
359
360}
361
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.
const Amg::Transform3D & localToGlobalTransform(const ActsTrk::GeometryContext &ctx) const
Returns the transformation from the local coordinate system of the readout element into the global AT...
int stationEta() const
Returns the stationEta (positive A site, negative C site)
Amg::Transform3D globalToLocalTransform(const ActsTrk::GeometryContext &ctx) const
Returns the transformation from the global ATLAS coordinate system into the local coordinate system o...
const std::string & chamberDesign() const
The chamber design refers to the construction parameters of a readout element.
Identifier identify() const override final
Return the ATLAS 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
Return the alignable transform node of the readout element.
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.
unsigned numChannels(const IdentifierHash &measHash) const
Returns the number of strips / wires / pads in a given gasGap.
IdentifierHash measurementHash(const Identifier &measId) const override final
Constructs the identifier hash from the full measurement Identifier.
const PadDesign & padDesign(const IdentifierHash &measHash) const
Retrieves the readoutElement Layer given the Identifier/Hash.
double padHeight(const IdentifierHash &measHash) const
Returns the height of all the pads that are not adjacent to the bottom edge of the trapezoid active a...
unsigned padEta(const IdentifierHash &measHash) const
Returns the Eta index of the pad for the given pad identifier.
double gasGapThickness() const
Returns the thickness of the gas gap.
int multilayer() const
Returns the multilayer of the sTgcReadoutElement.
localCornerArray localPadCorners(const IdentifierHash &measHash) const
double stripLength(const IdentifierHash &measHash) const
Length of each strip.
Identifier measurementId(const IdentifierHash &measHash) const override final
Converts the measurement hash back to the full Identifier.
double padPhiShift(const IdentifierHash &measHash) const
Returns the staggering shift of inner pad edges in the phi direction.
int padNumber(const Amg::Vector2D &hitPos, const IdentifierHash &measHash) const
Returns the pad Number given local position of hit and Identifier/Hash.
double sChamberLength() const
Length of the chamber on the short side.
const StripDesign & stripDesign(const IdentifierHash &measHash) const
Retrieves the readoutElement Layer given the Identifier/Hash.
globalCornerArray globalPadCorners(const ActsTrk::GeometryContext &ctx, const IdentifierHash &measHash) const
unsigned numLayers() const
Returns the number of gas gap layers.
double anglePadPhi(const IdentifierHash &measHash) const
Returns the angular pitch of the pads in the phi direction.
IdentifierHash layerHash(const Identifier &measId) const override final
Transforms the Identifier into a layer hash.
unsigned numPadEta(const IdentifierHash &measHash) const
Returns the number of pads in the eta direction in the given layer.
unsigned padPhi(const IdentifierHash &measHash) const
Returns the Phi index of the pad for the given pad identifier.
double beamlineRadius(const IdentifierHash &measHash) const
Returns the distance between the gasGap center and the beamline.
double chamberHeight() const
Height of the chamber.
double lChamberLength() const
Length of the chamber on the long side.
Amg::Vector3D globalChannelPosition(const ActsTrk::GeometryContext &ctx, const IdentifierHash &measHash) const
Returns the global pad/strip/wireGroup position.
unsigned numPadPhi(const IdentifierHash &measHash) const
Returns the number of pads in the Phi direction in the given gasGap layer.
Amg::Vector2D localChannelPosition(const IdentifierHash &measHash) const
Returns the local position of the measurement in the repsective frame.
const WireGroupDesign & wireDesign(const IdentifierHash &measHash) const
Retrieves the readoutElement Layer given the Identifier/Hash.
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.