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"
31using namespace Acts::UnitLiterals;
37 constexpr double tolerance = 10. *Gaudi::Units::micrometer;
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); });
55 return StatusCode::SUCCESS;
57 template <
class EnvelopeType>
58#if defined(FLATTEN) && defined(__GNUC__)
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());
85 planeTrapezoid.
setLevel(MSG::VERBOSE);
87 static const Eigen::Rotation2D axisSwap{90. *Gaudi::Units::deg};
88 if (std::abs(locPos.z()) - chamb.halfZ() < -
tolerance &&
90 return StatusCode::SUCCESS;
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
99 return StatusCode::FAILURE;
104 const std::string& descr,
107 return StatusCode::SUCCESS;
109 const std::array<Amg::Vector3D, 8> volumeCorners =
cornerPoints(volume);
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) {
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) {
133 <<std::endl<<(*readOut->chamber())<<std::endl<<envelope);
134 return StatusCode::FAILURE;
137 switch (readOut->detectorType()) {
161 return StatusCode::FAILURE;
165 ATH_MSG_DEBUG(
"All "<<reEles.size()<<
" readout elements are embedded in "<<envelope);
166 return StatusCode::SUCCESS;
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;
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;
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");
250#if defined(FLATTEN) && defined(__GNUC__)
259 const Acts::Volume& volume)
const {
263 double minDist = 1._km;
265 minDist = std::min(minDist, (edge - center).
mag());
269 std::vector<double> boundValues = volume.volumeBounds().values();
270 if (std::ranges::none_of(boundValues, [minDist](
const double bound){
271 return minDist < 2.5*bound;
277 const Acts::VolumeBounds& volBounds = volume.volumeBounds();
278 const Acts::Transform3& itransform = volume.itransform();
279 for (
unsigned edge1 = 1; edge1 < chamberEdges.size(); ++edge1) {
280 for (
unsigned edge2 = 0; edge2 < edge1; ++edge2) {
282 const double section = stepLength * step;
285 Acts::Vector3 posInVolFrame = itransform * testPoint;
286 if (volBounds.inside (posInVolFrame)) {
296 std::vector<const MuonReadoutElement*> allRE =
m_detMgr->getAllReadoutElements();
299 ATH_MSG_INFO(
"Fetched "<<chambers.size()<<
" chambers.");
300 std::vector<const Chamber*> chamberVec{chambers.begin(), chambers.end()};
303 return std::ranges::find(chamberVec,
re->chamber()) == chamberVec.end();
305 if (missChamb != allRE.end()) {
306 ATH_MSG_FATAL(
"The chamber "<<(*(*missChamb)->chamber())<<
" is not in the chamber set");
307 return StatusCode::FAILURE;
310 std::set<const Chamber*> overlapChambers{};
311 std::stringstream overlapstream{};
312 for (std::size_t chIdx = 0; chIdx< chamberVec.size(); ++chIdx) {
313 const Chamber& chamber{*chamberVec[chIdx]};
315 saveEnvelope(gctx, std::format(
"Chamber_{:}{:}{:}{:}{:}",
317 chName(chamber.chamberIndex()),
318 Acts::abs(chamber.stationEta()),
319 chamber.stationEta() > 0 ?
'A' :
'C',
320 chamber.stationPhi()),
321 *chamber.boundingVolume(gctx), chamber.readoutEles());
324 const std::array<Amg::Vector3D, 8> chambCorners =
cornerPoints(*chamber.boundingVolume(gctx));
326 std::vector<const Chamber*> overlaps{};
327 for (std::size_t chIdx1 = 0; chIdx1<chamberVec.size(); ++chIdx1) {
328 if (chIdx == chIdx1) {
331 const Chamber* overlapTest{chamberVec[chIdx1]};
333 overlaps.push_back(overlapTest);
336 if (overlaps.empty()) {
339 overlapstream<<
"The chamber "<<chamber<<
" overlaps with "<<std::endl;
340 for (
const Chamber* itOverlaps : overlaps) {
341 overlapstream<<
" *** "<<(*itOverlaps)<<std::endl;
343 overlapstream<<std::endl<<std::endl;
344 overlapChambers.insert(overlaps.begin(), overlaps.end());
345 overlapChambers.insert(chamberVec[chIdx]);
347 if (!overlapChambers.empty()) {
348 Acts::ObjVisualization3D visualHelper{};
350 Acts::GeometryView3D::drawVolume(visualHelper, *
hasOverlap->boundingVolume(gctx), gctx.
context());
359 return overlapChambers.empty() ||
m_ignoreOverlapCh ? StatusCode::SUCCESS : StatusCode::FAILURE;
364 std::vector<const MuonReadoutElement*> allREs =
m_detMgr->getAllReadoutElements();
366 if (!
re->msSector()) {
368 return StatusCode::FAILURE;
373 if (sectorFromDet !=
re->msSector()) {
376 <<
" is not the one attached to the readout geometry \n"<<(*
re->msSector())<<
"\n"<<(*sectorFromDet));
377 return StatusCode::FAILURE;
381 const SectorSet sectors =
m_detMgr->getAllSectors();
386 chName(sector->chamberIndex()),
387 sector->side() >0?
'A' :
'C',
388 sector->stationPhi() ),
389 *sector->boundingVolume(gctx), sector->readoutEles(),
390 chamberVolumes(gctx, *sector));
393 const std::shared_ptr<Acts::Volume> secVolume = sector->boundingVolume(gctx);
395 const std::array<Amg::Vector3D, 8> edges =
cornerPoints(*chamber->boundingVolume(gctx));
396 unsigned int edgeCount{0};
399 chamber->readoutEles().front()->identify()));
403 return StatusCode::SUCCESS;
406 const std::string& envName,
407 const Acts::Volume& envelopeVol,
408 const std::vector<const MuonGMR4::MuonReadoutElement*>& assocRE,
409 const std::vector<std::shared_ptr<Acts::Volume>>& subVols)
const {
410 Acts::ObjVisualization3D visualHelper{};
412 std::ranges::for_each(
re->getSurfaces(),[&visualHelper, &gctx](
const std::shared_ptr<Acts::Surface>& surface){
413 Acts::GeometryView3D::drawSurface(visualHelper, *surface, gctx.context());
416 std::ranges::for_each(subVols, [&visualHelper, &gctx](
const std::shared_ptr<Acts::Volume>& subVol ){
417 Acts::GeometryView3D::drawVolume(visualHelper,*subVol, gctx.
context(), Amg::Transform3D::Identity(),
418 Acts::s_viewPassive);
420 Acts::GeometryView3D::drawVolume(visualHelper, envelopeVol, gctx.
context());
421 ATH_MSG_DEBUG(
"Save new envelope 'MsTrackTest_"<<envName<<
".obj'");
422 visualHelper.write(std::format(
"MsTrackTest_{:}.obj", envName));
428 std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry =
m_trackingGeometrySvc->trackingGeometry();
433 return StatusCode::SUCCESS;
435 template <
class EnvelopeType>
438 const EnvelopeType& chamber,
439 const Acts::Volume& detVol)
const {
442 for (
unsigned int layer = 1; layer <= mdtMl.
numLayers(); ++layer) {
443 for (
unsigned int tube = 1; tube <= mdtMl.
numTubesInLay(); ++tube) {
457 "bottom of the tube box", measId));
459 "sealing of the tube box", measId));
462 "wall to the previous tube", measId));
464 "wall to the next tube", measId));
467 return StatusCode::SUCCESS;
469 template<
class EnvelopeType>
472 const EnvelopeType& chamber,
473 const Acts::Volume& detVol)
const {
478 for (
unsigned int gasGap = 1 ; gasGap <= rpc.
nGasGaps(); ++gasGap) {
480 for (
bool measPhi : {
false,
true}) {
484 doubletPhi, gasGap, measPhi,
strip);
492 return StatusCode::SUCCESS;
494 template <
class EnevelopeType>
497 const EnevelopeType& chamber,
498 const Acts::Volume& detVol)
const {
499 for (
unsigned int gasGap = 1; gasGap <= tgc.
nGasGaps(); ++gasGap){
500 for (
bool isStrip : {
false}) {
502 const unsigned int nChannel = tgc.
numChannels(layHash);
503 for (
unsigned int channel = 1; channel <= nChannel ; ++channel) {
509 return StatusCode::SUCCESS;
511 template <
class EnevelopeType>
514 const EnevelopeType& chamber,
515 const Acts::Volume& detVol)
const {
518 for(
unsigned int gasGap = 1; gasGap <= mm.nGasGaps(); ++gasGap){
520 unsigned int firstStrip = mm.firstStrip(gasGapHash);
521 for(
unsigned int strip = firstStrip;
strip <= mm.numStrips(gasGapHash); ++
strip){
524 ATH_CHECK(
pointInside(chamber, detVol, mm.leftStripEdge(gctx, mm.measurementHash(stripId)),
"left edge", stripId));
525 ATH_CHECK(
pointInside(chamber, detVol, mm.rightStripEdge(gctx, mm.measurementHash(stripId)),
"right edge", stripId));
529 return StatusCode::SUCCESS;
531 template <
class EnvelopeType>
534 const EnvelopeType& chamber,
535 const Acts::Volume& detVol)
const{
538 for(
unsigned int gasGap = 1; gasGap <= stgc.
numLayers(); ++gasGap){
540 for(
unsigned int nch = 1; nch <= stgc.
nChTypes(); ++nch){
542 const unsigned int nStrips = stgc.
numChannels(gasGapHash);
556 return StatusCode::SUCCESS;
const boost::regex re(r_e)
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_WARNING(x)
Acts::GeometryContext context() const
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
std::shared_ptr< Acts::Volume > boundingVolume(const ActsTrk::GeometryContext &gctx) const
Returns the Acts::Volume representation of the chamber.
std::vector< const MuonReadoutElement * > ReadoutSet
Define the list of read out elements of the chamber.
Amg::Vector3D highVoltPos(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the global position of the High Voltage connectors.
static IdentifierHash measurementHash(unsigned int layerNumber, unsigned int tubeNumber)
Transform the layer and tube number to the measurementHash.
bool isValid(const IdentifierHash &measHash) const
Amg::Vector3D readOutPos(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the global position of the readout card.
const parameterBook & getParameters() const
Amg::Vector3D globalTubePos(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the global position of the tube center.
unsigned int numTubesInLay() const
Returns the number of tubes per layer.
double innerTubeRadius() const
Returns the inner tube radius.
Identifier measurementId(const IdentifierHash &measHash) const override final
Converts the measurement hash back to the full Identifier.
unsigned int numLayers() const
Returns the number of tube layer.
static IdentifierHash createHash(const int gasGap, const int strip)
std::vector< const Chamber * > MuonChamberSet
std::vector< const SpectrometerSector * > MuonSectorSet
The MuonReadoutElement is an abstract class representing the geometry representing the muon detector.
const Amg::Transform3D & localToGlobalTrans(const ActsTrk::GeometryContext &ctx) const
Returns the local to global transformation into the ATLAS coordinate system.
Identifier identify() const override final
Return the athena 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
Converts the measurement hash back to the full Identifier.
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)
Amg::Vector3D globalChannelPosition(const ActsTrk::GeometryContext &ctx, const Identifier &measId) const
Returns the global pad/strip/wireGroup position.
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
static IdentifierHash createHash(const unsigned int gasGap, const unsigned int channelType, const unsigned int channel, const unsigned int wireInGrp=0)
Create a measurement hash from the Identifier fields.
int multilayer() const
Returns the multilayer of the sTgcReadoutElement.
Amg::Vector3D rightStripEdge(const ActsTrk::GeometryContext &ctx, const IdentifierHash &measHash) const
unsigned int nChTypes() const
Number of Channel Types.
unsigned int numLayers() const
Returns the number of gas gap layers.
ReadoutChannelType
ReadoutChannelType to distinguish the available readout channels Pad - pad readout channel Strip - et...
unsigned int numChannels(const Identifier &measId) const
Returns the number of strips / wires / pads in a given gasGap.
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.
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
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)
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.