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