22 using namespace SegmentFit;
27 copied.reserve(
hits.size());
29 [](
const auto& hit) {
return std::make_unique<MuonR4::CalibratedSpacePoint>(*hit);});
36 toRet.chi2 = toCopy.
chi2;
37 toRet.nDoF = toCopy.
nDoF;
42 std::size_t before =
hits.size();
45 return a->type() == xAOD::UncalibMeasType::Other;
47 return before !=
hits.size();
59 ATH_CHECK(m_visionTool.retrieve(EnableTool{!m_visionTool.empty()}));
61 m_ambiSolver = std::make_unique<SegmentAmbiSolver>(
name(), std::move(
cfg));
62 return StatusCode::SUCCESS;
71 ATH_CHECK(writeSegments.record(std::make_unique<SegmentContainer>()));
72 std::vector<std::unique_ptr<Segment>> allSegments{};
74 std::vector<std::unique_ptr<Segment>> segments = fitSegmentSeed(ctx, *gctx, seed);
75 if (m_visionTool.isEnabled() && segments.size() > 1) {
76 auto drawFinalReco = [
this, &segments, &gctx, &ctx,&seed](
const std::string& nameTag) {
79 segmentLines.push_back(
drawLabel(
std::format(
"# segments: {:d}", segments.size()), 0.2, yLegend, 14));
81 for (
const std::unique_ptr<Segment>& seg : segments) {
85 std::stringstream signStream{};
86 signStream<<
std::format(
"#chi^{{2}}/nDoF: {:.2f} ({:}), ", seg->chi2() / seg->nDoF(), seg->nDoF());
87 signStream<<
std::format(
"y_{{0}}={:.2f}",
pars[Acts::toUnderlying(ParamDefs::y0)])<<
", ";
91 signStream<<(SeedingAux::strawSign(
pos,
dir, *
m) == -1 ?
"L" :
"R");
94 segmentLines.push_back(
drawLabel(signStream.str(), 0.2, yLegend, 13));
98 m_visionTool->visualizeBucket(ctx, *seed->parentBucket(), nameTag, std::move(segmentLines));
100 drawFinalReco(
"all segments");
101 const unsigned int nBeforeAmbi = segments.size();
102 segments = m_ambiSolver->resolveAmbiguity(*gctx, std::move(segments));
103 if (nBeforeAmbi != segments.size()) {
104 drawFinalReco(
"post ambiguity");
106 }
else if (m_visionTool.isEnabled() && segments.empty() &&
107 std::ranges::count_if(seed->getHitsInMax(),[
this](
const SpacePoint* hit){
108 return m_visionTool->isLabeled(*hit);
110 m_visionTool->visualizeSeed(ctx, *seed,
"Failed fit");
112 allSegments.insert(allSegments.end(), std::make_move_iterator(segments.begin()),
113 std::make_move_iterator(segments.end()));
115 resolveAmbiguities(*gctx, allSegments);
116 writeSegments->insert(writeSegments->end(),
117 std::make_move_iterator(allSegments.begin()),
118 std::make_move_iterator(allSegments.end()));
119 ATH_MSG_VERBOSE(
"Found in total "<<writeSegments->size()<<
" segments. ");
120 return StatusCode::SUCCESS;
128 if (calibHits.empty()) {
134 if (m_doBeamspotConstraint) {
135 unsigned int numPhi =
std::accumulate(calibHits.begin(), calibHits.end(),0,
136 [](
unsigned int n,
const HitVec::value_type& hit){
137 return n + (hit->fitState() == CalibratedSpacePoint::State::Valid &&
141 const Amg::Transform3D globToLoc{calibHits[0]->spacePoint()->msSector()->globalToLocalTrans(gctx)};
144 covariance[Acts::toUnderlying(
AxisDefs::etaCov)] = Acts::square(m_beamSpotR);
145 covariance[Acts::toUnderlying(
AxisDefs::phiCov)] = Acts::square(m_beamSpotL);
148 auto beamSpotSP = std::make_unique<CalibratedSpacePoint>(
nullptr, std::move(
beamSpot));
149 beamSpotSP->setCovariance(std::move(covariance));
151 calibHits.push_back(std::move(beamSpotSP));
155 const Amg::Transform3D& locToGlob{calibHits[0]->spacePoint()->msSector()->localToGlobalTrans(gctx)};
159 fitCfg.doTimeFit = m_doT0Fit;
160 fitCfg.reCalibrate = m_recalibInFit;
161 fitCfg.useFastFit = m_useFastFitter;
162 fitCfg.useSecOrderDeriv = m_hessianResidual;
165 return fitter.fitSegment(ctx, std::move(calibHits), startPars, locToGlob);
167 std::vector<std::unique_ptr<Segment>>
173 std::vector<std::unique_ptr<Segment>> segments{};
177 genCfg.recalibSeedCircles = m_recalibSeed;
178 genCfg.calibrator = m_calibTool.get();
179 genCfg.startWithPattern = m_tryPatternPars;
185 if (m_visionTool.isEnabled()) {
188 while(
auto s = drawMe.nextSeed(ctx)) {
191 seedLines.push_back(
drawLabel(
std::format(
"possible seeds: {:d}", drawMe.numGenerated()), 0.2, 0.85, 14));
192 m_visionTool->visualizeSeed(ctx, *patternSeed,
"pattern", std::move(seedLines));
197 while (
auto seed = seedGen.nextSeed(ctx)) {
199 data.segmentPars = seed->parameters;
200 data.calibMeasurements = std::move(seed->measurements);
202 if (m_visionTool.isEnabled()) {
203 auto seedCopy = convertToSegment(locToGlob, patternSeed,
copy(
data));
204 m_visionTool->visualizeSegment(ctx, *seedCopy,
std::format(
"Pre fit {:d}", seedGen.numGenerated()));
206 data = fitSegmentHits(ctx, gctx, seed->parameters, std::move(
data.calibMeasurements));
207 data.nIter += seed->nIter;
208 if (m_visionTool.isEnabled() &&
data.converged) {
209 auto seedCopy = convertToSegment(locToGlob, patternSeed,
copy(
data));
210 m_visionTool->visualizeSegment(ctx, *seedCopy,
std::format(
"Intermediate fit {:d}", seedGen.numGenerated()));
212 if (!removeOutliers(ctx, gctx, *patternSeed,
data)) {
215 if (!plugHoles(ctx, gctx, *patternSeed,
data)) {
218 if (m_visionTool.isEnabled()) {
219 auto seedCopy = convertToSegment(locToGlob, patternSeed,
copy(
data));
220 m_visionTool->visualizeSegment(ctx, *seedCopy,
std::format(
"Final fit {:d}", seedGen.numGenerated()));
222 segments.push_back(convertToSegment(locToGlob, patternSeed, std::move(
data)));
224 ATH_MSG_VERBOSE(
"fitSegmentHits() - In total "<<segments.size()<<
" segment were constructed ");
231 const auto [locPos,
locDir] =
data.makeLine();
236 auto finalSeg = std::make_unique<Segment>(std::move(globPos), std::move(globDir),
237 patternSeed, std::move(
data.calibMeasurements),
239 finalSeg->setCallsToConverge(
data.nIter);
240 finalSeg->setParUncertainties(std::move(
data.segmentParErrs));
253 if (
data.nDoF<=0 ||
data.calibMeasurements.empty() ||
data.nPrecMeas < m_precHitCut) {
254 ATH_MSG_VERBOSE(
"No degree of freedom available. What shall be removed?!. nDoF: "
255 <<
data.nDoF<<
", n-meas: "<<
data.calibMeasurements);
259 if (
data.converged &&
data.chi2 /
data.nDoF < m_outlierRemovalCut) {
262 <<
". Don't remove outliers");
273 const auto [segPos, segDir] =
data.makeLine();
276 std::ranges::sort(
data.calibMeasurements,
277 [&](
const HitVec::value_type&
a,
const HitVec::value_type&
b){
278 using enum CalibratedSpacePoint::State;
279 const double chiSqA = a->fitState() == Valid ? SeedingAux::chi2Term(segPos, segDir, *a) : 0.;
280 const double chiSqB = b->fitState() == Valid ? SeedingAux::chi2Term(segPos, segDir, *b) : 0.;
281 return chiSqA < chiSqB;
286 data.nDoF -=
data.calibMeasurements.back()->measuresEta();
287 data.nDoF -=
data.calibMeasurements.back()->measuresPhi();
288 if (m_doT0Fit &&
data.calibMeasurements.back()->hasTime() &&
293 std::vector<HoughHitType> uncalib{};
294 for (
const HitVec::value_type&
calib :
data.calibMeasurements) {
295 uncalib.push_back(
calib->spacePoint());
300 data = std::move(newAttempt);
301 if (m_visionTool.isEnabled()) {
302 auto seedCopy = convertToSegment(seed.msSector()->localToGlobalTrans(gctx), &seed,
copy(
data));
303 m_visionTool->visualizeSegment(ctx, *seedCopy,
"Bad fit recovery");
308 return removeOutliers(ctx, gctx, seed,
data);
317 <<
", chi2: "<<beforeRecov.
chi2<<
", nDoF: "<<beforeRecov.
nDoF<<
", "
320 std::unordered_set<const SpacePoint*> usedSpacePoint{};
322 usedSpacePoint.insert(hit->spacePoint());
327 bool hasCandidate{
false};
329 for (
const std::vector<HoughHitType>& mdtLayer : hitLayers.mdtHits()) {
332 if (usedSpacePoint.count(mdtHit)) {
337 if (dist >= dc->readoutElement()->innerTubeRadius()) {
341 const double pull = std::sqrt(SeedingAux::chi2Term(locPos,
locDir, *calibHit));
342 ATH_MSG_VERBOSE(__func__<<
"() :"<<__LINE__<<
" Candidate hit for recovery "<<m_idHelperSvc->toString(mdtHit->identify())<<
", chi2: "<<
pull);
343 if (
pull <= m_recoveryPull) {
345 candidateHits.push_back(std::move(calibHit));
348 candidateHits.push_back(std::move(calibHit));
355 std::make_move_iterator(candidateHits.begin()),
356 std::make_move_iterator(candidateHits.end()));
357 eraseWrongHits(beforeRecov);
358 return beforeRecov.
nDoF > 0;
363 if (m_doBeamspotConstraint) {
367 candidateHits.insert(candidateHits.end(), std::make_move_iterator(copied.begin()), std::make_move_iterator(copied.end()));
375 for (HitVec::value_type& hit : copiedCandidates) {
379 eraseWrongHits(beforeRecov);
385 if (redChi2 < m_outlierRemovalCut || (beforeRecov.
nDoF == 0) || redChi2 < beforeRecov.
chi2 / beforeRecov.
nDoF) {
388 beforeRecov = std::move(recovered);
391 bool runAnotherTrial =
false;
393 if (m_doBeamspotConstraint) {
396 const auto [beforePos, beforeDir] = beforeRecov.
makeLine();
397 for (HitVec::value_type& copyHit : copied) {
402 bool append = std::sqrt(SeedingAux::chi2Term(beforePos, beforeDir, *copyHit)) < m_recoveryPull;
404 runAnotherTrial =
true;
409 if (!runAnotherTrial) {
412 recovered = fitSegmentHits(ctx, gctx, beforeRecov.
segmentPars, std::move(copied));
420 if (redChi2 < m_outlierRemovalCut || redChi2 < beforeRecov.
chi2 / beforeRecov.
nDoF) {
422 beforeRecov = std::move(recovered);
428 eraseWrongHits(beforeRecov);
430 for (HitVec::value_type& hit : copiedCandidates) {
440 [&segPos, &segDir](
const HitVec::value_type& hit){
441 if (hit->fitState() != CalibratedSpacePoint::State::Outlier) {
446 const double dist = Amg::lineDistance(segPos, segDir, hit->localPosition(), hit->sensorDirection());
447 const auto* dc = static_cast<const xAOD::MdtDriftCircle*>(hit->spacePoint()->primaryMeasurement());
448 return dist >= dc->readoutElement()->innerTubeRadius();
451 }), candidate.calibMeasurements.end());
454 return a->localPosition().z() < b->localPosition().z();
458 std::vector<std::unique_ptr<Segment>>& segmentCandidates)
const {
459 if (segmentCandidates.empty()) {
462 using SegmentVec = std::vector<std::unique_ptr<Segment>>;
463 ATH_MSG_VERBOSE(
"Resolve ambiguities amongst "<<segmentCandidates.size()<<
" segment candidates. ");
464 std::unordered_map<const MuonGMR4::SpectrometerSector*, SegmentVec> candidatesPerChamber{};
466 for (std::unique_ptr<Segment>& sortMe : segmentCandidates) {
468 candidatesPerChamber[chamb].push_back(std::move(sortMe));
470 segmentCandidates.clear();
471 for (
auto& [
chamber, resolveMe] : candidatesPerChamber) {
472 SegmentVec resolvedSegments = m_ambiSolver->resolveAmbiguity(gctx, std::move(resolveMe));
473 segmentCandidates.insert(segmentCandidates.end(),
474 std::make_move_iterator(resolvedSegments.begin()),
475 std::make_move_iterator(resolvedSegments.end()));