Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
MooTrackFitter.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "MooTrackFitter.h"
6 
32 #include "TrkGeometry/Layer.h"
38 #include "TrkTrack/Track.h"
39 #include "TrkTrack/TrackInfo.h"
42 
43 namespace {
44  const double FiftyOverSqrt12 = 50. / std::sqrt(12);
45 
46  struct Unowned{
47  void operator()(const Muon::MuonSegment*) const {};
48  };
49 }
50 namespace Muon {
51  using namespace MuonStationIndex;
52 
53  MooTrackFitter::MooTrackFitter(const std::string& t, const std::string& n, const IInterface* p) : AthAlgTool(t, n, p) {
54  declareInterface<MooTrackFitter>(this);
55  }
56 
58  ATH_CHECK(m_propagator.retrieve());
59  ATH_CHECK(m_trackSummaryTool.retrieve());
60  ATH_CHECK(m_cleaner.retrieve());
61  ATH_CHECK(m_overlapResolver.retrieve());
62  ATH_CHECK(m_trackFitter.retrieve());
63  ATH_CHECK(m_momentumEstimator.retrieve());
64  ATH_CHECK(m_idHelperSvc.retrieve());
65  ATH_CHECK(m_edmHelperSvc.retrieve());
66  ATH_CHECK(m_hitHandler.retrieve());
67  ATH_CHECK(m_printer.retrieve());
68 
69  // Configuration of the material effects
72 
73  ATH_CHECK(m_trackToSegmentTool.retrieve());
74  ATH_CHECK(m_phiHitSelector.retrieve());
75 
76  return StatusCode::SUCCESS;
77  }
78 
80  double nfits = m_nfits.load() > 0 ? m_nfits.load() : 1.;
81  double nfailedExtractInital = m_nfailedExtractInital / nfits;
82  double nfailedMinMaxPhi = m_nfailedMinMaxPhi / nfits;
83  double nfailedParsInital = m_nfailedParsInital / nfits;
84  double nfailedExtractCleaning = m_nfailedExtractCleaning / nfits;
85  double nfailedFakeInitial = m_nfailedFakeInitial / nfits;
86  double nfailedTubeFit = m_nfailedTubeFit / nfits;
87  double noPerigee = m_noPerigee / nfits;
88  double nlowMomentum = m_nlowMomentum / nfits;
89  double nfailedExtractPrecise = m_nfailedExtractPrecise / nfits;
90  double nfailedFakePrecise = m_nfailedFakePrecise / nfits;
91  double nfailedFitPrecise = m_nfailedFitPrecise / nfits;
92  double nsuccess = m_nsuccess / nfits;
93  ATH_MSG_INFO(" Summarizing statistics: nfits "
94  << m_nfits << std::endl
95  << "| extract | phi range | startPars | clean phi | add fake | fit | no perigee | low mom | extract | "
96  "add fake | final fit | passed |"
97  << std::endl
98  << std::setprecision(2) << std::setw(12) << nfailedExtractInital << std::setw(12) << nfailedMinMaxPhi << std::setw(12)
99  << nfailedParsInital << std::setw(12) << nfailedExtractCleaning << std::setw(12) << nfailedFakeInitial << std::setw(12)
100  << nfailedTubeFit << std::setw(13) << noPerigee << std::setw(12) << nlowMomentum << std::setw(12)
101  << nfailedExtractPrecise << std::setw(12) << nfailedFakePrecise << std::setw(12) << nfailedFitPrecise << std::setw(12)
102  << nsuccess);
103 
104  return StatusCode::SUCCESS;
105  }
106 
108  if (entry.hits().size() < entry.etaHits().size()) {
109  ATH_MSG_WARNING(" Corrupt Entry: more eta hits than hits! ");
110  return true;
111  }
112  if (entry.etaHits().size() < 3) { return (entry.ncscHitsEta < 2); }
113  return false;
114  }
115 
116  std::unique_ptr<Trk::Track> MooTrackFitter::refit(const EventContext& ctx, const MuPatTrack& trkCan) const {
117 
118  // internal representation of the track in fitter
119  FitterData fitterData;
120 
121  // copy hit list
122  fitterData.hitList = trkCan.hitList();
123 
124  // extract hits from hit list and add them to fitterData
125  if (!extractData(fitterData, true)) return nullptr;
126 
127  // create start parameters
128  const Trk::Perigee* pp = trkCan.track().perigeeParameters();
129  if (!pp) return nullptr;
130 
131  // fit track
132  std::unique_ptr<Trk::Track> track = fit(ctx, *pp, fitterData.measurements, Trk::muon, false);
133 
134  if (track) {
135  // clean and evaluate track
136  std::set<Identifier> excludedChambers;
137  std::unique_ptr<Trk::Track> cleanTrack = cleanAndEvaluateTrack(ctx, *track, excludedChambers);
138  if (cleanTrack && !(*cleanTrack->perigeeParameters() == *track->perigeeParameters())) track.swap(cleanTrack);
139  } else {
140  ATH_MSG_DEBUG(" Fit failed ");
141  }
142  return track;
143  }
144 
145  std::unique_ptr<Trk::Track> MooTrackFitter::refit(const EventContext& ctx, const Trk::Track& track) const {
146  if (msgLvl(MSG::DEBUG)) {
147  const Trk::TrackStates* states = track.trackStateOnSurfaces();
148  int nStates = 0;
149  if (states) nStates = states->size();
150  msg(MSG::DEBUG) << MSG::DEBUG << "refit: fitting track with hits: " << nStates;
151  if (msgLvl(MSG::VERBOSE)) { msg(MSG::VERBOSE) << std::endl << m_printer->printMeasurements(track); }
152  msg(MSG::DEBUG) << endmsg;
153  }
154  // fit track
155  std::unique_ptr<Trk::Track> newTrack = m_trackFitter->fit(ctx,track, false, m_ParticleHypothesis);
156 
157  if (newTrack) {
158  // clean and evaluate track
159  std::set<Identifier> excludedChambers;
160  std::unique_ptr<Trk::Track> cleanTrack = cleanAndEvaluateTrack(ctx, *newTrack, excludedChambers);
161 
162  if (cleanTrack) {
163  // check whether cleaner returned same track, if not delete old track
164  if (!(*cleanTrack->perigeeParameters() == *newTrack->perigeeParameters())) newTrack.swap(cleanTrack);
165  } else {
166  ATH_MSG_DEBUG(" Refit failed, rejected by cleaner ");
167  newTrack.reset();
168  }
169  } else {
170  ATH_MSG_DEBUG(" Refit failed ");
171  }
172 
173  return newTrack;
174  }
175 
176  std::unique_ptr<Trk::Track> MooTrackFitter::fit(const EventContext& ctx, const MuPatCandidateBase& entry1, const MuPatCandidateBase& entry2,
177  const PrepVec& externalPhiHits) const {
178  ++m_nfits;
179  // internal representation of the track in fitter
180  FitterData fitterData;
181 
182  // extract hits and geometrical information
183  if (!extractData(entry1, entry2, fitterData)) {
184  ATH_MSG_DEBUG(" Failed to extract data for initial fit");
185  return nullptr;
186  }
188 
189  // get the minimum and maximum phi compatible with all eta hits, don't use for cosmics
190  if (!m_cosmics && !getMinMaxPhi(fitterData)) {
191  ATH_MSG_DEBUG(" Phi range check failed, candidate stations not pointing. Will not fit track");
192  return nullptr;
193  }
194 
196 
197  // create start parameters
198  createStartParameters(ctx, fitterData);
199  std::unique_ptr<Trk::Perigee>& startPars = fitterData.startPars;
200  if (!startPars) {
201  ATH_MSG_DEBUG(" Creation of start parameters failed ");
202  return nullptr;
203  }
204  ATH_MSG_VERBOSE("Extracted start parameters: "<<Amg::toString(startPars->momentum().unit())<< " "<<Amg::toString(startPars->position()));
206 
207  // clean phi hits and reevaluate hits. Do not run for cosmics
208  bool hasCleaned = m_cleanPhiHits && cleanPhiHits(ctx, startPars->momentum().mag(), fitterData, externalPhiHits);
209  if (hasCleaned) {
210  ATH_MSG_DEBUG(" Cleaned phi hits, re-extracting hits");
211  bool usePrecise = m_usePreciseHits || (fitterData.firstHasMomentum || fitterData.secondHasMomentum);
212  ATH_MSG_VERBOSE("Call extract data with usePrecise "<<usePrecise);
213  if (!extractData(fitterData, usePrecise)) {
214  ATH_MSG_DEBUG(" Failed to extract data after phi hit cleaning");
215  return nullptr;
216  }
217  }
219 
220  // check whether there are enough phi constraints, if not add fake phi hits
221  if (!addFakePhiHits(ctx, fitterData, *startPars)) {
222  ATH_MSG_DEBUG(" Failed to add fake phi hits for precise fit");
223  return nullptr;
224  }
226 
227  // fit track with broad errors, no material
228  bool doPreFit = m_usePrefit;
230  if (fitterData.firstHasMomentum || fitterData.secondHasMomentum) doPreFit = false;
231  if (!doPreFit) particleType = Trk::muon;
232 
233  std::unique_ptr<Trk::Track> track = fit(ctx, *startPars, fitterData.measurements, particleType, doPreFit);
234 
235  if (!track) {
236  ATH_MSG_DEBUG(" Fit failed ");
237  return nullptr;
238  }
240 
241  // create start parameters
242  const Trk::Perigee* pp = track->perigeeParameters();
243  if (!pp) {
244  ATH_MSG_DEBUG(" Track without perigee parameters, exit ");
245  return nullptr;
246  }
247  ++m_noPerigee;
248 
249  if (!m_slFit && !validMomentum(*pp)) {
250  ATH_MSG_VERBOSE(" Low momentum, rejected ");
251  return nullptr;
252  }
253  ++m_nlowMomentum;
254 
255  if (!fitterData.firstHasMomentum && !fitterData.secondHasMomentum && doPreFit) {
256  ATH_MSG_DEBUG(" Performing second fit ");
257 
258  // refit with precise errors
259  FitterData fitterDataRefit{};
260  fitterDataRefit.startPars.reset(pp->clone());
261  fitterDataRefit.firstIsTrack = fitterData.firstIsTrack;
262  fitterDataRefit.secondIsTrack = fitterData.secondIsTrack;
263  fitterDataRefit.firstHasMomentum = fitterData.firstHasMomentum;
264  fitterDataRefit.secondHasMomentum = fitterData.secondHasMomentum;
265  fitterDataRefit.avePhi = fitterData.avePhi;
266  fitterDataRefit.phiMin = fitterData.phiMin;
267  fitterDataRefit.phiMax = fitterData.phiMax;
268  fitterDataRefit.firstEntry = fitterData.firstEntry;
269  fitterDataRefit.secondEntry = fitterData.secondEntry;
270  fitterDataRefit.hitList = fitterData.hitList;
271 
272  // extract hits from hit list and add them to fitterData
273  if (!extractData(fitterDataRefit, true)) {
274  ATH_MSG_DEBUG(" Failed to extract data for precise fit");
275  return nullptr;
276  }
278 
279  // check whether there are enough phi constraints, if not add fake phi hits
280  if (!addFakePhiHits(ctx, fitterDataRefit, *startPars)) {
281  ATH_MSG_DEBUG(" Failed to add fake phi hits for precise fit");
282  return nullptr;
283  }
285 
286  // fit track
287  std::unique_ptr<Trk::Track> newTrack = fit(ctx, *pp, fitterDataRefit.measurements, Trk::muon, false);
288  if (newTrack)
289  track.swap(newTrack);
290  else if (!m_allowFirstFit) {
291  ATH_MSG_DEBUG(" Precise fit failed ");
292  return nullptr;
293  } else {
294  ATH_MSG_DEBUG(" Precise fit failed, keep fit with broad errors");
295  }
297 
298  fitterData.garbage.insert(fitterData.garbage.end(), std::make_move_iterator(fitterDataRefit.garbage.begin()),
299  std::make_move_iterator(fitterDataRefit.garbage.end()));
300  fitterDataRefit.garbage.clear();
301  }
302 
303  if (track) {
304  // clean and evaluate track
305  std::set<Identifier> excludedChambers;
306  if (fitterData.firstIsTrack && !fitterData.secondIsTrack) {
307  excludedChambers = fitterData.secondEntry->chamberIds();
308  ATH_MSG_VERBOSE(" Using exclusion list of second entry for cleaning");
309  } else if (!fitterData.firstIsTrack && fitterData.secondIsTrack) {
310  excludedChambers = fitterData.firstEntry->chamberIds();
311  ATH_MSG_VERBOSE(" Using exclusion list of first entry for cleaning");
312  }
313  if (!excludedChambers.empty()) { ATH_MSG_DEBUG(" Using exclusion list for cleaning"); }
314  std::unique_ptr<Trk::Track> cleanTrack = cleanAndEvaluateTrack(ctx, *track, excludedChambers);
315  if (cleanTrack) {
316  if (!(*cleanTrack->perigeeParameters() == *track->perigeeParameters())) track.swap(cleanTrack);
317  } else
318  track.reset();
319  }
320 
321  if (track) ++m_nsuccess;
322 
323  if (msgLvl(MSG::DEBUG) && track) msg(MSG::DEBUG) << MSG::DEBUG << " Track found " << endmsg;
324  return track;
325  }
326 
328  MooTrackFitter::FitterData& fitterData) const {
329  // sanity checks on the entries
330  if (corruptEntry(entry1)) {
331  ATH_MSG_DEBUG(" corrupt first entry, cannot perform fit: eta hits " << entry1.etaHits().size());
332  return false;
333  }
334  if (corruptEntry(entry2)) {
335  ATH_MSG_DEBUG(" corrupt second entry, cannot perform fit: eta hits " << entry2.etaHits().size());
336  return false;
337  }
338  // are we in the endcap region?
339  bool isEndcap = entry1.hasEndcap() || entry2.hasEndcap();
340 
341 
342  // measurement sorting function
343  SortMeasurementsByPosition sortMeasurements(isEndcap);
344 
345  bool entry1IsFirst = sortMeasurements(entry1.hits().front(), entry2.hits().front());
346  if (m_cosmics) {
347  DistanceToPars distToPars(&entry1.entryPars());
348  double distToSecond = distToPars(entry2.entryPars().position());
349  if (distToSecond < 0) entry1IsFirst = false;
350  ATH_MSG_DEBUG(" first entry dir " << Amg::toString(entry1.entryPars().momentum())
351  << " pos " << Amg::toString(entry1.entryPars().position()) << " second "
352  << Amg::toString(entry2.entryPars().position()) << " dist " << distToSecond);
353  }
354  const MuPatCandidateBase& firstEntry = entry1IsFirst ? entry1 : entry2;
355  const MuPatCandidateBase& secondEntry = entry1IsFirst ? entry2 : entry1;
356 
357  fitterData.firstEntry = &firstEntry;
358  fitterData.secondEntry = &secondEntry;
359 
360  // check whether we are dealing with a track or a segment
361  if (dynamic_cast<const MuPatTrack*>(fitterData.firstEntry)) {
362  fitterData.firstIsTrack = true;
363  fitterData.firstHasMomentum = fitterData.firstEntry->hasMomentum();
364  }
365  if (dynamic_cast<const MuPatTrack*>(fitterData.secondEntry)) {
366  fitterData.secondIsTrack = true;
367  fitterData.secondHasMomentum = fitterData.secondEntry->hasMomentum();
368  }
369  // merge hitLists and add them to the fitterData
370  fitterData.hitList = m_hitHandler->merge(entry1.hitList(), entry2.hitList());
371 
372  bool usePrecise = m_usePreciseHits || (fitterData.firstHasMomentum || fitterData.secondHasMomentum);
373  if (msgLvl(MSG::DEBUG)) {
374  msg(MSG::DEBUG) << MSG::DEBUG << " entering fitter: etaHits, first entry: ";
375  if (fitterData.firstIsTrack)
376  msg(MSG::DEBUG) << " track ";
377  else
378  msg(MSG::DEBUG) << " segment ";
379  msg(MSG::DEBUG) << fitterData.firstEntry->etaHits().size() << std::endl
380  << m_hitHandler->print(fitterData.firstEntry->hitList()) << std::endl
381  << " second entry: ";
382  if (fitterData.secondIsTrack)
383  msg(MSG::DEBUG) << " track ";
384  else
385  msg(MSG::DEBUG) << " segment ";
386  msg(MSG::DEBUG) << fitterData.secondEntry->etaHits().size() << std::endl
387  << m_hitHandler->print(fitterData.secondEntry->hitList()) << endmsg;
388  }
389 
390  if (msgLvl(MSG::DEBUG)) {
391  msg(MSG::DEBUG) << MSG::DEBUG << " merged hit lists, new list size: " << fitterData.hitList.size();
392  if (usePrecise) msg(MSG::DEBUG) << " using precise errors" << endmsg;
393  if (msgLvl(MSG::VERBOSE)) msg(MSG::DEBUG) << std::endl << m_hitHandler->print(fitterData.hitList);
394  msg(MSG::DEBUG) << endmsg;
395  }
396 
397  return extractData(fitterData, usePrecise);
398  }
399 
400  bool MooTrackFitter::extractData(MooTrackFitter::FitterData& fitterData, bool usePreciseHits) const {
401  ATH_MSG_DEBUG(" extracting hits from hit list, using " << (usePreciseHits ? "precise measurements" : "broad measurements"));
402 
403  MuPatHitList& hitList = fitterData.hitList;
404  // make sure the vector is sufficiently large
405  unsigned int nhits = hitList.size();
406 
407  fitterData.measurements.clear();
408  fitterData.firstLastMeasurements.clear();
409  fitterData.etaHits.clear();
410  fitterData.phiHits.clear();
411  fitterData.measurements.reserve(nhits);
412  fitterData.firstLastMeasurements.reserve(nhits);
413 
414  if (usePreciseHits && fitterData.startPars) removeSegmentOutliers(fitterData);
415 
416  StIndex firstStation = StIndex::StUnknown;
417  ChIndex currentChIndex = ChIndex::ChUnknown;
418  bool currentMeasPhi = false;
419  MuPatHitPtr previousHit{nullptr};
420 
421  // loop over hit list
422  for (const MuPatHitPtr& hit : hitList) {
423  const Identifier& id = hit->info().id;
424  if (hit->info().status != MuPatHit::OnTrack || !id.is_valid()) {
425  ATH_MSG_VERBOSE("Discard outlier "<<m_idHelperSvc->toString(id));
426  continue;
427  }
428  // in theory, there are only MuPatHit objects for MS hits
429  if (!m_idHelperSvc->isMuon(id)) {
430  ATH_MSG_WARNING("given Identifier " << id.get_compact() << " (" << m_idHelperSvc->toString(id)
431  << ") is not a muon Identifier, continuing");
432  continue;
433  }
434 
435  ChIndex chIndex = m_idHelperSvc->chamberIndex(id);
437  fitterData.stations.insert(stIndex);
438 
439  if (firstStation == StIndex::StUnknown) {
440  firstStation = stIndex;
441  }
442 
443  const bool measuresPhi = hit->info().measuresPhi;
444 
445  if (!m_idHelperSvc->isTgc(id) && !measuresPhi) {
446  const bool isSmall = m_idHelperSvc->isSmallChamber(id);
447  SmallLargeChambers& stCount = fitterData.smallLargeChambersPerStation[stIndex];
448  stCount.first += isSmall;
449  stCount.second += !isSmall;
450  }
451 
452  bool isEndcap = m_idHelperSvc->isEndcap(id);
453  fitterData.hasEndcap |= isEndcap;
454  fitterData.hasBarrel |= !isEndcap;
455 
456  const Trk::MeasurementBase* meas = usePreciseHits ? &hit->preciseMeasurement() : &hit->broadMeasurement();
457 
458  // special treatment of hits in first stations on the track to stabalise the track fit
459  if (!usePreciseHits && m_preciseFirstStation) { meas = &hit->preciseMeasurement(); }
460 
461  if (measuresPhi)
462  fitterData.phiHits.push_back(meas);
463  else
464  fitterData.etaHits.push_back(meas);
465 
466  if (msgLvl(MSG::DEBUG)) {
467  double rDrift = meas->localParameters()[Trk::locR];
468  double rError = Amg::error(meas->localCovariance(), Trk::locR);
469  if (usePreciseHits && m_idHelperSvc->isMdt(id) && std::abs(rDrift) < 0.01 && rError > 4.) {
470  ATH_MSG_WARNING(" MDT hit error broad but expected precise error ");
471  }
472  }
473 
474  fitterData.measurements.push_back(meas);
475 
476  if (!measuresPhi && m_idHelperSvc->isTrigger(id)) continue;
477 
478  if (!previousHit) {
479  currentChIndex = chIndex;
480  currentMeasPhi = measuresPhi;
481  fitterData.firstLastMeasurements.push_back(&hit->broadMeasurement());
482  } else if (currentChIndex == chIndex && currentMeasPhi == measuresPhi) {
483  previousHit = hit;
484  } else {
485  currentChIndex = chIndex;
486  currentMeasPhi = measuresPhi;
487  previousHit = hit;
488  fitterData.firstLastMeasurements.push_back(&hit->broadMeasurement());
489  }
490  }
491 
492  // add last hit if not already inserted
493  if (previousHit && &previousHit->broadMeasurement() != fitterData.firstLastMeasurements.back())
494  fitterData.firstLastMeasurements.push_back(&previousHit->broadMeasurement());
495 
496  // require at least 6 measurements on a track
497  if (fitterData.measurements.size() < 7) {
498  ATH_MSG_VERBOSE(" Too few measurements, cannot perform fit " << fitterData.measurements.size());
499  return false;
500  }
501 
502  // require at least 6 measurements on a track
503  if (fitterData.etaHits.size() < 7) {
504  ATH_MSG_VERBOSE(" Too few eta measurements, cannot perform fit " << fitterData.etaHits.size());
505  return false;
506  }
507 
508  ATH_MSG_VERBOSE(" Extracted measurements: total " << fitterData.measurements.size() << " eta "
509  << fitterData.etaHits.size() << " phi " << fitterData.phiHits.size()<< std::endl << m_printer->print(fitterData.measurements));
510  return true;
511  }
512 
513  bool MooTrackFitter::addFakePhiHits(const EventContext& ctx, MooTrackFitter::FitterData& fitterData, const Trk::TrackParameters& startpar) const {
514 
515  // check whether we have enough phi constraints
516  unsigned nphiConstraints = hasPhiConstrain(fitterData);
517 
518  // do we have enough constraints to fit the track
519  if (nphiConstraints >= 2) {
520  if (fitterData.firstEntry->stations().size() == 1 && fitterData.firstEntry->containsStation(StIndex::EI) &&
521  (fitterData.firstEntry->phiHits().empty() || (fitterData.firstEntry->containsChamber(ChIndex::CSS) ||
522  fitterData.firstEntry->containsChamber(ChIndex::CSL)))) {
523  ATH_MSG_VERBOSE( " Special treatment of the forward region: adding fake at ip ");
524  }
525  return true;
526  }
527 
528  // in case of a single station overlap fit, calculate a global position that is more or less located at
529  // the overlap. It is used to decide on which side of the tube the fake should be produced
530  std::unique_ptr<Amg::Vector3D> overlapPos;
531  std::unique_ptr<const Amg::Vector3D> phiPos;
532  if (fitterData.numberOfSLOverlaps() > 0 || (fitterData.numberOfSmallChambers() > 0 && fitterData.numberOfLargeChambers() > 0)) {
533  // in case of SL overlaps, pass average position of the two segments
534  // overlapPos = new Amg::Vector3D( 0.5*(fitterData.firstEntry->etaHits().front()->globalPosition() +
535  // fitterData.secondEntry->etaHits().front()->globalPosition()) );
536  overlapPos = std::make_unique<Amg::Vector3D>(1., 1., 1.);
537  double phi = fitterData.avePhi;
538  double theta = fitterData.secondEntry->etaHits().front()->globalPosition().theta();
539  if (m_cosmics) {
540  if (fitterData.firstEntry->hasSLOverlap()) {
541  theta = fitterData.firstEntry->entryPars().momentum().theta();
542  phi = fitterData.firstEntry->entryPars().momentum().phi();
543  } else {
544  theta = fitterData.secondEntry->entryPars().momentum().theta();
545  phi = fitterData.secondEntry->entryPars().momentum().phi();
546  }
547  }
548  Amg::setThetaPhi(*overlapPos, theta, phi);
549 
550  if (fitterData.startPars) {
551  phiPos = std::make_unique<Amg::Vector3D>(fitterData.startPars->momentum());
552  } else {
553  phiPos = std::make_unique<Amg::Vector3D>(*overlapPos);
554  }
555 
556  if (msgLvl(MSG::VERBOSE)) {
557  if (fitterData.numberOfSLOverlaps() > 0) {
558  if (fitterData.stations.size() == 1)
559  msg(MSG::VERBOSE) << " one station fit with SL overlap, using overlapPos " << *overlapPos << endmsg;
560  else
561  msg(MSG::VERBOSE) << " multi station fit with SL overlap, using overlapPos " << *overlapPos << endmsg;
562  } else if (fitterData.numberOfSmallChambers() > 0 && fitterData.numberOfLargeChambers() > 0) {
563  msg(MSG::VERBOSE) << " multi station fit, SL overlap not in same station, using overlapPos " << *overlapPos << endmsg;
564  } else
565  ATH_MSG_WARNING(" Unknown overlap type ");
566  }
567  }
568  // add fake phi hit on first and last measurement
569  if (fitterData.phiHits.empty()) {
570  const MuPatSegment* segInfo1 = dynamic_cast<const MuPatSegment*>(fitterData.firstEntry);
571  const MuPatSegment* segInfo2 = dynamic_cast<const MuPatSegment*>(fitterData.secondEntry);
572  if (segInfo1 && segInfo2 && fitterData.stations.size() == 1 && fitterData.numberOfSLOverlaps() == 1) {
573  // only perform SL overlap fit for MDT segments
574  Identifier chId = m_edmHelperSvc->chamberId(*segInfo1->segment);
575  if (!m_idHelperSvc->isMdt(chId)) return false;
576 
577  ATH_MSG_VERBOSE(" Special treatment for tracks with one station, a SL overlap and no phi hits ");
578 
580  m_overlapResolver->matchResult(ctx, *segInfo1->segment, *segInfo2->segment);
581 
582  if (!result.goodMatch()) {
583  ATH_MSG_VERBOSE(" Match failed ");
584  return false;
585  }
586  // create a track parameter for the segment
587  double locx1 = result.segmentResult1.positionInTube1;
588  double locy1 =
589  segInfo1->segment->localParameters().contains(Trk::locY) ? segInfo1->segment->localParameters()[Trk::locY] : 0.;
590  Trk::AtaPlane segPars1(locx1, locy1, result.phiResult.segmentDirection1.phi(), result.phiResult.segmentDirection1.theta(),
591  0., segInfo1->segment->associatedSurface());
592  // ownership retained, original code deleted exPars1
593  std::unique_ptr<Trk::TrackParameters> exPars1 = m_propagator->propagate(ctx,
594  segPars1, fitterData.measurements.front()->associatedSurface(), Trk::anyDirection,
595  false, m_magFieldProperties);
596  if (exPars1) {
597  Amg::Vector3D position = exPars1->position();
598  std::unique_ptr<Trk::MeasurementBase> fake =
599  createFakePhiForMeasurement(*fitterData.measurements.front(), &position, nullptr, 10.);
600  if (fake) {
601  fitterData.phiHits.push_back(fake.get());
602  fitterData.measurements.insert(fitterData.measurements.begin(), fake.get());
603  fitterData.firstLastMeasurements.insert(fitterData.firstLastMeasurements.begin(), fake.get());
604  fitterData.garbage.push_back(std::move(fake));
605  }
606  } else {
607  ATH_MSG_WARNING(" failed to create fake for first segment ");
608  return false;
609  }
610  double locx2 = result.segmentResult2.positionInTube1;
611  double locy2 =
612  segInfo2->segment->localParameters().contains(Trk::locY) ? segInfo2->segment->localParameters()[Trk::locY] : 0.;
613  Trk::AtaPlane segPars2(locx2, locy2, result.phiResult.segmentDirection2.phi(), result.phiResult.segmentDirection2.theta(),
614  0., segInfo2->segment->associatedSurface());
615  // ownership retained
616  auto exPars2 = m_propagator->propagate(ctx,
617  segPars2, fitterData.measurements.back()->associatedSurface(), Trk::anyDirection,
618  false, m_magFieldProperties);
619  if (exPars2) {
620  Amg::Vector3D position = exPars2->position();
621  std::unique_ptr<Trk::MeasurementBase> fake =
622  createFakePhiForMeasurement(*fitterData.measurements.back(), &position, nullptr, 10.);
623  if (fake) {
624  fitterData.phiHits.push_back(fake.get());
625  fitterData.measurements.push_back(fake.get());
626  fitterData.firstLastMeasurements.push_back(fake.get());
627  fitterData.garbage.push_back(std::move(fake));
628  }
629  } else {
630  ATH_MSG_WARNING(" failed to create fake for second segment ");
631  return false;
632  }
633  } else if (nphiConstraints == 0 || (fitterData.stations.size() == 1) ||
634  (nphiConstraints == 1 && fitterData.numberOfSLOverlaps() == 0 && fitterData.numberOfSmallChambers() > 0 &&
635  fitterData.numberOfLargeChambers() > 0)) {
636  {
637  std::unique_ptr<Trk::MeasurementBase> fake = createFakePhiForMeasurement(*fitterData.measurements.front(),
638  overlapPos.get(), phiPos.get(), 100.);
639  if (fake) {
640  fitterData.phiHits.push_back(fake.get());
641  fitterData.measurements.insert(fitterData.measurements.begin(), fake.get());
642  fitterData.firstLastMeasurements.insert(fitterData.firstLastMeasurements.begin(), fake.get());
643  fitterData.garbage.push_back(std::move(fake));
644  }
645 
646  }
647  {
648  std::unique_ptr<Trk::MeasurementBase> fake = createFakePhiForMeasurement(*fitterData.measurements.back(),
649  overlapPos.get(), phiPos.get(), 100.);
650  if (fake) {
651  fitterData.phiHits.push_back(fake.get());
652  fitterData.measurements.push_back(fake.get());
653  fitterData.firstLastMeasurements.push_back(fake.get());
654  fitterData.garbage.push_back(std::move(fake));
655  }
656  }
657 
658  } else if (fitterData.numberOfSLOverlaps() == 1) {
659  // there is one overlap, add the fake in the station without the overlap
660  ATH_MSG_VERBOSE(" Special treatment for tracks with one SL overlap and no phi hits ");
661 
662  StIndex overlapStation = StIndex::StUnknown;
664  SLStationMap::iterator it_end = fitterData.smallLargeChambersPerStation.end();
665  for (; it != it_end; ++it) {
666  if (it->second.first && it->second.second) {
667  overlapStation = it->first;
668  break;
669  }
670  }
671  if (overlapStation == StIndex::StUnknown) {
672  ATH_MSG_WARNING(" unexpected condition, unknown station type ");
673  return false;
674  }
675 
676  Identifier firstId = m_edmHelperSvc->getIdentifier(*fitterData.measurements.front());
677  if (!firstId.is_valid()) {
678  ATH_MSG_WARNING(" unexpected condition, first measurement has no identifier ");
679  return false;
680  }
681  MuonStationIndex::StIndex firstSt = m_idHelperSvc->stationIndex(firstId);
682  if (overlapStation == firstSt) {
683  ATH_MSG_VERBOSE(" Adding fake in same station as overlap ");
684 
685  // create pseudo at end of track
686  std::unique_ptr<Trk::MeasurementBase> fake = createFakePhiForMeasurement(*fitterData.measurements.back(),
687  overlapPos.get(), phiPos.get(), 100.);
688  if (fake) {
689  fitterData.phiHits.push_back(fake.get());
690  fitterData.measurements.push_back(fake.get());
691  fitterData.firstLastMeasurements.push_back(fake.get());
692  fitterData.garbage.push_back(std::move(fake));
693  }
694  } else {
695  ATH_MSG_VERBOSE(" Adding fake in other station as overlap ");
696  // create pseudo at begin of track
697  std::unique_ptr<Trk::MeasurementBase> fake = createFakePhiForMeasurement(*fitterData.measurements.front(),
698  overlapPos.get(), phiPos.get(), 100.);
699  if (fake) {
700  fitterData.phiHits.push_back(fake.get());
701  fitterData.measurements.insert(fitterData.measurements.begin(), fake.get());
702  fitterData.firstLastMeasurements.insert(fitterData.firstLastMeasurements.begin(), fake.get());
703  fitterData.garbage.push_back(std::move(fake));
704  }
705  }
706 
707  } else {
708  ATH_MSG_WARNING(" unexpected condition, cannot create fakes ");
709  return false;
710  }
711  } else {
712  // calculate distance between first phi/eta hit and last phi/eta hit
713  double distFirstEtaPhi =
714  (fitterData.measurements.front()->globalPosition() - fitterData.phiHits.front()->globalPosition()).mag();
715  double distLastEtaPhi = (fitterData.measurements.back()->globalPosition() - fitterData.phiHits.back()->globalPosition()).mag();
716 
717  // if there is one phi, use its phi + IP constraint to calculate position of fake
718  if (!overlapPos && m_seedWithAvePhi) {
719  phiPos = std::make_unique<Amg::Vector3D>(fitterData.phiHits.back()->globalPosition());
720  ATH_MSG_VERBOSE(" using pointing constraint to calculate fake phi hit ");
721  }
722 
723  // create a fake on the first and/or last MDT measurement if not near phi hits
724  const Trk::Surface *firstmdtsurf = nullptr, *lastmdtsurf = nullptr;
725  const Trk::TrackParameters *lastmdtpar = nullptr;
726  int indexfirst = 0, indexlast = (int)fitterData.measurements.size();
727  MuPatHitCit hitit = fitterData.hitList.begin();
728  for (; hitit != fitterData.hitList.end(); hitit++) {
729  if ((**hitit).info().measuresPhi) break;
730  if ((**hitit).info().type == MuPatHit::MDT || (**hitit).info().type == MuPatHit::sTGC) {
731  firstmdtsurf = &(**hitit).measurement().associatedSurface();
732  break;
733  }
734  indexfirst++;
735  }
736  hitit = fitterData.hitList.end();
737  hitit--;
738  for (; hitit != fitterData.hitList.begin(); hitit--) {
739  if ((**hitit).info().measuresPhi) break;
740  if ((**hitit).info().type == MuPatHit::MDT) {
741  lastmdtsurf = &(**hitit).measurement().associatedSurface();
742  lastmdtpar = &(**hitit).parameters();
743  break;
744  }
745  indexlast--;
746  }
749  indexlast = std::max(indexlast, 0);
750  bool phifromextrapolation = false;
751  if (!fitterData.secondEntry->phiHits().empty() || !fitterData.firstEntry->phiHits().empty()) phifromextrapolation = true;
752 
753  const Trk::Surface *firstphisurf = nullptr, *lastphisurf = nullptr;
754  Amg::Vector3D firstphinormal{Amg::Vector3D::Zero()}, lastphinormal{Amg::Vector3D::Zero()};
755  if (!fitterData.phiHits.empty()) {
756  firstphisurf = &fitterData.phiHits.front()->associatedSurface();
757  lastphisurf = &fitterData.phiHits.back()->associatedSurface();
758  firstphinormal = firstphisurf->normal();
759  lastphinormal = lastphisurf->normal();
760  if (firstphinormal.dot(startpar.momentum()) < 0) firstphinormal = -firstphinormal;
761  if (lastphinormal.dot(startpar.momentum()) < 0) lastphinormal = -lastphinormal;
762  }
763  if (lastmdtsurf && (!firstphisurf || (lastmdtsurf->center() - lastphisurf->center()).dot(lastphinormal) > 1000)) {
764  ATH_MSG_VERBOSE(" Adding fake at last hit: dist first phi/first eta " << distFirstEtaPhi << " dist last phi/last eta "
765  << distLastEtaPhi);
766  std::unique_ptr<Trk::MeasurementBase> fake{};
767  if (fitterData.secondEntry->hasSLOverlap() || phifromextrapolation) {
768  // this scope manages lifetime of mdtpar
769  std::unique_ptr<Trk::TrackParameters> mdtpar{};
770  if (fitterData.secondEntry->hasSLOverlap()){
771  mdtpar = lastmdtpar->uniqueClone();
772  } else {
773  mdtpar = m_propagator->propagateParameters(ctx, startpar, *lastmdtsurf,
775  }
776  if (mdtpar) {
777  Amg::MatrixX cov(1, 1);
778  cov(0, 0) = 100.;
779  fake = std::make_unique<Trk::PseudoMeasurementOnTrack>(
781  std::move(cov),
782  mdtpar->associatedSurface());
783 
784  }
785  } else {
786  fake = createFakePhiForMeasurement(*fitterData.measurements.back(), overlapPos.get(), phiPos.get(), 10.);
787  }
788  if (fake) {
789  fitterData.phiHits.push_back(fake.get());
790  fitterData.measurements.insert(fitterData.measurements.begin() + indexlast, fake.get());
791  fitterData.firstLastMeasurements.push_back(fake.get());
792  fitterData.garbage.push_back(std::move(fake));
793  }
794  }
795 
796  if (firstmdtsurf && (!firstphisurf || (firstmdtsurf->center() - firstphisurf->center()).dot(firstphinormal) < -1000)) {
797  ATH_MSG_VERBOSE(" Adding fake at first hit: dist first phi/first eta " << distFirstEtaPhi << " dist last phi/last eta "
798  << distLastEtaPhi);
799  std::unique_ptr<Trk::MeasurementBase> fake{};
800  if (phifromextrapolation) {
801  // lifetime of mdtpar managed here
802  auto mdtpar = m_propagator->propagateParameters(ctx, startpar,
803  *firstmdtsurf, Trk::oppositeMomentum, false, m_magFieldProperties);
804  if (mdtpar) {
805  Amg::MatrixX cov(1, 1);
806  cov(0, 0) = 100.;
807  fake = std::make_unique<Trk::PseudoMeasurementOnTrack>(
809  std::move(cov),
810  mdtpar->associatedSurface());
811  }
812  } else{
813  fake = createFakePhiForMeasurement(*fitterData.measurements.front(), overlapPos.get(), phiPos.get(), 100.);
814  }
815  if (fake) {
816  fitterData.phiHits.insert(fitterData.phiHits.begin(), fake.get());
817  fitterData.measurements.insert(fitterData.measurements.begin() + indexfirst, fake.get());
818  fitterData.firstLastMeasurements.insert(fitterData.firstLastMeasurements.begin(), fake.get());
819  fitterData.garbage.push_back(std::move(fake));
820  }
821  }
822  }
823  return true;
824  }
825 
826  std::unique_ptr<Trk::MeasurementBase> MooTrackFitter::createFakePhiForMeasurement(const Trk::MeasurementBase& meas,
827  const Amg::Vector3D* overlapPos, const Amg::Vector3D* phiPos,
828  double errPos) const {
829  // check whether measuring phi
830  Identifier id = m_edmHelperSvc->getIdentifier(meas);
831  if (id == Identifier()) {
832  ATH_MSG_WARNING(" Cannot create fake phi hit from a measurement without Identifier ");
833  return nullptr;
834  }
835  // check whether phi measurement, exit if true
836  if (m_idHelperSvc->measuresPhi(id)) {
837  ATH_MSG_WARNING(" Measurement is a phi measurement! " << m_idHelperSvc->toString(id));
838  return nullptr;
839  }
840 
841 
842  // the MDT and CSC hits are ROTs
843  const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(&meas);
844  if (!rot) {
845  const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(&meas);
846  // if also to a crot we cannot create a fake phi hit
847  if (!crot || crot->containedROTs().empty()) return nullptr;
848  rot = &crot->rioOnTrack(0);
849  }
850 
851 
852 
853  // get channel length and detector element
854  const Trk::TrkDetElementBase* detEl = rot->detectorElement();
855  if (!detEl) {
856  return nullptr;
857  }
858 
859  auto [halfLengthL, halfLengthR] = getElementHalfLengths(id, detEl);
860 
861  // error
862  std::optional<Amg::Vector2D> lpos = std::nullopt;
863  if (phiPos) {
864  Amg::Vector3D dir(1., 0., 0.);
865  Amg::setThetaPhi(dir, rot->globalPosition().theta(), phiPos->phi());
867  Trk::Perigee perigee(ip, dir, 0., ip);
868 
869  // special treatment of MDTs, intersect with detector element surface instead of wire surface to avoid problem with
870  // shift of phi angle after projection into wire frame
871  const Trk::Surface& measSurf = m_idHelperSvc->isMdt(id) ? detEl->surface() : meas.associatedSurface();
872 
874  if (!intersect.valid) {
875  ATH_MSG_WARNING(" Intersect with surface failed for measurement "
876  << m_printer->print(meas) << " position " << Amg::toString(ip) << " direction: phi " << dir.phi()
877  << " theta " << dir.theta() << " seed: phi " << phiPos->phi() << " theta "
878  << rot->globalPosition().theta());
879  } else {
880  // now get central phi position on surface of segment
881  lpos = meas.associatedSurface().globalToLocal(intersect.position, 3000.);
882 
883  }
884  } else {
885  // now get central phi position on surface of segment
886  lpos = meas.associatedSurface().globalToLocal(detEl->center(), 3000.);
887  if (!lpos){
888  lpos = meas.associatedSurface().globalToLocal(meas.associatedSurface().center(), 3000.);
889  }
890 
891  }
892 
893  if (!lpos) {
894  ATH_MSG_WARNING(" No local position, cannot make fake phi hit "<<m_idHelperSvc->toString(id)<<" "<<typeid(meas).name());
895  return nullptr;
896  }
897 
898  double ly = (*lpos)[Trk::locY];
899  double halfLength = ly < 0 ? halfLengthL : halfLengthR;
900  bool shiftedPos = false;
901 
902  if (std::abs(ly) > halfLength) {
903  double lyold = ly;
904  ly = ly < 0 ? -halfLength : halfLength;
905  ATH_MSG_DEBUG(" extrapolated position outside detector, shifting it back: " << lyold << " size " << halfLength << " new pos "
906  << ly);
907  if (phiPos && std::abs(lyold) - halfLength > 1000.) {
908  ATH_MSG_DEBUG(" rejecting track ");
909  return nullptr;
910  }
911  shiftedPos = true;
912  }
913 
914  ATH_MSG_VERBOSE("Creating fake measurement using measurement " << m_printer->print(meas));
915 
916  const Trk::Surface& surf = meas.associatedSurface();
917 
918  // no overlap, put fake phi hit at center of the chamber
919  if (overlapPos) {
920  // overlap, fake hit at 100. mm from the edge, error 100./sqrt(12.)
921 
922  // transform estimate of overlap position into surface frame
923  std::optional<Amg::Vector2D> loverlapPos = surf.globalToLocal(*overlapPos, 3000.);
924  if (!loverlapPos) {
925  ATH_MSG_DEBUG(" globalToLocal failed for overlap position: " << surf.transform() * (*overlapPos));
926  // calculate position fake
927  double lyfake = halfLength - 50.;
928  if (ly < 0.) lyfake *= -1.;
929  ly = lyfake;
930  errPos = FiftyOverSqrt12;
931 
932  if (msgLvl(MSG::VERBOSE)){
933  Amg::Vector2D LocVec2D_plus(0., lyfake);
934  const Amg::Vector3D fakePos_plus = meas.associatedSurface().localToGlobal(LocVec2D_plus);
935  Amg::Vector2D LocVec2D_min(0., -lyfake);
936  const Amg::Vector3D fakePos_min = meas.associatedSurface().localToGlobal(LocVec2D_min);
937 
938  double phi_min = fakePos_min.phi();
939  double phi_plus = fakePos_plus.phi();
940  double phi_overlap = phiPos->phi();
941  ATH_MSG_VERBOSE(" fake lpos " << lyfake << " ch half length " << halfLength << " phi+ " << phi_plus << " phi- " << phi_min
942  << " phi overlap " << phi_overlap << " err " << errPos);
943  }
944 
945  } else {
946  ly = (*loverlapPos)[Trk::locY];
947  halfLength = ly < 0 ? halfLengthL : halfLengthR; // safer to redo since ly changed
948  if (std::abs(ly) > halfLength) { ly = ly < 0 ? -halfLength : halfLength; }
949  ATH_MSG_VERBOSE(" fake from overlap: lpos " << ly << " ch half length " << halfLength << " overlapPos " << *overlapPos);
950  }
951  }
952 
954  // Error matrix
955  Amg::MatrixX cov(1, 1);
956  cov(0, 0) = errPos * errPos;
957  std::unique_ptr<Trk::PseudoMeasurementOnTrack> fake = std::make_unique<Trk::PseudoMeasurementOnTrack>(std::move(locPars),
958  std::move(cov), surf);
959 
960  if (msgLvl(MSG::DEBUG)) {
961  Amg::Vector2D LocVec2D(0., fake->localParameters().get(Trk::locY));
962  const Amg::Vector3D fakePos = meas.associatedSurface().localToGlobal(LocVec2D);
963 
964  msg(MSG::DEBUG) << MSG::DEBUG << " createFakePhiForMeasurement for: " << m_idHelperSvc->toStringChamber(id) << " locY " << ly
965  << " errpr " << errPos << " phi " << fakePos.phi() << endmsg;
966 
967  if (!shiftedPos && !overlapPos && phiPos && std::abs(phiPos->phi() - fakePos.phi()) > 0.01) {
968  Amg::Transform3D gToLocal = meas.associatedSurface().transform().inverse();
969  Amg::Vector3D locMeas = gToLocal * fake->globalPosition();
970  ATH_MSG_WARNING(" Problem calculating fake from IP seed: phi fake " << fakePos.phi() << " IP phi " << phiPos->phi()
971  << " local meas pos " << locMeas);
972  }
973  }
974  return fake;
975  }
976 
978  // check distance between first and last hit to determine whether we need additional phi constrainst
979 
980  if ((fitterData.firstEntry->containsChamber(ChIndex::CSS) ||
981  fitterData.firstEntry->containsChamber(ChIndex::CSL)) &&
982  !fitterData.secondEntry->phiHits().empty())
983  return 2;
984 
985  unsigned int nphiConstraints = fitterData.phiHits.size();
986  // count SL overlap as one phi constraint
987  // if( fitterData.numberOfSLOverlaps() > 0 ) {
988  // nphiConstraints += fitterData.numberOfSLOverlaps();
989  // ATH_MSG_VERBOSE(" track has small/large overlaps " << fitterData.numberOfSLOverlaps() );
990  // }else if( (fitterData.numberOfSmallChambers() > 0 && fitterData.numberOfLargeChambers() > 0 ) ){
991  // nphiConstraints += 1;
992  // ATH_MSG_VERBOSE(" track has small and large chambers " );
993  // }
994 
995  double distanceMin = 400.;
996  double distance = 0.;
997  // we need at least two phis
998  if (fitterData.phiHits.size() > 1) {
999  // assume the hits to be sorted
1000  const Amg::Vector3D& gposFirstPhi = fitterData.phiHits.front()->globalPosition();
1001  const Amg::Vector3D& gposLastPhi = fitterData.phiHits.back()->globalPosition();
1002  double distFirstEtaPhi =
1003  (fitterData.measurements.front()->globalPosition() - fitterData.phiHits.front()->globalPosition()).mag();
1004  double distLastEtaPhi = (fitterData.measurements.back()->globalPosition() - fitterData.phiHits.back()->globalPosition()).mag();
1005 
1006  // calculate difference between hits
1007  Amg::Vector3D globalDistance = gposLastPhi - gposFirstPhi;
1008 
1009  // calculate 'projective' distance
1010  distance = fitterData.hasEndcap ? std::abs(globalDistance.z()) : globalDistance.perp();
1011 
1012  // if the distance between the first and last phi hit is smaller than 1000. count as 1 phi hit
1013  if (distance < distanceMin || distFirstEtaPhi > 1000 || distLastEtaPhi > 1000) {
1014  nphiConstraints -= fitterData.phiHits.size(); // subtract phi hits as they should only count as one phi hit
1015  nphiConstraints += 1; // add one phi hit
1016  ATH_MSG_VERBOSE(" distance between phi hits too small, updating phi constraints ");
1017  } else {
1018  ATH_MSG_VERBOSE(" distance between phi hits sufficient, no fake hits needed ");
1019  }
1020  }
1021  if (msgLvl(MSG::DEBUG)) {
1022  msg(MSG::DEBUG) << MSG::DEBUG << " Check phi: " << std::endl
1023  << " | nphi hits | distance | SL station overlaps | small ch | large ch | nphiConstraints " << std::endl
1024  << std::setw(12) << fitterData.phiHits.size() << std::setw(11) << (int)distance << std::setw(22)
1025  << fitterData.numberOfSLOverlaps() << std::setw(11) << fitterData.numberOfSmallChambers() << std::setw(11)
1026  << fitterData.numberOfLargeChambers() << std::setw(18) << nphiConstraints << endmsg;
1027  }
1028 
1029  return nphiConstraints;
1030  }
1031 
1032  unsigned int MooTrackFitter::hasPhiConstrain(Trk::Track* track) const {
1033  std::map<MuonStationIndex::StIndex, StationPhiData> stationDataMap;
1034 
1035  // Get a MuonTrackSummary.
1036  const Trk::TrackSummary* summary = track->trackSummary();
1037  Trk::MuonTrackSummary muonSummary;
1038  if (summary) {
1039  if (summary->muonTrackSummary()) {
1040  muonSummary = *summary->muonTrackSummary();
1041  } else {
1042  Trk::TrackSummary tmpSum(*summary);
1043  m_trackSummaryTool->addDetailedTrackSummary(*track, tmpSum);
1044  if (tmpSum.muonTrackSummary()) muonSummary = *(tmpSum.muonTrackSummary());
1045  }
1046  } else {
1047  Trk::TrackSummary tmpSummary;
1048  m_trackSummaryTool->addDetailedTrackSummary(*track, tmpSummary);
1049  if (tmpSummary.muonTrackSummary()) muonSummary = *(tmpSummary.muonTrackSummary());
1050  }
1051 
1052  std::vector<Trk::MuonTrackSummary::ChamberHitSummary>::const_iterator chit = muonSummary.chamberHitSummary().begin();
1053  std::vector<Trk::MuonTrackSummary::ChamberHitSummary>::const_iterator chit_end = muonSummary.chamberHitSummary().end();
1054  for (; chit != chit_end; ++chit) {
1055  // get station data
1056  const Identifier& chId = chit->chamberId();
1057  MuonStationIndex::StIndex stIndex = m_idHelperSvc->stationIndex(chId);
1058  StationPhiData& stData = stationDataMap[stIndex];
1059  if (chit->isMdt()) {
1060  if (m_idHelperSvc->isSmallChamber(chId))
1061  ++stData.nSmallChambers;
1062  else
1063  ++stData.nLargeChambers;
1064  } else {
1065  if (chit->phiProjection().nhits) ++stData.nphiHits;
1066  }
1067  }
1068 
1069  unsigned int phiConstraints = 0;
1070  unsigned int stationsWithSmall = 0;
1071  unsigned int stationsWithLarge = 0;
1072 
1075  for (; sit != sit_end; ++sit) {
1076  StationPhiData& stData = sit->second;
1077 
1078  // count all stations with phi hits as phi constraint
1079  phiConstraints += stData.nphiHits;
1080 
1081  if (stData.nSmallChambers > 0 && stData.nLargeChambers > 0)
1082  ++phiConstraints;
1083  else if (stData.nSmallChambers > 0)
1084  ++stationsWithSmall;
1085  else if (stData.nLargeChambers > 0)
1086  ++stationsWithLarge;
1087  }
1088 
1089  if (stationsWithSmall > 0 && stationsWithLarge > 0) { ++phiConstraints; }
1090 
1091  return phiConstraints;
1092  }
1093  std::pair<double, double> MooTrackFitter::getElementHalfLengths(const Identifier& id, const Trk::TrkDetElementBase* ele ) const{
1094  if (m_idHelperSvc->isMdt(id)) {
1095  const MuonGM::MdtReadoutElement* mdtDetEl = dynamic_cast<const MuonGM::MdtReadoutElement*>(ele);
1096  if (!mdtDetEl){ return std::make_pair(0., 0.); }
1097  const double halfLength = 0.5 * mdtDetEl->getActiveTubeLength(m_idHelperSvc->mdtIdHelper().tubeLayer(id),
1098  m_idHelperSvc->mdtIdHelper().tube(id));
1099  return std::make_pair(halfLength, halfLength);
1100 
1101  } else if (m_idHelperSvc->isCsc(id)) {
1102  const MuonGM::CscReadoutElement* cscDetEl = dynamic_cast<const MuonGM::CscReadoutElement*>(ele);
1103  if (!cscDetEl) { return std::make_pair(0., 0.);}
1104  const double halfLenghth = 0.5 * cscDetEl->stripLength(id);
1105  return std::make_pair(halfLenghth, halfLenghth);
1106  } else if (m_idHelperSvc->isRpc(id)) {
1107  const MuonGM::RpcReadoutElement* rpcDetEl = dynamic_cast<const MuonGM::RpcReadoutElement*>(ele);
1108  if (!rpcDetEl) { return std::make_pair(0, 0);}
1109  const double halfLength = 0.5 * rpcDetEl->StripLength(false); // eta-strip
1110  return std::make_pair(halfLength, halfLength);
1111  } else if (m_idHelperSvc->isTgc(id)) {
1112  const MuonGM::TgcReadoutElement* tgcDetEl = dynamic_cast<const MuonGM::TgcReadoutElement*>(ele);
1113  if (!tgcDetEl) {return std::make_pair(0.,0.);}
1114  const double halfLength = 0.5 * tgcDetEl->gangCentralWidth(m_idHelperSvc->tgcIdHelper().gasGap(id), m_idHelperSvc->tgcIdHelper().channel(id));
1115  return std::make_pair(halfLength, halfLength);
1116  } else if (m_idHelperSvc->issTgc(id)) {
1117  const MuonGM::sTgcReadoutElement* stgcDetEl = dynamic_cast<const MuonGM::sTgcReadoutElement*>(ele);
1118  if (!stgcDetEl || !stgcDetEl->getDesign(id)) {return std::make_pair(0.,0.);}
1119  const double halfLength = 0.5 * stgcDetEl->getDesign(id)->channelLength(m_idHelperSvc->stgcIdHelper().channel(id));
1120  return std::make_pair(halfLength, halfLength);
1121 
1122  } else if (m_idHelperSvc->isMM(id)) {
1123  const MuonGM::MMReadoutElement* mmDetEl = dynamic_cast<const MuonGM::MMReadoutElement*>(ele);
1124  if (mmDetEl) {
1125  return std::make_pair(mmDetEl->stripActiveLengthLeft(id) ,
1126  mmDetEl->stripActiveLengthRight(id)); // components along the local Y axis
1127  }
1128  }
1129  return std::make_pair(0.,0.);
1130  }
1131  bool MooTrackFitter::getMinMaxPhi(FitterData& fitterData) const {
1132  double phiStart = fitterData.etaHits.front()->globalPosition().phi();
1133  double phiOffset = 0.;
1134  double phiRange = 0.75 * M_PI;
1135  double phiRange2 = 0.25 * M_PI;
1136  if (phiStart > phiRange || phiStart < -phiRange)
1137  phiOffset = 2 * M_PI;
1138  else if (phiStart > -phiRange2 && phiStart < phiRange2)
1139  phiOffset = M_PI;
1140 
1141  double phiMin = -999.;
1142  double phiMax = 999.;
1143 
1144  for (const Trk::MeasurementBase* meas :fitterData.etaHits) {
1145 
1146  const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(meas);
1147  if (!rot) {
1148  const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(meas);
1149  // if also to a crot we cannot create a fake phi hit
1150  if (!crot || crot->containedROTs().empty()) continue;
1151  rot = crot->containedROTs().front();
1152  }
1153 
1154  if (!rot) {
1155  ATH_MSG_WARNING(" Measurement not a ROT ");
1156  continue;
1157  }
1158 
1159  Identifier id = rot->identify();
1160  const Trk::Surface& surf = meas->associatedSurface();
1161  double x = rot->localParameters()[Trk::locX];
1162 
1163  // distinguishing left-right just to treat the asymmetry of the active region in MM chambers
1164  // getElementHalfLengths
1165  auto [halfLengthL, halfLengthR] = getElementHalfLengths(id, rot->detectorElement());
1166 
1167  Amg::Vector2D lpLeft(x, -halfLengthL);
1168  const Amg::Vector3D gposLeft = surf.localToGlobal(lpLeft);
1169  double phiLeft = gposLeft.phi();
1170 
1171  Amg::Vector2D lpRight(x, halfLengthR);
1172  const Amg::Vector3D gposRight = surf.localToGlobal(lpRight);
1173  double phiRight = gposRight.phi();
1174 
1175  if (phiOffset > 1.5 * M_PI) {
1176  if (phiLeft < 0) phiLeft = phiOffset + phiLeft;
1177  if (phiRight < 0) phiRight = phiOffset + phiRight;
1178  } else if (phiOffset > 0.) {
1179  phiLeft = phiLeft + phiOffset;
1180  phiRight = phiRight + phiOffset;
1181  }
1182 
1183  bool leftSmaller = phiLeft < phiRight;
1184 
1185  double phiMinMeas = leftSmaller ? phiLeft : phiRight;
1186  double phiMaxMeas = leftSmaller ? phiRight : phiLeft;
1187  double orgPhiMin = phiMinMeas;
1188  double orgPhiMax = phiMaxMeas;
1189 
1190  if (phiOffset > 1.5 * M_PI) {
1191  if (orgPhiMin > M_PI) orgPhiMin = orgPhiMin - phiOffset;
1192  if (orgPhiMax > M_PI) orgPhiMax = orgPhiMax - phiOffset;
1193  } else if (phiOffset > 0.) {
1194  orgPhiMin = orgPhiMin - phiOffset;
1195  orgPhiMax = orgPhiMax - phiOffset;
1196  }
1197 
1198  if (phiMinMeas > phiMin) { phiMin = phiMinMeas; }
1199  if (phiMaxMeas < phiMax) { phiMax = phiMaxMeas; }
1200  }
1201  if (phiMin < -998 || phiMax > 998) {
1202  ATH_MSG_WARNING(" Could not determine minimum and maximum phi ");
1203  return false;
1204  }
1205 
1206  double diffPhi = phiMax - phiMin;
1207  double avePhi = phiMin + 0.5 * diffPhi;
1208 
1209  ATH_MSG_VERBOSE("Phi ranges: min " << phiMin << " max " << phiMax << " average phi " << avePhi);
1210 
1211  if (diffPhi < 0) {
1212  if (std::abs(diffPhi) > m_openingAngleCut) {
1213  ATH_MSG_VERBOSE(" Inconsistent min/max, rejecting track ");
1214  return false;
1215  }
1216  }
1217 
1218  if (!fitterData.phiHits.empty()) {
1219  for (const Trk::MeasurementBase* meas : fitterData.phiHits) {
1220  const double minPhi = std::min(phiMin, phiMax);
1221  const double maxPhi = std::max(phiMin, phiMax);
1222  double phiMeas = meas->globalPosition().phi();
1223  if (phiOffset > 1.5 * M_PI) {
1224  if (phiMeas < 0.) phiMeas = phiOffset + phiMeas;
1225  } else if (phiOffset > 0.) {
1226  phiMeas = phiMeas + phiOffset;
1227  }
1228  double diffMin = phiMeas - minPhi;
1229  double diffMax = phiMeas - maxPhi;
1230  if (diffMin < 0. || diffMax > 0.) {
1231  if (diffMin < -m_openingAngleCut || diffMax > m_openingAngleCut) {
1232  ATH_MSG_VERBOSE(" Phi hits inconsistent with min/max, rejecting track: phi meas " << phiMeas);
1233  return false;
1234  }
1235  }
1236  }
1237  }
1238 
1239  if (phiOffset > 1.5 * M_PI) {
1240  if (phiMax > M_PI) phiMax = phiMax - phiOffset;
1241  if (phiMin > M_PI) phiMin = phiMin - phiOffset;
1242  if (avePhi > M_PI) avePhi = avePhi - phiOffset;
1243  } else if (phiOffset > 0.) {
1244  phiMax = phiMax - phiOffset;
1245  phiMin = phiMin - phiOffset;
1246  avePhi = avePhi - phiOffset;
1247  }
1248 
1249  fitterData.avePhi = avePhi;
1250  fitterData.phiMin = phiMin;
1251  fitterData.phiMax = phiMax;
1252 
1253  return true;
1254  }
1255 
1256  std::shared_ptr<const MuonSegment> MooTrackFitter::segmentFromEntry(const EventContext& ctx, const MuPatCandidateBase& entry) const {
1257  // if track entry use first segment
1258  const MuPatTrack* trkEntry = dynamic_cast<const MuPatTrack*>(&entry);
1259  if (trkEntry) {
1260  std::shared_ptr<MuonSegment> seg{m_trackToSegmentTool->convert(ctx, trkEntry->track())};
1261  return seg;
1262  }
1263 
1264  // if segment entry use segment directly
1265  const MuPatSegment* segEntry = dynamic_cast<const MuPatSegment*>(&entry);
1266  if (segEntry) {
1267  return std::shared_ptr<const MuonSegment> {segEntry->segment, Unowned()};
1268  }
1269 
1270  return nullptr;
1271  }
1272 
1274  return entry.entryPars().charge() / entry.entryPars().momentum().mag();
1275  }
1276 
1277  double MooTrackFitter::qOverPFromEntries(const EventContext& ctx, const MuPatCandidateBase& firstEntry, const MuPatCandidateBase& secondEntry) const {
1278  if (m_slFit) return 0;
1279 
1280  double qOverP = 0;
1281  // if available take momentum from entries
1282  if (firstEntry.hasMomentum())
1283  return qOverPFromEntry(firstEntry);
1284  else if (secondEntry.hasMomentum())
1285  return qOverPFromEntry(secondEntry);
1286 
1287  // no momentum yet, estimate from segments
1288  std::shared_ptr<const MuonSegment> segFirst = segmentFromEntry(ctx, firstEntry);
1289  if (!segFirst) {
1290  ATH_MSG_WARNING(" failed to get segment for first entry, this should not happen ");
1291  return qOverP;
1292  }
1293 
1294  std::shared_ptr<const MuonSegment> segSecond = segmentFromEntry(ctx, secondEntry);
1295  if (!segSecond) {
1296  ATH_MSG_WARNING(" failed to get segment for second entry, this should not happen ");
1297  return qOverP;
1298  }
1299 
1300  std::vector<const MuonSegment*> segments{segFirst.get(), segSecond.get()};
1301 
1302  double momentum{1.};
1303  m_momentumEstimator->fitMomentumVectorSegments(ctx, segments, momentum);
1304  // momentum = restrictedMomentum(momentum);
1305 
1306  if (momentum == 0.) return 0.;
1307 
1308  qOverP = 1. / momentum;
1309  return qOverP;
1310  }
1311 
1312  double MooTrackFitter::phiSeeding(const EventContext& ctx, MooTrackFitter::FitterData& fitterData) const {
1313  if (m_cosmics) {
1314  // check whether the first entry is a track, if not consider the second entry for phi seeding
1315  if (!dynamic_cast<const MuPatTrack*>(fitterData.firstEntry)) {
1316  // if second entry is a track, use its phi value
1317  if (dynamic_cast<const MuPatTrack*>(fitterData.secondEntry)) {
1318  ATH_MSG_DEBUG("Using phi of second entry " << fitterData.secondEntry->entryPars().momentum().phi());
1319  return fitterData.secondEntry->entryPars().momentum().phi();
1320  }
1321  }
1322 
1323  // add fake phi hit on first and last measurement
1324  const MuPatSegment* segInfo1 = dynamic_cast<const MuPatSegment*>(fitterData.firstEntry);
1325  const MuPatSegment* segInfo2 = dynamic_cast<const MuPatSegment*>(fitterData.secondEntry);
1326  if (segInfo1 && segInfo2 && fitterData.stations.size() == 1 && fitterData.numberOfSLOverlaps() == 1) {
1327  // only perform SL overlap fit for MDT segments
1328  Identifier chId = m_edmHelperSvc->chamberId(*segInfo1->segment);
1329  if (m_idHelperSvc->isMdt(chId)) {
1331  m_overlapResolver->matchResult(ctx, *segInfo1->segment, *segInfo2->segment);
1332 
1333  if (!result.goodMatch()) {
1334  ATH_MSG_VERBOSE(" Match failed ");
1335  return false;
1336  }
1337  double overlapPhi = result.phiResult.segmentDirection1.phi();
1338  ATH_MSG_DEBUG(" using overlap phi " << overlapPhi);
1339  return overlapPhi;
1340  }
1341  }
1342 
1343  // calculate the difference between the segment positions to estimate the direction of the muon
1344  Amg::Vector3D difPos = fitterData.firstEntry->entryPars().position() - fitterData.secondEntry->entryPars().position();
1345  // check whether the new direction is pointing down
1346  if (difPos.y() > 0) difPos *= -1.;
1347 
1348  // calculate difference in angle between phi from segment and the phi of the two new segment positions
1349  const double dphi = fitterData.firstEntry->entryPars().momentum().deltaPhi(difPos);
1350  if (std::abs(dphi) > 0.2) {
1351  ATH_MSG_DEBUG("Large diff between phi of segment direction and of position "
1352  << fitterData.firstEntry->entryPars().momentum().phi() << " from pos " << difPos.phi() << " dphi " << dphi);
1353  return difPos.phi();
1354  }
1355 
1356  ATH_MSG_DEBUG("Using phi of first entry " << fitterData.firstEntry->entryPars().momentum().phi() << " phi from position "
1357  << dphi);
1358 
1359  return fitterData.firstEntry->entryPars().momentum().phi();
1360  }
1361 
1362  double phi(0.);
1363  // update parameters if seeding purely with positions
1364  if (m_seedPhiWithEtaHits) {
1365  // use eta of vector connecting first/last hit
1366  MooTrackFitter::MeasVec& etaHits = fitterData.etaHits;
1367  Amg::Vector3D difPos = etaHits.back()->globalPosition() - etaHits.front()->globalPosition();
1368  if (difPos.mag() > 3000) {
1369  ATH_MSG_DEBUG("Seeding phi using average phi of eta hits ");
1370  phi = difPos.phi();
1371  return phi;
1372  }
1373  }
1374 
1375  // should have at least one phi hit
1376  MooTrackFitter::MeasVec& phiHits = fitterData.phiHits;
1377 
1378  if (phiHits.empty()) {
1379  ATH_MSG_DEBUG("No phi hits, using average phi ");
1380  // use average phi value to seed fit
1381  return fitterData.avePhi;
1382  }
1383 
1384  // in this case can't do much...
1385  if (phiHits.size() == 1) { return phiHits.front()->globalPosition().phi(); }
1386 
1387  // in endcap, if first segment in EI use its direction
1388  const MuPatSegment* segInfo1 = dynamic_cast<const MuPatSegment*>(fitterData.firstEntry);
1389  if (segInfo1 && segInfo1->containsStation(StIndex::EI) && !segInfo1->phiHits().empty()) {
1390  return segInfo1->segment->globalDirection().phi();
1391  }
1392 
1393  // in endcap, if first segment in EM use its direction
1394  if (segInfo1 && segInfo1->containsStation(StIndex::EM) && !segInfo1->phiHits().empty()) {
1395  return segInfo1->segment->globalDirection().phi();
1396  }
1397 
1398  if (m_seedWithAvePhi) {
1399  // use average phi value to seed fit
1400  MeasCit hit = phiHits.begin();
1401  MeasCit hit_end = phiHits.end();
1402  Amg::Vector3D avePos(0., 0., 0.);
1403  for (; hit != hit_end; ++hit) avePos += (*hit)->globalPosition();
1404  avePos /= phiHits.size();
1405  phi = avePos.phi();
1406  } else {
1407  // use phi of vector connecting first/last hit
1408  Amg::Vector3D difPos = phiHits.back()->globalPosition() - phiHits.front()->globalPosition();
1409  phi = difPos.phi();
1410  }
1411 
1412  return phi;
1413  }
1414 
1416  // should have at least one eta hit
1417  if (etaHits.empty()) {
1418  ATH_MSG_WARNING(" cannot calculate eta seed from empty vector ");
1419  return 0;
1420  }
1421 
1422  double theta(0.);
1423  if (m_seedWithSegmentTheta) {
1424  theta = entry.entryPars().momentum().theta();
1425  } else {
1426  // in this case can't do much...
1427  if (etaHits.size() == 1) {
1428  theta = etaHits.front()->globalPosition().theta();
1429  } else {
1430  // use eta of vector connecting first/last hit
1431  Amg::Vector3D difPos = etaHits.back()->globalPosition() - etaHits.front()->globalPosition();
1432  theta = difPos.theta();
1433  }
1434  }
1435 
1436  return theta;
1437  }
1438 
1439  void MooTrackFitter::createStartParameters(const EventContext& ctx, MooTrackFitter::FitterData& fitterData) const {
1440  // get momentum + charge from entry if available, else use MuonSegmentMomentum to estimate the momentum
1441  double qOverP = qOverPFromEntries(ctx, *fitterData.firstEntry, *fitterData.secondEntry);
1442  std::unique_ptr<Trk::Perigee> startPars{nullptr};
1443  const MuPatCandidateBase *entry1 = fitterData.firstEntry, *entry2 = fitterData.secondEntry;
1444 
1445  const MuPatTrack* trkEntry1 = dynamic_cast<const MuPatTrack*>(entry1);
1446  const MuPatTrack* trkEntry2 = dynamic_cast<const MuPatTrack*>(entry2);
1447  const MuPatSegment* seg1 = dynamic_cast<const MuPatSegment*>(entry1);
1448  const MuPatSegment* seg2 = dynamic_cast<const MuPatSegment*>(entry2);
1449 
1452  if (seg1) {
1453  dir1 = seg1->segment->globalDirection();
1454  point1 = seg1->segment->globalPosition();
1455  } else {
1456  if (trkEntry1->track().perigeeParameters()) {
1457  dir1 = trkEntry1->track().perigeeParameters()->momentum().unit();
1458  point1 = trkEntry1->track().perigeeParameters()->position();
1459  } else {
1460  return;
1461  }
1462  }
1463  if (seg2) {
1464  dir2 = seg2->segment->globalDirection();
1465  point2 = seg2->segment->globalPosition();
1466  } else {
1467  if (trkEntry2->track().perigeeParameters()) {
1468  dir2 = trkEntry2->track().perigeeParameters()->momentum().unit();
1469  point2 = trkEntry2->track().perigeeParameters()->position();
1470  } else {
1471  return;
1472  }
1473  }
1474  if (dir1.dot(point2 - point1) < 0) {
1475  std::swap(point1, point2);
1476  std::swap(dir1, dir2);
1477  entry1 = fitterData.secondEntry;
1478  entry2 = fitterData.firstEntry;
1479  trkEntry1 = dynamic_cast<const MuPatTrack*>(entry1);
1480  trkEntry2 = dynamic_cast<const MuPatTrack*>(entry2);
1481  seg1 = dynamic_cast<const MuPatSegment*>(entry1);
1482  seg2 = dynamic_cast<const MuPatSegment*>(entry2);
1483  }
1484 
1485  const MuPatCandidateBase* bestentry = entry1;
1486  double dist1 = -1, dist2 = -1;
1487  MuPatHitPtr firstphi1{nullptr}, lastphi1{nullptr}, firstphi2{nullptr}, lastphi2{nullptr};
1488 
1489  for (const MuPatHitPtr& hit : entry1->hitList()) {
1490  if (hit->info().type != MuPatHit::Pseudo && hit->info().measuresPhi) {
1491  if (!firstphi1) firstphi1 = hit;
1492  lastphi1 = hit;
1493  }
1494  }
1495  for (const MuPatHitPtr& hit : entry2->hitList()) {
1496  if (hit->info().type != MuPatHit::Pseudo && hit->info().measuresPhi) {
1497  if (!firstphi2) firstphi2 = hit;
1498  lastphi2 = hit;
1499  }
1500  }
1501  if (firstphi1) dist1 = std::abs((firstphi1->measurement().globalPosition() - lastphi1->measurement().globalPosition()).dot(dir1));
1502  if (firstphi2) dist2 = std::abs((firstphi2->measurement().globalPosition() - lastphi2->measurement().globalPosition()).dot(dir2));
1503  if (dist2 > dist1) { bestentry = entry2; }
1504  const MuPatTrack* besttrkEntry = dynamic_cast<const MuPatTrack*>(bestentry);
1505  const MuPatSegment* bestseg = dynamic_cast<const MuPatSegment*>(bestentry);
1506  if (besttrkEntry) {
1507  const Trk::TrackParameters* mdtpar = nullptr;
1508  for (DataVector<const Trk::TrackParameters>::const_iterator parit = besttrkEntry->track().trackParameters()->begin();
1509  parit != besttrkEntry->track().trackParameters()->end(); ++parit) {
1510  mdtpar = *parit;
1511  if (mdtpar) break;
1512  }
1513  if (!mdtpar) {
1514  ATH_MSG_WARNING("Failed to find valid Trackparameters on track ");
1515  return;
1516  }
1517  Amg::VectorX newpar = mdtpar->parameters(); // besttrkEntry->track().perigeeParameters()->parameters();
1518  newpar[Trk::qOverP] = qOverP;
1519  Trk::PerigeeSurface persurf(mdtpar->position());
1520  startPars = std::make_unique<Trk::Perigee>(0, 0, newpar[Trk::phi], newpar[Trk::theta], qOverP,
1521  persurf); // besttrkEntry->track().perigeeParameters()->cloneToNew(newpar);
1522  }
1523 
1524  else {
1525  Trk::PerigeeSurface persurf(bestseg->segment->globalPosition());
1526  double phi = bestseg->segment->globalDirection().phi();
1527  if ((fitterData.firstEntry->containsChamber(ChIndex::CSS) ||
1528  fitterData.firstEntry->containsChamber(ChIndex::CSL)) &&
1529  fitterData.secondEntry->hasSLOverlap())
1530  phi = (fitterData.hitList.back()->parameters().position() - bestseg->segment->globalPosition()).phi();
1531 
1532  double theta = bestseg->segment->globalDirection().theta();
1533  // create start parameter
1534  startPars = std::make_unique<Trk::Perigee>(0, 0, phi, theta, qOverP, persurf);
1535 
1536  }
1537  if (!startPars) {
1538  ATH_MSG_DEBUG(" failed to create perigee ");
1539  return;
1540  }
1541  fitterData.startPars = std::move(startPars);
1542  }
1543 
1544  std::unique_ptr<Trk::Perigee> MooTrackFitter::createPerigee(const EventContext& ctx, const Trk::TrackParameters& firstPars, const Trk::MeasurementBase& firstMeas) const {
1545  // const Amg::Vector3D& firstPos = firstMeas.globalPosition();
1546 
1548  // propagate segment parameters to first measurement
1549  const Trk::TrackParameters* exPars = &firstPars;
1550  std::unique_ptr<Trk::TrackParameters> garbage;
1551  double shift = 1.;
1552  if (m_seedAtStartOfTrack) {
1553  // not sure whats going on with ownership here, so let this code take care of it
1554  garbage =
1555  m_propagator->propagate(ctx, firstPars, firstMeas.associatedSurface(), Trk::anyDirection, false, m_magFieldProperties);
1556  if (!exPars) {
1557  ATH_MSG_DEBUG(" Propagation failed in createPerigee!! ");
1558  return nullptr;
1559  }
1560  exPars = garbage.get();
1561  shift = 100.;
1562  }
1563 
1564  // small shift towards the ip
1565  double sign = exPars->position().dot(exPars->momentum()) > 0 ? 1. : -1.;
1566  perpos = exPars->position() - shift * sign * exPars->momentum().unit();
1567 
1568  // create perigee
1569  double phi = exPars->momentum().phi();
1570  double theta = exPars->momentum().theta();
1571  double qoverp = exPars->charge() / exPars->momentum().mag();
1572  if (m_slFit)
1573  qoverp = 0;
1574  else {
1575  if (!validMomentum(*exPars)) {
1576  return nullptr;
1577  }
1578  }
1579 
1580  Trk::PerigeeSurface persurf(perpos);
1581  std::unique_ptr<Trk::Perigee> perigee = std::make_unique<Trk::Perigee>(0, 0, phi, theta, qoverp, persurf);
1582 
1583  ATH_MSG_DEBUG( std::setprecision(5) << " creating perigee: phi " << phi << " theta " << theta << " q*mom "
1584  << perigee->charge() * perigee->momentum().mag() << " r " << perigee->position().perp() << " z "
1585  << perigee->position().z() << " input q*mom " << firstPars.charge() * firstPars.momentum().mag());
1586  return perigee;
1587  }
1588 
1590  // restrict range of momenta to 2 GeV / 10 GeV
1591  if (momentum > 0) {
1592  if (momentum > 20000.)
1593  momentum = 20000.;
1594  else if (momentum < 2000)
1595  momentum = 2000;
1596  } else {
1597  if (momentum < -20000.)
1598  momentum = -20000.;
1599  else if (momentum > -2000.)
1600  momentum = -2000.;
1601  }
1602 
1603  return momentum;
1604  }
1605 
1606  std::unique_ptr<Trk::Track> MooTrackFitter::fit(const EventContext& ctx, const Trk::Perigee& startPars, MooTrackFitter::MeasVec& hits,
1607  Trk::ParticleHypothesis partHypo, bool prefit) const {
1608  if (hits.empty()) return nullptr;
1609  std::unique_ptr<Trk::Perigee> perigee{};
1610  ATH_MSG_VERBOSE(std::setprecision(5) << " track start parameter: phi " << startPars.momentum().phi() << " theta "
1611  << startPars.momentum().theta() << " q*mom " << startPars.charge() * startPars.momentum().mag()
1612  << " r " << startPars.position().perp() << " z " << startPars.position().z() << std::endl
1613  << " start par is a perigee "
1614  << " partHypo " << partHypo << std::endl
1615  << m_printer->print(hits));
1616 
1617  const Trk::TrackParameters* pars = &startPars;
1618  if (m_seedAtStartOfTrack) {
1619  DistanceAlongParameters distAlongPars;
1620  double dist = distAlongPars(startPars, *hits.front());
1621 
1622  if (dist < 0.) {
1623  ATH_MSG_DEBUG(" start parameters after first hit, shifting them.... ");
1624  perigee = createPerigee(ctx, startPars, *hits.front());
1625  if (perigee) {
1626  pars = perigee.get();
1627  } else {
1628  ATH_MSG_DEBUG(" failed to move start pars, failing fit ");
1629  return nullptr;
1630  }
1631  }
1632  }
1633 
1634  // fit track
1635 
1636  ATH_MSG_VERBOSE("fit: " << (prefit ? "prefit" : "fit") << "track with hits: " << hits.size() << std::endl
1637  << m_printer->print(hits));
1638  //The 'pars' is from perigee.get(), and the perigee object still exists in the 'garbage' vector
1639  //cppcheck-suppress invalidLifetime
1640  std::unique_ptr<Trk::Track> track{m_trackFitter->fit(ctx, hits, *pars, m_runOutlier, partHypo)};
1641 
1642  // 'sign' track
1643  if (track) {
1644  ATH_MSG_VERBOSE("Got back this track:"<<*track);
1645  track->info().setPatternRecognitionInfo(m_patRecInfo);
1646  }
1647 
1648  return track;
1649  }
1650 
1651  std::unique_ptr<Trk::Track> MooTrackFitter::fitWithRefit(const EventContext& ctx, const Trk::Perigee& startPars, MooTrackFitter::MeasVec& hits) const {
1652 
1653  std::unique_ptr<Trk::Track> track = fit(ctx, startPars, hits, Trk::muon, false);
1654 
1655  // exceptions that are not refitted
1656  if (m_slFit) return track;
1657 
1658  // refit track to ensure correct handling of material effects
1659  if (track) {
1660  const Trk::Perigee* pp = track->perigeeParameters();
1661  if (pp) {
1662  ATH_MSG_VERBOSE(" found track: " << m_printer->print(*track));
1663 
1664  // refit if absolute difference of the initial momentum and the final momentum is larger than 5 GeV
1665  double difMom = startPars.momentum().mag() - pp->momentum().mag();
1666  if (std::abs(difMom) > 5000.) {
1667  ATH_MSG_DEBUG(" absolute difference in momentum too large, refitting track. Dif momentum= " << difMom);
1668  ATH_MSG_DEBUG("fitWithRefit: refitting track with hits: " << hits.size() << std::endl << m_printer->print(hits));
1669  std::unique_ptr<Trk::Track> refittedTrack(m_trackFitter->fit(ctx, hits, *pp, false, m_ParticleHypothesis));
1670  if (refittedTrack) {
1671  track.swap(refittedTrack);
1672 
1673  if (msgLvl(MSG::DEBUG)) {
1674  const Trk::Perigee* pp = track->perigeeParameters();
1675  if (pp) {
1676  ATH_MSG_DEBUG(" refitted track fit perigee: r " << pp->position().perp() << " z " << pp->position().z());
1677  }
1678  }
1679  }
1680  }
1681  }
1682  }
1683 
1684  return track;
1685  }
1686 
1687  bool MooTrackFitter::cleanPhiHits(const EventContext& ctx, double momentum, MooTrackFitter::FitterData& fitterData,
1688  const std::vector<const Trk::PrepRawData*>& patternPhiHits) const {
1689  ATH_MSG_VERBOSE(" cleaning phi hits ");
1690 
1691  MeasVec& phiHits = fitterData.phiHits;
1692 
1693  // copy phi ROTs into vector, split up competing ROTs
1694  std::vector<const Trk::RIO_OnTrack*> rots;
1695  std::vector<std::unique_ptr<const Trk::RIO_OnTrack>> rotsNSW; // hack as the phi hit cleaning does not work for NSW hits
1696  std::set<Identifier> ids;
1697  std::set<MuonStationIndex::StIndex> stations;
1698  rots.reserve(phiHits.size() + 5);
1699 
1700  for (const Trk::MeasurementBase* hit : phiHits) {
1701  const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(hit);
1702  if (rot) {
1703  if (m_idHelperSvc->issTgc(rot->identify())) {
1704  rotsNSW.push_back(rot->uniqueClone());
1705  continue;
1706  }
1707  rots.push_back(rot);
1708  ids.insert(rot->identify());
1709  continue;
1710  }
1711  const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(hit);
1712  if (crot) {
1713  for (const MuonClusterOnTrack* mit : crot->containedROTs()) {
1714  rots.push_back(mit);
1715  ids.insert(mit->identify());
1716  MuonStationIndex::StIndex stIndex = m_idHelperSvc->stationIndex(mit->identify());
1717  stations.insert(stIndex);
1718  }
1719  } else {
1720  ATH_MSG_WARNING(" phi hits should be ROTs or competing ROTs! Dropping hit ");
1721  }
1722  }
1723 
1724  if (rots.empty()) return false;
1725 
1726  if (rots.size() > m_phiHitsMax) {
1727  ATH_MSG_DEBUG(" too many phi hits, not running cleaning " << rots.size());
1728  return true;
1729  }
1730 
1731  if (msgLvl(MSG::VERBOSE)) {
1732  msg(MSG::VERBOSE) << " contained phi hits ";
1733  for (const Trk::RIO_OnTrack* rit : rots) { msg(MSG::DEBUG) << std::endl << " " << m_printer->print(*rit); }
1734  msg(MSG::DEBUG) << endmsg;
1735  }
1736 
1737  // if available, extract additional phi hits from the road that were not on the entries
1738  std::vector<const Trk::PrepRawData*> roadPhiHits;
1739  std::copy_if(patternPhiHits.begin(), patternPhiHits.end(), std::back_inserter(roadPhiHits), [&ids, this](const Trk::PrepRawData* prd){
1740  return !(ids.count(prd->identify()) ||
1742  m_idHelperSvc->isCsc(prd->identify()) || m_idHelperSvc->issTgc(prd->identify()));
1743  });
1744 
1745 
1746  if (roadPhiHits.size() + rots.size() > m_phiHitsMax) {
1747  ATH_MSG_VERBOSE(" too many pattern phi hits, not adding any " << roadPhiHits.size());
1748  roadPhiHits.clear(); // cleaning road hits as we do not want to add them but we do want to clean
1749  }
1750  if (msgLvl(MSG::VERBOSE)) {
1751  if (!roadPhiHits.empty()) {
1752  msg(MSG::VERBOSE) << " additional pattern phi hits " << std::endl;
1753  std::vector<const Trk::PrepRawData*>::const_iterator pit = roadPhiHits.begin();
1754  std::vector<const Trk::PrepRawData*>::const_iterator pit_end = roadPhiHits.end();
1755  for (; pit != pit_end; ++pit) {
1756  msg(MSG::DEBUG) << " " << m_printer->print(**pit);
1757  if (pit + 1 != pit_end)
1758  msg(MSG::DEBUG) << std::endl;
1759  else
1760  msg(MSG::DEBUG) << endmsg;
1761  }
1762  }
1763  }
1764 
1765  std::vector<std::unique_ptr<const Trk::MeasurementBase>> newMeasurements{m_phiHitSelector->select_rio(momentum, rots, roadPhiHits)};
1766 
1767  newMeasurements.insert(newMeasurements.end(),
1768  std::make_move_iterator(rotsNSW.begin()),
1769  std::make_move_iterator(rotsNSW.end()));
1770 
1771  ATH_MSG_VERBOSE(" selected phi hits " << newMeasurements.size());
1772 
1773  if (newMeasurements.empty()) {
1774  ATH_MSG_DEBUG(" empty list of phi hits return from phi hit selector: input size " << phiHits.size());
1775  return false;
1776  }
1777 
1778  // require the new hits to be within a certain distance of the hits already on the track candidate
1779  DistanceAlongParameters distAlongPars;
1780  constexpr double maxDistCut = 800.;
1781  std::vector<const Trk::MeasurementBase*> measurementsToBeAdded{};
1782  measurementsToBeAdded.reserve(newMeasurements.size());
1783  for (std::unique_ptr<const Trk::MeasurementBase>& meas : newMeasurements) {
1784  const Identifier id = m_edmHelperSvc->getIdentifier(*meas);
1785  if (!id.is_valid()) {
1786  ATH_MSG_WARNING(" Phi measurement without valid Identifier! ");
1787  continue;
1788  }
1789  ATH_MSG_VERBOSE(" Test phi hit - " << m_printer->print(*meas));
1790  // only add hits if the hitList is not empty so we can calculate the distance of the new hit to the first and last hit on the
1791  // track
1792  if (fitterData.hitList.empty()) {
1793  ATH_MSG_VERBOSE(" discarding phi hit due to empty hitList ");
1794  break;
1795  }
1796 
1797  // calculate the distance of the phi hit to the first hit. If the phi hit lies before the first hit,
1798  // remove the hit if the distance is too large
1799  double dist = distAlongPars(fitterData.hitList.front()->parameters(), *meas);
1800  if (dist < -maxDistCut) {
1801  ATH_MSG_VERBOSE(" discarded phi hit, distance to first hit too large " << dist);
1802  continue;
1803  }
1804 
1805  // calculate the distance of the phi hit to the last hit. If the phi hit lies after the last hit,
1806  // remove the hit if the distance is too large
1807  double distBack = distAlongPars(fitterData.hitList.back()->parameters(), *meas);
1808  if (distBack > maxDistCut) {
1809  ATH_MSG_VERBOSE(" discarded phi hit, distance to last hit too large " << distBack);
1810  continue;
1811  }
1812 
1813  ATH_MSG_VERBOSE(" new phi hit, distance from start pars " << dist << " distance to last pars " << distBack);
1814 
1815  measurementsToBeAdded.push_back(meas.get());
1816  fitterData.garbage.push_back(std::move(meas));
1817  }
1818 
1819  // now remove all previous phi hits and replace them with the new ones
1820 
1821  for (const Trk::MeasurementBase* hit : phiHits) {
1822  ATH_MSG_VERBOSE(" Remove phi measurement " << m_printer->print(*hit));
1823  m_hitHandler->remove(*hit, fitterData.hitList);
1824 
1825  }
1826 
1827  // add the new phi hits to the hit list
1828  if (!measurementsToBeAdded.empty()) {
1829  ATH_MSG_VERBOSE(" adding measurements "<<std::endl<<m_printer->print(measurementsToBeAdded));
1830  MuPatHitList newHitList;
1831  m_hitHandler->create(ctx, fitterData.firstEntry->entryPars(), measurementsToBeAdded, newHitList);
1832  fitterData.hitList = m_hitHandler->merge(newHitList, fitterData.hitList);
1833  }
1834 
1835  ATH_MSG_VERBOSE(" done cleaning ");
1836 
1837  return true;
1838  }
1839 
1840  std::unique_ptr<Trk::Track> MooTrackFitter::cleanAndEvaluateTrack(const EventContext& ctx, Trk::Track& track,
1841  const std::set<Identifier>& excludedChambers) const {
1842  // preselection to get ride of really bad tracks
1843  if (!m_edmHelperSvc->goodTrack(track, m_preCleanChi2Cut)) {
1844  ATH_MSG_DEBUG(" Track rejected due to large chi2" << std::endl << m_printer->print(track));
1845  return nullptr;
1846  }
1847 
1848  // perform cleaning of track
1849  std::unique_ptr<Trk::Track> cleanTrack;
1850  if (excludedChambers.empty())
1851  cleanTrack = m_cleaner->clean(track, ctx);
1852  else {
1853  ATH_MSG_DEBUG(" Cleaning with exclusion list " << excludedChambers.size());
1854  cleanTrack = m_cleaner->clean(track, excludedChambers, ctx);
1855  }
1856  if (!cleanTrack) {
1857  ATH_MSG_DEBUG(" Cleaner returned a zero pointer, reject track ");
1858  return nullptr;
1859  }
1860 
1861  // selection to get ride of bad tracks after cleaning
1862  if (!m_edmHelperSvc->goodTrack(*cleanTrack, m_chi2Cut)) {
1863  ATH_MSG_DEBUG(" Track rejected after cleaning " << std::endl << m_printer->print(*cleanTrack));
1864  return nullptr;
1865  }
1866 
1867  ATH_MSG_DEBUG(" Track passed selection after cleaning! ");
1868  return cleanTrack;
1869  }
1870 
1872  const double p = pars.momentum().mag();
1873  if (p < m_pThreshold) {
1874  ATH_MSG_DEBUG(" momentum below threshold: momentum " << pars.momentum().mag() << " p " << pars.momentum().perp());
1875  return false;
1876  }
1877  return true;
1878  }
1879 
1880  void MooTrackFitter::cleanEntry(const MuPatCandidateBase& entry, std::set<Identifier>& removedIdentifiers) const {
1881  // if segment entry use segment directly
1882  const MuPatSegment* segEntry = dynamic_cast<const MuPatSegment*>(&entry);
1883  if (segEntry && segEntry->segment) {
1884  if (entry.hasSmallChamber() && entry.hasLargeChamber()) {
1885  ATH_MSG_DEBUG(" Segment with SL overlap, cannot perform cleaning ");
1886  } else {
1887  cleanSegment(*segEntry->segment, removedIdentifiers);
1888  }
1889  }
1890  }
1891 
1892  void MooTrackFitter::cleanSegment(const MuonSegment& seg, std::set<Identifier>& removedIdentifiers) const {
1894  /* ******** Mdt hits ******** */
1895 
1896  const MuonGM::MdtReadoutElement* detEl = nullptr;
1897 
1898  Amg::Transform3D gToStation{Amg::Transform3D::Identity()};
1899 
1900 
1901  float tubeRadius = 14.6;
1902 
1903  ATH_MSG_DEBUG("loop through hits for segment");
1904  for ( const Trk::MeasurementBase* meas : seg.containedMeasurements()) {
1905  const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(meas);
1906 
1907  if (!mdt) { continue; }
1908  Identifier id = mdt->identify();
1909  if (!detEl) {
1910  detEl = mdt->prepRawData()->detectorElement();
1911  gToStation = detEl->GlobalToAmdbLRSTransform();
1912  }
1913  if (!detEl) {
1914  ATH_MSG_WARNING(" error aborting not detEl found ");
1915  break;
1916  }
1917 
1918  ATH_MSG_DEBUG("detector element of station type " << detEl->getStationType());
1919  tubeRadius = detEl->innerTubeRadius();
1920 
1921  // calculate local AMDB position
1922  Amg::Vector3D LocVec2D = gToStation * mdt->prepRawData()->globalPosition();
1923  TrkDriftCircleMath::LocVec2D lpos(LocVec2D.y(), LocVec2D.z());
1924 
1925  double r = mdt->localParameters()[Trk::locR];
1926  double dr = Amg::error(mdt->localCovariance(), Trk::locR);
1927 
1928  // create identifier
1929  TrkDriftCircleMath::MdtId mdtid(m_idHelperSvc->mdtIdHelper().isBarrel(id), m_idHelperSvc->mdtIdHelper().multilayer(id) - 1,
1930  m_idHelperSvc->mdtIdHelper().tubeLayer(id) - 1, m_idHelperSvc->mdtIdHelper().tube(id) - 1);
1931 
1932  // create new DriftCircle
1934  TrkDriftCircleMath::DCOnTrack dcOnTrack(dc, 1., 1.);
1935  ATH_MSG_VERBOSE(" new MDT hit " << m_idHelperSvc->toString(id));
1936 
1937  dcs.push_back(dcOnTrack);
1938 
1939  }
1940 
1941  double angleYZ = seg.localDirection().angleYZ();
1942  const Amg::Vector3D lpos = gToStation * seg.globalPosition();
1943 
1944  ATH_MSG_DEBUG(" cleaning segment " << m_printer->print(seg) << std::endl
1945  << " local parameters " << lpos.y() << " " << lpos.z() << " phi " << angleYZ << " with "
1946  << dcs.size() << " hits ");
1947 
1948  TrkDriftCircleMath::LocVec2D segPos(lpos.y(), lpos.z());
1949  TrkDriftCircleMath::Line segPars(segPos, angleYZ);
1950 
1953  fitter.fit(segment, segPars, dcs);
1954  segment.hitsOnTrack(dcs.size());
1955  ATH_MSG_DEBUG(" segment after fit " << segment.chi2() << " ndof " << segment.ndof() << " local parameters " << segment.line().x0()
1956  << " " << segment.line().y0() << " phi " << segment.line().phi());
1957 
1958  bool hasDroppedHit = false;
1959  unsigned int dropDepth = 0;
1961  bool success = finder.dropHits(segment, hasDroppedHit, dropDepth);
1962  if (!success) {
1963  ATH_MSG_DEBUG(" drop hits failed ");
1964  return;
1965  }
1966 
1967  if (dcs.size() == segment.ndof() + 2) {
1968  ATH_MSG_DEBUG(" segment unchanges ");
1969  } else if (dcs.size() != segment.ndof() + 3) {
1970  ATH_MSG_DEBUG(" more than one hit removed, keeping old segment ");
1971  } else {
1972  ATH_MSG_DEBUG(" removed single hit, not using it in fit ");
1973 
1975  const TrkDriftCircleMath::DCOnTrackVec& matchedDCs = matchDC.match(segment.dcs());
1976 
1977  for (const TrkDriftCircleMath::DCOnTrack& dcit: matchedDCs) {
1978  if (dcit.state() == TrkDriftCircleMath::DCOnTrack::OnTrack) continue;
1979  removedIdentifiers.insert(dcit.rot()->identify());
1980  ATH_MSG_VERBOSE("Removing hit "<<m_idHelperSvc->toString(dcit.rot()->identify()));
1981  }
1982  }
1983  }
1984 
1986  if (fitterData.startPars->momentum().mag() < 4000.) return;
1987 
1988  std::set<Identifier> removedIdentifiers;
1989  if (fitterData.firstEntry) cleanEntry(*fitterData.firstEntry, removedIdentifiers);
1990  if (fitterData.secondEntry) cleanEntry(*fitterData.secondEntry, removedIdentifiers);
1991 
1992  ATH_MSG_DEBUG(" removing hits " << removedIdentifiers.size());
1993 
1994  for (const Identifier& id : removedIdentifiers) {
1995  ATH_MSG_VERBOSE("Remove hit "<<m_idHelperSvc->toString(id));
1996  m_hitHandler->remove(id, fitterData.hitList);
1997  }
1998  }
1999 
2000  std::pair<std::unique_ptr<Trk::Track>, std::unique_ptr<Trk::Track>> MooTrackFitter::splitTrack(const EventContext& ctx, const Trk::Track& track) const {
2001 
2002  // access TSOS of track
2003  const Trk::TrackStates* oldTSOT = track.trackStateOnSurfaces();
2004  if (!oldTSOT) return std::make_pair<std::unique_ptr<Trk::Track>, std::unique_ptr<Trk::Track>>(nullptr, nullptr);
2005 
2006  // check whether the perigee is expressed at the point of closes approach or at muon entry
2007  const Trk::Perigee* perigee = track.perigeeParameters();
2008  if (perigee) {
2009  bool atIP = std::abs(perigee->position().dot(perigee->momentum().unit())) < 10;
2010  if (atIP) {
2011  ATH_MSG_DEBUG(" track extressed at perigee, cannot split it ");
2012  return std::make_pair<std::unique_ptr<Trk::Track>, std::unique_ptr<Trk::Track>>(nullptr, nullptr);
2013  }
2014  }
2015 
2016  // loop over content input track and count perigees
2017  unsigned int nperigees(0);
2019  Trk::TrackStates::const_iterator tit_end = oldTSOT->end();
2020  for (; tit != tit_end; ++tit) {
2021  // look whether state is a perigee
2022  if ((*tit)->type(Trk::TrackStateOnSurface::Perigee) && dynamic_cast<const Trk::Perigee*>((*tit)->trackParameters()))
2023  ++nperigees;
2024  }
2025  if (nperigees != 2) {
2026  ATH_MSG_DEBUG(" Number of perigees is not one, cannot split it " << nperigees);
2027  return std::make_pair<std::unique_ptr<Trk::Track>, std::unique_ptr<Trk::Track>>(nullptr, nullptr);
2028  }
2029 
2030  struct TrackContent {
2031  TrackContent() : firstParameters(nullptr), tsos(), track() {}
2032  const Trk::TrackParameters* firstParameters;
2033  std::vector<const Trk::TrackStateOnSurface*> tsos;
2034  std::unique_ptr<Trk::Track> track;
2035  std::set<MuonStationIndex::StIndex> stations;
2036  };
2037 
2038  // store content of split tracks
2039  TrackContent firstTrack;
2040  firstTrack.tsos.reserve(oldTSOT->size());
2041 
2042  TrackContent secondTrack;
2043  secondTrack.tsos.reserve(oldTSOT->size());
2044 
2045  // keep track of the current set that is being filled
2046  TrackContent* currentTrack = &firstTrack;
2047 
2048  // count perigees on track
2049  nperigees = 0;
2050 
2051  // loop over content input track and extract the content of the two split tracks
2052  tit = oldTSOT->begin();
2053  tit_end = oldTSOT->end();
2054  for (; tit != tit_end; ++tit) {
2055  const Trk::TrackParameters* pars = (*tit)->trackParameters();
2056 
2057  // look whether state is a perigee
2058  if ((*tit)->type(Trk::TrackStateOnSurface::Perigee) && dynamic_cast<const Trk::Perigee*>(pars)) {
2059  ++nperigees;
2060 
2061  if (msgLvl(MSG::DEBUG) && nperigees == 1) msg(MSG::DEBUG) << MSG::DEBUG << " found first perigee on track " << endmsg;
2062 
2063  // if this is the second perigee, switch to second part of the track
2064  if (nperigees == 2) {
2065  ATH_MSG_DEBUG(" found second perigee, switch to second track");
2066  currentTrack = &secondTrack;
2067 
2068  } else if (nperigees > 2) {
2069  ATH_MSG_WARNING(" Unexpected number of perigees: " << nperigees);
2070  }
2071  }
2072 
2073  // we should drop all states inbetween the two perigees
2074  if (nperigees == 1) { ATH_MSG_VERBOSE(" state between the two perigees "); }
2075 
2076  // check whether the current TrackContent has firstParameters, if not set them
2077  if (!currentTrack->firstParameters) {
2078  ATH_MSG_VERBOSE(" found first parameters " << m_printer->print(*pars));
2079  currentTrack->firstParameters = pars;
2080  }
2081 
2082  // check whether there are track parameters on the current state
2083  if (!pars) {
2084  ATH_MSG_VERBOSE(" adding state without parameters ");
2085  currentTrack->tsos.push_back(*tit);
2086  continue;
2087  }
2088 
2089  // check whether state is a measurement, if not continue
2090  const Trk::MeasurementBase* meas = (*tit)->measurementOnTrack();
2091  if (!meas) {
2092  ATH_MSG_VERBOSE(" adding state without measurement " << m_printer->print(*pars));
2093  currentTrack->tsos.push_back(*tit);
2094  continue;
2095  }
2096 
2097  // get identifier, if it has no identifier or is not a muon hit continue
2098  Identifier id = m_edmHelperSvc->getIdentifier(*meas);
2099  if (!id.is_valid() || !m_idHelperSvc->isMuon(id)) {
2100  ATH_MSG_VERBOSE(" adding state with measurement without valid identifier " << m_printer->print(*pars));
2101  currentTrack->tsos.push_back(*tit);
2102  continue;
2103  }
2104 
2105  if (nperigees == 1) ATH_MSG_WARNING(" found muon measurement inbetween the two perigees, this should not happen ");
2106 
2107  // add station index for MDT and CSC hits
2108  if (!m_idHelperSvc->isTrigger(id)) currentTrack->stations.insert(m_idHelperSvc->stationIndex(id));
2109 
2110  ATH_MSG_VERBOSE(" adding " << m_printer->print(*meas));
2111 
2112  currentTrack->tsos.push_back(*tit);
2113  }
2114 
2115  if (firstTrack.firstParameters)
2116  ATH_MSG_DEBUG(" first track content: states " << firstTrack.tsos.size() << " stations " << firstTrack.stations.size() << endmsg
2117  << " first pars " << m_printer->print(*firstTrack.firstParameters));
2118 
2119  else if (secondTrack.firstParameters)
2120  ATH_MSG_DEBUG(" second track content: states " << secondTrack.tsos.size() << " stations " << secondTrack.stations.size()
2121  << endmsg << " first pars " << m_printer->print(*secondTrack.firstParameters));
2122 
2123  // check whether both tracks have start parameters and sufficient stations
2124  if ((firstTrack.firstParameters && firstTrack.stations.size() > 1) &&
2125  (secondTrack.firstParameters && secondTrack.stations.size() > 1)) {
2126  ATH_MSG_DEBUG(" track candidate can be split, trying to fit split tracks ");
2127  // fit the two tracks
2128  firstTrack.track = fitSplitTrack(ctx, *firstTrack.firstParameters, firstTrack.tsos);
2129  if (firstTrack.track) {
2130  ATH_MSG_DEBUG(" fitted first track, trying second ");
2131 
2132  secondTrack.track = fitSplitTrack(ctx, *secondTrack.firstParameters, secondTrack.tsos);
2133 
2134  if (secondTrack.track) {
2135  ATH_MSG_DEBUG(" fitted second track ");
2136 
2137  } else {
2138  ATH_MSG_DEBUG(" failed to fit second track ");
2139  firstTrack.track.reset();
2140  }
2141  } else {
2142  ATH_MSG_DEBUG(" failed to fit first track ");
2143  }
2144  }
2145 
2146  return std::make_pair<std::unique_ptr<Trk::Track>, std::unique_ptr<Trk::Track>>(std::move(firstTrack.track),
2147  std::move(secondTrack.track));
2148  }
2149 
2150  std::unique_ptr<Trk::Track> MooTrackFitter::fitSplitTrack(const EventContext& ctx, const Trk::TrackParameters& startPars,
2151  const std::vector<const Trk::TrackStateOnSurface*>& tsos) const {
2152  // first create track out of the constituent
2153  double phi = startPars.momentum().phi();
2154  double theta = startPars.momentum().theta();
2155  double qoverp = startPars.charge() / startPars.momentum().mag();
2156  if (m_slFit) qoverp = 0;
2157  Trk::PerigeeSurface persurf(startPars.position());
2158  std::unique_ptr<Trk::Perigee> perigee = std::make_unique<Trk::Perigee>(0, 0, phi, theta, qoverp, persurf);
2159 
2160  auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
2161  trackStateOnSurfaces->reserve(tsos.size() + 1);
2162  trackStateOnSurfaces->push_back(MuonTSOSHelper::createPerigeeTSOS(std::move(perigee)));
2163  for (const Trk::TrackStateOnSurface* tsos : tsos) trackStateOnSurfaces->push_back(tsos->clone());
2164 
2166  std::unique_ptr<Trk::Track> track = std::make_unique<Trk::Track>(trackInfo, std::move(trackStateOnSurfaces), nullptr);
2167 
2168  unsigned int nphi = hasPhiConstrain(track.get());
2169 
2170  if (nphi > 1) {
2171  ATH_MSG_DEBUG("Track has sufficient phi constraints, fitting ");
2172 
2173  } else {
2174  // loop over the track and find the first and last measurement and the phi hit if any
2175  const Trk::TrackStateOnSurface* firstMeas = nullptr;
2176  const Trk::TrackStateOnSurface* lastMeas = nullptr;
2177  const Trk::TrackStateOnSurface* phiMeas = nullptr;
2178 
2179  std::vector<const Trk::TrackStateOnSurface*>::const_iterator tit = tsos.begin();
2180  std::vector<const Trk::TrackStateOnSurface*>::const_iterator tit_end = tsos.end();
2181  for (; tit != tit_end; ++tit) {
2182  // require track parameters;
2183  if (!(*tit)->trackParameters()) continue;
2184 
2185  const Trk::MeasurementBase* meas = (*tit)->measurementOnTrack();
2186  if (!meas) continue;
2187 
2188  Identifier id = m_edmHelperSvc->getIdentifier(*meas);
2189  if (!id.is_valid() || !m_idHelperSvc->isMuon(id)) continue;
2190 
2191  if (m_idHelperSvc->isMdt(id)) {
2192  if (!firstMeas) firstMeas = *tit;
2193  lastMeas = *tit;
2194  } else if (m_idHelperSvc->measuresPhi(id)) {
2195  phiMeas = *tit;
2196  }
2197  }
2198 
2199  if (!firstMeas) {
2200  ATH_MSG_WARNING(" failed to find first MDT measurement with track parameters");
2201  return nullptr;
2202  }
2203 
2204  if (!lastMeas) {
2205  ATH_MSG_WARNING(" failed to find second MDT measurement with track parameters");
2206  return nullptr;
2207  }
2208 
2209  if (firstMeas == lastMeas) {
2210  ATH_MSG_WARNING(" first MDT measurement with track parameters equals to second");
2211  return nullptr;
2212  }
2213 
2214  const Trk::TrackStateOnSurface* positionFirstFake = nullptr;
2215  const Trk::TrackStateOnSurface* positionSecondFake = nullptr;
2216 
2217  if (phiMeas) {
2218  double distFirst = (firstMeas->trackParameters()->position() - phiMeas->trackParameters()->position()).mag();
2219  double distSecond = (lastMeas->trackParameters()->position() - phiMeas->trackParameters()->position()).mag();
2220  ATH_MSG_DEBUG("Track has one phi constraints, adding second: dist to first " << distFirst << " dist to second "
2221  << distSecond);
2222  // add fake at position furthest away from phi measurement
2223  if (distFirst < distSecond) {
2224  positionFirstFake = lastMeas;
2225  } else {
2226  positionFirstFake = firstMeas;
2227  }
2228 
2229  } else {
2230  ATH_MSG_DEBUG("Track has no phi constraints, adding one at beginning and one at the end of the track ");
2231 
2232  positionFirstFake = firstMeas;
2233  positionSecondFake = lastMeas;
2234  }
2235 
2236  // clean up previous track and create new one with fake hits
2237  auto uniquePerigee = std::make_unique<Trk::Perigee>(0, 0, phi, theta, qoverp, persurf);
2238  auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
2239  trackStateOnSurfaces->reserve(tsos.size() + 3);
2240  trackStateOnSurfaces->push_back(MuonTSOSHelper::createPerigeeTSOS(std::move(uniquePerigee)));
2241 
2242  tit = tsos.begin();
2243  tit_end = tsos.end();
2244  for (; tit != tit_end; ++tit) {
2245  // remove existing pseudo measurements
2246  const Trk::MeasurementBase* meas = (*tit)->measurementOnTrack();
2247  if (meas && dynamic_cast<const Trk::PseudoMeasurementOnTrack*>(meas)) {
2248  ATH_MSG_DEBUG("removing existing pseudo measurement ");
2249  continue;
2250  }
2251 
2252  trackStateOnSurfaces->push_back((*tit)->clone());
2253  if (*tit == positionFirstFake) {
2254  double fakeError = 100.;
2255  if (positionFirstFake->trackParameters()->covariance()) {
2256  fakeError = Amg::error(*positionFirstFake->trackParameters()->covariance(), Trk::loc2);
2257  ATH_MSG_DEBUG(" Using error of parameters " << fakeError);
2258  }
2259 
2260  Amg::Vector3D position = positionFirstFake->trackParameters()->position();
2261  std::unique_ptr<Trk::MeasurementBase> fake =
2262  createFakePhiForMeasurement(*(positionFirstFake->measurementOnTrack()), &position, nullptr, fakeError);
2263  if (fake) {
2264  // need to clone as fake is already added to garbage collection
2265  trackStateOnSurfaces->push_back(MuonTSOSHelper::createMeasTSOSWithUpdate(
2266  **tit, std::move(fake), positionFirstFake->trackParameters()->uniqueClone(), Trk::TrackStateOnSurface::Measurement));
2267  } else {
2268  ATH_MSG_WARNING(" failed to create fake at first measurement ");
2269  }
2270  }
2271  if (*tit == positionSecondFake && positionSecondFake) {
2272  double fakeError = 100.;
2273  if (positionSecondFake->trackParameters()->covariance()) {
2274  fakeError = Amg::error(*positionSecondFake->trackParameters()->covariance(), Trk::loc2);
2275  ATH_MSG_DEBUG(" Using error of parameters " << fakeError);
2276  }
2277 
2278  Amg::Vector3D position = positionSecondFake->trackParameters()->position();
2279  std::unique_ptr<Trk::MeasurementBase> fake =
2280  createFakePhiForMeasurement(*(positionSecondFake->measurementOnTrack()), &position, nullptr, fakeError);
2281  if (fake) {
2282  // need to clone as fake is already added to garbage collection
2283  trackStateOnSurfaces->push_back(MuonTSOSHelper::createMeasTSOSWithUpdate(
2284  **tit, std::move(fake), positionSecondFake->trackParameters()->uniqueClone(), Trk::TrackStateOnSurface::Measurement));
2285  } else {
2286  ATH_MSG_WARNING(" failed to create fake at second measurement ");
2287  }
2288  }
2289  }
2290 
2292  track = std::make_unique<Trk::Track>(trackInfo, std::move(trackStateOnSurfaces), nullptr);
2293  }
2294 
2295  // refit track
2296  std::unique_ptr<Trk::Track> refittedTrack = refit(ctx, *track);
2297  if (refittedTrack) refittedTrack->info().setPatternRecognitionInfo(m_patRecInfo);
2298 
2299  return refittedTrack;
2300  }
2301 
2302 } // namespace Muon
Muon::MooTrackFitter::cleanAndEvaluateTrack
std::unique_ptr< Trk::Track > cleanAndEvaluateTrack(const EventContext &ctx, Trk::Track &track, const std::set< Identifier > &excludedChambers) const
clean and evaluate the track,
Definition: MooTrackFitter.cxx:1840
Muon::MooTrackFitter::m_phiHitsMax
Gaudi::Property< unsigned int > m_phiHitsMax
Definition: MooTrackFitter.h:302
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
Trk::RIO_OnTrack::uniqueClone
std::unique_ptr< RIO_OnTrack > uniqueClone() const
NVI clone returning unique_ptr.
Definition: RIO_OnTrack.h:97
Muon::MooTrackFitter::m_nfits
std::atomic_uint m_nfits
Definition: MooTrackFitter.h:314
Muon::MooTrackFitter::FitterData::hitList
MuPatHitList hitList
Definition: MooTrackFitter.h:156
Muon::MooTrackFitter::m_printer
PublicToolHandle< MuonEDMPrinterTool > m_printer
tool to print out EDM objects
Definition: MooTrackFitter.h:276
Muon::MuonTSOSHelper::createPerigeeTSOS
static std::unique_ptr< Trk::TrackStateOnSurface > createPerigeeTSOS(std::unique_ptr< Trk::TrackParameters > perigee)
create a perigee TSOS, takes ownership of the Perigee
Definition: MuonTSOSHelper.h:54
Trk::anyDirection
@ anyDirection
Definition: PropDirection.h:22
TrkDriftCircleMath::MatchDCWithLine::match
const DCOnTrackVec & match(const DCVec &dcs)
Definition: MatchDCWithLine.cxx:9
Muon::MooTrackFitter::extractData
bool extractData(const MuPatCandidateBase &entry1, const MuPatCandidateBase &entry2, FitterData &fitterData) const
extract all information needed for the fit from the track
Definition: MooTrackFitter.cxx:327
make_hlt_rep.pars
pars
Definition: make_hlt_rep.py:90
beamspotman.r
def r
Definition: beamspotman.py:676
LArSamples::FitterData::fitter
const ShapeFitter * fitter
Definition: ShapeFitter.cxx:23
Trk::LocalParameters
Definition: LocalParameters.h:98
Trk::TrackStateOnSurface::trackParameters
const TrackParameters * trackParameters() const
return ptr to trackparameters const overload
Muon::MooTrackFitter::m_seedPhiWithEtaHits
Gaudi::Property< bool > m_seedPhiWithEtaHits
Definition: MooTrackFitter.h:294
MdtReadoutElement.h
Muon::MooTrackFitter::StationPhiData::nphiHits
unsigned int nphiHits
Definition: MooTrackFitter.h:329
Trk::TrackInfo
Contains information about the 'fitter' of this track.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/TrackInfo.h:32
Trk::TrackStateOnSurface::Perigee
@ Perigee
This represents a perigee, and so will contain a Perigee object only.
Definition: TrackStateOnSurface.h:117
Muon::MooTrackFitter::qOverPFromEntry
static double qOverPFromEntry(const MuPatCandidateBase &entry)
get q/p from entry
Definition: MooTrackFitter.cxx:1273
Muon::MooTrackFitter::FitterData::smallLargeChambersPerStation
SLStationMap smallLargeChambersPerStation
Definition: MooTrackFitter.h:145
DataModel_detail::const_iterator
Const iterator class for DataVector/DataList.
Definition: DVLIterator.h:82
Trk::ParticleSwitcher::particle
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:76
Muon::MooTrackFitter::FitterData::measurements
MeasVec measurements
Definition: MooTrackFitter.h:139
Muon::MooTrackFitter::createPerigee
std::unique_ptr< Trk::Perigee > createPerigee(const EventContext &ctx, const Trk::TrackParameters &firstPars, const Trk::MeasurementBase &firstMeas) const
create perigee parameter to initialize fit
Definition: MooTrackFitter.cxx:1544
Muon::MooTrackFitter::m_nfailedExtractCleaning
std::atomic_uint m_nfailedExtractCleaning
Definition: MooTrackFitter.h:318
Muon::MooTrackFitter::m_nfailedExtractInital
std::atomic_uint m_nfailedExtractInital
Definition: MooTrackFitter.h:315
Amg::VectorX
Eigen::Matrix< double, Eigen::Dynamic, 1 > VectorX
Dynamic Vector - dynamic allocation.
Definition: EventPrimitives.h:30
Amg::MatrixX
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Definition: EventPrimitives.h:27
Muon::MooTrackFitter::m_seedWithSegmentTheta
Gaudi::Property< bool > m_seedWithSegmentTheta
Definition: MooTrackFitter.h:292
Muon::MuPatCandidateBase::phiHits
const MeasVec & phiHits() const
return all phi hits on the entry
Definition: MuPatCandidateBase.cxx:57
Trk::Intersection
Definition: Intersection.h:24
Muon::MooTrackFitter::FitterData::numberOfSmallChambers
int numberOfSmallChambers()
Definition: MooTrackFitter.h:186
TRTCalib_Extractor.hits
hits
Definition: TRTCalib_Extractor.py:35
get_generator_info.result
result
Definition: get_generator_info.py:21
TrkDriftCircleMath::DCOnTrackVec
std::vector< DCOnTrack > DCOnTrackVec
Definition: DCOnTrack.h:59
Muon::MuPatCandidateBase::hasMomentum
bool hasMomentum() const
returns whether entry has a momentum measurement
Definition: MuPatCandidateBase.cxx:89
StraightLineSurface.h
MuonGM::RpcReadoutElement::StripLength
double StripLength(bool measphi) const
returns the strip length for the phi or eta plane
Muon::MooTrackFitter::refit
std::unique_ptr< Trk::Track > refit(const EventContext &ctx, const MuPatTrack &trkCan) const
refit a MuPatTrack
Definition: MooTrackFitter.cxx:116
MeasurementBase.h
Muon::MuPatCandidateBase
track candidate entry object.
Definition: MuPatCandidateBase.h:46
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
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:37
TrkDriftCircleMath::MdtId
Definition: MdtId.h:14
Trk::ParametersBase::charge
double charge() const
Returns the charge.
MuonTrackSummary.h
Trk::locY
@ locY
local cartesian
Definition: ParamDefs.h:38
Muon::MooTrackFitter::getMinMaxPhi
bool getMinMaxPhi(FitterData &fitterData) const
calculate the minimum and maximum phi value a track could have to pass all eta channels
Definition: MooTrackFitter.cxx:1131
Trk::Track
The ATLAS Track class.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/Track.h:73
Muon::MooTrackFitter::m_usePreciseHits
Gaudi::Property< bool > m_usePreciseHits
Definition: MooTrackFitter.h:295
MuonGM::MdtReadoutElement::innerTubeRadius
double innerTubeRadius() const
Returns the inner tube radius excluding the aluminium walls.
Muon::MooTrackFitter::m_hitHandler
PublicToolHandle< MuPatHitTool > m_hitHandler
hit handler
Definition: MooTrackFitter.h:263
Muon::MooTrackFitter::m_momentumEstimator
ToolHandle< IMuonSegmentMomentumEstimator > m_momentumEstimator
tool to estimate track momentum
Definition: MooTrackFitter.h:264
Trk::Surface::straightLineIntersection
Intersection straightLineIntersection(const T &pars, bool forceDir=false, const Trk::BoundaryCheck &bchk=false) const
fst straight line intersection schema - templated for charged and neutral parameters
Definition: Tracking/TrkDetDescr/TrkSurfaces/TrkSurfaces/Surface.h:352
MaterialProperties.h
MatchDCWithLine.h
Trk::PerigeeSurface
Definition: PerigeeSurface.h:43
Muon::MooTrackFitter::segmentFromEntry
std::shared_ptr< const MuonSegment > segmentFromEntry(const EventContext &ctx, const MuPatCandidateBase &entry) const
get segment from entry
Definition: MooTrackFitter.cxx:1256
sTgcReadoutElement.h
Trk::ParametersBase::position
const Amg::Vector3D & position() const
Access method for the position.
Amg::Vector2D
Eigen::Matrix< double, 2, 1 > Vector2D
Definition: GeoPrimitives.h:48
Trk::oppositeMomentum
@ oppositeMomentum
Definition: PropDirection.h:21
Muon::MooTrackFitter::m_noPerigee
std::atomic_uint m_noPerigee
Definition: MooTrackFitter.h:321
Muon::MuonStationIndex::StIndex::EM
@ EM
Trk::ParametersBase::uniqueClone
std::unique_ptr< ParametersBase< DIM, T > > uniqueClone() const
clone method for polymorphic deep copy returning unique_ptr; it is not overriden, but uses the existi...
Definition: ParametersBase.h:97
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
Trk::ParametersT
Dummy class used to allow special convertors to be called for surfaces owned by a detector element.
Definition: EMErrorDetail.h:25
Trk::Track::info
const TrackInfo & info() const
Returns a const ref to info of a const tracks.
Muon::MooTrackFitter::m_nfailedTubeFit
std::atomic_uint m_nfailedTubeFit
Definition: MooTrackFitter.h:320
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
Muon::MooTrackFitter::m_chi2Cut
Gaudi::Property< double > m_chi2Cut
Definition: MooTrackFitter.h:312
Muon::MooTrackFitter::FitterData::avePhi
double avePhi
Definition: MooTrackFitter.h:147
Muon::MooTrackFitter::m_openingAngleCut
Gaudi::Property< double > m_openingAngleCut
Definition: MooTrackFitter.h:308
Muon::MooTrackFitter::thetaSeeding
double thetaSeeding(const MuPatCandidateBase &entry, MeasVec &etaHits) const
calculate theta used for seeding the fit
Definition: MooTrackFitter.cxx:1415
EventPrimitivesHelpers.h
Muon::MooTrackFitter::m_nsuccess
std::atomic_uint m_nsuccess
Definition: MooTrackFitter.h:326
Trk::RIO_OnTrack::globalPosition
virtual const Amg::Vector3D & globalPosition() const override=0
Interface method to get the global Position.
TrkDriftCircleMath::MatchDCWithLine::Pull
@ Pull
Definition: MatchDCWithLine.h:18
MuonGM::MuonReadoutElement::GlobalToAmdbLRSTransform
virtual Amg::Transform3D GlobalToAmdbLRSTransform() const
Definition: MuonDetDescr/MuonReadoutGeometry/src/MuonReadoutElement.cxx:154
Muon::MooTrackFitter::addFakePhiHits
bool addFakePhiHits(const EventContext &ctx, FitterData &fitterData, const Trk::TrackParameters &referenceParameter) const
check fitterData, add fake phi hits if needed.
Definition: MooTrackFitter.cxx:513
Trk::LocalParameters::contains
bool contains(ParamDefs par) const
The simple check for the clients whether the parameter is contained.
skel.it
it
Definition: skel.GENtoEVGEN.py:407
Muon::MooTrackFitter::SmallLargeChambers
std::pair< int, int > SmallLargeChambers
Definition: MooTrackFitter.h:69
Muon::MuPatHit::Pseudo
@ Pseudo
Definition: MuPatHit.h:32
plotBeamSpotVxVal.cov
cov
Definition: plotBeamSpotVxVal.py:201
TrkDriftCircleMath::DCSLFitter
Definition: Tracking/TrkUtilityPackages/TrkDriftCircleMath/TrkDriftCircleMath/DCSLFitter.h:17
M_PI
#define M_PI
Definition: ActiveFraction.h:11
MuonGM::sTgcReadoutElement::getDesign
const MuonChannelDesign * getDesign(const Identifier &id) const
returns the MuonChannelDesign class for the given identifier
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/sTgcReadoutElement.h:279
Muon::MooTrackFitter::m_matEffects
Gaudi::Property< int > m_matEffects
Definition: MooTrackFitter.h:268
AthCommonMsg< AlgTool >::msgLvl
bool msgLvl(const MSG::Level lvl) const
Definition: AthCommonMsg.h:30
Muon::MooTrackFitter::m_seedWithAvePhi
Gaudi::Property< bool > m_seedWithAvePhi
Definition: MooTrackFitter.h:293
Trk::TrackStateOnSurface::measurementOnTrack
const MeasurementBase * measurementOnTrack() const
returns MeasurementBase const overload
MuPatCandidateBase.h
MuonGM::RpcReadoutElement
An RpcReadoutElement corresponds to a single RPC module; therefore typicaly a barrel muon station con...
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/RpcReadoutElement.h:55
Trk::loc2
@ loc2
generic first and second local coordinate
Definition: ParamDefs.h:35
Segment.h
Layer.h
Trk::RIO_OnTrack
Definition: RIO_OnTrack.h:70
Muon::MooTrackFitter::m_nfailedExtractPrecise
std::atomic_uint m_nfailedExtractPrecise
Definition: MooTrackFitter.h:323
Trk::alongMomentum
@ alongMomentum
Definition: PropDirection.h:20
Trk::TrkDetElementBase
Definition: TrkDetElementBase.h:52
Muon::MooTrackFitter::cleanPhiHits
bool cleanPhiHits(const EventContext &ctx, double momentum, FitterData &phiHits, const PrepVec &patternPhiHits) const
clean phi hits, returns true if anything happened during the cleaning
Definition: MooTrackFitter.cxx:1687
Muon::MooTrackFitter::m_patRecInfo
Trk::TrackInfo::TrackPatternRecoInfo m_patRecInfo
Definition: MooTrackFitter.h:270
python.TurnDataReader.dr
dr
Definition: TurnDataReader.py:112
Muon::MooTrackFitter::StationPhiData
Definition: MooTrackFitter.h:328
Trk::locR
@ locR
Definition: ParamDefs.h:44
TrkDriftCircleMath::DriftCircle
This class represents a drift time measurement.
Definition: DriftCircle.h:22
MuonGM::CscReadoutElement
Definition: CscReadoutElement.h:56
Muon::MooTrackFitter::FitterData::secondHasMomentum
bool secondHasMomentum
Definition: MooTrackFitter.h:165
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
Muon::MooTrackFitter::fitSplitTrack
std::unique_ptr< Trk::Track > fitSplitTrack(const EventContext &ctx, const Trk::TrackParameters &startPars, const std::vector< const Trk::TrackStateOnSurface * > &tsos) const
construct a track from a list of TSOS and a start parameters
Definition: MooTrackFitter.cxx:2150
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
Muon::CompetingMuonClustersOnTrack
Definition: CompetingMuonClustersOnTrack.h:54
Muon::MooTrackFitter::m_pThreshold
Gaudi::Property< double > m_pThreshold
Definition: MooTrackFitter.h:298
MdtDriftCircleOnTrack.h
InDetAccessor::qOverP
@ qOverP
perigee
Definition: InDetAccessor.h:35
Muon::MooTrackFitter::FitterData::hasBarrel
bool hasBarrel
Definition: MooTrackFitter.h:151
Trk::Surface::center
const Amg::Vector3D & center() const
Returns the center position of the Surface.
Muon
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
Definition: TrackSystemController.h:45
Muon::MooTrackFitter::m_trackToSegmentTool
ToolHandle< IMuonTrackToSegmentTool > m_trackToSegmentTool
helper tool to convert tracks into segments
Definition: MooTrackFitter.h:278
x
#define x
LArSamples::ShapeFitter::fit
bool fit(const LArSamples::AbsShape &data, const AbsShape &reference, double &k, double &deltaT, double &chi2, const ScaledErrorData *sed=0) const
Definition: ShapeFitter.cxx:32
Muon::MooTrackFitter::createFakePhiForMeasurement
std::unique_ptr< Trk::MeasurementBase > createFakePhiForMeasurement(const Trk::MeasurementBase &measurement, const Amg::Vector3D *overlapPos, const Amg::Vector3D *phiPos, double error) const
create fake phi hit on the surface of the give measurement
Definition: MooTrackFitter.cxx:826
Muon::MooTrackFitter::FitterData::firstHasMomentum
bool firstHasMomentum
Definition: MooTrackFitter.h:164
particleType
Definition: particleType.h:29
Identifier::is_valid
bool is_valid() const
Check if id is in a valid state.
Muon::MooTrackFitter::MeasCit
MeasVec::const_iterator MeasCit
Definition: MooTrackFitter.h:63
MuPatSegment.h
MuonGM::CscReadoutElement::stripLength
double stripLength(int chamberLayer, int measuresPhi, int stripNumber, double &epsilon) const
Definition: CscReadoutElement.cxx:292
MuonTrackMakerStlTools.h
Muon::MuonStationIndex::ChIndex::CSL
@ CSL
TrkDriftCircleMath::Segment
Definition: Tracking/TrkUtilityPackages/TrkDriftCircleMath/TrkDriftCircleMath/Segment.h:18
Muon::MooTrackFitter::m_slProp
Gaudi::Property< bool > m_slProp
Definition: MooTrackFitter.h:291
TrkDriftCircleMath::LocVec2D
Implementation of 2 dimensional vector class.
Definition: LocVec2D.h:16
Muon::MooTrackFitter::FitterData::phiHits
MeasVec phiHits
Definition: MooTrackFitter.h:137
Trk::DefinedParameter
std::pair< double, ParamDefs > DefinedParameter
Definition: DefinedParameter.h:27
Trk::MuonTrackSummary::chamberHitSummary
const std::vector< ChamberHitSummary > & chamberHitSummary() const
access to the vector of chamber hit summaries on the track
Definition: MuonTrackSummary.h:148
Muon::MooTrackFitter::m_preCleanChi2Cut
Gaudi::Property< double > m_preCleanChi2Cut
Definition: MooTrackFitter.h:310
Muon::MooTrackFitter::MeasVec
std::vector< const Trk::MeasurementBase * > MeasVec
Definition: MooTrackFitter.h:61
Trk::LocalDirection::angleYZ
double angleYZ() const
access method for angle of local YZ projection
Definition: LocalDirection.h:106
Track.h
MagneticFieldProperties.h
Muon::MooTrackFitter::FitterData::startPars
std::unique_ptr< Trk::Perigee > startPars
Definition: MooTrackFitter.h:158
Trk::PseudoMeasurementOnTrack
Class to handle pseudo-measurements in fitters and on track objects.
Definition: PseudoMeasurementOnTrack.h:44
Muon::MooTrackFitter::FitterData::etaHits
MeasVec etaHits
Definition: MooTrackFitter.h:138
TrkDriftCircleMath::Line
Definition: Line.h:17
Trk::LocalParameters::get
double get(ParamDefs par) const
Retrieve specified parameter (const version).
MuonGM::MMReadoutElement::stripActiveLengthRight
double stripActiveLengthRight(const Identifier &id) const
Definition: MMReadoutElement.h:240
Trk::ParticleHypothesis
ParticleHypothesis
Definition: ParticleHypothesis.h:25
MooTrackFitter.h
Muon::MooTrackFitter::FitterData::numberOfSLOverlaps
int numberOfSLOverlaps()
Definition: MooTrackFitter.h:169
Muon::MuonStationIndex::toStationIndex
StIndex toStationIndex(ChIndex index)
convert ChIndex into StIndex
Muon::MooTrackFitter::m_runOutlier
Gaudi::Property< Trk::RunOutlierRemoval > m_runOutlier
Definition: MooTrackFitter.h:267
MuonTSOSHelper.h
MMReadoutElement.h
TileDCSDataPlotter.tit
tit
Definition: TileDCSDataPlotter.py:890
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
Muon::SortMeasurementsByPosition
Definition: SortMeasurementsByPosition.h:152
Amg::toString
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Definition: GeoPrimitivesToStringConverter.h:40
Muon::MuPatCandidateBase::chamberIds
const std::set< Identifier > & chamberIds() const
returns set with contained chamber ids
Definition: MuPatCandidateBase.cxx:33
Muon::MooTrackFitter::m_cleanPhiHits
Gaudi::Property< bool > m_cleanPhiHits
Definition: MooTrackFitter.h:301
Muon::MuPatCandidateBase::etaHits
const MeasVec & etaHits() const
return all eta hits on the entry
ParticleGun_EoverP_Config.momentum
momentum
Definition: ParticleGun_EoverP_Config.py:63
Muon::MooTrackFitter::corruptEntry
bool corruptEntry(const MuPatCandidateBase &entry) const
sanity check for entries
Definition: MooTrackFitter.cxx:107
MuonGM::MdtReadoutElement
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/MdtReadoutElement.h:51
Line.h
Muon::MuonStationIndex::chIndex
ChIndex chIndex(const std::string &index)
convert ChIndex name string to enum
Definition: MuonStationIndex.cxx:11
Muon::MooTrackFitter::finalize
StatusCode finalize()
finialize method, method taken from bass-class AlgTool
Definition: MooTrackFitter.cxx:79
Muon::MuPatHitCit
MuPatHitList::const_iterator MuPatHitCit
Definition: MuPatHit.h:27
Muon::MuPatHit::OnTrack
@ OnTrack
Definition: MuPatHit.h:33
beamspotman.n
n
Definition: beamspotman.py:731
Trk::theta
@ theta
Definition: ParamDefs.h:66
SortMuPatHits.h
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::MooTrackFitter::validMomentum
bool validMomentum(const Trk::TrackParameters &pars) const
check whether mometum of start parameter is ok
Definition: MooTrackFitter.cxx:1871
urldecode::states
states
Definition: urldecode.h:39
MuonGM::MdtReadoutElement::getActiveTubeLength
double getActiveTubeLength(const int tubeLayer, const int tube) const
MuonGM::sTgcReadoutElement
An sTgcReadoutElement corresponds to a single STGC module; therefore typicaly a barrel muon station c...
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/sTgcReadoutElement.h:30
Muon::MuonSegment::localDirection
const Trk::LocalDirection & localDirection() const
local direction
Definition: MuonSpectrometer/MuonReconstruction/MuonRecEvent/MuonSegment/MuonSegment/MuonSegment.h:169
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
Trk::Segment::containedMeasurements
const std::vector< const Trk::MeasurementBase * > & containedMeasurements() const
returns the vector of Trk::MeasurementBase objects
Definition: Tracking/TrkEvent/TrkSegment/TrkSegment/Segment.h:166
MuPatTrack.h
CscReadoutElement.h
Muon::MuPatSegment::segment
const MuonSegment * segment
Definition: MuPatSegment.h:53
MuonGM::TgcReadoutElement
A TgcReadoutElement corresponds to a single TGC chamber; therefore typically a TGC station contains s...
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/TgcReadoutElement.h:42
PseudoMeasurementOnTrack.h
Muon::MooTrackFitter::StationPhiData::nLargeChambers
unsigned int nLargeChambers
Definition: MooTrackFitter.h:331
sign
int sign(int a)
Definition: TRT_StrawNeighbourSvc.h:107
Trk::TrkDetElementBase::surface
virtual const Surface & surface() const =0
Return surface associated with this detector element.
Muon::MooTrackFitter::FitterData::phiMax
double phiMax
Definition: MooTrackFitter.h:149
Muon::MooTrackFitter::m_nfailedFakePrecise
std::atomic_uint m_nfailedFakePrecise
Definition: MooTrackFitter.h:324
AnalysisUtils::copy_if
Out copy_if(In first, const In &last, Out res, const Pred &p)
Definition: IFilterUtils.h:30
Muon::MooTrackFitter::FitterData::hasEndcap
bool hasEndcap
Definition: MooTrackFitter.h:152
Muon::MdtPrepData::globalPosition
virtual const Amg::Vector3D & globalPosition() const
Returns the global position of the CENTER of the drift tube (i.e.
Definition: MdtPrepData.h:133
find_tgc_unfilled_channelids.ip
ip
Definition: find_tgc_unfilled_channelids.py:3
Trk::Surface::normal
virtual const Amg::Vector3D & normal() const
Returns the normal vector of the Surface (i.e.
Muon::MuonStationIndex::ChIndex::CSS
@ CSS
Muon::MooTrackFitter::m_usePrefit
Gaudi::Property< bool > m_usePrefit
Definition: MooTrackFitter.h:296
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Muon::MooTrackFitter::FitterData::firstEntry
const MuPatCandidateBase * firstEntry
Definition: MooTrackFitter.h:153
Muon::MooTrackFitter::removeSegmentOutliers
void removeSegmentOutliers(FitterData &fitterData) const
Definition: MooTrackFitter.cxx:1985
Trk::MuonTrackSummary
Detailed track summary for the muon system Give access to hit counts per chamber.
Definition: MuonTrackSummary.h:26
Muon::MooTrackFitter::m_preciseFirstStation
Gaudi::Property< bool > m_preciseFirstStation
Definition: MooTrackFitter.h:305
TrackSummary.h
Muon::MuPatHit::MDT
@ MDT
Definition: MuPatHit.h:32
Trk::ParametersBase
Definition: ParametersBase.h:55
TrkDriftCircleMath::MatchDCWithLine
Definition: MatchDCWithLine.h:16
Muon::MooTrackFitter::m_ParticleHypothesis
Trk::ParticleHypothesis m_ParticleHypothesis
nomen est omen
Definition: MooTrackFitter.h:269
Muon::MooTrackFitter::m_nlowMomentum
std::atomic_uint m_nlowMomentum
Definition: MooTrackFitter.h:322
Trk::muon
@ muon
Definition: ParticleHypothesis.h:28
Muon::MooTrackFitter::FitterData::stations
std::set< MuonStationIndex::StIndex > stations
Definition: MooTrackFitter.h:155
MuonGM::TgcReadoutElement::gangCentralWidth
double gangCentralWidth(int gasGap, int gang) const
Returns the length of the central wire in the gang.
Definition: MuonDetDescr/MuonReadoutGeometry/src/TgcReadoutElement.cxx:92
DataVector< const Trk::TrackStateOnSurface >
WriteCalibToCool.swap
swap
Definition: WriteCalibToCool.py:94
Muon::MooTrackFitter::m_nfailedMinMaxPhi
std::atomic_uint m_nfailedMinMaxPhi
Definition: MooTrackFitter.h:316
TrkDriftCircleMath::DCOnTrack::OnTrack
@ OnTrack
Definition: DCOnTrack.h:20
Muon::MuPatHitPtr
std::shared_ptr< MuPatHit > MuPatHitPtr
Definition: MuPatHit.h:25
SortMeasurementsByPosition.h
trackInfo
Definition: TrigInDetUtils.h:13
Trk::FullField
@ FullField
Field is set to be realistic, but within a given Volume.
Definition: MagneticFieldMode.h:21
Muon::MooTrackFitter::m_phiHitSelector
ToolHandle< IMuonHitSelector > m_phiHitSelector
tool to clean phi hits
Definition: MooTrackFitter.h:282
Muon::MooTrackFitter::FitterData::secondEntry
const MuPatCandidateBase * secondEntry
Definition: MooTrackFitter.h:154
Muon::MuPatCandidateBase::entryPars
virtual const Trk::TrackParameters & entryPars() const =0
return track parameters representing the entry
Trk::MeasurementBase::localCovariance
const Amg::MatrixX & localCovariance() const
Interface method to get the localError.
Definition: MeasurementBase.h:138
beamspotman.dir
string dir
Definition: beamspotman.py:623
Muon::MooTrackFitter::restrictedMomentum
static double restrictedMomentum(double momentum)
impose upper and lower bound on momentum
Definition: MooTrackFitter.cxx:1589
Muon::MuonStationIndex::StIndex
StIndex
enum to classify the different station layers in the muon spectrometer
Definition: MuonStationIndex.h:23
Trk::PrepRawData
Definition: PrepRawData.h:62
Trk::MeasurementBase
Definition: MeasurementBase.h:58
GetAllXsec.entry
list entry
Definition: GetAllXsec.py:132
Trk::Track::trackParameters
const DataVector< const TrackParameters > * trackParameters() const
Return a pointer to a vector of TrackParameters.
Definition: Tracking/TrkEvent/TrkTrack/src/Track.cxx:97
Trk::NoField
@ NoField
Field is set to 0., 0., 0.,.
Definition: MagneticFieldMode.h:18
Muon::MooTrackFitter::FitterData::firstIsTrack
bool firstIsTrack
Definition: MooTrackFitter.h:162
Trk::Track::perigeeParameters
const Perigee * perigeeParameters() const
return Perigee.
Definition: Tracking/TrkEvent/TrkTrack/src/Track.cxx:163
Trk::TrackStateOnSurface
represents the track state (measurement, material, fit parameters and quality) at a surface.
Definition: TrackStateOnSurface.h:71
Trk::PseudoMeasurementOnTrack::globalPosition
virtual const Amg::Vector3D & globalPosition() const override final
returns the global Position (interface from MeasurementBase)
Definition: PseudoMeasurementOnTrack.h:122
Trk::TrackSummary
A summary of the information contained by a track.
Definition: Tracking/TrkEvent/TrkTrackSummary/TrkTrackSummary/TrackSummary.h:287
Trk::MeasurementBase::associatedSurface
virtual const Surface & associatedSurface() const =0
Interface method to get the associated Surface.
TrackInfo.h
python.subdetectors.mmg.ids
ids
Definition: mmg.py:8
Muon::MooTrackFitter::m_allowFirstFit
Gaudi::Property< bool > m_allowFirstFit
Definition: MooTrackFitter.h:297
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
Muon::MooTrackFitter::initialize
StatusCode initialize()
initialize method, method taken from bass-class AlgTool
Definition: MooTrackFitter.cxx:57
Muon::MooTrackFitter::m_cosmics
Gaudi::Property< bool > m_cosmics
Definition: MooTrackFitter.h:300
Muon::MdtDriftCircleOnTrack
This class represents the corrected MDT measurements, where the corrections include the effects of wi...
Definition: MdtDriftCircleOnTrack.h:37
Muon::MooTrackFitter::MooTrackFitter
MooTrackFitter(const std::string &, const std::string &, const IInterface *)
default AlgTool constructor
Definition: MooTrackFitter.cxx:53
Muon::MooTrackFitter::FitterData::phiMin
double phiMin
Definition: MooTrackFitter.h:148
Muon::MuPatCandidateBase::hasEndcap
bool hasEndcap() const
returns whether the entry contains endcap hits
Definition: MuPatCandidateBase.cxx:71
Muon::MooTrackFitter::m_trackSummaryTool
ToolHandle< Trk::ITrackSummaryHelperTool > m_trackSummaryTool
Definition: MooTrackFitter.h:287
Muon::MooTrackFitter::m_nfailedFitPrecise
std::atomic_uint m_nfailedFitPrecise
Definition: MooTrackFitter.h:325
Trk::MeasurementBase::globalPosition
virtual const Amg::Vector3D & globalPosition() const =0
Interface method to get the global Position.
Muon::MooTrackFitter::cleanSegment
void cleanSegment(const MuonSegment &seg, std::set< Identifier > &removedIdentifiers) const
Definition: MooTrackFitter.cxx:1892
Muon::MooTrackFitter::FitterData::firstLastMeasurements
MeasVec firstLastMeasurements
Definition: MooTrackFitter.h:140
columnar::operator()
decltype(auto) operator()(ObjectId< OT, CM > id) const noexcept
Definition: ColumnAccessor.h:175
Muon::MuPatCandidateBase::containsStation
bool containsStation(MuonStationIndex::StIndex chIndex) const
returns whether the StationIndex is already contained in candidate
Definition: MuPatCandidateBase.cxx:79
Muon::CompetingMuonClustersOnTrack::containedROTs
const std::vector< const MuonClusterOnTrack * > & containedROTs() const
returns the vector of SCT_ClusterOnTrack objects .
Definition: CompetingMuonClustersOnTrack.h:184
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
Muon::MuPatHitList
std::vector< MuPatHitPtr > MuPatHitList
Definition: MuPatHit.h:26
Muon::MooTrackFitter::PrepVec
std::vector< const Trk::PrepRawData * > PrepVec
Definition: MooTrackFitter.h:65
Muon::MooTrackFitter::m_nfailedParsInital
std::atomic_uint m_nfailedParsInital
Definition: MooTrackFitter.h:317
Muon::MuPatSegment
segment candidate object.
Definition: MuPatSegment.h:43
Muon::MooTrackFitter::m_propagator
ToolHandle< Trk::IPropagator > m_propagator
propagator
Definition: MooTrackFitter.h:260
Trk::MeasurementBase::localParameters
const LocalParameters & localParameters() const
Interface method to get the LocalParameters.
Definition: MeasurementBase.h:132
Muon::MooTrackFitter::m_magFieldProperties
Trk::MagneticFieldProperties m_magFieldProperties
magnetic field properties
Definition: MooTrackFitter.h:271
MuonGM::MuonChannelDesign::channelLength
double channelLength(int channel) const
STRIPS ONLY: calculate channel length for a given strip number.
Definition: MuonChannelDesign.h:386
Muon::MuPatCandidateBase::hasSLOverlap
bool hasSLOverlap() const
returns whether there is at least one small/large overlap in the same station layer
Definition: MuPatCandidateBase.cxx:47
DataVector::end
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
Muon::MooTrackFitter::hasPhiConstrain
unsigned int hasPhiConstrain(FitterData &inputData) const
check whether data has sufficient phi constraints
Definition: MooTrackFitter.cxx:977
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::MooTrackFitter::FitterData::numberOfLargeChambers
int numberOfLargeChambers()
Definition: MooTrackFitter.h:190
Muon::MooTrackFitter::m_nfailedFakeInitial
std::atomic_uint m_nfailedFakeInitial
Definition: MooTrackFitter.h:319
Muon::MooTrackFitter::StationPhiData::nSmallChambers
unsigned int nSmallChambers
Definition: MooTrackFitter.h:330
Muon::MuPatCandidateBase::containsChamber
bool containsChamber(MuonStationIndex::ChIndex chIndex) const
returns whether the ChamberIndex is already contained in candidate
Definition: MuPatCandidateBase.cxx:75
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
Muon::MuPatTrack::track
Trk::Track & track() const
access to track
Definition: MuPatTrack.h:175
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::MooTrackFitter::m_cleaner
ToolHandle< IMuonTrackCleaner > m_cleaner
Definition: MooTrackFitter.h:284
Amg::intersect
std::optional< double > intersect(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
Calculates the point B' along the line B that's closest to a second line A.
Definition: GeoPrimitivesHelpers.h:347
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Muon::MuPatCandidateBase::hitList
const MuPatHitList & hitList() const
returns a reference to the hit list
Definition: MuPatCandidateBase.h:108
GeoPrimitivesHelpers.h
Muon::MuPatTrack
track candidate object.
Definition: MuPatTrack.h:37
MuonGM::MuonReadoutElement::getStationType
std::string getStationType() const
Definition: MuonDetDescr/MuonReadoutGeometry/MuonReadoutGeometry/MuonReadoutElement.h:189
Trk::RIO_OnTrack::identify
Identifier identify() const
return the identifier -extends MeasurementBase
Definition: RIO_OnTrack.h:152
DEBUG
#define DEBUG
Definition: page_access.h:11
Muon::MooTrackFitter::fitWithRefit
std::unique_ptr< Trk::Track > fitWithRefit(const EventContext &ctx, const Trk::Perigee &startPars, MeasVec &hits) const
fit track, refit if needed
Definition: MooTrackFitter.cxx:1651
Muon::IMuonSegmentInOverlapResolvingTool::SegmentMatchResult
Definition: IMuonSegmentInOverlapResolvingTool.h:133
AthCommonMsg< AlgTool >::msg
MsgStream & msg() const
Definition: AthCommonMsg.h:24
Trk::qOverP
@ qOverP
perigee
Definition: ParamDefs.h:67
Muon::MooTrackFitter::splitTrack
std::pair< std::unique_ptr< Trk::Track >, std::unique_ptr< Trk::Track > > splitTrack(const EventContext &ctx, const Trk::Track &track) const
split given track if it crosses the calorimeter volume, code assumes that the track was already extra...
Definition: MooTrackFitter.cxx:2000
GeoPrimitivesToStringConverter.h
Muon::MooTrackFitter::FitterData::secondIsTrack
bool secondIsTrack
Definition: MooTrackFitter.h:163
Muon::MooTrackFitter::m_slFit
Gaudi::Property< bool > m_slFit
Definition: MooTrackFitter.h:290
MuonGM::MMReadoutElement
An MMReadoutElement corresponds to a single STGC module; therefore typicaly a barrel muon station con...
Definition: MMReadoutElement.h:25
TrkDriftCircleMath::DCOnTrack
class representing a drift circle meaurement on segment
Definition: DCOnTrack.h:16
Muon::MooTrackFitter::m_trackFitter
ToolHandle< Trk::ITrackFitter > m_trackFitter
fitter
Definition: MooTrackFitter.h:262
MuonSegment.h
Muon::MuonTSOSHelper::createMeasTSOSWithUpdate
static std::unique_ptr< Trk::TrackStateOnSurface > createMeasTSOSWithUpdate(const Trk::TrackStateOnSurface &tsos, std::unique_ptr< Trk::MeasurementBase > meas, std::unique_ptr< Trk::TrackParameters > pars, Trk::TrackStateOnSurface::TrackStateOnSurfaceType type)
create a TSOS with a measurement, takes ownership of the pointers
Definition: MuonTSOSHelper.h:74
TgcReadoutElement.h
TrkDriftCircleMath::SegmentFinder
Definition: SegmentFinder.h:32
Muon::MooTrackFitter::phiSeeding
double phiSeeding(const EventContext &ctx, FitterData &fitterData) const
calculate phi used to for seeding the fit
Definition: MooTrackFitter.cxx:1312
Trk::phi
@ phi
Definition: ParamDefs.h:75
Muon::MuonSegment::globalPosition
virtual const Amg::Vector3D & globalPosition() const override final
global position
Definition: MuonSpectrometer/MuonReconstruction/MuonRecEvent/MuonSegment/MuonSegment/MuonSegment.h:157
Muon::MuonStationIndex::ChIndex
ChIndex
enum to classify the different chamber layers in the muon spectrometer
Definition: MuonStationIndex.h:15
LocalDirection.h
Muon::MooTrackFitter::FitterData
Definition: MooTrackFitter.h:133
Muon::MooTrackFitter::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: MooTrackFitter.h:272
LArCellBinning.phiRange
phiRange
Filling Phi ranges.
Definition: LArCellBinning.py:107
Muon::MooTrackFitter::fit
std::unique_ptr< Trk::Track > fit(const EventContext &ctx, const MuPatCandidateBase &firstEntry, const MuPatCandidateBase &secondEntry, const PrepVec &externalPhiHits) const
fit the hits of two MuPatCandidateBase
Definition: MooTrackFitter.cxx:176
Trk::RIO_OnTrack::detectorElement
virtual const TrkDetElementBase * detectorElement() const =0
returns the detector element, assoicated with the PRD of this class
Trk::TrackInfo::setPatternRecognitionInfo
void setPatternRecognitionInfo(const TrackPatternRecoInfo &patternReco)
Method setting the pattern recognition algorithm.
Muon::MooTrackFitter::cleanEntry
void cleanEntry(const MuPatCandidateBase &entry, std::set< Identifier > &removedIdentifiers) const
Definition: MooTrackFitter.cxx:1880
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:13
Muon::MuonSegment
Definition: MuonSpectrometer/MuonReconstruction/MuonRecEvent/MuonSegment/MuonSegment/MuonSegment.h:45
Muon::MooTrackFitter::createStartParameters
void createStartParameters(const EventContext &ctx, FitterData &inputData) const
create a perigee parameter give the input data
Definition: MooTrackFitter.cxx:1439
AthAlgTool
Definition: AthAlgTool.h:26
Muon::DistanceAlongParameters
Definition: SortMuPatHits.h:16
Trk::TrackSummary::muonTrackSummary
const MuonTrackSummary * muonTrackSummary() const
returns a pointer to the MuonTrackSummary if available
TrackSurfaceIntersection.h
Trk::Surface
Definition: Tracking/TrkDetDescr/TrkSurfaces/TrkSurfaces/Surface.h:79
Amg::distance
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
Definition: GeoPrimitivesHelpers.h:54
Trk::Surface::transform
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
Trk::TrkDetElementBase::center
virtual const Amg::Vector3D & center() const =0
Return the center of the element.
Intersection.h
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
python.TrkVertexSeedFinderToolsConfig.finder
finder
Definition: TrkVertexSeedFinderToolsConfig.py:99
LocVec2D.h
Trk::ParametersT::clone
virtual ParametersT< DIM, T, S > * clone() const override final
Virtual clone.
Muon::MuPatCandidateBase::hits
const MeasVec & hits() const
return all hits on the entry.
Definition: MuPatCandidateBase.cxx:61
Muon::MdtPrepData::detectorElement
virtual const MuonGM::MdtReadoutElement * detectorElement() const override
Returns the detector element corresponding to this PRD.
Definition: MdtPrepData.h:141
Muon::MooTrackFitter::m_seedAtStartOfTrack
Gaudi::Property< bool > m_seedAtStartOfTrack
Definition: MooTrackFitter.h:304
mag
Scalar mag() const
mag method
Definition: AmgMatrixBasePlugin.h:26
Muon::MuPatCandidateBase::stations
const std::set< MuonStationIndex::StIndex > & stations() const
returns set with contained stationIndices
Definition: MuPatCandidateBase.cxx:29
Muon::MuonStationIndex::StIndex::EI
@ EI
Muon::DistanceToPars
Definition: SortMeasurementsByPosition.h:20
Trk::Surface::localToGlobal
virtual void localToGlobal(const Amg::Vector2D &locp, const Amg::Vector3D &mom, Amg::Vector3D &glob) const =0
Specified by each surface type: LocalToGlobal method without dynamic memory allocation.
Trk::TrackStateOnSurface::Measurement
@ Measurement
This is a measurement, and will at least contain a Trk::MeasurementBase.
Definition: TrackStateOnSurface.h:101
Muon::MooTrackFitter::qOverPFromEntries
double qOverPFromEntries(const EventContext &ctx, const MuPatCandidateBase &firstEntry, const MuPatCandidateBase &secondEntry) const
get q/p using angle + position of the two entries
Definition: MooTrackFitter.cxx:1277
Muon::MuPatHit::sTGC
@ sTGC
Definition: MuPatHit.h:32
Muon::MooTrackFitter::m_edmHelperSvc
ServiceHandle< IMuonEDMHelperSvc > m_edmHelperSvc
multi purpose helper tool
Definition: MooTrackFitter.h:273
Muon::MuonClusterOnTrack
Base class for Muon cluster RIO_OnTracks.
Definition: MuonClusterOnTrack.h:34
Muon::MuonSegment::associatedSurface
virtual const Trk::PlaneSurface & associatedSurface() const override final
returns the surface for the local to global transformation
Definition: MuonSpectrometer/MuonReconstruction/MuonRecEvent/MuonSegment/MuonSegment/MuonSegment.h:175
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
Muon::MooTrackFitter::m_overlapResolver
ToolHandle< IMuonSegmentInOverlapResolvingTool > m_overlapResolver
Definition: MooTrackFitter.h:285
Muon::MuonSegment::globalDirection
const Amg::Vector3D & globalDirection() const
global direction
Definition: MuonSpectrometer/MuonReconstruction/MuonRecEvent/MuonSegment/MuonSegment/MuonSegment.h:163
Amg::setThetaPhi
void setThetaPhi(Amg::Vector3D &v, double theta, double phi)
sets the theta and phi angle of a vector without changing the magnitude
Definition: GeoPrimitivesHelpers.h:70
generate::Zero
void Zero(TH1D *hin)
Definition: generate.cxx:32
Muon::MuonStationIndex::isSmall
bool isSmall(const ChIndex index)
Returns true if the chamber index is in a small sector.
NSWL1::PadTriggerAdapter::segment
Muon::NSW_PadTriggerSegment segment(const NSWL1::PadTrigger &data)
Definition: PadTriggerAdapter.cxx:5
Muon::MooTrackFitter::getElementHalfLengths
std::pair< double, double > getElementHalfLengths(const Identifier &id, const Trk::TrkDetElementBase *ele) const
Definition: MooTrackFitter.cxx:1093
Muon::MooTrackFitter::FitterData::garbage
std::vector< std::unique_ptr< const Trk::MeasurementBase > > garbage
Definition: MooTrackFitter.h:160
TrkDriftCircleMath::DriftCircle::InTime
@ InTime
drift time too small to be compatible with drift spectrum
Definition: DriftCircle.h:27
RpcReadoutElement.h
MuonGM::MMReadoutElement::stripActiveLengthLeft
double stripActiveLengthLeft(const Identifier &id) const
Definition: MMReadoutElement.h:228
Trk::TrackInfo::Unknown
@ Unknown
Track fitter not defined.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/TrackInfo.h:41
Identifier
Definition: IdentifierFieldParser.cxx:14
SCT_Monitoring::summary
@ summary
Definition: SCT_MonitoringNumbers.h:65