ATLAS Offline Software
MuonTrackCleaner.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 #include "MuonTrackCleaner.h"
5 
6 #include <iostream>
7 
31 #include "TrkSurfaces/Surface.h"
32 #include "TrkTrack/Track.h"
33 #include "CxxUtils/trapping_fp.h"
34 
35 namespace Muon {
36 
37  MuonTrackCleaner::MuonTrackCleaner(const std::string& ty, const std::string& na, const IInterface* pa) : AthAlgTool(ty, na, pa) {
38  declareInterface<IMuonTrackCleaner>(this);
39  }
40 
42  ATH_CHECK(m_trackFitter.retrieve());
43  ATH_CHECK(m_slTrackFitter.retrieve());
44  ATH_CHECK(m_idHelperSvc.retrieve());
45  ATH_CHECK(m_edmHelperSvc.retrieve());
46  ATH_CHECK(m_printer.retrieve());
47  ATH_CHECK(m_extrapolator.retrieve());
48  ATH_CHECK(m_pullCalculator.retrieve());
49  ATH_CHECK(m_mdtRotCreator.retrieve());
50  ATH_CHECK(m_compRotCreator.retrieve());
51  ATH_CHECK(m_measurementUpdator.retrieve());
53 
54  return StatusCode::SUCCESS;
55  }
56 
57  std::unique_ptr<Trk::Track> MuonTrackCleaner::clean(const Trk::Track& track, const std::set<Identifier>& chamberRemovalExclusionList,
58  const EventContext& ctx) const {
59  CleaningState state;
60  state.chamberRemovalExclusionList = chamberRemovalExclusionList;
61 
62  if (!state.chamberRemovalExclusionList.empty()) {
63  ATH_MSG_DEBUG(" Cleaning with exclusion list " << state.chamberRemovalExclusionList.size());
64  }
65 
66  std::unique_ptr<Trk::Track> cleanedTrack = cleanTrack(ctx, &track, state);
67  return cleanedTrack;
68  }
69  std::unique_ptr<Trk::Track> MuonTrackCleaner::clean(const Trk::Track& track, const EventContext& ctx) const {
70  CleaningState state;
71  std::unique_ptr<Trk::Track> cleanedTrack = cleanTrack(ctx, &track, state);
72  return cleanedTrack;
73  }
74 
75  std::unique_ptr<Trk::Track> MuonTrackCleaner::cleanTrack(const EventContext& ctx, const Trk::Track* track, CleaningState& state) const {
76  ATH_MSG_DEBUG(" Perform cleaning for track ");
77  ATH_MSG_DEBUG(m_printer->print(*track));
78 
79  init(ctx, *track, state);
80 
81  ATH_MSG_DEBUG("after init, track is " << m_printer->print(*track));
82  ATH_MSG_DEBUG(" start cleaning ");
83 
84  unsigned int nstationsInitial = state.stations.size();
85 
86  // first clean up chambers
87  std::unique_ptr<Trk::Track> chamberTrack = chamberCleaning(ctx, std::make_unique<Trk::Track>(*track), state);
88  if (!chamberTrack) {
89  ATH_MSG_DEBUG(" chamber removal failed ");
90  return nullptr;
91  }
92  ATH_MSG_DEBUG("after chamber cleaning, track is " << m_printer->print(*chamberTrack));
93 
94  // fail if only station remains on the track
95  unsigned int nstationsChamberCleaning = state.stations.size();
96  if (nstationsInitial != nstationsChamberCleaning) {
97  if (!checkStations(state)) return nullptr;
98  }
99 
100  // if performed curved fit and we did not have a vertex constraint or ID hits, reject the track if inner was removed
101  if (!state.slFit && !state.hasVertexConstraint && state.nIdHits <= 0) {
102  if (!checkInnerConstraint(state)) return nullptr;
103  }
104 
105  // if performing a single station layer cleaning without ID hits, reject track if there are insufficient phi constraints
106  if (!checkPhiConstraint(state)) return nullptr;
107 
108  // clean competing ROTs
109  std::unique_ptr<Trk::Track> cleanCompTrack = cleanCompROTs(ctx, std::move(chamberTrack), state);
110  if (!cleanCompTrack) {
111  ATH_MSG_DEBUG(" CompROT cleaning failed ");
112  return nullptr;
113  }
114  ATH_MSG_DEBUG("after comp rot cleaning, track is " << m_printer->print(*cleanCompTrack));
115 
116  // recover MDTs with flipped signs
117  std::unique_ptr<Trk::Track> flippedTrack = recoverFlippedMdt(ctx, std::move(cleanCompTrack), state);
118  if (!flippedTrack) {
119  ATH_MSG_DEBUG(" MDT sign flipping failed ");
120  return nullptr;
121  }
122  ATH_MSG_DEBUG("after flipped mdt recovery, track is " << m_printer->print(*flippedTrack));
123 
124  std::unique_ptr<Trk::Track> hitTrack = hitCleaning(ctx, std::move(flippedTrack), state);
125  if (!hitTrack) {
126  ATH_MSG_DEBUG(" track lost after outlier removal ");
127  return nullptr;
128  }
129  ATH_MSG_DEBUG("after hit cleaning, track is " << m_printer->print(*hitTrack));
130 
131  // keep this clone in case outlier recovery fails but the rest of the cleaning was succesful.
132  std::unique_ptr<Trk::Track> hitTrackClone = std::make_unique<Trk::Track>(*hitTrack);
133 
134  // fail if only one station remains
135  unsigned int nstationsHitCleaning = state.stations.size();
136  if (nstationsInitial != nstationsHitCleaning) {
137  if (!checkStations(state)) return nullptr;
138  }
139 
140  // if performed curved fit and we did not have a vertex constraint or ID hits, reject the track if inner was removed
141  if (!state.slFit && !state.hasVertexConstraint && state.nIdHits <= 0) {
142  if (!checkInnerConstraint(state)) return nullptr;
143  }
144 
145  // if performing a single station layer cleaning without ID hits, reject track if there are insufficient phi constraints
146  if (!checkPhiConstraint(state)) return nullptr;
147 
148  std::unique_ptr<Trk::Track> cleanedTrack = outlierRecovery(ctx, std::move(hitTrack), state);
149  // do not discard tracks that fail outlierRecovery, check that the track is ok
150  // note that this also performs a useful check on the quality of the cleaning in general
151  if (!cleanedTrack || !state.chambersToBeRemoved.empty() || !state.largePullMeasurements.empty()) {
152  init(ctx, *hitTrackClone, state);
153  if (!state.chambersToBeRemoved.empty() || !state.largePullMeasurements.empty()) {
154  ATH_MSG_DEBUG("Outlier recovery failure unrecoverable, reject track");
155  return nullptr;
156  } else {
157  ATH_MSG_DEBUG("Outlier recovery failed but initial track is recoverable");
158  cleanedTrack = std::move(hitTrackClone);
159  }
160  }
161 
162  if (state.nhits < state.noutliers) {
163  ATH_MSG_DEBUG(" track rejected due to high outlier ratio: hits " << state.nhits << " outliers " << state.noutliers);
164  return nullptr;
165  }
166 
167  unsigned int nstationsFinal = state.stations.size();
168  if (nstationsInitial != nstationsFinal) {
169  if (!checkStations(state)) return nullptr;
170  }
171 
172  ATH_MSG_VERBOSE(" final track " << m_printer->print(*cleanedTrack));
173  ATH_MSG_VERBOSE(m_printer->printStations(*cleanedTrack));
174 
175  return cleanedTrack;
176  }
177 
178  std::unique_ptr<Trk::Track> MuonTrackCleaner::cleanCompROTs(const EventContext& ctx, std::unique_ptr<Trk::Track> track,
179  CleaningState& state) const {
180  if (!m_cleanCompROTs || state.numberOfCleanedCompROTs == 0) return track;
181 
182  const Trk::Perigee* perigee = track->perigeeParameters();
183  if (!perigee) {
184  ATH_MSG_DEBUG(" track without perigee ");
185  return nullptr;
186  }
187 
188  ATH_MSG_DEBUG(" Clean comp rots " << state.numberOfCleanedCompROTs);
189 
190  auto tsos = std::make_unique<Trk::TrackStates>();
191  tsos->reserve(state.measInfo.size());
192 
193  unsigned int nmeas = 0;
194  // loop over hits
195  InfoIt hit = state.measInfo.begin();
196  InfoIt hit_end = state.measInfo.end();
197  for (; hit != hit_end; ++hit) {
198  // hits that are flagged as outlier or hits in the chamber to be removed are added as Outlier
199  if (!hit->useInFit) {
200  ATH_MSG_DEBUG(" removing hit " << m_idHelperSvc->toString(hit->id) << " pull " << hit->resPull->pull().front());
201  if (hit->inBounds)
202  tsos->push_back(MuonTSOSHelper::cloneTSOSWithUpdate(*hit->originalState, *hit->meas, *hit->pars,
204 
205  continue;
206  } else {
207  if (hit->meas) ++nmeas;
208 
209  if (hit->cleanedCompROT) {
210  tsos->push_back(MuonTSOSHelper::cloneTSOSWithUpdate(*hit->originalState, *hit->cleanedCompROT, *hit->pars,
212  ATH_MSG_DEBUG(" replacing CompROT " << m_idHelperSvc->toString(hit->id) << " pull " << hit->resPull->pull().front());
213  } else {
214  tsos->push_back(hit->originalState->clone());
215  }
216  }
217  }
218 
219  if (nmeas < 6) {
220  ATH_MSG_DEBUG(" too few hits, cannot recover CompROTS ");
221  return nullptr;
222  }
223 
224  // create new track
225  std::unique_ptr<Trk::Track> cleanedTrack =
226  std::make_unique<Trk::Track>(track->info(), std::move(tsos), track->fitQuality() ? track->fitQuality()->uniqueClone() : nullptr);
227  printStates(cleanedTrack.get());
228 
229  // fit new track
230  std::unique_ptr<Trk::Track> newTrack = fitTrack(ctx, *cleanedTrack, track->info().particleHypothesis(), state.slFit);
231 
232  if (newTrack) {
233  init(ctx, *newTrack, state);
234  return newTrack;
235  } else
236  return nullptr;
237  }
238 
239  std::unique_ptr<Trk::Track> MuonTrackCleaner::recoverFlippedMdt(const EventContext& ctx, std::unique_ptr<Trk::Track> track,
240  CleaningState& state) const {
241  if (!m_flipMdtDriftRadii || state.numberOfFlippedMdts == 0) return track;
242 
243  const Trk::Perigee* perigee = track->perigeeParameters();
244  if (!perigee) {
245  ATH_MSG_DEBUG(" track without perigee ");
246  return nullptr;
247  }
248 
249  ATH_MSG_DEBUG(" Trying to flip MDT signs: total number of hits with wrong sign " << state.numberOfFlippedMdts);
250 
251  auto tsos = std::make_unique<Trk::TrackStates>();
252  tsos->reserve(state.measInfo.size());
253 
254  unsigned int nmeas = 0;
255  // loop over hits
256  InfoIt hit = state.measInfo.begin();
257  InfoIt hit_end = state.measInfo.end();
258  for (; hit != hit_end; ++hit) {
259  // hits that are flagged as outlier or hits in the chamber to be removed are added as Outlier
260  if (!hit->useInFit) {
261  ATH_MSG_DEBUG(" removing hit " << m_idHelperSvc->toString(hit->id) << " pull " << hit->resPull->pull().front());
262  if (hit->inBounds)
263  tsos->push_back(MuonTSOSHelper::cloneTSOSWithUpdate(*hit->originalState, *hit->meas, *hit->pars,
265 
266  continue;
267  } else {
268  if (hit->meas) ++nmeas;
269 
270  if (hit->flippedMdt) {
271  tsos->push_back(MuonTSOSHelper::cloneTSOSWithUpdate(*hit->originalState, *hit->flippedMdt, *hit->pars,
273  ATH_MSG_DEBUG(" flipping sign hit " << m_idHelperSvc->toString(hit->id) << " pull " << hit->resPull->pull().front());
274  } else {
275  tsos->push_back(hit->originalState->clone());
276  }
277  }
278  }
279 
280  if (nmeas < 6) {
281  ATH_MSG_DEBUG(" too few hits, cannot flip MDT hit sign ");
282  return nullptr;
283  }
284 
285  // create new track
286  std::unique_ptr<Trk::Track> cleanedTrack =
287  std::make_unique<Trk::Track>(track->info(), std::move(tsos), track->fitQuality() ? track->fitQuality()->uniqueClone() : nullptr);
288  printStates(cleanedTrack.get());
289 
290  // fit new track
291  std::unique_ptr<Trk::Track> newTrack = fitTrack(ctx, *cleanedTrack, track->info().particleHypothesis(), state.slFit);
292 
293  if (newTrack) {
294  init(ctx, *newTrack, state);
295  return newTrack;
296  } else
297  return nullptr;
298  }
299 
300  std::unique_ptr<Trk::Track> MuonTrackCleaner::hitCleaning(const EventContext& ctx, std::unique_ptr<Trk::Track> track,
301  CleaningState& state) const {
302  if (state.largePullMeasurements.empty()) return track;
303  ATH_MSG_DEBUG(" trying outlier removal ");
304 
305  const Trk::Perigee* perigee = track->perigeeParameters();
306  if (!perigee) {
307  ATH_MSG_DEBUG("input track without perigee ");
308  return nullptr;
309  }
310 
311  std::unique_ptr<Trk::Track> newTrack;
312 
313  for (unsigned int n = 0; n < m_ncycles; ++n) {
314  // sanity check, should not remove too many hits
315  if (state.largePullMeasurements.size() > 10) {
316  ATH_MSG_DEBUG(" Too many outliers, cannot perform cleaning ");
317  return nullptr;
318  }
319 
320  ATH_MSG_VERBOSE(" outlier removal cycle " << n);
321 
322  auto tsos = std::make_unique<Trk::TrackStates>();
323  tsos->reserve(state.measInfo.size());
324  ATH_MSG_VERBOSE("cleaning track with " << state.measInfo.size() << " hits");
325 
326  unsigned int nmeas = 0;
327  unsigned int nremovedPhi = 0;
328  bool hasSmall = false;
329  bool hasLarge = false;
330  MCTBCleaningInfo* firstPhi = nullptr;
331  MCTBCleaningInfo* lastPhi = nullptr;
332  std::map<MuonStationIndex::StIndex, std::pair<bool, bool> > slCountsPerStationLayer;
333  // loop over hits
334  InfoIt hit = state.measInfo.begin();
335  InfoIt hit_end = state.measInfo.end();
336  for (; hit != hit_end; ++hit) {
337  bool remove = state.largePullMeasurements.count(hit->meas) || !hit->inBounds || hit->isNoise;
338  // hits that are flagged as outlier or hits in the chamber to be removed are added as Outlier
339  if (!hit->useInFit || remove) {
340  hit->useInFit = 0;
341 
342  // count number of phi outliers
343  if (!hit->id.is_valid() || m_idHelperSvc->measuresPhi(hit->id)) ++nremovedPhi;
344 
345  if (remove) {
346  std::string inb = hit->inBounds ? " inBounds" : " outBounds";
347  ATH_MSG_DEBUG(" removing hit " << m_idHelperSvc->toString(hit->id) << " pull " << hit->resPull->pull().front()
348  << inb);
349  }
350  if (hit->inBounds) {
351  if (hit->cleanedCompROT) {
352  tsos->push_back(MuonTSOSHelper::cloneTSOSWithUpdate(*hit->originalState, *hit->cleanedCompROT, *hit->pars,
354  } else {
355  tsos->push_back(MuonTSOSHelper::cloneTSOSWithUpdate(*hit->originalState, *hit->meas, *hit->pars,
357  }
358  }
359  continue;
360  } else {
361  if (hit->resPull)
362  ATH_MSG_DEBUG(" keeping hit " << m_idHelperSvc->toString(hit->id) << " pull " << hit->resPull->pull().front());
363 
364  if (hit->meas) {
365  ++nmeas;
366  if (!hit->id.is_valid() || m_idHelperSvc->measuresPhi(hit->id)) {
367  if (!firstPhi)
368  firstPhi = &(*hit);
369  else
370  lastPhi = &(*hit);
371  }
372 
373  if (hit->id.is_valid() && m_idHelperSvc->isMdt(hit->id)) {
375  bool isSmall = m_idHelperSvc->isSmallChamber(hit->id);
376  bool isLarge = !isSmall;
377  // look for layer
378  std::map<MuonStationIndex::StIndex, std::pair<bool, bool> >::iterator pos =
379  slCountsPerStationLayer.find(stIndex);
380 
381  // if not found add current
382  if (pos == slCountsPerStationLayer.end())
383  slCountsPerStationLayer[stIndex] = std::make_pair(isSmall, isLarge);
384  else {
385  // update
386  if (isSmall) slCountsPerStationLayer[stIndex].first = true;
387  if (isLarge) slCountsPerStationLayer[stIndex].second = true;
388  }
389  }
390  }
391  if (!hit->originalState) ATH_MSG_DEBUG("no original state!");
392  tsos->push_back(hit->originalState->clone());
393  }
394  }
395  // loop over sl map and count the overlaps
396  unsigned int noverlaps = 0;
397  for (auto [index, slCounts] : slCountsPerStationLayer) {
398  if (!hasSmall && slCounts.first) hasSmall = true;
399  if (!hasLarge && slCounts.second) hasLarge = true;
400  if (slCounts.first && slCounts.second) ++noverlaps;
401  }
402  // now update for the case there are small and large chambers but not in the same layer
403  if (noverlaps == 0 && hasSmall && hasLarge) ++noverlaps;
404 
405  if (nmeas < 6) {
406  ATH_MSG_DEBUG(" too few hits, cannot perform hitCleaning ");
407  return nullptr;
408  }
409 
410  ATH_MSG_DEBUG(" nremovedPhi " << nremovedPhi << " noverlaps " << noverlaps << " nid " << state.nIdHits);
411  if (firstPhi) ATH_MSG_DEBUG(" hasFirstPhi: " << m_idHelperSvc->toString(firstPhi->id));
412  if (lastPhi) ATH_MSG_DEBUG(" hasLastPhi: " << m_idHelperSvc->toString(lastPhi->id));
413 
414  // only perform check on phi constraints if any phi hits were removed
415  if (nremovedPhi > 0) {
416  bool hasPhiConstraint = false;
417 
418  if (state.nIdHits > 0)
419  hasPhiConstraint = true; // ok if ID hits
420  else if (firstPhi && noverlaps > 0)
421  hasPhiConstraint = true; // ok if one phi hit + one overlap
422  else if (noverlaps > 1)
423  hasPhiConstraint = true; // ok if two overlaps
424  else if (firstPhi && lastPhi && firstPhi->pars && lastPhi->pars) {
425  double distPhi =
426  std::abs((firstPhi->pars->position() - lastPhi->pars->position()).dot(firstPhi->pars->momentum().unit()));
427  ATH_MSG_DEBUG(" Distance between phi hits " << distPhi);
428  if (distPhi > 450.) hasPhiConstraint = true;
429  }
430  if (!hasPhiConstraint) {
431  ATH_MSG_DEBUG("Lost phi constraint during track cleaning, reject track");
432  return nullptr;
433  }
434  }
435 
436  // create new track
437  std::unique_ptr<Trk::Track> cleanedTrack =
438  std::make_unique<Trk::Track>(track->info(), std::move(tsos), track->fitQuality() ? track->fitQuality()->uniqueClone() : nullptr);
439 
440  // fit new track
441  printStates(cleanedTrack.get());
442 
443  newTrack = fitTrack(ctx, *cleanedTrack, track->info().particleHypothesis(), state.slFit);
444 
445  if (!newTrack) {
446  return nullptr;
447  } else {
448  const Trk::Perigee* perigee = newTrack->perigeeParameters();
449  if (!perigee) {
450  ATH_MSG_DEBUG(" track without perigee ");
451  return nullptr;
452  }
453  // reinitialize cleaner
454  init(ctx, *newTrack, state);
455  }
456 
457  if (state.largePullMeasurements.empty()) {
458  ATH_MSG_DEBUG(" cleaning ended successfully after cycle " << n);
459  return newTrack;
460  }
461  }
462 
463  return nullptr;
464  }
465 
466  std::unique_ptr<Trk::Track> MuonTrackCleaner::chamberCleaning(const EventContext& ctx, std::unique_ptr<Trk::Track> track,
467  CleaningState& state) const {
468  ATH_MSG_DEBUG("run chamber cleaning on track " << m_printer->print(*track));
469 
470  if (state.chambersToBeRemoved.empty() && state.chambersToBeRemovedPhi.empty()) return track;
471 
472  if (state.pullSumPerChamber.size() == 2) {
473  // loop over chambers that should be removed, if one of them is MDT or CSC don't clean
474  // as this would result in a single chamber track
475  PullChIt chit = state.chambersToBeRemoved.begin();
476  PullChIt chit_end = state.chambersToBeRemoved.end();
477  for (; chit != chit_end; ++chit) {
478  const Identifier& chid = chit->second;
479  if (m_idHelperSvc->isMdt(chid) || m_idHelperSvc->isCsc(chid)) {
480  ATH_MSG_DEBUG(" only two precision chambers, cannot remove chamber. ");
481  return nullptr;
482  }
483  }
484  }
485 
486  if (!state.chamberRemovalExclusionList.empty()) {
487  unsigned int foundChambers = 0;
488  // loop over chambers that should be removed and check if they are in the exclusion list
489  PullChIt chit = state.chambersToBeRemoved.begin();
490  PullChIt chit_end = state.chambersToBeRemoved.end();
491  for (; chit != chit_end; ++chit) {
492  const Identifier& chid = chit->second;
493  if (m_idHelperSvc->isMdt(chid) && state.chamberRemovalExclusionList.count(chid)) {
494  ATH_MSG_DEBUG(" found excluded chamber " << m_idHelperSvc->toStringChamber(chid));
495  ++foundChambers;
496  }
497  }
498  unsigned int excludedChambers = state.chamberRemovalExclusionList.size();
499  if (foundChambers > excludedChambers) {
500  ATH_MSG_WARNING(" Found more excluded chambers than in list, this should not happen ");
501  return nullptr;
502  } else if (foundChambers == excludedChambers) {
503  ATH_MSG_DEBUG(" all excluded chambers in removal list, failing cleaning ");
504  return nullptr;
505  }
506  }
507 
508  std::vector<ChamberRemovalOutput> cleaningResults;
509  cleaningResults.reserve(state.chambersToBeRemoved.size());
510 
511  // TODO first remove hits in both eta and phi
512 
513  ATH_MSG_DEBUG(" number of chambers short listed to be removed: " << state.chambersToBeRemoved.size());
514  std::stable_sort(state.chambersToBeRemoved.begin(), state.chambersToBeRemoved.end(), SortByAvePull());
515 
516  // try all combinations of removing a chamber with eta hits
517  unsigned int nchambers = state.chambersToBeRemoved.size() + state.chambersToBeRemovedPhi.size();
518  PullChIt chit = state.chambersToBeRemoved.begin();
519  PullChIt chit_end = state.chambersToBeRemoved.end();
520  for (; chit != chit_end; ++chit) {
521  ChamberRemovalOutput result = removeChamber(ctx, track, chit->second, false, true, state);
522  if (!result.track) {
523  ATH_MSG_DEBUG(" Removed eta hits of " << m_idHelperSvc->toStringChamber(chit->second) << ", track lost ");
524  continue;
525  }
526  ATH_MSG_DEBUG(" Removed eta hits of " << m_idHelperSvc->toStringChamber(chit->second));
527  ATH_MSG_DEBUG(m_printer->print(*result.track));
528 
529  // this is an optimization for the common case where there is only one chamber to be removed
530  if (nchambers > 1) unremoveHits(result);
531 
532  cleaningResults.push_back(std::move(result));
533  } // for (chit)
534 
535  ATH_MSG_DEBUG(" number of phi chambers short listed to be removed: " << state.chambersToBeRemoved.size());
536  std::stable_sort(state.chambersToBeRemovedPhi.begin(), state.chambersToBeRemovedPhi.end(), SortByAvePull());
537  // try all combinations of removing a chamber with phi hits
538  chit = state.chambersToBeRemovedPhi.begin();
539  chit_end = state.chambersToBeRemovedPhi.end();
540  for (; chit != chit_end; ++chit) {
541  ChamberRemovalOutput result = removeChamber(ctx, track, chit->second, true, false, state);
542  if (!result.track) {
543  ATH_MSG_DEBUG(" Removed phi hits of " << m_idHelperSvc->toStringChamber(chit->second) << ", track lost ");
544  continue;
545  }
546  ATH_MSG_DEBUG(" Removed phi hits of " << m_idHelperSvc->toStringChamber(chit->second));
547  ATH_MSG_DEBUG(m_printer->print(*result.track));
548 
549  // this is an optimization for the common case where there is only one chamber to be removed
550  if (nchambers > 1) unremoveHits(result);
551 
552  cleaningResults.push_back(std::move(result));
553  }
554 
555  // if no cleaned tracks return 0
556  if (cleaningResults.empty()) return nullptr;
557  std::stable_sort(cleaningResults.begin(), cleaningResults.end(), SortChamberRemovalResultByChi2Ndof());
558  ATH_MSG_DEBUG(" chamberCleaning Results nr " << cleaningResults.size());
559  for (auto& res : cleaningResults) { ATH_MSG_DEBUG(" track " << m_printer->print(*res.track)); }
560 
561  ChamberRemovalOutput& finalResult = cleaningResults.front();
562  if (nchambers > 1) {
563  // loop over removed hits and redo 'remove'
564  for (auto* hit : finalResult.removedHits) hit->useInFit = 0;
565  }
566 
567  ATH_MSG_DEBUG(" chamberCleaning: track ");
568  ATH_MSG_DEBUG(m_printer->print(*finalResult.track));
569 
570  // make clone just in case outlier recovery fails
571  std::unique_ptr<Trk::Track> finalResultTrackClone = std::make_unique<Trk::Track>(*finalResult.track);
572 
573  init(ctx, *finalResultTrackClone, state);
574 
575  // now finally check whether the removed layer now is recoverable (happens sometimes if the segment has one or more bad hits)
576  MuonStationIndex::ChIndex removedChamberIndex = m_idHelperSvc->chamberIndex(finalResult.chId);
577  std::unique_ptr<Trk::Track> recoveredTrack = outlierRecovery(ctx, std::move(finalResult.track), state, &removedChamberIndex);
578  if (!recoveredTrack) return finalResultTrackClone;
579  init(ctx, *recoveredTrack, state);
580  return recoveredTrack;
581  }
582 
584  const std::unique_ptr<Trk::Track>& track, Identifier chId,
585  bool removePhi, bool removeEta, CleaningState& state) const {
586  ATH_MSG_DEBUG(" removing chamber " << m_idHelperSvc->toStringChamber(chId));
587 
588  // store result
590  result.chId = chId;
591  const Trk::Perigee* perigee = track->perigeeParameters();
592  if (!perigee) {
593  ATH_MSG_DEBUG(" track without perigee ");
594  return result;
595  }
596 
597  auto tsos = std::make_unique<Trk::TrackStates>();
598  tsos->reserve(state.measInfo.size());
599 
600  unsigned int nmeas = 0;
601  // loop over hits
602  std::set<Identifier> stations{};
603  for (MCTBCleaningInfo& hit : state.measInfo) {
604  if (hit.id.is_valid()) {
605  bool measuresPhi = m_idHelperSvc->measuresPhi(hit.id);
606  bool remove = hit.chId == chId && ((removePhi && measuresPhi) || (removeEta && !measuresPhi));
607  // hits that are flagged as outlier or hits in the chamber to be removed are added as Outlier
608  if (!hit.useInFit || remove) {
609  ATH_MSG_DEBUG(" removing hit " << m_idHelperSvc->toString(hit.id) << " pull " << hit.resPull->pull().front());
610  // add as outlier
611  if (hit.inBounds)
612  tsos->push_back(MuonTSOSHelper::cloneTSOSWithUpdate(*hit.originalState, *hit.meas, *hit.pars,
614 
615  // if removed, add hit to vector of hits
616  // but only if the hit was not already an outlier to be skipped!
617  if (remove && hit.useInFit) result.removedHits.push_back(&hit);
618  hit.useInFit = 0;
619  continue;
620  }
621  }
622  if (hit.meas) {
623  ++nmeas;
624  // Through how many detector layers went actually the track ?
625  if (m_idHelperSvc->isMdt(hit.id)) stations.insert(m_idHelperSvc->mdtIdHelper().multilayerID(hit.id));
626  // Keep it for the run 2 legacy
627  else if (m_idHelperSvc->isCsc(hit.id)) stations.insert(m_idHelperSvc->cscIdHelper().elementID(hit.id));
628  // Multilayer defines here whether the track went through the IP or HO wedge
629  else if (m_idHelperSvc->isMM(hit.id)) stations.insert(m_idHelperSvc->mmIdHelper().multilayerID(hit.id));
630  // Hits on track in the site before or after the Micromega wedges... yeah micromega sandwich
631  else if (m_idHelperSvc->issTgc(hit.id)) stations.insert(m_idHelperSvc->stgcIdHelper().multilayerID(hit.id));
632  }
633  tsos->push_back(hit.originalState->clone());
634  }
635 
636  if (nmeas < 6 || stations.size() < 2) {
637  ATH_MSG_DEBUG(" too few hits, cannot perform chamberCleaning ");
638  return result;
639  }
640 
641  // create new track
642  std::unique_ptr<Trk::Track> cleanedTrack =
643  std::make_unique<Trk::Track>(track->info(), std::move(tsos), track->fitQuality() ? track->fitQuality()->uniqueClone() : nullptr);
644 
645  // fit new track
646  printStates(cleanedTrack.get());
647 
648  if (!cleanedTrack->perigeeParameters()) { ATH_MSG_DEBUG(" track without perigee "); }
649 
650  std::unique_ptr<Trk::Track> newTrack = fitTrack(ctx, *cleanedTrack, track->info().particleHypothesis(), state.slFit);
651 
652  if (newTrack && !newTrack->perigeeParameters()) {
653  ATH_MSG_DEBUG(" fitted track without perigee " << *newTrack << " " << newTrack->perigeeParameters());
654  }
655 
656  result.track = std::move(newTrack);
657  return result;
658  }
659 
660  std::unique_ptr<Trk::Track> MuonTrackCleaner::outlierRecovery(const EventContext& ctx, std::unique_ptr<Trk::Track> track,
661  CleaningState& state,
662  const MuonStationIndex::ChIndex* currentIndex) const {
663  const Trk::Perigee* perigee = track->perigeeParameters();
664  if (!perigee) {
665  ATH_MSG_DEBUG(" track without perigee ");
666  return nullptr;
667  }
668 
669  ATH_MSG_VERBOSE(" outlierRecovery: ");
670  if (currentIndex) ATH_MSG_VERBOSE(" layer " << MuonStationIndex::chName(*currentIndex));
671  ATH_MSG_VERBOSE(" printing chamber statistics ");
672 
673  for (auto [stationIndex, layer] : state.chamberLayerStatistics) {
674  if (stationIndex == MuonStationIndex::ChUnknown) continue;
676  }
677 
678  std::set<MuonStationIndex::ChIndex> recoverableLayers;
679  for (auto [stationIndex, layer] : state.chamberLayerStatistics) {
680  if (stationIndex == MuonStationIndex::ChUnknown) continue;
681 
682  // skip all chamber layers except the requested one
683  if (currentIndex && *currentIndex != stationIndex) continue;
684 
685  ChamberLayerStatistics& statistics = layer;
686  unsigned int nhits = statistics.nhits;
687  unsigned int noutliers = statistics.noutliers;
688  // unsigned int ndeltas = statistics.ndeltas;
689  unsigned int nrecoverableOutliers = statistics.nrecoverableOutliers;
690  unsigned int noutBounds = statistics.noutBounds;
691 
692  if (nrecoverableOutliers > 0) {
693  if (nhits + nrecoverableOutliers > 2 &&
694  ((noutBounds == 0 && noutliers == 0) || (nrecoverableOutliers != 0 && noutliers < 2))) {
695  recoverableLayers.insert(stationIndex);
696  ATH_MSG_DEBUG(" found recoverable layer " << MuonStationIndex::chName(statistics.chIndex));
697  }
698  }
699  }
700 
701  // if there is nothing to be done exit
702  if (recoverableLayers.empty() && !state.hasOfBoundsOutliers) return track;
703  bool addedHits = false;
704  unsigned int removedOutOfBoundsHits(0);
705 
706  auto tsos = std::make_unique<Trk::TrackStates>();
707  tsos->reserve(state.measInfo.size());
708 
709  // loop over hits
710  for (auto& hit : state.measInfo) {
711  if (!hit.useInFit) {
712  if (hit.inBounds) {
713  if (recoverableLayers.count(hit.chIndex)) {
714  // check whether we can savely add hits in this chamber to the track
715  bool recover = !isOutsideOnTrackCut(hit.id, hit.residual, hit.pull, m_associationScaleFactor);
716  if (recover && m_onlyUseHitErrorInRecovery && hit.pars) {
717  std::optional<const Trk::ResidualPull> resPull{
718  m_pullCalculator->residualPull(hit.meas, hit.pars, Trk::ResidualPull::HitOnly)};
719  if (!resPull) {
720  ATH_MSG_DEBUG(" calculation of residual/pull failed !!!!! ");
721  recover = false;
722  } else {
723  recover = !isOutsideOnTrackCut(hit.id, resPull->residual().front(), std::abs(resPull->pull().front()),
724 
726  }
727  }
728  if (recover) {
729  ATH_MSG_DEBUG(" adding outlier " << m_idHelperSvc->toString(hit.id) << " pull " << std::setw(7) << hit.pull);
730  if (hit.flippedMdt) {
731  double rDrift = hit.meas->localParameters()[Trk::locR];
732  double rDriftFlip = hit.flippedMdt->localParameters()[Trk::locR];
733  double rTrack = hit.pars->parameters()[Trk::locR];
734  ATH_MSG_DEBUG(" flipped MDT: r_orig " << rDrift << " flip " << rDriftFlip << " rTrack " << rTrack);
735  }
736  addedHits = true;
737  const Trk::MeasurementBase* newMeas = hit.flippedMdt ? hit.flippedMdt.get() : hit.meas;
738 
739  tsos->push_back(MuonTSOSHelper::cloneTSOSWithUpdate(*hit.originalState, *newMeas, *hit.pars,
741  } else {
742  tsos->push_back(hit.originalState->clone());
743  }
744  }
745  // layer not recoverable, drop the outliers: but if RPC, TGC, or CSC, expect track to go through all layers, so add a
746  // hole instead
747  if (m_idHelperSvc->isRpc(hit.id) || m_idHelperSvc->isTgc(hit.id) || m_idHelperSvc->isCsc(hit.id))
748  tsos->push_back(MuonTSOSHelper::createHoleTSOS(hit.pars->uniqueClone()));
749  } else {
750  ++removedOutOfBoundsHits;
751  // if RPC, TGC, or CSC, expect track to go through all layers: add a hole to replace lost outlier
752  if (m_idHelperSvc->isRpc(hit.id) || m_idHelperSvc->isTgc(hit.id) || m_idHelperSvc->isCsc(hit.id))
753  tsos->push_back(MuonTSOSHelper::createHoleTSOS(hit.pars->uniqueClone()));
754  ATH_MSG_DEBUG(" removing out of bounds outlier " << m_idHelperSvc->toString(hit.id) << " pull " << std::setw(7)
755  << hit.pull);
756  }
757  } else {
758  tsos->push_back(hit.originalState->clone());
759  }
760  }
761 
762  if (!addedHits && removedOutOfBoundsHits == 0) {
763  ATH_MSG_DEBUG(" track unchanged ");
764  return track;
765  }
766 
767  if (tsos->size() < 6) {
768  ATH_MSG_WARNING(" too few hits, cannot add hits. This should not happen ");
769  return nullptr;
770  }
771 
772  // create new track
773  std::unique_ptr<Trk::Track> cleanedTrack =
774  std::make_unique<Trk::Track>(track->info(), std::move(tsos), track->fitQuality() ? track->fitQuality()->uniqueClone() : nullptr);
775 
776  if (!addedHits) {
777  ATH_MSG_DEBUG(" only removed out of bound hits, returning track without new fit ");
778  return cleanedTrack;
779  }
780 
781  // fit new track
782  printStates(cleanedTrack.get());
783 
784  std::unique_ptr<Trk::Track> newTrack = fitTrack(ctx, *cleanedTrack, track->info().particleHypothesis(), state.slFit);
785 
786  if (newTrack) {
787  ATH_MSG_DEBUG("Outlier recovery successfull ");
788  init(ctx, *newTrack, state);
789  } else {
790  ATH_MSG_DEBUG("refit after outlier recovery failed ");
791  }
792 
793  return newTrack;
794  }
795 
796  void MuonTrackCleaner::init(const EventContext& ctx, const Trk::Track& track, CleaningState& state) const {
797  // Tell clang to optimize assuming that FP exceptions can trap.
798  // Otherwise, it can vectorize the division, which can lead to
799  // spurious division-by-zero traps from unused vector lanes.
801 
802  state.nscatterers = 0;
803  state.numberOfFlippedMdts = 0;
804  state.numberOfCleanedCompROTs = 0;
805  state.nhits = 0;
806  state.noutliers = 0;
807  state.pullSum = ChamberPullInfo();
808  state.pullSumPhi = ChamberPullInfo();
810  state.chambersToBeRemoved.clear();
811  state.chambersToBeRemovedPhi.clear();
812  state.pullSumPerChamber.clear();
813  state.pullSumPerChamberPhi.clear();
814  state.pullSumPerChamberEta.clear();
815  state.hitsPerChamber.clear();
816  state.outBoundsPerChamber.clear();
817  state.measInfo.clear();
818  state.largePullMeasurements.clear();
819  state.chamberLayerStatistics.clear();
820  state.stations.clear();
821  state.phiLayers.clear();
822  state.hasOfBoundsOutliers = false;
823  state.hasVertexConstraint = false;
824  state.hasSmall = false;
825  state.hasLarge = false;
826  state.nIdHits = 0;
827  state.nPseudoMeasurements = 0;
828  state.nPhiConstraints = 0;
829 
830  MagField::AtlasFieldCache fieldCache;
831  // Get field cache object
833  if (!readHandle.isValid()) {
834  ATH_MSG_ERROR("Failed to retrieve AtlasFieldCacheCondObj with key " << m_fieldCacheCondObjInputKey.key());
835  return;
836  }
837  readHandle->getInitializedCache(fieldCache);
838 
839  state.slFit = !fieldCache.toroidOn() || m_edmHelperSvc->isSLTrack(track);
840  if (m_use_slFit) state.slFit = true;
841 
842  // loop over track and calculate residuals
843  const Trk::TrackStates* states = track.trackStateOnSurfaces();
844  if (!states) {
845  ATH_MSG_WARNING(" track without states, cannot perform cleaning ");
846  return;
847  }
848 
849  ATH_MSG_DEBUG(" init: " << m_printer->print(track));
850 
851  state.measInfo.reserve(states->size());
852 
853  std::set<int> rpcLayers;
854  std::set<int> tgcLayers;
855  const Trk::MeasurementBase* mdtmeas = nullptr;
856  double largestmdtpull = -999;
857 
858  // loop over TSOSs
859  for (const Trk::TrackStateOnSurface* tsit : *states) {
860  if (tsit->type(Trk::TrackStateOnSurface::Perigee))
861  ATH_MSG_DEBUG(tsit->dumpType() << ", parameters " << *tsit->trackParameters());
862  const Trk::TrackParameters* pars = tsit->trackParameters();
863  if (!pars) {
864  state.measInfo.emplace_back(tsit);
865  continue;
866  }
867 
868  if (tsit->type(Trk::TrackStateOnSurface::Scatterer)) {
869  const Trk::MaterialEffectsBase* matEff = tsit->materialEffectsOnTrack();
870  const Trk::MaterialEffectsOnTrack* matTrk = dynamic_cast<const Trk::MaterialEffectsOnTrack*>(matEff);
871  ATH_MSG_VERBOSE(" Scatterer: r " << pars->position().perp() << " z " << pars->position().z());
872  if (matEff) ATH_MSG_VERBOSE(" X0 " << matEff->thicknessInX0());
873  if (matTrk && matTrk->scatteringAngles()) {
874  const Trk::ScatteringAngles* scatAngle = matTrk->scatteringAngles();
875  ATH_MSG_VERBOSE(" pull phi " << scatAngle->deltaPhi() / scatAngle->sigmaDeltaPhi() << " pull theta "
876  << scatAngle->deltaTheta() / scatAngle->sigmaDeltaTheta());
877  }
878  if (matTrk && matTrk->energyLoss()) {
879  const Trk::EnergyLoss* eloss = matTrk->energyLoss();
880  ATH_MSG_DEBUG(" eloss " << eloss->deltaE());
881  }
882  ++state.nscatterers;
883  state.measInfo.emplace_back(tsit);
884  continue;
885  }
886 
887  // check whether state is a measurement
888  const Trk::MeasurementBase* meas = tsit->measurementOnTrack();
889  if (!meas) {
890  state.measInfo.emplace_back(tsit);
891  continue;
892  }
893 
894  Identifier id = m_edmHelperSvc->getIdentifier(*meas);
895  bool pseudo = !id.is_valid();
896  if (pseudo) ++state.nPseudoMeasurements;
897 
898  if (!pseudo && !m_idHelperSvc->mdtIdHelper().is_muon(id)) {
899  ATH_MSG_VERBOSE(" TSOS is not a muon hit, position: r " << pars->position().perp() << " z " << pars->position().z());
900 
901  // count ID hits on track
902  if (tsit->type(Trk::TrackStateOnSurface::Measurement) && m_idHelperSvc->mdtIdHelper().is_indet(id)) { ++state.nIdHits; }
903  state.measInfo.emplace_back(tsit);
904  continue;
905  }
906 
907  // check whether there is a vertex constraint
908  if (pseudo && dynamic_cast<const Trk::PseudoMeasurementOnTrack*>(meas) && pars->associatedSurface().center().perp() < 200.) {
909  state.hasVertexConstraint = true;
910  }
911 
912  Identifier chId = pseudo ? id : m_idHelperSvc->chamberId(id);
913  bool measuresPhi = pseudo ? true : m_idHelperSvc->measuresPhi(id);
914 
915  // bound checks
916  Amg::Vector2D locPos;
917  if (!meas->associatedSurface().globalToLocal(pars->position(), pars->position(), locPos)) {
918  ATH_MSG_DEBUG(" localToGlobal failed !!!!! ");
919  continue;
920  }
921  bool inBounds = true;
922  double tol1 = 100.;
923  double tol2 = 2 * tol1;
924  if (!pseudo && m_idHelperSvc->isMdt(id)) tol1 = 5.;
925 
926  // we need a special bound check for MDTs so we cast to SL surface
927  const Trk::StraightLineSurface* slSurf = dynamic_cast<const Trk::StraightLineSurface*>(&meas->associatedSurface());
928  // we need a special bound check also for MMs to consider edge passivation
929  const MMClusterOnTrack* mmClusterOnTrack = dynamic_cast<const MMClusterOnTrack*>(meas);
930 
931  if (slSurf) {
932  // perform bound check only for second coordinate
933  inBounds = slSurf->bounds().insideLoc2(locPos, tol2);
934  } else if (mmClusterOnTrack) {
935  // for MM, perform the bound check from the detector element
936  inBounds = mmClusterOnTrack->detectorElement()->insideActiveBounds(id, locPos, tol1, tol2);
937  } else {
938  inBounds = meas->associatedSurface().insideBounds(locPos, tol1, tol2);
939  }
940 
941  MuonStationIndex::ChIndex chIndex = !pseudo ? m_idHelperSvc->chamberIndex(id) : MuonStationIndex::ChUnknown;
942 
943  // pointer to resPull: workaround because a const pointer is returned
944  std::optional<Trk::ResidualPull> resPull{m_pullCalculator->residualPull(
946  if (!resPull) {
947  ATH_MSG_DEBUG(" calculation of residual/pull failed !!!!! ");
948  continue;
949  }
950  int pullSize = resPull->pull().size();
951  double residual = resPull->residual().front();
952  double pull = std::abs(resPull->pull().front());
953 
954  // sanity check
955  if (!pseudo && pullSize != 1) {
956  ATH_MSG_WARNING(" ResidualPull vector has size " << pullSize << " for channel " << m_idHelperSvc->toString(id));
957  continue;
958  }
959 
960  bool isMDT = !pseudo ? m_idHelperSvc->isMdt(id) : false;
961  double error = pull > 0.001 ? std::abs(residual / pull) : 1000.;
962  double rDrift = isMDT ? meas->localParameters()[Trk::locR] : 0.;
963  double rTrack = isMDT ? pars->parameters()[Trk::locR] : 0.;
964  double rTrackAbs = std::abs(rTrack);
965  double flippedResidual = isMDT ? rDrift + rTrack : 1e10;
966  double flippedPull = isMDT ? std::abs(flippedResidual / error) : 1e10;
967 
968  bool isNoise = false;
969  bool isOutlier = isOutsideOnTrackCut(id, residual, pull, 1);
970  bool isRecoverable = m_recoverOutliers && !isOutlier && !isOutsideOnTrackCut(id, residual, pull, m_associationScaleFactor);
971  bool flippedIsRecoverable =
972  isMDT && flippedPull < pull - 0.1 && !isOutsideOnTrackCut(id, flippedResidual, flippedPull, m_associationScaleFactor);
973  double innerRadius = 14.6;
974  if (isMDT) {
975  const MdtDriftCircleOnTrack* mdtdc = dynamic_cast<const MdtDriftCircleOnTrack*>(meas);
976  if (mdtdc) innerRadius = mdtdc->detectorElement()->innerTubeRadius();
977  }
978 
979  bool isDelta = isOutlier && isMDT && rTrackAbs < innerRadius && rTrackAbs > std::abs(rDrift);
980 
981  // remove all outliers that are too far from the track
982  if (isOutlier) {
983  if (isMDT) {
984  if (rTrackAbs > innerRadius) inBounds = false;
985  } else if (pull > 10.) {
986  inBounds = false;
987  }
988  }
989 
990  std::unique_ptr<MdtDriftCircleOnTrack> mdtRotFlipped;
991  std::unique_ptr<const CompetingMuonClustersOnTrack> updatedCompRot;
992  bool flipSign = false;
993  if (!pseudo) {
994  const MdtDriftCircleOnTrack* mdtRot = isMDT ? dynamic_cast<const MdtDriftCircleOnTrack*>(meas) : nullptr;
995  if (mdtRot && mdtRot->prepRawData() && mdtRot->prepRawData()->adc() < m_adcCut) {
996  isNoise = true;
997  isOutlier = true;
998  isRecoverable = false;
999  flippedIsRecoverable = false;
1000  isDelta = false;
1001  }
1002  if (flippedIsRecoverable) {
1003  residual = flippedResidual;
1004  pull = flippedPull;
1005  flipSign = true;
1006  }
1007  if (!isNoise && flipSign) {
1008  if (mdtRot) {
1009  mdtRotFlipped = std::make_unique<MdtDriftCircleOnTrack>(*mdtRot);
1010  Trk::DriftCircleSide side = rDrift < 0. ? Trk::RIGHT : Trk::LEFT;
1011  m_mdtRotCreator->updateSign(*mdtRotFlipped, side);
1012  double rDriftFlip = mdtRotFlipped->localParameters()[Trk::locR];
1013  int signRot = rDrift < 0 ? -1 : 1;
1014  int signRotFlip = rDriftFlip < 0 ? -1 : 1;
1015  if (rDrift != 0. && signRot == signRotFlip) {
1016  ATH_MSG_WARNING(" failed to flip sign of MDT " << rDrift << " flip " << rDriftFlip);
1017  }
1018  } else {
1019  ATH_MSG_WARNING(" failed to dynamic_cast measurement with MDT Identifier to a MdtDriftCircleOnTrack");
1020  }
1021  } else {
1022  // if the outlier MDT is not recoverable by flipping the sign, add it as the worst outlier
1023  if (isOutlier && isMDT && pull > largestmdtpull && !tsit->type(Trk::TrackStateOnSurface::Outlier)) {
1024  largestmdtpull = pull;
1025  mdtmeas = meas;
1026  }
1027  }
1028 
1029  if (measuresPhi) {
1030  bool isRpc = m_idHelperSvc->isRpc(id);
1031  if (isRpc) {
1032  int layer = 0;
1033  MuonStationIndex::StIndex stIndex = m_idHelperSvc->stationIndex(id);
1034  if (stIndex == Muon::MuonStationIndex::BM && m_idHelperSvc->rpcIdHelper().doubletR(id) == 1)
1035  layer = 1;
1036  else if (stIndex == Muon::MuonStationIndex::BO)
1037  layer = 2;
1038  rpcLayers.insert(layer);
1039  }
1040 
1041  bool isTgc = m_idHelperSvc->isTgc(id);
1042  if (isTgc) {
1043  int layer = 0;
1044  MuonStationIndex::StIndex stIndex = m_idHelperSvc->stationIndex(id);
1045  if (stIndex == Muon::MuonStationIndex::EM) {
1046  std::string stName = m_idHelperSvc->chamberNameString(id);
1047  if (stName[1] == '1')
1048  layer = 1;
1049  else if (stName[1] == '2')
1050  layer = 2;
1051  else if (stName[1] == '3')
1052  layer = 3;
1053  else {
1054  ATH_MSG_WARNING("Unable to calculate TGC layer for " << m_idHelperSvc->toString(id));
1055  layer = -1;
1056  }
1057  }
1058  if (layer != -1) tgcLayers.insert(layer);
1059  }
1060  if (m_idHelperSvc->issTgc(id)) {
1061  int layer = 4;
1062  if (m_idHelperSvc->stgcIdHelper().multilayer(id) == 2) layer = 5;
1063  tgcLayers.insert(layer);
1064  ATH_MSG_VERBOSE("adding STGC phi hit " << layer << " size " << tgcLayers.size());
1065  }
1066  }
1067 
1068  if (m_cleanCompROTs) {
1069  const CompetingMuonClustersOnTrack* crot = (measuresPhi && !isMDT && m_idHelperSvc->isRpc(id))
1070  ? dynamic_cast<const CompetingMuonClustersOnTrack*>(meas)
1071  : nullptr;
1072  if (crot) {
1073  ATH_MSG_DEBUG(" CompetingMuonClustersOnTrack with rots " << crot->numberOfContainedROTs());
1074  double minpos = 0.;
1075  double minres = 0.;
1076  double maxres = 0.;
1077  double absminres = 0.;
1078  double absmaxres = 0.;
1079  for (unsigned int i = 0; i < crot->numberOfContainedROTs(); ++i) {
1080  const MuonClusterOnTrack* cluster = &crot->rioOnTrack(i);
1081  if (!cluster) continue;
1082  double residual = cluster->localParameters()[Trk::locX] - pars->parameters()[Trk::locX];
1083  double absres = residual < 0. ? -1. * residual : residual;
1084  if (i == 0) {
1085  minres = residual;
1086  maxres = residual;
1087  minpos = cluster->localParameters()[Trk::locX];
1088  absminres = absres;
1089  absmaxres = absres;
1090  } else if (absres < absminres) {
1091  minres = residual;
1092  absminres = absres;
1093  minpos = cluster->localParameters()[Trk::locX];
1094  } else if (absres > absmaxres) {
1095  maxres = residual;
1096  absmaxres = absres;
1097  }
1098  ATH_MSG_VERBOSE(" ROT " << m_idHelperSvc->toString(cluster->identify()) << " lpos "
1099  << cluster->localParameters()[Trk::locX] << " pars " << pars->parameters()[Trk::locX]
1100  << " residual " << residual);
1101  }
1102  ATH_MSG_DEBUG(" residuals: min " << minres << " max " << maxres << " diff " << maxres - minres);
1103  bool splitCompRot = false;
1104  if (std::abs(maxres - minres) > 100 && absmaxres - absminres > 20 && crot->numberOfContainedROTs() < 20) {
1105  ATH_MSG_DEBUG(" recoverable double cluster ");
1106  splitCompRot = true;
1107  }
1108  if (splitCompRot) {
1109  std::list<const Trk::PrepRawData*> prdList;
1110  ATH_MSG_DEBUG(" Splitting comp rot ");
1111  for (unsigned int i = 0; i < crot->numberOfContainedROTs(); ++i) {
1112  const MuonClusterOnTrack* cluster = &crot->rioOnTrack(i);
1113  if (!cluster) continue;
1114  double residual = cluster->localParameters()[Trk::locX] - minpos;
1115  double absres = residual < 0. ? -1. * residual : residual;
1116  if (absres < 40) {
1117  ATH_MSG_DEBUG(" NEW ROT " << m_idHelperSvc->toString(cluster->identify()) << " lpos "
1118  << cluster->localParameters()[Trk::locX] << " pars "
1119  << pars->parameters()[Trk::locX] << " residual " << residual);
1120  prdList.push_back(cluster->prepRawData());
1121  }
1122  }
1123  if (prdList.empty()) {
1124  ATH_MSG_WARNING("No clusters selected during comprot cleaning, keeping old cluster");
1125  } else {
1126  updatedCompRot=m_compRotCreator->createBroadCluster(prdList, 0.);
1127  ++state.numberOfCleanedCompROTs;
1128  }
1129  }
1130  }
1131  }
1132  }
1133 
1134  state.measInfo.emplace_back(id, chId, chIndex, inBounds, residual, pull, tsit, meas, pars, std::move(resPull), nullptr);
1135  MCTBCleaningInfo& info = state.measInfo.back();
1136  if (flipSign) { info.flippedMdt = std::move(mdtRotFlipped); }
1137  info.isNoise = isNoise;
1138  if (updatedCompRot) {
1139  ATH_MSG_DEBUG("updated competing ROT");
1140  info.cleanedCompROT = std::move(updatedCompRot);
1141  if (info.cleanedCompROT->associatedSurface() != meas->associatedSurface()) {
1142  std::unique_ptr<Trk::TrackParameters> exPars = m_extrapolator->extrapolate(ctx,
1143  *pars, info.cleanedCompROT->associatedSurface(),
1144  Trk::anyDirection, false, Trk::muon);
1145  if (!exPars) {
1146  ATH_MSG_WARNING("Update of comp rot parameters failed, keeping old ones");
1147  info.cleanedCompROT.reset();
1148  } else {
1149  info.pars = exPars.get();
1150  state.parsToBeDeleted.emplace_back(std::move(exPars));
1151  }
1152  }
1153  }
1154 
1155  ChamberLayerStatistics& chamberStatistics = state.chamberLayerStatistics[chIndex];
1156  chamberStatistics.chIndex = chIndex;
1157 
1158  if (tsit->type(Trk::TrackStateOnSurface::Outlier)) {
1159  ATH_MSG_DEBUG(" Outlier " << m_idHelperSvc->toString(id) << m_printer->print(*(info.resPull)));
1160  if (isMDT)
1161  ATH_MSG_DEBUG(" r_drift " << rDrift << " r_trk " << rTrack << " dr " << std::setw(7)
1162  << Amg::error(meas->localCovariance(), Trk::locR));
1163  if (isNoise) ATH_MSG_DEBUG(" noise ");
1164  if (!inBounds)
1165  ATH_MSG_DEBUG(" outBounds ");
1166  else {
1167  ATH_MSG_DEBUG(" inBounds ");
1168  if (flippedIsRecoverable)
1169  ATH_MSG_DEBUG(" flipped is recoverable, rFlipped " << info.flippedMdt->localParameters()[Trk::locR]);
1170  else if (isRecoverable)
1171  ATH_MSG_DEBUG(" recoverable ");
1172  else if (isDelta)
1173  ATH_MSG_DEBUG(" delta ");
1174  }
1175 
1176  if (!inBounds) {
1177  state.hasOfBoundsOutliers = true;
1178  ++chamberStatistics.noutBounds;
1179  } else if (flippedIsRecoverable || isRecoverable)
1180  ++chamberStatistics.nrecoverableOutliers;
1181  else if (isDelta)
1182  ++chamberStatistics.ndeltas;
1183  else if (pull < 10)
1184  ++chamberStatistics.noutliers;
1185 
1186  if (!pseudo) ++state.noutliers; // don't count pseudos here
1187  info.useInFit = 0;
1188  continue;
1189  }
1190 
1191  // if we get here could be as hit
1192  ++chamberStatistics.nhits;
1193  if (!pseudo) ++state.nhits; // pseudo's shouldn't count here
1194 
1195  if (flipSign) ++state.numberOfFlippedMdts;
1196 
1197  std::string idString = pseudo ? " Pseudomeasurement " : m_idHelperSvc->toString(id);
1198  std::string boundCheck = inBounds ? "inBounds" : "outBounds";
1199  ATH_MSG_VERBOSE(m_printer->print(*(info.resPull)) << " " << idString << " " << boundCheck);
1200  if (isNoise)
1201  ATH_MSG_VERBOSE(" noise");
1202  else if (isOutlier)
1203  ATH_MSG_VERBOSE(" outlier");
1204  if (isMDT) {
1205  ATH_MSG_VERBOSE(" r_drift " << std::setw(8) << rDrift << " r_trk " << std::setw(7) << rTrack << " dr " << std::setw(7)
1206  << Amg::error(meas->localCovariance(), Trk::locR));
1207  if (flipSign)
1208  ATH_MSG_VERBOSE(" flipped rDrift " << info.flippedMdt->localParameters()[Trk::locR] << " pull " << flippedPull);
1209  else if (isDelta)
1210  ATH_MSG_VERBOSE(" delta ");
1211  } else {
1212  const RpcClusterOnTrack* rpc = dynamic_cast<const RpcClusterOnTrack*>(meas);
1213  if (!rpc) {
1214  const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(meas);
1215  if (crot) { rpc = dynamic_cast<const RpcClusterOnTrack*>(crot->containedROTs().front()); }
1216  }
1217  if (rpc) ATH_MSG_DEBUG(" time " << rpc->prepRawData()->time() - rpc->globalPosition().mag() / 300.);
1218  }
1219 
1220  if (pseudo) {
1221  // pseudo measurements should not be included in chamber hit removal so stop here
1222  if (!isNoise && isOutlier) { state.largePullPseudoMeasurements.insert(meas); }
1223  continue;
1224 
1225  } else {
1226  // count hits
1227  EtaPhiHits& hits = state.hitsPerChamber[info.chId];
1228  if (measuresPhi)
1229  ++hits.nphi;
1230  else
1231  ++hits.neta;
1232 
1233  // bound checks
1234  if (!inBounds) {
1235  EtaPhiHits& outHits = state.outBoundsPerChamber[info.chId];
1236  if (measuresPhi)
1237  ++outHits.nphi;
1238  else
1239  ++outHits.neta;
1240  }
1241 
1242  // measurements with large pull
1243  if (!tsit->type(Trk::TrackStateOnSurface::Outlier) && isOutlier && !isMDT) { state.largePullMeasurements.insert(meas); }
1244 
1245  // pulls per chamber
1246  if (!m_idHelperSvc->isTrigger(info.chId)) {
1247  ChamberPullInfo& pullInfoHits = measuresPhi ? state.pullSumPhi : state.pullSum;
1248  pullInfoHits.pullSum += pull;
1249  ++pullInfoHits.nhits;
1250  if (pull > pullInfoHits.maxPull) pullInfoHits.maxPull = pull;
1251 
1252  ChamberPullInfo& pullInfoCh = measuresPhi ? state.pullSumPerChamberPhi[info.chId] : state.pullSumPerChamber[info.chId];
1253  pullInfoCh.pullSum += pull;
1254  ++pullInfoCh.nhits;
1255  if (pull > pullInfoCh.maxPull) pullInfoCh.maxPull = pull;
1256  } else {
1257  ChamberPullInfo& pullInfoTrig = measuresPhi ? state.pullSumPhi : state.pullSumTrigEta;
1258  if (!measuresPhi) state.pullSumPerChamberEta[info.chId];
1259  pullInfoTrig.pullSum += pull;
1260  ++pullInfoTrig.nhits;
1261  if (pull > pullInfoTrig.maxPull) pullInfoTrig.maxPull = pull;
1262  }
1263  }
1264  }
1265 
1266  // if there was an MDT outlier add it to the list of hits to be removed
1267  if (mdtmeas) state.largePullMeasurements.insert(mdtmeas);
1268 
1269  // check whether we have sufficient layers to savely clean the RPC/TGC comp rots
1270  unsigned int nphiLayers = rpcLayers.size() + tgcLayers.size();
1271  if (state.hasVertexConstraint) { nphiLayers += 1; }
1272  if (state.nIdHits > 0) { nphiLayers += 2; }
1273 
1274  if ((nphiLayers > 2) && state.numberOfCleanedCompROTs > 0) {
1275  ATH_MSG_DEBUG(" Sufficient constraints to clean competing ROTs: trigger layers " << nphiLayers);
1276  } else {
1277  // reset counter so no cleaning is performed
1278  state.numberOfCleanedCompROTs = 0;
1279  }
1280 
1281  // update sl fit configuration if track has ID hits or vertex constraint
1282  if (!m_use_slFit && state.slFit && (state.hasVertexConstraint || state.nIdHits > 0) && fieldCache.solenoidOn()) {
1283  state.slFit = false;
1284  }
1285 
1286  if (state.hasVertexConstraint || state.nIdHits) {
1287  if (state.hasVertexConstraint) ATH_MSG_DEBUG(" Track has vertex contraint:");
1288  if (state.nIdHits > 0) ATH_MSG_DEBUG(" Track has ID Hits: " << state.nIdHits);
1289  if (fieldCache.solenoidOn())
1290  ATH_MSG_DEBUG(" Solenoid On");
1291  else
1292  ATH_MSG_DEBUG(" Solenoid Off");
1293  if (fieldCache.toroidOn())
1294  ATH_MSG_DEBUG(" Toroid On");
1295  else
1296  ATH_MSG_DEBUG(" Toroid Off");
1297  if (state.slFit)
1298  ATH_MSG_DEBUG(" Use SL fit");
1299  else
1300  ATH_MSG_DEBUG(" Use curved fit");
1301  }
1302 
1303  std::set<Identifier> chambersToBeRemoved, chambersToBeRemovedPhi, goodEtaLayers, goodPhiLayers;
1304 
1305  // check whether there are any chambers in eta that should be removed
1306  extractChambersToBeRemoved(state, chambersToBeRemoved);
1307 
1308  // check whether there are any chambers in phi that should be removed
1309  extractChambersToBeRemoved(state, chambersToBeRemovedPhi, true);
1310 
1311  ATH_MSG_DEBUG("Chambers on track summary:");
1312 
1313  EtaPhiPerChamberIt chit = state.hitsPerChamber.begin();
1314  EtaPhiPerChamberIt chit_end = state.hitsPerChamber.end();
1315  for (; chit != chit_end; ++chit) {
1316  if (!chit->first.is_valid()) continue;
1317 
1318  bool isPrec = m_idHelperSvc->isMdt(chit->first) || m_idHelperSvc->isCsc(chit->first) || m_idHelperSvc->isMM(chit->first) ||
1319  m_idHelperSvc->issTgc(chit->first);
1320  if (isPrec) {
1321  MuonStationIndex::StIndex stIndex = m_idHelperSvc->stationIndex(chit->first);
1322  state.stations.insert(stIndex);
1323  }
1324 
1325  EtaPhiHits& nhits = chit->second;
1326  EtaPhiHits& noutBounds = state.outBoundsPerChamber[chit->first];
1327  ATH_MSG_DEBUG(" chamber " << m_idHelperSvc->toStringChamber(chit->first) << " eta hits " << nhits.neta << " outBounds "
1328  << noutBounds.neta << " phi hits " << nhits.nphi << " outBounds " << noutBounds.nphi);
1329  if (nhits.neta != 0 && nhits.neta == noutBounds.neta) {
1330  ATH_MSG_DEBUG(" --> All eta hits out of bounds ");
1331  // remove eta hits for this chamber
1332  double fakePull = 1000. * nhits.neta;
1333  if (!chambersToBeRemoved.count(chit->first)) {
1334  // just add it
1335  state.chambersToBeRemoved.emplace_back(fakePull, chit->first);
1336  chambersToBeRemoved.insert(chit->first);
1337  } else {
1338  // replace existing entry if new one has larger Pull
1339  PullChIt pIt = state.chambersToBeRemoved.begin();
1340  PullChIt pIt_end = state.chambersToBeRemoved.end();
1341  for (; pIt != pIt_end; ++pIt) {
1342  if (pIt->second == chit->first && pIt->first < fakePull) {
1343  pIt->first = fakePull;
1344  break;
1345  }
1346  }
1347  }
1348  } else {
1349  if (noutBounds.neta != 0) ATH_MSG_DEBUG(" --> Some eta hits out of bounds ");
1350 
1351  if (isPrec && nhits.neta > 0) {
1352  if (m_idHelperSvc->isSmallChamber(chit->first))
1353  state.hasSmall = true;
1354  else
1355  state.hasLarge = true;
1356  }
1357  }
1358  if (nhits.nphi != 0 && nhits.nphi == noutBounds.nphi) {
1359  ATH_MSG_DEBUG(" --> All phi hits out of bounds ");
1360  // remove phi hits for this chamber
1361  double fakePull = 1000. * nhits.nphi;
1362  if (!chambersToBeRemovedPhi.count(chit->first)) {
1363  // just add it
1364  state.chambersToBeRemovedPhi.emplace_back(fakePull, chit->first);
1365  chambersToBeRemovedPhi.insert(chit->first);
1366  } else {
1367  // replace existing entry if new one has larger pull
1368  PullChIt pIt = state.chambersToBeRemovedPhi.begin();
1369  PullChIt pIt_end = state.chambersToBeRemovedPhi.end();
1370  for (; pIt != pIt_end; ++pIt) {
1371  if (pIt->second == chit->first) {
1372  pIt->first = std::max(pIt->first, fakePull);
1373  break;
1374  }
1375  }
1376  }
1377  } else {
1378  if (noutBounds.nphi != 0) ATH_MSG_DEBUG(" --> Some phi hits out of bounds ");
1379  if (nhits.nphi > 0) {
1380  MuonStationIndex::PhiIndex phiIndex = m_idHelperSvc->phiIndex(chit->first);
1381  state.phiLayers.insert(phiIndex);
1382  }
1383  }
1384  }
1385 
1386  state.nPhiConstraints = state.phiLayers.size() + state.nPseudoMeasurements;
1387  if (state.hasLarge && state.hasSmall) ++state.nPhiConstraints;
1388  if (state.stations.size() == 1 && nphiLayers > 1) ++state.nPhiConstraints;
1389 
1390  double pull_precisionhits = -1.;
1391  if (state.pullSum.nhits != 0) { pull_precisionhits = state.pullSum.pullSum / state.pullSum.nhits; }
1392  double pull_triggerhits = -1.;
1393  if (state.pullSumTrigEta.nhits != 0) { pull_triggerhits = state.pullSumTrigEta.pullSum / state.pullSumTrigEta.nhits; }
1394  double pull_phihits = -1.;
1395  if (state.pullSumPhi.nhits != 0) { pull_phihits = state.pullSumPhi.pullSum / state.pullSumPhi.nhits; }
1396  ATH_MSG_DEBUG(" pull sum: precision hits "
1397  << pull_precisionhits << " trigger eta " << pull_triggerhits << " phi " << pull_phihits << " measurements "
1398  << state.measInfo.size() << std::endl
1399  << " precision chambers " << state.pullSumPerChamber.size() << " hits with large pull "
1400  << state.largePullMeasurements.size() << " pseudos with large pull " << state.largePullPseudoMeasurements.size()
1401  << " chambers to be removed " << state.chambersToBeRemoved.size() << " phi " << state.chambersToBeRemovedPhi.size()
1402  << " phi lay " << state.phiLayers.size() << " phi constr " << state.nPhiConstraints);
1403 
1404  if (state.pullSumPhi.nhits != 0) {
1405  double phiPull = state.pullSumPhi.pullSum / state.pullSumPhi.nhits;
1406  if (state.stations.size() == 1 && phiPull > 5.) { ATH_MSG_DEBUG(" Single station track with large phi pulls!! "); }
1407  } else
1408  ATH_MSG_DEBUG(" Track with no phi hits!! ");
1409  }
1410 
1411  bool MuonTrackCleaner::extractChambersToBeRemoved(CleaningState& state, std::set<Identifier>& chambersToBeRemovedSet,
1412  bool usePhi) const {
1413  bool doCleaning = false;
1414  PullChamberMap& pullSumPerChamber = usePhi ? state.pullSumPerChamberPhi : state.pullSumPerChamber;
1415  PullChVec& chambersToBeRemoved = usePhi ? state.chambersToBeRemovedPhi : state.chambersToBeRemoved;
1416 
1417  PullChamberCit cit = pullSumPerChamber.begin();
1418  PullChamberCit cit_end = pullSumPerChamber.end();
1419  if (msgLvl(MSG::DEBUG)) {
1420  if (!pullSumPerChamber.empty()) msg() << MSG::DEBUG << "Chamber pulls " << pullSumPerChamber.size() << ":";
1421  }
1422  int ndof = 0;
1423  double pulltot = 0.;
1424  for (; cit != cit_end; ++cit) {
1425  double avePull = cit->second.pullSum / cit->second.nhits;
1426  pulltot += cit->second.pullSum;
1427  ndof += cit->second.nhits;
1428  double avePullReduced = cit->second.nhits > 1 ? (cit->second.pullSum - cit->second.maxPull) / (cit->second.nhits - 1) : avePull;
1429  if (msgLvl(MSG::DEBUG))
1430  msg() << MSG::DEBUG << std::endl
1431  << " chamber " << m_idHelperSvc->toStringChamber(cit->first) << " pull sum " << cit->second.pullSum << " max pull "
1432  << cit->second.maxPull << " nhits " << cit->second.nhits << " ave pull " << avePull << " reduced ave pull "
1433  << avePullReduced;
1434  if (avePull > m_avePullSumPerChamberCut) {
1435  doCleaning = true;
1436  if (cit->second.nhits > 3 && avePullReduced < m_avePullSumPerChamberCut) {
1437  if (msgLvl(MSG::DEBUG)) msg() << MSG::DEBUG << " large pull sum ignored ";
1438  doCleaning = false;
1439  } else {
1440  if (msgLvl(MSG::DEBUG)) msg() << MSG::DEBUG << " large pull sum => removing";
1441  if (!chambersToBeRemovedSet.count(cit->first)) {
1442  chambersToBeRemoved.emplace_back(avePull, cit->first);
1443  chambersToBeRemovedSet.insert(cit->first);
1444  }
1445  }
1446  }
1447  }
1448  if (msgLvl(MSG::DEBUG)) msg() << endmsg;
1449  bool dropMore = false;
1450  if (dropMore && pulltot * pulltot > 2. * ndof * ndof) {
1451  doCleaning = true;
1452  if (msgLvl(MSG::DEBUG)) msg() << MSG::DEBUG << " large pull per dof " << pulltot << " ndof " << ndof << endmsg;
1453  }
1454 
1455  if (doCleaning && m_iterate) {
1456  cit = pullSumPerChamber.begin();
1457  for (; cit != cit_end; ++cit) {
1458  double avePull = cit->second.pullSum / cit->second.nhits;
1459  if (!chambersToBeRemovedSet.count(cit->first)) {
1460  chambersToBeRemoved.emplace_back(avePull, cit->first);
1461  chambersToBeRemovedSet.insert(cit->first);
1462  }
1463  }
1464  }
1465 
1466  if (dropMore && doCleaning && m_iterate) {
1467  // add trigger chambers
1468  cit = state.pullSumPerChamberEta.begin();
1469  cit_end = state.pullSumPerChamberEta.end();
1470  for (; cit != cit_end; ++cit) {
1471  double avePull = cit->second.pullSum / cit->second.nhits;
1472  if (!chambersToBeRemovedSet.count(cit->first)) {
1473  chambersToBeRemoved.emplace_back(avePull, cit->first);
1474  chambersToBeRemovedSet.insert(cit->first);
1475  }
1476  }
1477  }
1478 
1479  return doCleaning;
1480  }
1481 
1482  bool MuonTrackCleaner::isOutsideOnTrackCut(const Identifier& id, double res, double pull, double cutScaleFactor) const {
1483  bool isMdt = id.is_valid() ? m_idHelperSvc->isMdt(id) : false;
1484  bool measuresPhi = id.is_valid() ? m_idHelperSvc->measuresPhi(id) : false;
1485 
1486  // look at pulls and identify outliers
1487  double pullCut = measuresPhi ? m_pullCutPhi : m_pullCut;
1488 
1489  if (isMdt) {
1490  // if mdt residual cut is activated check whether the residual is small that 80% of the cut of
1491  if (m_useMdtResiCut) {
1492  return std::abs(res) > cutScaleFactor * m_mdtResiCut;
1493  } else {
1494  return std::abs(pull) > cutScaleFactor * pullCut;
1495  }
1496  } else {
1497  return std::abs(pull) > cutScaleFactor * pullCut;
1498  }
1499  }
1500 
1502  std::ostringstream sout;
1503 
1504  unsigned int nhits = statistics.nhits;
1505  unsigned int noutliers = statistics.noutliers;
1506  unsigned int ndeltas = statistics.ndeltas;
1507  unsigned int nrecoverableOutliers = statistics.nrecoverableOutliers;
1508  unsigned int noutBounds = statistics.noutBounds;
1509 
1510  sout << MuonStationIndex::chName(statistics.chIndex) << " hits " << std::setw(6) << nhits << " outliers " << std::setw(6)
1511  << noutliers << " deltas " << std::setw(6) << ndeltas << " recoverableOutliers " << std::setw(6) << nrecoverableOutliers
1512  << " outBounds " << std::setw(6) << noutBounds;
1513 
1514  return sout.str();
1515  }
1516 
1518  unsigned int nstationsChamberCleaning = state.stations.size();
1519  ATH_MSG_DEBUG(" Cleaner removed full station from track: remaining layers " << nstationsChamberCleaning);
1520 
1521  if (nstationsChamberCleaning < 2) {
1522  ATH_MSG_DEBUG(" Cleaner removed all but one station from track!!! ");
1523  return false;
1524  }
1525  return true;
1526  }
1527 
1529  unsigned int nstations = state.stations.size();
1530  if (nstations == 1 ||
1531  (nstations == 2 && (state.stations.count(MuonStationIndex::EM) && state.stations.count(MuonStationIndex::EO)))) {
1532  ATH_MSG_DEBUG(" Momentum measurement lost, cleaning given up ");
1533  return false;
1534  }
1535  return true;
1536  }
1537 
1539  if (state.stations.size() == 1 && !state.nIdHits && state.nPhiConstraints < 2) {
1540  ATH_MSG_DEBUG(" Underconstraint fit " << state.nPhiConstraints);
1541  return false;
1542  }
1543  return true;
1544  }
1545 
1547  // loop over removed hits and 'unremove' them so they are used in the next iteration
1548  for (auto* hit : result.removedHits) hit->useInFit = 1;
1549  }
1550 
1552  const Trk::TrackStates* states = track->trackStateOnSurfaces();
1553  int nStates = 0;
1554  if (states) nStates = states->size();
1555  ATH_MSG_DEBUG("Calling fit with hits: " << nStates<<std::endl<<m_printer->printMeasurements(*track));
1556  }
1557 
1558  std::unique_ptr<Trk::Track> MuonTrackCleaner::fitTrack(const EventContext& ctx, Trk::Track& track, Trk::ParticleHypothesis pHyp,
1559  bool slFit) const {
1560  return slFit ? m_slTrackFitter->fit(ctx, track, false, pHyp) : m_trackFitter->fit(ctx, track, false, pHyp);
1561  }
1562 } // namespace Muon
grepfile.info
info
Definition: grepfile.py:38
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
Muon::MuonStationIndex::chName
static const std::string & chName(ChIndex index)
convert ChIndex into a string
Definition: MuonStationIndex.cxx:157
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:142
Muon::MuonTrackCleaner::ChamberLayerStatistics::nrecoverableOutliers
unsigned int nrecoverableOutliers
Definition: MuonTrackCleaner.h:145
CXXUTILS_TRAPPING_FP
#define CXXUTILS_TRAPPING_FP
Definition: trapping_fp.h:24
Muon::MuonTrackCleaner::m_measurementUpdator
ToolHandle< Trk::IUpdator > m_measurementUpdator
Definition: MuonTrackCleaner.h:287
MdtReadoutElement.h
Muon::MuonStationIndex::toStationIndex
static StIndex toStationIndex(ChIndex index)
convert ChIndex into StIndex
Definition: MuonStationIndex.cxx:43
EnergyLoss.h
Muon::MuonTrackCleaner::ChamberRemovalOutput
struct to store return values of chamber removal, contains the new track plus a list the removed hits
Definition: MuonTrackCleaner.h:100
Trk::TrackStateOnSurface::Perigee
@ Perigee
This represents a perigee, and so will contain a Perigee object only.
Definition: TrackStateOnSurface.h:117
ScatteringAngles.h
Muon::MuonTrackCleaner::CleaningState::nPseudoMeasurements
unsigned int nPseudoMeasurements
Definition: MuonTrackCleaner.h:167
Muon::MuonTrackCleaner::CleaningState::nhits
unsigned int nhits
Definition: MuonTrackCleaner.h:162
Muon::MuonTrackCleaner::CleaningState::chambersToBeRemovedPhi
PullChVec chambersToBeRemovedPhi
Definition: MuonTrackCleaner.h:189
Muon::MuonTrackCleaner::MCTBCleaningInfo::inBounds
bool inBounds
Definition: MuonTrackCleaner.h:51
Muon::MuonTrackCleaner::isOutsideOnTrackCut
bool isOutsideOnTrackCut(const Identifier &id, double res, double pull, double cutScaleFactor) const
check whether hit is an outlier
Definition: MuonTrackCleaner.cxx:1482
Trk::StraightLineSurface::bounds
virtual const SurfaceBounds & bounds() const override final
This method returns the bounds of the Surface by reference.
get_generator_info.result
result
Definition: get_generator_info.py:21
Muon::MuonTrackCleaner::m_ncycles
Gaudi::Property< unsigned int > m_ncycles
Definition: MuonTrackCleaner.h:309
Muon::MuonTrackCleaner::CleaningState::hasLarge
bool hasLarge
Definition: MuonTrackCleaner.h:175
max
#define max(a, b)
Definition: cfImp.cxx:41
MeasurementBase.h
MuonGM::MMReadoutElement::insideActiveBounds
bool insideActiveBounds(const Identifier &id, const Amg::Vector2D &locpos, double tol1=0., double tol2=0.) const
boundary check Wrapper Trk::PlaneSurface::insideBounds() taking into account the passivated width
Definition: MMReadoutElement.h:257
Muon::MuonTrackCleaner::m_pullCutPhi
Gaudi::Property< double > m_pullCutPhi
Definition: MuonTrackCleaner.h:307
Muon::MuonClusterOnTrack::globalPosition
virtual const Amg::Vector3D & globalPosition() const override
Returns global position.
Definition: MuonClusterOnTrack.cxx:93
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
Muon::MdtDriftCircleOnTrack::prepRawData
virtual const MdtPrepData * prepRawData() const override final
Returns the PrepRawData used to create this corrected measurement.
Definition: MdtDriftCircleOnTrack.h:257
Trk::locX
@ locX
Definition: ParamDefs.h:43
Muon::MuonTrackCleaner::CleaningState::largePullMeasurements
MeasSet largePullMeasurements
Definition: MuonTrackCleaner.h:153
Muon::MuonTrackCleaner::CleaningState::parsToBeDeleted
std::vector< std::unique_ptr< Trk::TrackParameters > > parsToBeDeleted
Definition: MuonTrackCleaner.h:159
Surface.h
Trk::Track
The ATLAS Track class.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/Track.h:73
MuonGM::MdtReadoutElement::innerTubeRadius
double innerTubeRadius() const
Returns the inner tube radius excluding the aluminium walls.
Muon::MuonTrackCleaner::m_pullCut
Gaudi::Property< double > m_pullCut
Definition: MuonTrackCleaner.h:305
Muon::MuonTrackCleaner::CleaningState::pullSumTrigEta
ChamberPullInfo pullSumTrigEta
Definition: MuonTrackCleaner.h:179
Muon::MuonTrackCleaner::ChamberLayerStatistics
Definition: MuonTrackCleaner.h:140
ClusterSeg::residual
@ residual
Definition: ClusterNtuple.h:20
Trk::TrackStateOnSurface::clone
virtual TrackStateOnSurface * clone() const
Pseudo-constructor: needed to avoid excessive RTTI.
Trk::ParametersBase::position
const Amg::Vector3D & position() const
Access method for the position.
Muon::MuonStationIndex::EO
@ EO
Definition: MuonStationIndex.h:26
Amg::Vector2D
Eigen::Matrix< double, 2, 1 > Vector2D
Definition: GeoPrimitives.h:48
index
Definition: index.py:1
Muon::MuonTrackCleaner::ChamberLayerStatistics::noutBounds
unsigned int noutBounds
Definition: MuonTrackCleaner.h:146
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:583
Muon::MuonClusterOnTrack::prepRawData
virtual const MuonCluster * prepRawData() const override=0
Returns the Trk::PrepRawData - is a MuonCluster in this scope.
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::MCTBCleaningInfo
Definition: MuonTrackCleaner.h:46
EventPrimitivesHelpers.h
Muon::MuonTrackCleaner::MuonTrackCleaner
MuonTrackCleaner(const std::string &, const std::string &, const IInterface *)
constructor
Definition: MuonTrackCleaner.cxx:37
Muon::MuonTrackCleaner::m_useMdtResiCut
Gaudi::Property< bool > m_useMdtResiCut
Definition: MuonTrackCleaner.h:303
Muon::MuonTrackCleaner::m_mdtRotCreator
ToolHandle< Muon::IMdtDriftCircleOnTrackCreator > m_mdtRotCreator
Definition: MuonTrackCleaner.h:288
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:1538
Muon::MuonTrackCleaner::CleaningState::stations
std::set< MuonStationIndex::StIndex > stations
Definition: MuonTrackCleaner.h:191
Muon::MuonTrackCleaner::ChamberLayerStatistics::chIndex
MuonStationIndex::ChIndex chIndex
Definition: MuonTrackCleaner.h:141
Muon::MuonTrackCleaner::m_cleanCompROTs
Gaudi::Property< bool > m_cleanCompROTs
Definition: MuonTrackCleaner.h:313
AthCommonMsg< AlgTool >::msgLvl
bool msgLvl(const MSG::Level lvl) const
Definition: AthCommonMsg.h:30
Muon::MuonTrackCleaner::m_edmHelperSvc
ServiceHandle< Muon::IMuonEDMHelperSvc > m_edmHelperSvc
Definition: MuonTrackCleaner.h:294
Muon::MuonTrackCleaner::PullChIt
PullChVec::iterator PullChIt
Definition: MuonTrackCleaner.h:132
Muon::MuonTrackCleaner::CleaningState::phiLayers
std::set< MuonStationIndex::PhiIndex > phiLayers
Definition: MuonTrackCleaner.h:192
Muon::MuonTrackCleaner::checkStations
bool checkStations(CleaningState &state) const
Definition: MuonTrackCleaner.cxx:1517
Trk::ScatteringAngles
represents a deflection of the track caused through multiple scattering in material.
Definition: ScatteringAngles.h:26
Muon::MuonTrackCleaner::CleaningState::pullSumPhi
ChamberPullInfo pullSumPhi
Definition: MuonTrackCleaner.h:178
FitQualityOnSurface.h
Trk::MaterialEffectsBase::thicknessInX0
double thicknessInX0() const
returns the actually traversed material .
Muon::MuonTrackCleaner::MCTBCleaningInfo::originalState
const Trk::TrackStateOnSurface * originalState
Definition: MuonTrackCleaner.h:56
Muon::MuonTrackCleaner::CleaningState::slFit
bool slFit
Definition: MuonTrackCleaner.h:165
Muon::RpcClusterOnTrack
Class to represent calibrated clusters formed from RPC strips.
Definition: RpcClusterOnTrack.h:35
Trk::locR
@ locR
Definition: ParamDefs.h:50
Muon::MdtDriftCircleOnTrack::detectorElement
virtual const MuonGM::MdtReadoutElement * detectorElement() const override final
Returns the detector element, assoicated with the PRD of this class.
Definition: MdtDriftCircleOnTrack.h:268
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
Muon::CompetingMuonClustersOnTrack
Definition: CompetingMuonClustersOnTrack.h:54
SG::VarHandleKey::key
const std::string & key() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:141
Muon::MuonTrackCleaner::SortByAvePull
Definition: MuonTrackCleaner.h:134
Trk::MaterialEffectsBase
base class to integrate material effects on Trk::Track in a flexible way.
Definition: MaterialEffectsBase.h:35
Muon::MuonTrackCleaner::CleaningState::hasSmall
bool hasSmall
Definition: MuonTrackCleaner.h:174
Muon::MuonTrackCleaner::InfoIt
InfoVec::iterator InfoIt
Definition: MuonTrackCleaner.h:94
MagField::AtlasFieldCache::toroidOn
bool toroidOn() const
Muon
This class provides conversion from CSC RDO data to CSC Digits.
Definition: TrackSystemController.h:49
Muon::MdtPrepData::adc
int adc() const
Returns the ADC (typically range is 0 to 250)
Definition: MdtPrepData.h:166
Muon::MuonTrackCleaner::ChamberLayerStatistics::nhits
unsigned int nhits
Definition: MuonTrackCleaner.h:142
MaterialEffectsBase.h
Identifier::is_valid
bool is_valid() const
Check if id is in a valid state.
Muon::MuonStationIndex::PhiIndex
PhiIndex
enum to classify the different phi layers in the muon spectrometer
Definition: MuonStationIndex.h:31
Muon::MuonTrackCleaner::m_avePullSumPerChamberCut
Gaudi::Property< double > m_avePullSumPerChamberCut
Definition: MuonTrackCleaner.h:310
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:75
MuonTrackMakerStlTools.h
Muon::MuonTrackCleaner::m_slTrackFitter
ToolHandle< Trk::ITrackFitter > m_slTrackFitter
Definition: MuonTrackCleaner.h:286
MMClusterOnTrack.h
Muon::MuonTrackCleaner::m_flipMdtDriftRadii
Gaudi::Property< bool > m_flipMdtDriftRadii
Definition: MuonTrackCleaner.h:312
Muon::MuonTrackCleaner::MCTBCleaningInfo::meas
const Trk::MeasurementBase * meas
Definition: MuonTrackCleaner.h:57
Muon::MuonTrackCleaner::ChamberLayerStatistics::ndeltas
unsigned int ndeltas
Definition: MuonTrackCleaner.h:144
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:300
Muon::MuonTrackCleaner::m_extrapolator
ToolHandle< Trk::IExtrapolator > m_extrapolator
Definition: MuonTrackCleaner.h:298
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
Track.h
Muon::MuonTrackCleaner::CleaningState::largePullPseudoMeasurements
MeasSet largePullPseudoMeasurements
Definition: MuonTrackCleaner.h:155
Muon::MuonTrackCleaner::CleaningState::nscatterers
unsigned int nscatterers
Definition: MuonTrackCleaner.h:161
MaterialEffectsOnTrack.h
TgcClusterOnTrack.h
Muon::MuonTrackCleaner::CleaningState::numberOfCleanedCompROTs
unsigned int numberOfCleanedCompROTs
Definition: MuonTrackCleaner.h:171
Trk::PseudoMeasurementOnTrack
Class to handle pseudo-measurements in fitters and on track objects.
Definition: PseudoMeasurementOnTrack.h:44
Muon::RpcPrepData::time
float time() const
Returns the time.
Definition: RpcPrepData.h:197
Muon::MuonTrackCleaner::CleaningState::hasVertexConstraint
bool hasVertexConstraint
Definition: MuonTrackCleaner.h:173
Muon::MuonTrackCleaner::unremoveHits
static void unremoveHits(ChamberRemovalOutput &result)
Definition: MuonTrackCleaner.cxx:1546
Muon::MuonTrackCleaner::init
void init(const EventContext &ctx, const Trk::Track &track, CleaningState &state) const
init cleaner
Definition: MuonTrackCleaner.cxx:796
PixelModuleFeMask_create_db.remove
string remove
Definition: PixelModuleFeMask_create_db.py:83
Trk::ParticleHypothesis
ParticleHypothesis
Definition: ParticleHypothesis.h:25
GeoPrimitives.h
Muon::MuonTrackCleaner::CleaningState::chambersToBeRemoved
PullChVec chambersToBeRemoved
Definition: MuonTrackCleaner.h:188
Trk::MaterialEffectsOnTrack
represents the full description of deflection and e-loss of a track in material.
Definition: MaterialEffectsOnTrack.h:40
MuonTSOSHelper.h
MMReadoutElement.h
RpcClusterOnTrack.h
Trk::ScatteringAngles::sigmaDeltaTheta
double sigmaDeltaTheta() const
returns the
Definition: ScatteringAngles.h:100
Muon::MuonTrackCleaner::ChamberRemovalOutput::removedHits
std::vector< MCTBCleaningInfo * > removedHits
Definition: MuonTrackCleaner.h:104
Muon::MuonTrackCleaner::CleaningState::nIdHits
unsigned int nIdHits
Definition: MuonTrackCleaner.h:166
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::MCTBCleaningInfo::resPull
std::optional< Trk::ResidualPull > resPull
Definition: MuonTrackCleaner.h:59
lumiFormat.i
int i
Definition: lumiFormat.py:92
Muon::MuonStationIndex::BM
@ BM
Definition: MuonStationIndex.h:25
Muon::MuonTrackCleaner::CleaningState::chamberLayerStatistics
std::map< MuonStationIndex::ChIndex, ChamberLayerStatistics > chamberLayerStatistics
Definition: MuonTrackCleaner.h:194
Muon::MuonTrackCleaner::EtaPhiHits::neta
int neta
Definition: MuonTrackCleaner.h:125
Identifier
Definition: DetectorDescription/Identifier/Identifier/Identifier.h:32
beamspotman.n
n
Definition: beamspotman.py:731
Muon::MuonTrackCleaner::m_trackFitter
ToolHandle< Trk::ITrackFitter > m_trackFitter
Definition: MuonTrackCleaner.h:281
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Muon::MuonTrackCleaner::MCTBCleaningInfo::chId
Identifier chId
Definition: MuonTrackCleaner.h:48
urldecode::states
states
Definition: urldecode.h:39
LArG4ShowerLibProcessing.hits
hits
Definition: LArG4ShowerLibProcessing.py:136
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
Trk::RIGHT
@ RIGHT
the drift radius is positive (see Trk::AtaStraightLine)
Definition: DriftCircleSide.h:22
Muon::MuonTrackCleaner::EtaPhiHits
Definition: MuonTrackCleaner.h:123
Muon::MuonTrackCleaner::MCTBCleaningInfo::pars
const Trk::TrackParameters * pars
Definition: MuonTrackCleaner.h:58
res
std::pair< std::vector< unsigned int >, bool > res
Definition: JetGroupProductTest.cxx:14
Muon::MuonTrackCleaner::CleaningState::chamberRemovalExclusionList
std::set< Identifier > chamberRemovalExclusionList
Definition: MuonTrackCleaner.h:196
CscClusterOnTrack.h
Muon::MuonTrackCleaner::m_use_slFit
Gaudi::Property< bool > m_use_slFit
Definition: MuonTrackCleaner.h:317
Muon::MuonTrackCleaner::printStates
void printStates(Trk::Track *track) const
Definition: MuonTrackCleaner.cxx:1551
CscReadoutElement.h
Trk::EnergyLoss::deltaE
double deltaE() const
returns the
Muon::MuonTrackCleaner::m_adcCut
Gaudi::Property< double > m_adcCut
Definition: MuonTrackCleaner.h:315
PseudoMeasurementOnTrack.h
python.StandardJetMods.pull
pull
Definition: StandardJetMods.py:264
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Muon::MuonTrackCleaner::ChamberPullInfo
Definition: MuonTrackCleaner.h:113
Trk::ParametersBase
Definition: ParametersBase.h:55
Muon::MuonTrackCleaner::m_recoverOutliers
Gaudi::Property< bool > m_recoverOutliers
Definition: MuonTrackCleaner.h:311
Trk::muon
@ muon
Definition: ParticleHypothesis.h:28
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
DataVector< const Trk::TrackStateOnSurface >
Trk::ResidualPull::HitOnly
@ HitOnly
RP with biased track state, but pull from hit only.
Definition: ResidualPull.h:56
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:660
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:292
Trk::distPhi
@ distPhi
Definition: ParamDefs.h:56
MuonTrackCleaner.h
Trk::MeasurementBase::localCovariance
const Amg::MatrixX & localCovariance() const
Interface method to get the localError.
Definition: MeasurementBase.h:138
Muon::MuonStationIndex::ChUnknown
@ ChUnknown
Definition: MuonStationIndex.h:16
trapping_fp.h
Tell the compiler to optimize assuming that FP may trap.
Muon::MMClusterOnTrack
Class to represent calibrated clusters formed from TGC strips.
Definition: MMClusterOnTrack.h:26
Trk::MeasurementBase
Definition: MeasurementBase.h:58
Muon::RpcClusterOnTrack::prepRawData
virtual const RpcPrepData * prepRawData() const override final
Returns the RpcPrepData - is a TRT_DriftCircle in this scope.
Definition: RpcClusterOnTrack.h:127
Muon::CompetingMuonClustersOnTrack::numberOfContainedROTs
unsigned int numberOfContainedROTs() const
Number of RIO_OnTracks to be contained by this CompetingRIOsOnTrack.
Definition: CompetingMuonClustersOnTrack.h:178
Muon::MuonTrackCleaner::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: MuonTrackCleaner.h:297
Trk::Track::perigeeParameters
const Perigee * perigeeParameters() const
return Perigee.
Definition: Tracking/TrkEvent/TrkTrack/src/Track.cxx:163
Muon::MuonTrackCleaner::CleaningState::hasOfBoundsOutliers
bool hasOfBoundsOutliers
Definition: MuonTrackCleaner.h:172
Muon::MuonTrackCleaner::ChamberRemovalOutput::chId
Identifier chId
Definition: MuonTrackCleaner.h:103
Muon::MuonTrackCleaner::CleaningState
Definition: MuonTrackCleaner.h:151
Muon::MuonTrackCleaner::SortChamberRemovalResultByChi2Ndof
Definition: MuonTrackCleaner.h:106
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:191
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::MdtDriftCircleOnTrack
This class represents the corrected MDT measurements, where the corrections include the effects of wi...
Definition: MdtDriftCircleOnTrack.h:37
Muon::MuonTrackCleaner::PullChamberCit
PullChamberMap::const_iterator PullChamberCit
Definition: MuonTrackCleaner.h:121
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
Muon::MuonTrackCleaner::m_printer
ToolHandle< Muon::MuonEDMPrinterTool > m_printer
Definition: MuonTrackCleaner.h:296
Muon::MuonTrackCleaner::CleaningState::measInfo
InfoVec measInfo
Definition: MuonTrackCleaner.h:152
Muon::MuonTrackCleaner::ChamberLayerStatistics::noutliers
unsigned int noutliers
Definition: MuonTrackCleaner.h:143
Muon::MuonTrackCleaner::EtaPhiPerChamberIt
EtaPhiPerChamberMap::iterator EtaPhiPerChamberIt
Definition: MuonTrackCleaner.h:129
Muon::CompetingMuonClustersOnTrack::containedROTs
const std::vector< const MuonClusterOnTrack * > & containedROTs() const
returns the vector of SCT_ClusterOnTrack objects .
Definition: CompetingMuonClustersOnTrack.h:184
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
LocalParameters.h
Muon::MuonTrackCleaner::ChamberPullInfo::maxPull
double maxPull
Definition: MuonTrackCleaner.h:116
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
Muon::MuonTrackCleaner::ChamberRemovalOutput::track
std::unique_ptr< Trk::Track > track
Definition: MuonTrackCleaner.h:102
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:300
Muon::MuonTrackCleaner::CleaningState::pullSumPerChamberPhi
PullChamberMap pullSumPerChamberPhi
Definition: MuonTrackCleaner.h:185
eflowRec::phiIndex
unsigned int phiIndex(float phi, float binsize)
calculate phi index for a given phi
Definition: EtaPhiLUT.cxx:23
Muon::MuonTrackCleaner::MCTBCleaningInfo::useInFit
int useInFit
Definition: MuonTrackCleaner.h:50
Muon::MuonTrackCleaner::clean
std::unique_ptr< Trk::Track > clean(const Trk::Track &track, const EventContext &ctx) const override
clean a track, returns a pointer to a new track if successfull.
Definition: MuonTrackCleaner.cxx:69
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:1411
CylinderBounds.h
Muon::MuonTrackCleaner::CleaningState::numberOfFlippedMdts
unsigned int numberOfFlippedMdts
Definition: MuonTrackCleaner.h:170
Trk::ParametersBase::momentum
const Amg::Vector3D & momentum() const
Access method for the momentum.
Muon::CompetingMuonClustersOnTrack::rioOnTrack
const MuonClusterOnTrack & rioOnTrack(unsigned int) const
returns the RIO_OnTrack (also known as ROT) objects depending on the integer
Definition: CompetingMuonClustersOnTrack.h:190
Muon::MuonTrackCleaner::EtaPhiHits::nphi
int nphi
Definition: MuonTrackCleaner.h:126
Trk::ResidualPull::Biased
@ Biased
RP with track state including the hit.
Definition: ResidualPull.h:55
Muon::MuonTrackCleaner::initialize
StatusCode initialize() override
AlgTool initialize.
Definition: MuonTrackCleaner.cxx:41
Muon::MuonTrackCleaner::CleaningState::hitsPerChamber
EtaPhiPerChamberMap hitsPerChamber
Definition: MuonTrackCleaner.h:181
Trk::MaterialEffectsOnTrack::energyLoss
const EnergyLoss * energyLoss() const
returns the energy loss object.
Muon::MuonTrackCleaner::checkInnerConstraint
bool checkInnerConstraint(CleaningState &state) const
Definition: MuonTrackCleaner.cxx:1528
Muon::MuonTrackCleaner::CleaningState::pullSum
ChamberPullInfo pullSum
Definition: MuonTrackCleaner.h:177
Muon::MuonTrackCleaner::fitTrack
std::unique_ptr< Trk::Track > fitTrack(const EventContext &ctx, Trk::Track &track, Trk::ParticleHypothesis pHyp, bool slFit) const
Definition: MuonTrackCleaner.cxx:1558
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...
Muon::MuonTrackCleaner::CleaningState::nPhiConstraints
unsigned int nPhiConstraints
Definition: MuonTrackCleaner.h:168
Muon::MuonTrackCleaner::MCTBCleaningInfo::id
Identifier id
Definition: MuonTrackCleaner.h:47
Muon::MuonStationIndex::BO
@ BO
Definition: MuonStationIndex.h:25
Muon::MuonTrackCleaner::CleaningState::pullSumPerChamberEta
PullChamberMap pullSumPerChamberEta
Definition: MuonTrackCleaner.h:186
Muon::MuonTrackCleaner::CleaningState::pullSumPerChamber
PullChamberMap pullSumPerChamber
Definition: MuonTrackCleaner.h:184
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Muon::MuonTrackCleaner::m_onlyUseHitErrorInRecovery
Gaudi::Property< bool > m_onlyUseHitErrorInRecovery
Definition: MuonTrackCleaner.h:314
DEBUG
#define DEBUG
Definition: page_access.h:11
Trk::MaterialEffectsOnTrack::scatteringAngles
const ScatteringAngles * scatteringAngles() const
returns the MCS-angles object.
Muon::MuonTrackCleaner::ChamberPullInfo::nhits
int nhits
Definition: MuonTrackCleaner.h:117
AthCommonMsg< AlgTool >::msg
MsgStream & msg() const
Definition: AthCommonMsg.h:24
MagField::AtlasFieldCache
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h)
Definition: AtlasFieldCache.h:43
Trk::RIO_OnTrack::identify
virtual Identifier identify() const final
return the identifier -extends MeasurementBase
Definition: RIO_OnTrack.h:155
Muon::MuonTrackCleaner::m_iterate
Gaudi::Property< bool > m_iterate
Definition: MuonTrackCleaner.h:316
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:178
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
Muon::MuonStationIndex::ChIndex
ChIndex
enum to classify the different chamber layers in the muon spectrometer
Definition: MuonStationIndex.h:15
Muon::MuonStationIndex::StIndex
StIndex
enum to classify the different station layers in the muon spectrometer
Definition: MuonStationIndex.h:23
TgcReadoutElement.h
Trk::LEFT
@ LEFT
the drift radius is negative (see Trk::AtaStraightLine)
Definition: DriftCircleSide.h:20
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
Muon::MuonTrackCleaner::ChamberPullInfo::pullSum
double pullSum
Definition: MuonTrackCleaner.h:115
Trk::ScatteringAngles::deltaTheta
double deltaTheta() const
returns the
Definition: ScatteringAngles.h:88
AthAlgTool
Definition: AthAlgTool.h:26
Muon::MuonTrackCleaner::CleaningState::noutliers
unsigned int noutliers
Definition: MuonTrackCleaner.h:163
Muon::MuonTrackCleaner::m_associationScaleFactor
Gaudi::Property< double > m_associationScaleFactor
Definition: MuonTrackCleaner.h:308
FitQuality.h
Muon::MuonTrackCleaner::m_mdtResiCut
Gaudi::Property< double > m_mdtResiCut
Definition: MuonTrackCleaner.h:306
error
Definition: IImpactPoint3dEstimator.h:70
Muon::MMClusterOnTrack::detectorElement
virtual const MuonGM::MMReadoutElement * detectorElement() const
Returns the detector element, assoicated with the PRD of this class.
Definition: MMClusterOnTrack.h:139
Muon::MuonTrackCleaner::CleaningState::outBoundsPerChamber
EtaPhiPerChamberMap outBoundsPerChamber
Definition: MuonTrackCleaner.h:182
Muon::MuonTrackCleaner::print
static std::string print(ChamberLayerStatistics &statistics)
Definition: MuonTrackCleaner.cxx:1501
Muon::MuonTrackCleaner::m_compRotCreator
ToolHandle< IMuonCompetingClustersOnTrackCreator > m_compRotCreator
Definition: MuonTrackCleaner.h:290
Trk::TrackStateOnSurface::Measurement
@ Measurement
This is a measurement, and will at least contain a Trk::MeasurementBase.
Definition: TrackStateOnSurface.h:101
Muon::MuonStationIndex::EM
@ EM
Definition: MuonStationIndex.h:26
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:239
Trk::StraightLineSurface
Definition: StraightLineSurface.h:51
Muon::MuonClusterOnTrack
Base class for Muon cluster RIO_OnTracks.
Definition: MuonClusterOnTrack.h:34
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:466
RpcReadoutElement.h