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}
90
91 const EventContext& ctx{Gaudi::Hive::currentContext()};
93 if (!detMgr.isValid()) {
94 ATH_MSG_FATAL("Failed to retrieve MuonDetectorManager "
95 << m_detMgrKey.fullKey());
96 return StatusCode::FAILURE;
97 }
98 const MmIdHelper& id_helper{m_idHelperSvc->mmIdHelper()};
99 //Looping through the MicroMegas identifiers and pushing back the respective roe.
100 for (const Identifier& test_me : m_testStations) {
101 ATH_MSG_VERBOSE("Test retrieval of Mm detector element "
102 << m_idHelperSvc->toStringDetEl(test_me));
103 const MuonGM::MMReadoutElement *reElement = detMgr->getMMReadoutElement(test_me);
104 if (!reElement) {
105 ATH_MSG_VERBOSE("Detector element is invalid");
106 continue;
107 }
109 if (m_idHelperSvc->toStringDetEl(reElement->identify()) != m_idHelperSvc->toStringDetEl(test_me)) {
110 ATH_MSG_FATAL("Expected to retrieve "
111 << m_idHelperSvc->toStringDetEl(test_me) << ". But got instead "
112 << m_idHelperSvc->toStringDetEl(reElement->identify()));
113 return StatusCode::FAILURE;
114 }
115 for (int gasGap = 1; gasGap <= 4; ++gasGap) {
116 const Identifier layerId = id_helper.channelID(test_me, id_helper.multilayer(test_me), gasGap, 1024);
117 int fStrip = reElement->numberOfMissingBottomStrips(layerId) + 1;
118 int lStrip = id_helper.channelMax(layerId)-reElement->numberOfMissingTopStrips(layerId);
119 for (int channel=fStrip; channel<=lStrip; ++channel) {
120
121 bool is_valid{false};
122 const Identifier strip_id = id_helper.channelID(test_me, id_helper.multilayer(test_me),
123 gasGap, channel, is_valid);
124 if (!is_valid) {
125 continue;
126 }
127 Amg::Vector3D globStripPos{Amg::Vector3D::Zero()};
128 reElement->stripGlobalPosition(strip_id, globStripPos);
129 Amg::Vector2D locPos{Amg::Vector2D::Zero()};
130 reElement->surface(strip_id).globalToLocal(globStripPos, Amg::Vector3D::Zero(), locPos);
131 const MuonGM::MuonChannelDesign& design{*reElement->getDesign(strip_id)};
132 const double stripLength = 0.49 * reElement->stripLength(strip_id);
133 if (design.channelNumber(locPos) != channel ||
134 design.channelNumber(locPos + stripLength *Amg::Vector2D::UnitY()) != channel ||
135 design.channelNumber(locPos - stripLength *Amg::Vector2D::UnitY()) != channel ){
136 ATH_MSG_FATAL("Conversion of channel -> strip -> channel failed for "
137 <<m_idHelperSvc->toString(strip_id)<<", global pos:"
138 <<Amg::toString(globStripPos)<<", locPos: "<<Amg::toString(locPos)
139 <<", backward channel: "<<design.channelNumber(locPos));
140 return StatusCode::FAILURE;
141 }
142 }
143 }
144 ATH_CHECK(dumpToTree(ctx,reElement));
145
146 }
147 return StatusCode::SUCCESS;
148}
149
150StatusCode GeoModelMmTest::dumpToTree(const EventContext& ctx, const MuonGM::MMReadoutElement* roEl) {
151
152 const MmIdHelper& id_helper = m_idHelperSvc->mmIdHelper();
153 const Identifier detElId = roEl->identify();
156 m_stationEta = roEl->getStationEta();
157 m_stationPhi = roEl->getStationPhi();
158 m_stationName = id_helper.stationName(detElId);
159 const int multilayer = id_helper.multilayer(detElId);
160 m_moduleHeight = roEl->getRsize();
161 m_moduleWidthS = roEl->getSsize();
163 m_multilayer = multilayer;
164 m_stStripPitch = roEl->getDesign(detElId)->inputPitch;
165 const Amg::Transform3D permute{GeoTrf::GeoRotation{90.*Gaudi::Units::deg,90.*Gaudi::Units::deg, 0.}};
166 m_alignableNode = roEl->AmdbLRSToGlobalTransform() * roEl->getDelta().inverse()*permute;
167
169
171 for (int gasgap = 1; gasgap <= 4; ++gasgap) {
172
173 const Identifier layerId = id_helper.channelID(detElId, multilayer, gasgap, 1024);
174 const int fStrip = roEl->numberOfMissingBottomStrips(layerId)+1;
175 const int lStrip = id_helper.channelMax(layerId)-roEl->numberOfMissingTopStrips(layerId);
176
177 for (int channel=fStrip; channel<=lStrip; ++channel) {
178
179 bool is_valid{false};
180 const Identifier strip_id = id_helper.channelID(detElId, multilayer,
181 gasgap, channel, is_valid);
182 if (!is_valid) continue;
183
184
185 //If the strip number is outside the range of valid strips, the function will return false
186 //this method also assignes strip center global coordinates to the gp vector.
187
188 //Strip global points
189 Amg::Vector3D strip_center{Amg::Vector3D::Zero()},
190 strip_leftEdge{Amg::Vector3D::Zero()},
191 strip_rightEdge{Amg::Vector3D::Zero()};
192
193 Amg::Vector2D l_cen{Amg::Vector2D::Zero()},
194 l_left{Amg::Vector2D::Zero()},
195 l_right{Amg::Vector2D::Zero()};
196
197 const MuonGM::MuonChannelDesign& design{*roEl->getDesign(strip_id)};
198
199 if (!design.leftEdge(channel, l_left) || !design.center(channel, l_cen) ||
200 !design.rightEdge(channel, l_right)){
201 continue;
202 }
203
204 roEl->surface(strip_id).localToGlobal(l_left, Amg::Vector3D::Zero(), strip_leftEdge);
205 roEl->surface(strip_id).localToGlobal(l_cen, Amg::Vector3D::Zero(), strip_center);
206 roEl->surface(strip_id).localToGlobal(l_right, Amg::Vector3D::Zero(), strip_rightEdge);
207
208 m_locStripCenter.push_back(l_cen);
209 m_isStereo.push_back(design.hasStereoAngle());
210 m_gasGap.push_back(id_helper.gasGap(strip_id));
211 m_channel.push_back(id_helper.channel(strip_id));
212 m_stripCenter.push_back(strip_center);
213 m_stripLeftEdge.push_back(strip_leftEdge);
214 m_stripRightEdge.push_back(strip_rightEdge);
215 m_stripLength.push_back(roEl->stripLength(strip_id));
216 m_stripActiveLength.push_back(roEl->stripActiveLength(strip_id));
217 m_stripActiveLengthLeft.push_back(roEl->stripActiveLengthLeft(strip_id));
218 m_stripActiveLengthRight.push_back(roEl->stripActiveLengthRight(strip_id));
219
220 m_ActiveHeightR = design.xSize();
221 m_ActiveWidthL = design.maxYSize();
222 m_ActiveWidthS = design.minYSize();
223
224 if (channel != fStrip) continue;
225 ATH_MSG_VERBOSE(m_idHelperSvc->toStringGasGap(strip_id)<<" "<<Amg::toString(roEl->transform(strip_id).translation(), 4)
226 <<", "<<roEl->transform(strip_id).translation().perp());
227 m_stripRot.push_back(roEl->transform(strip_id));
228 m_stripRotGasGap.push_back(gasgap);
229 m_firstStripPos.push_back(design.firstPos() * Amg::Vector2D::UnitX());
230 m_firstStrip.push_back(design.numberOfMissingBottomStrips() + 1);
231 m_nStrips.push_back(design.nch);
232 m_readoutSide.push_back(roEl->getReadoutSide()[gasgap -1]);
233 }
234 }
235 return m_tree.fill(ctx) ? StatusCode::SUCCESS : StatusCode::FAILURE;
236}
237
238
239
240}
#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)
bool isValid(const T &p)
Av: we implement here an ATLAS-sepcific convention: all particles which are 99xxxxx are fine.
Definition AtlasPID.h:878
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.
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