ATLAS Offline Software
Loading...
Searching...
No Matches
Muon::MuonTrackCleaner Class Reference

#include <MuonTrackCleaner.h>

Inheritance diagram for Muon::MuonTrackCleaner:
Collaboration diagram for Muon::MuonTrackCleaner:

Classes

struct  ChamberLayerStatistics
struct  ChamberPullInfo
struct  ChamberRemovalOutput
 struct to store return values of chamber removal, contains the new track plus a list the removed hits More...
struct  CleaningState
struct  EtaPhiHits
struct  MCTBCleaningInfo
struct  SortByAvePull
struct  SortChamberRemovalResultByChi2Ndof

Public Types

typedef std::vector< MCTBCleaningInfoInfoVec
typedef InfoVec::iterator InfoIt
typedef std::set< const Trk::MeasurementBase * > MeasSet
typedef MeasSet::iterator MeasIt
typedef std::map< Identifier, ChamberPullInfoPullChamberMap
typedef PullChamberMap::iterator PullChamberIt
typedef PullChamberMap::const_iterator PullChamberCit
typedef std::map< Identifier, EtaPhiHitsEtaPhiPerChamberMap
typedef EtaPhiPerChamberMap::iterator EtaPhiPerChamberIt
typedef std::vector< std::pair< double, Identifier > > PullChVec
typedef PullChVec::iterator PullChIt

Public Member Functions

 ~MuonTrackCleaner ()=default
 destructor
StatusCode initialize () override
 AlgTool initialize.
std::unique_ptr< Trk::Trackclean (const Trk::Track &track, const EventContext &ctx) const override
 clean a track, returns a pointer to a new track if successfull.
std::unique_ptr< Trk::Trackclean (const Trk::Track &track, const std::set< Identifier > &chamberRemovalExclusionList, const EventContext &ctx) const override
 clean a track, returns a pointer to a new track if successfull.

Private Member Functions

const Trk::ResidualPullcalculateResPul (const Trk::MeasurementBase &meas, const Trk::TrackParameters &pars) const
 calculate Residual/Pull for a given MeasurementBase + TrackParameters, ownership is transfered to user
std::unique_ptr< Trk::TrackcleanTrack (const EventContext &ctx, const Trk::Track *track, CleaningState &state) const
 clean a track, actual implementation
double calcPull (const double residual, const double locMesCov, const double locTrkCov, const bool &trkStateIsUnbiased) const
 calculate the pull given measurement error and track error
std::unique_ptr< Trk::TrackcleanCompROTs (const EventContext &ctx, std::unique_ptr< Trk::Track > track, CleaningState &state) const
 clean up competing ROTs that consist out of two clusters
std::unique_ptr< Trk::TrackrecoverFlippedMdt (const EventContext &ctx, std::unique_ptr< Trk::Track > track, CleaningState &state) const
 flip signs of MDT hits with large pull if pull if the oppositely signed radius is small
std::unique_ptr< Trk::TrackhitCleaning (const EventContext &ctx, std::unique_ptr< Trk::Track > track, CleaningState &state) const
 remove bad hits from track.
std::unique_ptr< Trk::TrackchamberCleaning (const EventContext &ctx, std::unique_ptr< Trk::Track > track, CleaningState &state) const
 remove bad chamber from track.
std::unique_ptr< Trk::TrackoutlierRecovery (const EventContext &ctx, std::unique_ptr< Trk::Track > track, CleaningState &state, const MuonStationIndex::ChIndex *currentIndex=nullptr) const
 recover outliers that are within the cuts.
bool isOutsideOnTrackCut (const Identifier &id, double res, double pull, double cutScaleFactor) const
 check whether hit is an outlier
ChamberRemovalOutput removeChamber (const EventContext &ctx, const std::unique_ptr< Trk::Track > &track, Identifier chId, bool removePhi, bool removeEta, CleaningState &state) const
 remove chamber from track
void init (const EventContext &ctx, const Trk::Track &track, CleaningState &state) const
 init cleaner
bool checkStations (CleaningState &state) const
bool checkInnerConstraint (CleaningState &state) const
bool checkPhiConstraint (CleaningState &state) const
void printStates (Trk::Track *track) const
std::unique_ptr< Trk::TrackfitTrack (const EventContext &ctx, Trk::Track &track, Trk::ParticleHypothesis pHyp, bool slFit) const
bool extractChambersToBeRemoved (CleaningState &state, std::set< Identifier > &chambersToBeRemovedSet, bool usePhi=false) const
 helper function to extract chambers that are to be removed

Static Private Member Functions

static void unremoveHits (ChamberRemovalOutput &result)
static std::string print (ChamberLayerStatistics &statistics)

Private Attributes

ToolHandle< Trk::ITrackFitterm_trackFitter
ToolHandle< Trk::ITrackFitterm_slTrackFitter {this, "SLFitter", "Trk::GlobalChi2Fitter/MCTBSLFitterMaterialFromTrack"}
ToolHandle< Trk::IUpdatorm_measurementUpdator {this, "MeasurementUpdator", "Trk::KalmanUpdator/MuonMeasUpdator"}
ToolHandle< Muon::IMdtDriftCircleOnTrackCreatorm_mdtRotCreator
ToolHandle< IMuonCompetingClustersOnTrackCreatorm_compRotCreator
ToolHandle< Trk::IResidualPullCalculatorm_pullCalculator
ServiceHandle< Muon::IMuonEDMHelperSvcm_edmHelperSvc
PublicToolHandle< Muon::MuonEDMPrinterToolm_printer {this, "Printer", "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool"}
ServiceHandle< Muon::IMuonIdHelperSvcm_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}
ToolHandle< Trk::IExtrapolatorm_extrapolator {this, "Extrapolator", "Trk::Extrapolator/AtlasExtrapolator"}
SG::ReadCondHandleKey< AtlasFieldCacheCondObjm_fieldCacheCondObjInputKey
Gaudi::Property< bool > m_useMdtResiCut {this, "UseMdtResiCut", false}
Gaudi::Property< double > m_chi2Cut {this, "Chi2Cut", 100.}
Gaudi::Property< double > m_pullCut {this, "PullCut", 5.}
Gaudi::Property< double > m_mdtResiCut {this, "MdtResiCut", 1.}
Gaudi::Property< double > m_pullCutPhi {this, "PullCutPhi", 10.}
Gaudi::Property< double > m_associationScaleFactor {this, "AssociationScaleFactor", 0.7}
Gaudi::Property< unsigned int > m_ncycles {this, "CleaningCycles", 5}
Gaudi::Property< double > m_avePullSumPerChamberCut {this, "MaxAvePullSumPerChamber", 3.5}
Gaudi::Property< bool > m_recoverOutliers {this, "RecoverOutliers", true}
Gaudi::Property< bool > m_flipMdtDriftRadii {this, "FlipMdtDriftRadii", true}
Gaudi::Property< bool > m_cleanCompROTs {this, "CleanCompROTs", true}
Gaudi::Property< bool > m_onlyUseHitErrorInRecovery {this, "OnlyUseHitErrorInRecovery", true}
Gaudi::Property< double > m_adcCut {this, "AdcCut", 50.}
Gaudi::Property< bool > m_iterate {this, "Iterate", 0.7}
Gaudi::Property< bool > m_use_slFit {this, "UseSLFit", false}

Detailed Description

Definition at line 44 of file MuonTrackCleaner.h.

Member Typedef Documentation

◆ EtaPhiPerChamberIt

typedef EtaPhiPerChamberMap::iterator Muon::MuonTrackCleaner::EtaPhiPerChamberIt

Definition at line 129 of file MuonTrackCleaner.h.

◆ EtaPhiPerChamberMap

◆ InfoIt

typedef InfoVec::iterator Muon::MuonTrackCleaner::InfoIt

Definition at line 94 of file MuonTrackCleaner.h.

◆ InfoVec

Definition at line 93 of file MuonTrackCleaner.h.

◆ MeasIt

typedef MeasSet::iterator Muon::MuonTrackCleaner::MeasIt

Definition at line 97 of file MuonTrackCleaner.h.

◆ MeasSet

Definition at line 96 of file MuonTrackCleaner.h.

◆ PullChamberCit

typedef PullChamberMap::const_iterator Muon::MuonTrackCleaner::PullChamberCit

Definition at line 121 of file MuonTrackCleaner.h.

◆ PullChamberIt

typedef PullChamberMap::iterator Muon::MuonTrackCleaner::PullChamberIt

Definition at line 120 of file MuonTrackCleaner.h.

◆ PullChamberMap

◆ PullChIt

typedef PullChVec::iterator Muon::MuonTrackCleaner::PullChIt

Definition at line 132 of file MuonTrackCleaner.h.

◆ PullChVec

typedef std::vector<std::pair<double, Identifier> > Muon::MuonTrackCleaner::PullChVec

Definition at line 131 of file MuonTrackCleaner.h.

Constructor & Destructor Documentation

◆ ~MuonTrackCleaner()

Muon::MuonTrackCleaner::~MuonTrackCleaner ( )
default

destructor

Member Function Documentation

◆ calcPull()

double Muon::MuonTrackCleaner::calcPull ( const double residual,
const double locMesCov,
const double locTrkCov,
const bool & trkStateIsUnbiased ) const
private

calculate the pull given measurement error and track error

◆ calculateResPul()

const Trk::ResidualPull * Muon::MuonTrackCleaner::calculateResPul ( const Trk::MeasurementBase & meas,
const Trk::TrackParameters & pars ) const
private

calculate Residual/Pull for a given MeasurementBase + TrackParameters, ownership is transfered to user

◆ chamberCleaning()

std::unique_ptr< Trk::Track > Muon::MuonTrackCleaner::chamberCleaning ( const EventContext & ctx,
std::unique_ptr< Trk::Track > track,
CleaningState & state ) const
private

remove bad chamber from track.

The returned track pointer can be zero, pointing to the initial track or a new pointer

Definition at line 462 of file MuonTrackCleaner.cxx.

463 {
464 ATH_MSG_DEBUG("run chamber cleaning on track " << m_printer->print(*track));
465
466 if (state.chambersToBeRemoved.empty() && state.chambersToBeRemovedPhi.empty()) return track;
467
468 if (state.pullSumPerChamber.size() == 2) {
469 // loop over chambers that should be removed, if one of them is MDT or CSC don't clean
470 // as this would result in a single chamber track
471 PullChIt chit = state.chambersToBeRemoved.begin();
472 PullChIt chit_end = state.chambersToBeRemoved.end();
473 for (; chit != chit_end; ++chit) {
474 const Identifier& chid = chit->second;
475 if (m_idHelperSvc->isMdt(chid) || m_idHelperSvc->isCsc(chid)) {
476 ATH_MSG_DEBUG(" only two precision chambers, cannot remove chamber. ");
477 return nullptr;
478 }
479 }
480 }
481
482 if (!state.chamberRemovalExclusionList.empty()) {
483 unsigned int foundChambers = 0;
484 // loop over chambers that should be removed and check if they are in the exclusion list
485 PullChIt chit = state.chambersToBeRemoved.begin();
486 PullChIt chit_end = state.chambersToBeRemoved.end();
487 for (; chit != chit_end; ++chit) {
488 const Identifier& chid = chit->second;
489 if (m_idHelperSvc->isMdt(chid) && state.chamberRemovalExclusionList.count(chid)) {
490 ATH_MSG_DEBUG(" found excluded chamber " << m_idHelperSvc->toStringChamber(chid));
491 ++foundChambers;
492 }
493 }
494 unsigned int excludedChambers = state.chamberRemovalExclusionList.size();
495 if (foundChambers > excludedChambers) {
496 ATH_MSG_WARNING(" Found more excluded chambers than in list, this should not happen ");
497 return nullptr;
498 } else if (foundChambers == excludedChambers) {
499 ATH_MSG_DEBUG(" all excluded chambers in removal list, failing cleaning ");
500 return nullptr;
501 }
502 }
503
504 std::vector<ChamberRemovalOutput> cleaningResults;
505 cleaningResults.reserve(state.chambersToBeRemoved.size());
506
507 // TODO first remove hits in both eta and phi
508
509 ATH_MSG_DEBUG(" number of chambers short listed to be removed: " << state.chambersToBeRemoved.size());
510 std::stable_sort(state.chambersToBeRemoved.begin(), state.chambersToBeRemoved.end(), SortByAvePull());
511
512 // try all combinations of removing a chamber with eta hits
513 unsigned int nchambers = state.chambersToBeRemoved.size() + state.chambersToBeRemovedPhi.size();
514 PullChIt chit = state.chambersToBeRemoved.begin();
515 PullChIt chit_end = state.chambersToBeRemoved.end();
516 for (; chit != chit_end; ++chit) {
517 ChamberRemovalOutput result = removeChamber(ctx, track, chit->second, false, true, state);
518 if (!result.track) {
519 ATH_MSG_DEBUG(" Removed eta hits of " << m_idHelperSvc->toStringChamber(chit->second) << ", track lost ");
520 continue;
521 }
522 ATH_MSG_DEBUG(" Removed eta hits of " << m_idHelperSvc->toStringChamber(chit->second));
523 ATH_MSG_DEBUG(m_printer->print(*result.track));
524
525 // this is an optimization for the common case where there is only one chamber to be removed
526 if (nchambers > 1) unremoveHits(result);
527
528 cleaningResults.push_back(std::move(result));
529 } // for (chit)
530
531 ATH_MSG_DEBUG(" number of phi chambers short listed to be removed: " << state.chambersToBeRemoved.size());
532 std::stable_sort(state.chambersToBeRemovedPhi.begin(), state.chambersToBeRemovedPhi.end(), SortByAvePull());
533 // try all combinations of removing a chamber with phi hits
534 chit = state.chambersToBeRemovedPhi.begin();
535 chit_end = state.chambersToBeRemovedPhi.end();
536 for (; chit != chit_end; ++chit) {
537 ChamberRemovalOutput result = removeChamber(ctx, track, chit->second, true, false, state);
538 if (!result.track) {
539 ATH_MSG_DEBUG(" Removed phi hits of " << m_idHelperSvc->toStringChamber(chit->second) << ", track lost ");
540 continue;
541 }
542 ATH_MSG_DEBUG(" Removed phi hits of " << m_idHelperSvc->toStringChamber(chit->second));
543 ATH_MSG_DEBUG(m_printer->print(*result.track));
544
545 // this is an optimization for the common case where there is only one chamber to be removed
546 if (nchambers > 1) unremoveHits(result);
547
548 cleaningResults.push_back(std::move(result));
549 }
550
551 // if no cleaned tracks return 0
552 if (cleaningResults.empty()) return nullptr;
553 std::stable_sort(cleaningResults.begin(), cleaningResults.end(), SortChamberRemovalResultByChi2Ndof());
554 ATH_MSG_DEBUG(" chamberCleaning Results nr " << cleaningResults.size());
555 for (auto& res : cleaningResults) { ATH_MSG_DEBUG(" track " << m_printer->print(*res.track)); }
556
557 ChamberRemovalOutput& finalResult = cleaningResults.front();
558 if (nchambers > 1) {
559 // loop over removed hits and redo 'remove'
560 for (auto* hit : finalResult.removedHits) hit->useInFit = 0;
561 }
562
563 ATH_MSG_DEBUG(" chamberCleaning: track ");
564 ATH_MSG_DEBUG(m_printer->print(*finalResult.track));
565
566 // make clone just in case outlier recovery fails
567 std::unique_ptr<Trk::Track> finalResultTrackClone = std::make_unique<Trk::Track>(*finalResult.track);
568
569 init(ctx, *finalResultTrackClone, state);
570
571 // now finally check whether the removed layer now is recoverable (happens sometimes if the segment has one or more bad hits)
572 ChIndex removedChamberIndex = m_idHelperSvc->chamberIndex(finalResult.chId);
573 std::unique_ptr<Trk::Track> recoveredTrack = outlierRecovery(ctx, std::move(finalResult.track), state, &removedChamberIndex);
574 if (!recoveredTrack) return finalResultTrackClone;
575 init(ctx, *recoveredTrack, state);
576 return recoveredTrack;
577 }
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
std::pair< std::vector< unsigned int >, bool > res
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
void init(const EventContext &ctx, const Trk::Track &track, CleaningState &state) const
init cleaner
std::unique_ptr< Trk::Track > outlierRecovery(const EventContext &ctx, std::unique_ptr< Trk::Track > track, CleaningState &state, const MuonStationIndex::ChIndex *currentIndex=nullptr) const
recover outliers that are within the cuts.
static void unremoveHits(ChamberRemovalOutput &result)
PublicToolHandle< Muon::MuonEDMPrinterTool > m_printer
ChamberRemovalOutput removeChamber(const EventContext &ctx, const std::unique_ptr< Trk::Track > &track, Identifier chId, bool removePhi, bool removeEta, CleaningState &state) const
remove chamber from track
PullChVec::iterator PullChIt
ChIndex
enum to classify the different chamber layers in the muon spectrometer
void stable_sort(DataModel_detail::iterator< DVL > beg, DataModel_detail::iterator< DVL > end)
Specialization of stable_sort for DataVector/List.
struct to store return values of chamber removal, contains the new track plus a list the removed hits

◆ checkInnerConstraint()

bool Muon::MuonTrackCleaner::checkInnerConstraint ( CleaningState & state) const
private

Definition at line 1519 of file MuonTrackCleaner.cxx.

1519 {
1520 unsigned int nstations = state.stations.size();
1521 if (nstations == 1 ||
1522 (nstations == 2 && (state.stations.count(StIndex::EM) && state.stations.count(StIndex::EO)))) {
1523 ATH_MSG_DEBUG(" Momentum measurement lost, cleaning given up ");
1524 return false;
1525 }
1526 return true;
1527 }

◆ checkPhiConstraint()

bool Muon::MuonTrackCleaner::checkPhiConstraint ( CleaningState & state) const
private

Definition at line 1529 of file MuonTrackCleaner.cxx.

1529 {
1530 if (state.stations.size() == 1 && !state.nIdHits && state.nPhiConstraints < 2) {
1531 ATH_MSG_DEBUG(" Underconstraint fit " << state.nPhiConstraints);
1532 return false;
1533 }
1534 return true;
1535 }

◆ checkStations()

bool Muon::MuonTrackCleaner::checkStations ( CleaningState & state) const
private

Definition at line 1508 of file MuonTrackCleaner.cxx.

1508 {
1509 unsigned int nstationsChamberCleaning = state.stations.size();
1510 ATH_MSG_DEBUG(" Cleaner removed full station from track: remaining layers " << nstationsChamberCleaning);
1511
1512 if (nstationsChamberCleaning < 2) {
1513 ATH_MSG_DEBUG(" Cleaner removed all but one station from track!!! ");
1514 return false;
1515 }
1516 return true;
1517 }

◆ clean() [1/2]

std::unique_ptr< Trk::Track > Muon::MuonTrackCleaner::clean ( const Trk::Track & track,
const EventContext & ctx ) const
override

clean a track, returns a pointer to a new track if successfull.

If the input track is does not require cleaning a pointer the the initial track is return in which case the user should not delete the old track! The caller should ensure the track gets deleted.

Definition at line 65 of file MuonTrackCleaner.cxx.

65 {
66 CleaningState state;
67 std::unique_ptr<Trk::Track> cleanedTrack = cleanTrack(ctx, &track, state);
68 return cleanedTrack;
69 }
std::unique_ptr< Trk::Track > cleanTrack(const EventContext &ctx, const Trk::Track *track, CleaningState &state) const
clean a track, actual implementation

◆ clean() [2/2]

std::unique_ptr< Trk::Track > Muon::MuonTrackCleaner::clean ( const Trk::Track & track,
const std::set< Identifier > & chamberRemovalExclusionList,
const EventContext & ctx ) const
override

clean a track, returns a pointer to a new track if successfull.

If the input track is does not require cleaning a pointer the the initial track is return in which case the user should not delete the old track! The cleaning will not clean if all the chambers in the exclusions list are marked as to be deleted. The caller should ensure the track gets deleted.

Definition at line 53 of file MuonTrackCleaner.cxx.

54 {
55 CleaningState state;
56 state.chamberRemovalExclusionList = chamberRemovalExclusionList;
57
58 if (!state.chamberRemovalExclusionList.empty()) {
59 ATH_MSG_DEBUG(" Cleaning with exclusion list " << state.chamberRemovalExclusionList.size());
60 }
61
62 std::unique_ptr<Trk::Track> cleanedTrack = cleanTrack(ctx, &track, state);
63 return cleanedTrack;
64 }
std::set< Identifier > chamberRemovalExclusionList

◆ cleanCompROTs()

std::unique_ptr< Trk::Track > Muon::MuonTrackCleaner::cleanCompROTs ( const EventContext & ctx,
std::unique_ptr< Trk::Track > track,
CleaningState & state ) const
private

clean up competing ROTs that consist out of two clusters

Definition at line 174 of file MuonTrackCleaner.cxx.

175 {
176 if (!m_cleanCompROTs || state.numberOfCleanedCompROTs == 0) return track;
177
178 const Trk::Perigee* perigee = track->perigeeParameters();
179 if (!perigee) {
180 ATH_MSG_DEBUG(" track without perigee ");
181 return nullptr;
182 }
183
184 ATH_MSG_DEBUG(" Clean comp rots " << state.numberOfCleanedCompROTs);
185
186 auto tsos = std::make_unique<Trk::TrackStates>();
187 tsos->reserve(state.measInfo.size());
188
189 unsigned int nmeas = 0;
190 // loop over hits
191 InfoIt hit = state.measInfo.begin();
192 InfoIt hit_end = state.measInfo.end();
193 for (; hit != hit_end; ++hit) {
194 // hits that are flagged as outlier or hits in the chamber to be removed are added as Outlier
195 if (!hit->useInFit) {
196 ATH_MSG_DEBUG(" removing hit " << m_idHelperSvc->toString(hit->id) << " pull " << hit->resPull->pull().front());
197 if (hit->inBounds)
198 tsos->push_back(MuonTSOSHelper::cloneTSOSWithUpdate(*hit->originalState, *hit->meas, *hit->pars,
200
201 continue;
202 } else {
203 if (hit->meas) ++nmeas;
204
205 if (hit->cleanedCompROT) {
206 tsos->push_back(MuonTSOSHelper::cloneTSOSWithUpdate(*hit->originalState, *hit->cleanedCompROT, *hit->pars,
208 ATH_MSG_DEBUG(" replacing CompROT " << m_idHelperSvc->toString(hit->id) << " pull " << hit->resPull->pull().front());
209 } else {
210 tsos->push_back(hit->originalState->clone());
211 }
212 }
213 }
214
215 if (nmeas < 6) {
216 ATH_MSG_DEBUG(" too few hits, cannot recover CompROTS ");
217 return nullptr;
218 }
219
220 // create new track
221 std::unique_ptr<Trk::Track> cleanedTrack =
222 std::make_unique<Trk::Track>(track->info(), std::move(tsos), track->fitQuality() ? track->fitQuality()->uniqueClone() : nullptr);
223 printStates(cleanedTrack.get());
224
225 // fit new track
226 std::unique_ptr<Trk::Track> newTrack = fitTrack(ctx, *cleanedTrack, track->info().particleHypothesis(), state.slFit);
227
228 if (newTrack) {
229 init(ctx, *newTrack, state);
230 return newTrack;
231 } else
232 return nullptr;
233 }
static std::unique_ptr< Trk::TrackStateOnSurface > cloneTSOSWithUpdate(const Trk::TrackStateOnSurface &tsos, const Trk::MeasurementBase &meas, const Trk::TrackParameters &pars, Trk::TrackStateOnSurface::TrackStateOnSurfaceType type)
clone input, replacing the track parameteres and the measurement base and updating the type
InfoVec::iterator InfoIt
std::unique_ptr< Trk::Track > fitTrack(const EventContext &ctx, Trk::Track &track, Trk::ParticleHypothesis pHyp, bool slFit) const
Gaudi::Property< bool > m_cleanCompROTs
void printStates(Trk::Track *track) const
@ Measurement
This is a measurement, and will at least contain a Trk::MeasurementBase.
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee

◆ cleanTrack()

std::unique_ptr< Trk::Track > Muon::MuonTrackCleaner::cleanTrack ( const EventContext & ctx,
const Trk::Track * track,
CleaningState & state ) const
private

clean a track, actual implementation

Definition at line 71 of file MuonTrackCleaner.cxx.

71 {
72 ATH_MSG_DEBUG(" Perform cleaning for track ");
73 ATH_MSG_DEBUG(m_printer->print(*track));
74
75 init(ctx, *track, state);
76
77 ATH_MSG_DEBUG("after init, track is " << m_printer->print(*track));
78 ATH_MSG_DEBUG(" start cleaning ");
79
80 unsigned int nstationsInitial = state.stations.size();
81
82 // first clean up chambers
83 std::unique_ptr<Trk::Track> chamberTrack = chamberCleaning(ctx, std::make_unique<Trk::Track>(*track), state);
84 if (!chamberTrack) {
85 ATH_MSG_DEBUG(" chamber removal failed ");
86 return nullptr;
87 }
88 ATH_MSG_DEBUG("after chamber cleaning, track is " << m_printer->print(*chamberTrack));
89
90 // fail if only station remains on the track
91 unsigned int nstationsChamberCleaning = state.stations.size();
92 if (nstationsInitial != nstationsChamberCleaning) {
93 if (!checkStations(state)) return nullptr;
94 }
95
96 // if performed curved fit and we did not have a vertex constraint or ID hits, reject the track if inner was removed
97 if (!state.slFit && !state.hasVertexConstraint && state.nIdHits <= 0) {
98 if (!checkInnerConstraint(state)) return nullptr;
99 }
100
101 // if performing a single station layer cleaning without ID hits, reject track if there are insufficient phi constraints
102 if (!checkPhiConstraint(state)) return nullptr;
103
104 // clean competing ROTs
105 std::unique_ptr<Trk::Track> cleanCompTrack = cleanCompROTs(ctx, std::move(chamberTrack), state);
106 if (!cleanCompTrack) {
107 ATH_MSG_DEBUG(" CompROT cleaning failed ");
108 return nullptr;
109 }
110 ATH_MSG_DEBUG("after comp rot cleaning, track is " << m_printer->print(*cleanCompTrack));
111
112 // recover MDTs with flipped signs
113 std::unique_ptr<Trk::Track> flippedTrack = recoverFlippedMdt(ctx, std::move(cleanCompTrack), state);
114 if (!flippedTrack) {
115 ATH_MSG_DEBUG(" MDT sign flipping failed ");
116 return nullptr;
117 }
118 ATH_MSG_DEBUG("after flipped mdt recovery, track is " << m_printer->print(*flippedTrack));
119
120 std::unique_ptr<Trk::Track> hitTrack = hitCleaning(ctx, std::move(flippedTrack), state);
121 if (!hitTrack) {
122 ATH_MSG_DEBUG(" track lost after outlier removal ");
123 return nullptr;
124 }
125 ATH_MSG_DEBUG("after hit cleaning, track is " << m_printer->print(*hitTrack));
126
127 // keep this clone in case outlier recovery fails but the rest of the cleaning was succesful.
128 std::unique_ptr<Trk::Track> hitTrackClone = std::make_unique<Trk::Track>(*hitTrack);
129
130 // fail if only one station remains
131 unsigned int nstationsHitCleaning = state.stations.size();
132 if (nstationsInitial != nstationsHitCleaning) {
133 if (!checkStations(state)) return nullptr;
134 }
135
136 // if performed curved fit and we did not have a vertex constraint or ID hits, reject the track if inner was removed
137 if (!state.slFit && !state.hasVertexConstraint && state.nIdHits <= 0) {
138 if (!checkInnerConstraint(state)) return nullptr;
139 }
140
141 // if performing a single station layer cleaning without ID hits, reject track if there are insufficient phi constraints
142 if (!checkPhiConstraint(state)) return nullptr;
143
144 std::unique_ptr<Trk::Track> cleanedTrack = outlierRecovery(ctx, std::move(hitTrack), state);
145 // do not discard tracks that fail outlierRecovery, check that the track is ok
146 // note that this also performs a useful check on the quality of the cleaning in general
147 if (!cleanedTrack || !state.chambersToBeRemoved.empty() || !state.largePullMeasurements.empty()) {
148 init(ctx, *hitTrackClone, state);
149 if (!state.chambersToBeRemoved.empty() || !state.largePullMeasurements.empty()) {
150 ATH_MSG_DEBUG("Outlier recovery failure unrecoverable, reject track");
151 return nullptr;
152 } else {
153 ATH_MSG_DEBUG("Outlier recovery failed but initial track is recoverable");
154 cleanedTrack = std::move(hitTrackClone);
155 }
156 }
157
158 if (state.nhits < state.noutliers) {
159 ATH_MSG_DEBUG(" track rejected due to high outlier ratio: hits " << state.nhits << " outliers " << state.noutliers);
160 return nullptr;
161 }
162
163 unsigned int nstationsFinal = state.stations.size();
164 if (nstationsInitial != nstationsFinal) {
165 if (!checkStations(state)) return nullptr;
166 }
167
168 ATH_MSG_VERBOSE(" final track " << m_printer->print(*cleanedTrack));
169 ATH_MSG_VERBOSE(m_printer->printStations(*cleanedTrack));
170
171 return cleanedTrack;
172 }
#define ATH_MSG_VERBOSE(x)
bool checkPhiConstraint(CleaningState &state) const
bool checkStations(CleaningState &state) const
bool checkInnerConstraint(CleaningState &state) const
std::unique_ptr< Trk::Track > cleanCompROTs(const EventContext &ctx, std::unique_ptr< Trk::Track > track, CleaningState &state) const
clean up competing ROTs that consist out of two clusters
std::unique_ptr< Trk::Track > chamberCleaning(const EventContext &ctx, std::unique_ptr< Trk::Track > track, CleaningState &state) const
remove bad chamber from track.
std::unique_ptr< Trk::Track > hitCleaning(const EventContext &ctx, std::unique_ptr< Trk::Track > track, CleaningState &state) const
remove bad hits from track.
std::unique_ptr< Trk::Track > recoverFlippedMdt(const EventContext &ctx, std::unique_ptr< Trk::Track > track, CleaningState &state) const
flip signs of MDT hits with large pull if pull if the oppositely signed radius is small

◆ extractChambersToBeRemoved()

bool Muon::MuonTrackCleaner::extractChambersToBeRemoved ( CleaningState & state,
std::set< Identifier > & chambersToBeRemovedSet,
bool usePhi = false ) const
private

helper function to extract chambers that are to be removed

Definition at line 1402 of file MuonTrackCleaner.cxx.

1403 {
1404 bool doCleaning = false;
1405 PullChamberMap& pullSumPerChamber = usePhi ? state.pullSumPerChamberPhi : state.pullSumPerChamber;
1406 PullChVec& chambersToBeRemoved = usePhi ? state.chambersToBeRemovedPhi : state.chambersToBeRemoved;
1407
1408 PullChamberCit cit = pullSumPerChamber.begin();
1409 PullChamberCit cit_end = pullSumPerChamber.end();
1410 if (msgLvl(MSG::DEBUG)) {
1411 if (!pullSumPerChamber.empty()) msg() << MSG::DEBUG << "Chamber pulls " << pullSumPerChamber.size() << ":";
1412 }
1413 int ndof = 0;
1414 double pulltot = 0.;
1415 for (; cit != cit_end; ++cit) {
1416 double avePull = cit->second.pullSum / cit->second.nhits;
1417 pulltot += cit->second.pullSum;
1418 ndof += cit->second.nhits;
1419 double avePullReduced = cit->second.nhits > 1 ? (cit->second.pullSum - cit->second.maxPull) / (cit->second.nhits - 1) : avePull;
1420 if (msgLvl(MSG::DEBUG))
1421 msg() << MSG::DEBUG << std::endl
1422 << " chamber " << m_idHelperSvc->toStringChamber(cit->first) << " pull sum " << cit->second.pullSum << " max pull "
1423 << cit->second.maxPull << " nhits " << cit->second.nhits << " ave pull " << avePull << " reduced ave pull "
1424 << avePullReduced;
1425 if (avePull > m_avePullSumPerChamberCut) {
1426 doCleaning = true;
1427 if (cit->second.nhits > 3 && avePullReduced < m_avePullSumPerChamberCut) {
1428 if (msgLvl(MSG::DEBUG)) msg() << MSG::DEBUG << " large pull sum ignored ";
1429 doCleaning = false;
1430 } else {
1431 if (msgLvl(MSG::DEBUG)) msg() << MSG::DEBUG << " large pull sum => removing";
1432 if (!chambersToBeRemovedSet.count(cit->first)) {
1433 chambersToBeRemoved.emplace_back(avePull, cit->first);
1434 chambersToBeRemovedSet.insert(cit->first);
1435 }
1436 }
1437 }
1438 }
1439 if (msgLvl(MSG::DEBUG)) msg() << endmsg;
1440 bool dropMore = false;
1441 if (dropMore && pulltot * pulltot > 2. * ndof * ndof) {
1442 doCleaning = true;
1443 if (msgLvl(MSG::DEBUG)) msg() << MSG::DEBUG << " large pull per dof " << pulltot << " ndof " << ndof << endmsg;
1444 }
1445
1446 if (doCleaning && m_iterate) {
1447 cit = pullSumPerChamber.begin();
1448 for (; cit != cit_end; ++cit) {
1449 double avePull = cit->second.pullSum / cit->second.nhits;
1450 if (!chambersToBeRemovedSet.count(cit->first)) {
1451 chambersToBeRemoved.emplace_back(avePull, cit->first);
1452 chambersToBeRemovedSet.insert(cit->first);
1453 }
1454 }
1455 }
1456
1457 if (dropMore && doCleaning && m_iterate) {
1458 // add trigger chambers
1459 cit = state.pullSumPerChamberEta.begin();
1460 cit_end = state.pullSumPerChamberEta.end();
1461 for (; cit != cit_end; ++cit) {
1462 double avePull = cit->second.pullSum / cit->second.nhits;
1463 if (!chambersToBeRemovedSet.count(cit->first)) {
1464 chambersToBeRemoved.emplace_back(avePull, cit->first);
1465 chambersToBeRemovedSet.insert(cit->first);
1466 }
1467 }
1468 }
1469
1470 return doCleaning;
1471 }
#define endmsg
PullChamberMap::const_iterator PullChamberCit
Gaudi::Property< double > m_avePullSumPerChamberCut
std::map< Identifier, ChamberPullInfo > PullChamberMap
std::vector< std::pair< double, Identifier > > PullChVec
Gaudi::Property< bool > m_iterate
float ndof(const U &p)
MsgStream & msg
Definition testRead.cxx:32

◆ fitTrack()

std::unique_ptr< Trk::Track > Muon::MuonTrackCleaner::fitTrack ( const EventContext & ctx,
Trk::Track & track,
Trk::ParticleHypothesis pHyp,
bool slFit ) const
private

Definition at line 1549 of file MuonTrackCleaner.cxx.

1550 {
1551 return slFit ? m_slTrackFitter->fit(ctx, track, false, pHyp) : m_trackFitter->fit(ctx, track, false, pHyp);
1552 }
ToolHandle< Trk::ITrackFitter > m_trackFitter
ToolHandle< Trk::ITrackFitter > m_slTrackFitter

◆ hitCleaning()

std::unique_ptr< Trk::Track > Muon::MuonTrackCleaner::hitCleaning ( const EventContext & ctx,
std::unique_ptr< Trk::Track > track,
CleaningState & state ) const
private

remove bad hits from track.

The returned track pointer can be zero, pointing to the initial track or a new pointer

Definition at line 296 of file MuonTrackCleaner.cxx.

297 {
298 if (state.largePullMeasurements.empty()) return track;
299 ATH_MSG_DEBUG(" trying outlier removal ");
300
301 const Trk::Perigee* perigee = track->perigeeParameters();
302 if (!perigee) {
303 ATH_MSG_DEBUG("input track without perigee ");
304 return nullptr;
305 }
306
307 std::unique_ptr<Trk::Track> newTrack;
308
309 for (unsigned int n = 0; n < m_ncycles; ++n) {
310 // sanity check, should not remove too many hits
311 if (state.largePullMeasurements.size() > 10) {
312 ATH_MSG_DEBUG(" Too many outliers, cannot perform cleaning ");
313 return nullptr;
314 }
315
316 ATH_MSG_VERBOSE(" outlier removal cycle " << n);
317
318 auto tsos = std::make_unique<Trk::TrackStates>();
319 tsos->reserve(state.measInfo.size());
320 ATH_MSG_VERBOSE("cleaning track with " << state.measInfo.size() << " hits");
321
322 unsigned int nmeas = 0;
323 unsigned int nremovedPhi = 0;
324 bool hasSmall = false;
325 bool hasLarge = false;
326 MCTBCleaningInfo* firstPhi = nullptr;
327 MCTBCleaningInfo* lastPhi = nullptr;
328 std::map<StIndex, std::pair<bool, bool> > slCountsPerStationLayer;
329 // loop over hits
330 InfoIt hit = state.measInfo.begin();
331 InfoIt hit_end = state.measInfo.end();
332 for (; hit != hit_end; ++hit) {
333 bool remove = state.largePullMeasurements.count(hit->meas) || !hit->inBounds || hit->isNoise;
334 // hits that are flagged as outlier or hits in the chamber to be removed are added as Outlier
335 if (!hit->useInFit || remove) {
336 hit->useInFit = 0;
337
338 // count number of phi outliers
339 if (!hit->id.is_valid() || m_idHelperSvc->measuresPhi(hit->id)) ++nremovedPhi;
340
341 if (remove) {
342 std::string inb = hit->inBounds ? " inBounds" : " outBounds";
343 ATH_MSG_DEBUG(" removing hit " << m_idHelperSvc->toString(hit->id) << " pull " << hit->resPull->pull().front()
344 << inb);
345 }
346 if (hit->inBounds) {
347 if (hit->cleanedCompROT) {
348 tsos->push_back(MuonTSOSHelper::cloneTSOSWithUpdate(*hit->originalState, *hit->cleanedCompROT, *hit->pars,
350 } else {
351 tsos->push_back(MuonTSOSHelper::cloneTSOSWithUpdate(*hit->originalState, *hit->meas, *hit->pars,
353 }
354 }
355 continue;
356 } else {
357 if (hit->resPull)
358 ATH_MSG_DEBUG(" keeping hit " << m_idHelperSvc->toString(hit->id) << " pull " << hit->resPull->pull().front());
359
360 if (hit->meas) {
361 ++nmeas;
362 if (!hit->id.is_valid() || m_idHelperSvc->measuresPhi(hit->id)) {
363 if (!firstPhi)
364 firstPhi = &(*hit);
365 else
366 lastPhi = &(*hit);
367 }
368
369 if (hit->id.is_valid() && m_idHelperSvc->isMdt(hit->id)) {
370 StIndex stIndex = toStationIndex(hit->chIndex);
371 bool isSmall = m_idHelperSvc->isSmallChamber(hit->id);
372 bool isLarge = !isSmall;
373 // look for layer
374 std::map<StIndex, std::pair<bool, bool> >::iterator pos =
375 slCountsPerStationLayer.find(stIndex);
376
377 // if not found add current
378 if (pos == slCountsPerStationLayer.end())
379 slCountsPerStationLayer[stIndex] = std::make_pair(isSmall, isLarge);
380 else {
381 // update
382 if (isSmall) slCountsPerStationLayer[stIndex].first = true;
383 if (isLarge) slCountsPerStationLayer[stIndex].second = true;
384 }
385 }
386 }
387 if (!hit->originalState) ATH_MSG_DEBUG("no original state!");
388 tsos->push_back(hit->originalState->clone());
389 }
390 }
391 // loop over sl map and count the overlaps
392 unsigned int noverlaps = 0;
393 for (auto [index, slCounts] : slCountsPerStationLayer) {
394 if (!hasSmall && slCounts.first) hasSmall = true;
395 if (!hasLarge && slCounts.second) hasLarge = true;
396 if (slCounts.first && slCounts.second) ++noverlaps;
397 }
398 // now update for the case there are small and large chambers but not in the same layer
399 if (noverlaps == 0 && hasSmall && hasLarge) ++noverlaps;
400
401 if (nmeas < 6) {
402 ATH_MSG_DEBUG(" too few hits, cannot perform hitCleaning ");
403 return nullptr;
404 }
405
406 ATH_MSG_DEBUG(" nremovedPhi " << nremovedPhi << " noverlaps " << noverlaps << " nid " << state.nIdHits);
407 if (firstPhi) ATH_MSG_DEBUG(" hasFirstPhi: " << m_idHelperSvc->toString(firstPhi->id));
408 if (lastPhi) ATH_MSG_DEBUG(" hasLastPhi: " << m_idHelperSvc->toString(lastPhi->id));
409
410 // only perform check on phi constraints if any phi hits were removed
411 if (nremovedPhi > 0) {
412 bool hasPhiConstraint = false;
413
414 if (state.nIdHits > 0)
415 hasPhiConstraint = true; // ok if ID hits
416 else if (firstPhi && noverlaps > 0)
417 hasPhiConstraint = true; // ok if one phi hit + one overlap
418 else if (noverlaps > 1)
419 hasPhiConstraint = true; // ok if two overlaps
420 else if (firstPhi && lastPhi && firstPhi->pars && lastPhi->pars) {
421 double distPhi =
422 std::abs((firstPhi->pars->position() - lastPhi->pars->position()).dot(firstPhi->pars->momentum().unit()));
423 ATH_MSG_DEBUG(" Distance between phi hits " << distPhi);
424 if (distPhi > 450.) hasPhiConstraint = true;
425 }
426 if (!hasPhiConstraint) {
427 ATH_MSG_DEBUG("Lost phi constraint during track cleaning, reject track");
428 return nullptr;
429 }
430 }
431
432 // create new track
433 std::unique_ptr<Trk::Track> cleanedTrack =
434 std::make_unique<Trk::Track>(track->info(), std::move(tsos), track->fitQuality() ? track->fitQuality()->uniqueClone() : nullptr);
435
436 // fit new track
437 printStates(cleanedTrack.get());
438
439 newTrack = fitTrack(ctx, *cleanedTrack, track->info().particleHypothesis(), state.slFit);
440
441 if (!newTrack) {
442 return nullptr;
443 } else {
444 const Trk::Perigee* perigee = newTrack->perigeeParameters();
445 if (!perigee) {
446 ATH_MSG_DEBUG(" track without perigee ");
447 return nullptr;
448 }
449 // reinitialize cleaner
450 init(ctx, *newTrack, state);
451 }
452
453 if (state.largePullMeasurements.empty()) {
454 ATH_MSG_DEBUG(" cleaning ended successfully after cycle " << n);
455 return newTrack;
456 }
457 }
458
459 return nullptr;
460 }
Gaudi::Property< unsigned int > m_ncycles
StIndex
enum to classify the different station layers in the muon spectrometer
StIndex toStationIndex(ChIndex index)
convert ChIndex into StIndex
bool isSmall(const ChIndex index)
Returns true if the chamber index is in a small sector.
@ distPhi
Definition ParamDefs.h:50

◆ init()

void Muon::MuonTrackCleaner::init ( const EventContext & ctx,
const Trk::Track & track,
CleaningState & state ) const
private

init cleaner

Definition at line 788 of file MuonTrackCleaner.cxx.

788 {
789 // Tell clang to optimize assuming that FP exceptions can trap.
790 // Otherwise, it can vectorize the division, which can lead to
791 // spurious division-by-zero traps from unused vector lanes.
793
794 state.nscatterers = 0;
795 state.numberOfFlippedMdts = 0;
796 state.numberOfCleanedCompROTs = 0;
797 state.nhits = 0;
798 state.noutliers = 0;
799 state.pullSum = ChamberPullInfo();
800 state.pullSumPhi = ChamberPullInfo();
801 state.pullSumTrigEta = ChamberPullInfo();
802 state.chambersToBeRemoved.clear();
803 state.chambersToBeRemovedPhi.clear();
804 state.pullSumPerChamber.clear();
805 state.pullSumPerChamberPhi.clear();
806 state.pullSumPerChamberEta.clear();
807 state.hitsPerChamber.clear();
808 state.outBoundsPerChamber.clear();
809 state.measInfo.clear();
810 state.largePullMeasurements.clear();
811 state.chamberLayerStatistics.clear();
812 state.stations.clear();
813 state.phiLayers.clear();
814 state.hasOfBoundsOutliers = false;
815 state.hasVertexConstraint = false;
816 state.hasSmall = false;
817 state.hasLarge = false;
818 state.nIdHits = 0;
819 state.nPseudoMeasurements = 0;
820 state.nPhiConstraints = 0;
821
822 MagField::AtlasFieldCache fieldCache;
823 // Get field cache object
824 SG::ReadCondHandle<AtlasFieldCacheCondObj> readHandle{m_fieldCacheCondObjInputKey, ctx};
825 if (!readHandle.isValid()) {
826 ATH_MSG_ERROR("Failed to retrieve AtlasFieldCacheCondObj with key " << m_fieldCacheCondObjInputKey.key());
827 return;
828 }
829 readHandle->getInitializedCache(fieldCache);
830
831 state.slFit = !fieldCache.toroidOn() || m_edmHelperSvc->isSLTrack(track);
832 if (m_use_slFit) state.slFit = true;
833
834 // loop over track and calculate residuals
835 const Trk::TrackStates* states = track.trackStateOnSurfaces();
836 if (!states) {
837 ATH_MSG_WARNING(" track without states, cannot perform cleaning ");
838 return;
839 }
840
841 ATH_MSG_DEBUG(" init: " << m_printer->print(track));
842
843 state.measInfo.reserve(states->size());
844
845 std::set<int> rpcLayers;
846 std::set<int> tgcLayers;
847 const Trk::MeasurementBase* mdtmeas = nullptr;
848 double largestmdtpull = -999;
849
850 // loop over TSOSs
851 for (const Trk::TrackStateOnSurface* tsit : *states) {
852 if (tsit->type(Trk::TrackStateOnSurface::Perigee))
853 ATH_MSG_DEBUG(tsit->dumpType() << ", parameters " << *tsit->trackParameters());
854 const Trk::TrackParameters* pars = tsit->trackParameters();
855 if (!pars) {
856 state.measInfo.emplace_back(tsit);
857 continue;
858 }
859
860 if (tsit->type(Trk::TrackStateOnSurface::Scatterer)) {
861 const Trk::MaterialEffectsBase* matEff = tsit->materialEffectsOnTrack();
862 const Trk::MaterialEffectsOnTrack* matTrk = dynamic_cast<const Trk::MaterialEffectsOnTrack*>(matEff);
863 ATH_MSG_VERBOSE(" Scatterer: r " << pars->position().perp() << " z " << pars->position().z());
864 if (matEff) ATH_MSG_VERBOSE(" X0 " << matEff->thicknessInX0());
865 if (matTrk && matTrk->scatteringAngles()) {
866 const Trk::ScatteringAngles* scatAngle = matTrk->scatteringAngles();
867 ATH_MSG_VERBOSE(" pull phi " << scatAngle->deltaPhi() / scatAngle->sigmaDeltaPhi() << " pull theta "
868 << scatAngle->deltaTheta() / scatAngle->sigmaDeltaTheta());
869 }
870 if (matTrk && matTrk->energyLoss()) {
871 const Trk::EnergyLoss* eloss = matTrk->energyLoss();
872 ATH_MSG_DEBUG(" eloss " << eloss->deltaE());
873 }
874 ++state.nscatterers;
875 state.measInfo.emplace_back(tsit);
876 continue;
877 }
878
879 // check whether state is a measurement
880 const Trk::MeasurementBase* meas = tsit->measurementOnTrack();
881 if (!meas) {
882 state.measInfo.emplace_back(tsit);
883 continue;
884 }
885
886 Identifier id = m_edmHelperSvc->getIdentifier(*meas);
887 bool pseudo = !id.is_valid();
888 if (pseudo) ++state.nPseudoMeasurements;
889
890 if (!pseudo && !m_idHelperSvc->mdtIdHelper().is_muon(id)) {
891 ATH_MSG_VERBOSE(" TSOS is not a muon hit, position: r " << pars->position().perp() << " z " << pars->position().z());
892
893 // count ID hits on track
894 if (tsit->type(Trk::TrackStateOnSurface::Measurement) && m_idHelperSvc->mdtIdHelper().is_indet(id)) { ++state.nIdHits; }
895 state.measInfo.emplace_back(tsit);
896 continue;
897 }
898
899 // check whether there is a vertex constraint
900 if (pseudo && dynamic_cast<const Trk::PseudoMeasurementOnTrack*>(meas) && pars->associatedSurface().center().perp() < 200.) {
901 state.hasVertexConstraint = true;
902 }
903
904 Identifier chId = pseudo ? id : m_idHelperSvc->chamberId(id);
905 bool measuresPhi = pseudo ? true : m_idHelperSvc->measuresPhi(id);
906
907 // bound checks
908 Amg::Vector2D locPos;
909 if (!meas->associatedSurface().globalToLocal(pars->position(), pars->position(), locPos)) {
910 ATH_MSG_DEBUG(" localToGlobal failed !!!!! ");
911 continue;
912 }
913 bool inBounds = true;
914 double tol1 = 100.;
915 double tol2 = 2 * tol1;
916 if (!pseudo && m_idHelperSvc->isMdt(id)) tol1 = 5.;
917
918 // we need a special bound check for MDTs so we cast to SL surface
919 const Trk::StraightLineSurface* slSurf = dynamic_cast<const Trk::StraightLineSurface*>(&meas->associatedSurface());
920 // we need a special bound check also for MMs to consider edge passivation
921 const MMClusterOnTrack* mmClusterOnTrack = dynamic_cast<const MMClusterOnTrack*>(meas);
922
923 if (slSurf) {
924 // perform bound check only for second coordinate
925 inBounds = slSurf->bounds().insideLoc2(locPos, tol2);
926 } else if (mmClusterOnTrack) {
927 // for MM, perform the bound check from the detector element
928 inBounds = mmClusterOnTrack->detectorElement()->insideActiveBounds(id, locPos, tol1, tol2);
929 } else {
930 inBounds = meas->associatedSurface().insideBounds(locPos, tol1, tol2);
931 }
932
933 ChIndex chIndex = !pseudo ? m_idHelperSvc->chamberIndex(id) : ChIndex::ChUnknown;
934
935 // pointer to resPull: workaround because a const pointer is returned
936 std::optional<Trk::ResidualPull> resPull{m_pullCalculator->residualPull(
938 if (!resPull) {
939 ATH_MSG_DEBUG(" calculation of residual/pull failed !!!!! ");
940 continue;
941 }
942 int pullSize = resPull->pull().size();
943 double residual = resPull->residual().front();
944 double pull = std::abs(resPull->pull().front());
945
946 // sanity check
947 if (!pseudo && pullSize != 1) {
948 ATH_MSG_WARNING(" ResidualPull vector has size " << pullSize << " for channel " << m_idHelperSvc->toString(id));
949 continue;
950 }
951
952 bool isMDT = !pseudo ? m_idHelperSvc->isMdt(id) : false;
953 double error = pull > 0.001 ? std::abs(residual / pull) : 1000.;
954 double rDrift = isMDT ? meas->localParameters()[Trk::locR] : 0.;
955 double rTrack = isMDT ? pars->parameters()[Trk::locR] : 0.;
956 double rTrackAbs = std::abs(rTrack);
957 double flippedResidual = isMDT ? rDrift + rTrack : 1e10;
958 double flippedPull = isMDT ? std::abs(flippedResidual / error) : 1e10;
959
960 bool isNoise = false;
961 bool isOutlier = isOutsideOnTrackCut(id, residual, pull, 1);
962 bool isRecoverable = m_recoverOutliers && !isOutlier && !isOutsideOnTrackCut(id, residual, pull, m_associationScaleFactor);
963 bool flippedIsRecoverable =
964 isMDT && flippedPull < pull - 0.1 && !isOutsideOnTrackCut(id, flippedResidual, flippedPull, m_associationScaleFactor);
965 double innerRadius = 14.6;
966 if (isMDT) {
967 const MdtDriftCircleOnTrack* mdtdc = dynamic_cast<const MdtDriftCircleOnTrack*>(meas);
968 if (mdtdc) innerRadius = mdtdc->detectorElement()->innerTubeRadius();
969 }
970
971 bool isDelta = isOutlier && isMDT && rTrackAbs < innerRadius && rTrackAbs > std::abs(rDrift);
972
973 // remove all outliers that are too far from the track
974 if (isOutlier) {
975 if (isMDT) {
976 if (rTrackAbs > innerRadius) inBounds = false;
977 } else if (pull > 10.) {
978 inBounds = false;
979 }
980 }
981
982 std::unique_ptr<MdtDriftCircleOnTrack> mdtRotFlipped;
983 std::unique_ptr<const CompetingMuonClustersOnTrack> updatedCompRot;
984 bool flipSign = false;
985 if (!pseudo) {
986 const MdtDriftCircleOnTrack* mdtRot = isMDT ? dynamic_cast<const MdtDriftCircleOnTrack*>(meas) : nullptr;
987 if (mdtRot && mdtRot->prepRawData() && mdtRot->prepRawData()->adc() < m_adcCut) {
988 isNoise = true;
989 isOutlier = true;
990 isRecoverable = false;
991 flippedIsRecoverable = false;
992 isDelta = false;
993 }
994 if (flippedIsRecoverable) {
995 residual = flippedResidual;
996 pull = flippedPull;
997 flipSign = true;
998 }
999 if (!isNoise && flipSign) {
1000 if (mdtRot) {
1001 mdtRotFlipped = std::make_unique<MdtDriftCircleOnTrack>(*mdtRot);
1003 m_mdtRotCreator->updateSign(*mdtRotFlipped, side);
1004 double rDriftFlip = mdtRotFlipped->localParameters()[Trk::locR];
1005 int signRot = rDrift < 0 ? -1 : 1;
1006 int signRotFlip = rDriftFlip < 0 ? -1 : 1;
1007 if (rDrift != 0. && signRot == signRotFlip) {
1008 ATH_MSG_WARNING(" failed to flip sign of MDT " << rDrift << " flip " << rDriftFlip);
1009 }
1010 } else {
1011 ATH_MSG_WARNING(" failed to dynamic_cast measurement with MDT Identifier to a MdtDriftCircleOnTrack");
1012 }
1013 } else {
1014 // if the outlier MDT is not recoverable by flipping the sign, add it as the worst outlier
1015 if (isOutlier && isMDT && pull > largestmdtpull && !tsit->type(Trk::TrackStateOnSurface::Outlier)) {
1016 largestmdtpull = pull;
1017 mdtmeas = meas;
1018 }
1019 }
1020
1021 if (measuresPhi) {
1022 bool isRpc = m_idHelperSvc->isRpc(id);
1023 if (isRpc) {
1024 int layer = 0;
1025 StIndex stIndex = m_idHelperSvc->stationIndex(id);
1026 if (stIndex == StIndex::BM && m_idHelperSvc->rpcIdHelper().doubletR(id) == 1)
1027 layer = 1;
1028 else if (stIndex == StIndex::BO)
1029 layer = 2;
1030 rpcLayers.insert(layer);
1031 }
1032
1033 bool isTgc = m_idHelperSvc->isTgc(id);
1034 if (isTgc) {
1035 int layer = 0;
1036 StIndex stIndex = m_idHelperSvc->stationIndex(id);
1037 if (stIndex == StIndex::EM) {
1038 std::string stName = m_idHelperSvc->chamberNameString(id);
1039 if (stName[1] == '1')
1040 layer = 1;
1041 else if (stName[1] == '2')
1042 layer = 2;
1043 else if (stName[1] == '3')
1044 layer = 3;
1045 else {
1046 ATH_MSG_WARNING("Unable to calculate TGC layer for " << m_idHelperSvc->toString(id));
1047 layer = -1;
1048 }
1049 }
1050 if (layer != -1) tgcLayers.insert(layer);
1051 }
1052 if (m_idHelperSvc->issTgc(id)) {
1053 int layer = 4;
1054 if (m_idHelperSvc->stgcIdHelper().multilayer(id) == 2) layer = 5;
1055 tgcLayers.insert(layer);
1056 ATH_MSG_VERBOSE("adding STGC phi hit " << layer << " size " << tgcLayers.size());
1057 }
1058 }
1059
1060 if (m_cleanCompROTs) {
1061 const CompetingMuonClustersOnTrack* crot = (measuresPhi && !isMDT && m_idHelperSvc->isRpc(id))
1062 ? dynamic_cast<const CompetingMuonClustersOnTrack*>(meas)
1063 : nullptr;
1064 if (crot) {
1065 ATH_MSG_DEBUG(" CompetingMuonClustersOnTrack with rots " << crot->numberOfContainedROTs());
1066 double minpos = 0.;
1067 double minres = 0.;
1068 double maxres = 0.;
1069 double absminres = 0.;
1070 double absmaxres = 0.;
1071 for (unsigned int i = 0; i < crot->numberOfContainedROTs(); ++i) {
1072 const MuonClusterOnTrack* cluster = &crot->rioOnTrack(i);
1073 if (!cluster) continue;
1074 double residual = cluster->localParameters()[Trk::locX] - pars->parameters()[Trk::locX];
1075 double absres = residual < 0. ? -1. * residual : residual;
1076 if (i == 0) {
1077 minres = residual;
1078 maxres = residual;
1079 minpos = cluster->localParameters()[Trk::locX];
1080 absminres = absres;
1081 absmaxres = absres;
1082 } else if (absres < absminres) {
1083 minres = residual;
1084 absminres = absres;
1085 minpos = cluster->localParameters()[Trk::locX];
1086 } else if (absres > absmaxres) {
1087 maxres = residual;
1088 absmaxres = absres;
1089 }
1090 ATH_MSG_VERBOSE(" ROT " << m_idHelperSvc->toString(cluster->identify()) << " lpos "
1091 << cluster->localParameters()[Trk::locX] << " pars " << pars->parameters()[Trk::locX]
1092 << " residual " << residual);
1093 }
1094 ATH_MSG_DEBUG(" residuals: min " << minres << " max " << maxres << " diff " << maxres - minres);
1095 bool splitCompRot = false;
1096 if (std::abs(maxres - minres) > 100 && absmaxres - absminres > 20 && crot->numberOfContainedROTs() < 20) {
1097 ATH_MSG_DEBUG(" recoverable double cluster ");
1098 splitCompRot = true;
1099 }
1100 if (splitCompRot) {
1101 std::list<const Trk::PrepRawData*> prdList;
1102 ATH_MSG_DEBUG(" Splitting comp rot ");
1103 for (unsigned int i = 0; i < crot->numberOfContainedROTs(); ++i) {
1104 const MuonClusterOnTrack* cluster = &crot->rioOnTrack(i);
1105 if (!cluster) continue;
1106 double residual = cluster->localParameters()[Trk::locX] - minpos;
1107 double absres = residual < 0. ? -1. * residual : residual;
1108 if (absres < 40) {
1109 ATH_MSG_DEBUG(" NEW ROT " << m_idHelperSvc->toString(cluster->identify()) << " lpos "
1110 << cluster->localParameters()[Trk::locX] << " pars "
1111 << pars->parameters()[Trk::locX] << " residual " << residual);
1112 prdList.push_back(cluster->prepRawData());
1113 }
1114 }
1115 if (prdList.empty()) {
1116 ATH_MSG_WARNING("No clusters selected during comprot cleaning, keeping old cluster");
1117 } else {
1118 updatedCompRot=m_compRotCreator->createBroadCluster(prdList, 0.);
1119 ++state.numberOfCleanedCompROTs;
1120 }
1121 }
1122 }
1123 }
1124 }
1125
1126 state.measInfo.emplace_back(id, chId, chIndex, inBounds, residual, pull, tsit, meas, pars, std::move(resPull), nullptr);
1127 MCTBCleaningInfo& info = state.measInfo.back();
1128 if (flipSign) { info.flippedMdt = std::move(mdtRotFlipped); }
1129 info.isNoise = isNoise;
1130 if (updatedCompRot) {
1131 ATH_MSG_DEBUG("updated competing ROT");
1132 info.cleanedCompROT = std::move(updatedCompRot);
1133 if (info.cleanedCompROT->associatedSurface() != meas->associatedSurface()) {
1134 std::unique_ptr<Trk::TrackParameters> exPars = m_extrapolator->extrapolate(ctx,
1135 *pars, info.cleanedCompROT->associatedSurface(),
1137 if (!exPars) {
1138 ATH_MSG_WARNING("Update of comp rot parameters failed, keeping old ones");
1139 info.cleanedCompROT.reset();
1140 } else {
1141 info.pars = exPars.get();
1142 state.parsToBeDeleted.emplace_back(std::move(exPars));
1143 }
1144 }
1145 }
1146
1147 ChamberLayerStatistics& chamberStatistics = state.chamberLayerStatistics[chIndex];
1148 chamberStatistics.chIndex = chIndex;
1149
1150 if (tsit->type(Trk::TrackStateOnSurface::Outlier)) {
1151 ATH_MSG_DEBUG(" Outlier " << m_idHelperSvc->toString(id) << m_printer->print(*(info.resPull)));
1152 if (isMDT)
1153 ATH_MSG_DEBUG(" r_drift " << rDrift << " r_trk " << rTrack << " dr " << std::setw(7)
1154 << Amg::error(meas->localCovariance(), Trk::locR));
1155 if (isNoise) ATH_MSG_DEBUG(" noise ");
1156 if (!inBounds)
1157 ATH_MSG_DEBUG(" outBounds ");
1158 else {
1159 ATH_MSG_DEBUG(" inBounds ");
1160 if (flippedIsRecoverable)
1161 ATH_MSG_DEBUG(" flipped is recoverable, rFlipped " << info.flippedMdt->localParameters()[Trk::locR]);
1162 else if (isRecoverable)
1163 ATH_MSG_DEBUG(" recoverable ");
1164 else if (isDelta)
1165 ATH_MSG_DEBUG(" delta ");
1166 }
1167
1168 if (!inBounds) {
1169 state.hasOfBoundsOutliers = true;
1170 ++chamberStatistics.noutBounds;
1171 } else if (flippedIsRecoverable || isRecoverable)
1172 ++chamberStatistics.nrecoverableOutliers;
1173 else if (isDelta)
1174 ++chamberStatistics.ndeltas;
1175 else if (pull < 10)
1176 ++chamberStatistics.noutliers;
1177
1178 if (!pseudo) ++state.noutliers; // don't count pseudos here
1179 info.useInFit = 0;
1180 continue;
1181 }
1182
1183 // if we get here could be as hit
1184 ++chamberStatistics.nhits;
1185 if (!pseudo) ++state.nhits; // pseudo's shouldn't count here
1186
1187 if (flipSign) ++state.numberOfFlippedMdts;
1188
1189 std::string idString = pseudo ? " Pseudomeasurement " : m_idHelperSvc->toString(id);
1190 std::string boundCheck = inBounds ? "inBounds" : "outBounds";
1191 ATH_MSG_VERBOSE(m_printer->print(*(info.resPull)) << " " << idString << " " << boundCheck);
1192 if (isNoise)
1193 ATH_MSG_VERBOSE(" noise");
1194 else if (isOutlier)
1195 ATH_MSG_VERBOSE(" outlier");
1196 if (isMDT) {
1197 ATH_MSG_VERBOSE(" r_drift " << std::setw(8) << rDrift << " r_trk " << std::setw(7) << rTrack << " dr " << std::setw(7)
1198 << Amg::error(meas->localCovariance(), Trk::locR));
1199 if (flipSign)
1200 ATH_MSG_VERBOSE(" flipped rDrift " << info.flippedMdt->localParameters()[Trk::locR] << " pull " << flippedPull);
1201 else if (isDelta)
1202 ATH_MSG_VERBOSE(" delta ");
1203 } else {
1204 const RpcClusterOnTrack* rpc = dynamic_cast<const RpcClusterOnTrack*>(meas);
1205 if (!rpc) {
1206 const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(meas);
1207 if (crot) { rpc = dynamic_cast<const RpcClusterOnTrack*>(crot->containedROTs().front()); }
1208 }
1209 if (rpc) ATH_MSG_DEBUG(" time " << rpc->prepRawData()->time() - rpc->globalPosition().mag() / 300.);
1210 }
1211
1212 if (pseudo) {
1213 // pseudo measurements should not be included in chamber hit removal so stop here
1214 if (!isNoise && isOutlier) { state.largePullPseudoMeasurements.insert(meas); }
1215 continue;
1216
1217 } else {
1218 // count hits
1219 EtaPhiHits& hits = state.hitsPerChamber[info.chId];
1220 if (measuresPhi)
1221 ++hits.nphi;
1222 else
1223 ++hits.neta;
1224
1225 // bound checks
1226 if (!inBounds) {
1227 EtaPhiHits& outHits = state.outBoundsPerChamber[info.chId];
1228 if (measuresPhi)
1229 ++outHits.nphi;
1230 else
1231 ++outHits.neta;
1232 }
1233
1234 // measurements with large pull
1235 if (!tsit->type(Trk::TrackStateOnSurface::Outlier) && isOutlier && !isMDT) { state.largePullMeasurements.insert(meas); }
1236
1237 // pulls per chamber
1238 if (!m_idHelperSvc->isTrigger(info.chId)) {
1239 ChamberPullInfo& pullInfoHits = measuresPhi ? state.pullSumPhi : state.pullSum;
1240 pullInfoHits.pullSum += pull;
1241 ++pullInfoHits.nhits;
1242 if (pull > pullInfoHits.maxPull) pullInfoHits.maxPull = pull;
1243
1244 ChamberPullInfo& pullInfoCh = measuresPhi ? state.pullSumPerChamberPhi[info.chId] : state.pullSumPerChamber[info.chId];
1245 pullInfoCh.pullSum += pull;
1246 ++pullInfoCh.nhits;
1247 if (pull > pullInfoCh.maxPull) pullInfoCh.maxPull = pull;
1248 } else {
1249 ChamberPullInfo& pullInfoTrig = measuresPhi ? state.pullSumPhi : state.pullSumTrigEta;
1250 if (!measuresPhi) state.pullSumPerChamberEta[info.chId];
1251 pullInfoTrig.pullSum += pull;
1252 ++pullInfoTrig.nhits;
1253 if (pull > pullInfoTrig.maxPull) pullInfoTrig.maxPull = pull;
1254 }
1255 }
1256 }
1257
1258 // if there was an MDT outlier add it to the list of hits to be removed
1259 if (mdtmeas) state.largePullMeasurements.insert(mdtmeas);
1260
1261 // check whether we have sufficient layers to savely clean the RPC/TGC comp rots
1262 unsigned int nphiLayers = rpcLayers.size() + tgcLayers.size();
1263 if (state.hasVertexConstraint) { nphiLayers += 1; }
1264 if (state.nIdHits > 0) { nphiLayers += 2; }
1265
1266 if ((nphiLayers > 2) && state.numberOfCleanedCompROTs > 0) {
1267 ATH_MSG_DEBUG(" Sufficient constraints to clean competing ROTs: trigger layers " << nphiLayers);
1268 } else {
1269 // reset counter so no cleaning is performed
1270 state.numberOfCleanedCompROTs = 0;
1271 }
1272
1273 // update sl fit configuration if track has ID hits or vertex constraint
1274 if (!m_use_slFit && state.slFit && (state.hasVertexConstraint || state.nIdHits > 0) && fieldCache.solenoidOn()) {
1275 state.slFit = false;
1276 }
1277
1278 if (state.hasVertexConstraint || state.nIdHits) {
1279 if (state.hasVertexConstraint) ATH_MSG_DEBUG(" Track has vertex contraint:");
1280 if (state.nIdHits > 0) ATH_MSG_DEBUG(" Track has ID Hits: " << state.nIdHits);
1281 if (fieldCache.solenoidOn())
1282 ATH_MSG_DEBUG(" Solenoid On");
1283 else
1284 ATH_MSG_DEBUG(" Solenoid Off");
1285 if (fieldCache.toroidOn())
1286 ATH_MSG_DEBUG(" Toroid On");
1287 else
1288 ATH_MSG_DEBUG(" Toroid Off");
1289 if (state.slFit)
1290 ATH_MSG_DEBUG(" Use SL fit");
1291 else
1292 ATH_MSG_DEBUG(" Use curved fit");
1293 }
1294
1295 std::set<Identifier> chambersToBeRemoved, chambersToBeRemovedPhi, goodEtaLayers, goodPhiLayers;
1296
1297 // check whether there are any chambers in eta that should be removed
1298 extractChambersToBeRemoved(state, chambersToBeRemoved);
1299
1300 // check whether there are any chambers in phi that should be removed
1301 extractChambersToBeRemoved(state, chambersToBeRemovedPhi, true);
1302
1303 ATH_MSG_DEBUG("Chambers on track summary:");
1304
1305 EtaPhiPerChamberIt chit = state.hitsPerChamber.begin();
1306 EtaPhiPerChamberIt chit_end = state.hitsPerChamber.end();
1307 for (; chit != chit_end; ++chit) {
1308 if (!chit->first.is_valid()) continue;
1309
1310 bool isPrec = m_idHelperSvc->isMdt(chit->first) || m_idHelperSvc->isCsc(chit->first) || m_idHelperSvc->isMM(chit->first) ||
1311 m_idHelperSvc->issTgc(chit->first);
1312 if (isPrec) {
1313 StIndex stIndex = m_idHelperSvc->stationIndex(chit->first);
1314 state.stations.insert(stIndex);
1315 }
1316
1317 EtaPhiHits& nhits = chit->second;
1318 EtaPhiHits& noutBounds = state.outBoundsPerChamber[chit->first];
1319 ATH_MSG_DEBUG(" chamber " << m_idHelperSvc->toStringChamber(chit->first) << " eta hits " << nhits.neta << " outBounds "
1320 << noutBounds.neta << " phi hits " << nhits.nphi << " outBounds " << noutBounds.nphi);
1321 if (nhits.neta != 0 && nhits.neta == noutBounds.neta) {
1322 ATH_MSG_DEBUG(" --> All eta hits out of bounds ");
1323 // remove eta hits for this chamber
1324 double fakePull = 1000. * nhits.neta;
1325 if (!chambersToBeRemoved.count(chit->first)) {
1326 // just add it
1327 state.chambersToBeRemoved.emplace_back(fakePull, chit->first);
1328 chambersToBeRemoved.insert(chit->first);
1329 } else {
1330 // replace existing entry if new one has larger Pull
1331 PullChIt pIt = state.chambersToBeRemoved.begin();
1332 PullChIt pIt_end = state.chambersToBeRemoved.end();
1333 for (; pIt != pIt_end; ++pIt) {
1334 if (pIt->second == chit->first && pIt->first < fakePull) {
1335 pIt->first = fakePull;
1336 break;
1337 }
1338 }
1339 }
1340 } else {
1341 if (noutBounds.neta != 0) ATH_MSG_DEBUG(" --> Some eta hits out of bounds ");
1342
1343 if (isPrec && nhits.neta > 0) {
1344 if (m_idHelperSvc->isSmallChamber(chit->first))
1345 state.hasSmall = true;
1346 else
1347 state.hasLarge = true;
1348 }
1349 }
1350 if (nhits.nphi != 0 && nhits.nphi == noutBounds.nphi) {
1351 ATH_MSG_DEBUG(" --> All phi hits out of bounds ");
1352 // remove phi hits for this chamber
1353 double fakePull = 1000. * nhits.nphi;
1354 if (!chambersToBeRemovedPhi.count(chit->first)) {
1355 // just add it
1356 state.chambersToBeRemovedPhi.emplace_back(fakePull, chit->first);
1357 chambersToBeRemovedPhi.insert(chit->first);
1358 } else {
1359 // replace existing entry if new one has larger pull
1360 PullChIt pIt = state.chambersToBeRemovedPhi.begin();
1361 PullChIt pIt_end = state.chambersToBeRemovedPhi.end();
1362 for (; pIt != pIt_end; ++pIt) {
1363 if (pIt->second == chit->first) {
1364 pIt->first = std::max(pIt->first, fakePull);
1365 break;
1366 }
1367 }
1368 }
1369 } else {
1370 if (noutBounds.nphi != 0) ATH_MSG_DEBUG(" --> Some phi hits out of bounds ");
1371 if (nhits.nphi > 0) {
1372 state.phiLayers.insert(m_idHelperSvc->phiIndex(chit->first));
1373 }
1374 }
1375 }
1376
1377 state.nPhiConstraints = state.phiLayers.size() + state.nPseudoMeasurements;
1378 if (state.hasLarge && state.hasSmall) ++state.nPhiConstraints;
1379 if (state.stations.size() == 1 && nphiLayers > 1) ++state.nPhiConstraints;
1380
1381 double pull_precisionhits = -1.;
1382 if (state.pullSum.nhits != 0) { pull_precisionhits = state.pullSum.pullSum / state.pullSum.nhits; }
1383 double pull_triggerhits = -1.;
1384 if (state.pullSumTrigEta.nhits != 0) { pull_triggerhits = state.pullSumTrigEta.pullSum / state.pullSumTrigEta.nhits; }
1385 double pull_phihits = -1.;
1386 if (state.pullSumPhi.nhits != 0) { pull_phihits = state.pullSumPhi.pullSum / state.pullSumPhi.nhits; }
1387 ATH_MSG_DEBUG(" pull sum: precision hits "
1388 << pull_precisionhits << " trigger eta " << pull_triggerhits << " phi " << pull_phihits << " measurements "
1389 << state.measInfo.size() << std::endl
1390 << " precision chambers " << state.pullSumPerChamber.size() << " hits with large pull "
1391 << state.largePullMeasurements.size() << " pseudos with large pull " << state.largePullPseudoMeasurements.size()
1392 << " chambers to be removed " << state.chambersToBeRemoved.size() << " phi " << state.chambersToBeRemovedPhi.size()
1393 << " phi lay " << state.phiLayers.size() << " phi constr " << state.nPhiConstraints);
1394
1395 if (state.pullSumPhi.nhits != 0) {
1396 double phiPull = state.pullSumPhi.pullSum / state.pullSumPhi.nhits;
1397 if (state.stations.size() == 1 && phiPull > 5.) { ATH_MSG_DEBUG(" Single station track with large phi pulls!! "); }
1398 } else
1399 ATH_MSG_DEBUG(" Track with no phi hits!! ");
1400 }
#define ATH_MSG_ERROR(x)
bool solenoidOn() const
status of the magnets
virtual const MuonGM::MdtReadoutElement * detectorElement() const override final
Returns the detector element, assoicated with the PRD of this class.
virtual const MdtPrepData * prepRawData() const override final
Returns the PrepRawData used to create this corrected measurement.
virtual const MuonCluster * prepRawData() const override=0
Returns the Trk::PrepRawData - is a MuonCluster in this scope.
double innerTubeRadius() const
Returns the inner tube radius excluding the aluminium walls.
ToolHandle< Trk::IExtrapolator > m_extrapolator
ServiceHandle< Muon::IMuonEDMHelperSvc > m_edmHelperSvc
bool extractChambersToBeRemoved(CleaningState &state, std::set< Identifier > &chambersToBeRemovedSet, bool usePhi=false) const
helper function to extract chambers that are to be removed
ToolHandle< IMuonCompetingClustersOnTrackCreator > m_compRotCreator
ToolHandle< Muon::IMdtDriftCircleOnTrackCreator > m_mdtRotCreator
ToolHandle< Trk::IResidualPullCalculator > m_pullCalculator
Gaudi::Property< double > m_associationScaleFactor
EtaPhiPerChamberMap::iterator EtaPhiPerChamberIt
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
bool isOutsideOnTrackCut(const Identifier &id, double res, double pull, double cutScaleFactor) const
check whether hit is an outlier
Gaudi::Property< double > m_adcCut
Gaudi::Property< bool > m_recoverOutliers
Gaudi::Property< bool > m_use_slFit
double deltaE() const
returns the
double thicknessInX0() const
returns the actually traversed material .
const EnergyLoss * energyLoss() const
returns the energy loss object.
const ScatteringAngles * scatteringAngles() const
returns the MCS-angles object.
const LocalParameters & localParameters() const
Interface method to get the LocalParameters.
virtual const Surface & associatedSurface() const =0
Interface method to get the associated Surface.
const Amg::MatrixX & localCovariance() const
Interface method to get the localError.
@ Biased
RP with track state including the hit.
@ Unbiased
RP with track state that has measurement not included.
double sigmaDeltaPhi() const
returns the
double deltaPhi() const
returns the
double sigmaDeltaTheta() const
returns the
double deltaTheta() const
returns the
virtual const SurfaceBounds & bounds() const override final
This method returns the bounds of the Surface by reference.
virtual bool insideLoc2(const Amg::Vector2D &locpo, double tol2=0.) const =0
Extend the interface to for single inside Loc 1 / Loc2 tests.
virtual bool globalToLocal(const Amg::Vector3D &glob, const Amg::Vector3D &mom, Amg::Vector2D &loc) const =0
Specified by each surface type: GlobalToLocal method without dynamic memory allocation - boolean chec...
virtual bool insideBounds(const Amg::Vector2D &locpos, double tol1=0., double tol2=0.) const =0
virtual methods to be overwritten by the inherited surfaces
@ Perigee
This represents a perigee, and so will contain a Perigee object only.
@ Scatterer
This represents a scattering point on the track, and so will contain TrackParameters and MaterialEffe...
double error(const Amg::MatrixX &mat, int index)
return diagonal error of the matrix caller should ensure the matrix is symmetric and the index is in ...
Eigen::Matrix< double, 2, 1 > Vector2D
ChIndex chIndex(const std::string &index)
convert ChIndex name string to enum
const std::string & stName(StIndex index)
convert StIndex into a string
@ layer
Definition HitInfo.h:79
@ anyDirection
DriftCircleSide
Enumerates the 'side' of the wire on which the tracks passed (i.e.
@ RIGHT
the drift radius is positive (see Trk::AtaStraightLine)
@ LEFT
the drift radius is negative (see Trk::AtaStraightLine)
DataVector< const Trk::TrackStateOnSurface > TrackStates
@ locX
Definition ParamDefs.h:37
@ locR
Definition ParamDefs.h:44
ParametersBase< TrackParametersDim, Charged > TrackParameters
#define CXXUTILS_TRAPPING_FP
Definition trapping_fp.h:24

◆ initialize()

StatusCode Muon::MuonTrackCleaner::initialize ( )
override

AlgTool initialize.

Definition at line 37 of file MuonTrackCleaner.cxx.

37 {
38 ATH_CHECK(m_trackFitter.retrieve());
39 ATH_CHECK(m_slTrackFitter.retrieve());
40 ATH_CHECK(m_idHelperSvc.retrieve());
41 ATH_CHECK(m_edmHelperSvc.retrieve());
42 ATH_CHECK(m_printer.retrieve());
43 ATH_CHECK(m_extrapolator.retrieve());
44 ATH_CHECK(m_pullCalculator.retrieve());
45 ATH_CHECK(m_mdtRotCreator.retrieve());
46 ATH_CHECK(m_compRotCreator.retrieve());
49
50 return StatusCode::SUCCESS;
51 }
#define ATH_CHECK
Evaluate an expression and check for errors.
ToolHandle< Trk::IUpdator > m_measurementUpdator

◆ isOutsideOnTrackCut()

bool Muon::MuonTrackCleaner::isOutsideOnTrackCut ( const Identifier & id,
double res,
double pull,
double cutScaleFactor ) const
private

check whether hit is an outlier

Definition at line 1473 of file MuonTrackCleaner.cxx.

1473 {
1474 bool isMdt = id.is_valid() ? m_idHelperSvc->isMdt(id) : false;
1475 bool measuresPhi = id.is_valid() ? m_idHelperSvc->measuresPhi(id) : false;
1476
1477 // look at pulls and identify outliers
1478 double pullCut = measuresPhi ? m_pullCutPhi : m_pullCut;
1479
1480 if (isMdt) {
1481 // if mdt residual cut is activated check whether the residual is small that 80% of the cut of
1482 if (m_useMdtResiCut) {
1483 return std::abs(res) > cutScaleFactor * m_mdtResiCut;
1484 } else {
1485 return std::abs(pull) > cutScaleFactor * pullCut;
1486 }
1487 } else {
1488 return std::abs(pull) > cutScaleFactor * pullCut;
1489 }
1490 }
Gaudi::Property< double > m_pullCutPhi
Gaudi::Property< double > m_mdtResiCut
Gaudi::Property< double > m_pullCut
Gaudi::Property< bool > m_useMdtResiCut

◆ outlierRecovery()

std::unique_ptr< Trk::Track > Muon::MuonTrackCleaner::outlierRecovery ( const EventContext & ctx,
std::unique_ptr< Trk::Track > track,
CleaningState & state,
const MuonStationIndex::ChIndex * currentIndex = nullptr ) const
private

recover outliers that are within the cuts.

If the additional chamber index is provided, the code will only consider that particular layer

Definition at line 656 of file MuonTrackCleaner.cxx.

658 {
659 const Trk::Perigee* perigee = track->perigeeParameters();
660 if (!perigee) {
661 ATH_MSG_DEBUG(" track without perigee ");
662 return nullptr;
663 }
664
665 ATH_MSG_VERBOSE(" outlierRecovery: ");
666 if (currentIndex) ATH_MSG_VERBOSE(" layer " << chName(*currentIndex));
667 ATH_MSG_VERBOSE(" printing chamber statistics ");
668
669 std::set<ChIndex> recoverableLayers;
670 for (auto [stationIndex, layer] : state.chamberLayerStatistics) {
671 if (stationIndex == ChIndex::ChUnknown) continue;
672 ATH_MSG_VERBOSE(print(layer));
673
674 // skip all chamber layers except the requested one
675 if (currentIndex && *currentIndex != stationIndex) continue;
676
677 ChamberLayerStatistics& statistics = layer;
678 unsigned int nhits = statistics.nhits;
679 unsigned int noutliers = statistics.noutliers;
680 // unsigned int ndeltas = statistics.ndeltas;
681 unsigned int nrecoverableOutliers = statistics.nrecoverableOutliers;
682 unsigned int noutBounds = statistics.noutBounds;
683
684 if (nrecoverableOutliers > 0) {
685 if (nhits + nrecoverableOutliers > 2 &&
686 ((noutBounds == 0 && noutliers == 0) || (nrecoverableOutliers != 0 && noutliers < 2))) {
687 recoverableLayers.insert(stationIndex);
688 ATH_MSG_DEBUG(" found recoverable layer " << chName(statistics.chIndex));
689 }
690 }
691 }
692
693 // if there is nothing to be done exit
694 if (recoverableLayers.empty() && !state.hasOfBoundsOutliers) return track;
695 bool addedHits = false;
696 unsigned int removedOutOfBoundsHits(0);
697
698 auto tsos = std::make_unique<Trk::TrackStates>();
699 tsos->reserve(state.measInfo.size());
700
701 // loop over hits
702 for (auto& hit : state.measInfo) {
703 if (!hit.useInFit) {
704 if (hit.inBounds) {
705 if (recoverableLayers.count(hit.chIndex)) {
706 // check whether we can savely add hits in this chamber to the track
707 bool recover = !isOutsideOnTrackCut(hit.id, hit.residual, hit.pull, m_associationScaleFactor);
708 if (recover && m_onlyUseHitErrorInRecovery && hit.pars) {
709 std::optional<const Trk::ResidualPull> resPull{
710 m_pullCalculator->residualPull(hit.meas, hit.pars, Trk::ResidualPull::HitOnly)};
711 if (!resPull) {
712 ATH_MSG_DEBUG(" calculation of residual/pull failed !!!!! ");
713 recover = false;
714 } else {
715 recover = !isOutsideOnTrackCut(hit.id, resPull->residual().front(), std::abs(resPull->pull().front()),
716
718 }
719 }
720 if (recover) {
721 ATH_MSG_DEBUG(" adding outlier " << m_idHelperSvc->toString(hit.id) << " pull " << std::setw(7) << hit.pull);
722 if (hit.flippedMdt) {
723 double rDrift = hit.meas->localParameters()[Trk::locR];
724 double rDriftFlip = hit.flippedMdt->localParameters()[Trk::locR];
725 double rTrack = hit.pars->parameters()[Trk::locR];
726 ATH_MSG_DEBUG(" flipped MDT: r_orig " << rDrift << " flip " << rDriftFlip << " rTrack " << rTrack);
727 }
728 addedHits = true;
729 const Trk::MeasurementBase* newMeas = hit.flippedMdt ? hit.flippedMdt.get() : hit.meas;
730
731 tsos->push_back(MuonTSOSHelper::cloneTSOSWithUpdate(*hit.originalState, *newMeas, *hit.pars,
733 } else {
734 tsos->push_back(hit.originalState->clone());
735 }
736 }
737 // layer not recoverable, drop the outliers: but if RPC, TGC, or CSC, expect track to go through all layers, so add a
738 // hole instead
739 if (m_idHelperSvc->isRpc(hit.id) || m_idHelperSvc->isTgc(hit.id) || m_idHelperSvc->isCsc(hit.id))
740 tsos->push_back(MuonTSOSHelper::createHoleTSOS(hit.pars->uniqueClone()));
741 } else {
742 ++removedOutOfBoundsHits;
743 // if RPC, TGC, or CSC, expect track to go through all layers: add a hole to replace lost outlier
744 if (m_idHelperSvc->isRpc(hit.id) || m_idHelperSvc->isTgc(hit.id) || m_idHelperSvc->isCsc(hit.id))
745 tsos->push_back(MuonTSOSHelper::createHoleTSOS(hit.pars->uniqueClone()));
746 ATH_MSG_DEBUG(" removing out of bounds outlier " << m_idHelperSvc->toString(hit.id) << " pull " << std::setw(7)
747 << hit.pull);
748 }
749 } else {
750 tsos->push_back(hit.originalState->clone());
751 }
752 }
753
754 if (!addedHits && removedOutOfBoundsHits == 0) {
755 ATH_MSG_DEBUG(" track unchanged ");
756 return track;
757 }
758
759 if (tsos->size() < 6) {
760 ATH_MSG_WARNING(" too few hits, cannot add hits. This should not happen ");
761 return nullptr;
762 }
763
764 // create new track
765 std::unique_ptr<Trk::Track> cleanedTrack =
766 std::make_unique<Trk::Track>(track->info(), std::move(tsos), track->fitQuality() ? track->fitQuality()->uniqueClone() : nullptr);
767
768 if (!addedHits) {
769 ATH_MSG_DEBUG(" only removed out of bound hits, returning track without new fit ");
770 return cleanedTrack;
771 }
772
773 // fit new track
774 printStates(cleanedTrack.get());
775
776 std::unique_ptr<Trk::Track> newTrack = fitTrack(ctx, *cleanedTrack, track->info().particleHypothesis(), state.slFit);
777
778 if (newTrack) {
779 ATH_MSG_DEBUG("Outlier recovery successfull ");
780 init(ctx, *newTrack, state);
781 } else {
782 ATH_MSG_DEBUG("refit after outlier recovery failed ");
783 }
784
785 return newTrack;
786 }
static std::unique_ptr< Trk::TrackStateOnSurface > createHoleTSOS(std::unique_ptr< Trk::TrackParameters > pars)
create a hole TSOS, takes ownership of the pointers
Gaudi::Property< bool > m_onlyUseHitErrorInRecovery
static std::string print(ChamberLayerStatistics &statistics)
@ HitOnly
RP with biased track state, but pull from hit only.
const std::string & chName(ChIndex index)
convert ChIndex into a string
recover(listarray, ref_val)
Definition Recovery.py:95

◆ print()

std::string Muon::MuonTrackCleaner::print ( MuonTrackCleaner::ChamberLayerStatistics & statistics)
staticprivate

Definition at line 1492 of file MuonTrackCleaner.cxx.

1492 {
1493 std::ostringstream sout;
1494
1495 unsigned int nhits = statistics.nhits;
1496 unsigned int noutliers = statistics.noutliers;
1497 unsigned int ndeltas = statistics.ndeltas;
1498 unsigned int nrecoverableOutliers = statistics.nrecoverableOutliers;
1499 unsigned int noutBounds = statistics.noutBounds;
1500
1501 sout << chName(statistics.chIndex) << " hits " << std::setw(6) << nhits << " outliers " << std::setw(6)
1502 << noutliers << " deltas " << std::setw(6) << ndeltas << " recoverableOutliers " << std::setw(6) << nrecoverableOutliers
1503 << " outBounds " << std::setw(6) << noutBounds;
1504
1505 return sout.str();
1506 }

◆ printStates()

void Muon::MuonTrackCleaner::printStates ( Trk::Track * track) const
private

Definition at line 1542 of file MuonTrackCleaner.cxx.

1542 {
1543 const Trk::TrackStates* states = track->trackStateOnSurfaces();
1544 int nStates = 0;
1545 if (states) nStates = states->size();
1546 ATH_MSG_DEBUG("Calling fit with hits: " << nStates<<std::endl<<m_printer->printMeasurements(*track));
1547 }

◆ recoverFlippedMdt()

std::unique_ptr< Trk::Track > Muon::MuonTrackCleaner::recoverFlippedMdt ( const EventContext & ctx,
std::unique_ptr< Trk::Track > track,
CleaningState & state ) const
private

flip signs of MDT hits with large pull if pull if the oppositely signed radius is small

Definition at line 235 of file MuonTrackCleaner.cxx.

236 {
237 if (!m_flipMdtDriftRadii || state.numberOfFlippedMdts == 0) return track;
238
239 const Trk::Perigee* perigee = track->perigeeParameters();
240 if (!perigee) {
241 ATH_MSG_DEBUG(" track without perigee ");
242 return nullptr;
243 }
244
245 ATH_MSG_DEBUG(" Trying to flip MDT signs: total number of hits with wrong sign " << state.numberOfFlippedMdts);
246
247 auto tsos = std::make_unique<Trk::TrackStates>();
248 tsos->reserve(state.measInfo.size());
249
250 unsigned int nmeas = 0;
251 // loop over hits
252 InfoIt hit = state.measInfo.begin();
253 InfoIt hit_end = state.measInfo.end();
254 for (; hit != hit_end; ++hit) {
255 // hits that are flagged as outlier or hits in the chamber to be removed are added as Outlier
256 if (!hit->useInFit) {
257 ATH_MSG_DEBUG(" removing hit " << m_idHelperSvc->toString(hit->id) << " pull " << hit->resPull->pull().front());
258 if (hit->inBounds)
259 tsos->push_back(MuonTSOSHelper::cloneTSOSWithUpdate(*hit->originalState, *hit->meas, *hit->pars,
261
262 continue;
263 } else {
264 if (hit->meas) ++nmeas;
265
266 if (hit->flippedMdt) {
267 tsos->push_back(MuonTSOSHelper::cloneTSOSWithUpdate(*hit->originalState, *hit->flippedMdt, *hit->pars,
269 ATH_MSG_DEBUG(" flipping sign hit " << m_idHelperSvc->toString(hit->id) << " pull " << hit->resPull->pull().front());
270 } else {
271 tsos->push_back(hit->originalState->clone());
272 }
273 }
274 }
275
276 if (nmeas < 6) {
277 ATH_MSG_DEBUG(" too few hits, cannot flip MDT hit sign ");
278 return nullptr;
279 }
280
281 // create new track
282 std::unique_ptr<Trk::Track> cleanedTrack =
283 std::make_unique<Trk::Track>(track->info(), std::move(tsos), track->fitQuality() ? track->fitQuality()->uniqueClone() : nullptr);
284 printStates(cleanedTrack.get());
285
286 // fit new track
287 std::unique_ptr<Trk::Track> newTrack = fitTrack(ctx, *cleanedTrack, track->info().particleHypothesis(), state.slFit);
288
289 if (newTrack) {
290 init(ctx, *newTrack, state);
291 return newTrack;
292 } else
293 return nullptr;
294 }
Gaudi::Property< bool > m_flipMdtDriftRadii

◆ removeChamber()

MuonTrackCleaner::ChamberRemovalOutput Muon::MuonTrackCleaner::removeChamber ( const EventContext & ctx,
const std::unique_ptr< Trk::Track > & track,
Identifier chId,
bool removePhi,
bool removeEta,
CleaningState & state ) const
private

remove chamber from track

Definition at line 579 of file MuonTrackCleaner.cxx.

581 {
582 ATH_MSG_DEBUG(" removing chamber " << m_idHelperSvc->toStringChamber(chId));
583
584 // store result
586 result.chId = chId;
587 const Trk::Perigee* perigee = track->perigeeParameters();
588 if (!perigee) {
589 ATH_MSG_DEBUG(" track without perigee ");
590 return result;
591 }
592
593 auto tsos = std::make_unique<Trk::TrackStates>();
594 tsos->reserve(state.measInfo.size());
595
596 unsigned int nmeas = 0;
597 // loop over hits
598 std::set<Identifier> stations{};
599 for (MCTBCleaningInfo& hit : state.measInfo) {
600 if (hit.id.is_valid()) {
601 bool measuresPhi = m_idHelperSvc->measuresPhi(hit.id);
602 bool remove = hit.chId == chId && ((removePhi && measuresPhi) || (removeEta && !measuresPhi));
603 // hits that are flagged as outlier or hits in the chamber to be removed are added as Outlier
604 if (!hit.useInFit || remove) {
605 ATH_MSG_DEBUG(" removing hit " << m_idHelperSvc->toString(hit.id) << " pull " << hit.resPull->pull().front());
606 // add as outlier
607 if (hit.inBounds)
608 tsos->push_back(MuonTSOSHelper::cloneTSOSWithUpdate(*hit.originalState, *hit.meas, *hit.pars,
610
611 // if removed, add hit to vector of hits
612 // but only if the hit was not already an outlier to be skipped!
613 if (remove && hit.useInFit) result.removedHits.push_back(&hit);
614 hit.useInFit = 0;
615 continue;
616 }
617 }
618 if (hit.meas) {
619 ++nmeas;
620 // Through how many detector layers went actually the track ?
621 if (m_idHelperSvc->isMdt(hit.id)) stations.insert(m_idHelperSvc->mdtIdHelper().multilayerID(hit.id));
622 // Keep it for the run 2 legacy
623 else if (m_idHelperSvc->isCsc(hit.id)) stations.insert(m_idHelperSvc->cscIdHelper().elementID(hit.id));
624 // Multilayer defines here whether the track went through the IP or HO wedge
625 else if (m_idHelperSvc->isMM(hit.id)) stations.insert(m_idHelperSvc->mmIdHelper().multilayerID(hit.id));
626 // Hits on track in the site before or after the Micromega wedges... yeah micromega sandwich
627 else if (m_idHelperSvc->issTgc(hit.id)) stations.insert(m_idHelperSvc->stgcIdHelper().multilayerID(hit.id));
628 }
629 tsos->push_back(hit.originalState->clone());
630 }
631
632 if (nmeas < 6 || stations.size() < 2) {
633 ATH_MSG_DEBUG(" too few hits, cannot perform chamberCleaning ");
634 return result;
635 }
636
637 // create new track
638 std::unique_ptr<Trk::Track> cleanedTrack =
639 std::make_unique<Trk::Track>(track->info(), std::move(tsos), track->fitQuality() ? track->fitQuality()->uniqueClone() : nullptr);
640
641 // fit new track
642 printStates(cleanedTrack.get());
643
644 if (!cleanedTrack->perigeeParameters()) { ATH_MSG_DEBUG(" track without perigee "); }
645
646 std::unique_ptr<Trk::Track> newTrack = fitTrack(ctx, *cleanedTrack, track->info().particleHypothesis(), state.slFit);
647
648 if (newTrack && !newTrack->perigeeParameters()) {
649 ATH_MSG_DEBUG(" fitted track without perigee " << *newTrack << " " << newTrack->perigeeParameters());
650 }
651
652 result.track = std::move(newTrack);
653 return result;
654 }

◆ unremoveHits()

void Muon::MuonTrackCleaner::unremoveHits ( ChamberRemovalOutput & result)
staticprivate

Definition at line 1537 of file MuonTrackCleaner.cxx.

1537 {
1538 // loop over removed hits and 'unremove' them so they are used in the next iteration
1539 for (auto* hit : result.removedHits) hit->useInFit = 1;
1540 }

Member Data Documentation

◆ m_adcCut

Gaudi::Property<double> Muon::MuonTrackCleaner::m_adcCut {this, "AdcCut", 50.}
private

Definition at line 313 of file MuonTrackCleaner.h.

313{this, "AdcCut", 50.};

◆ m_associationScaleFactor

Gaudi::Property<double> Muon::MuonTrackCleaner::m_associationScaleFactor {this, "AssociationScaleFactor", 0.7}
private

Definition at line 306 of file MuonTrackCleaner.h.

306{this, "AssociationScaleFactor", 0.7};

◆ m_avePullSumPerChamberCut

Gaudi::Property<double> Muon::MuonTrackCleaner::m_avePullSumPerChamberCut {this, "MaxAvePullSumPerChamber", 3.5}
private

Definition at line 308 of file MuonTrackCleaner.h.

308{this, "MaxAvePullSumPerChamber", 3.5};

◆ m_chi2Cut

Gaudi::Property<double> Muon::MuonTrackCleaner::m_chi2Cut {this, "Chi2Cut", 100.}
private

Definition at line 302 of file MuonTrackCleaner.h.

302{this, "Chi2Cut", 100.};

◆ m_cleanCompROTs

Gaudi::Property<bool> Muon::MuonTrackCleaner::m_cleanCompROTs {this, "CleanCompROTs", true}
private

Definition at line 311 of file MuonTrackCleaner.h.

311{this, "CleanCompROTs", true};

◆ m_compRotCreator

ToolHandle<IMuonCompetingClustersOnTrackCreator> Muon::MuonTrackCleaner::m_compRotCreator
private
Initial value:
{
this, "CompRotCreator", "Muon::TriggerChamberClusterOnTrackCreator/TriggerChamberClusterOnTrackCreator"}

Definition at line 288 of file MuonTrackCleaner.h.

288 {
289 this, "CompRotCreator", "Muon::TriggerChamberClusterOnTrackCreator/TriggerChamberClusterOnTrackCreator"};

◆ m_edmHelperSvc

ServiceHandle<Muon::IMuonEDMHelperSvc> Muon::MuonTrackCleaner::m_edmHelperSvc
private
Initial value:
{this, "edmHelper", "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc",
"Handle to the service providing the IMuonEDMHelperSvc interface"}

Definition at line 292 of file MuonTrackCleaner.h.

292 {this, "edmHelper", "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc",
293 "Handle to the service providing the IMuonEDMHelperSvc interface"};

◆ m_extrapolator

ToolHandle<Trk::IExtrapolator> Muon::MuonTrackCleaner::m_extrapolator {this, "Extrapolator", "Trk::Extrapolator/AtlasExtrapolator"}
private

Definition at line 296 of file MuonTrackCleaner.h.

296{this, "Extrapolator", "Trk::Extrapolator/AtlasExtrapolator"};

◆ m_fieldCacheCondObjInputKey

SG::ReadCondHandleKey<AtlasFieldCacheCondObj> Muon::MuonTrackCleaner::m_fieldCacheCondObjInputKey
private
Initial value:
{this, "AtlasFieldCacheCondObj", "fieldCondObj",
"Name of the Magnetic Field conditions object key"}

Definition at line 298 of file MuonTrackCleaner.h.

298 {this, "AtlasFieldCacheCondObj", "fieldCondObj",
299 "Name of the Magnetic Field conditions object key"};

◆ m_flipMdtDriftRadii

Gaudi::Property<bool> Muon::MuonTrackCleaner::m_flipMdtDriftRadii {this, "FlipMdtDriftRadii", true}
private

Definition at line 310 of file MuonTrackCleaner.h.

310{this, "FlipMdtDriftRadii", true};

◆ m_idHelperSvc

ServiceHandle<Muon::IMuonIdHelperSvc> Muon::MuonTrackCleaner::m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}
private

Definition at line 295 of file MuonTrackCleaner.h.

295{this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"};

◆ m_iterate

Gaudi::Property<bool> Muon::MuonTrackCleaner::m_iterate {this, "Iterate", 0.7}
private

Definition at line 314 of file MuonTrackCleaner.h.

314{this, "Iterate", 0.7};

◆ m_mdtResiCut

Gaudi::Property<double> Muon::MuonTrackCleaner::m_mdtResiCut {this, "MdtResiCut", 1.}
private

Definition at line 304 of file MuonTrackCleaner.h.

304{this, "MdtResiCut", 1.};

◆ m_mdtRotCreator

ToolHandle<Muon::IMdtDriftCircleOnTrackCreator> Muon::MuonTrackCleaner::m_mdtRotCreator
private
Initial value:
{this, "MdtRotCreator",
"Muon::MdtDriftCircleOnTrackCreator/MdtDriftCircleOnTrackCreator"}

Definition at line 286 of file MuonTrackCleaner.h.

286 {this, "MdtRotCreator",
287 "Muon::MdtDriftCircleOnTrackCreator/MdtDriftCircleOnTrackCreator"};

◆ m_measurementUpdator

ToolHandle<Trk::IUpdator> Muon::MuonTrackCleaner::m_measurementUpdator {this, "MeasurementUpdator", "Trk::KalmanUpdator/MuonMeasUpdator"}
private

Definition at line 285 of file MuonTrackCleaner.h.

285{this, "MeasurementUpdator", "Trk::KalmanUpdator/MuonMeasUpdator"};

◆ m_ncycles

Gaudi::Property<unsigned int> Muon::MuonTrackCleaner::m_ncycles {this, "CleaningCycles", 5}
private

Definition at line 307 of file MuonTrackCleaner.h.

307{this, "CleaningCycles", 5};

◆ m_onlyUseHitErrorInRecovery

Gaudi::Property<bool> Muon::MuonTrackCleaner::m_onlyUseHitErrorInRecovery {this, "OnlyUseHitErrorInRecovery", true}
private

Definition at line 312 of file MuonTrackCleaner.h.

312{this, "OnlyUseHitErrorInRecovery", true};

◆ m_printer

PublicToolHandle<Muon::MuonEDMPrinterTool> Muon::MuonTrackCleaner::m_printer {this, "Printer", "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool"}
private

Definition at line 294 of file MuonTrackCleaner.h.

294{this, "Printer", "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool"};

◆ m_pullCalculator

ToolHandle<Trk::IResidualPullCalculator> Muon::MuonTrackCleaner::m_pullCalculator
private
Initial value:
{this, "PullCalculator",
"Trk::ResidualPullCalculator/ResidualPullCalculator"}

Definition at line 290 of file MuonTrackCleaner.h.

290 {this, "PullCalculator",
291 "Trk::ResidualPullCalculator/ResidualPullCalculator"};

◆ m_pullCut

Gaudi::Property<double> Muon::MuonTrackCleaner::m_pullCut {this, "PullCut", 5.}
private

Definition at line 303 of file MuonTrackCleaner.h.

303{this, "PullCut", 5.};

◆ m_pullCutPhi

Gaudi::Property<double> Muon::MuonTrackCleaner::m_pullCutPhi {this, "PullCutPhi", 10.}
private

Definition at line 305 of file MuonTrackCleaner.h.

305{this, "PullCutPhi", 10.};

◆ m_recoverOutliers

Gaudi::Property<bool> Muon::MuonTrackCleaner::m_recoverOutliers {this, "RecoverOutliers", true}
private

Definition at line 309 of file MuonTrackCleaner.h.

309{this, "RecoverOutliers", true};

◆ m_slTrackFitter

ToolHandle<Trk::ITrackFitter> Muon::MuonTrackCleaner::m_slTrackFitter {this, "SLFitter", "Trk::GlobalChi2Fitter/MCTBSLFitterMaterialFromTrack"}
private

Definition at line 284 of file MuonTrackCleaner.h.

284{this, "SLFitter", "Trk::GlobalChi2Fitter/MCTBSLFitterMaterialFromTrack"};

◆ m_trackFitter

ToolHandle<Trk::ITrackFitter> Muon::MuonTrackCleaner::m_trackFitter
private
Initial value:
{
this,
"Fitter",
"Trk::GlobalChi2Fitter/MCTBFitterMaterialFromTrack",
}

Definition at line 279 of file MuonTrackCleaner.h.

279 {
280 this,
281 "Fitter",
282 "Trk::GlobalChi2Fitter/MCTBFitterMaterialFromTrack",
283 };

◆ m_use_slFit

Gaudi::Property<bool> Muon::MuonTrackCleaner::m_use_slFit {this, "UseSLFit", false}
private

Definition at line 315 of file MuonTrackCleaner.h.

315{this, "UseSLFit", false};

◆ m_useMdtResiCut

Gaudi::Property<bool> Muon::MuonTrackCleaner::m_useMdtResiCut {this, "UseMdtResiCut", false}
private

Definition at line 301 of file MuonTrackCleaner.h.

301{this, "UseMdtResiCut", false};

The documentation for this class was generated from the following files: