ATLAS Offline Software
Loading...
Searching...
No Matches
MuonDetDescr/MuonGeoModelTest/src/GeoModelMmTest.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 "GeoModelMmTest.h"
5
6#include <fstream>
7#include <iostream>
8
9
12#include "GeoModelKernel/GeoDefinitions.h"
14#include "GaudiKernel/SystemOfUnits.h"
15
16namespace MuonGM {
17
19 ATH_CHECK(m_tree.write());
20 return StatusCode::SUCCESS;
21}
23 ATH_CHECK(m_detMgrKey.initialize());
24 ATH_CHECK(m_idHelperSvc.retrieve());
25 ATH_CHECK(m_tree.init(this));
26
27 const MmIdHelper& idHelper{m_idHelperSvc->mmIdHelper()};
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 GeoModelMmTest::execute(const EventContext& ctx) {
90
92 if (!detMgr.isValid()) {
93 ATH_MSG_FATAL("Failed to retrieve MuonDetectorManager "
94 << m_detMgrKey.fullKey());
95 return StatusCode::FAILURE;
96 }
97 const MmIdHelper& id_helper{m_idHelperSvc->mmIdHelper()};
98 //Looping through the MicroMegas identifiers and pushing back the respective roe.
99 for (const Identifier& test_me : m_testStations) {
100 ATH_MSG_VERBOSE("Test retrieval of Mm detector element "
101 << m_idHelperSvc->toStringDetEl(test_me));
102 const MuonGM::MMReadoutElement *reElement = detMgr->getMMReadoutElement(test_me);
103 if (!reElement) {
104 ATH_MSG_VERBOSE("Detector element is invalid");
105 continue;
106 }
108 if (m_idHelperSvc->toStringDetEl(reElement->identify()) != m_idHelperSvc->toStringDetEl(test_me)) {
109 ATH_MSG_FATAL("Expected to retrieve "
110 << m_idHelperSvc->toStringDetEl(test_me) << ". But got instead "
111 << m_idHelperSvc->toStringDetEl(reElement->identify()));
112 return StatusCode::FAILURE;
113 }
114 for (int gasGap = 1; gasGap <= 4; ++gasGap) {
115 const Identifier layerId = id_helper.channelID(test_me, id_helper.multilayer(test_me), gasGap, 1024);
116 int fStrip = reElement->numberOfMissingBottomStrips(layerId) + 1;
117 int lStrip = id_helper.channelMax(layerId)-reElement->numberOfMissingTopStrips(layerId);
118 for (int channel=fStrip; channel<=lStrip; ++channel) {
119
120 bool is_valid{false};
121 const Identifier strip_id = id_helper.channelID(test_me, id_helper.multilayer(test_me),
122 gasGap, channel, is_valid);
123 if (!is_valid) {
124 continue;
125 }
126 Amg::Vector3D globStripPos{Amg::Vector3D::Zero()};
127 reElement->stripGlobalPosition(strip_id, globStripPos);
128 Amg::Vector2D locPos{Amg::Vector2D::Zero()};
129 reElement->surface(strip_id).globalToLocal(globStripPos, Amg::Vector3D::Zero(), locPos);
130 const MuonGM::MuonChannelDesign& design{*reElement->getDesign(strip_id)};
131 const double stripLength = 0.49 * reElement->stripLength(strip_id);
132 if (design.channelNumber(locPos) != channel ||
133 design.channelNumber(locPos + stripLength *Amg::Vector2D::UnitY()) != channel ||
134 design.channelNumber(locPos - stripLength *Amg::Vector2D::UnitY()) != channel ){
135 ATH_MSG_FATAL("Conversion of channel -> strip -> channel failed for "
136 <<m_idHelperSvc->toString(strip_id)<<", global pos:"
137 <<Amg::toString(globStripPos)<<", locPos: "<<Amg::toString(locPos)
138 <<", backward channel: "<<design.channelNumber(locPos));
139 return StatusCode::FAILURE;
140 }
141 }
142 }
143 ATH_CHECK(dumpToTree(ctx,reElement));
144
145 }
146 return StatusCode::SUCCESS;
147}
148
149StatusCode GeoModelMmTest::dumpToTree(const EventContext& ctx, const MuonGM::MMReadoutElement* roEl) {
150
151 const MmIdHelper& id_helper = m_idHelperSvc->mmIdHelper();
152 const Identifier detElId = roEl->identify();
155 m_stationEta = roEl->getStationEta();
156 m_stationPhi = roEl->getStationPhi();
157 m_stationName = id_helper.stationName(detElId);
158 const int multilayer = id_helper.multilayer(detElId);
159 m_moduleHeight = roEl->getRsize();
160 m_moduleWidthS = roEl->getSsize();
162 m_multilayer = multilayer;
163 m_stStripPitch = roEl->getDesign(detElId)->inputPitch;
164 const Amg::Transform3D permute{GeoTrf::GeoRotation{90.*Gaudi::Units::deg,90.*Gaudi::Units::deg, 0.}};
165 m_alignableNode = roEl->AmdbLRSToGlobalTransform() * roEl->getDelta().inverse()*permute;
166
168
170 for (int gasgap = 1; gasgap <= 4; ++gasgap) {
171
172 const Identifier layerId = id_helper.channelID(detElId, multilayer, gasgap, 1024);
173 const int fStrip = roEl->numberOfMissingBottomStrips(layerId)+1;
174 const int lStrip = id_helper.channelMax(layerId)-roEl->numberOfMissingTopStrips(layerId);
175
176 for (int channel=fStrip; channel<=lStrip; ++channel) {
177
178 bool is_valid{false};
179 const Identifier strip_id = id_helper.channelID(detElId, multilayer,
180 gasgap, channel, is_valid);
181 if (!is_valid) continue;
182
183
184 //If the strip number is outside the range of valid strips, the function will return false
185 //this method also assignes strip center global coordinates to the gp vector.
186
187 //Strip global points
188 Amg::Vector3D strip_center{Amg::Vector3D::Zero()},
189 strip_leftEdge{Amg::Vector3D::Zero()},
190 strip_rightEdge{Amg::Vector3D::Zero()};
191
192 Amg::Vector2D l_cen{Amg::Vector2D::Zero()},
193 l_left{Amg::Vector2D::Zero()},
194 l_right{Amg::Vector2D::Zero()};
195
196 const MuonGM::MuonChannelDesign& design{*roEl->getDesign(strip_id)};
197
198 if (!design.leftEdge(channel, l_left) || !design.center(channel, l_cen) ||
199 !design.rightEdge(channel, l_right)){
200 continue;
201 }
202
203 roEl->surface(strip_id).localToGlobal(l_left, Amg::Vector3D::Zero(), strip_leftEdge);
204 roEl->surface(strip_id).localToGlobal(l_cen, Amg::Vector3D::Zero(), strip_center);
205 roEl->surface(strip_id).localToGlobal(l_right, Amg::Vector3D::Zero(), strip_rightEdge);
206
207 m_locStripCenter.push_back(l_cen);
208 m_isStereo.push_back(design.hasStereoAngle());
209 m_gasGap.push_back(id_helper.gasGap(strip_id));
210 m_channel.push_back(id_helper.channel(strip_id));
211 m_stripCenter.push_back(strip_center);
212 m_stripLeftEdge.push_back(strip_leftEdge);
213 m_stripRightEdge.push_back(strip_rightEdge);
214 m_stripLength.push_back(roEl->stripLength(strip_id));
215 m_stripActiveLength.push_back(roEl->stripActiveLength(strip_id));
216 m_stripActiveLengthLeft.push_back(roEl->stripActiveLengthLeft(strip_id));
217 m_stripActiveLengthRight.push_back(roEl->stripActiveLengthRight(strip_id));
218
219 m_ActiveHeightR = design.xSize();
220 m_ActiveWidthL = design.maxYSize();
221 m_ActiveWidthS = design.minYSize();
222
223 if (channel != fStrip) continue;
224 ATH_MSG_VERBOSE(m_idHelperSvc->toStringGasGap(strip_id)<<" "<<Amg::toString(roEl->transform(strip_id).translation(), 4)
225 <<", "<<roEl->transform(strip_id).translation().perp());
226 m_stripRot.push_back(roEl->transform(strip_id));
227 m_stripRotGasGap.push_back(gasgap);
228 m_firstStripPos.push_back(design.firstPos() * Amg::Vector2D::UnitX());
229 m_firstStrip.push_back(design.numberOfMissingBottomStrips() + 1);
230 m_nStrips.push_back(design.nch);
231 m_readoutSide.push_back(roEl->getReadoutSide()[gasgap -1]);
232 }
233 }
234 return m_tree.fill(ctx) ? StatusCode::SUCCESS : StatusCode::FAILURE;
235}
236
237
238
239}
#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)
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int channel) const
Identifier elementID(int stationName, int stationEta, int stationPhi) const
static int channelMax()
Identifier multilayerID(const Identifier &channeldID) const
int channel(const Identifier &id) const override
int gasGap(const Identifier &id) const override
get the hashes
int multilayer(const Identifier &id) const
MuonVal::ScalarBranch< unsigned short > & m_stationIndex
MuonVal::CoordTransformBranch m_readoutTransform
Transformation of the readout element (Translation, ColX, ColY, ColZ).
StatusCode dumpToTree(const EventContext &ctx, const MuonGM::MMReadoutElement *detEl)
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Gaudi::Property< std::vector< std::string > > m_selectStat
String should be formated like MM<L or S><1 or 2><A/C><layer> Example string MML1A6 ,...
SG::ReadCondHandleKey< MuonGM::MuonDetectorManager > m_detMgrKey
MuonDetectorManager from the conditions store.
MuonVal::CoordSystemsBranch m_stripRot
Rotation matrix of the respective strip layers.
StatusCode execute(const EventContext &ctx) override
Execute method.
MuonVal::VectorBranch< uint8_t > & m_stripRotGasGap
MuonVal::VectorBranch< float > & m_stripActiveLengthRight
Gaudi::Property< std::vector< std::string > > m_excludeStat
MuonVal::VectorBranch< float > & m_stripActiveLengthLeft
std::set< Identifier > m_testStations
Set of stations to be tested.
An MMReadoutElement corresponds to a single STGC module; therefore typicaly a barrel muon station con...
const Amg::Transform3D & getDelta() const
read A-line parameters and include the chamber rotation/translation in the local-to-global (ATLAS) re...
int numberOfMissingTopStrips(const Identifier &layerId) const
Number of missing bottom and top strips (not read out).
const std::array< int, 4 > & getReadoutSide() const
double stripActiveLengthRight(const Identifier &id) const
virtual Amg::Transform3D AmdbLRSToGlobalTransform() const override final
int numberOfMissingBottomStrips(const Identifier &layerId) const
double stripActiveLength(const Identifier &id) const
double stripActiveLengthLeft(const Identifier &id) const
double stripLength(const Identifier &id) const
strip length Wrappers to MuonChannelDesign::channelLength() taking into account the passivated width
const MuonChannelDesign * getDesign(const Identifier &id) const
returns the MuonChannelDesign class for the given identifier
bool stripGlobalPosition(const Identifier &id, Amg::Vector3D &gpos) const
virtual const Trk::PlaneSurface & surface() const override
access to chamber surface (phi orientation), uses the first gas gap
virtual const Amg::Transform3D & transform() const override
Return local to global transform.
Identifier identify() const override final
Returns the ATLAS Identifier of the MuonReadOutElement.
const_id_iterator detectorElement_begin() const
Iterators over full set of ids.
int stationName(const Identifier &id) const
const_id_iterator detectorElement_end() const
virtual void localToGlobal(const Amg::Vector2D &locp, const Amg::Vector3D &mom, Amg::Vector3D &glob) const override final
Specified for PlaneSurface: LocalToGlobal method without dynamic memory allocation.
virtual bool globalToLocal(const Amg::Vector3D &glob, const Amg::Vector3D &mom, Amg::Vector2D &loc) const override final
Specified for PlaneSurface: GlobalToLocal method without dynamic memory allocation - boolean checks i...
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
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.
bool center(int channel, Amg::Vector2D &pos) const
STRIPS ONLY: Returns the center on the strip.
bool leftEdge(int channel, Amg::Vector2D &pos) const
STRIPS ONLY: Returns the left edge of the strip.
int numberOfMissingBottomStrips() const
Returns the number of missing bottom strips.
bool rightEdge(int channel, Amg::Vector2D &pos) const
STRIPS ONLY: Returns the right edge of the strip.
double hasStereoAngle() const
returns whether the stereo angle is non-zero
double firstPos() const
Returns the position of the first strip along the x-axis.
int channelNumber(const Amg::Vector2D &pos) const
calculate local channel number, range 1=nstrips like identifiers. Returns -1 if out of range