ATLAS Offline Software
Loading...
Searching...
No Matches
MuonDetDescr/MuonGeoModelTest/src/GeoModelsTgcTest.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4#include "GeoModelsTgcTest.h"
5
6#include <fstream>
7#include <iostream>
8
12#include "GeoModelKernel/GeoDefinitions.h"
14#include "GaudiKernel/SystemOfUnits.h"
15
16namespace MuonGM {
17
18
20 ATH_CHECK(m_tree.write());
21 return StatusCode::SUCCESS;
22}
24 ATH_CHECK(m_detMgrKey.initialize());
25 ATH_CHECK(m_idHelperSvc.retrieve());
26 ATH_CHECK(m_tree.init(this));
27 const sTgcIdHelper& idHelper{m_idHelperSvc->stgcIdHelper()};
28 auto translateTokenList = [this, &idHelper](const std::vector<std::string>& chNames){
29
30 std::set<Identifier> transcriptedIds{};
31 for (const std::string& token : chNames) {
32 if (token.size() != 6) {
33 ATH_MSG_WARNING("Wrong format given for "<<token<<". Expecting 6 characters");
34 continue;
35 }
37 const std::string statName = token.substr(0, 3);
38 const unsigned statEta = std::atoi(token.substr(3, 1).c_str()) * (token[4] == 'A' ? 1 : -1);
39 const unsigned statPhi = std::atoi(token.substr(5, 1).c_str());
40 bool isValid{false};
41 const Identifier eleId = idHelper.elementID(statName, statEta, statPhi, isValid);
42 if (!isValid) {
43 ATH_MSG_WARNING("Failed to deduce a station name for " << token);
44 continue;
45 }
46 transcriptedIds.insert(eleId);
47 const Identifier secMlId = idHelper.multilayerID(eleId, 2, isValid);
48 if (isValid){
49 transcriptedIds.insert(secMlId);
50 }
51 }
52 return transcriptedIds;
53 };
54
55 std::vector <std::string>& selectedSt = m_selectStat.value();
56 const std::vector <std::string>& excludedSt = m_excludeStat.value();
57 selectedSt.erase(std::remove_if(selectedSt.begin(), selectedSt.end(),
58 [&excludedSt](const std::string& token){
59 return std::ranges::find(excludedSt, token) != excludedSt.end();
60 }), selectedSt.end());
61
62 if (selectedSt.size()) {
63 m_testStations = translateTokenList(selectedSt);
64 std::stringstream sstr{};
65 for (const Identifier& id : m_testStations) {
66 sstr<<" *** "<<m_idHelperSvc->toString(id)<<std::endl;
67 }
68 ATH_MSG_INFO("Test only the following stations "<<std::endl<<sstr.str());
69 } else {
70 const std::set<Identifier> excluded = translateTokenList(excludedSt);
72 for(auto itr = idHelper.detectorElement_begin();
73 itr!= idHelper.detectorElement_end();++itr){
74 if (!excluded.count(*itr)) {
75 m_testStations.insert(*itr);
76 }
77 }
79 if (!excluded.empty()) {
80 std::stringstream excluded_report{};
81 for (const Identifier& id : excluded){
82 excluded_report << " *** " << m_idHelperSvc->toStringDetEl(id) << std::endl;
83 }
84 ATH_MSG_INFO("Test all station except the following excluded ones " << std::endl << excluded_report.str());
85 }
86 }
87 return StatusCode::SUCCESS;
88}
89StatusCode GeoModelsTgcTest::execute(const EventContext& ctx) {
91 if (!detMgr.isValid()) {
92 ATH_MSG_FATAL("Failed to retrieve MuonDetectorManager "
93 << m_detMgrKey.fullKey());
94 return StatusCode::FAILURE;
95 }
96 for (const Identifier& test_me : m_testStations) {
97 ATH_MSG_VERBOSE("Test retrieval of sTgc detector element "
98 << m_idHelperSvc->toStringDetEl(test_me));
99 const sTgcReadoutElement* reElement = detMgr->getsTgcReadoutElement(test_me);
100 if (!reElement) {
101 ATH_MSG_VERBOSE("Detector element is invalid");
102 continue;
103 }
105 if (m_idHelperSvc->toStringDetEl(reElement->identify()) != m_idHelperSvc->toStringDetEl(test_me)) {
106 ATH_MSG_FATAL("Expected to retrieve "
107 << m_idHelperSvc->toStringDetEl(test_me) << ". But got instead "
108 << m_idHelperSvc->toStringDetEl(reElement->identify()));
109 return StatusCode::FAILURE;
110 }
111 ATH_CHECK(dumpToTree(ctx, reElement));
112 }
113 return StatusCode::SUCCESS;
114}
115StatusCode GeoModelsTgcTest::dumpToTree(const EventContext& ctx, const sTgcReadoutElement* roEl) {
116 const sTgcIdHelper& id_helper{m_idHelperSvc->stgcIdHelper()};
117
118 const Amg::Transform3D permute{GeoTrf::GeoRotation{90.*Gaudi::Units::deg,90.*Gaudi::Units::deg, 0.}};
119 m_alignableNode = roEl->AmdbLRSToGlobalTransform() * roEl->getDelta().inverse()*permute;
121 int stIndex = roEl->getStationIndex();
122 int stEta = roEl->getStationEta();
123 int stPhi = roEl->getStationPhi();
124 int stML = id_helper.multilayer(roEl->identify());
125 std::string chamberDesign = roEl->getStationType();
126
127 m_stIndex = stIndex;
128 m_stEta = stEta;
129 m_stPhi = stPhi;
130 m_stML = stML;
131 m_chamberDesign = chamberDesign;
132
133 const Identifier genStripID =id_helper.channelID(stIndex, stEta, stPhi,
135 const Identifier genPadID =id_helper.channelID(stIndex, stEta, stPhi,
137
139 int numLayers = roEl->numberOfLayers(true);
140 double yCutout = roEl->getDesign(genStripID)->yCutout();
141 double gasTck = roEl->getDesign(genStripID)->thickness;
142
143 m_numLayers = numLayers;
144 m_yCutout = yCutout;
145 m_gasTck = gasTck;
147 double sGapLength = roEl->getDesign(genStripID)->minYSize();
148 double lGapLength = roEl->getDesign(genStripID)->maxYSize();
149 double gapHeight = roEl->getDesign(genStripID)->xSize();
150
151 double sPadLength = roEl->getPadDesign(genPadID)->sPadWidth;
152 double lPadLength = roEl->getPadDesign(genPadID)->lPadWidth;
153
154 m_sGapLength = sGapLength;
155 m_lGapLength = lGapLength;
156 m_gapHeight = gapHeight;
157
158 m_sPadLength = sPadLength;
159 m_lPadLength = lPadLength;
161 double sChamberLength = roEl->getPadDesign(genPadID)->sWidth;
162 double lChamberLength = roEl->getPadDesign(genPadID)->lWidth;
163 double chamberHeight = roEl->getPadDesign(genPadID)->Length;
164
165 m_sChamberLength = sChamberLength;
166 m_lChamberLength = lChamberLength;
167 m_chamberHeight = chamberHeight;
168
170 const Amg::Transform3D& trans{roEl->transform()};
171 m_readoutTransform = trans;
172
174 for (int lay = 1; lay <= numLayers; ++lay) {
175 const Identifier layWireID =id_helper.channelID(stIndex, stEta, stPhi,
177 const Identifier layStripID =id_helper.channelID(stIndex, stEta, stPhi,
179 const Identifier layPadID =id_helper.padID(stIndex, stEta, stPhi,
180 stML, lay, sTgcIdHelper::sTgcChannelTypes::Pad, 1, 1);
181
183 unsigned int numWires = roEl->numberOfWires(layWireID);
184 unsigned int firstWireGroupWidth = roEl->getDesign(layWireID)->firstPitch;
185 int numWireGroups = roEl->getDesign(layWireID)->nGroups;
186 double wireCutout = roEl->getDesign(layWireID)->wireCutout;
187 double wirePitch = roEl->wirePitch();
188 double wireWidth = roEl->getDesign(layWireID)->inputWidth;
189 double wireGroupWidth = roEl->getDesign(layWireID)->groupWidth;
190
191 m_numWires.push_back(numWires);
192 m_firstWireGroupWidth.push_back(firstWireGroupWidth);
193 m_numWireGroups.push_back(numWireGroups);
194 m_wireCutout.push_back(wireCutout);
195 m_wirePitch = wirePitch;
196 m_wireWidth = wireWidth;
197 m_wireGroupWidth = wireGroupWidth;
198
200 for (int wireGroupIndex = 1; wireGroupIndex <= numWireGroups; ++wireGroupIndex) {
201 bool isValid = false;
202 const Identifier wireGroupID =id_helper.channelID(stIndex, stEta, stPhi, stML, lay,
204 if(!isValid) {
205 ATH_MSG_WARNING("The following wire group ID is not valid: " << wireGroupID);
206 }
207 Amg::Vector3D wireGroupPos(Amg::Vector3D::Zero());
208 Amg::Vector2D localWireGroupPos(Amg::Vector2D::Zero());
209 roEl->stripPosition(wireGroupID, localWireGroupPos);
210 m_localWireGroupPos.push_back(localWireGroupPos);
211 roEl->stripGlobalPosition(wireGroupID, wireGroupPos);
212 m_globalWireGroupPos.push_back(wireGroupPos);
213 m_wireGroupNum.push_back(wireGroupIndex);
214 m_wireGroupGasGap.push_back(lay);
215
216 if (wireGroupIndex != 1) continue;
217 const Amg::Transform3D locToGlob = roEl->transform(wireGroupID);
218 m_wireGroupRot.push_back(locToGlob);
219 m_wireGroupRotGasGap.push_back(lay);
220 }
221
223 int numStrips = roEl->getDesign(layStripID)->nch;
224 double stripPitch = roEl->channelPitch(layStripID);
225 double stripWidth = roEl->getDesign(layStripID)->inputWidth;
226 double firstStripPitch = roEl->getDesign(layStripID)->firstPitch;
227
228 m_numStrips = numStrips;
229 m_stripPitch = stripPitch;
230 m_stripWidth = stripWidth;
231 m_firstStripPitch.push_back(firstStripPitch);
232
234 for (int stripIndex = 1; stripIndex <= numStrips; ++stripIndex) {
235 bool isValid = false;
236 const Identifier stripID =id_helper.channelID(stIndex, stEta, stPhi, stML, lay,
238 if(!isValid) {
239 ATH_MSG_WARNING("The following strip ID is not valid: " << stripID);
240 }
241 double stripLength = roEl->getDesign(stripID)->channelLength(stripIndex);
242 Amg::Vector3D globalStripPos(Amg::Vector3D::Zero());
243 Amg::Vector2D localStripPos(Amg::Vector2D::Zero());
244 roEl->stripPosition(stripID, localStripPos);
245 m_localStripPos.push_back(localStripPos);
246 roEl->stripGlobalPosition(stripID, globalStripPos);
247 m_globalStripPos.push_back(globalStripPos);
248 m_stripNum.push_back(stripIndex);
249 m_stripGasGap.push_back(lay);
250 m_stripLengths.push_back(stripLength);
251
252 if (stripIndex != 1) continue;
253 const Amg::Transform3D locToGlob = roEl->transform(stripID);
254 m_stripRot.push_back(locToGlob);
255 m_stripRotGasGap.push_back(lay);
256 }
257
259 unsigned int numPads = roEl->numberOfPads(layPadID);
260 int numPadEta = roEl->getPadDesign(layPadID)->nPadH;
261 int numPadPhi = roEl->getPadDesign(layPadID)->nPadColumns;
262 double firstPadHeight = roEl->getPadDesign(layPadID)->firstRowPos;
263 double padHeight = roEl->getPadDesign(layPadID)->inputRowPitch;
264 double padPhiShift = roEl->getPadDesign(layPadID)->PadPhiShift;
265 double firstPadPhiDiv = roEl->getPadDesign(layPadID)->firstPhiPos;
266 double anglePadPhi = roEl->getPadDesign(layPadID)->inputPhiPitch;
267 double beamlineRadius = roEl->getPadDesign(layPadID)->radialDistance;
268
269 m_numPads.push_back(numPads);
270 m_numPadEta.push_back(numPadEta);
271 m_numPadPhi.push_back(numPadPhi);
272 m_firstPadHeight.push_back(firstPadHeight);
273 m_padHeight.push_back(padHeight);
274 m_padPhiShift.push_back(padPhiShift);
275 m_firstPadPhiDiv.push_back(firstPadPhiDiv);
276 m_anglePadPhi = anglePadPhi;
277 m_beamlineRadius = beamlineRadius;
278
280 for (int phiIndex = 1; phiIndex <= numPadPhi; ++phiIndex) {
281 for(int etaIndex = 1; etaIndex <= numPadEta; ++etaIndex) {
282 bool isValid = false;
283 const Identifier padID =id_helper.padID(stIndex, stEta, stPhi, stML, lay,
284 sTgcIdHelper::sTgcChannelTypes::Pad, etaIndex, phiIndex, isValid);
285 if(!isValid) {
286 ATH_MSG_WARNING("The following pad ID is not valid: " << padID);
287 }
288 Amg::Vector2D localPadPos(Amg::Vector2D::Zero());
289 Amg::Vector3D globalPadPos(Amg::Vector3D::Zero());
290 std::array<Amg::Vector2D,4> localPadCorners{make_array<Amg::Vector2D, 4>(Amg::Vector2D::Zero())};
291 std::array<Amg::Vector3D,4> globalPadCorners{make_array<Amg::Vector3D, 4>(Amg::Vector3D::Zero())};
292
293 roEl->padPosition(padID, localPadPos);
294 roEl->padGlobalPosition(padID, globalPadPos);
295 roEl->padCorners(padID, localPadCorners);
296 roEl->padGlobalCorners(padID, globalPadCorners);
297
298 m_localPadPos.push_back(localPadPos);
299 m_localPadCornerBL.push_back(localPadCorners[0]);
300 m_localPadCornerBR.push_back(localPadCorners[1]);
301 m_localPadCornerTL.push_back(localPadCorners[2]);
302 m_localPadCornerTR.push_back(localPadCorners[3]);
303
304 Amg::Vector2D hitCorrection{-.1, -.1};
305 Amg::Vector2D hitPos = localPadCorners[3] + hitCorrection;
306 m_hitPosition.push_back(hitPos);
307 m_padNumber.push_back(roEl->padNumber(hitPos, padID));
308
309 m_globalPadPos.push_back(globalPadPos);
310 m_globalPadCornerBR.push_back(globalPadCorners[0]);
311 m_globalPadCornerBL.push_back(globalPadCorners[1]);
312 m_globalPadCornerTR.push_back(globalPadCorners[2]);
313 m_globalPadCornerTL.push_back(globalPadCorners[3]);
314
315 m_padEta.push_back(etaIndex);
316 m_padPhi.push_back(phiIndex);
317 m_padGasGap.push_back(lay);
318
319 if (etaIndex != 1 || phiIndex != 1) continue;
320 const Amg::Transform3D locToGlob = roEl->transform(padID);
321 m_padRot.push_back(locToGlob);
322 m_padRotGasGap.push_back(lay);
323 }
324 }
325 }
326
327 return m_tree.fill(ctx) ? StatusCode::SUCCESS : StatusCode::FAILURE;
328}
329
330}
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)
MuonVal::ScalarBranch< short > & m_stIndex
Identifier of the readout element.
MuonVal::VectorBranch< uint > & m_numPads
Pad dimensions.
MuonVal::ScalarBranch< std::string > & m_chamberDesign
MuonVal::ScalarBranch< float > & m_sChamberLength
Chamber Length for debug.
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
MuonVal::CoordSystemsBranch m_stripRot
Rotation matrix of the respective strip layers.
MuonVal::CoordSystemsBranch m_padRot
Rotation matrix of the respective pad layers.
std::set< Identifier > m_testStations
Set of stations to be tested.
MuonVal::ScalarBranch< float > & m_sGapLength
GasGap Lengths for debug.
SG::ReadCondHandleKey< MuonGM::MuonDetectorManager > m_detMgrKey
MuonDetectorManager from the conditions store.
StatusCode dumpToTree(const EventContext &ctx, const sTgcReadoutElement *readoutEle)
Gaudi::Property< std::vector< std::string > > m_selectStat
String should be formated like <stationName><stationEta><A/C><stationPhi>.
MuonVal::ScalarBranch< uint > & m_numStrips
Strip dimensions.
Gaudi::Property< std::vector< std::string > > m_excludeStat
MuonVal::CoordSystemsBranch m_wireGroupRot
Rotation matrix of the respective wireGroup layers.
StatusCode execute(const EventContext &ctx) override
Execute method.
MuonVal::CoordTransformBranch m_readoutTransform
Transformation of the readout element (Translation, ColX, ColY, ColZ).
virtual const Amg::Transform3D & transform() const override
Return local to global transform.
Identifier identify() const override final
Returns the ATLAS Identifier of the MuonReadOutElement.
An sTgcReadoutElement corresponds to a single STGC module; therefore typicaly a barrel muon station c...
bool padPosition(const Identifier &id, Amg::Vector2D &pos) const
pad position
const MuonPadDesign * getPadDesign(const Identifier &id) const
returns the MuonChannelDesign class for the given identifier
virtual bool stripPosition(const Identifier &id, Amg::Vector2D &pos) const override final
strip position - should be renamed to channel position If the strip number is outside the range of va...
bool padCorners(const Identifier &id, std::array< Amg::Vector2D, 4 > &corners) const
pad corners
const MuonChannelDesign * getDesign(const Identifier &id) const
returns the MuonChannelDesign class for the given identifier
int numberOfWires(const Identifier &id) const
Get the total number of wires (single wires) of a chamber.
double channelPitch(const Identifier &id) const
Channel pitch.
const Amg::Transform3D & getDelta() const
read A-line parameters and include the chamber rotation/translation in the local-to-global (ATLAS) re...
bool padGlobalPosition(const Identifier &id, Amg::Vector3D &gpos) const
pad global position
bool stripGlobalPosition(const Identifier &id, Amg::Vector3D &gpos) const
virtual int numberOfLayers(bool) const override final
number of layers in phi/eta projection
int numberOfPads(const Identifier &layerId) const
Get the number of pad per layer.
bool padGlobalCorners(const Identifier &id, std::array< Amg::Vector3D, 4 > &gcorners) const
pad global corners
int padNumber(const Amg::Vector2D &pos, const Identifier &id) const
pad number corresponding to local position
const_id_iterator detectorElement_begin() const
Iterators over full set of ids.
const_id_iterator detectorElement_end() const
int multilayer(const Identifier &id) 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
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
Ensure that the Athena extensions are properly loaded.
Definition GeoMuonHits.h:27
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.
double channelLength(int channel) const
STRIPS ONLY: calculate channel length for a given strip number.
double radialDistance
DT-2015-11-29 distance from the beamline to the center of the module.