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/Surfaces/TrapezoidBounds.hpp"
25 #include "Acts/Visualization/ObjVisualization3D.hpp"
26 #include "Acts/Visualization/GeometryView3D.hpp"
27 #include "Acts/Definitions/Units.hpp"
31 using namespace Acts::UnitLiterals;
41 std::vector<std::shared_ptr<Acts::Volume>> vols{};
43 [&gctx](
const auto&
ch){ return ch->boundingVolume(gctx); });
53 ATH_CHECK(m_trackingGeometrySvc.retrieve());
55 return StatusCode::SUCCESS;
57 template <
class EnvelopeType>
58 #if defined(FLATTEN) && defined(__GNUC__)
66 StatusCode MuonChamberToolTest::pointInside(
const EnvelopeType& chamb,
67 const Acts::Volume& boundVol,
69 const std::string&
descr,
74 Acts::Vector3 posInVolFrame((boundVol.transform().inverse()) * point);
75 if (boundVol.volumeBounds().inside(posInVolFrame,
tolerance)) {
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;
84 planeTrapezoid.
defineTrapezoid(chamb.halfXShort(), chamb.halfXLong(), chamb.halfY());
88 if (std::abs(locPos.z()) - chamb.halfZ() < -
tolerance &&
89 planeTrapezoid.insideTrapezoid(axisSwap*locPos.block<2,1>(0,0))) {
90 return StatusCode::SUCCESS;
92 planeTrapezoid.defineStripLayout(locPos.y() * Amg::Vector2D::UnitX(), 1, 1, 1);
95 <<std::endl<<std::endl<<chamb<<std::endl<<
"Local position "<<
Amg::toString(locPos)
96 <<
", "<<planeTrapezoid
99 return StatusCode::FAILURE;
102 StatusCode MuonChamberToolTest::pointInside(
const Acts::TrackingVolume& volume,
104 const std::string&
descr,
107 return StatusCode::SUCCESS;
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) {
115 return StatusCode::FAILURE;
118 template <
class EnvelopeType>
120 const EnvelopeType& envelope)
const {
121 std::shared_ptr<Acts::Volume> boundVol = envelope.boundingVolume(gctx);
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;
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;
137 switch (readOut->detectorType()) {
140 ATH_CHECK(testReadoutEle(gctx, *detEle, envelope, *boundVol));
144 ATH_CHECK(testReadoutEle(gctx, *detEle, envelope, *boundVol));
148 ATH_CHECK(testReadoutEle(gctx, *detEle, envelope, *boundVol));
152 ATH_CHECK(testReadoutEle(gctx, *detEle, envelope, *boundVol));
156 ATH_CHECK(testReadoutEle(gctx, *detEle, envelope, *boundVol));
161 return StatusCode::FAILURE;
165 ATH_MSG_DEBUG(
"All "<<reEles.size()<<
" readout elements are embedded in "<<envelope);
166 return StatusCode::SUCCESS;
169 std::array<Amg::Vector3D, 8> MuonChamberToolTest::cornerPoints(
const Acts::Volume& volume)
const {
171 unsigned int edgeIdx{0};
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.}) {
180 edges[edgeIdx] = volume.transform() * edge;
189 std::array<Amg::Vector3D, 8> MuonChamberToolTest::cornerPoints(
const Acts::GeometryContext& gctx,
const Acts::StrawSurface& surface)
const {
191 using BoundEnum = Acts::LineBounds::BoundValues;
192 const auto& bounds =
static_cast<const Acts::LineBounds&
>(surface.bounds());
193 unsigned int edgeIdx{0};
196 for (
const double signX : {-1., 1.}) {
197 for (
const double signY : { -1., 1.}) {
198 for (
const double signZ: {-1., 1.}) {
200 signY*bounds.get(BoundEnum::eR),
201 signZ*bounds.get(BoundEnum::eHalfLengthZ)};
202 edges[edgeIdx] = surface.transform(gctx) * edge;
210 std::array<Amg::Vector3D, 4> MuonChamberToolTest::cornerPoints(
const Acts::GeometryContext& gctx,
const Acts::PlaneSurface& surface)
const {
212 if(surface.bounds().type() == Acts::SurfaceBounds::BoundsType::eRectangle) {
213 const Acts::RectangleBounds& bounds =
static_cast<const Acts::RectangleBounds&
>(surface.bounds());
214 using BoundEnum = Acts::RectangleBounds::BoundValues;
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;
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};
232 for (
const double signX : {-1., 1.}) {
233 for (
const double signY : { -1., 1.}) {
235 Amg::Vector3D(signX*bounds.get(signY < 0 ? BoundEnum::eHalfLengthXnegY : BoundEnum::eHalfLengthXposY),
236 signY*bounds.get(BoundEnum::eHalfLengthY), 0.)};
238 edges[edgeIdx] = surface.transform(gctx) * edge;
245 ATH_MSG_FATAL(
"The surface bounds are neither a rectangle nor a trapezoid, this is not supported yet");
249 bool MuonChamberToolTest::hasOverlap(
const std::array<Amg::Vector3D, 8>& chamberEdges,
250 const Acts::Volume& volume)
const {
254 double minDist = 1._km;
256 minDist =
std::min(minDist, (edge - center).
mag());
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;
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) {
272 if (volume.inside(testPoint)) {
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()};
291 if (missChamb != allRE.end()) {
292 ATH_MSG_FATAL(
"The chamber "<<(*(*missChamb)->chamber())<<
" is not in the chamber set");
293 return StatusCode::FAILURE;
296 std::set<const Chamber*> overlapChambers{};
297 std::stringstream overlapstream{};
298 for (std::size_t chIdx = 0; chIdx< chamberVec.size(); ++chIdx) {
301 saveEnvelope(gctx,
std::format(
"Chamber_{:}{:}{:}{:}{:}",
304 Acts::abs(
chamber.stationEta()),
305 chamber.stationEta() > 0 ?
'A' :
'C',
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) {
317 const Chamber* overlapTest{chamberVec[chIdx1]};
318 if (hasOverlap(chambCorners, *(overlapTest->boundingVolume(gctx)))) {
319 overlaps.push_back(overlapTest);
322 if (overlaps.empty()) {
325 overlapstream<<
"The chamber "<<
chamber<<
" overlaps with "<<std::endl;
326 for (
const Chamber* itOverlaps : overlaps) {
327 overlapstream<<
" *** "<<(*itOverlaps)<<std::endl;
329 overlapstream<<std::endl<<std::endl;
330 overlapChambers.insert(overlaps.begin(), overlaps.end());
331 overlapChambers.insert(chamberVec[chIdx]);
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());
339 if (m_ignoreOverlapCh) {
345 return overlapChambers.empty() || m_ignoreOverlapCh ? StatusCode::SUCCESS : StatusCode::FAILURE;
350 std::vector<const MuonReadoutElement*> allREs = m_detMgr->getAllReadoutElements();
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;
357 m_idHelperSvc->sector(
re->identify()),
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;
367 const SectorSet sectors = m_detMgr->getAllSectors();
372 chName(sector->chamberIndex()),
373 sector->side() >0?
'A' :
'C',
374 sector->stationPhi() ),
375 *sector->boundingVolume(gctx), sector->readoutEles(),
376 chamberVolumes(gctx, *sector));
378 ATH_CHECK(allReadoutInEnvelope(gctx, *sector));
379 const std::shared_ptr<Acts::Volume> secVolume = sector->boundingVolume(gctx);
381 const std::array<Amg::Vector3D, 8> edges = cornerPoints(*
chamber->boundingVolume(gctx));
382 unsigned int edgeCount{0};
385 chamber->readoutEles().front()->identify()));
389 return StatusCode::SUCCESS;
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{};
398 std::ranges::for_each(
re->getSurfaces(),[&visualHelper, &gctx](
const std::shared_ptr<Acts::Surface>& surface){
399 Acts::GeometryView3D::drawSurface(visualHelper, *surface, gctx.context());
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);
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));
414 std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry = m_trackingGeometrySvc->trackingGeometry();
419 return StatusCode::SUCCESS;
421 template <
class EnvelopeType>
425 const Acts::Volume& detVol)
const {
443 "bottom of the tube box", measId));
445 "sealing of the tube box", measId));
448 "wall to the previous tube", measId));
450 "wall to the next tube", measId));
453 return StatusCode::SUCCESS;
455 template<
class EnvelopeType>
459 const Acts::Volume& detVol)
const {
463 const RpcIdHelper& idHelper{m_idHelperSvc->rpcIdHelper()};
466 for (
bool measPhi : {
false,
true}) {
468 for (
int strip = 1; strip <=
nStrips; ++strip) {
478 return StatusCode::SUCCESS;
480 template <
class EnevelopeType>
484 const Acts::Volume& detVol)
const {
495 return StatusCode::SUCCESS;
497 template <
class EnevelopeType>
501 const Acts::Volume& detVol)
const {
503 const MmIdHelper& idHelper{m_idHelperSvc->mmIdHelper()};
505 IdentifierHash gasGapHash = MmReadoutElement::createHash(
gasGap,0);
507 for(
unsigned int strip =
firstStrip; strip <=
mm.numStrips(gasGapHash); ++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));
515 return StatusCode::SUCCESS;
517 template <
class EnvelopeType>
521 const Acts::Volume& detVol)
const{
523 const sTgcIdHelper& idHelper{m_idHelperSvc->stgcIdHelper()};
526 for(
unsigned int nch = 1; nch <= stgc.
nChTypes(); ++nch){
527 IdentifierHash gasGapHash = sTgcReadoutElement::createHash(
gasGap, nch, 0, 0);
531 for(
unsigned int strip = 1; strip <=
nStrips; ++strip){
535 if(channelType == sTgcReadoutElement::ReadoutChannelType::Wire || channelType == sTgcReadoutElement::ReadoutChannelType::Strip){
542 return StatusCode::SUCCESS;