ATLAS Offline Software
Classes | Public Types | Public Member Functions | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
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 More...
 
StatusCode initialize () override
 AlgTool initialize. More...
 
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. More...
 
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. More...
 

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 More...
 
std::unique_ptr< Trk::TrackcleanTrack (const EventContext &ctx, const Trk::Track *track, CleaningState &state) const
 clean a track, actual implementation More...
 
double calcPull (const double residual, const double locMesCov, const double locTrkCov, const bool &trkStateIsUnbiased) const
 calculate the pull given measurement error and track error More...
 
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 More...
 
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 More...
 
std::unique_ptr< Trk::TrackhitCleaning (const EventContext &ctx, std::unique_ptr< Trk::Track > track, CleaningState &state) const
 remove bad hits from track. More...
 
std::unique_ptr< Trk::TrackchamberCleaning (const EventContext &ctx, std::unique_ptr< Trk::Track > track, CleaningState &state) const
 remove bad chamber from track. More...
 
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. More...
 
bool isOutsideOnTrackCut (const Identifier &id, double res, double pull, double cutScaleFactor) const
 check whether hit is an outlier More...
 
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 More...
 
void init (const EventContext &ctx, const Trk::Track &track, CleaningState &state) const
 init cleaner More...
 
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 More...
 

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

Definition at line 128 of file MuonTrackCleaner.h.

◆ 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

Definition at line 119 of file MuonTrackCleaner.h.

◆ 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  }

◆ 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  }

◆ 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  }

◆ 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  }

◆ 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  }

◆ 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  }

◆ 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  }

◆ 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  }

◆ 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
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);
1002  Trk::DriftCircleSide side = rDrift < 0. ? Trk::RIGHT : Trk::LEFT;
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(),
1136  Trk::anyDirection, false, Trk::muon);
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  }

◆ 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());
47  ATH_CHECK(m_measurementUpdator.retrieve());
49 
50  return StatusCode::SUCCESS;
51  }

◆ 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  }

◆ 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;
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  }

◆ 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  }

◆ 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
585  ChamberRemovalOutput 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.

◆ m_associationScaleFactor

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

Definition at line 306 of file MuonTrackCleaner.h.

◆ m_avePullSumPerChamberCut

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

Definition at line 308 of file MuonTrackCleaner.h.

◆ m_chi2Cut

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

Definition at line 302 of file MuonTrackCleaner.h.

◆ m_cleanCompROTs

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

Definition at line 311 of file MuonTrackCleaner.h.

◆ m_compRotCreator

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

Definition at line 288 of file MuonTrackCleaner.h.

◆ 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.

◆ m_extrapolator

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

Definition at line 296 of file MuonTrackCleaner.h.

◆ 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.

◆ m_flipMdtDriftRadii

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

Definition at line 310 of file MuonTrackCleaner.h.

◆ m_idHelperSvc

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

Definition at line 295 of file MuonTrackCleaner.h.

◆ m_iterate

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

Definition at line 314 of file MuonTrackCleaner.h.

◆ m_mdtResiCut

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

Definition at line 304 of file MuonTrackCleaner.h.

◆ 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.

◆ m_measurementUpdator

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

Definition at line 285 of file MuonTrackCleaner.h.

◆ m_ncycles

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

Definition at line 307 of file MuonTrackCleaner.h.

◆ m_onlyUseHitErrorInRecovery

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

Definition at line 312 of file MuonTrackCleaner.h.

◆ m_printer

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

Definition at line 294 of file MuonTrackCleaner.h.

◆ 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.

◆ m_pullCut

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

Definition at line 303 of file MuonTrackCleaner.h.

◆ m_pullCutPhi

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

Definition at line 305 of file MuonTrackCleaner.h.

◆ m_recoverOutliers

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

Definition at line 309 of file MuonTrackCleaner.h.

◆ m_slTrackFitter

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

Definition at line 284 of file MuonTrackCleaner.h.

◆ 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.

◆ m_use_slFit

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

Definition at line 315 of file MuonTrackCleaner.h.

◆ m_useMdtResiCut

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

Definition at line 301 of file MuonTrackCleaner.h.


The documentation for this class was generated from the following files:
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
Trk::ScatteringAngles::deltaPhi
double deltaPhi() const
returns the
Definition: ScatteringAngles.h:82
Trk::anyDirection
@ anyDirection
Definition: PropDirection.h:22
make_hlt_rep.pars
pars
Definition: make_hlt_rep.py:90
IDTPM::ndof
float ndof(const U &p)
Definition: TrackParametersHelper.h:134
CXXUTILS_TRAPPING_FP
#define CXXUTILS_TRAPPING_FP
Definition: trapping_fp.h:24
Muon::MuonTrackCleaner::m_measurementUpdator
ToolHandle< Trk::IUpdator > m_measurementUpdator
Definition: MuonTrackCleaner.h:285
Trk::TrackStateOnSurface::Perigee
@ Perigee
This represents a perigee, and so will contain a Perigee object only.
Definition: TrackStateOnSurface.h:117
Muon::MuonTrackCleaner::isOutsideOnTrackCut
bool isOutsideOnTrackCut(const Identifier &id, double res, double pull, double cutScaleFactor) const
check whether hit is an outlier
Definition: MuonTrackCleaner.cxx:1473
Trk::StraightLineSurface::bounds
virtual const SurfaceBounds & bounds() const override final
This method returns the bounds of the Surface by reference.
TRTCalib_Extractor.hits
hits
Definition: TRTCalib_Extractor.py:35
get_generator_info.result
result
Definition: get_generator_info.py:21
Muon::MuonTrackCleaner::m_ncycles
Gaudi::Property< unsigned int > m_ncycles
Definition: MuonTrackCleaner.h:307
Muon::MuonTrackCleaner::m_pullCutPhi
Gaudi::Property< double > m_pullCutPhi
Definition: MuonTrackCleaner.h:305
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
Trk::locX
@ locX
Definition: ParamDefs.h:37
Muon::MuonTrackCleaner::m_pullCut
Gaudi::Property< double > m_pullCut
Definition: MuonTrackCleaner.h:303
ClusterSeg::residual
@ residual
Definition: ClusterNtuple.h:20
Amg::Vector2D
Eigen::Matrix< double, 2, 1 > Vector2D
Definition: GeoPrimitives.h:48
index
Definition: index.py:1
TRT_PAI_gasdata::EO
const float EO[NO]
Energy levels for Oxygen.
Definition: TRT_PAI_gasdata.h:301
Muon::MuonStationIndex::StIndex::EM
@ EM
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
Muon::MuonTrackCleaner::removeChamber
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
Definition: MuonTrackCleaner.cxx:579
Trk::ParametersT
Dummy class used to allow special convertors to be called for surfaces owned by a detector element.
Definition: EMErrorDetail.h:25
Muon::MuonTSOSHelper::createHoleTSOS
static std::unique_ptr< Trk::TrackStateOnSurface > createHoleTSOS(std::unique_ptr< Trk::TrackParameters > pars)
create a hole TSOS, takes ownership of the pointers
Definition: MuonTSOSHelper.h:92
Muon::MuonTrackCleaner::m_useMdtResiCut
Gaudi::Property< bool > m_useMdtResiCut
Definition: MuonTrackCleaner.h:301
Muon::MuonStationIndex::stName
const std::string & stName(StIndex index)
convert StIndex into a string
Definition: MuonStationIndex.cxx:104
Muon::MuonTrackCleaner::m_mdtRotCreator
ToolHandle< Muon::IMdtDriftCircleOnTrackCreator > m_mdtRotCreator
Definition: MuonTrackCleaner.h:286
Trk::ResidualPull::Unbiased
@ Unbiased
RP with track state that has measurement not included.
Definition: ResidualPull.h:57
Muon::MuonTrackCleaner::checkPhiConstraint
bool checkPhiConstraint(CleaningState &state) const
Definition: MuonTrackCleaner.cxx:1529
Muon::MuonTrackCleaner::m_cleanCompROTs
Gaudi::Property< bool > m_cleanCompROTs
Definition: MuonTrackCleaner.h:311
Muon::MuonTrackCleaner::m_edmHelperSvc
ServiceHandle< Muon::IMuonEDMHelperSvc > m_edmHelperSvc
Definition: MuonTrackCleaner.h:292
Muon::MuonTrackCleaner::PullChIt
PullChVec::iterator PullChIt
Definition: MuonTrackCleaner.h:132
Muon::MuonTrackCleaner::checkStations
bool checkStations(CleaningState &state) const
Definition: MuonTrackCleaner.cxx:1508
Trk::ScatteringAngles
represents a deflection of the track caused through multiple scattering in material.
Definition: ScatteringAngles.h:26
Trk::MaterialEffectsBase::thicknessInX0
double thicknessInX0() const
returns the actually traversed material .
Trk::locR
@ locR
Definition: ParamDefs.h:44
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
SG::VarHandleKey::key
const std::string & key() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:141
Trk::MaterialEffectsBase
base class to integrate material effects on Trk::Track in a flexible way.
Definition: MaterialEffectsBase.h:35
Muon::MuonTrackCleaner::InfoIt
InfoVec::iterator InfoIt
Definition: MuonTrackCleaner.h:94
MagField::AtlasFieldCache::toroidOn
bool toroidOn() const
Muon::MuonTrackCleaner::m_avePullSumPerChamberCut
Gaudi::Property< double > m_avePullSumPerChamberCut
Definition: MuonTrackCleaner.h:308
Muon::MuonTrackCleaner::cleanTrack
std::unique_ptr< Trk::Track > cleanTrack(const EventContext &ctx, const Trk::Track *track, CleaningState &state) const
clean a track, actual implementation
Definition: MuonTrackCleaner.cxx:71
Muon::MuonTrackCleaner::m_slTrackFitter
ToolHandle< Trk::ITrackFitter > m_slTrackFitter
Definition: MuonTrackCleaner.h:284
std::stable_sort
void stable_sort(std::reverse_iterator< DataModel_detail::iterator< DVL > > beg, std::reverse_iterator< DataModel_detail::iterator< DVL > > end, Compare comp)
Specialization of stable_sort for DataVector/List.
Definition: DVL_algorithms.h:711
Muon::MuonTrackCleaner::m_flipMdtDriftRadii
Gaudi::Property< bool > m_flipMdtDriftRadii
Definition: MuonTrackCleaner.h:310
Muon::MuonTrackCleaner::PullChVec
std::vector< std::pair< double, Identifier > > PullChVec
Definition: MuonTrackCleaner.h:131
Muon::MuonTrackCleaner::hitCleaning
std::unique_ptr< Trk::Track > hitCleaning(const EventContext &ctx, std::unique_ptr< Trk::Track > track, CleaningState &state) const
remove bad hits from track.
Definition: MuonTrackCleaner.cxx:296
Muon::MuonTrackCleaner::m_extrapolator
ToolHandle< Trk::IExtrapolator > m_extrapolator
Definition: MuonTrackCleaner.h:296
Trk::TrackStateOnSurface::Outlier
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
Definition: TrackStateOnSurface.h:122
TRT::Hit::side
@ side
Definition: HitInfo.h:83
Trk::PseudoMeasurementOnTrack
Class to handle pseudo-measurements in fitters and on track objects.
Definition: PseudoMeasurementOnTrack.h:44
Muon::MuonTrackCleaner::unremoveHits
static void unremoveHits(ChamberRemovalOutput &result)
Definition: MuonTrackCleaner.cxx:1537
Muon::MuonTrackCleaner::init
void init(const EventContext &ctx, const Trk::Track &track, CleaningState &state) const
init cleaner
Definition: MuonTrackCleaner.cxx:788
PixelModuleFeMask_create_db.remove
string remove
Definition: PixelModuleFeMask_create_db.py:83
Muon::MuonStationIndex::toStationIndex
StIndex toStationIndex(ChIndex index)
convert ChIndex into StIndex
Trk::MaterialEffectsOnTrack
represents the full description of deflection and e-loss of a track in material.
Definition: MaterialEffectsOnTrack.h:40
Trk::ScatteringAngles::sigmaDeltaTheta
double sigmaDeltaTheta() const
returns the
Definition: ScatteringAngles.h:100
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
Muon::MuonTrackCleaner::PullChamberMap
std::map< Identifier, ChamberPullInfo > PullChamberMap
Definition: MuonTrackCleaner.h:119
Muon::MuonTrackCleaner::m_printer
PublicToolHandle< Muon::MuonEDMPrinterTool > m_printer
Definition: MuonTrackCleaner.h:294
lumiFormat.i
int i
Definition: lumiFormat.py:85
Muon::MuonStationIndex::chIndex
ChIndex chIndex(const std::string &index)
convert ChIndex name string to enum
Definition: MuonStationIndex.cxx:11
beamspotman.n
n
Definition: beamspotman.py:729
Muon::MuonTrackCleaner::m_trackFitter
ToolHandle< Trk::ITrackFitter > m_trackFitter
Definition: MuonTrackCleaner.h:279
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
Muon::MuonStationIndex::chName
const std::string & chName(ChIndex index)
convert ChIndex into a string
Definition: MuonStationIndex.cxx:119
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
urldecode::states
states
Definition: urldecode.h:39
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
Trk::RIGHT
@ RIGHT
the drift radius is positive (see Trk::AtaStraightLine)
Definition: DriftCircleSide.h:22
res
std::pair< std::vector< unsigned int >, bool > res
Definition: JetGroupProductTest.cxx:11
Muon::MuonTrackCleaner::m_use_slFit
Gaudi::Property< bool > m_use_slFit
Definition: MuonTrackCleaner.h:315
Muon::MuonTrackCleaner::printStates
void printStates(Trk::Track *track) const
Definition: MuonTrackCleaner.cxx:1542
Trk::EnergyLoss::deltaE
double deltaE() const
returns the
Muon::MuonTrackCleaner::m_adcCut
Gaudi::Property< double > m_adcCut
Definition: MuonTrackCleaner.h:313
python.StandardJetMods.pull
pull
Definition: StandardJetMods.py:305
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Trk::ParametersBase
Definition: ParametersBase.h:55
Muon::MuonTrackCleaner::m_recoverOutliers
Gaudi::Property< bool > m_recoverOutliers
Definition: MuonTrackCleaner.h:309
Trk::muon
@ muon
Definition: ParticleHypothesis.h:31
Muon::MuonTSOSHelper::cloneTSOSWithUpdate
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
Definition: MuonTSOSHelper.h:34
Trk::ResidualPull::HitOnly
@ HitOnly
RP with biased track state, but pull from hit only.
Definition: ResidualPull.h:56
DataVector< const Trk::TrackStateOnSurface >
Muon::MuonTrackCleaner::outlierRecovery
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.
Definition: MuonTrackCleaner.cxx:656
Trk::SurfaceBounds::insideLoc2
virtual bool insideLoc2(const Amg::Vector2D &locpo, double tol2=0.) const =0
Extend the interface to for single inside Loc 1 / Loc2 tests.
MagField::AtlasFieldCache::solenoidOn
bool solenoidOn() const
status of the magnets
Muon::MuonTrackCleaner::m_pullCalculator
ToolHandle< Trk::IResidualPullCalculator > m_pullCalculator
Definition: MuonTrackCleaner.h:290
Trk::distPhi
@ distPhi
Definition: ParamDefs.h:50
Trk::MeasurementBase::localCovariance
const Amg::MatrixX & localCovariance() const
Interface method to get the localError.
Definition: MeasurementBase.h:138
Muon::MuonStationIndex::StIndex::BO
@ BO
Trk::MeasurementBase
Definition: MeasurementBase.h:58
Muon::MuonTrackCleaner::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: MuonTrackCleaner.h:295
Trk::Track::perigeeParameters
const Perigee * perigeeParameters() const
return Perigee.
Definition: Tracking/TrkEvent/TrkTrack/src/Track.cxx:163
Trk::TrackStateOnSurface
represents the track state (measurement, material, fit parameters and quality) at a surface.
Definition: TrackStateOnSurface.h:71
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:239
Trk::MeasurementBase::associatedSurface
virtual const Surface & associatedSurface() const =0
Interface method to get the associated Surface.
Amg::error
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 ...
Definition: EventPrimitivesHelpers.h:40
Trk::EnergyLoss
This class describes energy loss material effects in the ATLAS tracking EDM.
Definition: EnergyLoss.h:34
Muon::MuonTrackCleaner::PullChamberCit
PullChamberMap::const_iterator PullChamberCit
Definition: MuonTrackCleaner.h:121
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
Muon::MuonTrackCleaner::EtaPhiPerChamberIt
EtaPhiPerChamberMap::iterator EtaPhiPerChamberIt
Definition: MuonTrackCleaner.h:129
Trk::Surface::insideBounds
virtual bool insideBounds(const Amg::Vector2D &locpos, double tol1=0., double tol2=0.) const =0
virtual methods to be overwritten by the inherited surfaces
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:16
Trk::MeasurementBase::localParameters
const LocalParameters & localParameters() const
Interface method to get the LocalParameters.
Definition: MeasurementBase.h:132
Trk::DriftCircleSide
DriftCircleSide
Enumerates the 'side' of the wire on which the tracks passed (i.e.
Definition: DriftCircleSide.h:16
Muon::MuonTrackCleaner::m_fieldCacheCondObjInputKey
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
Definition: MuonTrackCleaner.h:298
Muon::MuonTrackCleaner::extractChambersToBeRemoved
bool extractChambersToBeRemoved(CleaningState &state, std::set< Identifier > &chambersToBeRemovedSet, bool usePhi=false) const
helper function to extract chambers that are to be removed
Definition: MuonTrackCleaner.cxx:1402
Trk::ResidualPull::Biased
@ Biased
RP with track state including the hit.
Definition: ResidualPull.h:55
Trk::MaterialEffectsOnTrack::energyLoss
const EnergyLoss * energyLoss() const
returns the energy loss object.
Muon::MuonTrackCleaner::checkInnerConstraint
bool checkInnerConstraint(CleaningState &state) const
Definition: MuonTrackCleaner.cxx:1519
Muon::MuonTrackCleaner::fitTrack
std::unique_ptr< Trk::Track > fitTrack(const EventContext &ctx, Trk::Track &track, Trk::ParticleHypothesis pHyp, bool slFit) const
Definition: MuonTrackCleaner.cxx:1549
Trk::Surface::globalToLocal
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...
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Muon::MuonTrackCleaner::m_onlyUseHitErrorInRecovery
Gaudi::Property< bool > m_onlyUseHitErrorInRecovery
Definition: MuonTrackCleaner.h:312
DEBUG
#define DEBUG
Definition: page_access.h:11
Trk::MaterialEffectsOnTrack::scatteringAngles
const ScatteringAngles * scatteringAngles() const
returns the MCS-angles object.
MagField::AtlasFieldCache
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h)
Definition: AtlasFieldCache.h:43
Muon::StIndex
MuonStationIndex::StIndex StIndex
Definition: MuonSegmentMatchingTool.cxx:14
Muon::MuonTrackCleaner::m_iterate
Gaudi::Property< bool > m_iterate
Definition: MuonTrackCleaner.h:314
Muon::MuonTrackCleaner::cleanCompROTs
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
Definition: MuonTrackCleaner.cxx:174
Trk::ScatteringAngles::sigmaDeltaPhi
double sigmaDeltaPhi() const
returns the
Definition: ScatteringAngles.h:94
Trk::TrackStateOnSurface::Scatterer
@ Scatterer
This represents a scattering point on the track, and so will contain TrackParameters and MaterialEffe...
Definition: TrackStateOnSurface.h:113
Trk::LEFT
@ LEFT
the drift radius is negative (see Trk::AtaStraightLine)
Definition: DriftCircleSide.h:20
Muon::MuonStationIndex::ChIndex
ChIndex
enum to classify the different chamber layers in the muon spectrometer
Definition: MuonStationIndex.h:15
xAOD::track
@ track
Definition: TrackingPrimitives.h:513
Trk::ScatteringAngles::deltaTheta
double deltaTheta() const
returns the
Definition: ScatteringAngles.h:88
Muon::MuonTrackCleaner::m_associationScaleFactor
Gaudi::Property< double > m_associationScaleFactor
Definition: MuonTrackCleaner.h:306
Muon::MuonStationIndex::StIndex::BM
@ BM
Muon::MuonTrackCleaner::m_mdtResiCut
Gaudi::Property< double > m_mdtResiCut
Definition: MuonTrackCleaner.h:304
error
Definition: IImpactPoint3dEstimator.h:70
python.ParticleTypeUtil.info
def info
Definition: ParticleTypeUtil.py:87
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
Muon::MuonTrackCleaner::print
static std::string print(ChamberLayerStatistics &statistics)
Definition: MuonTrackCleaner.cxx:1492
Muon::MuonTrackCleaner::m_compRotCreator
ToolHandle< IMuonCompetingClustersOnTrackCreator > m_compRotCreator
Definition: MuonTrackCleaner.h:288
Trk::TrackStateOnSurface::Measurement
@ Measurement
This is a measurement, and will at least contain a Trk::MeasurementBase.
Definition: TrackStateOnSurface.h:101
Muon::MuonTrackCleaner::recoverFlippedMdt
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
Definition: MuonTrackCleaner.cxx:235
Trk::StraightLineSurface
Definition: StraightLineSurface.h:51
Muon::MuonStationIndex::isSmall
bool isSmall(const ChIndex index)
Returns true if the chamber index is in a small sector.
Recovery.recover
def recover(listarray, ref_val)
Definition: Recovery.py:95
Muon::MuonTrackCleaner::chamberCleaning
std::unique_ptr< Trk::Track > chamberCleaning(const EventContext &ctx, std::unique_ptr< Trk::Track > track, CleaningState &state) const
remove bad chamber from track.
Definition: MuonTrackCleaner.cxx:462
Identifier
Definition: IdentifierFieldParser.cxx:14