15#include "GeoModelKernel/GeoDefinitions.h"
16#include "GeoModelKernel/GeoTube.h"
20#include "GeoModelKernel/throwExcept.h"
21#include "GeoModelHelpers/TransformToStringConverter.h"
22#include "GeoModelHelpers/GeoShapeUtils.h"
39#define verbose_Bline false
71 std::vector<const Trk::Surface*> elementSurfaces;
75 if (s) elementSurfaces.push_back(s.get());
77 return elementSurfaces;
82 if (tubeLayer >
getNLayers() || tubeLayer < 1)
return false;
88 if (tubeLayer >
getNLayers() || tubeLayer < 1)
return false;
103 double nominalTubeLength = 0.;
108 if (istep < 0 || istep >=
m_nsteps) {
110 <<
" DEid = " <<
idHelperSvc()->toStringDetEl(
identify()) <<
" called with: tubeL, tube " << tubeLayer <<
" " << tube
117 double tlength = nominalTubeLength;
120 if (
manager()->MinimalGeoFlag() == 0) {
122 <<
" has cutouts, check for real tube length for tubeLayer, tube " << tubeLayer <<
" " << tube );
123 PVConstLink cv = getMaterialGeom();
124 int nGrandchildren = cv->getNChildVols();
125 if (nGrandchildren <= 0)
return tlength;
134 int packed_id = tube + maxNTubesPerLayer * tubeLayer;
139 if (!found &&
id == packed_id) {
146 ATH_MSG_DEBUG(
" MdtReadoutElement tube match found for BMG - input : tube(" << tube <<
"), layer("
147 << tubeLayer <<
") - output match : tube(" << ii % maxNTubesPerLayer <<
"), layer(" << ii / maxNTubesPerLayer
151 if (ii >= nGrandchildren) {
153 <<
" --- getTubeLength is looking for child with index ii=" << ii <<
" for tubeL and tube = " << tubeLayer <<
" "
160 <<
" --- getTubeLength is looking for child with index ii=" << ii <<
" for tubeL and tube = " << tubeLayer <<
" "
165 PVConstLink physChild = cv->getChildVol(ii);
166 const GeoShape* shape = physChild->getLogVol()->getShape();
167 if (shape ==
nullptr)
return tlength;
168 const GeoTube* theTube =
dynamic_cast<const GeoTube*
>(shape);
169 if (theTube !=
nullptr)
170 tlength = 2. * theTube->getZHalfLength();
173 <<
" out of (tubeLayer-1)*m_ntubesperlayer+tube with tubeLayer=" << tubeLayer <<
" tubes/lay=" <<
m_ntubesperlayer
174 <<
" t=" << tube <<
" for MdtReadoutElement " <<
idHelperSvc()->toStringDetEl(
identify()) );
176 if (std::abs(tlength - nominalTubeLength) > 0.1) {
178 <<
" is affected by a cutout: eff. length = " << tlength <<
" while nominal = " << nominalTubeLength
182 <<
" is NOT affected by the cutout: eff. length = " << tlength <<
" while nominal = " << nominalTubeLength);
195 double scalprod = c_ro.dot(x_ro);
197 if (wlen > 10. * CLHEP::mm)
198 scalprod = std::abs(2. * scalprod /
getWireLength(tubeLayer, tube));
207 double distance =
distanceFromRO(GlobalHitPosition, tubeLayer, tube);
209 ATH_MSG_WARNING(
"isAtReadoutSide() - GlobalHitPosition appears to be outside the tube volume " << distance );
216 ATH_MSG_WARNING(
"isAtReadoutSide() - GlobalHitPosition appears to be outside the tube volume " << distance );
227 int amdb_plus_minus1 = 1;
230 if (std::abs(ms->xAmdbCRO()) > 10.) {
235 if (ROtubeFrame.z() < 0)
274 if (amdb_plus_minus1 == 0) {
275 ATH_MSG_WARNING(
"Unable to get the sign of RO side; signedRODistancefromTubeCenter returns 0" );
278 return amdb_plus_minus1 *
getWireLength(tubeLayer, tube) / 2.;
290 if (istep < 0 || istep >= ntot_steps) {
292 <<
" DEid = " <<
idHelperSvc()->toStringDetEl(
identify()) <<
" called with: tubeL, tube " << tubeLayer <<
" " << tube
294 ATH_MSG_WARNING(
"Please run in DEBUG mode to get extra diagnostic; setting istep = 0" );
320 <<
"/" << tubeLayer <<
"/" << tube );
321 double xtube{0.}, ytube{0.}, ztube{0.};
331 if (
manager()->MinimalGeoFlag() == 0) {
333 PVConstLink cv = getMaterialGeom();
334 int nGrandchildren = cv->getNChildVols();
344 int packed_id = tube + maxNTubesPerLayer * tubeLayer;
349 if (!found &&
id == packed_id) {
357 ATH_MSG_DEBUG(
" MdtReadoutElement tube match found for BMG - input : tube(" << tube <<
"), layer("
358 << tubeLayer <<
") - output match : tube(" << ii % maxNTubesPerLayer <<
"), layer(" << ii / maxNTubesPerLayer
362 GeoTrf::Transform3D tubeTrans = cv->getXToChildVol(ii);
363 PVConstLink tv = cv->getChildVol(ii);
364 constexpr double maxtol = 0.0000001;
366 if (std::abs(xtube - tubeTrans(0, 3)) > maxtol || std::abs(ztube - tubeTrans(2, 3)) > maxtol) {
367 THROW_EXCEPTION(__func__<<
"("<<tubeLayer<<
","<<tube<<
")"<<
" - mismatch between local from tube-id/pitch/cutout position"<<
369 idHelperSvc()->toStringDetEl(
identify()) <<
"There are "<<nGrandchildren<<
" child volumes and "<<
373 if (tubeTrans(1, 3) > maxtol) {
376 <<
"/" << tubeLayer <<
"/" << tube);
379 THROW_EXCEPTION(__func__<<
"("<<tubeLayer<<
","<<tube<<
")"<<
" - mismatch between local from tube-id/pitch/cutout position"<<
381 idHelperSvc()->toStringDetEl(
identify()) <<
"There are "<<nGrandchildren<<
" child volumes and "<<
424 return transform(tubeLayer, tube).inverse();
435 if (istep < 0 || istep >=
m_nsteps) {
437 <<
" called with: tubeL, tube " << tubeLayer
438 <<
" " << tube <<
"; step " << istep <<
" out of range 0-" <<
m_nsteps - 1 <<
" m_ntubesinastep " <<
m_ntubesinastep);
445 double xtube{0.}, ztube{0.};
459 ATH_MSG_WARNING(__func__<<
"() :"<<__LINE__<<
" called with tubeLayer or tube out of range in chamber "
461 <<
" max " <<
m_ntubesperlayer <<
" will compute deformation for first tube in this chamber" );
467 return geo.deformedTrf ? *geo.deformedTrf : ident;
482 if (!ms->hasBLines() && !ms->hasMdtAsBuiltParams()) {
483 return Amg::Transform3D::Identity();
485 const Amg::Vector3D fixedPoint = ms->getBlineFixedPointInAmdbLRS();
490 double height =
barrel() ? ms->ZsizeMdtStation() : ms->RsizeMdtStation();
491 double thickness =
barrel() ? ms->RsizeMdtStation() : ms->ZsizeMdtStation();
494 <<
", layer: "<<tubeLayer<<
", tube: "<<tube<<
", fixedPoint: "<<
Amg::toString(fixedPoint)<<
" / "
495 <<
Amg::toString(ms->getGeoTransform()->getDefTransform() *ms->getNativeToAmdbLRS().inverse()* fixedPoint)
496 <<
", height: "<<height<<
", thickness: "<<thickness
502 if (std::abs(height - heightML) > 10.) {
504 <<
"Different ML and MDTStation length in the precision coord.direction --- MultiLayerHeight, MDTstationHeigh "
505 << heightML <<
" " << height <<
" MultiLayerThickness, MDTstationThickness " << thicknessML <<
" " << thickness);
521 Amg::Vector3D pt_end1 = toAMDB * pt_center + halftubelen * Amg::Vector3D::UnitX();
522 Amg::Vector3D pt_end2 = toAMDB * pt_center - halftubelen * Amg::Vector3D::UnitX();
528 if (ms->hasMdtAsBuiltParams()) {
533 if (ms->hasBLines()) {
537 pt_end1_new =
posOnDefChamWire(pt_end1_new, moduleWidthS, moduleWidthL, height, thickness, fixedPoint);
540 pt_end2_new =
posOnDefChamWire(pt_end2_new, moduleWidthS, moduleWidthL, height, thickness, fixedPoint);
544 pt_end1 = fromAMDB * pt_end1;
545 pt_end2 = fromAMDB * pt_end2;
546 pt_end1_new = fromAMDB * pt_end1_new;
547 pt_end2_new = fromAMDB * pt_end2_new;
554 const Amg::Vector3D pt_center_new = 0.5 * (pt_end1_new + pt_end2_new);
559 const Amg::Vector3D rotation_vector = old_direction.cross(new_direction);
563 if (rotation_vector.mag() > 10. * std::numeric_limits<double>::epsilon()) {
564 const Amg::AngleAxis3D wire_rotation(std::asin(rotation_vector.mag()), rotation_vector.unit());
569 ATH_MSG_VERBOSE(
"To center "<<GeoTrf::toString(to_center)<<
" from: "<<GeoTrf::toString(from_center)<<
570 " -- direction: "<<GeoTrf::toString(old_direction)<<
" vs. "<<GeoTrf::toString(new_direction)
571 <<
" --> rot: "<<GeoTrf::toString(rotation_vector)<<
" ==> "<<GeoTrf::toString(
deformedTransform,
true));
597 const double moduleWidthS,
598 const double moduleWidthL,
600 const double thickness,
604 const double sp =
m_BLinePar->getParameter(Parameter::sp);
605 const double sn =
m_BLinePar->getParameter(Parameter::sn);
606 const double tw =
m_BLinePar->getParameter(Parameter::tw);
607 const double eg =
m_BLinePar->getParameter(Parameter::eg);
608 double ep =
m_BLinePar->getParameter(Parameter::ep);
609 double en =
m_BLinePar->getParameter(Parameter::en);
640 ATH_MSG_VERBOSE(
"** In "<<__func__<<
" - moduleWidthS " << moduleWidthS<<
", moduleWidthL: "
641 <<moduleWidthL <<
", height: "<<height<<
", thickness: " <<thickness <<
"." );
643 <<
" in the amdb-szt frame" );
645 double s0mdt = locAMDBPos.x();
646 if (std::abs(fixedPoint.x()) > 0.01) {
647 s0mdt = locAMDBPos.x() - fixedPoint.x();
649 double z0mdt = locAMDBPos.y();
651 if (std::abs(fixedPoint.y()) > 0.01) {
652 z0mdt = locAMDBPos.y() - fixedPoint.y();
654 double t0mdt = locAMDBPos.z();
656 if (std::abs(fixedPoint.z()) > 0.01) t0mdt = locAMDBPos.z() - fixedPoint.z();
657 if (z0mdt < 0 || t0mdt < 0) {
658 ATH_MSG_WARNING(
""<<__func__<<
": correcting the local position of a point outside the mdt station (2 multilayers) volume -- RE "
662 ATH_MSG_VERBOSE(
"** In "<<__func__<<
" - correct for offset of B-line fixed point " << s0mdt <<
" " << z0mdt <<
" " << t0mdt);
664 double ds{0.},dz{0.},dt{0.};
665 double width_actual = moduleWidthS + (moduleWidthL - moduleWidthS) * (z0mdt / height);
666 double s_rel = s0mdt / (width_actual / 2.);
667 double z_rel = (z0mdt - height / 2.) / (height / 2.);
668 double t_rel = (t0mdt - thickness / 2.) / (thickness / 2.);
670 ATH_MSG_VERBOSE(
"** In "<<__func__<<
" - width_actual: "<<width_actual<<
", s_rel: "<<s_rel<<
", z_rel: "
671 <<z_rel<<
", t_rel: "<<t_rel);
674 if ((
sp != 0) || (sn != 0)) {
675 double ztmp = z_rel * z_rel - 1;
676 dt += 0.5 * (
sp + sn) * ztmp + 0.5 * (
sp - sn) * ztmp * s_rel;
681 dt -= tw * s_rel * z_rel;
682 dz += tw * s_rel * t_rel * thickness / height;
683 ATH_MSG_VERBOSE(
"** In "<<__func__<<
": tw=" << tw <<
" dt, dz " << dt <<
" " << dz );
688 double egppm = eg / 1000.;
700 if ((ep != 0) || (en != 0)) {
703 double phi = 0.5 * (ep + en) * s_rel * s_rel + 0.5 * (ep - en) * s_rel;
704 double localDt =
phi * (t0mdt - thickness / 2.);
705 double localDz =
phi * (z0mdt - height / 2.);
710 ATH_MSG_VERBOSE(
"posOnDefChamStraighWire: ds,z,t = " << ds <<
" " << dz <<
" " << dt );
711 deformPos[0] = locAMDBPos[0] + ds;
712 deformPos[1] = locAMDBPos[1] + dz;
713 deformPos[2] = locAMDBPos[2] + dt;
731 const int tubeLayer,
const int tube)
const {
739 <<
" tubeLayer=" << tubeLayer <<
" tube=" << tube);
741 constexpr int nsid = 2;
744 std::array<MdtAsBuiltPar::tubeSide_t, nsid> tubeSide{tubeSide_t::POS, tubeSide_t::NEG};
745 std::array<Amg::Vector3D, nsid> wireEnd{locAMDBWireEndP, locAMDBWireEndN};
746 multilayer_t ml = (
getMultilayer() == 1) ? multilayer_t::ML1 : multilayer_t::ML2;
749 const int ref_layer = (ml == multilayer_t::ML1) ?
m_nlayers : 1;
752 for (
int isid = 0; isid < nsid; ++isid) {
754 double xref{0.}, yref{0.}, zref{0.};
765 reference_point = toAMDB * reference_point;
773 " "<<GeoTrf::toString(toAMDB,
true)<<
", reference point: "<<
Amg::toString(reference_point));
775 int layer_delta = tubeLayer;
776 if (ml == multilayer_t::ML1) layer_delta =
m_nlayers + 1 - tubeLayer;
779 double zpitch = params->zpitch(ml, tubeSide[isid]);
780 double ypitch = params->ypitch(ml, tubeSide[isid]);
781 double stagg = (double)params->stagg(ml, tubeSide[isid]);
782 double alpha = params->alpha(ml, tubeSide[isid]);
783 double y0 = params->y0(ml, tubeSide[isid]);
784 double z0 = params->z0(ml, tubeSide[isid]);
787 int do_stagg = (layer_delta - 1) % 2;
788 double offset_stagg = ((double)do_stagg) * 0.5 * zpitch * stagg;
789 Amg::Vector3D end_plug(0., (tube - 1.0) * zpitch + offset_stagg, (layer_delta - 1) * ypitch);
792 end_plug = amgTransf * end_plug;
801 Amg::Vector3D ret(reference_point.x() + xshift, reference_point.y() + z0 + end_plug.y(),
802 reference_point.z() + y0 + end_plug.z());
806 if ((ret - wireEnd[isid]).
mag() > 3. * CLHEP::mm) {
808 << isid <<
", Delta " <<
Amg::toString(ret - wireEnd[isid]) );
810 ATH_MSG_VERBOSE(( tubeSide[isid] == tubeSide_t::POS ?
"positive" :
"negative")<<
" wire end has moved from "
814 if (tubeSide[isid] == tubeSide_t::POS)
815 locAMDBWireEndP = ret;
817 locAMDBWireEndN = ret;
823 info.deformedTrf = std::make_unique<Amg::Transform3D>(std::move(deformedTrf));
830 ATH_MSG_WARNING(__func__<<
"() :"<<__LINE__<<
" called with tubeLayer or tube out of range in chamber "
832 <<
" max " <<
m_ntubesperlayer <<
" will compute transform for first tube in this chamber" );
842 THROW_EXCEPTION(
"There is no transform cached for tubeLayer: "<<tubeLayer
845 return info.m_transform;
852 if (itube >= ntot_tubes) {
853 ATH_MSG_WARNING(
"surface called with tubeLayer or tube out of range in chamber "
855 <<
" max " <<
m_ntubesperlayer <<
" will compute surface for first tube in this chamber" );
910 for (
int tubeLayer = 1; tubeLayer <=
getNLayers(); ++tubeLayer) {
921 int packed_id = tube + maxNTubesPerLayer * tubeLayer;
924 if (
id == packed_id) {
928 }, getMaterialGeom());
940 surface = std::make_unique<Trk::StraightLineSurface>(*
this,
id);
952 surfaceTRotation.col(0) = muonTRotation.col(1);
953 surfaceTRotation.col(1) = muonTRotation.col(2);
954 surfaceTRotation.col(2) = muonTRotation.col(0);
957 trans3D.pretranslate(
transform().translation());
965 if (layer < 1 || layer >
getNLayers())
return false;
Scalar phi() const
phi method
Scalar mag() const
mag method
const PlainObject unit() const
This is a plugin that makes Eigen look like CLHEP & defines some convenience methods.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
Visitor to collect all IDs under a GeoModel node.
void geoGetIds(FUNCTION f, const GeoGraphNode *node, int depthLimit=1)
Template helper for running the visitor.
Container classifier the MDT as-built parameters See parameter description in http://atlas-muon-align...
multilayer_t
MDT multi-layer index.
static constexpr int maxNTubesPerLayer
The maxNTubesPerLayer represents the absolute maximum of tubes which are built into a single multilay...
Amg::Transform3D tubeToMultilayerTransf(const Identifier &id) const
double getTubeLengthForCaching(const int tubeLayer, const int tube) const
virtual const Amg::Vector3D & center() const override final
Return the center of the element.
int isAtReadoutSide(const Amg::Vector3D &GlobalHitPosition, const Identifier &id) const
bool endcap() const
Returns whether the chamber is in the endcap.
void setMultilayer(const int ml)
Sets the multilayer number.
Amg::Vector3D localTubePos(const Identifier &id) const
void wireEndpointsAsBuilt(Amg::Vector3D &locAMDBWireEndP, Amg::Vector3D &locAMDBWireEndN, const int tubelayer, const int tube) const
double signedRODistanceFromTubeCentre(const Identifier &id) const
Amg::Vector3D tubePos(const Identifier &id) const
Returns the global position of the given tube.
Amg::Vector3D ROPos(const int tubelayer, const int tube) const
Amg::Transform3D nodeform_globalToLocalTransf(const Identifier &id) const
double getNominalTubeLengthWoCutouts(const int tubeLayer, const int tube) const
Amg::Vector3D localROPos(const Identifier &id) const
Amg::Transform3D globalTransform(const Amg::Vector3D &tubePos, const Amg::Transform3D &toDeform) const
Amg::Vector3D localNominalTubePosWoCutouts(const int tubelayer, const int tube) const
Amg::Vector3D nodeform_localTubePos(const Identifier &id) const
Amg::Transform3D nodeform_localToGlobalTransf(const Identifier &id) const
std::array< double, maxnlayers > m_firstwire_x
std::array< double, maxnsteps > m_tubelength
unsigned boundHash(const int tubeLayer, const int tube) const
Return the hash for the bounds.
void setBLinePar(const BLinePar *bLine)
Amg::Vector3D tubeFrame_localROPos(const int tubelayer, const int tube) const
bool m_builtFromCnv
Flag indicating whether the RE is built by the ReadoutGeomCnvAlg.
std::shared_ptr< Trk::SurfaceBounds > m_associatedBounds
std::vector< std::unique_ptr< Trk::StraightLineSurface > > m_tubeSurfaces
int getNLayers() const
Returns the number of tube layers inside the multilayer.
int getMultilayer() const
Returns the multilayer represented by the readout element.
Amg::Vector3D posOnDefChamWire(const Amg::Vector3D &locAMDBPos, const double width_narrow, const double width_wide, const double height, const double thickness, const Amg::Vector3D &fixedPoint) const
const Amg::Transform3D & fromIdealToDeformed(const int tubelayer, const int tube) const
virtual const Amg::Transform3D & transform() const override final
Return local to global transform.
virtual const Trk::SurfaceBounds & bounds() const override final
Return the boundaries of the element.
const BLinePar * m_BLinePar
virtual const Amg::Vector3D & normal() const override final
Return the normal of the element.
double distanceFromRO(const Amg::Vector3D &GlobalHitPosition, const Identifier &id) const
double RODistanceFromTubeCentre(const Identifier &id) const
double outerTubeRadius() const
Returns the tube radius taking the thickness of the tubes into account.
const GeoInfo & geoInfo(const int tubeLayer, const int tube) const
int getNtubesperlayer() const
Returns the number of tubes in each tube layer.
std::unique_ptr< Trk::Surface > m_associatedSurface
std::vector< GeoInfo > m_tubeGeo
GeoInfo makeGeoInfo(const int tubelayer, const int tube) const
double tubePitch() const
Returns the distance between 2 tubes in a tube layer.
bool getWireFirstLocalCoordAlongR(int tubeLayer, double &coord) const
Amg::Vector3D nodeform_tubePos(const Identifier &id) const
Returns the global position of the tube excluding the B-line & As-built corrections.
bool barrel() const
Returns whether the chamber is in the barrel (Assement on first later in stationName).
void clearCache() override final
virtual const Trk::Surface & surface() const override final
Return surface associated with this detector element.
CxxUtils::CachedValue< int > m_zsignRO_tubeFrame
double innerTubeRadius() const
Returns the inner tube radius excluding the aluminium walls.
std::vector< std::unique_ptr< Trk::CylinderBounds > > m_tubeBounds
CxxUtils::CachedValue< Amg::Vector3D > m_elemNormal
bool containsId(const Identifier &id) const override
Amg::Transform3D deformedTransform(const int tubelayer, const int tube) const
std::vector< const Trk::Surface * > surfaces() const
returns all the surfaces contained in this detector element
bool getWireFirstLocalCoordAlongZ(int tubeLayer, double &coord) const
void fillCache() override final
double getWireLength(const int tubeLayer, const int tube) const
void setNLayers(const int nl)
Sets the number of layers.
Amg::Transform3D globalToLocalTransf(const int tubeLayer, const int tube) const
const MdtIdHelper & m_idHelper
MdtReadoutElement(GeoVFullPhysVol *pv, const std::string &stName, MuonDetectorManager *mgr)
std::array< double, maxnlayers > m_firstwire_y
The MuonDetectorManager stores the transient representation of the Muon Spectrometer geometry and pro...
MuonReadoutElement(GeoVFullPhysVol *pv, MuonDetectorManager *mgr, Trk::DetectorElemType detType)
const Muon::IMuonIdHelperSvc * idHelperSvc() const
Amg::Transform3D toParentStation() const
int getStationIndex() const
void setStationName(const std::string &)
int getStationPhi() const
const MuonDetectorManager * manager() const
int getStationEta() const
double getLongSsize() const
const MuonStation * parentMuonStation() const
const std::string & getStationName() const
Identifier identify() const override final
Returns the ATLAS Identifier of the MuonReadOutElement.
std::string getTechnologyType() const
const Amg::Transform3D & getNativeToAmdbLRS() const
const MdtAsBuiltPar * getMdtAsBuiltParams() const
Bounds for a cylindrical Surface.
Class for a StraightLineSurface in the ATLAS detector to describe dirft tube and straw like detectors...
Abstract base class for surface bounds to be specified.
Abstract Base Class for tracking surfaces.
const Amg::Vector3D & center() const
Returns the center position of the Surface.
Amg::Transform3D getRotateX3D(double angle)
get a rotation transformation around X-axis
Amg::Transform3D getTranslate3D(const double X, const double Y, const double Z)
: Returns a shift transformation along an arbitrary axis
Eigen::AngleAxisd AngleAxis3D
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Matrix< double, 3, 3 > RotationMatrix3D
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
Eigen::Translation< double, 3 > Translation3D
Ensure that the Athena extensions are properly loaded.
Ensure that the ATLAS eigen extensions are properly loaded.
#define THROW_EXCEPTION(MESSAGE)