ATLAS Offline Software
MuonTrackExtrapolationTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3  */
4 
6 
7 
8 
18 #include "TrkTrack/Track.h"
21 #include <memory>
22 #include <map>
23 
24 namespace Muon {
25 
26  MuonTrackExtrapolationTool::MuonTrackExtrapolationTool(const std::string &ty, const std::string &na, const IInterface *pa) :
27  AthAlgTool(ty, na, pa) {
28  declareInterface<IMuonTrackExtrapolationTool>(this);
29  }
30 
32  ATH_CHECK(m_edmHelperSvc.retrieve());
33  ATH_CHECK(m_printer.retrieve());
34  ATH_CHECK(m_idHelperSvc.retrieve());
35  if (!m_atlasExtrapolator.empty()) ATH_CHECK(m_atlasExtrapolator.retrieve());
36  if (!m_muonExtrapolator.empty()) ATH_CHECK(m_muonExtrapolator.retrieve());
39  } else {
40  ATH_MSG_ERROR("Could not retrieve a valid tracking geometry");
41  }
43 
44  if (m_cosmics) ATH_MSG_DEBUG("Running in cosmics mode");
45 
46  return StatusCode::SUCCESS;
47  }
48 
49  std::unique_ptr<Trk::TrackParameters> MuonTrackExtrapolationTool::extrapolateToMuonEntryRecord(const EventContext &ctx,
51  Trk::ParticleHypothesis particleHypo) const {
52  if (m_muonExtrapolator.empty()) return nullptr;
53  const Trk::TrackingVolume *msEntrance = getVolume(m_msEntranceName, ctx);
54 
55  if (!msEntrance) {
56  ATH_MSG_WARNING(" MS entrance not found");
57  return nullptr;
58  }
59 
61  if (msEntrance->inside(pars.position())) { dir = Trk::alongMomentum; }
62 
63  if (m_cosmics) {
64  // for cosmics try both directions
65  std::unique_ptr<Trk::TrackParameters> entryPars =
66  m_muonExtrapolator->extrapolateToVolume(ctx, pars, *msEntrance, Trk::oppositeMomentum, particleHypo);
67  if (!entryPars) {
68  ATH_MSG_VERBOSE(" failed to extrapolate opposite momentum");
69  // retry in other direction
70  entryPars = m_muonExtrapolator->extrapolateToVolume(ctx, pars, *msEntrance, Trk::alongMomentum, particleHypo);
71  if (!entryPars) ATH_MSG_VERBOSE(" failed to extrapolate along momentum for the second trial");
72  }
73  return entryPars;
74  }
75 
76  return m_muonExtrapolator->extrapolateToVolume(ctx, pars, *msEntrance, dir, particleHypo);
77  }
78 
79  std::unique_ptr<Trk::TrackParameters> MuonTrackExtrapolationTool::extrapolateToIP(const EventContext& ctx, const Trk::TrackParameters &pars,
80  Trk::ParticleHypothesis particleHypo) const {
81  if (m_atlasExtrapolator.empty()) return nullptr;
82  // temporary hack to avoid crashes in Muid.
83  Amg::Vector3D refPos(0.1, 0.1, 0.1);
84  Trk::PerigeeSurface persurf(refPos);
85 
86  double dirPosProduct = (pars.position() - refPos).dot(pars.momentum());
87  Trk::PropDirection propDir = dirPosProduct < 0. ? Trk::alongMomentum : Trk::oppositeMomentum;
88 
89  ATH_MSG_VERBOSE(" extrapolating to IP: " << m_printer->print(pars) << std::setprecision(2) << " pos " << pars.position() << " dir "
90  << pars.momentum().unit()
91  << (propDir == Trk::alongMomentum ? " going along momentum"
92  : propDir == Trk::oppositeMomentum ? " going opposite momentum"
93  : ""));
94 
95  // for cosmics try both directions
96  std::unique_ptr<Trk::TrackParameters> entryPars =
97  m_atlasExtrapolator->extrapolate(ctx, pars, persurf, propDir, false, particleHypo);
98  if (!entryPars) ATH_MSG_VERBOSE(" failed to extrapolate to IP");
99 
100  if (m_cosmics && !entryPars) {
101  // flip propagation direction and retry in other direction
103  entryPars = m_atlasExtrapolator->extrapolate(ctx, pars, persurf, propDir, false, particleHypo);
104  if (!entryPars) ATH_MSG_VERBOSE(" failed to extrapolate to IP in opposite direction");
105  }
106 
107  return entryPars;
108  }
109 
111  const Trk::Track &track) const {
112  const Trk::TrackingVolume *msEntrance = getVolume(m_msEntranceName, ctx);
113 
114  if (!msEntrance) {
115  ATH_MSG_WARNING("Failed to obtain muon entry volume");
116  return nullptr;
117  }
118  const Trk::Perigee *pp = track.perigeeParameters();
119  if (!pp) return nullptr;
120 
121  const Trk::TrackParameters *closestPars = pp;
122  const Trk::TrackParameters *closestMeasPars = pp->covariance() ? pp : nullptr;
123 
124  double perp = pp->associatedSurface().center().perp();
125  double z = pp->associatedSurface().center().z();
126  ATH_MSG_DEBUG(" perigee surface position: r " << perp << " z " << z);
127 
128  if (m_cosmics) {
129  // for cosmics we have to find the closest track parameters to the muon entry record
130 
131  double minDistance = 1e9;
132  double minMeasDistance = 1e9;
133 
134  ATH_MSG_DEBUG(" Cosmic model, starting for measurement closest to muon entry record ");
135  const Trk::TrackStates *oldTSOT = track.trackStateOnSurfaces();
136  for (const Trk::TrackStateOnSurface *surf : *oldTSOT) {
137  const Trk::TrackParameters *pars = surf->trackParameters();
138  if (!pars) { continue; }
139 
140  // drop states without measurement
141  if (!surf->measurementOnTrack()) continue;
142 
143  double distance = pars->position().perp(); // estimateDistanceToEntryRecord(ctx, *pars);
144  if (distance < minDistance) {
145  minDistance = distance;
146  closestPars = pars;
147  }
148 
149  if (pars->covariance() && distance < minMeasDistance) {
150  minMeasDistance = distance;
151  closestMeasPars = pars;
152  }
153  const Trk::MeasurementBase *meas = surf->measurementOnTrack();
154  ATH_MSG_VERBOSE(" Dist: " << std::setw(6) << (int)distance << " r " << std::setw(5) << (int)pars->position().perp() << " z "
155  << std::setw(6) << (int)pars->position().z() << (pars->covariance() ? " measured" : "")
156  << (meas ? m_idHelperSvc->toString(m_edmHelperSvc->getIdentifier(*meas)) : ""));
157  }
158 
159  } else if (perp < 1000. && std::abs(z) < 1000.) {
160  ATH_MSG_VERBOSE(" track at IP, starting from closest measurement in muon spectrometer ");
161  const Trk::TrackStates *oldTSOT = track.trackStateOnSurfaces();
162  for (const Trk::TrackStateOnSurface *surf : *oldTSOT) {
163  const Trk::TrackParameters *pars = surf->trackParameters();
164  if (!pars) { continue; }
165 
166  // check whether state is a measurement
167  const Trk::MeasurementBase *meas = surf->measurementOnTrack();
168  if (!meas) { continue; }
169 
170  const Trk::PseudoMeasurementOnTrack *pseudo = dynamic_cast<const Trk::PseudoMeasurementOnTrack *>(meas);
171  if (pseudo) { continue; }
172 
173  Identifier id = m_edmHelperSvc->getIdentifier(*meas);
174  if (!m_idHelperSvc->isMuon(id)) continue;
175 
176  closestPars = pars;
177 
178  break;
179  }
180  }
181 
182  // if we have MeasuredTrackParameters, use those, else return pars
183  if (closestMeasPars) {
184  ATH_MSG_DEBUG(" closest measured parameters: " << m_printer->print(*closestMeasPars));
185  return closestMeasPars;
186  }
187  if (closestPars) ATH_MSG_DEBUG(" closest parameters: " << m_printer->print(*closestPars));
188 
189  return closestPars;
190  }
191 
193  const Trk::TrackingVolume *msEntrance = getVolume("Calo::Container", ctx);
194 
195  if (!msEntrance) return 0;
196 
197  // get boundary surfaces of muon entry record
198  const auto& boundarySurfs = msEntrance->boundarySurfaces();
199 
200  double minDistance = 1e9;
201 
202  // loop over surfaces and find the closest to the parameters
203  for (size_t ib =0 ; !boundarySurfs.empty();++ib) {
204  const Trk::Surface &surf = boundarySurfs[ib]->surfaceRepresentation();
205  Trk::DistanceSolution solution = surf.straightLineDistanceEstimate(pars.position(), pars.momentum());
206  double distance = solution.currentDistance();
207  if (distance < minDistance) minDistance = distance;
208  }
209  return minDistance;
210  }
211 
213  const Trk::Track &track) {
214  double dirPosProduct = firstCrossing.position().dot(firstCrossing.momentum());
215  double sign = dirPosProduct < 0. ? 1. : -1.;
216  // create new TSOS DataVector and reserve enough space to fit all old TSOS + one new TSOS
217  const Trk::TrackStates *oldTSOT = track.trackStateOnSurfaces();
218 
219  Amg::Vector3D perDir = firstCrossing.momentum().unit();
220  double minDistance = 1e9;
221  double minMeasDistance = 1e9;
222  const Trk::TrackParameters *closestPars = nullptr;
223  const Trk::TrackParameters *closestMeasPars = nullptr;
224 
225  for (const Trk::TrackStateOnSurface *surf : *oldTSOT) {
226  // do not consider perigee
227  if (surf->type(Trk::TrackStateOnSurface::Perigee)) continue;
228 
229  // drop states without parameters
230  const Trk::TrackParameters *pars = surf->trackParameters();
231  if (!pars) continue;
232 
233  // drop states without measurement
234  if (!surf->measurementOnTrack()) continue;
235 
236  double distanceOfPerigeeToCurrent = (pars->position() - firstCrossing.position()).dot(perDir);
237 
238  if (sign * distanceOfPerigeeToCurrent > 0.) {
239  double distance = std::abs(distanceOfPerigeeToCurrent);
240  if (distance < minDistance) {
241  minDistance = distance;
242  closestPars = pars;
243  }
244  if (pars->covariance() && distance < minMeasDistance) {
245  minMeasDistance = distance;
246  closestMeasPars = pars;
247  }
248  }
249  }
250  // if we have MeasuredTrackParameters, use those, else return pars
251  return closestMeasPars ? closestMeasPars : closestPars;
252  }
253 
254  std::unique_ptr<Trk::Track> MuonTrackExtrapolationTool::extrapolate(const Trk::Track &track, const EventContext &ctx) const {
255  if (m_muonExtrapolator.empty()) return nullptr;
256  // if straightline track and the field is on return nullptr
257  bool isSL = m_edmHelperSvc->isSLTrack(track);
258  if (isSL) { // check isSL first to limit access overhead
259  MagField::AtlasFieldCache fieldCache;
260  // Get field cache object
262  const AtlasFieldCacheCondObj *fieldCondObj{*readHandle};
263 
264  if (!fieldCondObj) {
265  ATH_MSG_ERROR("Failed to retrieve AtlasFieldCacheCondObj with key " << m_fieldCacheCondObjInputKey.key());
266  return nullptr;
267  }
268  fieldCondObj->getInitializedCache(fieldCache);
269  if (fieldCache.toroidOn()) { return nullptr; }
270  }
271 
272  const Trk::Perigee *pp = track.perigeeParameters();
273  if (!pp) return nullptr;
274 
276  if (!firstPars) {
277  ATH_MSG_WARNING("failed to find closest parameters to muon entry ");
278  return nullptr;
279  }
280 
281  // extrapolate to muon entry record
282  Trk::ParticleHypothesis particleHypo = track.info().particleHypothesis();
283  if (isSL) particleHypo = Trk::nonInteracting;
284  std::shared_ptr<Trk::TrackParameters>exPars{extrapolateToMuonEntryRecord(ctx, *firstPars, particleHypo)};
285 
286  bool atIP = false;
287  if (!exPars) {
288  ATH_MSG_DEBUG("failed to extrapolate parameters to muon entry, trying perigee ");
289 
290  // for cosmics also try extrapolate to IP
291  if (m_cosmics) {
292  exPars = extrapolateToIP(ctx, *firstPars, particleHypo);
293  atIP = true;
294  }
295  }
296  if (!exPars) {
297  // check mometum, this should always work for high pt track but low momentum track could get stuck
298  if (firstPars->momentum().mag() < 7000.)
299  ATH_MSG_DEBUG("lower energy muon lost during extrapolation ");
300  else
301  ATH_MSG_WARNING("failed to extrapolate parameters to muon entry and perigee ");
302  return nullptr;
303  }
304 
305  // sanity check for cosmics, if we are at the IP we should not
306  if (m_cosmics && atIP) {
307  double tolerance = -50.;
308  const Trk::TrackingVolume *msEntrance = getVolume("Calo::Container", ctx);
309 
310  if (msEntrance && msEntrance->inside(exPars->position(), tolerance)) {
311  ATH_MSG_DEBUG("extrapolate parameters at perigee inside muon entry volume " << m_printer->print(*exPars));
312  }
313  }
314 
315  ATH_MSG_DEBUG(" first pars: " << m_printer->print(*firstPars) << endmsg << " extrapolated pars " << m_printer->print(*exPars)
316  << endmsg);
317  // create new perigee
318  std::shared_ptr<Trk::Perigee> perigee = std::dynamic_pointer_cast<Trk::Perigee>(exPars);
319 
320  if (!perigee) {
321  perigee = createPerigee(ctx, *exPars);
322  }
323  // double check
324  if (!perigee) {
325  ATH_MSG_WARNING(" failed to create perigee ");
326  return nullptr;
327  }
328 
329  // direction of perigee
330  Amg::Vector3D perDir = perigee->momentum().unit();
331 
332  // for cosmics we could have hits on both side of the muon entry volume.
333  // check whether that is the case and calculate a second perigee in that case
334  std::shared_ptr< Trk::Perigee>secondPerigee;
335  if (m_cosmics && !atIP) {
336  ATH_MSG_DEBUG(" trying to calculate second crossing ");
337 
338  const Trk::TrackParameters *secondEntryCrossing = checkForSecondCrossing(*perigee, track);
339  if (secondEntryCrossing) {
340  ATH_MSG_DEBUG(" Expect second crossing ");
341 
342  // create second perigee
343  std::shared_ptr<Trk::TrackParameters> secondExPars = extrapolateToMuonEntryRecord(ctx, *secondEntryCrossing, particleHypo);
344  if (secondExPars) {
345  // check distence to first perigee
346  double distance = (secondExPars->position() - perigee->position()).dot(perDir);
347  ATH_MSG_DEBUG(" second crossing: " << m_printer->print(*secondExPars) << " distance to first " << distance);
348  if (std::abs(distance) < 1.) {
349  ATH_MSG_DEBUG(" second perigee too close to first: " << m_printer->print(*secondExPars));
350  } else {
351  // create new perigee
352  secondPerigee = std::dynamic_pointer_cast<Trk::Perigee>(secondExPars);
353  if (!secondPerigee) {
354  secondPerigee = createPerigee(ctx, *secondExPars);
355  }
356  }
357  } else {
358  ATH_MSG_DEBUG(" Extrapolation to muon entry failed for second crossing ");
359  }
360  }
361  }
362 
363  ATH_MSG_DEBUG(" perigee pars: " << m_printer->print(*perigee));
364 
365  // flag whether the perigees were inserted
366  bool perigeeWasInserted = false;
367  bool secondPerigeeWasInserted = false;
368 
369  // flag whether the perigees are pointing towards the IP
370  bool perigeePointsToIP = perigee->position().dot(perDir) < 0.;
371  bool secondPerigeePointsToIP = false;
372  if (secondPerigee) {
373  ATH_MSG_DEBUG(" second perigee pars: " << m_printer->print(*secondPerigee));
374  secondPerigeePointsToIP = secondPerigee->position().dot(secondPerigee->momentum()) < 0.;
375  if (perigeePointsToIP == secondPerigeePointsToIP) {
376  ATH_MSG_DEBUG(" Track has two perigee's with the same orientation with respect to the IP ");
377  }
378  }
379 
380  // create new TSOS DataVector and reserve enough space to fit all old TSOS + one new TSOS
381  const Trk::TrackStates *oldTSOT = track.trackStateOnSurfaces();
382  auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
383  unsigned int newSize = oldTSOT->size();
384  trackStateOnSurfaces->reserve(newSize + 11);
385 
387  Trk::TrackStates::const_iterator tit_prev = tit; // iterator pointing to the previous TSOS
388  Trk::TrackStates::const_iterator tit_end = oldTSOT->end();
389  for (; tit != tit_end; ++tit) {
390  // remove old perigee if we didn't start from a parameter in the muon system
391  if ((*tit)->trackParameters() == pp) {
392  if (m_keepOldPerigee) {
393  const Amg::VectorX &ppars = pp->parameters();
394  Amg::Transform3D ptrans = Amg::Transform3D(pp->associatedSurface().transform());
395  Trk::StraightLineSurface slSurf(ptrans);
396  auto slPars = std::make_unique<Trk::AtaStraightLine>(ppars[Trk::locR], ppars[Trk::locZ], ppars[Trk::phi],
397  ppars[Trk::theta], ppars[Trk::qOverP], slSurf);
398  trackStateOnSurfaces->push_back(MuonTSOSHelper::createPerigeeTSOS(std::move(slPars)));
399  }
400  continue;
401  }
402  const Trk::TrackParameters *pars = (*tit)->trackParameters();
403  if (!pars) {
404  // keep state but do not consider any further
405  trackStateOnSurfaces->push_back((*tit)->clone());
406  continue;
407  }
408 
409  double distanceOfPerigeeToCurrent = (pars->position() - perigee->position()).dot(perDir);
410 
411  ATH_MSG_VERBOSE(" new state " << m_printer->print(*pars) << " dist to perigee " << distanceOfPerigeeToCurrent);
412 
413  if (!perigeeWasInserted && distanceOfPerigeeToCurrent > 0.) {
414  ATH_MSG_VERBOSE(" inserting first perigee " << m_printer->print(*perigee) << " dist to prev "
415  << distanceOfPerigeeToCurrent);
416 
417  // check whether we should add material between the previous TSOS and the new perigee
418  // make sure that we are not at the same TSOS (could happen if this were the first TSOS
419  if (!atIP) {
420  ATH_MSG_VERBOSE(" not at IP ");
421 
422  // check direction of perigee wrt IP
423  if (perigeePointsToIP) {
424  // perigee points to the IP so we have to collect material between the perigee and the previous measurement
425 
426  ATH_MSG_VERBOSE(" perigee points towards IP, inserting material first ");
427 
428  // check whether the previous state is a measurement, else we will assume the material is there
429  if (tit_prev != tit) {
430  const Trk::MeasurementBase *meas = (*tit_prev)->measurementOnTrack();
431  if (meas) {
432  ATH_MSG_VERBOSE(" trying to adding material layers extrapolating to previous measurement ");
433 
434  // collect the material going in opposite direction
435  const std::vector<const Trk::TrackStateOnSurface *> *matvec = m_muonExtrapolator->extrapolateM(
436  ctx, *perigee, meas->associatedSurface(), Trk::oppositeMomentum, false, particleHypo);
437  if (matvec && !matvec->empty()) {
438  ATH_MSG_VERBOSE(" got material layers " << matvec->size());
439 
440  trackStateOnSurfaces->insert(trackStateOnSurfaces->end(), matvec->begin(), matvec->end());
441  } else {
442  ATH_MSG_VERBOSE(" no layers obtained from extrapolator ");
443  }
444  delete matvec;
445  }
446  } else {
447  ATH_MSG_VERBOSE(" first measurement, cannot allocated material ");
448  }
449  } else {
450  // we have to collect material from the perigee to the next measurement
451 
452  ATH_MSG_VERBOSE(" perigee points away from IP, inserting perigee ");
453 
454  // first add perigee; cop out here on the unique_ptr magic
455  trackStateOnSurfaces->push_back(MuonTSOSHelper::createPerigeeTSOS(perigee->uniqueClone()));
456  perigeeWasInserted = true;
457 
458  // // now look whether there are measurements upstream of this point add add material if needed
459  // Trk::TrackStates::const_iterator tit_next = tit; ++tit_next;
460  // if( tit_next != tit_end ){
461 
462  // check whether a measurement, else we will assume the material is there
463  const Trk::MeasurementBase *meas = (*tit)->measurementOnTrack();
464  if (meas) {
465  ATH_MSG_VERBOSE(" trying to add material layers extrapolating to next measurement ");
466  const std::vector<const Trk::TrackStateOnSurface *> *matvec = m_muonExtrapolator->extrapolateM(
467  ctx, *perigee, meas->associatedSurface(), Trk::alongMomentum, false, particleHypo);
468  if (matvec && !matvec->empty()) {
469  ATH_MSG_VERBOSE(" got material layers " << matvec->size());
470 
471  trackStateOnSurfaces->insert(trackStateOnSurfaces->end(), matvec->begin(), matvec->end());
472  } else {
473  ATH_MSG_VERBOSE(" no layers obtained from extrapolator ");
474  }
475  delete matvec;
476  }
477  }
478  }
479 
480  // check whether we did not insert the perigee, if not insert
481  if (!perigeeWasInserted) {
482  trackStateOnSurfaces->push_back(MuonTSOSHelper::createPerigeeTSOS(perigee->uniqueClone()));
483  perigeeWasInserted = true;
484  ATH_MSG_VERBOSE(" inserting perigee ");
485  }
486  }
487  if (secondPerigee) {
488  double distanceOfSecondPerigeeToCurrent =
489  (pars->position() - secondPerigee->position()).dot(secondPerigee->momentum().unit());
490  if (!secondPerigeeWasInserted && distanceOfSecondPerigeeToCurrent > 0.) {
491  // hack copied code should be put into a function
492 
493  ATH_MSG_VERBOSE(" inserting second perigee " << m_printer->print(*secondPerigee) << " dist to prev "
494  << distanceOfSecondPerigeeToCurrent);
495 
496  // check direction of perigee wrt IP
497  if (secondPerigeePointsToIP) {
498  // perigee points to the IP so we have to collect material between the perigee and the previous measurement
499 
500  ATH_MSG_VERBOSE(" perigee points towards IP, inserting material first ");
501 
502  // check whether the previous state is a measurement, else we will assume the material is there
503  if (tit_prev != tit) {
504  const Trk::MeasurementBase *meas = (*tit_prev)->measurementOnTrack();
505  if (meas) {
506  ATH_MSG_VERBOSE(" trying to adding material layers extrapolating to previous measurement ");
507 
508  // collect the material going in opposite direction
509  const std::vector<const Trk::TrackStateOnSurface *> *matvec = m_muonExtrapolator->extrapolateM(
510  ctx, *secondPerigee, meas->associatedSurface(), Trk::oppositeMomentum, false, particleHypo);
511  if (matvec && !matvec->empty()) {
512  ATH_MSG_VERBOSE(" got material layers " << matvec->size());
513 
514  trackStateOnSurfaces->insert(trackStateOnSurfaces->end(), matvec->begin(), matvec->end());
515  } else {
516  ATH_MSG_VERBOSE(" no layers obtained from extrapolator ");
517  }
518  delete matvec;
519  }
520  }
521  } else {
522  // we have to collect material from the perigee to the next measurement
523 
524  ATH_MSG_VERBOSE(" perigee points away from IP, inserting perigee ");
525 
526  // first add perigee
527  trackStateOnSurfaces->push_back(MuonTSOSHelper::createPerigeeTSOS(secondPerigee->uniqueClone()));
528  secondPerigeeWasInserted = true;
529 
530  // // now look whether there are measurements upstream of this point add add material if needed
531  // Trk::TrackStates::const_iterator tit_next = tit; ++tit_next;
532  // if( tit_next != tit_end ){
533  // check whether a measurement, else we will assume the material is there
534  const Trk::MeasurementBase *meas = (*tit)->measurementOnTrack();
535  if (meas) {
536  ATH_MSG_VERBOSE(" trying to add material layers extrapolating to next measurement ");
537  const std::vector<const Trk::TrackStateOnSurface *> *matvec = m_muonExtrapolator->extrapolateM(
538  ctx, *secondPerigee, meas->associatedSurface(), Trk::alongMomentum, false, particleHypo);
539  if (matvec && !matvec->empty()) {
540  ATH_MSG_VERBOSE(" got material layers " << matvec->size());
541 
542  trackStateOnSurfaces->insert(trackStateOnSurfaces->end(), matvec->begin(), matvec->end());
543  } else {
544  ATH_MSG_VERBOSE(" no layers obtained from extrapolator ");
545  }
546  delete matvec;
547  }
548  }
549 
550  // check whether we did not insert the perigee, if not insert
551  if (!secondPerigeeWasInserted) {
552  trackStateOnSurfaces->push_back(MuonTSOSHelper::createPerigeeTSOS(secondPerigee->uniqueClone()));
553  secondPerigeeWasInserted = true;
554  ATH_MSG_VERBOSE(" inserting second perigee ");
555  }
556  }
557  }
558 
559  // copy TSOS
560  trackStateOnSurfaces->push_back((*tit)->clone());
561 
562  // update iterator previous TSTO
563  tit_prev = tit;
564  }
565 
566  if (!perigeeWasInserted) {
567  // check whether the previous state is a measurement, else we will assume the material is there
568  if (tit_prev != tit_end) {
569  const Trk::MeasurementBase *meas = (*tit_prev)->measurementOnTrack();
570  if (meas) {
571  ATH_MSG_VERBOSE(" trying to adding material layers extrapolating to previous measurement ");
572 
573  // collect the material going in opposite direction
574  const std::vector<const Trk::TrackStateOnSurface *> *matvec = m_muonExtrapolator->extrapolateM(
575  ctx, *perigee, meas->associatedSurface(), Trk::oppositeMomentum, false, particleHypo);
576  if (matvec && !matvec->empty()) {
577  ATH_MSG_VERBOSE(" got material layers " << matvec->size());
578 
579  trackStateOnSurfaces->insert(trackStateOnSurfaces->end(), matvec->begin(), matvec->end());
580  } else {
581  ATH_MSG_VERBOSE(" no layers obtained from extrapolator ");
582  }
583  delete matvec;
584  }
585  }
586  ATH_MSG_VERBOSE(" inserting perigee ");
587  trackStateOnSurfaces->push_back(MuonTSOSHelper::createPerigeeTSOS(perigee->uniqueClone()));
588  }
589  if (secondPerigee && !secondPerigeeWasInserted) {
590  // check whether the previous state is a measurement, else we will assume the material is there
591  if (tit_prev != tit_end) {
592  const Trk::MeasurementBase *meas = (*tit_prev)->measurementOnTrack();
593  if (meas) {
594  ATH_MSG_VERBOSE(" trying to adding material layers extrapolating to previous measurement ");
595 
596  // collect the material going in opposite direction
597  const std::vector<const Trk::TrackStateOnSurface *> *matvec = m_muonExtrapolator->extrapolateM(
598  ctx, *secondPerigee, meas->associatedSurface(), Trk::oppositeMomentum, false, particleHypo);
599  if (matvec && !matvec->empty()) {
600  ATH_MSG_VERBOSE(" got material layers " << matvec->size());
601 
602  trackStateOnSurfaces->insert(trackStateOnSurfaces->end(), matvec->begin(), matvec->end());
603  } else {
604  ATH_MSG_VERBOSE(" no layers obtained from extrapolator ");
605  }
606  delete matvec;
607  }
608  }
609  ATH_MSG_VERBOSE(" inserting second perigee ");
610  trackStateOnSurfaces->push_back(MuonTSOSHelper::createPerigeeTSOS(secondPerigee->uniqueClone()));
611  }
612 
613  // create new track
614  return std::make_unique<Trk::Track>(track.info(), std::move(trackStateOnSurfaces),
615  track.fitQuality() ? track.fitQuality()->uniqueClone() : nullptr);
616  }
617 
618  std::unique_ptr<TrackCollection> MuonTrackExtrapolationTool::extrapolate(const TrackCollection &tracks, const EventContext &ctx) const {
619  std::unique_ptr<TrackCollection> extrapolateTracks = std::make_unique<TrackCollection>();
620  extrapolateTracks->reserve(tracks.size());
621 
622  // loop over muon tracks and extrapolate them to the IP
623  for (const Trk::Track *tit : tracks) {
624  std::unique_ptr<Trk::Track> extrapolateTrack = extrapolate(*tit, ctx);
625  if (!extrapolateTrack) { continue; }
626 
627  extrapolateTracks->push_back(std::move(extrapolateTrack));
628  }
629  return extrapolateTracks;
630  }
631 
632  std::shared_ptr<Trk::Perigee> MuonTrackExtrapolationTool::createPerigee(const EventContext& ctx, const Trk::TrackParameters &pars) const {
633  if (m_muonExtrapolator.empty()) { return nullptr; }
634  Trk::PerigeeSurface persurf(pars.position());
635  std::shared_ptr<Trk::TrackParameters> exPars {
636  m_muonExtrapolator->extrapolateDirectly(ctx, pars, persurf)};
637  std::shared_ptr<Trk::Perigee> pp = std::dynamic_pointer_cast<Trk::Perigee>(exPars);
638  if (!pp) {
639  ATH_MSG_WARNING(" Extrapolation to Perigee surface did not return a perigee!! ");
640  }
641  return pp;
642  }
643 } // namespace Muon
DataVector::reserve
void reserve(size_type n)
Attempt to preallocate enough memory for a specified number of elements.
Trk::DistanceSolution::currentDistance
double currentDistance(bool signedDist=false) const
Current distance to surface (spatial), signed (along/opposite to surface normal) if input argument tr...
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
make_hlt_rep.pars
pars
Definition: make_hlt_rep.py:90
Muon::MuonTrackExtrapolationTool::extrapolateToIP
std::unique_ptr< Trk::TrackParameters > extrapolateToIP(const EventContext &ctx, const Trk::TrackParameters &pars, Trk::ParticleHypothesis particleHypo=Trk::muon) const
extrapolates track parameters to muon entry record, will return a zero pointer if the extrapolation f...
Definition: MuonTrackExtrapolationTool.cxx:79
Trk::TrackStateOnSurface::Perigee
@ Perigee
This represents a perigee, and so will contain a Perigee object only.
Definition: TrackStateOnSurface.h:117
DataModel_detail::const_iterator
Const iterator class for DataVector/DataList.
Definition: DVLIterator.h:82
Amg::VectorX
Eigen::Matrix< double, Eigen::Dynamic, 1 > VectorX
Dynamic Vector - dynamic allocation.
Definition: EventPrimitives.h:32
MeasurementBase.h
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
PerigeeSurface.h
Trk::Track
The ATLAS Track class.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/Track.h:73
DistanceSolution.h
AtlasFieldCacheCondObj
Definition: AtlasFieldCacheCondObj.h:19
perp
Scalar perp() const
perp method - perpenticular length
Definition: AmgMatrixBasePlugin.h:35
Trk::DistanceSolution
Definition: DistanceSolution.h:25
MaterialProperties.h
Trk::Volume::inside
bool inside(const Amg::Vector3D &gp, double tol=0.) const
Inside() method for checks.
Definition: Volume.cxx:90
Muon::MuonTrackExtrapolationTool::getVolume
const Trk::TrackingVolume * getVolume(const std::string &vol_name, const EventContext &ctx) const
Definition: MuonTrackExtrapolationTool.h:89
Trk::PerigeeSurface
Definition: PerigeeSurface.h:43
Trk::ParametersBase::position
const Amg::Vector3D & position() const
Access method for the position.
Trk::oppositeMomentum
@ oppositeMomentum
Definition: PropDirection.h:21
Trk::Surface::straightLineDistanceEstimate
virtual DistanceSolution straightLineDistanceEstimate(const Amg::Vector3D &pos, const Amg::Vector3D &dir) const =0
fast straight line distance evaluation to Surface
Muon::MuonTrackExtrapolationTool::m_keepOldPerigee
Gaudi::Property< bool > m_keepOldPerigee
Definition: MuonTrackExtrapolationTool.h:86
Trk::ParametersT
Dummy class used to allow special convertors to be called for surfaces owned by a detector element.
Definition: EMErrorDetail.h:25
Trk::TrackingVolume::boundarySurfaces
std::vector< SharedObject< BoundarySurface< TrackingVolume > > > & boundarySurfaces()
Method to return the BoundarySurfaces.
Definition: TrackingVolume.cxx:982
PlotCalibFromCool.ib
ib
Definition: PlotCalibFromCool.py:419
Muon::MuonTrackExtrapolationTool::extrapolate
virtual std::unique_ptr< Trk::Track > extrapolate(const Trk::Track &track, const EventContext &ctx) const override
extrapolates a muon track to the muon entry record and returns a new track expressed at the destinati...
Definition: MuonTrackExtrapolationTool.cxx:254
Trk::alongMomentum
@ alongMomentum
Definition: PropDirection.h:20
Trk::locR
@ locR
Definition: ParamDefs.h:50
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
SG::VarHandleKey::key
const std::string & key() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:141
SG::VarHandleKey::empty
bool empty() const
Test if the key is blank.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:150
MagField::AtlasFieldCache::toroidOn
bool toroidOn() const
Muon
This class provides conversion from CSC RDO data to CSC Digits.
Definition: TrackSystemController.h:49
Track.h
MagneticFieldProperties.h
Muon::MuonTrackExtrapolationTool::createPerigee
std::shared_ptr< Trk::Perigee > createPerigee(const EventContext &ctx, const Trk::TrackParameters &pars) const
Definition: MuonTrackExtrapolationTool.cxx:632
Trk::PseudoMeasurementOnTrack
Class to handle pseudo-measurements in fitters and on track objects.
Definition: PseudoMeasurementOnTrack.h:44
Muon::MuonTrackExtrapolationTool::m_edmHelperSvc
ServiceHandle< Muon::IMuonEDMHelperSvc > m_edmHelperSvc
Definition: MuonTrackExtrapolationTool.h:76
Trk::ParticleHypothesis
ParticleHypothesis
Definition: ParticleHypothesis.h:25
Trk::ParametersT::associatedSurface
virtual const S & associatedSurface() const override final
Access to the Surface method.
MuonTSOSHelper.h
TileDCSDataPlotter.tit
tit
Definition: TileDCSDataPlotter.py:890
Trk::PropDirection
PropDirection
Definition: PropDirection.h:19
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
Trk::locZ
@ locZ
local cylindrical
Definition: ParamDefs.h:48
z
#define z
Identifier
Definition: DetectorDescription/Identifier/Identifier/Identifier.h:32
Trk::theta
@ theta
Definition: ParamDefs.h:72
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
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
Muon::MuonTrackExtrapolationTool::m_fieldCacheCondObjInputKey
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
Definition: MuonTrackExtrapolationTool.h:71
PseudoMeasurementOnTrack.h
sign
int sign(int a)
Definition: TRT_StrawNeighbourSvc.h:127
Muon::MuonTrackExtrapolationTool::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: MuonTrackExtrapolationTool.h:78
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Trk::ParametersBase
Definition: ParametersBase.h:55
DataVector< const Trk::TrackStateOnSurface >
dot.dot
def dot(G, fn, nodesToHighlight=[])
Definition: dot.py:5
Muon::MuonTrackExtrapolationTool::m_trackingGeometryReadKey
SG::ReadCondHandleKey< Trk::TrackingGeometry > m_trackingGeometryReadKey
Definition: MuonTrackExtrapolationTool.h:74
Muon::MuonTrackExtrapolationTool::checkForSecondCrossing
static const Trk::TrackParameters * checkForSecondCrossing(const Trk::TrackParameters &firstCrossing, const Trk::Track &track)
Definition: MuonTrackExtrapolationTool.cxx:212
Muon::MuonTrackExtrapolationTool::m_atlasExtrapolator
ToolHandle< Trk::IExtrapolator > m_atlasExtrapolator
Definition: MuonTrackExtrapolationTool.h:82
beamspotman.dir
string dir
Definition: beamspotman.py:623
tolerance
Definition: suep_shower.h:17
Trk::MeasurementBase
Definition: MeasurementBase.h:58
Trk::TrackStateOnSurface
represents the track state (measurement, material, fit parameters and quality) at a surface.
Definition: TrackStateOnSurface.h:71
Trk::MeasurementBase::associatedSurface
virtual const Surface & associatedSurface() const =0
Interface method to get the associated Surface.
Muon::MuonTrackExtrapolationTool::m_printer
ToolHandle< Muon::MuonEDMPrinterTool > m_printer
Definition: MuonTrackExtrapolationTool.h:80
Trk::nonInteracting
@ nonInteracting
Definition: ParticleHypothesis.h:25
Muon::MuonTrackExtrapolationTool::m_msEntranceName
Gaudi::Property< std::string > m_msEntranceName
Definition: MuonTrackExtrapolationTool.h:87
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
Muon::MuonTrackExtrapolationTool::estimateDistanceToEntryRecord
double estimateDistanceToEntryRecord(const EventContext &ctx, const Trk::TrackParameters &pars) const
Definition: MuonTrackExtrapolationTool.cxx:192
BoundarySurface.h
Muon::MuonTrackExtrapolationTool::extrapolateToMuonEntryRecord
std::unique_ptr< Trk::TrackParameters > extrapolateToMuonEntryRecord(const EventContext &ctx, const Trk::TrackParameters &pars, Trk::ParticleHypothesis particleHypo=Trk::muon) const
extrapolates track parameters to muon entry record, will return a zero pointer if the extrapolation f...
Definition: MuonTrackExtrapolationTool.cxx:49
DataVector::end
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
Trk::ParametersBase::momentum
const Amg::Vector3D & momentum() const
Access method for the momentum.
TrackingVolume.h
Muon::MuonTrackExtrapolationTool::findClosestParametersToMuonEntry
const Trk::TrackParameters * findClosestParametersToMuonEntry(const EventContext &ctx, const Trk::Track &track) const
Definition: MuonTrackExtrapolationTool.cxx:110
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
MagField::AtlasFieldCache
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h)
Definition: AtlasFieldCache.h:43
Trk::qOverP
@ qOverP
perigee
Definition: ParamDefs.h:73
Muon::MuonTrackExtrapolationTool::initialize
virtual StatusCode initialize() override
AlgTool initilize.
Definition: MuonTrackExtrapolationTool.cxx:31
MuonTrackExtrapolationTool.h
TrackingGeometry.h
Trk::phi
@ phi
Definition: ParamDefs.h:81
Muon::MuonTrackExtrapolationTool::m_cosmics
Gaudi::Property< bool > m_cosmics
Definition: MuonTrackExtrapolationTool.h:85
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
Muon::MuonTrackExtrapolationTool::m_muonExtrapolator
ToolHandle< Trk::IExtrapolator > m_muonExtrapolator
Definition: MuonTrackExtrapolationTool.h:83
AthAlgTool
Definition: AthAlgTool.h:26
Trk::Surface
Definition: Tracking/TrkDetDescr/TrkSurfaces/TrkSurfaces/Surface.h:75
Trk::TrackingVolume
Definition: TrackingVolume.h:121
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
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
Muon::MuonTrackExtrapolationTool::MuonTrackExtrapolationTool
MuonTrackExtrapolationTool(const std::string &, const std::string &, const IInterface *)
constructor
Definition: MuonTrackExtrapolationTool.cxx:26
TrackStateOnSurface.h
Trk::StraightLineSurface
Definition: StraightLineSurface.h:51
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.