5#if defined(FLATTEN) && defined(__GNUC__)
7#pragma GCC optimize "-fno-var-tracking-assignments"
19#include <GaudiKernel/SystemOfUnits.h>
21#include "Acts/Geometry/TrapezoidVolumeBounds.hpp"
22#include "Acts/Geometry/TrackingGeometry.hpp"
23#include "Acts/Geometry/DiamondVolumeBounds.hpp"
24#include "Acts/Surfaces/TrapezoidBounds.hpp"
25#include "Acts/Surfaces/CylinderBounds.hpp"
26#include "Acts/Surfaces/RadialBounds.hpp"
27#include "Acts/Surfaces/CylinderSurface.hpp"
28#include "Acts/Surfaces/DiscSurface.hpp"
29#include "Acts/Geometry/VolumePlacementBase.hpp"
31#include "Acts/Visualization/ObjVisualization3D.hpp"
32#include "Acts/Visualization/GeometryView3D.hpp"
33#include "Acts/Definitions/Units.hpp"
39using namespace Acts::UnitLiterals;
43 constexpr double tolerance = 10. *Gaudi::Units::micrometer;
47 std::vector<std::shared_ptr<const Acts::Volume>> vols{};
48 std::ranges::transform(sector.
chambers(),std::back_inserter(vols),
49 [&gctx](
const auto& ch){ return ch->boundingVolume(gctx); });
52 std::vector<const Acts::Volume*> chamberVolumes(
const Acts::TrackingVolume& vol) {
53 std::vector<const Acts::Volume*>
children {};
54 for (
const Acts::TrackingVolume& childVol : vol.volumes()) {
55 std::vector<const Acts::Volume*> grandChildren = chamberVolumes(childVol);
62 std::vector<const Acts::Surface*> extractSurfaces(
const std::vector<const MuonGMR4::MuonReadoutElement*>& reEles){
63 std::vector<const Acts::Surface*> surfaces{};
64 for (
const auto*
re : reEles) {
65 std::ranges::transform(
re->getSurfaces(), std::back_inserter(surfaces),
66 [](
const std::shared_ptr<Acts::Surface>& surface) { return surface.get() ; });
71 std::vector<const Acts::Surface*> extractSurfaces(
const Acts::TrackingVolume& volume) {
72 std::vector<const Acts::Surface*> surfaces{};
73 std::ranges::for_each(volume.surfaces(), [&surfaces](
const Acts::Surface& surface){
74 if (surface.isSensitive()) {
75 surfaces.push_back(&surface);
78 for (
const Acts::TrackingVolume& subVol : volume.volumes()) {
79 std::vector<const Acts::Surface*> childSurfaces = extractSurfaces(subVol);
80 surfaces.insert(surfaces.end(), childSurfaces.begin(), childSurfaces.end());
91 bool insideInterval(
const double testLow,
const double testHigh,
92 const double envLow,
const double envHigh) {
93 return envLow < testLow && testHigh < envHigh;
96 bool outsideInterval(
const double testLow,
const double testHigh,
97 const double envLow,
const double envHigh) {
98 return testHigh < envLow || envHigh < testLow;
101 bool overlapsInterval(
const double testLow,
const double testHigh,
102 const double envLow,
const double envHigh) {
103 return !insideInterval(testLow, testHigh, envLow, envHigh) &&
104 !outsideInterval(testLow, testHigh, envLow, envHigh);
115 return StatusCode::SUCCESS;
117 template <
class EnvelopeType>
118#if defined(FLATTEN) && defined(__GNUC__)
127 const EnvelopeType& chamb,
128 const Acts::Volume& boundVol,
130 const std::string& descr,
137 if (boundVol.volumeBounds().inside(locPos,
tolerance)) {
139 <<
", point "<<descr <<
" is inside of the chamber "<<std::endl<<chamb<<std::endl
141 return StatusCode::SUCCESS;
145 planeTrapezoid.
defineTrapezoid(chamb.halfXShort(), chamb.halfXLong(), chamb.halfY());
146 planeTrapezoid.
setLevel(MSG::VERBOSE);
148 static const Eigen::Rotation2D axisSwap{90. *Gaudi::Units::deg};
149 if (std::abs(locPos.z()) - chamb.halfZ() < -
tolerance &&
151 return StatusCode::SUCCESS;
155 << descr <<
" "<<
Amg::toString(point)<<
" is not part of the chamber volume."
156 <<std::endl<<std::endl<<chamb<<std::endl<<
"Local position "<<
Amg::toString(locPos)
157 <<
", "<<planeTrapezoid
160 return StatusCode::FAILURE;
164 const Acts::TrackingVolume& volume,
166 const std::string& descr,
169 return StatusCode::SUCCESS;
171 const std::vector<Amg::Vector3D> volumeCorners =
cornerPoints(gctx, volume);
174 <<
" is not part of the chamber volume. The corners of the volume are:");
175 for(
const auto& corner : volumeCorners) {
178 return StatusCode::FAILURE;
181 template <
class EnvelopeType>
183 const EnvelopeType& envelope)
const {
184 std::shared_ptr<Acts::Volume> boundVol = envelope.boundingVolume(gctx);
187 if constexpr (std::is_same_v<EnvelopeType, SpectrometerSector>) {
188 if (readOut->msSector() != &envelope) {
190 <<std::endl<<(*readOut->msSector())<<std::endl<<envelope);
191 return StatusCode::FAILURE;
193 }
else if constexpr (std::is_same_v<EnvelopeType, Chamber>) {
194 if (readOut->chamber() != &envelope) {
196 <<std::endl<<(*readOut->chamber())<<std::endl<<envelope);
197 return StatusCode::FAILURE;
200 switch (readOut->detectorType()) {
224 return StatusCode::FAILURE;
228 ATH_MSG_DEBUG(
"All "<<reEles.size()<<
" readout elements are embedded in "<<envelope);
229 return StatusCode::SUCCESS;
234 const auto& bounds = volume.volumeBounds();
235 unsigned int edgeIdx{0};
237 if(bounds.type() == Acts::VolumeBounds::BoundsType::eDiamond){
238 const auto& diamondBounds =
static_cast<const Acts::DiamondVolumeBounds&
>(bounds);
239 using BoundEnum = Acts::DiamondVolumeBounds::BoundValues;
240 std::vector<Amg::Vector3D> edges(12, Amg::Vector3D::Zero());
243 for(
double signX : {-1.,1.}){
244 for(
double signY : {-1., 0., 1.}){
245 for(
double signZ : {-1.,1.}){
247 xCord = diamondBounds.get(BoundEnum::eHalfLengthX2);
249 xCord = diamondBounds.get(BoundEnum::eHalfLengthX1);
250 yCord = diamondBounds.get(BoundEnum::eLengthY1);
252 xCord = diamondBounds.get(BoundEnum::eHalfLengthX3);
253 yCord = diamondBounds.get(BoundEnum::eLengthY2);
258 signZ*diamondBounds.get(BoundEnum::eHalfLengthZ)};
259 edges[edgeIdx] = volume.localToGlobalTransform(gctx.
context())*edge;
269 std::vector<Amg::Vector3D> edges{};
271 for (
const double signX : {-1., 1.}) {
272 for (
const double signY : { -1., 1.}) {
273 for (
const double signZ: {-1., 1.}) {
277 edges.push_back(volume.localToGlobalTransform(gctx.
context()) * edge);
288 using BoundEnum = Acts::LineBounds::BoundValues;
289 const auto& bounds =
static_cast<const Acts::LineBounds&
>(surface.bounds());
290 unsigned int edgeIdx{0};
293 for (
const double signX : {-1., 1.}) {
294 for (
const double signY : { -1., 1.}) {
295 for (
const double signZ: {-1., 1.}) {
297 signY*bounds.get(BoundEnum::eR),
298 signZ*bounds.get(BoundEnum::eHalfLengthZ)};
299 edges[edgeIdx] = surface.localToGlobalTransform(gctx.
context()) * edge;
309 if(surface.bounds().type() == Acts::SurfaceBounds::BoundsType::eRectangle) {
310 const Acts::RectangleBounds& bounds =
static_cast<const Acts::RectangleBounds&
>(surface.bounds());
311 using BoundEnum = Acts::RectangleBounds::BoundValues;
313 unsigned int edgeIdx{0};
314 for(
const double signX : {-1., 1.}) {
315 for (
const double signY : { -1., 1.}) {
316 const Amg::Vector3D edge{signX < 0 ? bounds.get(BoundEnum::eMinX) : bounds.get(BoundEnum::eMaxX),
317 signY < 0 ? bounds.get(BoundEnum::eMinY) : bounds.get(BoundEnum::eMaxY), 0.};
318 edges[edgeIdx] = surface.localToGlobalTransform(gctx.
context()) * edge;
323 }
else if(surface.bounds().type() == Acts::SurfaceBounds::BoundsType::eTrapezoid) {
324 using BoundEnum = Acts::TrapezoidBounds::BoundValues;
325 const auto& bounds =
static_cast<const Acts::TrapezoidBounds&
>(surface.bounds());
326 unsigned int edgeIdx{0};
329 for (
const double signX : {-1., 1.}) {
330 for (
const double signY : { -1., 1.}) {
332 Amg::Vector3D(signX*bounds.get(signY < 0 ? BoundEnum::eHalfLengthXnegY : BoundEnum::eHalfLengthXposY),
333 signY*bounds.get(BoundEnum::eHalfLengthY), 0.)};
335 edges[edgeIdx] = surface.localToGlobalTransform(gctx.
context()) * edge;
342 ATH_MSG_ERROR(
"The surface bounds are neither a rectangle nor a trapezoid, this is not supported yet");
348#if defined(FLATTEN) && defined(__GNUC__)
357 const std::vector<Amg::Vector3D>& chamberEdges,
358 const Acts::Volume& volume)
const {
362 double minDist = 1._km;
364 minDist = std::min(minDist, (edge - center).
mag());
368 if (std::ranges::none_of(volume.volumeBounds().values(),
369 [minDist](
const double bound){
370 return minDist < 2.5*bound;
376 const Acts::VolumeBounds& volBounds = volume.volumeBounds();
377 const Acts::Transform3& transform = volume.globalToLocalTransform(gctx.
context());
378 for (
unsigned edge1 = 1; edge1 < chamberEdges.size(); ++edge1) {
379 for (
unsigned edge2 = 0; edge2 < edge1; ++edge2) {
381 const double section = stepLength * step;
386 if (volBounds.inside (transform * testPoint)) {
396 std::vector<const MuonReadoutElement*> allRE =
m_detMgr->getAllReadoutElements();
399 ATH_MSG_INFO(
"Fetched "<<chambers.size()<<
" chambers.");
400 std::vector<const Chamber*> chamberVec{chambers.begin(), chambers.end()};
403 return std::ranges::find(chamberVec,
re->chamber()) == chamberVec.end();
405 if (missChamb != allRE.end()) {
406 ATH_MSG_ERROR(
"The chamber "<<(*(*missChamb)->chamber())<<
" is not in the chamber set");
407 return StatusCode::FAILURE;
412 std::vector<std::shared_ptr<Acts::Volume> > chamberBoundsVec;
413 chamberBoundsVec.reserve (chamberVec.size());
414 for (
const Chamber* ch : chamberVec)
415 chamberBoundsVec.push_back (ch->boundingVolume(gctx));
417 std::set<const Chamber*> overlapChambers{};
418 std::stringstream overlapstream{};
419 for (std::size_t chIdx = 0; chIdx< chamberVec.size(); ++chIdx) {
420 const Chamber& chamber{*chamberVec[chIdx]};
421 const Acts::Volume& chamberBounds = *chamberBoundsVec[chIdx];
423 saveEnvelope(gctx, std::format(
"Chamber_{:}{:}{:}{:}{:}",
425 chName(chamber.chamberIndex()),
426 Acts::abs(chamber.stationEta()),
427 chamber.stationEta() > 0 ?
'A' :
'C',
428 chamber.stationPhi()),
429 chamberBounds, extractSurfaces(chamber.readoutEles()));
432 const std::vector<Amg::Vector3D> chambCorners =
cornerPoints(gctx, chamberBounds);
434 std::vector<const Chamber*> overlaps{};
435 for (std::size_t chIdx1 = 0; chIdx1<chamberVec.size(); ++chIdx1) {
436 if (chIdx == chIdx1) {
439 const Chamber* overlapTest{chamberVec[chIdx1]};
440 if (
hasOverlap(gctx, chambCorners, *chamberBoundsVec[chIdx1])) {
441 overlaps.push_back(overlapTest);
444 if (overlaps.empty()) {
447 overlapstream<<
"The chamber "<<chamber<<
" overlaps with "<<std::endl;
448 for (
const Chamber* itOverlaps : overlaps) {
449 overlapstream<<
" *** "<<(*itOverlaps)<<std::endl;
451 overlapstream<<std::endl<<std::endl;
452 overlapChambers.insert(overlaps.begin(), overlaps.end());
453 overlapChambers.insert(chamberVec[chIdx]);
455 if (!overlapChambers.empty()) {
456 Acts::ObjVisualization3D visualHelper{};
458 Acts::GeometryView3D::drawVolume(visualHelper, *
hasOverlap->boundingVolume(gctx), gctx.
context());
467 ATH_MSG_INFO(
"Chamber test completed. Found "<<overlapChambers.size()<<
" overlapping chambers");
468 return overlapChambers.empty() ||
m_ignoreOverlapCh ? StatusCode::SUCCESS : StatusCode::FAILURE;
473 std::vector<const MuonReadoutElement*> allREs =
m_detMgr->getAllReadoutElements();
475 if (!
re->msSector()) {
477 return StatusCode::FAILURE;
482 if (sectorFromDet !=
re->msSector()) {
485 <<
" is not the one attached to the readout geometry \n"<<(*
re->msSector())<<
"\n"<<(*sectorFromDet));
486 return StatusCode::FAILURE;
490 const SectorSet sectors =
m_detMgr->getAllSectors();
491 ATH_MSG_INFO(__func__<<
"() "<<__LINE__<<
" - Fetched "<<sectors.size()<<
" sectors. ");
494 const auto subVols = chamberVolumes(gctx, *sector);
496 chName(sector->chamberIndex()),
497 sector->side() >0?
'A' :
'C',
498 sector->stationPhi() ),
499 *sector->boundingVolume(gctx),
500 extractSurfaces(sector->readoutEles()),
501 Acts::unpackSmartPointers(subVols));
504 const std::shared_ptr<Acts::Volume> secVolume = sector->boundingVolume(gctx);
506 const std::vector<Amg::Vector3D> edges =
cornerPoints(gctx, *chamber->boundingVolume(gctx));
507 unsigned int edgeCount{0};
510 chamber->readoutEles().front()->identify()));
514 ATH_MSG_INFO(__func__<<
"() "<<__LINE__<<
" - Sector envelope test completed.");
515 return StatusCode::SUCCESS;
518 const Acts::TrackingVolume& volume)
const {
519 if (!volume.isAlignable()) {
520 return StatusCode::SUCCESS;
522 const Acts::GeometryContext geoCtx = gctx.
context();
523 std::vector<std::shared_ptr<const Acts::Surface>> portals{};
524 for (
const Acts::Portal& portal : volume.portals()) {
525 if (portal.surface().geometryId().withBoundary(0) != volume.geometryId()) {
528 portals.push_back(portal.surface().getSharedPtr());
530 const auto unAlignedPortals = volume.volumeBounds().orientedSurfaces(volume.localToGlobalTransform(geoCtx));
532 if (unAlignedPortals.size() != portals.size()) {
533 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - The size of the aligned and unaligned portals don't match for volume "
534 <<volume.volumeName()<<
". Aligned: "<<portals.size()<<
", unaligned: "<<unAlignedPortals.size());
535 return StatusCode::FAILURE;
537 StatusCode retCode = StatusCode::SUCCESS;
538 for (std::size_t p =0 ; p < portals.size(); ++p){
540 if (portals[p]->bounds() != unAlignedPortals[p].surface->bounds()) {
541 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - The bounds of the "<<p
542 <<
"-th portal differ:\n -- aligned: "<<portals[p]->bounds()
543 <<
"\n -- unaligned: "<<unAlignedPortals[p].surface->bounds());
544 retCode = StatusCode::FAILURE;
546 const Amg::Transform3D& uTrf{unAlignedPortals[p].surface->localToGlobalTransform(geoCtx)};
551 <<
" - The unaligned and aligned portals don't end up at the same point \n"
553 retCode = StatusCode::FAILURE;
561 const Acts::TrackingGeometry& trackingGeometry)
const {
565 std::vector<const Acts::TrackingVolume*> volumeVec{};
566 std::vector<const Acts::Surface*> surfacesVec{};
568 std::unordered_set<const Acts::TrackingVolume*> overlapVolumes{};
569 std::unordered_set<const Acts::Surface*> overlapSurfaces{};
573 trackingGeometry.visitVolumes([&](
const Acts::TrackingVolume* vol) {
575 if(vol->volumeBounds().type() == Acts::VolumeBounds::BoundsType::eCylinder){
576 std::ranges::for_each(vol->surfaces(), [&](
const auto& surf){
577 surfacesVec.push_back(&surf);
584 ATH_MSG_DEBUG(
"checkTrackingGeometry() "<<__LINE__<<
" - Skip volume "
585 <<vol->volumeName()<<
".");
588 volumeVec.push_back(vol);
592 << surfacesVec.size()<<
" surfaces");
593 StatusCode retCode = StatusCode::SUCCESS;
594 for(std::size_t vIdx = 0; vIdx < volumeVec.size(); ++vIdx) {
595 const Acts::TrackingVolume* testVol{volumeVec.at(vIdx)};
598 std::vector<const Acts::TrackingVolume*> overlaps{};
599 const std::vector<Amg::Vector3D> edges =
cornerPoints(gctx, *testVol);
601 for(
const auto& surface : testVol->surfaces()) {
603 std::vector<Amg::Vector3D> surfEdges = {};
604 if(surface.type() == Acts::Surface::SurfaceType::Straw){
605 ATH_MSG_VERBOSE(__func__<<
"() - "<<__LINE__<<
" Checking "<<surface.type()<<
" surface "<<identify(surface)
606 <<
" / "<<surface.geometryId() <<
" in volume "<<testVol->volumeName());
608 auto edges =
cornerPoints(gctx,
dynamic_cast<const Acts::StrawSurface&
>(surface));
609 surfEdges.insert(surfEdges.end() , edges.begin(), edges.end());
610 }
else if(surface.type() == Acts::Surface::SurfaceType::Plane){
611 ATH_MSG_VERBOSE(__func__<<
"() - "<<__LINE__<<
" Checking "<<surface.type()<<
" surface "<<identify(surface)
612 <<
" / "<<surface.geometryId() <<
" in volume "<<testVol->volumeName());
614 auto edges =
cornerPoints(gctx,
dynamic_cast<const Acts::PlaneSurface&
>(surface));
615 surfEdges.insert(surfEdges.end() , edges.begin(), edges.end());
617 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - The "<<surface.type()<<
"-surface "
619 <<surface.geometryId() <<
" is neither a straw nor a plane surface");
620 return StatusCode::FAILURE;
623 for(
const auto& edge : surfEdges) {
624 if(!testVol->inside(gctx.
context(), edge, 0.01)) {
625 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - The "<<surface.type()<<
"-surface "
627 <<surface.geometryId() <<
" @vertex point "
630 <<
" is outside the parent volume: " << testVol->volumeName()
632 <<
", "<<testVol->volumeBounds());
633 overlapSurfaces.insert(&surface);
634 overlapVolumes.insert(testVol);
636 retCode = StatusCode::FAILURE;
643 for (
const Acts::TrackingVolume& child : testVol->volumes()) {
645 if(!testVol->inside(gctx.
context(), edge, 0.01)){
646 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - The children volume's "
647 << child.volumeName() <<
" vertex point " <<
Amg::toString(edge)
648 <<
" is outside the parent volume" << testVol->volumeName());
649 return StatusCode::FAILURE;
654 if (!testVol->motherVolume()->isAlignable() &&
m_dumpObjs) {
655 std::vector<const Acts::Surface*> surfaces = extractSurfaces(*testVol);
656 const Identifier volId = identify(*surfaces.front());
658 saveEnvelope(gctx, std::format(
"TrackingVolume_{:}{:}{:}{:}_{:}",
660 Acts::abs(
eta),
eta > 0 ?
'A' :
'C',
662 *testVol, surfaces , chamberVolumes(*testVol));
666 for (std::size_t vIdx1 = 0 ; vIdx1 < vIdx; ++vIdx1) {
667 const Acts::TrackingVolume* overlapTest{volumeVec.at(vIdx1)};
668 if (overlapTest->motherVolume() == testVol ||
669 testVol->motherVolume() == overlapTest){
673 overlaps.push_back(overlapTest);
674 std::ranges::copy(extractSurfaces(*testVol),
675 std::inserter(overlapSurfaces, overlapSurfaces.begin()));
676 std::ranges::copy(extractSurfaces(*overlapTest),
677 std::inserter(overlapSurfaces, overlapSurfaces.begin()));
682 const Identifier volId = identify(*extractSurfaces(*testVol).front());
683 double volHalfR{0.}, volHalfZ{0.};
694 const double rMin = center.perp() - volHalfR;
697 const double rMax = (testVol->localToGlobalTransform(gctx.
context()) *(
698 halfX * Amg::Vector3D::UnitX() +
699 volHalfR * Amg::Vector3D::Unit(1 +
isBarrel))).perp();
701 const double zMin = center.z() - volHalfZ;
702 const double zMax = center.z() + volHalfZ;
704 for(
const Acts::Surface* surf : surfacesVec) {
705 double surfRMin{0.}, surfRMax{0.},
halfZ{0.};
708 <<
" surface "<<surf->name()<<
" , "<<surf->geometryId());
710 if(surf->type() == Acts::Surface::SurfaceType::Cylinder) {
711 using BoundEnum = Acts::CylinderBounds::BoundValues;
712 const auto& bounds =
static_cast<const Acts::CylinderBounds&
>(surf->bounds());
713 surfRMax = bounds.get(BoundEnum::eR) + 2._mm;
714 surfRMin = bounds.get(BoundEnum::eR) - 2._mm;
716 halfZ = bounds.get(BoundEnum:: eHalfLengthZ);
717 }
else if(surf->type() == Acts::Surface::SurfaceType::Disc){
718 using BoundEnum = Acts::RadialBounds::BoundValues;
719 const auto& bounds =
static_cast<const Acts::RadialBounds&
>(surf->bounds());
720 surfRMax = bounds.get(BoundEnum::eMaxR);
721 surfRMin = bounds.get(BoundEnum::eMinR);
723 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - The surface "<< surf->geometryId()
724 <<
", "<< surf->name() <<
" is not a cylinder surface or disc");
725 return StatusCode::FAILURE;
730 const double surfZMin = center.z() -
halfZ;
731 const double surfZMax = center.z() +
halfZ;
733 const bool rOverlap = overlapsInterval(rMin, rMax, surfRMin, surfRMax);
734 const bool zOverlap = overlapsInterval(zMin, zMax, surfZMax, surfZMax);
736 const bool rOutside = outsideInterval(rMin, rMax, surfRMin, surfRMax);
737 const bool zOutside = outsideInterval(zMin, zMax, surfZMax, surfZMax);
738 if ( (!rOverlap && !zOverlap) || (rOverlap && zOutside) ||
739 (zOverlap && rOutside)) {
744 << testVol->volumeName() <<
" overlaps with the surface "
745 << surf->name() <<
" with geo id" << surf->geometryId()
746 <<
" -- volume radius: ["<<rMin<<
";"<<rMax<<
"] z: ["<<zMin<<
";"<<zMax<<
"]"
747 <<
" -- surface radius: ["<<surfRMin<<
";"<<surfRMax<<
"] z: ["<<surfZMin<<
";"<<surfZMax<<
"]");
749 retCode = StatusCode::FAILURE;
751 overlapSurfaces.insert(surf);
752 overlapVolumes.insert(testVol);
755 if(overlaps.empty()) {
756 ATH_MSG_DEBUG(__func__<<
"() "<<__LINE__<<
" - No overlaps detected for the volume "<<testVol->volumeName());
760 overlapVolumes.insert(overlaps.begin(), overlaps.end());
761 overlapVolumes.insert(testVol);
763 std::stringstream overlapStream{};
764 overlapStream<<__func__<<
"() "<<__LINE__<<
" - The volume "
765 <<testVol->volumeName() <<
" overlaps with: "<<std::endl;
767 for(
const Acts::TrackingVolume* overlap: overlaps){
768 overlapStream<<
" --- Volume: " << overlap->volumeName()<<
", "<<overlap->volumeBounds()
774 if (overlapVolumes.size() || overlapSurfaces.size()) {
775 const Acts::Volume* refVolume = (*overlapVolumes.begin());
776 std::vector<const Acts::Volume*> childVols{};
777 childVols.insert(childVols.begin(),std::next(overlapVolumes.begin()), overlapVolumes.end());
778 std::vector<const Acts::Surface*> childSurfs{overlapSurfaces.begin(), overlapSurfaces.end()};
779 saveEnvelope(gctx,
"TrackingGeometryOverlaps", *refVolume,
780 childSurfs, childVols);
784 if(overlapVolumes.empty()) {
785 ATH_MSG_ALWAYS(
"No overlaps detected in the tracking geometry!!");
787 retCode = StatusCode::FAILURE;
793 const std::string& envName,
794 const Acts::Volume& envelopeVol,
795 const std::vector<const Acts::Surface*>& assocSurfaces,
796 const std::vector<const Acts::Volume*>& subVols)
const {
797 Acts::ObjVisualization3D visualHelper{};
798 std::ranges::for_each(assocSurfaces, [&visualHelper, &gctx](
const Acts::Surface* surface) {
799 Acts::GeometryView3D::drawSurface(visualHelper, *surface, gctx.
context());
802 std::ranges::for_each(subVols, [&visualHelper, &gctx](
const Acts::Volume* subVol) {
803 Acts::GeometryView3D::drawVolume(visualHelper,*subVol, gctx.
context(), Amg::Transform3D::Identity(),
804 Acts::s_viewPassive);
806 Acts::GeometryView3D::drawVolume(visualHelper, envelopeVol, gctx.
context());
807 ATH_MSG_DEBUG(
"Save new envelope 'MsTrackTest_"<<envName<<
".obj'");
808 visualHelper.write(std::format(
"MsTrackTest_{:}.obj", envName));
819 return StatusCode::SUCCESS;
821 template <
class EnvelopeType>
824 const EnvelopeType& chamber,
825 const Acts::Volume& detVol)
const {
828 for (
unsigned int layer = 1; layer <= mdtMl.
numLayers(); ++layer) {
829 for (
unsigned int tube = 1; tube <= mdtMl.
numTubesInLay(); ++tube) {
843 "bottom of the tube box", measId));
845 "sealing of the tube box", measId));
848 "wall to the previous tube", measId));
850 "wall to the next tube", measId));
853 return StatusCode::SUCCESS;
855 template<
class EnvelopeType>
858 const EnvelopeType& chamber,
859 const Acts::Volume& detVol)
const {
864 for (
unsigned int gasGap = 1 ; gasGap <= rpc.
nGasGaps(); ++gasGap) {
866 for (
bool measPhi : {
false,
true}) {
870 doubletPhi, gasGap, measPhi,
strip);
878 return StatusCode::SUCCESS;
880 template <
class EnevelopeType>
883 const EnevelopeType& chamber,
884 const Acts::Volume& detVol)
const {
885 for (
unsigned int gasGap = 1; gasGap <= tgc.
nGasGaps(); ++gasGap){
886 for (
bool isStrip : {
false}) {
888 const unsigned int nChannel = tgc.
numChannels(layHash);
889 for (
unsigned int channel = 1; channel <= nChannel ; ++channel) {
896 return StatusCode::SUCCESS;
898 template <
class EnevelopeType>
901 const EnevelopeType& chamber,
902 const Acts::Volume& detVol)
const {
905 for(
unsigned int gasGap = 1; gasGap <= mm.nGasGaps(); ++gasGap){
907 unsigned int firstStrip = mm.firstStrip(gasGapHash);
908 for(
unsigned int strip = firstStrip;
strip <= mm.numStrips(gasGapHash); ++
strip){
910 ATH_CHECK(
pointInside(gctx, chamber, detVol, mm.stripPosition(gctx, stripId),
"center", stripId));
911 ATH_CHECK(
pointInside(gctx, chamber, detVol, mm.leftStripEdge(gctx, mm.measurementHash(stripId)),
"left edge", stripId));
912 ATH_CHECK(
pointInside(gctx, chamber, detVol, mm.rightStripEdge(gctx, mm.measurementHash(stripId)),
"right edge", stripId));
916 return StatusCode::SUCCESS;
918 template <
class EnvelopeType>
921 const EnvelopeType& chamber,
922 const Acts::Volume& detVol)
const{
925 for(
unsigned int gasGap = 1; gasGap <= stgc.
numLayers(); ++gasGap){
927 for(
unsigned int nch = 1; nch <= stgc.
nChTypes(); ++nch){
929 const unsigned int nStrips = stgc.
numChannels(gasGapHash);
944 return StatusCode::SUCCESS;
const boost::regex re(r_e)
Scalar eta() const
pseudorapidity method
Scalar mag() const
mag method
constexpr std::array< T, N > make_array(const T &def_val)
Helper function to initialize in-place arrays with non-zero values.
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_ALWAYS(x)
#define ATH_MSG_WARNING(x)
Acts::GeometryContext context() const
base class interface providing the bare minimal interface extension.
virtual Identifier identify() const =0
Return the ATLAS identifier.
Implementation to make a (tracking) volume alignable.
const ServiceHandle< StoreGateSvc > & detStore() const
void setLevel(MSG::Level lvl)
Change the current logging level.
This is a "hash" representation of an Identifier.
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int channel) const
Chamber represent the volume enclosing a muon station.
std::vector< const MuonReadoutElement * > ReadoutSet
Define the list of read out elements of the chamber.
Readout element to describe the Monitored Drift Tube (Mdt) chambers Mdt chambers usually comrpise out...
Amg::Vector3D highVoltPos(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the endpoint of the tube connected to the high voltage in the ATLAS coordinate frame.
unsigned numLayers() const
Returns how many tube layers are inside the multi layer [1;4].
bool isValid(const IdentifierHash &measHash) const
Checks whether the passed meaurement hash corresponds to a valid tube described by the readout elemen...
Amg::Vector3D readOutPos(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the endpoint of the tube where the readout card is mounted in the ATLAS coordinate frame.
const parameterBook & getParameters() const
Get a const reference to the parameter book.
Amg::Vector3D globalTubePos(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the position of the tube mid point in the ATLAS coordinate frame.
double innerTubeRadius() const
Returns the inner tube radius.
unsigned numTubesInLay() const
Returns the number of tubes in a layer.
static IdentifierHash measurementHash(unsigned layerNumber, unsigned tubeNumber)
Constructs a Measurement hash from layer && tube number.
Identifier measurementId(const IdentifierHash &measHash) const override final
Back conversion of the measurement hash towards a full identifier Tube & layer number are extracted f...
static IdentifierHash createHash(const int gasGap, const int strip)
std::vector< const Chamber * > MuonChamberSet
std::vector< const SpectrometerSector * > MuonSectorSet
MuonReadoutElement is an abstract class representing the geometry of a muon detector.
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...
Identifier identify() const override final
Return the ATLAS identifier.
unsigned nPhiStrips() const
Number of strips measuring the phi coordinate.
Amg::Vector3D leftStripEdge(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the global posiition of the strip edge at positive local Y.
int doubletZ() const
Returns the doublet Z field of the MuonReadoutElement identifier.
int doubletPhi() const
Returns the doublet Phi field of the MuonReadoutElement identifier.
Amg::Vector3D rightStripEdge(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the global position of the strip edge at negative local Y.
unsigned nEtaStrips() const
Number of strips measuring the eta coordinate.
int doubletPhiMax() const
Returns the maximum phi panel.
const parameterBook & getParameters() const
Amg::Vector3D stripPosition(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the position of the strip center.
unsigned nGasGaps() const
Returns the number of gasgaps described by this ReadOutElement (usally 2 or 3)
A spectrometer sector forms the envelope of all chambers that are placed in the same MS sector & laye...
const ChamberSet & chambers() const
Returns the associated chambers with this sector.
GeoModel::TransientConstSharedPtr< Chamber > ChamberPtr
void defineStripLayout(Amg::Vector2D &&posFirst, const double stripPitch, const double stripWidth, const int numStrips, const int numFirst=1)
Defines the layout of the strip detector by specifing the position of the first strip w....
CheckVector2D leftEdge(int stripNumb) const
Returns the left edge of the strip (Global numbering scheme)
void defineTrapezoid(double HalfShortY, double HalfLongY, double HalfHeight)
Defines the edges of the trapezoid.
bool insideTrapezoid(const Amg::Vector2D &extPos) const
Checks whether an external point is inside the trapezoidal area.
CheckVector2D rightEdge(int stripNumb) const
Returns the right edge of the strip (Global numbering scheme)
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...
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...
static IdentifierHash constructHash(unsigned measCh, unsigned gasGap, const bool isStrip)
Constructs the Hash out of the Identifier fields (channel, gasGap, isStrip)
unsigned numChannels(const IdentifierHash &measHash) const
Returns the number of readout channels.
unsigned nGasGaps() const
Returns the number of gasgaps described by this ReadOutElement (usally 2 or 3)
unsigned numChannels(const IdentifierHash &measHash) const
Returns the number of strips / wires / pads in a given gasGap.
IdentifierHash measurementHash(const Identifier &measId) const override final
Constructs the identifier hash from the full measurement Identifier.
Amg::Vector3D leftStripEdge(const ActsTrk::GeometryContext &ctx, const IdentifierHash &measHash) const
int multilayer() const
Returns the multilayer of the sTgcReadoutElement.
unsigned nChTypes() const
Number of Channel Types.
Amg::Vector3D rightStripEdge(const ActsTrk::GeometryContext &ctx, const IdentifierHash &measHash) const
unsigned numLayers() const
Returns the number of gas gap layers.
ReadoutChannelType
ReadoutChannelType to distinguish the available readout channels Pad - pad readout channel Strip - et...
Amg::Vector3D globalChannelPosition(const ActsTrk::GeometryContext &ctx, const IdentifierHash &measHash) const
Returns the global pad/strip/wireGroup position.
static IdentifierHash createHash(const unsigned gasGap, const unsigned channelType, const unsigned channel, const unsigned wireInGrp=0)
Create a measurement hash from the Identifier fields.
Identifier channelID(int stationName, int stationEta, int stationPhi, int doubletR, int doubletZ, int doubletPhi, int gasGap, int measuresPhi, int strip) const
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int gasGap, int channelType, int channel) const
std::string to_string(const DetectorType &type)
@ Mm
Maybe not needed in the migration.
@ Tgc
Resitive Plate Chambers.
@ Rpc
Monitored Drift Tubes.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
bool isIdentity(const Amg::Transform3D &trans)
Checks whether the transformation is the Identity transformation.
Amg::Transform3D getRotateZ3D(double angle)
get a rotation transformation around Z-axis
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
The ReadoutGeomCnvAlg converts the Run4 Readout geometry build from the GeoModelXML into the legacy M...
double halfY(const Acts::VolumeBounds &bounds)
Returns the half-Y length for the parsed volume bounds (Trapezoid/ Cuboid)
SpectrometerSector::ChamberSet ChamberSet
bool isMuon(const ActsTrk::DetectorType type)
Returns whether the parsed type is muon.
double halfZ(const Acts::VolumeBounds &bounds)
Returns the half-Z length for the parsed volume bounds (Trapezoid/ Cuboid)
double halfXhighY(const Acts::VolumeBounds &bounds)
Returns the half-Y length @ posiive Y for the parsed volume bounds (Trapezoid/ Cuboid)
double halfXlowY(const Acts::VolumeBounds &bounds)
Returns the half-X length @ negative Y for the parsed volume bounds (Trapezoid/ Cuboid)
bool isBarrel(const ChIndex index)
Returns true if the chamber index points to a barrel chamber.
const std::string & chName(ChIndex index)
convert ChIndex into a string
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
const Identifier & identify(const UncalibratedMeasurement *meas)
Returns the associated identifier from the muon measurement.