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);
61 std::vector<const Acts::Surface*> extractSurfaces(
const std::vector<const MuonGMR4::MuonReadoutElement*>& reEles){
62 std::vector<const Acts::Surface*> surfaces{};
63 for (
const auto*
re : reEles) {
64 std::ranges::transform(
re->getSurfaces(), std::back_inserter(surfaces),
65 [](
const std::shared_ptr<Acts::Surface>& surface) { return surface.get() ; });
70 std::vector<const Acts::Surface*> extractSurfaces(
const Acts::TrackingVolume& volume) {
71 std::vector<const Acts::Surface*> surfaces{};
72 std::ranges::for_each(volume.surfaces(), [&surfaces](
const Acts::Surface& surface){
73 if (surface.isSensitive()) {
74 surfaces.push_back(&surface);
77 for (
const Acts::TrackingVolume& subVol : volume.volumes()) {
78 std::vector<const Acts::Surface*> childSurfaces = extractSurfaces(subVol);
79 surfaces.insert(surfaces.end(), childSurfaces.begin(), childSurfaces.end());
98 return StatusCode::SUCCESS;
100 template <
class EnvelopeType>
101#if defined(FLATTEN) && defined(__GNUC__)
110 const EnvelopeType& chamb,
111 const Acts::Volume& boundVol,
113 const std::string& descr,
120 if (boundVol.volumeBounds().inside(locPos,
tolerance)) {
122 <<
", point "<<descr <<
" is inside of the chamber "<<std::endl<<chamb<<std::endl
124 return StatusCode::SUCCESS;
128 planeTrapezoid.
defineTrapezoid(chamb.halfXShort(), chamb.halfXLong(), chamb.halfY());
129 planeTrapezoid.
setLevel(MSG::VERBOSE);
131 static const Eigen::Rotation2D axisSwap{90. *Gaudi::Units::deg};
132 if (std::abs(locPos.z()) - chamb.halfZ() < -
tolerance &&
134 return StatusCode::SUCCESS;
138 << descr <<
" "<<
Amg::toString(point)<<
" is not part of the chamber volume."
139 <<std::endl<<std::endl<<chamb<<std::endl<<
"Local position "<<
Amg::toString(locPos)
140 <<
", "<<planeTrapezoid
143 return StatusCode::FAILURE;
147 const Acts::TrackingVolume& volume,
149 const std::string& descr,
152 return StatusCode::SUCCESS;
156 <<
" is not part of the chamber volume. The corners of the volume are:");
160 return StatusCode::FAILURE;
163 template <
class EnvelopeType>
165 const EnvelopeType& envelope)
const {
166 std::shared_ptr<Acts::Volume> boundVol = envelope.boundingVolume(gctx);
169 if constexpr (std::is_same_v<EnvelopeType, SpectrometerSector>) {
170 if (readOut->msSector() != &envelope) {
172 <<std::endl<<(*readOut->msSector())<<std::endl<<envelope);
173 return StatusCode::FAILURE;
175 }
else if constexpr (std::is_same_v<EnvelopeType, Chamber>) {
176 if (readOut->chamber() != &envelope) {
178 <<std::endl<<(*readOut->chamber())<<std::endl<<envelope);
179 return StatusCode::FAILURE;
182 switch (readOut->detectorType()) {
206 return StatusCode::FAILURE;
210 ATH_MSG_DEBUG(
"All "<<reEles.size()<<
" readout elements are embedded in "<<envelope);
211 return StatusCode::SUCCESS;
215 const Acts::Volume& volume)
const {
217 const auto& bounds = volume.volumeBounds();
218 unsigned int edgeIdx{0};
220 if(bounds.type() == Acts::VolumeBounds::BoundsType::eDiamond){
221 const auto& diamondBounds =
static_cast<const Acts::DiamondVolumeBounds&
>(bounds);
222 using BoundEnum = Acts::DiamondVolumeBounds::BoundValues;
223 std::vector<Amg::Vector3D> edges(12, Amg::Vector3D::Zero());
224 double xCord{0.}, yCord{0};
225 for(
double signX : {-1.,1.}){
226 for(
double signY : {-1., 0., 1.}){
227 for(
double signZ : {-1.,1.}){
229 xCord = diamondBounds.get(BoundEnum::eHalfLengthX2);
231 xCord = diamondBounds.get(BoundEnum::eHalfLengthX1);
232 yCord = diamondBounds.get(BoundEnum::eLengthY1);
234 xCord = diamondBounds.get(BoundEnum::eHalfLengthX3);
235 yCord = diamondBounds.get(BoundEnum::eLengthY2);
240 signZ*diamondBounds.get(BoundEnum::eHalfLengthZ)};
241 edges[edgeIdx] = volume.localToGlobalTransform(gctx.
context())*edge;
250 std::vector<Amg::Vector3D> edges{};
252 for (
const double signX : {-1., 1.}) {
253 for (
const double signY : { -1., 1.}) {
254 for (
const double signZ: {-1., 1.}) {
258 edges.push_back(volume.localToGlobalTransform(gctx.
context()) * edge);
269 using BoundEnum = Acts::LineBounds::BoundValues;
270 const auto& bounds =
static_cast<const Acts::LineBounds&
>(surface.bounds());
271 unsigned int edgeIdx{0};
274 for (
const double signX : {-1., 1.}) {
275 for (
const double signY : { -1., 1.}) {
276 for (
const double signZ: {-1., 1.}) {
278 signY*bounds.get(BoundEnum::eR),
279 signZ*bounds.get(BoundEnum::eHalfLengthZ)};
280 edges[edgeIdx] = surface.localToGlobalTransform(gctx.
context()) * edge;
290 if(surface.bounds().type() == Acts::SurfaceBounds::BoundsType::eRectangle) {
291 const Acts::RectangleBounds& bounds =
static_cast<const Acts::RectangleBounds&
>(surface.bounds());
292 using BoundEnum = Acts::RectangleBounds::BoundValues;
294 unsigned int edgeIdx{0};
295 for(
const double signX : {-1., 1.}) {
296 for (
const double signY : { -1., 1.}) {
297 const Amg::Vector3D edge{signX < 0 ? bounds.get(BoundEnum::eMinX) : bounds.get(BoundEnum::eMaxX),
298 signY < 0 ? bounds.get(BoundEnum::eMinY) : bounds.get(BoundEnum::eMaxY), 0.};
299 edges[edgeIdx] = surface.localToGlobalTransform(gctx.
context()) * edge;
304 }
else if(surface.bounds().type() == Acts::SurfaceBounds::BoundsType::eTrapezoid) {
305 using BoundEnum = Acts::TrapezoidBounds::BoundValues;
306 const auto& bounds =
static_cast<const Acts::TrapezoidBounds&
>(surface.bounds());
307 unsigned int edgeIdx{0};
310 for (
const double signX : {-1., 1.}) {
311 for (
const double signY : { -1., 1.}) {
313 Amg::Vector3D(signX*bounds.get(signY < 0 ? BoundEnum::eHalfLengthXnegY : BoundEnum::eHalfLengthXposY),
314 signY*bounds.get(BoundEnum::eHalfLengthY), 0.)};
316 edges[edgeIdx] = surface.localToGlobalTransform(gctx.
context()) * edge;
323 ATH_MSG_ERROR(
"The surface bounds are neither a rectangle nor a trapezoid, this is not supported yet");
329#if defined(FLATTEN) && defined(__GNUC__)
338 const std::vector<Amg::Vector3D>& chamberEdges,
339 const Acts::Volume& volume)
const {
343 double minDist = 1._km;
345 minDist = std::min(minDist, (edge - center).
mag());
349 if (std::ranges::none_of(volume.volumeBounds().values(),
350 [minDist](
const double bound){
351 return minDist < 2.5*bound;
357 const Acts::VolumeBounds& volBounds = volume.volumeBounds();
358 const Acts::Transform3& transform = volume.globalToLocalTransform(gctx.
context());
359 for (
unsigned edge1 = 1; edge1 < chamberEdges.size(); ++edge1) {
360 for (
unsigned edge2 = 0; edge2 < edge1; ++edge2) {
362 const double section = stepLength * step;
366 if (volBounds.inside (transform * testPoint)) {
376 std::vector<const MuonReadoutElement*> allRE =
m_detMgr->getAllReadoutElements();
379 ATH_MSG_INFO(
"Fetched "<<chambers.size()<<
" chambers.");
380 std::vector<const Chamber*> chamberVec{chambers.begin(), chambers.end()};
383 return std::ranges::find(chamberVec,
re->chamber()) == chamberVec.end();
385 if (missChamb != allRE.end()) {
386 ATH_MSG_ERROR(
"The chamber "<<(*(*missChamb)->chamber())<<
" is not in the chamber set");
387 return StatusCode::FAILURE;
392 std::vector<std::shared_ptr<Acts::Volume> > chamberBoundsVec;
393 chamberBoundsVec.reserve (chamberVec.size());
394 for (
const Chamber* ch : chamberVec)
395 chamberBoundsVec.push_back (ch->boundingVolume(gctx));
397 std::set<const Chamber*> overlapChambers{};
398 std::stringstream overlapstream{};
399 for (std::size_t chIdx = 0; chIdx< chamberVec.size(); ++chIdx) {
400 const Chamber& chamber{*chamberVec[chIdx]};
401 const Acts::Volume& chamberBounds = *chamberBoundsVec[chIdx];
403 saveEnvelope(gctx, std::format(
"Chamber_{:}{:}{:}{:}{:}",
405 chName(chamber.chamberIndex()),
406 Acts::abs(chamber.stationEta()),
407 chamber.stationEta() > 0 ?
'A' :
'C',
408 chamber.stationPhi()),
409 chamberBounds, extractSurfaces(chamber.readoutEles()));
412 const std::vector<Amg::Vector3D> chambCorners =
cornerPoints(gctx, chamberBounds);
414 std::vector<const Chamber*> overlaps{};
415 for (std::size_t chIdx1 = 0; chIdx1<chamberVec.size(); ++chIdx1) {
416 if (chIdx == chIdx1) {
419 const Chamber* overlapTest{chamberVec[chIdx1]};
420 if (
hasOverlap(gctx, chambCorners, *chamberBoundsVec[chIdx1])) {
421 overlaps.push_back(overlapTest);
424 if (overlaps.empty()) {
427 overlapstream<<
"The chamber "<<chamber<<
" overlaps with "<<std::endl;
428 for (
const Chamber* itOverlaps : overlaps) {
429 overlapstream<<
" *** "<<(*itOverlaps)<<std::endl;
431 overlapstream<<std::endl<<std::endl;
432 overlapChambers.insert(overlaps.begin(), overlaps.end());
433 overlapChambers.insert(chamberVec[chIdx]);
435 if (!overlapChambers.empty()) {
436 Acts::ObjVisualization3D visualHelper{};
438 Acts::GeometryView3D::drawVolume(visualHelper, *
hasOverlap->boundingVolume(gctx), gctx.
context());
447 ATH_MSG_INFO(
"Chamber test completed. Found "<<overlapChambers.size()<<
" overlapping chambers");
448 return overlapChambers.empty() ||
m_ignoreOverlapCh ? StatusCode::SUCCESS : StatusCode::FAILURE;
453 std::vector<const MuonReadoutElement*> allREs =
m_detMgr->getAllReadoutElements();
455 if (!
re->msSector()) {
457 return StatusCode::FAILURE;
462 if (sectorFromDet !=
re->msSector()) {
465 <<
" is not the one attached to the readout geometry \n"<<(*
re->msSector())<<
"\n"<<(*sectorFromDet));
466 return StatusCode::FAILURE;
470 const SectorSet sectors =
m_detMgr->getAllSectors();
471 ATH_MSG_INFO(__func__<<
"() "<<__LINE__<<
" - Fetched "<<sectors.size()<<
" sectors. ");
474 const auto subVols = chamberVolumes(gctx, *sector);
476 chName(sector->chamberIndex()),
477 sector->side() >0?
'A' :
'C',
478 sector->stationPhi() ),
479 *sector->boundingVolume(gctx),
480 extractSurfaces(sector->readoutEles()),
481 Acts::unpackSmartPointers(subVols));
484 const std::shared_ptr<Acts::Volume> secVolume = sector->boundingVolume(gctx);
486 const std::vector<Amg::Vector3D> edges =
cornerPoints(gctx, *chamber->boundingVolume(gctx));
487 unsigned int edgeCount{0};
490 chamber->readoutEles().front()->identify()));
494 ATH_MSG_INFO(__func__<<
"() "<<__LINE__<<
" - Sector envelope test completed.");
495 return StatusCode::SUCCESS;
498 const Acts::TrackingVolume& volume)
const {
499 if (!volume.isAlignable()) {
500 return StatusCode::SUCCESS;
502 const Acts::GeometryContext geoCtx = gctx.
context();
503 std::vector<std::shared_ptr<const Acts::Surface>> portals{};
504 for (
const Acts::Portal& portal : volume.portals()) {
505 if (portal.surface().geometryId().withBoundary(0) != volume.geometryId()) {
508 portals.push_back(portal.surface().getSharedPtr());
510 const auto unAlignedPortals = volume.volumeBounds().orientedSurfaces(volume.localToGlobalTransform(geoCtx));
512 if (unAlignedPortals.size() != portals.size()) {
513 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - The size of the aligned and unaligned portals don't match for volume "
514 <<volume.volumeName()<<
". Aligned: "<<portals.size()<<
", unaligned: "<<unAlignedPortals.size());
515 return StatusCode::FAILURE;
517 StatusCode retCode = StatusCode::SUCCESS;
518 for (std::size_t p =0 ; p < portals.size(); ++p){
520 if (portals[p]->bounds() != unAlignedPortals[p].surface->bounds()) {
521 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - The bounds of the "<<p
522 <<
"-th portal differ:\n -- aligned: "<<portals[p]->bounds()
523 <<
"\n -- unaligned: "<<unAlignedPortals[p].surface->bounds());
524 retCode = StatusCode::FAILURE;
526 const Amg::Transform3D& uTrf{unAlignedPortals[p].surface->localToGlobalTransform(geoCtx)};
531 <<
" - The unaligned and aligned portals don't end up at the same point \n"
533 retCode = StatusCode::FAILURE;
541 const Acts::TrackingGeometry& trackingGeometry)
const {
545 std::vector<const Acts::TrackingVolume*> volumeVec{};
546 std::vector<const Acts::Surface*> passiveSurfaces{};
548 std::unordered_set<const Acts::TrackingVolume*> overlapVolumes{};
549 std::unordered_set<const Acts::Surface*> overlapSurfaces{};
553 trackingGeometry.visitVolumes([&](
const Acts::TrackingVolume* vol) {
555 if(vol->volumeBounds().type() == Acts::VolumeBounds::BoundsType::eCylinder){
556 ATH_MSG_DEBUG(
"checkTrackingGeometry() "<<__LINE__<<
" - Fetch "<<vol->surfaces().size()
557 <<
" passive surfaces from "<<vol->volumeName()<<
".");
558 std::ranges::for_each(vol->surfaces(), [&](
const Acts::Surface& surf){
559 ATH_MSG_VERBOSE(
" --- "<<surf.type()<<
" @"<<Amg::toString(surf.center(gctx.context()))
560 <<
" "<<surf.bounds());
561 passiveSurfaces.push_back(&surf);
568 ATH_MSG_DEBUG(
"checkTrackingGeometry() "<<__LINE__<<
" - Skip volume "
569 <<vol->volumeName()<<
".");
572 volumeVec.push_back(vol);
576 << passiveSurfaces.size()<<
" passive surfaces");
578 Acts::ObjVisualization3D visualHelper{};
579 std::ranges::for_each(passiveSurfaces,
580 [&visualHelper, &gctx](
const Acts::Surface* surface) {
581 Acts::GeometryView3D::drawSurface(visualHelper, *surface, gctx.
context());
583 visualHelper.write(
"MsTrackTest_passiveSurfaces.obj");
586 StatusCode retCode = StatusCode::SUCCESS;
587 for(std::size_t vIdx = 0; vIdx < volumeVec.size(); ++vIdx) {
588 const Acts::TrackingVolume* testVol{volumeVec.at(vIdx)};
591 std::vector<const Acts::TrackingVolume*> overlaps{};
592 const std::vector<Amg::Vector3D> edges =
cornerPoints(gctx, *testVol);
594 for(
const auto& surface : testVol->surfaces()) {
596 std::vector<Amg::Vector3D> surfEdges = {};
597 if(surface.type() == Acts::Surface::SurfaceType::Straw){
598 ATH_MSG_VERBOSE(__func__<<
"() - "<<__LINE__<<
" Checking "<<surface.type()<<
" surface "<<identify(surface)
599 <<
" / "<<surface.geometryId() <<
" in volume "<<testVol->volumeName());
601 auto edges =
cornerPoints(gctx,
dynamic_cast<const Acts::StrawSurface&
>(surface));
602 surfEdges.insert(surfEdges.end() , edges.begin(), edges.end());
603 }
else if(surface.type() == Acts::Surface::SurfaceType::Plane){
604 ATH_MSG_VERBOSE(__func__<<
"() - "<<__LINE__<<
" Checking "<<surface.type()<<
" surface "<<identify(surface)
605 <<
" / "<<surface.geometryId() <<
" in volume "<<testVol->volumeName());
607 auto edges =
cornerPoints(gctx,
dynamic_cast<const Acts::PlaneSurface&
>(surface));
608 surfEdges.insert(surfEdges.end() , edges.begin(), edges.end());
610 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - The "<<surface.type()<<
"-surface "
612 <<surface.geometryId() <<
" is neither a straw nor a plane surface");
613 return StatusCode::FAILURE;
616 for(
const auto& edge : surfEdges) {
617 if(!testVol->inside(gctx.
context(), edge, 0.01)) {
618 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - The "<<surface.type()<<
"-surface "
620 <<surface.geometryId() <<
" @vertex point "
623 <<
" is outside the parent volume: " << testVol->volumeName()
625 <<
", "<<testVol->volumeBounds());
626 overlapSurfaces.insert(&surface);
627 overlapVolumes.insert(testVol);
629 retCode = StatusCode::FAILURE;
636 for (
const Acts::TrackingVolume& child : testVol->volumes()) {
638 if(!testVol->inside(gctx.
context(), edge, 0.01)){
639 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - The children volume's "
640 << child.volumeName() <<
" vertex point " <<
Amg::toString(edge)
641 <<
" is outside the parent volume" << testVol->volumeName());
642 return StatusCode::FAILURE;
647 if (!testVol->motherVolume()->isAlignable() &&
m_dumpObjs) {
648 std::vector<const Acts::Surface*> surfaces = extractSurfaces(*testVol);
649 const Identifier volId = identify(*surfaces.front());
651 saveEnvelope(gctx, std::format(
"TrackingVolume_{:}{:}{:}{:}_{:}",
653 Acts::abs(
eta),
eta > 0 ?
'A' :
'C',
655 *testVol, surfaces , chamberVolumes(*testVol));
659 for (std::size_t vIdx1 = 0 ; vIdx1 < vIdx; ++vIdx1) {
660 const Acts::TrackingVolume* overlapTest{volumeVec.at(vIdx1)};
661 if (overlapTest->motherVolume() == testVol ||
662 testVol->motherVolume() == overlapTest){
666 overlaps.push_back(overlapTest);
667 std::ranges::copy(extractSurfaces(*testVol),
668 std::inserter(overlapSurfaces, overlapSurfaces.begin()));
669 std::ranges::copy(extractSurfaces(*overlapTest),
670 std::inserter(overlapSurfaces, overlapSurfaces.begin()));
675 const Identifier volId = identify(*extractSurfaces(*testVol).front());
676 double volHalfR{0.}, volHalfZ{0.};
687 const double rMin = center.perp() - volHalfR;
690 const double rMax = (testVol->localToGlobalTransform(gctx.
context()) *(
691 halfX * Amg::Vector3D::UnitX() +
692 volHalfR * Amg::Vector3D::Unit(1 +
isBarrel))).perp();
694 double zMin = center.z() - volHalfZ;
695 double zMax = center.z() + volHalfZ;
697 if (testVol->volumeBounds().type() == Acts::VolumeBounds::eDiamond) {
698 zMin = 1._km; zMax = -1._km;
700 zMin = std::min(zMin, p.z());
701 zMax = std::max(zMax, p.z());
705 for(
const Acts::Surface* surf : passiveSurfaces) {
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 const double passiveR = bounds.get(BoundEnum::eR);
714 const double passiveZ = bounds.get(BoundEnum:: eHalfLengthZ);
715 if (rMin < passiveR || rMax > passiveR){
718 if (passiveZ < zMin || -passiveZ > zMax) {
721 }
else if(surf->type() == Acts::Surface::SurfaceType::Disc){
722 using BoundEnum = Acts::RadialBounds::BoundValues;
723 const auto& bounds =
static_cast<const Acts::RadialBounds&
>(surf->bounds());
724 if (center.z() < zMin || center.z() > zMax) {
727 const double surfRMax = bounds.get(BoundEnum::eMaxR);
728 const double surfRMin = bounds.get(BoundEnum::eMinR);
729 if (surfRMax < rMin || surfRMin > rMax){
734 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - The surface "<< surf->geometryId()
735 <<
", "<< surf->name() <<
" is not a cylinder surface or disc");
736 return StatusCode::FAILURE;
740 << testVol->volumeName() <<
" overlaps with the surface "
741 << surf->name() <<
" with geo id" << surf->geometryId()
742 <<
" -- volume radius: ["<<rMin<<
";"<<rMax<<
"] z: ["<<zMin<<
";"<<zMax<<
"]"
743 <<
" "<<surf->bounds());
745 retCode = StatusCode::FAILURE;
747 overlapSurfaces.insert(surf);
748 overlapVolumes.insert(testVol);
751 if(overlaps.empty()) {
752 ATH_MSG_DEBUG(__func__<<
"() "<<__LINE__<<
" - No overlaps detected for the volume "<<testVol->volumeName());
756 overlapVolumes.insert(overlaps.begin(), overlaps.end());
757 overlapVolumes.insert(testVol);
759 std::stringstream overlapStream{};
760 overlapStream<<__func__<<
"() "<<__LINE__<<
" - The volume "
761 <<testVol->volumeName() <<
" overlaps with: "<<std::endl;
763 for(
const Acts::TrackingVolume* overlap: overlaps){
764 overlapStream<<
" --- Volume: " << overlap->volumeName()<<
", "<<overlap->volumeBounds()
770 if (overlapVolumes.size() || overlapSurfaces.size()) {
771 const Acts::Volume* refVolume = (*overlapVolumes.begin());
772 std::vector<const Acts::Volume*> childVols{};
773 childVols.insert(childVols.begin(),std::next(overlapVolumes.begin()), overlapVolumes.end());
774 std::vector<const Acts::Surface*> childSurfs{overlapSurfaces.begin(), overlapSurfaces.end()};
775 saveEnvelope(gctx,
"TrackingGeometryOverlaps", *refVolume,
776 childSurfs, childVols);
780 if(overlapVolumes.empty()) {
781 ATH_MSG_ALWAYS(
"No overlaps detected in the tracking geometry!!");
783 retCode = StatusCode::FAILURE;
789 const std::string& envName,
790 const Acts::Volume& envelopeVol,
791 const std::vector<const Acts::Surface*>& assocSurfaces,
792 const std::vector<const Acts::Volume*>& subVols)
const {
793 Acts::ObjVisualization3D visualHelper{};
794 std::ranges::for_each(assocSurfaces, [&visualHelper, &gctx](
const Acts::Surface* surface) {
795 Acts::GeometryView3D::drawSurface(visualHelper, *surface, gctx.
context());
798 std::ranges::for_each(subVols, [&visualHelper, &gctx](
const Acts::Volume* subVol) {
799 Acts::GeometryView3D::drawVolume(visualHelper,*subVol, gctx.
context(), Amg::Transform3D::Identity(),
800 Acts::s_viewPassive);
802 Acts::GeometryView3D::drawVolume(visualHelper, envelopeVol, gctx.
context());
803 ATH_MSG_DEBUG(
"Save new envelope 'MsTrackTest_"<<envName<<
".obj'");
804 visualHelper.write(std::format(
"MsTrackTest_{:}.obj", envName));
815 return StatusCode::SUCCESS;
817 template <
class EnvelopeType>
820 const EnvelopeType& chamber,
821 const Acts::Volume& detVol)
const {
824 for (
unsigned int layer = 1; layer <= mdtMl.
numLayers(); ++layer) {
825 for (
unsigned int tube = 1; tube <= mdtMl.
numTubesInLay(); ++tube) {
839 "bottom of the tube box", measId));
841 "sealing of the tube box", measId));
844 "wall to the previous tube", measId));
846 "wall to the next tube", measId));
849 return StatusCode::SUCCESS;
851 template<
class EnvelopeType>
854 const EnvelopeType& chamber,
855 const Acts::Volume& detVol)
const {
860 for (
unsigned int gasGap = 1 ; gasGap <= rpc.
nGasGaps(); ++gasGap) {
862 for (
bool measPhi : {
false,
true}) {
866 doubletPhi, gasGap, measPhi,
strip);
874 return StatusCode::SUCCESS;
876 template <
class EnevelopeType>
879 const EnevelopeType& chamber,
880 const Acts::Volume& detVol)
const {
881 for (
unsigned int gasGap = 1; gasGap <= tgc.
nGasGaps(); ++gasGap){
882 for (
bool isStrip : {
false}) {
884 const unsigned int nChannel = tgc.
numChannels(layHash);
885 for (
unsigned int channel = 1; channel <= nChannel ; ++channel) {
892 return StatusCode::SUCCESS;
894 template <
class EnevelopeType>
897 const EnevelopeType& chamber,
898 const Acts::Volume& detVol)
const {
901 for(
unsigned int gasGap = 1; gasGap <= mm.nGasGaps(); ++gasGap){
903 unsigned int firstStrip = mm.firstStrip(gasGapHash);
904 for(
unsigned int strip = firstStrip;
strip <= mm.numStrips(gasGapHash); ++
strip){
906 ATH_CHECK(
pointInside(gctx, chamber, detVol, mm.stripPosition(gctx, stripId),
"center", stripId));
907 ATH_CHECK(
pointInside(gctx, chamber, detVol, mm.leftStripEdge(gctx, mm.measurementHash(stripId)),
"left edge", stripId));
908 ATH_CHECK(
pointInside(gctx, chamber, detVol, mm.rightStripEdge(gctx, mm.measurementHash(stripId)),
"right edge", stripId));
912 return StatusCode::SUCCESS;
914 template <
class EnvelopeType>
917 const EnvelopeType& chamber,
918 const Acts::Volume& detVol)
const{
921 for(
unsigned int gasGap = 1; gasGap <= stgc.
numLayers(); ++gasGap){
923 for(
unsigned int nch = 1; nch <= stgc.
nChTypes(); ++nch){
925 const unsigned int nStrips = stgc.
numChannels(gasGapHash);
940 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
@ Mm
Maybe not needed in the migration.
@ Tgc
Resitive Plate Chambers.
@ Rpc
Monitored Drift Tubes.
std::string to_string(const DetectorType &type)
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.