ATLAS Offline Software
Loading...
Searching...
No Matches
MuonPhaseII/MuonDetDescr/MuonGeoModelTestR4/src/GeoModelRpcTest.cxx
Go to the documentation of this file.
1
2/*
3 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
4*/
5#include "GeoModelRpcTest.h"
10#include <fstream>
11
12namespace {
13// Splitting this out into a separate function avoids a false positive
14// out-of-bounds array access warning from gcc14 in the archflag build.
15// (It should also be addressed in versions of Eigen after 3.4.)
16std::string stripPosToString (const MuonGMR4::RpcReadoutElement* reElement,
17 const ActsTrk::GeometryContext& gctx,
18 const IdentifierHash measHash)
19{
20 Amg::Vector3D v = reElement->stripPosition(gctx, measHash);
21 return Amg::toString(v);
22}
23}
24
25using namespace ActsTrk;
26namespace MuonGMR4{
27
28
30 ATH_CHECK(m_idHelperSvc.retrieve());
31 ATH_CHECK(m_geoCtxKey.initialize());
32 if (m_visualStrips) {
33 m_clientToken.preFixName="GeoModelRpcTest";
34 m_clientToken.subDirectory = "RpcPlots";
35 m_clientToken.canvasLimit = -1;
36 m_clientToken.drawSqrtS = false;
37 ATH_CHECK(m_visualSvc.retrieve());
38 ATH_CHECK(m_visualSvc->registerClient(m_clientToken));
39 }
41 ATH_CHECK(m_tree.init(this));
42
43 const RpcIdHelper& idHelper{m_idHelperSvc->rpcIdHelper()};
44 auto translateTokenList = [this, &idHelper](const std::vector<std::string>& chNames){
45
46 std::set<Identifier> transcriptedIds{};
47 for (const std::string& token : chNames) {
48 if (token.size() != 6) {
49 ATH_MSG_WARNING("Wrong format given for "<<token<<". Expecting 6 characters");
50 continue;
51 }
53 const std::string statName = token.substr(0, 3);
54 const unsigned statEta = std::atoi(token.substr(3, 1).c_str()) * (token[4] == 'A' ? 1 : -1);
55 const unsigned statPhi = std::atoi(token.substr(5, 1).c_str());
56 bool isValid{false};
57 const Identifier eleId = idHelper.elementID(statName, statEta, statPhi, 1, isValid);
58 if (!isValid) {
59 ATH_MSG_WARNING("Failed to deduce a station name for " << token);
60 continue;
61 }
62 transcriptedIds.insert(eleId);
63 std::copy_if(idHelper.detectorElement_begin(), idHelper.detectorElement_end(),
64 std::inserter(transcriptedIds, transcriptedIds.end()),
65 [&eleId, &idHelper](const Identifier& copyMe){
66 return idHelper.stationName(copyMe) == idHelper.stationName(eleId) &&
67 idHelper.stationEta(copyMe) == idHelper.stationEta(eleId) &&
68 idHelper.stationPhi(copyMe) == idHelper.stationPhi(eleId);
69 });
70 }
71 return transcriptedIds;
72 };
73
74 std::vector <std::string>& selectedSt = m_selectStat.value();
75 const std::vector <std::string>& excludedSt = m_excludeStat.value();
76 selectedSt.erase(std::remove_if(selectedSt.begin(), selectedSt.end(),
77 [&excludedSt](const std::string& token){
78 return std::ranges::find(excludedSt, token) != excludedSt.end();
79 }), selectedSt.end());
80
81 if (selectedSt.size()) {
82 m_testStations = translateTokenList(selectedSt);
83 std::stringstream sstr{};
84 for (const Identifier& id : m_testStations) {
85 sstr<<" *** "<<m_idHelperSvc->toString(id)<<std::endl;
86 }
87 ATH_MSG_INFO("Test only the following stations "<<std::endl<<sstr.str());
88 } else {
89 const std::set<Identifier> excluded = translateTokenList(excludedSt);
91 for(auto itr = idHelper.detectorElement_begin();
92 itr!= idHelper.detectorElement_end();++itr){
93 if (!excluded.count(*itr)) {
94 m_testStations.insert(*itr);
95 }
96 }
98 if (!excluded.empty()) {
99 std::stringstream excluded_report{};
100 for (const Identifier& id : excluded){
101 excluded_report << " *** " << m_idHelperSvc->toStringDetEl(id) << std::endl;
102 }
103 ATH_MSG_INFO("Test all station except the following excluded ones " << std::endl << excluded_report.str());
104 }
105 }
106 ATH_CHECK(detStore()->retrieve(m_detMgr));
107 return StatusCode::SUCCESS;
108}
110 ATH_CHECK(m_tree.write());
111 return StatusCode::SUCCESS;
112}
113void GeoModelRpcTest::visualizeStripPanel(const EventContext& ctx,
114 const StripDesignPtr& design,
115 const Identifier& detId,
116 const bool measPhi) const {
117 if (!design || !m_visualStrips) {
118 return;
119 }
120 const RpcIdHelper& idHelper{m_idHelperSvc->rpcIdHelper()};
121 const std::string chName = std::format("{:}{:}{:}{:}R{:}Z{:}P{:}{:}",
122 m_idHelperSvc->stationNameString(detId),
123 std::abs(m_idHelperSvc->stationEta(detId)),
124 m_idHelperSvc->stationEta(detId) > 0 ? 'A' : 'C',
125 m_idHelperSvc->stationPhi(detId),
126 idHelper.doubletR(detId), idHelper.doubletZ(detId),
127 idHelper.doubletPhi(detId), measPhi ? "Phi" : "Eta");
128 auto canvas = m_visualSvc->prepareCanvas(ctx, m_clientToken, chName);
129 canvas->expandPad(-design->halfWidth(), -design->shortHalfHeight());
130 canvas->expandPad(design->halfWidth(), design->shortHalfHeight());
131 canvas->setAxisTitles("x [mm]", "y [mm]");
132 canvas->setRangeScale(1.1);
133 using namespace MuonValR4;
134 canvas->add(drawBox(Amg::Vector3D::Zero(),
135 2.*design->halfWidth(),
136 2.*design->shortHalfHeight(),
137 kBlack, hollowFilling));
138 constexpr int oddFill = 3315;
139 constexpr int evenFill = 3351;
140 for (int strip = design->firstStripNumber(); strip <= design->numStrips(); ++strip) {
141 const Amg::Vector2D stripPos = design->center(strip).value_or(Amg::Vector2D::Zero());
142 canvas->add(drawBox(Amg::Vector3D{0., stripPos.x(), stripPos.y()},
143 design->stripWidth(),
144 2.*design->shortHalfHeight(), strip % 2 ? kBlue: kRed,
145 strip % 2 ? oddFill : evenFill));
146 }
147 canvas->add(drawLabel(std::format("{:}, #{:}-panel",
148 m_idHelperSvc->toStringDetEl(detId),
149 measPhi ? "phi" : "eta"), 0.1, 0.05));
150 canvas->add(drawLabel(std::format("Dimensions: {:.1f}X{:.1f} [mm]",
151 2.*design->halfWidth(),
152 2.*design->shortHalfHeight()), 0.1, 0.015));
153}
154StatusCode GeoModelRpcTest::execute(const EventContext& ctx) {
155
156 const ActsTrk::GeometryContext* geoContextHandle{nullptr};
157 ATH_CHECK(SG::get(geoContextHandle, m_geoCtxKey, ctx));
158 const ActsTrk::GeometryContext& gctx{*geoContextHandle};
159
160 for (const Identifier& test_me : m_testStations) {
161 ATH_MSG_DEBUG("Test retrieval of Rpc detector element "<<m_idHelperSvc->toStringDetEl(test_me));
162 const RpcReadoutElement* reElement = m_detMgr->getRpcReadoutElement(test_me);
163 if (!reElement) {
164 continue;
165 }
167 if (reElement->identify() != test_me) {
168 ATH_MSG_FATAL("Expected to retrieve "<<m_idHelperSvc->toStringDetEl(test_me)
169 <<". But got instead "<<m_idHelperSvc->toStringDetEl(reElement->identify()));
170 return StatusCode::FAILURE;
171 }
172 ATH_CHECK(dumpToTree(ctx, gctx, reElement));
173 visualizeStripPanel(ctx, reElement->getParameters().etaDesign, reElement->identify(), false);
174 visualizeStripPanel(ctx, reElement->getParameters().phiDesign, reElement->identify(), true);
175
176 const Amg::Transform3D globToLocal{reElement->globalToLocalTransform(gctx)};
177 const Amg::Transform3D& localToGlob{reElement->localToGlobalTransform(gctx)};
179 const Amg::Transform3D transClosure = globToLocal * localToGlob;
180 if (!Amg::doesNotDeform(transClosure)) {
181 ATH_MSG_FATAL("Closure test failed for "<<m_idHelperSvc->toStringDetEl(test_me)
182 <<". Ended up with "<< Amg::toString(transClosure) );
183 return StatusCode::FAILURE;
184 }
185 const RpcIdHelper& id_helper{m_idHelperSvc->rpcIdHelper()};
186 for (unsigned gasGap = 1; gasGap <= reElement->nGasGaps(); ++gasGap) {
187 for (int doubPhi = reElement->doubletPhi(); doubPhi <= reElement->doubletPhiMax(); ++doubPhi) {
188 for (bool measPhi: {false, true}) {
189 unsigned numStrip = (measPhi ? reElement->nPhiStrips() :
190 reElement->nEtaStrips());
191 for (unsigned strip = 1; strip < numStrip ; ++strip) {
192 bool isValid{false};
193 const Identifier chId = id_helper.channelID(reElement->identify(),
194 reElement->doubletZ(),
195 doubPhi, gasGap, measPhi, strip, isValid);
196 if (!isValid) {
197 continue;
198 }
200 const IdentifierHash measHash = reElement->measurementHash(chId);
201 const IdentifierHash layHash = reElement->layerHash(chId);
202 ATH_MSG_VERBOSE("gasGap: "<<gasGap<<", doubletPhi: "<<doubPhi<<", measPhi: "<<measPhi
203 <<" --> layerHash: "<<static_cast<unsigned>(layHash));
204 const Identifier backCnv = reElement->measurementId(measHash);
205 if (backCnv != chId) {
206 ATH_MSG_FATAL("The back and forth conversion of "<<m_idHelperSvc->toString(chId)
207 <<" failed. Got "<<m_idHelperSvc->toString(backCnv));
208 return StatusCode::FAILURE;
209 }
210 if (layHash != reElement->layerHash(measHash)) {
211 ATH_MSG_FATAL("Constructing the layer hash from the identifier "<<
212 m_idHelperSvc->toString(chId)<<" leadds to different layer hashes "<<
213 layHash<<" vs. "<< reElement->layerHash(measHash));
214 return StatusCode::FAILURE;
215 }
216 ATH_MSG_VERBOSE("Channel "<<m_idHelperSvc->toString(chId)<<" strip position "
217 <<stripPosToString(reElement, gctx, measHash));
218 }
219 }
220 }
221 }
222 }
223 return StatusCode::SUCCESS;
224}
225StatusCode GeoModelRpcTest::dumpToTree(const EventContext& ctx,
226 const ActsTrk::GeometryContext& gctx,
227 const RpcReadoutElement* reElement){
228
229 m_stIndex = reElement->stationName();
230 m_stEta = reElement->stationEta();
231 m_stPhi = reElement->stationPhi();
232 m_doubletR = reElement->doubletR();
233 m_doubletZ = reElement->doubletZ();
234 m_doubletPhi = reElement->doubletPhi();
235 m_chamberDesign = reElement->chamberDesign();
236
237 m_numRpcLayers = reElement->nGasGaps();
238
239 m_numGasGapsPhi = reElement->nPhiPanels();
240 m_numPhiPanels = reElement->nPhiPanels();
241
243 m_numStripsEta = reElement->nEtaStrips();
244 m_numStripsPhi = reElement->nPhiStrips();
245
246 m_stripEtaPitch = reElement->stripEtaPitch();
247 m_stripPhiPitch = reElement->stripPhiPitch();
248 m_stripEtaWidth = reElement->stripEtaWidth();
249 m_stripPhiWidth = reElement->stripPhiWidth();
250 m_stripEtaLength = reElement->stripEtaLength();
251 m_stripPhiLength = reElement->stripPhiLength();
252
254 m_envelopeWidth = 2.*reElement->getParameters().halfWidth;
255 m_envelopeLength = 2.*reElement->getParameters().halfLength;
257 const Amg::Transform3D& transform{reElement->localToGlobalTransform(gctx)};
258 m_readoutTransform = transform;
259 m_alignableNode = reElement->alignableTransform()->getDefTransform();
260
261 const RpcIdHelper& id_helper{m_idHelperSvc->rpcIdHelper()};
262
263 for (unsigned gasGap = 1; gasGap <= reElement->nGasGaps(); ++gasGap) {
264 for (int doubPhi = reElement->doubletPhi(); doubPhi <= reElement->doubletPhiMax(); ++doubPhi) {
265 for (bool measPhi: {false, true}) {
266 unsigned numStrip = (measPhi ? reElement->nPhiStrips() :
267 reElement->nEtaStrips());
268 for (unsigned strip = 1; strip <= numStrip ; ++strip) {
269
270 bool isValid{false};
271 const Identifier stripID = id_helper.channelID(reElement->identify(),
272 reElement->doubletZ(),
273 doubPhi, gasGap, measPhi, strip, isValid);
274 if (!isValid) {
275 ATH_MSG_WARNING("Invalid Identifier detected for readout element "
276 <<m_idHelperSvc->toStringDetEl(reElement->identify())
277 <<" gap: "<<gasGap<<" strip: "<<strip<<" meas phi: "<<measPhi);
278 continue;
279 }
280 const IdentifierHash measHash = reElement->measurementHash(stripID);
281 const IdentifierHash layHash = reElement->layerHash(measHash);
282 const Amg::Vector3D stripPos = reElement->stripPosition(gctx, measHash);
283 m_stripPos.push_back(stripPos);
284 m_locStripPos.push_back((reElement->globalToLocalTransform(gctx, layHash) * stripPos).block<2,1>(0,0));
285 m_stripPosGasGap.push_back(gasGap);
286 m_stripPosMeasPhi.push_back(measPhi);
287 m_stripPosNum.push_back(strip);
288 m_stripDblPhi.push_back(doubPhi);
289
290 if (strip != 1) continue;
291 const Amg::Transform3D locToGlob = reElement->localToGlobalTransform(gctx, layHash)
292 * Amg::getRotateZ3D(90.*Gaudi::Units::deg * measPhi);
293 m_stripRot.push_back(locToGlob);
294 m_stripRotGasGap.push_back(gasGap);
295 m_stripRotMeasPhi.push_back(measPhi);
296 m_stripRotDblPhi.push_back(doubPhi);
297 }
298 }
299 }
300 }
301 return m_tree.fill(ctx) ? StatusCode::SUCCESS : StatusCode::FAILURE;
302}
303
304}
305
#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)
virtual StatusCode execute()
Execute method without EventContext (deprecated).
const ServiceHandle< StoreGateSvc > & detStore() const
This is a "hash" representation of an Identifier.
Gaudi::Property< bool > m_visualStrips
Flag toggling whether the strip planes shall be printed.
void visualizeStripPanel(const EventContext &ctx, const StripDesignPtr &design, const Identifier &detId, const bool measPhi) const
Draw the strips in the panel on a Canvas.
MuonVal::ScalarBranch< float > & m_envelopeHeight
Box dimension.
ServiceHandle< MuonValR4::IRootVisualizationService > m_visualSvc
Service handle of the visualization service.
MuonVal::CoordSystemsBranch m_stripRot
Rotation matrix of the respective layers.
Gaudi::Property< std::vector< std::string > > m_selectStat
String should be formated like <stationName><stationEta><A/C><stationPhi>.
MuonValR4::IRootVisualizationService::ClientToken m_clientToken
Token to be presented to the visualization service.
MuonVal::ScalarBranch< uint8_t > & m_numRpcLayers
Number of eta & phi gas gaps.
MuonVal::ScalarBranch< uint8_t > & m_numStripsEta
Number of strips, strip pitch in eta & phi direction.
StatusCode dumpToTree(const EventContext &ctx, const ActsTrk::GeometryContext &gctx, const RpcReadoutElement *readoutEle)
MuonVal::ScalarBranch< unsigned short > & m_stIndex
Identifier of the readout element.
MuonVal::CoordTransformBranch m_readoutTransform
Transformation of the readout element (Translation, ColX, ColY, ColZ).
MuonVal::ScalarBranch< float > & m_stripEtaPitch
Strip dimensions.
std::set< Identifier > m_testStations
Set of stations to be tested.
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.
unsigned nPhiStrips() const
Number of strips measuring the phi coordinate.
IdentifierHash measurementHash(const Identifier &measId) const override final
Constructs the identifier hash from the full measurement Identifier.
int doubletR() const
Returns the doublet R field of the MuonReadoutElement identifier.
int doubletZ() const
Returns the doublet Z field of the MuonReadoutElement identifier.
int doubletPhi() const
Returns the doublet Phi field of the MuonReadoutElement identifier.
double stripPhiLength() const
Returns the length of a phi strip.
IdentifierHash layerHash(const Identifier &measId) const override final
The layer hash removes the bits from the IdentifierHash corresponding to the measurement's channel nu...
double stripEtaWidth() const
Strip width in eta.
Identifier measurementId(const IdentifierHash &measHash) const override final
Back conversion of the measurement hash to a full Athena Identifier The behaviour is undefined if a l...
double stripPhiPitch() const
Strip pitch in phi.
unsigned nEtaStrips() const
Number of strips measuring the eta coordinate.
double stripEtaPitch() const
Strip pitch in eta.
Amg::Vector3D stripPosition(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the position of the strip center.
int nPhiPanels() const
Returns the number of phi panels (1 or 2).
double stripPhiWidth() const
Strip width in phi.
unsigned nGasGaps() const
Returns the number of gasgaps described by this ReadOutElement (usally 2 or 3).
double stripEtaLength() const
Returns the length of an eta strip.
const_id_iterator detectorElement_begin() const
Iterators over full set of ids.
const_id_iterator detectorElement_end() const
Identifier channelID(int stationName, int stationEta, int stationPhi, int doubletR, int doubletZ, int doubletPhi, int gasGap, int measuresPhi, int strip) const
Identifier elementID(int stationName, int stationEta, int stationPhi, int doubletR) const
int doubletPhi(const Identifier &id) const
int doubletR(const Identifier &id) const
int doubletZ(const Identifier &id) 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.
bool doesNotDeform(const Amg::Transform3D &trans)
Checks whether the linear part of the transformation rotates or stetches any of the basis vectors.
Amg::Transform3D getRotateZ3D(double angle)
get a rotation transformation around Z-axis
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...
GeoModel::TransientConstSharedPtr< StripDesign > StripDesignPtr
Definition StripDesign.h:29
Lightweight algorithm to read xAOD MDT sim hits and (fast-digitised) drift circles from SG and fill a...
constexpr int hollowFilling
Filling codes for hollow / fullFilling / hatched filling.
std::unique_ptr< TLatex > drawLabel(const std::string &text, const double xPos, const double yPos, const double textSize=18, const bool useNDC=true, const int color=kBlack)
Create a TLatex label,.
std::unique_ptr< TBox > drawBox(const Amg::Vector3D &boxCenter, const double boxWidth, const double boxHeight, const int color=kGreen+2, const int fillStyle=hollowFilling, const int view=objViewEta)
Creates a box for drawing, e.g strip measurements.
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
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.