ATLAS Offline Software
MuonChamberToolTest.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #if defined(FLATTEN) && defined(__GNUC__)
6 // Avoid warning in dbg build
7 #pragma GCC optimize "-fno-var-tracking-assignments"
8 #endif
9 
10 #include "MuonChamberToolTest.h"
11 
19 #include <GaudiKernel/SystemOfUnits.h>
20 
21 #include "Acts/Geometry/TrapezoidVolumeBounds.hpp"
22 #include "Acts/Geometry/TrackingGeometry.hpp"
23 #include "Acts/Surfaces/TrapezoidBounds.hpp"
24 
25 #include "Acts/Visualization/ObjVisualization3D.hpp"
26 #include "Acts/Visualization/GeometryView3D.hpp"
27 #include "Acts/Definitions/Units.hpp"
28 
30 
31 using namespace Acts::UnitLiterals;
32 using namespace Muon::MuonStationIndex;
33 
34 
35 #include <format>
36 namespace{
37  constexpr double tolerance = 10. *Gaudi::Units::micrometer;
38 
39  std::vector<std::shared_ptr<Acts::Volume>> chamberVolumes(const ActsTrk::GeometryContext& gctx,
40  const MuonGMR4::SpectrometerSector& sector) {
41  std::vector<std::shared_ptr<Acts::Volume>> vols{};
42  std::ranges::transform(sector.chambers(),std::back_inserter(vols),
43  [&gctx](const auto& ch){ return ch->boundingVolume(gctx); });
44  return vols;
45  }
46 }
47 
48 namespace MuonGMR4 {
49 
51  ATH_CHECK(m_idHelperSvc.retrieve());
52  ATH_CHECK(m_geoCtxKey.initialize());
53  ATH_CHECK(m_trackingGeometrySvc.retrieve());
54  ATH_CHECK(detStore()->retrieve(m_detMgr));
55  return StatusCode::SUCCESS;
56  }
57  template <class EnvelopeType>
58 #if defined(FLATTEN) && defined(__GNUC__)
59 // We compile this function with optimization, even in debug builds; otherwise,
60 // the heavy use of Eigen makes it too slow. However, from here we may call
61 // to out-of-line Eigen code that is linked from other DSOs; in that case,
62 // it would not be optimized. Avoid this by forcing all Eigen code
63 // to be inlined here if possible.
64 [[gnu::flatten]]
65 #endif
66  StatusCode MuonChamberToolTest::pointInside(const EnvelopeType& chamb,
67  const Acts::Volume& boundVol,
68  const Amg::Vector3D& point,
69  const std::string& descr,
70  const Identifier& channelId) const {
71 
72  // Explicitly inline Volume::inside here so that it gets
73  // flattened in debug builds.
74  Acts::Vector3 posInVolFrame((boundVol.transform().inverse()) * point);
75  if (boundVol.volumeBounds().inside(posInVolFrame,tolerance)) {
76  ATH_MSG_VERBOSE("In channel "<<m_idHelperSvc->toString(channelId)
77  <<", point "<<descr <<" is inside of the chamber "<<std::endl<<chamb<<std::endl
78  <<"Local position:" <<Amg::toString(boundVol.itransform() * point));
79  return StatusCode::SUCCESS;
80  }
81  const Amg::Vector3D locPos{boundVol.itransform() * point};
82 
83  StripDesign planeTrapezoid{};
84  planeTrapezoid.defineTrapezoid(chamb.halfXShort(), chamb.halfXLong(), chamb.halfY());
85  planeTrapezoid.setLevel(MSG::VERBOSE);
87  static const Eigen::Rotation2D axisSwap{90. *Gaudi::Units::deg};
88  if (std::abs(locPos.z()) - chamb.halfZ() < -tolerance &&
89  planeTrapezoid.insideTrapezoid(axisSwap*locPos.block<2,1>(0,0))) {
90  return StatusCode::SUCCESS;
91  }
92  planeTrapezoid.defineStripLayout(locPos.y() * Amg::Vector2D::UnitX(), 1, 1, 1);
93  ATH_MSG_FATAL("In channel "<<m_idHelperSvc->toString(channelId) <<", the point "
94  << descr <<" "<<Amg::toString(point)<<" is not part of the chamber volume."
95  <<std::endl<<std::endl<<chamb<<std::endl<<"Local position "<<Amg::toString(locPos)
96  <<", "<<planeTrapezoid
97  <<", box left edge: "<<Amg::toString(planeTrapezoid.leftEdge(1).value_or(Amg::Vector2D::Zero()))
98  <<", box right edge "<<Amg::toString(planeTrapezoid.rightEdge(1).value_or(Amg::Vector2D::Zero())));
99  return StatusCode::FAILURE;
100  }
101 
102  StatusCode MuonChamberToolTest::pointInside(const Acts::TrackingVolume& volume,
103  const Amg::Vector3D& point,
104  const std::string& descr,
105  const Identifier& chamberId) const {
106  if (volume.inside(point, tolerance)) {
107  return StatusCode::SUCCESS;
108  }
109  const std::array<Amg::Vector3D, 8> volumeCorners = cornerPoints(volume);
110  ATH_MSG_FATAL("In channel "<<m_idHelperSvc->toString(chamberId) <<", the point "
111  << descr <<" "<<Amg::toString(volume.itransform()* point)<<" is not part of the chamber volume. The corners of the volume are:");
112  for(const auto& corner : volumeCorners) {
113  ATH_MSG_FATAL(" "<<Amg::toString(volume.itransform()*corner));
114  }
115  return StatusCode::FAILURE;
116  }
117 
118  template <class EnvelopeType>
119  StatusCode MuonChamberToolTest::allReadoutInEnvelope(const ActsTrk::GeometryContext& gctx,
120  const EnvelopeType& envelope) const {
121  std::shared_ptr<Acts::Volume> boundVol = envelope.boundingVolume(gctx);
122  const Chamber::ReadoutSet reEles = envelope.readoutEles();
123  for(const MuonReadoutElement* readOut : reEles) {
124  if constexpr (std::is_same_v<EnvelopeType, SpectrometerSector>) {
125  if (readOut->msSector() != &envelope) {
126  ATH_MSG_FATAL("Mismatch in the sector association "<<m_idHelperSvc->toStringDetEl(readOut->identify())
127  <<std::endl<<(*readOut->msSector())<<std::endl<<envelope);
128  return StatusCode::FAILURE;
129  }
130  } else if constexpr (std::is_same_v<EnvelopeType, Chamber>) {
131  if (readOut->chamber() != &envelope) {
132  ATH_MSG_FATAL("Mismatch in the chamber association "<<m_idHelperSvc->toStringDetEl(readOut->identify())
133  <<std::endl<<(*readOut->chamber())<<std::endl<<envelope);
134  return StatusCode::FAILURE;
135  }
136  }
137  switch (readOut->detectorType()) {
139  const auto* detEle = static_cast<const TgcReadoutElement*>(readOut);
140  ATH_CHECK(testReadoutEle(gctx, *detEle, envelope, *boundVol));
141  break;
143  const auto* detEle = static_cast<const MdtReadoutElement*>(readOut);
144  ATH_CHECK(testReadoutEle(gctx, *detEle, envelope, *boundVol));
145  break;
147  const auto* detEle = static_cast<const RpcReadoutElement*>(readOut);
148  ATH_CHECK(testReadoutEle(gctx, *detEle, envelope, *boundVol));
149  break;
150  } case ActsTrk::DetectorType::Mm: {
151  const auto* detEle = static_cast<const MmReadoutElement*>(readOut);
152  ATH_CHECK(testReadoutEle(gctx, *detEle, envelope, *boundVol));
153  break;
155  const auto* detEle = static_cast<const sTgcReadoutElement*>(readOut);
156  ATH_CHECK(testReadoutEle(gctx, *detEle, envelope, *boundVol));
157  break;
158  } default: {
159  ATH_MSG_FATAL("Who came up with putting "<<ActsTrk::to_string(readOut->detectorType())
160  <<" into the MS");
161  return StatusCode::FAILURE;
162  }
163  }
164  }
165  ATH_MSG_DEBUG("All "<<reEles.size()<<" readout elements are embedded in "<<envelope);
166  return StatusCode::SUCCESS;
167  }
168 
169  std::array<Amg::Vector3D, 8> MuonChamberToolTest::cornerPoints(const Acts::Volume& volume) const {
170  std::array<Amg::Vector3D, 8> edges{make_array<Amg::Vector3D,8>(Amg::Vector3D::Zero())};
171  unsigned int edgeIdx{0};
172  ATH_MSG_VERBOSE("Fetch volume bounds "<<Amg::toString(volume.transform()));
173  const auto& bounds = volume.volumeBounds();
174  for (const double signX : {-1., 1.}) {
175  for (const double signY : { -1., 1.}) {
176  for (const double signZ: {-1., 1.}) {
177  const Amg::Vector3D edge{signX* (signY>0 ? MuonGMR4::halfXhighY(bounds) : MuonGMR4::halfXlowY(bounds)),
178  signY*MuonGMR4::halfY(bounds),
179  signZ*MuonGMR4::halfZ(bounds)};
180  edges[edgeIdx] = volume.transform() * edge;
181  ATH_MSG_VERBOSE("Local edge "<<Amg::toString(edge)<<", global edge: "<<Amg::toString(edges[edgeIdx]));
182  ++edgeIdx;
183  }
184  }
185  }
186  return edges;
187  }
188 
189  std::array<Amg::Vector3D, 8> MuonChamberToolTest::cornerPoints(const Acts::GeometryContext& gctx, const Acts::StrawSurface& surface) const {
190  std::array<Amg::Vector3D, 8> edges{make_array<Amg::Vector3D,8>(Amg::Vector3D::Zero())};
191  using BoundEnum = Acts::LineBounds::BoundValues;
192  const auto& bounds = static_cast<const Acts::LineBounds&>(surface.bounds());
193  unsigned int edgeIdx{0};
194 
195  ATH_MSG_VERBOSE("Fetch volume bounds "<<Amg::toString(surface.transform(gctx)));
196  for (const double signX : {-1., 1.}) {
197  for (const double signY : { -1., 1.}) {
198  for (const double signZ: {-1., 1.}) {
199  const Amg::Vector3D edge{signX*bounds.get(BoundEnum::eR),
200  signY*bounds.get(BoundEnum::eR),
201  signZ*bounds.get(BoundEnum::eHalfLengthZ)};
202  edges[edgeIdx] = surface.transform(gctx) * edge;
203  ++edgeIdx;
204  }
205  }
206  }
207  return edges;
208  }
209 
210  std::array<Amg::Vector3D, 4> MuonChamberToolTest::cornerPoints(const Acts::GeometryContext& gctx, const Acts::PlaneSurface& surface) const {
211  std::array<Amg::Vector3D, 4> edges{make_array<Amg::Vector3D,4>(Amg::Vector3D::Zero())};
212  if(surface.bounds().type() == Acts::SurfaceBounds::BoundsType::eRectangle) { //RPC surfaces are rectangles
213  const Acts::RectangleBounds& bounds = static_cast<const Acts::RectangleBounds&>(surface.bounds());
214  using BoundEnum = Acts::RectangleBounds::BoundValues;
215 
216  unsigned int edgeIdx{0};
217  for(const double signX : {-1., 1.}) {
218  for (const double signY : { -1., 1.}) {
219  const Amg::Vector3D edge{signX < 0 ? bounds.get(BoundEnum::eMinX) : bounds.get(BoundEnum::eMaxX),
220  signY < 0 ? bounds.get(BoundEnum::eMinY) : bounds.get(BoundEnum::eMaxY), 0.};
221  edges[edgeIdx] = surface.transform(gctx) * edge;
222  ++edgeIdx;
223  }
224  }
225  return edges;
226  } else if(surface.bounds().type() == Acts::SurfaceBounds::BoundsType::eTrapezoid) {
227  using BoundEnum = Acts::TrapezoidBounds::BoundValues;
228  const auto& bounds = static_cast<const Acts::TrapezoidBounds&>(surface.bounds());
229  unsigned int edgeIdx{0};
230 
231  ATH_MSG_VERBOSE("Fetch volume bounds "<<Amg::toString(surface.transform(gctx)));
232  for (const double signX : {-1., 1.}) {
233  for (const double signY : { -1., 1.}) {
234  const Amg::Vector3D edge{Amg::getRotateZ3D(-1.*bounds.get(BoundEnum::eRotationAngle)) *
235  Amg::Vector3D(signX*bounds.get(signY < 0 ? BoundEnum::eHalfLengthXnegY : BoundEnum::eHalfLengthXposY),
236  signY*bounds.get(BoundEnum::eHalfLengthY), 0.)};
237 
238  edges[edgeIdx] = surface.transform(gctx) * edge;
239  ++edgeIdx;
240  }
241  }
242 
243  return edges;
244  } else {
245  ATH_MSG_FATAL("The surface bounds are neither a rectangle nor a trapezoid, this is not supported yet");
246  return edges;
247  }
248  }
249  bool MuonChamberToolTest::hasOverlap(const std::array<Amg::Vector3D, 8>& chamberEdges,
250  const Acts::Volume& volume) const {
251 
253  const Amg::Vector3D center{volume.center()};
254  double minDist = 1._km;
255  for (const Amg::Vector3D& edge : chamberEdges) {
256  minDist = std::min(minDist, (edge - center).mag());
257  }
260  std::vector<double> boundValues = volume.volumeBounds().values();
261  if (std::ranges::none_of(boundValues, [minDist](const double bound){
262  return minDist < 2.5*bound;
263  })) {
264  return false;
265  }
266  const double stepLength = 1. / m_overlapSamples;
267  for (unsigned edge1 = 1; edge1 < chamberEdges.size(); ++edge1) {
268  for (unsigned edge2 = 0; edge2 < edge1; ++edge2) {
269  for (unsigned step = 0 ; step <= m_overlapSamples; ++step) {
270  const double section = stepLength * step;
271  const Amg::Vector3D testPoint = section* chamberEdges[edge1] + (1. -section) *chamberEdges[edge2];
272  if (volume.inside(testPoint)) {
273  return true;
274  }
275  }
276  }
277  }
278  return false;
279  }
280  StatusCode MuonChamberToolTest::checkChambers(const ActsTrk::GeometryContext& gctx) const {
281 
282  std::vector<const MuonReadoutElement*> allRE = m_detMgr->getAllReadoutElements();
284  const ChamberSet chambers = m_detMgr->getAllChambers();
285  ATH_MSG_INFO("Fetched "<<chambers.size()<<" chambers.");
286  std::vector<const Chamber*> chamberVec{chambers.begin(), chambers.end()};
287 
288  const auto missChamb = std::ranges::find_if(allRE, [&chamberVec](const MuonGMR4::MuonReadoutElement* re){
289  return std::ranges::find(chamberVec, re->chamber()) == chamberVec.end();
290  });
291  if (missChamb != allRE.end()) {
292  ATH_MSG_FATAL("The chamber "<<(*(*missChamb)->chamber())<<" is not in the chamber set");
293  return StatusCode::FAILURE;
294  }
295 
296  std::set<const Chamber*> overlapChambers{};
297  std::stringstream overlapstream{};
298  for (std::size_t chIdx = 0; chIdx< chamberVec.size(); ++chIdx) {
299  const Chamber& chamber{*chamberVec[chIdx]};
300  if (m_dumpObjs) {
301  saveEnvelope(gctx, std::format("Chamber_{:}{:}{:}{:}{:}",
302  ActsTrk::to_string(chamber.detectorType()),
303  chName(chamber.chamberIndex()),
304  Acts::abs(chamber.stationEta()),
305  chamber.stationEta() > 0 ? 'A' : 'C',
306  chamber.stationPhi()),
307  *chamber.boundingVolume(gctx), chamber.readoutEles());
308  }
309  ATH_CHECK(allReadoutInEnvelope(gctx, chamber));
310  const std::array<Amg::Vector3D, 8> chambCorners = cornerPoints(*chamber.boundingVolume(gctx));
312  std::vector<const Chamber*> overlaps{};
313  for (std::size_t chIdx1 = 0; chIdx1<chamberVec.size(); ++chIdx1) {
314  if (chIdx == chIdx1) {
315  continue;
316  }
317  const Chamber* overlapTest{chamberVec[chIdx1]};
318  if (hasOverlap(chambCorners, *(overlapTest->boundingVolume(gctx)))) {
319  overlaps.push_back(overlapTest);
320  }
321  }
322  if (overlaps.empty()) {
323  continue;
324  }
325  overlapstream<<"The chamber "<<chamber<<" overlaps with "<<std::endl;
326  for (const Chamber* itOverlaps : overlaps) {
327  overlapstream<<" *** "<<(*itOverlaps)<<std::endl;
328  }
329  overlapstream<<std::endl<<std::endl;
330  overlapChambers.insert(overlaps.begin(), overlaps.end());
331  overlapChambers.insert(chamberVec[chIdx]);
332  }
333  if (!overlapChambers.empty()) {
334  Acts::ObjVisualization3D visualHelper{};
335  for (const Chamber* hasOverlap: overlapChambers) {
336  Acts::GeometryView3D::drawVolume(visualHelper, *hasOverlap->boundingVolume(gctx), gctx.context());
337  visualHelper.write(m_overlapChambObj.value());
338  }
339  if (m_ignoreOverlapCh) {
340  ATH_MSG_WARNING(overlapstream.str());
341  } else {
342  ATH_MSG_FATAL(overlapstream.str());
343  }
344  }
345  return overlapChambers.empty() || m_ignoreOverlapCh ? StatusCode::SUCCESS : StatusCode::FAILURE;
346  }
347 
348  StatusCode MuonChamberToolTest::checkEnvelopes(const ActsTrk::GeometryContext& gctx) const {
349 
350  std::vector<const MuonReadoutElement*> allREs = m_detMgr->getAllReadoutElements();
351  for (const MuonReadoutElement* re : allREs) {
352  if (!re->msSector()) {
353  ATH_MSG_FATAL("The readout element "<<m_idHelperSvc->toStringDetEl(re->identify())<<" does not have any sector associated ");
354  return StatusCode::FAILURE;
355  }
356  const SpectrometerSector* sectorFromDet = m_detMgr->getSectorEnvelope(re->chamberIndex(),
357  m_idHelperSvc->sector(re->identify()),
358  re->stationEta());
359  if (sectorFromDet != re->msSector()) {
360  ATH_MSG_FATAL("The sector attached to "<<m_idHelperSvc->toStringDetEl(re->identify())
361  <<", chIdx: "<<chName(re->chamberIndex())<<", sector: "<<m_idHelperSvc->sector(re->identify())
362  <<" is not the one attached to the readout geometry \n"<<(*re->msSector())<<"\n"<<(*sectorFromDet));
363  return StatusCode::FAILURE;
364  }
365  }
366  using SectorSet = MuonDetectorManager::MuonSectorSet;
367  const SectorSet sectors = m_detMgr->getAllSectors();
368  ATH_MSG_INFO("Fetched "<<sectors.size()<<" sectors. ");
369  for (const SpectrometerSector* sector : sectors) {
370  if (m_dumpObjs) {
371  saveEnvelope(gctx, std::format("Sector_{:}{:}{:}",
372  chName(sector->chamberIndex()),
373  sector->side() >0? 'A' :'C',
374  sector->stationPhi() ),
375  *sector->boundingVolume(gctx), sector->readoutEles(),
376  chamberVolumes(gctx, *sector));
377  }
378  ATH_CHECK(allReadoutInEnvelope(gctx, *sector));
379  const std::shared_ptr<Acts::Volume> secVolume = sector->boundingVolume(gctx);
380  for (const SpectrometerSector::ChamberPtr& chamber : sector->chambers()){
381  const std::array<Amg::Vector3D, 8> edges = cornerPoints(*chamber->boundingVolume(gctx));
382  unsigned int edgeCount{0};
383  for (const Amg::Vector3D& edge : edges) {
384  ATH_CHECK(pointInside(*sector,*secVolume, edge, std::format("Edge {:}", ++edgeCount),
385  chamber->readoutEles().front()->identify()));
386  }
387  }
388  }
389  return StatusCode::SUCCESS;
390  }
391  void MuonChamberToolTest::saveEnvelope(const ActsTrk::GeometryContext& gctx,
392  const std::string& envName,
393  const Acts::Volume& envelopeVol,
394  const std::vector<const MuonGMR4::MuonReadoutElement*>& assocRE,
395  const std::vector<std::shared_ptr<Acts::Volume>>& subVols) const {
396  Acts::ObjVisualization3D visualHelper{};
397  std::ranges::for_each(assocRE, [&visualHelper, &gctx](const MuonReadoutElement* re){
398  std::ranges::for_each(re->getSurfaces(),[&visualHelper, &gctx](const std::shared_ptr<Acts::Surface>& surface){
399  Acts::GeometryView3D::drawSurface(visualHelper, *surface, gctx.context());
400  });
401  });
402  std::ranges::for_each(subVols, [&visualHelper, &gctx](const std::shared_ptr<Acts::Volume>& subVol ){
403  Acts::GeometryView3D::drawVolume(visualHelper,*subVol, gctx.context(), Amg::Transform3D::Identity(),
404  Acts::s_viewPassive);
405  });
406  Acts::GeometryView3D::drawVolume(visualHelper, envelopeVol, gctx.context());
407  ATH_MSG_DEBUG("Save new envelope 'MsTrackTest_"<<envName<<".obj'");
408  visualHelper.write(std::format("MsTrackTest_{:}.obj", envName));
409  }
410 
411  StatusCode MuonChamberToolTest::execute(const EventContext& ctx) const {
412  const ActsTrk::GeometryContext* gctx{nullptr};
413  ATH_CHECK(SG::get(gctx, m_geoCtxKey, ctx));
414  std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry = m_trackingGeometrySvc->trackingGeometry();
416  ATH_CHECK(checkChambers(*gctx));
417  ATH_CHECK(checkEnvelopes(*gctx));
418 
419  return StatusCode::SUCCESS;
420  }
421  template <class EnvelopeType>
422  StatusCode MuonChamberToolTest::testReadoutEle(const ActsTrk::GeometryContext& gctx,
423  const MdtReadoutElement& mdtMl,
424  const EnvelopeType& chamber,
425  const Acts::Volume& detVol) const {
426  ATH_MSG_VERBOSE("Test whether "<<m_idHelperSvc->toStringDetEl(mdtMl.identify())<<std::endl<<mdtMl.getParameters());
427 
428  for (unsigned int layer = 1; layer <= mdtMl.numLayers(); ++layer) {
429  for (unsigned int tube = 1; tube <= mdtMl.numTubesInLay(); ++tube) {
430  const IdentifierHash idHash = mdtMl.measurementHash(layer, tube);
431  if (!mdtMl.isValid(idHash)){
432  continue;
433  }
434  const Amg::Transform3D& locToGlob{mdtMl.localToGlobalTrans(gctx, idHash)};
435  const Identifier measId{mdtMl.measurementId(idHash)};
436 
437  ATH_CHECK(pointInside(chamber, detVol, mdtMl.globalTubePos(gctx, idHash), "tube center", measId));
438 
439  ATH_CHECK(pointInside(chamber, detVol, mdtMl.readOutPos(gctx, idHash), "tube readout", measId));
440  ATH_CHECK(pointInside(chamber, detVol, mdtMl.highVoltPos(gctx, idHash), "tube HV", measId));
441 
442  ATH_CHECK(pointInside(chamber, detVol, locToGlob*(-mdtMl.innerTubeRadius() * Amg::Vector3D::UnitX()),
443  "bottom of the tube box", measId));
444  ATH_CHECK(pointInside(chamber, detVol, locToGlob*(mdtMl.innerTubeRadius() * Amg::Vector3D::UnitX()),
445  "sealing of the tube box", measId));
446 
447  ATH_CHECK(pointInside(chamber, detVol, locToGlob*(-mdtMl.innerTubeRadius() * Amg::Vector3D::UnitY()),
448  "wall to the previous tube", measId));
449  ATH_CHECK(pointInside(chamber, detVol, locToGlob*(-mdtMl.innerTubeRadius() * Amg::Vector3D::UnitY()),
450  "wall to the next tube", measId));
451  }
452  }
453  return StatusCode::SUCCESS;
454  }
455  template<class EnvelopeType>
456  StatusCode MuonChamberToolTest::testReadoutEle(const ActsTrk::GeometryContext& gctx,
457  const RpcReadoutElement& rpc,
458  const EnvelopeType& chamber,
459  const Acts::Volume& detVol) const {
460 
461  ATH_MSG_VERBOSE("Test whether "<<m_idHelperSvc->toStringDetEl(rpc.identify())<<std::endl<<rpc.getParameters());
462 
463  const RpcIdHelper& idHelper{m_idHelperSvc->rpcIdHelper()};
464  for (unsigned int gasGap = 1 ; gasGap <= rpc.nGasGaps(); ++gasGap) {
465  for (int doubletPhi = rpc.doubletPhi(); doubletPhi <= rpc.doubletPhiMax(); ++doubletPhi){
466  for (bool measPhi : {false, true}) {
467  const int nStrips = measPhi ? rpc.nPhiStrips() : rpc.nEtaStrips();
468  for (int strip = 1; strip <= nStrips; ++strip) {
469  const Identifier stripId = idHelper.channelID(rpc.identify(),rpc.doubletZ(),
470  doubletPhi, gasGap, measPhi, strip);
471  ATH_CHECK(pointInside(chamber, detVol, rpc.stripPosition(gctx, stripId), "center", stripId));
472  ATH_CHECK(pointInside(chamber, detVol, rpc.leftStripEdge(gctx, stripId), "right edge", stripId));
473  ATH_CHECK(pointInside(chamber, detVol, rpc.rightStripEdge(gctx, stripId), "left edge", stripId));
474  }
475  }
476  }
477  }
478  return StatusCode::SUCCESS;
479  }
480  template <class EnevelopeType>
481  StatusCode MuonChamberToolTest::testReadoutEle(const ActsTrk::GeometryContext& gctx,
482  const TgcReadoutElement& tgc,
483  const EnevelopeType& chamber,
484  const Acts::Volume& detVol) const {
485  for (unsigned int gasGap = 1; gasGap <= tgc.nGasGaps(); ++gasGap){
486  for (bool isStrip : {false}) {
487  const IdentifierHash layHash = tgc.constructHash(0, gasGap, isStrip);
488  const unsigned int nChannel = tgc.numChannels(layHash);
489  for (unsigned int channel = 1; channel <= nChannel ; ++channel) {
490  const IdentifierHash measHash = tgc.constructHash(channel, gasGap, isStrip);
491  ATH_CHECK(pointInside(chamber, detVol, tgc.channelPosition(gctx, measHash), "center", tgc.measurementId(measHash)));
492  }
493  }
494  }
495  return StatusCode::SUCCESS;
496  }
497  template <class EnevelopeType>
498  StatusCode MuonChamberToolTest::testReadoutEle(const ActsTrk::GeometryContext& gctx,
499  const MmReadoutElement& mm,
500  const EnevelopeType& chamber,
501  const Acts::Volume& detVol) const {
502 
503  const MmIdHelper& idHelper{m_idHelperSvc->mmIdHelper()};
504  for(unsigned int gasGap = 1; gasGap <= mm.nGasGaps(); ++gasGap){
505  IdentifierHash gasGapHash = MmReadoutElement::createHash(gasGap,0);
506  unsigned int firstStrip = mm.firstStrip(gasGapHash);
507  for(unsigned int strip = firstStrip; strip <= mm.numStrips(gasGapHash); ++strip){
508  const Identifier stripId = idHelper.channelID(mm.identify(), mm.multilayer(), gasGap, strip);
509  ATH_CHECK(pointInside(chamber, detVol, mm.stripPosition(gctx, stripId), "center", stripId));
510  ATH_CHECK(pointInside(chamber, detVol, mm.leftStripEdge(gctx, mm.measurementHash(stripId)), "left edge", stripId));
511  ATH_CHECK(pointInside(chamber, detVol, mm.rightStripEdge(gctx, mm.measurementHash(stripId)), "right edge", stripId));
512  }
513  }
514 
515  return StatusCode::SUCCESS;
516  }
517  template <class EnvelopeType>
518  StatusCode MuonChamberToolTest::testReadoutEle(const ActsTrk::GeometryContext& gctx,
519  const sTgcReadoutElement& stgc,
520  const EnvelopeType& chamber,
521  const Acts::Volume& detVol) const{
522 
523  const sTgcIdHelper& idHelper{m_idHelperSvc->stgcIdHelper()};
524  for(unsigned int gasGap = 1; gasGap <= stgc.numLayers(); ++gasGap){
525 
526  for(unsigned int nch = 1; nch <= stgc.nChTypes(); ++nch){
527  IdentifierHash gasGapHash = sTgcReadoutElement::createHash(gasGap, nch, 0, 0);
528  const unsigned int nStrips = stgc.numChannels(gasGapHash);
530 
531  for(unsigned int strip = 1; strip <= nStrips; ++strip){
532  const Identifier stripId = idHelper.channelID(stgc.identify(), stgc.multilayer(), gasGap, nch, strip);
533  ATH_CHECK(pointInside(chamber, detVol, stgc.globalChannelPosition(gctx, stripId), "channel position", stripId));
534 
535  if(channelType == sTgcReadoutElement::ReadoutChannelType::Wire || channelType == sTgcReadoutElement::ReadoutChannelType::Strip){
536  ATH_CHECK(pointInside(chamber, detVol, stgc.rightStripEdge(gctx, stgc.measurementHash(stripId)), "channel position", stripId));
537  ATH_CHECK(pointInside(chamber, detVol, stgc.leftStripEdge(gctx, stgc.measurementHash(stripId)), "channel position", stripId));
538  }
539  }
540  }
541  }
542  return StatusCode::SUCCESS;
543 
544  }
545 }
546 
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
MuonGMR4::RpcReadoutElement::doubletPhiMax
int doubletPhiMax() const
Returns the maximum phi panel.
MuonGMR4::sTgcReadoutElement::multilayer
int multilayer() const
Returns the multilayer of the sTgcReadoutElement.
GeoModel::TransientConstSharedPtr
The TransientConstSharedPtr allows non-const access if the pointer itself is non-const but in the con...
Definition: TransientConstSharedPtr.h:13
MuonGMR4::MmReadoutElement
Definition: MmReadoutElement.h:18
dumpTgcDigiDeadChambers.gasGap
list gasGap
Definition: dumpTgcDigiDeadChambers.py:33
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
MuonGMR4::StripDesign
Definition: StripDesign.h:30
sendEI_SPB.ch
ch
Definition: sendEI_SPB.py:35
python.SystemOfUnits.mm
float mm
Definition: SystemOfUnits.py:98
MuonGMR4::RpcReadoutElement::nGasGaps
unsigned nGasGaps() const
Returns the number of gasgaps described by this ReadOutElement (usally 2 or 3)
MuonGMR4::SpectrometerSector
A spectrometer sector forms the envelope of all chambers that are placed in the same MS sector & laye...
Definition: SpectrometerSector.h:40
MuonGMR4::MdtReadoutElement::numTubesInLay
unsigned int numTubesInLay() const
Returns the number of tubes per layer.
MuonGMR4::sTgcReadoutElement::globalChannelPosition
Amg::Vector3D globalChannelPosition(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the global pad/strip/wireGroup position.
plotting.yearwise_efficiency.channel
channel
Definition: yearwise_efficiency.py:24
vtune_athena.format
format
Definition: vtune_athena.py:14
MuonGMR4::MdtReadoutElement::readOutPos
Amg::Vector3D readOutPos(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the global position of the readout card.
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:138
MuonGMR4::sTgcReadoutElement::numChannels
unsigned int numChannels(const Identifier &measId) const
Returns the number of strips / wires / pads in a given gasGap.
Muon::MuonStationIndex
Definition: MuonStationIndex.h:13
calibdata.chamber
chamber
Definition: calibdata.py:31
MuonGMR4::SpectrometerSector::chambers
const ChamberSet & chambers() const
Returns the associated chambers with this sector.
Definition: SpectrometerSector.cxx:62
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
initialize
void initialize()
Definition: run_EoverP.cxx:894
MuonGMR4::MdtReadoutElement::measurementHash
static IdentifierHash measurementHash(unsigned int layerNumber, unsigned int tubeNumber)
Transform the layer and tube number to the measurementHash.
CaloCondBlobAlgs_fillNoiseFromASCII.nChannel
nChannel
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:90
ActsTrk::DetectorType::Tgc
@ Tgc
Resitive Plate Chambers.
MuonGMR4::MuonReadoutElement
The MuonReadoutElement is an abstract class representing the geometry representing the muon detector.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MuonReadoutElement.h:38
MuonGMR4::sTgcReadoutElement::nChTypes
unsigned int nChTypes() const
Number of Channel Types.
deg
#define deg
Definition: SbPolyhedron.cxx:17
MuonGMR4::halfXhighY
double halfXhighY(const Acts::VolumeBounds &bounds)
Returns the half-Y length @ posiive Y for the parsed volume bounds (Trapezoid/ Cuboid)
Definition: MuonDetectorDefs.cxx:28
MuonGMR4::sTgcReadoutElement::ReadoutChannelType
ReadoutChannelType
ReadoutChannelType to distinguish the available readout channels Pad - pad readout channel Strip - et...
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/sTgcReadoutElement.h:30
MuonGMR4::halfY
double halfY(const Acts::VolumeBounds &bounds)
Returns the half-Y length for the parsed volume bounds (Trapezoid/ Cuboid)
Definition: MuonDetectorDefs.cxx:44
MuonGMR4::TgcReadoutElement::channelPosition
Amg::Vector3D channelPosition(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the center of the measurement channel eta measurement: wire gang center phi measurement: stri...
MuonGMR4::halfZ
double halfZ(const Acts::VolumeBounds &bounds)
Returns the half-Z length for the parsed volume bounds (Trapezoid/ Cuboid)
Definition: MuonDetectorDefs.cxx:61
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
ActsTrk::DetectorType::sTgc
@ sTgc
Micromegas (NSW)
MuonGMR4::sTgcReadoutElement::rightStripEdge
Amg::Vector3D rightStripEdge(const ActsTrk::GeometryContext &ctx, const IdentifierHash &measHash) const
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/sTgcReadoutElement.cxx:277
SpectrometerSector.h
MuonGMR4::RpcReadoutElement
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/RpcReadoutElement.h:17
RpcIdHelper
Definition: RpcIdHelper.h:51
MuonGMR4::TgcReadoutElement::nGasGaps
unsigned nGasGaps() const
Returns the number of gasgaps described by this ReadOutElement (usally 2 or 3)
MuonGMR4::sTgcReadoutElement::measurementHash
IdentifierHash measurementHash(const Identifier &measId) const override final
Constructs the identifier hash from the full measurement Identifier.
ReadCondHandle.h
MuonGMR4::RpcReadoutElement::getParameters
const parameterBook & getParameters() const
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/RpcReadoutElement.cxx:33
MuonGMR4::ChamberSet
SpectrometerSector::ChamberSet ChamberSet
Definition: SpectrometerSector.cxx:35
MuonGMR4::halfXlowY
double halfXlowY(const Acts::VolumeBounds &bounds)
Returns the half-X length @ negative Y for the parsed volume bounds (Trapezoid/ Cuboid)
Definition: MuonDetectorDefs.cxx:12
Amg::getRotateZ3D
Amg::Transform3D getRotateZ3D(double angle)
get a rotation transformation around Z-axis
Definition: GeoPrimitivesHelpers.h:270
LArG4FSStartPointFilterLegacy.execute
execute
Definition: LArG4FSStartPointFilterLegacy.py:20
MuonGMR4::MdtReadoutElement::measurementId
Identifier measurementId(const IdentifierHash &measHash) const override final
Converts the measurement hash back to the full Identifier.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/MdtReadoutElement.cxx:46
MuonGMR4::Chamber
Definition: Chamber.h:23
sTgcReadoutElement.h
MuonGMR4::MdtReadoutElement::globalTubePos
Amg::Vector3D globalTubePos(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the global position of the tube center.
MuonGMR4::RpcReadoutElement::rightStripEdge
Amg::Vector3D rightStripEdge(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the global position of the strip edge at negative local Y.
Amg::toString
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Definition: GeoPrimitivesToStringConverter.h:40
MuonGMR4
The ReadoutGeomCnvAlg converts the Run4 Readout geometry build from the GeoModelXML into the legacy M...
Definition: MdtCalibInput.h:19
ActsTrk::DetectorType::Mm
@ Mm
Maybe not needed in the migration.
SG::get
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
Definition: ReadCondHandle.h:283
MuonGMR4::MdtReadoutElement::highVoltPos
Amg::Vector3D highVoltPos(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the global position of the High Voltage connectors.
python.SystemOfUnits.micrometer
float micrometer
Definition: SystemOfUnits.py:80
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
Muon::MuonStationIndex::chName
const std::string & chName(ChIndex index)
convert ChIndex into a string
Definition: MuonStationIndex.cxx:119
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
MuonGMR4::sTgcReadoutElement::leftStripEdge
Amg::Vector3D leftStripEdge(const ActsTrk::GeometryContext &ctx, const IdentifierHash &measHash) const
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/sTgcReadoutElement.cxx:233
MuonGMR4::RpcReadoutElement::doubletPhi
int doubletPhi() const
Returns the doublet Phi field of the MuonReadoutElement identifier.
MuonGMR4::MdtReadoutElement::numLayers
unsigned int numLayers() const
Returns the number of tube layer.
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
MuonGMR4::Chamber::ReadoutSet
std::vector< const MuonReadoutElement * > ReadoutSet
Define the list of read out elements of the chamber.
Definition: Chamber.h:26
Amg::transform
Amg::Vector3D transform(Amg::Vector3D &v, Amg::Transform3D &tr)
Transform a point from a Trasformation3D.
Definition: GeoPrimitivesHelpers.h:156
MuonGMR4::RpcReadoutElement::nEtaStrips
unsigned nEtaStrips() const
Number of strips measuring the eta coordinate.
MuonGMR4::TgcReadoutElement::measurementId
Identifier measurementId(const IdentifierHash &measHash) const override final
Converts the measurement hash back to the full Identifier.
MuonGMR4::MuonReadoutElement::localToGlobalTrans
const Amg::Transform3D & localToGlobalTrans(const ActsTrk::GeometryContext &ctx) const
Returns the local to global transformation into the ATLAS coordinate system.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/MuonReadoutElement.cxx:81
MuonGMR4::StripDesign::defineTrapezoid
void defineTrapezoid(double HalfShortY, double HalfLongY, double HalfHeight)
Defines the edges of the trapezoid.
Definition: StripDesign.cxx:71
MuonGMR4::RpcReadoutElement::doubletZ
int doubletZ() const
Returns the doublet Z field of the MuonReadoutElement identifier.
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
python.TransformConfig.descr
descr
print "%s.properties()" % self.__name__
Definition: TransformConfig.py:359
ActsTrk::GeometryContext
Definition: GeometryContext.h:28
CaloCondBlobAlgs_fillNoiseFromASCII.channelId
channelId
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:121
MuonChamberToolTest.h
MuonGMR4::MdtReadoutElement::innerTubeRadius
double innerTubeRadius() const
Returns the inner tube radius.
tolerance
Definition: suep_shower.h:17
MuonGM::nStrips
int nStrips(const MuonGM::TgcReadoutElement &readoutEle, int layer)
Definition: MuonDetDescr/MuonGeoModelTest/src/GeoModelTgcTest.cxx:46
python.PyKernel.detStore
detStore
Definition: PyKernel.py:41
dumpTgcDigiThreshold.isStrip
list isStrip
Definition: dumpTgcDigiThreshold.py:33
ActsTrk::DetectorType::Mdt
@ Mdt
MuonSpectrometer.
MuonGMR4::MdtReadoutElement
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MdtReadoutElement.h:18
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
sTgcIdHelper
Definition: sTgcIdHelper.h:55
MuonGMR4::RpcReadoutElement::leftStripEdge
Amg::Vector3D leftStripEdge(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the global posiition of the strip edge at positive local Y.
MuonGMR4::MuonReadoutElement::identify
Identifier identify() const override final
Return the athena identifier.
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
MuonGMR4::sTgcReadoutElement::numLayers
unsigned int numLayers() const
Returns the number of gas gap layers.
MuonGMR4::sTgcReadoutElement
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/sTgcReadoutElement.h:20
RpcReadoutElement.h
Chamber.h
MmIdHelper
Definition: MmIdHelper.h:54
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
ActsTrk::MuonSectorSet
MuonGMR4::MuonDetectorManager::MuonSectorSet MuonSectorSet
Definition: MuonBlueprintNodeBuilder.h:43
MdtReadoutElement.h
re
const boost::regex re(r_e)
MuonGMR4::TgcReadoutElement::constructHash
static IdentifierHash constructHash(unsigned measCh, unsigned gasGap, const bool isStrip)
Constructs the Hash out of the Identifier fields (channel, gasGap, isStrip)
ActsTrk::DetectorType::Rpc
@ Rpc
Monitored Drift Tubes.
ActsTrk::MuonChamberSet
MuonGMR4::MuonDetectorManager::MuonChamberSet MuonChamberSet
Definition: MuonBlueprintNodeBuilder.h:42
LArCellBinning.step
step
Definition: LArCellBinning.py:158
createCablingJSON.doubletPhi
int doubletPhi
Definition: createCablingJSON.py:16
SCT_CalibAlgs::firstStrip
@ firstStrip
Definition: SCT_CalibNumbers.h:10
MuonGMR4::MdtReadoutElement::getParameters
const parameterBook & getParameters() const
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/src/MdtReadoutElement.cxx:45
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:13
section
void section(const std::string &sec)
Definition: TestTriggerMenuAccess.cxx:22
MuonGMR4::TgcReadoutElement::numChannels
unsigned numChannels(const IdentifierHash &measHash) const
Returns the number of readout channels.
FileHelpers.h
MuonGMR4::MdtReadoutElement::isValid
bool isValid(const IdentifierHash &measHash) const
mag
Scalar mag() const
mag method
Definition: AmgMatrixBasePlugin.h:26
MuonGMR4::TgcReadoutElement
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/TgcReadoutElement.h:19
MuonGMR4::RpcReadoutElement::nPhiStrips
unsigned nPhiStrips() const
Number of strips measuring the phi coordinate.
calibdata.tube
tube
Definition: calibdata.py:30
MmReadoutElement.h
generate::Zero
void Zero(TH1D *hin)
Definition: generate.cxx:32
MuonGMR4::RpcReadoutElement::stripPosition
Amg::Vector3D stripPosition(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the position of the strip center.
ActsTrk::GeometryContext::context
Acts::GeometryContext context() const
Definition: GeometryContext.h:46
Identifier
Definition: IdentifierFieldParser.cxx:14