ATLAS Offline Software
Loading...
Searching...
No Matches
MuonFastSegmentFittingAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
11
13#include "ActsInterop/Logger.h"
14
15namespace {
19 unsigned int NDoF(const MuonR4::Segment& segment) {
21 const bool isNSW {std::ranges::any_of(segment.measurements(),
22 [](const auto& meas) { return xAOD::isNSW(meas->type()); })};
23 if (isNSW) {
24 return segment.nDoF();
25 }
28 unsigned int nMeas {0};
29 for (const auto& meas : segment.measurements()) {
30 if (!MuonR4::isGoodHit(*meas)) {
31 continue;
32 }
33 nMeas += meas->measuresEta();
34 }
35 return nMeas - 2u;
36 }
38 double calcRedChi2(const MuonR4::Segment& segment) {
39 const unsigned int nDoF {NDoF(segment)};
40 return nDoF > 0ul ? segment.chi2() / nDoF : segment.chi2();
41 }
43 bool betterSegment(const MuonR4::Segment& newSegment,
44 const MuonR4::Segment& oldSegment) {
45 const unsigned int nDoFNew {NDoF(newSegment)};
46 const unsigned int nDoFOld {NDoF(oldSegment)};
47 if (nDoFNew == nDoFOld) {
48 return newSegment.chi2() < oldSegment.chi2();
49 }
50 return nDoFNew > nDoFOld;
51 }
52 using namespace Muon::MuonStationIndex;
54 auto layerRank = [](LayerIndex l) {
55 switch (l) {
56 case LayerIndex::Inner: return 0;
57 case LayerIndex::Middle: return 1;
58 case LayerIndex::Outer: return 2;
59 case LayerIndex::BarrelExtended: return 3;
60 case LayerIndex::Extended: return 4;
61 default: return 5;
62 }
63 };
65 static constexpr double minZVariance {Acts::square(0.1 * Gaudi::Units::mm)};
66}
67
68namespace MuonR4 {
69using namespace Muon::MuonStationIndex;
70using namespace MuonR4::SegmentFit;
71using namespace Acts::UnitLiterals;
72
74 ATH_CHECK(m_outSegments.initialize());
75 ATH_CHECK(m_patternKey.initialize());
76 ATH_CHECK(m_localSegParKey.initialize());
77 ATH_CHECK(m_localSegCovKey.initialize());
78 ATH_CHECK(m_prdLinkKey.initialize());
79 ATH_CHECK(m_prdStateKey.initialize());
80 ATH_CHECK(m_combMeasKey.initialize());
81 ATH_CHECK(m_inPatterns.initialize());
82 ATH_CHECK(m_geoCtxKey.initialize());
83 ATH_CHECK(m_calibTool.retrieve());
84 ATH_CHECK(m_segmentCnvTool.retrieve());
85 ATH_CHECK(m_idHelperSvc.retrieve());
86
87 ATH_CHECK(m_segVisionTool.retrieve(EnableTool(!m_segVisionTool.empty())));
88
91 fitCfg.calibrator = m_calibTool.get();
92 fitCfg.visionTool = m_segVisionTool.get();
93 fitCfg.idHelperSvc = m_idHelperSvc.get();
94 fitCfg.fitT0 = false;
95 fitCfg.calcAlongStrip = false;
96 fitCfg.recalibrate = m_recalibInFit;
97 fitCfg.useFastFitter = m_useFastFitter;
98 fitCfg.fastPreFitter = m_fastPreFitter;
99 fitCfg.ignoreFailedPreFit = m_ignoreFailedPreFit;
100 fitCfg.useHessian = m_hessianResidual;
101 fitCfg.doBeamSpot = false;
104 fitCfg.nPrecHitCut = m_precHitCut;
105 fitCfg.maxIter = m_maxIter;
106 fitCfg.parsToUse = {ParamDefs::y0, ParamDefs::theta};
107
109 SegmentLineFitter::Config nswFitCfg{fitCfg};
110 nswFitCfg.parsToUse = {ParamDefs::x0, ParamDefs::y0, ParamDefs::theta, ParamDefs::phi};
111
112 m_fitter = std::make_unique<LineFitter>(name(), std::move(fitCfg));
113 m_nswFitter = std::make_unique<LineFitter>(name(), std::move(nswFitCfg));
114
116 MdtSegmentSeeder::Config genCfg{};
117 genCfg.hitPullCut = m_seedHitChi2;
118 genCfg.busyLayerLimit = 3;
119 genCfg.startWithPattern = false;
120 m_mdtSeeder = std::make_unique<MdtSegmentSeeder>(std::move(genCfg),
121 makeActsAthenaLogger(this, name()));
122
123 ATH_MSG_DEBUG("FastMuonSABuilder Configuration:\n"
124 << " Recalibrate in fit: " << m_recalibInFit << "\n"
125 << " Use Hessian in residual: " << m_hessianResidual << "\n"
126 << " Seed hit chi2: " << m_seedHitChi2 << "\n"
127 << " Recalibrate seed: " << m_recalibSeed << "\n"
128 << " Good segment cut (reduced chi2): " << m_goodSegmentCut << "\n"
129 << " Outlier removal cut (chi2/nDoF): " << m_outlierRemovalCut << "\n"
130 << " Recovery pull: " << m_recoveryPull << "\n"
131 << " Precision hit cut: " << m_precHitCut << "\n"
132 << " Use fast fitter: " << m_useFastFitter << "\n"
133 << " Fast fitter as pre-fitter: " << m_fastPreFitter << "\n"
134 << " Ignore failed pre-fits: " << m_ignoreFailedPreFit << "\n"
135 << " Max iterations: " << m_maxIter);
136
138 Acts::square(m_beamSpotRadius);
140
141 return StatusCode::SUCCESS;
142}
143
144StatusCode MuonFastSegmentFittingAlg::execute(const EventContext& ctx) const {
145
146 const ActsTrk::GeometryContext* gctx{nullptr};
147 ATH_CHECK(SG::get(gctx, m_geoCtxKey, ctx));
148
149 const GlobalPatternContainer* inPatterns{nullptr};
150 ATH_CHECK(SG::get(inPatterns, m_inPatterns, ctx));
151
153 ATH_CHECK(ship.segmentContainer.record(m_outSegments, ctx));
156
157 using PatLink_t = ElementLink<GlobalPatternContainer>;
159
160 std::size_t patIdx{0};
161 ATH_MSG_DEBUG(__func__<<"() Start fitting segments in " << inPatterns->size() << " global patterns");
162 for (const GlobalPattern* pat : *inPatterns) {
163
164 std::vector<SegmentSeedPair_t> seedSegPairs{processPattern(ctx, *gctx, *pat)};
165
166 if (seedSegPairs.size() <= 1u) {
167 ATH_MSG_DEBUG(__func__<<"() Not enough muon segments to construct a candidate - abort pattern"
168 << std::endl << *pat);
169 patIdx++;
170 continue;
171 }
174 const bool hasPhi {std::ranges::any_of(seedSegPairs, [](const SegmentSeedPair_t& seg) {
175 return std::ranges::any_of(seg.second->measurements(), [](const auto& meas) {
176 return isGoodHit(*meas) && meas->measuresPhi(); });
177 })};
178 const Segment* toAddPhi{nullptr};
179 if(!hasPhi) {
180 toAddPhi = findSegmentToAddPhi(seedSegPairs);
181 }
182
184 ship.segmentContainer->reserve(ship.segmentContainer->size() + seedSegPairs.size());
185 for (const SegmentSeedPair_t& seedSegPair : seedSegPairs) {
186 const Segment_t& seg = seedSegPair.second;
187 xAOD::MuonSegment* segXAOD = m_segmentCnvTool->convertSegment(ctx, *seg, ship);
188
190 dec_patternLink(*segXAOD) = PatLink_t{*inPatterns, patIdx};
191
193 if (toAddPhi && toAddPhi == seg.get()) {
194 segXAOD->setNHits(segXAOD->nPrecisionHits(),
195 segXAOD->nPhiLayers() + 1u,
196 segXAOD->nTrigEtaLayers());
197 }
198
199 ATH_MSG_VERBOSE(__func__<<"() Converted segment " << printSegment(*segXAOD));
200 }
201 patIdx++;
202 }
203 ATH_MSG_DEBUG("Written "<<ship.segmentContainer->size()<<" xAOD::Segments into StoreGate.");
204 return StatusCode::SUCCESS;
205}
206
207std::vector<MuonFastSegmentFittingAlg::SegmentSeedPair_t>
209 const ActsTrk::GeometryContext& gctx,
210 const GlobalPattern& pattern) const {
211 ATH_MSG_VERBOSE(__func__<<"() Start processing " << pattern);
212
213 std::vector<StIndex> stations {pattern.getStations()};
214 std::ranges::sort(stations, [](StIndex s1, StIndex s2) {
215 LayerIndex l1 {toLayerIndex(s1)}, l2 {toLayerIndex(s2)};
216 if (l1 == l2) {
217 return isBarrel(s1);
218 }
219 return layerRank(l1) < layerRank(l2);
220 });
221
222 std::vector<SegmentSeedPair_t> muonSegments{};
223 muonSegments.reserve(3u);
224 for (const StIndex st : stations) {
227 if (muonSegments.size() > 2 || (st == stations.back() && muonSegments.size() == 0.)) {
228 break;
229 }
230 // If we already have a segment in the layer, we don't try to fit another one
231 const LayerIndex layer {toLayerIndex(st)};
232 if (std::ranges::any_of(muonSegments, [&layer](const SegmentSeedPair_t& seg) {
233 return toLayerIndex(seg.second->msSector()->chamberIndex()) == layer; })) {
234 ATH_MSG_VERBOSE(__func__<<"() Already found a segment in layer " << layer
235 << " - skip station " << st);
236 continue;
237 }
239 const HitVec_t& hits {pattern.hitsInStation(st)};
240 const std::vector<Bucket_t>& buckets {pattern.bucketsInStation(st)};
241
243 std::unordered_map<const MuonGMR4::SpectrometerSector*, HitVec_t> hitsPerSector{};
244 std::ranges::for_each(hits, [&hitsPerSector](Hit_t hit) {
245 hitsPerSector[hit->msSector()].push_back(hit);
246 });
249 std::vector<const MuonGMR4::SpectrometerSector*> sectorsInStation{};
250 sectorsInStation.reserve(hitsPerSector.size());
251 std::ranges::transform(hitsPerSector, std::back_inserter(sectorsInStation),
252 [](const auto& pair) { return pair.first; });
253 assert(sectorsInStation.size() > 0 && sectorsInStation.size() <= 2u &&
254 (sectorsInStation.size() == 1u || isSmall(sectorsInStation[0]->chamberIndex()) != isSmall(sectorsInStation[1]->chamberIndex())));
256 if (sectorsInStation.size() == 2u && !isSmall(sectorsInStation[0]->chamberIndex())) {
257 std::swap(sectorsInStation[0], sectorsInStation[1]);
258 }
259
260 std::vector<SegmentSeedPair_t> stSegments{};
261 stSegments.reserve(sectorsInStation.size());
264 for (const MuonGMR4::SpectrometerSector* sector : sectorsInStation) {
265 ATH_MSG_VERBOSE(__func__<<"() Start segment fitting in sector " << sector->identString()
266 <<" station " << st << " with " << hitsPerSector[sector].size() << " hits.");
267 HitVec_t& sectorHits {hitsPerSector[sector]};
268
271 std::vector<Bucket_t> bucketsInSector {};
272 std::ranges::copy_if(buckets, std::back_inserter(bucketsInSector),
273 [&sector](Bucket_t bucket) { return bucket->msSector() == sector;
274 });
275 if (bucketsInSector.empty()) {
276 throw std::runtime_error(std::format("No parent bucket found for sector {} in station {}",
277 sector->identString(), stName(st)));
278 }
279 if (bucketsInSector.size() > 1u) {
280 Bucket_t primaryBucket {*std::ranges::max_element(bucketsInSector,
281 std::ranges::less{}, [&sectorHits](const Bucket_t& b) {
282 return std::ranges::count_if(sectorHits, [&b](const Hit_t& hit) {
283 return std::ranges::any_of(*b, [&hit](const auto& h) {
284 return h.get() == hit; });
285 });
286 })};
287 bucketsInSector.clear();
288 bucketsInSector.push_back(primaryBucket);
289 }
290 Bucket_t parentBucket {bucketsInSector.back()};
291
292 SegmentSeedOpt_t segment{fitSegment(ctx, sector->localToGlobalTransform(gctx),
293 parentBucket, std::move(sectorHits))};
294 if (segment) {
295 ATH_MSG_VERBOSE(__func__<<"() Successfully fitted segment in station "<< st
296 <<": Pos: "<< Amg::toString(segment->second->position())
297 << ", dir: "<< Amg::toString(segment->second->direction())
298 << ", chi2: "<< segment->second->chi2()<<", nDoF: "<<NDoF(*segment->second)<<std::endl
299 << print(segment->second->measurements()));
300 stSegments.push_back(std::move(*segment));
301 // If we found a good segment, we don't try to fit segments in other sectors of the same station.
302 const Segment_t& newSegment {stSegments.back().second};
303 if (calcRedChi2(*newSegment) <= m_goodSegmentCut &&
304 NDoF(*newSegment) >= m_goodSegmentDoF) {
305 break;
306 }
307 continue;
308 }
309 ATH_MSG_VERBOSE(__func__<<"() No segment could be fitted. Try next sector, if any.");
310 }
311 if (stSegments.empty()) {
312 ATH_MSG_DEBUG("No segment could be fitted in station " << st << " for " << pattern);
313 continue;
314 }
315 SegmentSeedPair_t& bestSeg {stSegments.size() > 1
316 ? *std::ranges::max_element(stSegments, [](const SegmentSeedPair_t& s1, const SegmentSeedPair_t& s2) {
317 return betterSegment(*s2.second, *s1.second); })
318 : stSegments.back()};
319 ATH_MSG_VERBOSE(__func__<<"() Best segment in station " << st << ": Pos: " << Amg::toString(bestSeg.second->position())
320 << ", dir: " << Amg::toString(bestSeg.second->direction()) << ", chi2: " << bestSeg.second->chi2() << ", nDoF: " << NDoF(*bestSeg.second));
321
322 muonSegments.push_back(std::move(bestSeg));
323 }
324 ATH_MSG_DEBUG(__func__<<"() Found "<< muonSegments.size()<<" muon segments to construct a candidate.");
325 return muonSegments;
326}
329 const Amg::Transform3D& localToGlobal,
330 Bucket_t parentBucket,
331 std::vector<Hit_t>&& hits) const {
333 std::set<unsigned> layers{};
334 std::ranges::for_each(hits, [this, &layers](Hit_t hit) {
335 if (isPrecisionHit(*hit)) {
336 layers.insert(m_spSorter.sectorLayerNum(*hit));
337 }
338 });
339 if (layers.size() < m_precHitCut) {
340 ATH_MSG_VERBOSE(__func__<<"() Not enough layers with hits to fit a segment, skipping!");
341 return std::nullopt;
342 }
343 Acts::CalibrationContext cctx {ActsTrk::getCalibrationContext(ctx)};
344
346 auto [ValidHits, initialPars] {initializePars(localToGlobal, hits)};
347 if (ValidHits.empty()) {
348 ATH_MSG_VERBOSE(__func__<<"() Failed to initialize initial parameters for segment fitting.");
349 return std::nullopt;
350 }
351 ATH_MSG_VERBOSE(__func__<<"() Start segment fitting with initial parameters: "
352 <<toString(initialPars)<<", hits: "<<print(ValidHits));
353
354 const auto [locPos, locDir] {makeLine(initialPars)};
355 auto houghSeed {std::make_unique<SegmentSeed>(houghTanBeta(locDir), locPos.y(),
356 houghTanAlpha(locDir), locPos.x(),
357 ValidHits.size(), std::move(ValidHits), parentBucket)};
358
360 if (toStationIndex(parentBucket->msSector()->chamberIndex()) == StIndex::EI &&
361 std::ranges::all_of(houghSeed->getHitsInMax(), [](const Hit_t& hit) {
362 return xAOD::isNSW(hit->type()); })) {
363
364 ATH_MSG_VERBOSE(__func__<<"() Found NSW hits. Use the NSW fitter to fit the segment.");
366 CalibSpacePointVec calibHits{m_calibTool->calibrate(ctx,
367 houghSeed->getHitsInMax(), locPos, locDir, 0.)};
368 Segment_t res {m_nswFitter->fitSegment(ctx,
369 houghSeed.get(), initialPars, localToGlobal, std::move(calibHits))};
370 if (res) {
371 return std::make_pair(std::move(houghSeed), std::move(res));
372 }
373 return std::nullopt;
374 }
375
378 std::vector<Segment_t> segments{};
379 MdtSegmentSeeder::State_t seedState{initialPars, houghSeed.get(), m_calibTool.get(), m_recalibSeed.value()};
380
381 ATH_MSG_VERBOSE(__func__<<"() Start segment seed search");
382 while (auto seed = m_mdtSeeder->nextSeed(cctx, seedState)) {
383 ATH_MSG_VERBOSE(__func__<<"() Found a seed. Try to fit the segment...");
384
385 Segment_t segment {m_fitter->fitSegment(ctx, houghSeed.get(), seed->parameters,
386 localToGlobal, std::move(seed->hits))};
387 if (segment) {
388 segments.push_back(std::move(segment));
389 }
390 }
391
392 if (!segments.empty()) {
393 ATH_MSG_VERBOSE(__func__<<"() In total "<<segments.size()<<" segment were constructed. Keep the best one.");
394 if (msgLvl(MSG::VERBOSE) && segments.size() > 1) {
395 for (const Segment_t& seg : segments) {
396 ATH_MSG_VERBOSE(__func__<<"() Segment: Pos: "<<Amg::toString(seg->position())
397 <<", dir: "<<Amg::toString(seg->direction())<<", chi2: "<<seg->chi2()
398 <<", nDoF: "<<NDoF(*seg)<<std::endl<<print(seg->measurements()));
399 }
400 }
401 Segment_t& bestSegment {*std::ranges::max_element(segments, [&](const Segment_t& s1, const Segment_t& s2) {
402 return betterSegment(*s2, *s1);
403 })};
404 return std::make_pair(std::move(houghSeed), std::move(bestSegment));
405 }
406 ATH_MSG_VERBOSE(__func__<<"() No segment seeds could be fitted.");
407 return std::nullopt;
408}
409std::pair<MuonFastSegmentFittingAlg::HitVec_t, Parameters>
411 const HitVec_t& hits) const {
412
413 auto [etaHits, etaPars] = linearRegression(CoordPlane::etaPlane, hits);
414 if (!etaPars || etaHits.size() < m_precHitCut) {
416 ATH_MSG_VERBOSE(__func__<<"() Failed to initialize eta parameters.");
417 return std::pair<HitVec_t, Parameters>{};
418 }
419 const Amg::Vector3D beamspotPos {localToGlobal.inverse().translation()};
420 const Beamspot beamspot{beamspotPos.x(), beamspotPos.z(),
421 beamspotCov(CoordPlane::phiPlane, localToGlobal)};
422 ATH_MSG_VERBOSE(__func__<<"() Use: "<<beamspot<<" for regression in "<<CoordPlane::phiPlane);
423 auto [phiHits, phiPars] = linearRegression(CoordPlane::phiPlane, hits, beamspot);
424
425 if (!phiPars) {
427 phiHits.clear();
428 phiPars = std::make_optional(Line2D_t{0., 0.});
429 }
430
432 for (Hit_t hit : phiHits) {
433 if (!hit->measuresEta()) {
434 etaHits.push_back(hit);
435 }
436 }
437 Parameters pars{};
438 const auto [tanAlpha, x0] = *phiPars;
439 const auto [tanBeta , y0] = *etaPars;
440 pars[Acts::toUnderlying(ParamDefs::y0)] = y0;
441 pars[Acts::toUnderlying(ParamDefs::x0)] = x0;
442 const Amg::Vector3D dir {Acts::makeDirectionFromAxisTangents(tanAlpha, tanBeta)};
443 pars[Acts::toUnderlying(ParamDefs::theta)] = dir.theta();
444 pars[Acts::toUnderlying(ParamDefs::phi)] = dir.phi();
445
446 return std::make_pair(std::move(etaHits), pars);
447}
450 const HitVec_t& hits,
451 const std::optional<Beamspot>& beamspot) const {
454 ATH_MSG_VERBOSE(__func__<<"() Start linear regression in the "<<Plane
455 <<" with "<<hits.size()<<" hits"<<(beamspot ? " & beamspot." : "."));
456
457 const auto CovIdx {Plane == CoordPlane::etaPlane
458 ? Acts::toUnderlying(SpacePoint::CovIdx::etaCov)
459 : Acts::toUnderlying(SpacePoint::CovIdx::phiCov)};
460
461 double S {0.}, Sy {0.}, Sz {0.}, Szz {0.}, Syz {0.};
463 auto accumulate = [&](const double y, const double z, const double w) {
464 S += w;
465 Sy += w * y;
466 Sz += w * z;
467 Szz += w * z * z;
468 Syz += w * z * y;
469 };
470
471 HitVec_t validHits {};
472 for (Hit_t hit : hits) {
473 if ((Plane == CoordPlane::etaPlane && !hit->measuresEta()) ||
474 (Plane == CoordPlane::phiPlane && !hit->measuresPhi())) {
475 continue;
476 }
477 const double sigma2 {(Plane == CoordPlane::etaPlane && hit->isStraw())
478 ? hit->covariance()[CovIdx] + Acts::square(hit->driftRadius())
479 : hit->covariance()[CovIdx]};
480
481 validHits.push_back(hit);
482 const Amg::Vector3D& locPos {hit->localPosition()};
483
484 accumulate(Plane == CoordPlane::etaPlane ? locPos.y() : locPos.x(),
485 locPos.z(),
486 1./sigma2);
487 }
488 if (beamspot) {
489 accumulate(beamspot->coord, beamspot->z, 1./beamspot->cov_coordCoord);
490 }
492 if (validHits.size() + beamspot.has_value() < 2u) {
493 ATH_MSG_VERBOSE(__func__<<"() Not enough hits to do a linear regression in the "
494 <<Plane<<". Valid hits: "<<print(validHits));
495 return std::make_pair(std::move(validHits), std::nullopt);
496 }
499 const double det {S * Szz - Acts::square(Sz)};
500 if (S <= Acts::s_epsilon ||
501 (det / Acts::square(S)) < minZVariance) {
502 ATH_MSG_WARNING(__func__<<"() Degenerate regression in the "
503 <<Plane<<": total weight: "<<S<<", variance in z: "
504 <<det/Acts::square(S)<<" valid hits: "<<print(validHits));
505 return std::make_pair(std::move(validHits), std::nullopt);
506 }
507 Line2D_t pars{};
508 pars[Acts::toUnderlying(ParamDefs2D::slope)] = (S * Syz - Sz * Sy) / det;
509 pars[Acts::toUnderlying(ParamDefs2D::intercept)] = (Szz * Sy - Sz * Syz) / det;
510 ATH_MSG_VERBOSE(__func__<<"() Linear regression in the "
511 <<Plane<<" -> "<<pars<<", with "<<validHits.size()
512 <<" valid hits"<<(beamspot ? " and beamspot." : "."));
513 return std::make_pair(std::move(validHits), std::move(pars));
514}
515const Segment* MuonFastSegmentFittingAlg::findSegmentToAddPhi(std::vector<SegmentSeedPair_t>& segs) const {
516 using enum LayerIndex;
517
520 for (const LayerIndex layer : {Middle, Inner, Outer, Extended, BarrelExtended}) {
521
522 auto it = std::ranges::find_if(segs, [&layer](const SegmentSeedPair_t& seg) {
523 return toLayerIndex(seg.second->msSector()->chamberIndex()) == layer; });
524 if (it != segs.end()) {
525 return it->second.get();
526 }
527 }
528 return nullptr;
529}
531 const Amg::Transform3D& localToGlobal) const {
532
533 const Amg::Vector3D localAxisDir {Amg::Vector3D::Unit(Plane == CoordPlane::etaPlane)};
534 const Amg::Vector3D globalAxisDir {localToGlobal.rotation() * localAxisDir};
535
536 return globalAxisDir.dot(m_beamspotCov * globalAxisDir);
537}
538
539std::ostream& operator<<(std::ostream& os, MuonFastSegmentFittingAlg::CoordPlane plane) {
540 switch (plane) {
542 return os << "etaPlane";
544 return os << "phiPlane";
545 }
546 return os;
547}
548std::ostream& operator<<(std::ostream& os, MuonFastSegmentFittingAlg::ParamDefs2D pars) {
549 switch (pars) {
551 return os << "Intercept";
553 return os << "Slope";
554 default:
555 return os;
556 }
557}
558std::ostream& operator<<(std::ostream& os, const MuonFastSegmentFittingAlg::Line2D_t& line) {
559 return os << "Line [slope, intercept]: ["
560 << line[Acts::toUnderlying(MuonFastSegmentFittingAlg::ParamDefs2D::slope)] << ", "
561 << line[Acts::toUnderlying(MuonFastSegmentFittingAlg::ParamDefs2D::intercept)] << "]";
562}
563std::ostream& operator<<(std::ostream& os, const MuonFastSegmentFittingAlg::Beamspot& beamspot) {
564 return os << "Beamspot [z, coord, sigmaCoord]: ["
565 << beamspot.z<< ", "<<beamspot.coord<< ", "<< std::sqrt(beamspot.cov_coordCoord) << "]";
566}
567}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
bool accumulate(AccumulateMap &map, std::vector< module_t > const &modules, FPGATrackSimMatrixAccumulator const &acc)
Accumulates an accumulator (e.g.
std::pair< std::vector< unsigned int >, bool > res
bool hit(const Container &ids, int pdgId)
std::unique_ptr< const Acts::Logger > makeActsAthenaLogger(IMessageSvc *svc, const std::string &name, int level, std::optional< std::string > parent_name)
Definition Logger.cxx:64
#define y
#define z
bool msgLvl(const MSG::Level lvl) const
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...
Muon::MuonStationIndex::ChIndex chamberIndex() const
Returns the chamber index scheme.
Data class to represent an eta maximum in hough space.
std::vector< CalibSpacePointPtr > CalibSpacePointVec
std::unique_ptr< LineFitter > m_fitter
Pointer to the actual segment fitter.
BooleanProperty m_fastPreFitter
The fast fitter is treated as a pre fitter.
SG::WriteHandleKey< xAOD::MuonSegmentContainer > m_outSegments
Write handle key for the output segments.
BooleanProperty m_useFastFitter
Use the fast Mdt fitter where possible.
Muon::MuonStationIndex::StIndex StIndex
Type alias for the station index.
SegmentFit::Parameters Parameters
Type alias for the segment fitting parameters.
const SpacePointBucket * Bucket_t
Type alias for the bucket type.
const Segment * findSegmentToAddPhi(std::vector< SegmentSeedPair_t > &segs) const
Find the segment to which increase the phi measurement count.
CoordPlane
Define the coordinate planes.
BooleanProperty m_recalibInFit
Toggle the recalibration of hits during the segment fit.
DoubleProperty m_outlierRemovalCut
Cut on the segment chi2 / nDoF to launch the outlier removal.
DoubleProperty m_recoveryPull
Pull value for hit recovery.
Acts::SquareMatrix< 3 > m_beamspotCov
Covariance matrix of the beam spot.
DoubleProperty m_seedHitChi2
Two mdt seeds are the same if their defining parameters match wihin.
std::unique_ptr< LineFitter > m_nswFitter
Pointer to the NSW segment fitter.
std::pair< HitVec_t, std::optional< Line2D_t > > RegressionRes_t
Type alias for the result of the linear regression, consisting of the valid hits and line parameters.
std::pair< Seed_t, Segment_t > SegmentSeedPair_t
Struct to hold the segment and the seed for the needed lifetime.
SG::ReadHandleKey< GlobalPatternContainer > m_inPatterns
Write handle key for the output global patterns.
BooleanProperty m_ignoreFailedPreFit
Switch to try the full fit when the fast pre-fitter fails.
BooleanProperty m_beamSpotLength
Beam spot length.
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Handle to the MuonIdHelper service.
virtual StatusCode execute(const EventContext &ctx) const override
ToolHandle< ISpacePointCalibrator > m_calibTool
Handle to the space point calibrator tool.
SG::WriteHandleKey< xAOD::CombinedMuonStripContainer > m_combMeasKey
Auxiliary container to model two measurements in the same gas gap as a single track state.
std::unique_ptr< Segment > Segment_t
Type alias for the segment type.
std::pair< HitVec_t, Parameters > initializePars(const Amg::Transform3D &localToGlobal, const HitVec_t &hits) const
Estimate the initial parameters for the segment fitting.
UnsignedIntegerProperty m_precHitCut
Minimum number of precision hits to accept the segment.
DecorKey_t m_prdStateKey
Decoration to the PrdLink state (I.e.
DecorKey_t m_localSegCovKey
Decoration of the local fit covariance parameters.
const SpacePoint * Hit_t
Type alias for the hit type & associated vector.
BooleanProperty m_beamSpotRadius
Beam spot radius.
DecorKey_t m_patternKey
Parent global pattern decoration of the segments.
BooleanProperty m_recalibSeed
Toggle seed recalibration.
@ slope
Tangent of the angle, defined as dy/dz or dx/dz according to the plane.
ToolHandle< MuonValR4::IPatternVisualizationTool > m_segVisionTool
Handle to the visualization tool for segments.
std::optional< SegmentSeedPair_t > SegmentSeedOpt_t
Type alias for the segment-seed optional.
UnsignedIntegerProperty m_maxIter
Tune the number of iterations.
SpacePointPerLayerSorter m_spSorter
Spacepoint sorter per logical measurement layer.
double beamspotCov(const CoordPlane Plane, const Amg::Transform3D &localToGlobal) const
Helper method to compute the beamspot covariance in one local coordinate.
std::array< double, Acts::toUnderlying(ParamDefs2D::nParams)> Line2D_t
Type alias for the line representation.
BooleanProperty m_hessianResidual
Use the expliciit Hessian in the residual calculation.
DecorKey_t m_prdLinkKey
Decoration to the links to the associated Uncalibrated measurements.
ActsTrk::GeoContextReadKey_t m_geoCtxKey
Geometry context key.
std::vector< SegmentSeedPair_t > processPattern(const EventContext &ctx, const ActsTrk::GeometryContext &gctx, const GlobalPattern &pattern) const
Main methods steering the segment fitting.
std::unique_ptr< MdtSegmentSeeder > m_mdtSeeder
Pointer to the L-R segment seeder.
SegmentSeedOpt_t fitSegment(const EventContext &ctx, const Amg::Transform3D &localToGlobal, Bucket_t parentBucket, HitVec_t &&hits) const
Fit a segment in a station given the hits & their parent bucket.
DecorKey_t m_localSegParKey
Decoration of the local segment parameters.
DoubleProperty m_goodSegmentCut
Reduced chi2 defining a good segment, stopping the fit of other segments in the same station.
ToolHandle< IxAODSegmentCnvTool > m_segmentCnvTool
Segment converter tool.
RegressionRes_t linearRegression(const CoordPlane Plane, const HitVec_t &hits, const std::optional< Beamspot > &beamspot=std::nullopt) const
Estimate the segment parameters in the plane defined by the CoordPlane template parameter using a wei...
UnsignedIntegerProperty m_goodSegmentDoF
Number of degrees of freedom defining a good segment, stopping the fit of other segments in the same ...
SeedingState< HitVec_t, CalibCont_t, SeederStateBase > State_t
Define the state holder object.
Placeholder for what will later be the muon segment EDM representation.
unsigned int nDoF() const
Returns the number of degrees of freedom.
const MeasVec & measurements() const
Returns the associated measurements.
const MuonGMR4::SpectrometerSector * msSector() const
returns th associated muonChamber
STL class.
Auxiliary class to instantiate WriteDecorHandles.The handles can be created in an empty state.
std::uint8_t nTrigEtaLayers() const
Returns the number of trigger eta hits.
void setNHits(const std::uint8_t nPrecisionHits, const std::uint8_t nPhiLayers, const std::uint8_t nTrigEtaLayers)
Assign the segment hit summary.
std::uint8_t nPrecisionHits() const
Returns the number of precision hits.
std::uint8_t nPhiLayers() const
Returns the number of trigger phi hits.
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
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.
ISpacePointCalibrator::CalibSpacePointVec CalibSpacePointVec
std::string printSegment(const xAOD::MuonSegment &seg)
Print the details of a segment.
double houghTanBeta(const Amg::Vector3D &v)
Returns the hough tanBeta [y] / [z].
std::ostream & operator<<(std::ostream &ostr, const MuonR4::MsTrackSeed &seed)
DataVector< GlobalPattern > GlobalPatternContainer
Abrivation of the GlobalPattern container type.
bool isPrecisionHit(const SpacePoint &hit)
Returns whether the uncalibrated spacepoint is a precision hit (Mdt, micromegas, stgc strips).
std::string print(const cont_t &container)
Print a space point container to string.
bool isGoodHit(const CalibratedSpacePoint &hit)
Returns whether the calibrated spacepoint is valid and therefore suitable to be used in the segment f...
double houghTanAlpha(const Amg::Vector3D &v)
: Returns the hough tanAlpha [x] / [z]
StIndex toStationIndex(ChIndex index)
convert ChIndex into StIndex
bool isSmall(const ChIndex index)
Returns true if the chamber index is in a small sector.
bool isBarrel(const ChIndex index)
Returns true if the chamber index points to a barrel chamber.
LayerIndex
enum to classify the different layers in the muon spectrometer
const std::string & stName(StIndex index)
convert StIndex into a string
LayerIndex toLayerIndex(ChIndex index)
convert ChIndex into LayerIndex
l
Printing final latex table to .tex output file.
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
unsigned long ul
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)
bool isNSW(const UncalibMeasType aodType)
Returns whether the measurement is a NSW measurement.
MuonSegment_v1 MuonSegment
Reference the current persistent version:
Structure to hold the data needed for the conversion and decoration.
StatusCode setupLocalParameters(const DecorKey_t &localParKey, const DecorKey_t &localCovKey, const EventContext &ctx)
Initialize the linking of the local segment parameters and covariance.
StatusCode setupMeasurementLink(const SG::WriteHandleKey< xAOD::CombinedMuonStripContainer > &combinedKey, const DecorKey_t &prdLinkKey, const DecorKey_t &prdStateKey, const EventContext &ctx)
Instantiate the linking of the measurements.
xAOD::FillContainer< xAOD::MuonSegmentContainer, xAOD::MuonSegmentAuxContainer > segmentContainer
Output segment container.
Define simplified beamspot measurement in a selected plane.
double coord
Coordinate of the beamspot in the selected plane, either y or x depending on the plane.
double cov_coordCoord
Variance of the beamspot coordinate in the selected plane.
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.