ATLAS Offline Software
Loading...
Searching...
No Matches
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
24namespace 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());
37 if (!m_trackingGeometryReadKey.empty()) {
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,
50 const Trk::TrackParameters &pars,
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
192 double MuonTrackExtrapolationTool::estimateDistanceToEntryRecord(const EventContext &ctx, const Trk::TrackParameters &pars) const {
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
275 const Trk::TrackParameters *firstPars = findClosestParametersToMuonEntry(ctx, track);
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();
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
Scalar perp() const
perp method - perpendicular length
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
int sign(int a)
DataVector< Trk::Track > TrackCollection
This typedef represents a collection of Trk::Track objects.
#define z
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
void getInitializedCache(MagField::AtlasFieldCache &cache) const
get B field cache for evaluation as a function of 2-d or 3-d position.
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h)
static std::unique_ptr< Trk::TrackStateOnSurface > createPerigeeTSOS(std::unique_ptr< Trk::TrackParameters > perigee)
create a perigee TSOS, takes ownership of the Perigee
ToolHandle< Trk::IExtrapolator > m_muonExtrapolator
static const Trk::TrackParameters * checkForSecondCrossing(const Trk::TrackParameters &firstCrossing, const Trk::Track &track)
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
std::shared_ptr< Trk::Perigee > createPerigee(const EventContext &ctx, const Trk::TrackParameters &pars) const
Gaudi::Property< std::string > m_msEntranceName
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...
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
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...
MuonTrackExtrapolationTool(const std::string &, const std::string &, const IInterface *)
constructor
const Trk::TrackParameters * findClosestParametersToMuonEntry(const EventContext &ctx, const Trk::Track &track) const
const Trk::TrackingVolume * getVolume(const std::string &vol_name, const EventContext &ctx) const
virtual StatusCode initialize() override
AlgTool initilize.
ToolHandle< Trk::IExtrapolator > m_atlasExtrapolator
double estimateDistanceToEntryRecord(const EventContext &ctx, const Trk::TrackParameters &pars) const
ServiceHandle< Muon::IMuonEDMHelperSvc > m_edmHelperSvc
SG::ReadCondHandleKey< Trk::TrackingGeometry > m_trackingGeometryReadKey
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...
PublicToolHandle< Muon::MuonEDMPrinterTool > m_printer
Access to distance solutions.
double currentDistance(bool signedDist=false) const
Current distance to surface (spatial), signed (along/opposite to surface normal) if input argument tr...
This class is the pure abstract base class for all fittable tracking measurements.
virtual const Surface & associatedSurface() const =0
Interface method to get the associated Surface.
const Amg::Vector3D & momentum() const
Access method for the momentum.
const Amg::Vector3D & position() const
Access method for the position.
virtual const S & associatedSurface() const override final
Access to the Surface method.
Class describing the Line to which the Perigee refers to.
Class to handle pseudo-measurements in fitters and on track objects.
Class for a StraightLineSurface in the ATLAS detector to describe dirft tube and straw like detectors...
Abstract Base Class for tracking surfaces.
virtual DistanceSolution straightLineDistanceEstimate(const Amg::Vector3D &pos, const Amg::Vector3D &dir) const =0
fast straight line distance evaluation to Surface
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
const Amg::Vector3D & center() const
Returns the center position of the Surface.
represents the track state (measurement, material, fit parameters and quality) at a surface.
@ Perigee
This represents a perigee, and so will contain a Perigee object only.
Full Volume description used in Tracking, it inherits from Volume to get the geometrical structure,...
std::vector< std::shared_ptr< BoundarySurface< TrackingVolume > > > & boundarySurfaces()
Method to return the BoundarySurfaces.
bool inside(const Amg::Vector3D &gp, double tol=0.) const
Inside() method for checks.
Definition Volume.cxx:72
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
Eigen::Matrix< double, Eigen::Dynamic, 1 > VectorX
Dynamic Vector - dynamic allocation.
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
PropDirection
PropDirection, enum for direction of the propagation.
@ oppositeMomentum
@ alongMomentum
DataVector< const Trk::TrackStateOnSurface > TrackStates
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
@ locR
Definition ParamDefs.h:44
@ theta
Definition ParamDefs.h:66
@ qOverP
perigee
Definition ParamDefs.h:67
@ phi
Definition ParamDefs.h:75
@ locZ
local cylindrical
Definition ParamDefs.h:42
ParticleHypothesis
Enumeration for Particle hypothesis respecting the interaction with material.
ParametersBase< TrackParametersDim, Charged > TrackParameters