ATLAS Offline Software
Loading...
Searching...
No Matches
SegmentExtpTest.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "SegmentExtpTest.h"
6
11
12#include "Acts/Definitions/Units.hpp"
13#include "Acts/Surfaces/LineBounds.hpp"
14#include "Acts/Surfaces/PlaneSurface.hpp"
15
19
21#include "GaudiKernel/PhysicalConstants.h"
23
24#include "Acts/Visualization/ObjVisualization3D.hpp"
25#include "Acts/Visualization/GeometryView3D.hpp"
27
28
29using namespace Acts::UnitLiterals;
30using namespace MuonR4::SegmentFit;
31using namespace Acts::detail::LineHelper;
32
33namespace MuonValR4{
35 ATH_CHECK(m_readKey.initialize());
36 ATH_CHECK(m_geoCtxKey.initialize());
37 ATH_CHECK(m_idHelperSvc.retrieve());
39 ATH_CHECK(detStore()->retrieve(m_detMgr));
40 return StatusCode::SUCCESS;
41 }
42 StatusCode SegmentExtpTest::execute(const EventContext& ctx) const {
43 const xAOD::MuonSegmentContainer* segments{nullptr};
44 ATH_CHECK(SG::get(segments, m_readKey, ctx));
45 const ActsTrk::GeometryContext* gctx{nullptr};
46 ATH_CHECK(SG::get(gctx, m_geoCtxKey, ctx));
47 const auto tgContext = gctx->context();
48
49 auto extrapolate = [&](const Acts::BoundTrackParameters& start,
50 const MuonR4::SpacePoint& sp) {
51 const Amg::Transform3D& trf = sp.msSector()->localToGlobalTrans(*gctx);
52 const Acts::Surface& target = xAOD::muonSurface(sp.primaryMeasurement());
53 const Amg::Vector3D n = target.normal(tgContext,
54 Amg::Vector3D::Zero(),
55 Amg::Vector3D::Zero());
56
57 auto lambda = sp.isStraw() ? Amg::intersect<3>(trf * sp.localPosition(),
58 trf.linear() * sp.sensorDirection(),
59 start.position(tgContext),
60 start.direction())
61 : Amg::intersect<3>(start.position(tgContext),
62 start.direction(), n,
63 n.dot(target.center(tgContext)));
64
65 const auto* detEl = static_cast<const ActsTrk::IDetectorElementBase*>(target.associatedDetectorElement());
66 ATH_MSG_VERBOSE("Propagate "<<Amg::toString(start.position(tgContext))<<" + "
67 <<Amg::toString(start.direction())<<" onto surface: "<<target.toString(tgContext)
68 <<"\n, "<<m_idHelperSvc->toString(detEl->identify())
69 << " geoId: "<<target.geometryId()<<", "<<( lambda.value_or(0.) > 0 ? "forward" : "backward"));
70
71 return m_extrapolationTool->propagate(ctx, start, target, lambda.value_or(0.) > 0
72 ? Acts::Direction::Forward()
73 : Acts::Direction::Backward(), 100._m);
74
75 };
76 StatusCode retCode = StatusCode::SUCCESS;
77 for (const xAOD::MuonSegment* segment : *segments) {
78 const MuonR4::Segment* detSeg = MuonR4::detailedSegment(*segment);
79
80 const auto segPars = localSegmentPars(*segment);
81 const auto [locPos, locDir] = makeLine(segPars);
82
83 const MuonGMR4::SpectrometerSector* sector = m_detMgr->getSectorEnvelope(segment->chamberIndex(),
84 segment->sector(),
85 segment->etaIndex());
86 auto startPars = boundSegmentPars(*gctx, *detSeg);
87
88 Acts::ObjVisualization3D visualHelper{};
89 if (m_drawEvent) {
91 drawSegmentLine(*gctx, *segment, visualHelper,
92 Acts::ViewConfig{.color = {220, 0, 0}});
93 drawSegmentMeasurements(*gctx, *segment, visualHelper, Acts::s_viewSurface);
94 }
95
96 if (msgLvl(MSG::VERBOSE)) {
97
98 std::stringstream sstr{};
99 sstr<<"pos: "<<Amg::toString(segment->position())<<", dir: "
100 <<Amg::toString(segment->direction())<<", chi2/nDoF: "
101 <<segment->chiSquared() / segment->numberDoF()<<", nDoF: "<<segment->numberDoF()<<", "
102 <<segment->nPrecisionHits()<<", "<<segment->nPhiLayers()<<std::endl;
103 for (const auto& meas : detSeg->measurements()) {
104 sstr<<" **** "<<(*meas)<<", chi2: "<<SeedingAux::chi2Term(locPos, locDir, *meas)
105 <<", sign: "<<(meas->isStraw() ?
106 (SeedingAux::strawSign(locPos,locDir, *meas) == 1 ? "R" : "L") : "-")
107 <<", geoId: "<<(meas->type() != xAOD::UncalibMeasType::Other ?
108 xAOD::muonSurface(meas->spacePoint()->primaryMeasurement()).geometryId()
109 : Acts::GeometryIdentifier{})
110 <<std::endl;
111 }
112 ATH_MSG_VERBOSE("Run propagation test on "<<sector->identString()<<std::endl<<sstr.str());
113 }
114
115 for (const auto& meas: detSeg->measurements()) {
116 if (!meas->spacePoint() ||
117 meas->fitState() != MuonR4::CalibratedSpacePoint::State::Valid) {
118 continue;
119 }
120 const auto sp = meas->spacePoint();
121 const Acts::Surface& targetSurf{xAOD::muonSurface(sp->primaryMeasurement())};
122
123 const auto& bounds = targetSurf.bounds();
124 Amg::Vector2D lPos{Amg::Vector2D::Zero()};
125 const auto trf = targetSurf.transform(tgContext).inverse() *
126 sector->surface().transform(tgContext);
127 if (targetSurf.type() == Acts::Surface::SurfaceType::Plane) {
128 lPos = (trf * SeedingAux::extrapolateToPlane(locPos, locDir, *meas)).block<2,1>(0,0);
129 if (!bounds.inside(lPos, Acts::BoundaryTolerance::AbsoluteEuclidean(-2._mm))){
130 ATH_MSG_WARNING("The position "<<Amg::toString(lPos)
131 <<" is outside the trapezoid "<<bounds
132 <<" "<<m_idHelperSvc->toString(sp->identify()));
133 continue;
134 }
135 } else if (targetSurf.type() == Acts::Surface::SurfaceType::Straw) {
136 const auto cIsect = lineIntersect<3>(meas->localPosition(),
137 meas->sensorDirection(),
138 locPos, locDir);
139 const auto cIsectPos = cIsect.position();
140 const auto cPos = trf * cIsectPos;
141 lPos[0] = cPos.perp() * SeedingAux::strawSign(locPos, locDir, *meas);
142 lPos[1] = cPos.z();
143 const auto& lBounds = static_cast<const Acts::LineBounds&>(bounds);
144 if (std::abs(cPos.z()) > lBounds.get(Acts::LineBounds::eHalfLengthZ) - 2._cm ||
145 cPos.perp() >lBounds.get(Acts::LineBounds::eR) - 0.2_mm) {
146 ATH_MSG_WARNING("The line is not on measurement "
147 <<m_idHelperSvc->toString(sp->identify())
148 <<" "<<Amg::toString(lPos)<<" vs. "<<bounds<<".");
149 continue;
150 }
151 }
152 auto extpPars = extrapolate(startPars, *sp);
153 if (!extpPars) {
154 ATH_MSG_FATAL("Failed to propagte to "<<(*meas)
155 <<",\n lPos: "<<Amg::toString(trf * meas->localPosition())
156 <<", expected: "<<Amg::toString(lPos)<<", "<<targetSurf.bounds());
157 retCode = StatusCode::FAILURE;
158 continue;
159 }
160 if (m_drawEvent) {
162 drawBoundParameters(*gctx, *extpPars, visualHelper,
163 Acts::ViewConfig{.color = {0, 0, 220}}, 6._cm);
164 }
165
166 if (targetSurf.type() == Acts::Surface::SurfaceType::Plane) {
167 ATH_MSG_DEBUG("Position on "<<m_idHelperSvc->toString(sp->identify())
168 <<" plane "<<Amg::toString(lPos)<<" vs. "
169 <<Amg::toString((*extpPars).localPosition()));
170 const Amg::Vector2D dPos = (*extpPars).localPosition() - lPos;
171 if (dPos.mag() > 0.1_mm) {
172 ATH_MSG_FATAL("Too large deviation on "<<m_idHelperSvc->toString(sp->identify())
173 <<", "<<Amg::toString(dPos));
174 retCode = StatusCode::FAILURE;
175 }
176 } else if (targetSurf.type() == Acts::Surface::SurfaceType::Straw) {
177 const double dist = lPos[0];
178 const double extDist = (*extpPars).parameters()[Acts::eBoundLoc0];
179 const double extLocZ = (*extpPars).parameters()[Acts::eBoundLoc1];
180 const double cov = meas->covariance()[Acts::toUnderlying(AxisDefs::etaCov)];
181 ATH_MSG_DEBUG("Distance on surface "<<m_idHelperSvc->toString(sp->identify())
182 <<" straight: "<<dist<<", extrapolated: "<<extDist
183 <<"--> "<<(extDist - dist ) / std::sqrt(cov)
184 <<", along the tube: "<<lPos[1]<<", extrapolated: "<<extLocZ);
185 if (std::abs(dist - extDist) / std::sqrt(cov) > 0.05 ||
186 std::abs(lPos[1] - extLocZ) > 0.1_mm) {
187 ATH_MSG_FATAL("Too large deviation on "<<m_idHelperSvc->toString(sp->identify())
188 <<", "<<Amg::toString(lPos)<<" vs. ("<<extDist<<", "<<extLocZ<<")"
189 <<", deviate R: "<<(std::abs(dist -extDist) / std::sqrt(cov))
190 <<", deviate Z: "<<std::abs(lPos[1] - extLocZ));
191 retCode = StatusCode::FAILURE;
192 }
193 }
194 }
195 if (m_drawEvent) {
196 visualHelper.write(std::format("ExtTpTest_{:}_{:}_{:}.obj",
197 ctx.eventID().event_number(), segment->index(),
198 MuonR4::printID(*segment)));
199 }
200 }
201
202 return retCode;
203 }
204
205}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static Double_t sp
Handle class for reading from StoreGate.
Acts::GeometryContext context() const
base class interface providing the bare minimal interface extension.
const ServiceHandle< StoreGateSvc > & detStore() const
bool msgLvl(const MSG::Level lvl) const
A spectrometer sector forms the envelope of all chambers that are placed in the same MS sector & laye...
std::string identString() const
Returns a string encoding the chamber index & the sector of the MS sector.
const Acts::PlaneSurface & surface() const
Returns the associated surface.
Placeholder for what will later be the muon segment EDM representation.
const MeasVec & measurements() const
Returns the associated measurements.
The muon space point is the combination of two uncalibrated measurements one of them measures the eta...
SG::ReadHandleKey< ActsTrk::GeometryContext > m_geoCtxKey
Dependency on the geometry alignment.
Gaudi::Property< bool > m_drawEvent
Option to draw every extrapolation asan obj file.
virtual StatusCode execute(const EventContext &ctx) const override final
const MuonGMR4::MuonDetectorManager * m_detMgr
Detector manager to fetch the sector surfaces.
ToolHandle< ActsTrk::IExtrapolationTool > m_extrapolationTool
Track extrapolation tool.
SG::ReadHandleKey< xAOD::MuonSegmentContainer > m_readKey
Declare the data dependency on the standard Mdt+Rpc+Tgc segment container.
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
IdHelperSvc to decode the Identifiers.
virtual StatusCode initialize() override final
std::optional< double > intersect(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
Calculates the point B' along the line B that's closest to a second line A.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
Parameters localSegmentPars(const xAOD::MuonSegment &seg)
Returns the localSegPars decoration from a xAODMuon::Segment.
std::pair< Amg::Vector3D, Amg::Vector3D > makeLine(const Parameters &pars)
Returns the parsed parameters into an Eigen line parametrization.
Acts::BoundTrackParameters boundSegmentPars(const MuonGMR4::MuonDetectorManager &detMgr, const xAOD::MuonSegment &segment, std::optional< Acts::BoundMatrix > cov=std::nullopt, Acts::ParticleHypothesis hypot=Acts::ParticleHypothesis::muon())
Returns the segment parameters as boundTrackParameters.
std::string printID(const xAOD::MuonSegment &seg)
Print the chamber ID of a segment, e.g.
const Segment * detailedSegment(const xAOD::MuonSegment &seg)
Helper function to navigate from the xAOD::MuonSegment to the MuonR4::Segment.
Lightweight algorithm to read xAOD MDT sim hits and (fast-digitised) drift circles from SG and fill a...
void drawBoundParameters(const ActsTrk::GeometryContext &gctx, const Acts::BoundTrackParameters &pars, Acts::ObjVisualization3D &visualHelper, const Acts::ViewConfig &viewConfig=Acts::s_viewLine, const double standardLength=3.*Gaudi::Units::cm)
Draw a line representing the bound track parameters.
void drawSegmentMeasurements(const ActsTrk::GeometryContext &gctx, const xAOD::MuonSegment &segment, Acts::ObjVisualization3D &visualHelper, const Acts::ViewConfig &viewConfig=Acts::s_viewSensitive)
Draw all uncalibrated measurements associated to the segment.
void drawSegmentLine(const ActsTrk::GeometryContext &gctx, const xAOD::MuonSegment &segment, Acts::ObjVisualization3D &visualHelper, const Acts::ViewConfig &viewConfig=Acts::s_viewLine, const double standardLength=1.*Gaudi::Units::m)
Draw a segment line inside the obj file.
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
MuonSegmentContainer_v1 MuonSegmentContainer
Definition of the current "MuonSegment container version".
const Acts::Surface & muonSurface(const UncalibratedMeasurement *meas)
Returns the associated Acts surface to the measurement.
MuonSegment_v1 MuonSegment
Reference the current persistent version: