ATLAS Offline Software
Loading...
Searching...
No Matches
SegmentFittingAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4#include "SegmentFittingAlg.h"
5
7
11#include <ActsInterop/Logger.h>
12
14
15#include <format>
16
17using namespace Acts;
18namespace MuonR4 {
19 using namespace SegmentFit;
20 using namespace MuonValR4;
21
23
26 ATH_CHECK(m_geoCtxKey.initialize());
27 ATH_CHECK(m_seedKey.initialize());
28 ATH_CHECK(m_outSegments.initialize());
29 ATH_CHECK(m_calibTool.retrieve());
30 ATH_CHECK(m_idHelperSvc.retrieve());
31 ATH_CHECK(m_visionTool.retrieve(EnableTool{!m_visionTool.empty()}));
33 m_ambiSolver = std::make_unique<SegmentAmbiSolver>(name(), std::move(cfg));
34
36 fitCfg.calibrator = m_calibTool.get();
37 fitCfg.visionTool = m_visionTool.get();
38 fitCfg.idHelperSvc = m_idHelperSvc.get();
39 fitCfg.fitT0 = m_doT0Fit;
40 fitCfg.recalibrate = m_recalibInFit;
41 fitCfg.useFastFitter = m_useFastFitter;
42 fitCfg.fastPreFitter = m_fastPreFitter;
43 fitCfg.ignoreFailedPreFit = m_ignoreFailedPreFit;
44 fitCfg.useHessian = m_hessianResidual;
45
49
53 fitCfg.maxIter = m_maxIter;
54 ATH_MSG_DEBUG("Fitter configuration: \n - fitT0: "<<m_doT0Fit
55 <<"\n - recalibInFit: "<<m_recalibInFit
56 <<"\n - useFastFitter: "<<m_useFastFitter
57 <<"\n - fastPreFitter: "<<m_fastPreFitter
58 <<"\n - ignoreFailedPreFit: "<<m_ignoreFailedPreFit
59 <<"\n - hessianResidual: "<<m_hessianResidual
60 <<"\n - doBeamSpotConstraint: "<<m_doBeamspotConstraint
61 <<"\n - beamSpotR: "<<m_beamSpotR
62 <<"\n - beamSpotL: "<<m_beamSpotL
63 <<"\n - outlierRemovalCut: "<<m_outlierRemovalCut
64 <<"\n - recoveryPull: "<<m_recoveryPull
65 <<"\n - precHitCut: "<<m_precHitCut
66 <<"\n - maxIter: "<<m_maxIter);
67
68 m_fitter = std::make_unique<SegmentFit::SegmentLineFitter>(name(), std::move(fitCfg));
69
70 MdtSegmentSeedGenerator::Config genCfg{};
71 genCfg.hitPullCut = m_seedHitChi2;
72 genCfg.busyLayerLimit = m_busyLayerLimit;
73 genCfg.startWithPattern = m_tryPatternPars;
74 ATH_MSG_DEBUG("Seeder configuration: \n - "<<m_tryPatternPars
75 <<"\n - "<<m_seedHitChi2
76 <<"\n - "<<m_busyLayerLimit);
77 m_seeder = std::make_unique<SegmentFit::MdtSegmentSeedGenerator>(genCfg, makeActsAthenaLogger(this, name()));
78 genCfg.busyLayerLimit += 2;
79 m_seederBEE = std::make_unique<SegmentFit::MdtSegmentSeedGenerator>(genCfg, makeActsAthenaLogger(this, name()));
80
81 return StatusCode::SUCCESS;
82 }
83 StatusCode SegmentFittingAlg::execute(const EventContext& ctx) const {
84 const ActsTrk::GeometryContext* gctx{nullptr};
85 ATH_CHECK(SG::get(gctx, m_geoCtxKey, ctx));
86 const SegmentSeedContainer* segmentSeeds=nullptr;
87 ATH_CHECK(SG::get(segmentSeeds, m_seedKey, ctx));
88
89 SG::WriteHandle writeSegments{m_outSegments, ctx};
90 ATH_CHECK(writeSegments.record(std::make_unique<SegmentContainer>()));
91 SegmentVec_t allSegments{};
92 ATH_MSG_VERBOSE("execute() - Start processing " << segmentSeeds->size() << " pattern seeds.");
93 for (const SegmentSeed* seed : *segmentSeeds) {
94 SegmentVec_t segments = fitSegmentSeed(ctx, *gctx, seed);
95 if (m_visionTool.isEnabled() && segments.size() > 1) {
96 auto drawFinalReco = [this, &segments, &gctx, &ctx,&seed](const std::string& nameTag) {
97 PrimitiveVec segmentLines{};
98 double yLegend{0.85};
99 segmentLines.push_back(drawLabel(std::format("# segments: {:d}", segments.size()), 0.2, yLegend, 14));
100 yLegend-=0.04;
101 for (const std::unique_ptr<Segment>& seg : segments) {
102 const Parameters pars = localSegmentPars(*gctx, *seg);
103 const auto [pos, dir] = makeLine(pars);
104 segmentLines.emplace_back(drawLine(pars, -Gaudi::Units::m, Gaudi::Units::m, kRed));
105 std::stringstream signStream{};
106 signStream<<std::format("#chi^{{2}}/nDoF: {:.2f} ({:}), ", seg->chi2() / seg->nDoF(), seg->nDoF());
107 signStream<<std::format("y_{{0}}={:.2f}",pars[toUnderlying(ParamDefs::y0)])<<", ";
108 signStream<<std::format("#theta={:.2f}^{{#circ}}", pars[toUnderlying(ParamDefs::theta)]/ Gaudi::Units::deg )<<", ";
109 for (const Segment::MeasType& m : seg->measurements()) {
110 if (m->type() == xAOD::UncalibMeasType::MdtDriftCircleType && m->fitState() == CalibratedSpacePoint::State::Valid) {
111 signStream<<(SeedingAux::strawSign(pos, dir, *m) == -1 ? "L" : "R");
112 }
113 }
114 segmentLines.push_back(drawLabel(signStream.str(), 0.2, yLegend, 13));
115 yLegend-=0.03;
116 }
117
118 m_visionTool->visualizeBucket(ctx, *seed->parentBucket(), nameTag, std::move(segmentLines));
119 };
120 drawFinalReco("all segments");
121 const unsigned int nBeforeAmbi = segments.size();
122 segments = m_ambiSolver->resolveAmbiguity(*gctx, std::move(segments));
123 if (nBeforeAmbi != segments.size()) {
124 drawFinalReco("post ambiguity");
125 }
126 } else if (m_visionTool.isEnabled() && segments.empty() &&
127 std::ranges::any_of(seed->getHitsInMax(),[this](const SpacePoint* hit){
128 return m_visionTool->isLabeled(*hit);
129 })) {
130 m_visionTool->visualizeSeed(ctx, *seed, "Failed fit");
131 }
132 allSegments.insert(allSegments.end(), std::make_move_iterator(segments.begin()),
133 std::make_move_iterator(segments.end()));
134 }
135 resolveAmbiguities(*gctx, allSegments);
136 writeSegments->insert(writeSegments->end(),
137 std::make_move_iterator(allSegments.begin()),
138 std::make_move_iterator(allSegments.end()));
139 ATH_MSG_VERBOSE("Found in total "<<writeSegments->size()<<" segments. ");
140 return StatusCode::SUCCESS;
141 }
142
144 SegmentFittingAlg::fitSegmentSeed(const EventContext& ctx,
145 const ActsTrk::GeometryContext& gctx,
146 const SegmentSeed* patternSeed) const {
147
148 const Amg::Transform3D& locToGlob{patternSeed->msSector()->localToGlobalTransform(gctx)};
149 std::vector<std::unique_ptr<Segment>> segments{};
150
151 Acts::CalibrationContext cctx = ActsTrk::getCalibrationContext(ctx);
152
153 using State_t = MdtSegmentSeedGenerator::State_t;
154 // Make sure patternSeed->parameters() are in ACTS units!
155 State_t seedState{patternSeed->parameters(), patternSeed, m_calibTool.get(), m_recalibSeed};
156
157 const auto* seeder = patternSeed->parameters()[toUnderlying(ParamDefs::theta)] > 50 * Gaudi::Units::deg ?
158 m_seederBEE.get() : m_seeder.get();
159
161 if (m_visionTool.isEnabled()) {
162 PrimitiveVec seedLines{};
163 State_t drawMe{seedState};
164 while(auto s = seeder->nextSeed(cctx, drawMe)) {
165 seedLines.push_back(drawLine(s->parameters, -Gaudi::Units::m, Gaudi::Units::m, kViolet));
166 }
167 seedLines.push_back(drawLabel(std::format("possible seeds: {:d}", drawMe.nGenSeeds()), 0.2, 0.85, 14));
168 m_visionTool->visualizeSeed(ctx, *patternSeed, std::format("pattern_{:}{:}{:}",
170 patternSeed->msSector()->side() ? 'A' : 'C' ,
171 patternSeed->msSector()->sector()), std::move(seedLines));
172 }
173
174 ATH_MSG_VERBOSE("fitSegmentHits() - Start segment seed search");
175 while (auto seed = seeder->nextSeed(cctx, seedState)) {
176 ATH_MSG_VERBOSE("fitSegmentHits() - Found a seed. Try to fit the segment...");
177 // Back convert the seed parameters to athena units
178 seed->parameters[toUnderlying(ParamDefs::t0)] = ActsTrk::timeToAthena(seed->parameters[toUnderlying(ParamDefs::t0)]);
179
181 const auto [pos, dir] = makeLine(seed->parameters);
182 using namespace Acts::detail::LineHelper;
183
184 const Acts::Intersection3D bsExtp = lineIntersect<3>(Amg::Vector3D::Zero(),
185 Amg::Vector3D::UnitZ(),
186 locToGlob*pos,
187 locToGlob.linear()*dir);
188 const Amg::Vector3D closePoint = bsExtp.position();
189 if (closePoint.perp() > 2.*m_beamSpotR ||
190 std::abs(closePoint.z()) > 2.*m_beamSpotL){
191 ATH_MSG_DEBUG("fitSegmentSeed() - Reject parameters "<<toString(seed->parameters)
192 <<" as extrapolation to beamspot is too far "<<Amg::toString(closePoint)
193 <<", r: "<<closePoint.perp());
194 continue;
195 }
196 }
197
198
199 auto segment = m_fitter->fitSegment(ctx, patternSeed, seed->parameters,
200 locToGlob, std::move(seed->hits));
201 if (segment) {
202 segments.push_back(std::move(segment));
203 }
204 }
205 ATH_MSG_VERBOSE("fitSegmentHits() - In total "<<segments.size()<<" segment were constructed ");
206 return segments;
207
208 }
209
211 SegmentVec_t& segmentCandidates) const {
212 if (segmentCandidates.empty()) {
213 return;
214 }
215 ATH_MSG_VERBOSE("resolveAmbiguities() - Resolve ambiguities amongst "
216 <<segmentCandidates.size()<<" segment candidates.");
219
220 for (std::unique_ptr<Segment>& sortMe : segmentCandidates) {
221 const MuonGMR4::SpectrometerSector* chamb = sortMe->msSector();
222 candidatesPerChamber[chamb].push_back(std::move(sortMe));
223 }
224 segmentCandidates.clear();
225 for (auto& [chamber, resolveMe] : candidatesPerChamber) {
226 const std::size_t nBefore = resolveMe.size();
227 SegmentVec_t resolvedSegments = m_ambiSolver->resolveAmbiguity(gctx, std::move(resolveMe));
228 ATH_MSG_DEBUG("resolveAmbiguities() - "<<resolvedSegments.size()<<"/"<<nBefore
229 <<" segments survived ambiguity solving in "<<chamber->identString()<<".");
230 segmentCandidates.insert(segmentCandidates.end(),
231 std::make_move_iterator(resolvedSegments.begin()),
232 std::make_move_iterator(resolvedSegments.end()));
233 }
234 ATH_MSG_VERBOSE("Ambiguity solving done "<<segmentCandidates.size()<<" survived.");
235 }
236}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
std::unique_ptr< const Acts::Logger > makeActsAthenaLogger(IMessageSvc *svc, const std::string &name, int level, std::optional< std::string > parent_name)
size_type size() const noexcept
Returns the number of elements in the collection.
A spectrometer sector forms the envelope of all chambers that are placed in the same MS sector & laye...
int8_t side() const
Returns the side of the MS-sector 1 -> A side ; -1 -> C side.
const Amg::Transform3D & localToGlobalTransform(const ActsTrk::GeometryContext &gctx) const
Returns the local -> global tarnsformation from the sector.
int sector() const
Returns the sector of the MS-sector.
Muon::MuonStationIndex::ChIndex chamberIndex() const
Returns the chamber index scheme.
SeedingState< HitVec_t, CalibCont_t, SeederStateBase > State_t
Define the state holder object.
std::unique_ptr< SegmentFit::SegmentAmbiSolver > m_ambiSolver
Pointer to the ambiguity reosolution.
Gaudi::Property< unsigned > m_precHitCut
Minimum number of precision hits to accept the segment.
Gaudi::Property< bool > m_hessianResidual
Use the expliciit Hessian in the residual calculation.
virtual StatusCode initialize() override
Gaudi::Property< bool > m_recalibSeed
Toggle seed recalibration.
Gaudi::Property< double > m_seedHitChi2
Two mdt seeds are the same if their defining parameters match wihin.
Gaudi::Property< bool > m_useFastFitter
Use the fast Mdt fitter where possible.
ToolHandle< MuonValR4::IPatternVisualizationTool > m_visionTool
Pattern visualization tool.
Gaudi::Property< double > m_beamSpotL
Gaudi::Property< bool > m_recalibInFit
SG::WriteHandleKey< SegmentContainer > m_outSegments
SegmentVec_t fitSegmentSeed(const EventContext &ctx, const ActsTrk::GeometryContext &gctx, const SegmentSeed *seed) const
Fit the hits from the pattern seed to segment candidates.
Gaudi::Property< bool > m_fastPreFitter
The fast fitter is treated as a pre fitter.
std::unique_ptr< SegmentFit::MdtSegmentSeedGenerator > m_seederBEE
Pointer to the L-R segment seeder used for the BEE chambers -> increased hit occupancy.
void resolveAmbiguities(const ActsTrk::GeometryContext &gctx, SegmentVec_t &segmentCandidates) const
Resolve the ambiguity amongst the segment candidates within a spectrometer sector.
std::unique_ptr< SegmentFit::MdtSegmentSeedGenerator > m_seeder
Pointer to the L-R segment seeder.
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
IdHelperSvc.
Gaudi::Property< bool > m_doBeamspotConstraint
Add beamline constraint.
ToolHandle< ISpacePointCalibrator > m_calibTool
Handle to the space point calibrator.
std::unique_ptr< SegmentFit::SegmentLineFitter > m_fitter
Pointer to the actual segment fitter.
std::vector< std::unique_ptr< Segment > > SegmentVec_t
Gaudi::Property< bool > m_ignoreFailedPreFit
Switch to try the full fit when the fast pre-fitter fails.
SegmentFit::Parameters Parameters
Gaudi::Property< bool > m_doT0Fit
SG::ReadHandleKey< SegmentSeedContainer > m_seedKey
ReadHandle of the seeds.
Gaudi::Property< double > m_recoveryPull
Gaudi::Property< double > m_beamSpotR
Gaudi::Property< unsigned > m_maxIter
Tune the number of iterations.
virtual StatusCode execute(const EventContext &ctx) const override
SG::ReadHandleKey< ActsTrk::GeometryContext > m_geoCtxKey
Gaudi::Property< unsigned > m_busyLayerLimit
Cut on the number of hits per layer to use the layer for seeding.
Gaudi::Property< double > m_outlierRemovalCut
Cut on the segment chi2 / nDoF to launch the outlier removal.
Gaudi::Property< bool > m_tryPatternPars
Try first to fit the pattern parameters. Then proceed with the straw line tangents.
Representation of a segment seed (a fully processed hough maximum) produced by the hough transform.
Definition SegmentSeed.h:14
const Parameters & parameters() const
Returns the parameter array.
const MuonGMR4::SpectrometerSector * msSector() const
Returns the associated chamber.
Acts::CloneablePtr< CalibratedSpacePoint > MeasType
Calibrated space point type.
The muon space point is the combination of two uncalibrated measurements one of them measures the eta...
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
constexpr double timeToAthena(const double actsT)
Converts a time unit from Acts to Athena units.
Acts::CalibrationContext getCalibrationContext(const EventContext &ctx)
The Acts::Calibration context is piped through the Acts fitters to (re)calibrate the Acts::SourceLink...
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Affine3d Transform3D
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.
std::string toString(const Parameters &pars)
Dumps the parameters into a string with labels in front of each number.
This header ties the generic definitions in this package.
MuonValR4::IPatternVisualizationTool::PrimitiveVec PrimitiveVec
DataVector< SegmentSeed > SegmentSeedContainer
std::unique_ptr< TLine > drawLine(const MuonR4::SegmentFit::Parameters &pars, const double lowEnd, const double highEnd, const int color=kRed+1, const int lineStyle=kDashed, const int view=objViewEta)
Draws a line from the segment fit parameters.
std::unique_ptr< TLatex > drawLabel(const std::string &text, const double xPos, const double yPos, const double textSize=18, const bool useNDC=true, const int color=kBlack)
Create a TLatex label,.
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.
Configuration object to stree the ambiguties.
const ISpacePointCalibrator * calibrator
Pointer to the calibrator.
bool doBeamSpot
Switch to insert a beamspot constraint if possible.
const Muon::IMuonIdHelperSvc * idHelperSvc
Pointer to the idHelperSvc.
unsigned nPrecHitCut
Minimum number of precision hits.
double outlierRemovalCut
Cut on the segment chi2 / nDoF to launch the outlier removal.
const MuonValR4::IPatternVisualizationTool * visionTool
Pointer to the visualization tool.
double recoveryPull
Maximum pull on a measurement to add it back on the line.
double beamSpotRadius
Parameters of the beamspot measurement.