ATLAS Offline Software
Loading...
Searching...
No Matches
MooTrackBuilder.cxx
Go to the documentation of this file.
1
2/*
3 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
4*/
5
6#include "MooTrackBuilder.h"
7
8#include <set>
9
26
27namespace Muon {
29
30 MooTrackBuilder::MooTrackBuilder(const std::string& t, const std::string& n, const IInterface* p) : AthAlgTool(t, n, p) {
31 declareInterface<IMuonSegmentTrackBuilder>(this);
32 declareInterface<MooTrackBuilder>(this);
33 declareInterface<IMuonTrackRefiner>(this);
34 declareInterface<IMuonTrackBuilder>(this);
35 }
36
38 ATH_CHECK(m_fitter.retrieve());
39 ATH_CHECK(m_slFitter.retrieve());
41 ATH_CHECK(m_errorOptimisationTool.retrieve(DisableTool{m_errorOptimisationTool.empty()}));
42 ATH_CHECK(m_candidateHandler.retrieve());
46 ATH_CHECK(m_idHelperSvc.retrieve());
47 ATH_CHECK(m_edmHelperSvc.retrieve());
48 ATH_CHECK(m_printer.retrieve());
51 ATH_CHECK(m_mdtRotCreator.retrieve());
52 ATH_CHECK(m_compRotCreator.retrieve());
53 ATH_CHECK(m_propagator.retrieve());
54 ATH_CHECK(m_pullCalculator.retrieve());
55 ATH_CHECK(m_trackSummaryTool.retrieve());
56
57 return StatusCode::SUCCESS;
58 }
59
61 if (m_nTimedOut > 0 && m_ncalls > 0) {
62 double scale = 1. / m_ncalls;
63 ATH_MSG_INFO(" Number of calls that timed out " << m_nTimedOut << " fraction of total calls " << scale * m_nTimedOut);
64 }
65 return StatusCode::SUCCESS;
66 }
67
68 std::unique_ptr<Trk::Track> MooTrackBuilder::refit(const EventContext& ctx, Trk::Track& track) const {
69 // use slFitter for straight line fit, or toroid off, otherwise use normal Fitter
70
71 if (m_edmHelperSvc->isSLTrack(track)) return m_slFitter->refit(ctx, track);
72
73 // Also check if toriod is off:
75 // Get field cache object
77 const AtlasFieldCacheCondObj* fieldCondObj{*readHandle};
78
79 if (!fieldCondObj) {
80 ATH_MSG_ERROR("refit: Failed to retrieve AtlasFieldCacheCondObj with key " << m_fieldCacheCondObjInputKey.key());
81 return nullptr;
82 }
83 fieldCondObj->getInitializedCache(fieldCache);
84 if (!fieldCache.toroidOn()) return m_slFitter->refit(ctx, track);
85
86 // if not refit tool specified do a pure refit
87 if (m_errorOptimisationTool.empty()) return m_fitter->refit(ctx, track);
88 std::unique_ptr<Trk::Track> optTrack = m_errorOptimisationTool->optimiseErrors(track, ctx);
89 return optTrack;
90 }
91
92 void MooTrackBuilder::refine(const EventContext& ctx, MuPatTrack& track) const {
93
94 ATH_MSG_VERBOSE("refine: before recovery " << std::endl
95 << m_printer->print(track.track()) << std::endl
96 << m_printer->print(track.track().measurementsOnTrack()->stdcont()));
97
98 std::unique_ptr<Trk::Track> finalTrack(m_muonChamberHoleRecoverTool->recover(track.track(), ctx));
99 if (!finalTrack) { ATH_MSG_WARNING(" final track lost, this should not happen "); }
100 ATH_MSG_VERBOSE("refine: after recovery " << std::endl
101 << m_printer->print(*finalTrack) << std::endl
102 << m_printer->print(finalTrack->measurementsOnTrack()->stdcont()));
103
104 // generate a track summary for this track
105 if (m_trackSummaryTool.isEnabled()) { m_trackSummaryTool->computeAndReplaceTrackSummary(ctx, *finalTrack, false); }
106
107 bool recalibrateMDTHits = m_recalibrateMDTHits;
108 bool recreateCompetingROTs = true;
109 std::unique_ptr<Trk::Track> recalibratedTrack = recalibrateHitsOnTrack(ctx, *finalTrack, recalibrateMDTHits, recreateCompetingROTs);
110 if (!recalibratedTrack) {
111 ATH_MSG_WARNING(" failed to recalibrate hits on track " << std::endl << m_printer->print(*finalTrack));
112 } else
113 finalTrack.swap(recalibratedTrack);
114
115 std::unique_ptr<Trk::Track> refittedTrack = refit(ctx, *finalTrack);
116 if (!refittedTrack) {
117 ATH_MSG_VERBOSE(" failed to refit track " << std::endl
118 << m_printer->print(*finalTrack) << std::endl
119 << m_printer->printStations(*finalTrack));
120 } else
121 finalTrack.swap(refittedTrack);
122
123 // redo holes as they are dropped in the fitter
124 std::unique_ptr<Trk::Track> finalTrackWithHoles(m_muonChamberHoleRecoverTool->recover(*finalTrack, ctx));
125 if (!finalTrackWithHoles) {
126 ATH_MSG_WARNING(" failed to add holes to final track, this should not happen ");
127 } else
128 finalTrack.swap(finalTrackWithHoles);
129
130 std::unique_ptr<Trk::Track> entryRecordTrack(m_trackExtrapolationTool->extrapolate(*finalTrack, ctx));
131 if (entryRecordTrack) {
132 finalTrack.swap(entryRecordTrack);
133 ATH_MSG_VERBOSE(" track at muon entry record " << std::endl << m_printer->print(*finalTrack));
134 }
135 m_candidateHandler->updateTrack(track, finalTrack);
136 }
137
138 std::unique_ptr<MuonSegment> MooTrackBuilder::combineToSegment(const EventContext& ctx, const MuonSegment& seg1, const MuonSegment& seg2, const PrepVec& externalPhiHits) const {
139 // try to get track
140 std::unique_ptr<Trk::Track> track = combine(ctx, seg1, seg2, externalPhiHits);
141
142 if (!track) return nullptr;
143
144 // create MuonSegment
145 std::unique_ptr<MuonSegment> seg{m_trackToSegmentTool->convert(ctx, *track)};
146 if (!seg) { ATH_MSG_WARNING(" conversion of track failed!! "); }
147
148 return seg;
149 }
150
151 std::unique_ptr<Trk::Track> MooTrackBuilder::combine(const EventContext& ctx, const MuonSegment& seg1, const MuonSegment& seg2,
152 const PrepVec& externalPhiHits) const {
153
154 // convert segments
155 std::unique_ptr<MuPatSegment> segInfo1{m_candidateHandler->createSegInfo(ctx, seg1)};
156 if (!segInfo1) {return nullptr; }
157 std::unique_ptr<MuPatSegment> segInfo2{m_candidateHandler->createSegInfo(ctx, seg2)};
158 if (!segInfo2) { return nullptr; }
159
160 // call fit()
161 return combine(ctx, *segInfo1, *segInfo2, externalPhiHits);
162 }
163
164 std::unique_ptr<MuonSegment> MooTrackBuilder::combineToSegment(const EventContext& ctx, const MuPatCandidateBase& firstCandidate, const MuPatCandidateBase& secondCandidate,
165 const PrepVec& externalPhiHits) const {
166 // try to get track
167 std::unique_ptr<Trk::Track> track = combine(ctx, firstCandidate, secondCandidate, externalPhiHits);
168
169 if (!track) return nullptr;
170
171 // create MuonSegment
172 std::unique_ptr<MuonSegment> seg{m_trackToSegmentTool->convert(ctx, *track)};
173 if (!seg) { ATH_MSG_WARNING(" conversion of track failed!! "); }
174
175 return seg;
176 }
177
178 std::unique_ptr<Trk::Track> MooTrackBuilder::combine(const EventContext& ctx, const MuPatCandidateBase& firstCandidate,
179 const MuPatCandidateBase& secondCandidate, const PrepVec& externalPhiHits) const {
180 ++m_ncalls;
181
182 if (m_doTimeOutChecks && Athena::Timeout::instance(ctx).reached()) {
183 ATH_MSG_DEBUG("Timeout reached. Aborting sequence.");
184 ++m_nTimedOut;
185 return nullptr;
186 }
187
188 std::set<MuonStationIndex::StIndex> stations = firstCandidate.stations();
189 stations.insert(secondCandidate.stations().begin(), secondCandidate.stations().end());
190 unsigned int nstations = stations.size();
191
192 MagField::AtlasFieldCache fieldCache;
193 // Get field cache object
195 const AtlasFieldCacheCondObj* fieldCondObj{*readHandle};
196
197 if (!fieldCondObj) {
198 ATH_MSG_ERROR("combine: Failed to retrieve AtlasFieldCacheCondObj with key " << m_fieldCacheCondObjInputKey.key());
199 return nullptr;
200 }
201 fieldCondObj->getInitializedCache(fieldCache);
202 using namespace MuonStationIndex;
203 bool slFit = !fieldCache.toroidOn() || nstations == 1 ||
204 (nstations == 2 && (stations.count(StIndex::EM) &&
205 (stations.count(StIndex::BO) || stations.count(StIndex::EO))));
206 if (msgLvl(MSG::DEBUG)) {
207 msg(MSG::DEBUG) << MSG::DEBUG << " combining entries: nstations " << nstations << " types:";
208 for (std::set<StIndex>::const_iterator it = stations.begin(); it != stations.end(); ++it) {
209 msg(MSG::DEBUG) << MSG::DEBUG << " " << stName(*it);
210 }
211 if (slFit) {
212 msg(MSG::DEBUG) << " doing SL fit ";
213 } else {
214 msg(MSG::DEBUG) << " doing curved fit ";
215 }
216 msg(MSG::DEBUG) << endmsg;
217 }
218
219 const MuPatTrack* trkCan1 = dynamic_cast<const MuPatTrack*>(&firstCandidate);
220 const MuPatTrack* trkCan2 = dynamic_cast<const MuPatTrack*>(&secondCandidate);
221
222 const MuPatSegment* segCan1 = dynamic_cast<const MuPatSegment*>(&firstCandidate);
223 const MuPatSegment* segCan2 = dynamic_cast<const MuPatSegment*>(&secondCandidate);
224
225 const MuPatTrack* candidate = nullptr;
226 const MuPatSegment* segment = nullptr;
227 if (trkCan1 && segCan2) {
228 candidate = trkCan1;
229 segment = segCan2;
230 } else if (trkCan2 && segCan1) {
231 candidate = trkCan2;
232 segment = segCan1;
233 }
234
235 // check whether this combination was already tried, if yes reject the combination
236 if (candidate && segment) {
237 ATH_MSG_DEBUG(" Track/segment combination");
238 const std::vector<MuPatSegment*>& excl = candidate->excludedSegments();
239 if (std::find(excl.begin(),excl.end(), segment) != excl.end()){
240 ATH_MSG_DEBUG(" Rejected segment based on exclusion list");
241 return nullptr;
242 }
243 }
244
245 // the following bit of code checks whether the current combination of segments was already tested
247 // create a set of all segments of the would-be candidate
248 std::set<const MuPatSegment*> segments;
249 if ((segCan1 && segCan2)) {
250 segments.insert(segCan1);
251 segments.insert(segCan2);
252 }
253 if (candidate && segment) {
254 segments.insert(segment);
255 segments.insert(candidate->segments().begin(), candidate->segments().end());
256 }
257 // now loop over the segments and check if any of them is associated with a track that contains all of the segments
258
259 for (const MuPatSegment* used : segments) {
260 // loop over the tracks associated with the current segment
261 for (const MuPatTrack* assoc_track : used->tracks()) {
262 // loop over the segments associated with the track
263 std::set<const MuPatSegment*> foundSegments;
264 for (const MuPatSegment* segOnTrack : assoc_track->segments()) {
265 if (segments.count(segOnTrack)) foundSegments.insert(segOnTrack);
266 }
267 // if all segments are already part of an existing track, don't perform the fit
268 if (foundSegments.size() == segments.size()) {
269 ATH_MSG_DEBUG("Combination already part of an existing track");
270 return nullptr;
271 }
272
273 // if all segments but one are already part of an existing track, check the exclusion list
274 if (candidate && !candidate->excludedSegments().empty() && foundSegments.size() == segments.size() - 1) {
275 // create destination vector for segments that are not found
276 std::vector<const MuPatSegment*> unassociatedSegments(segments.size(), nullptr);
277 std::vector<const MuPatSegment*>::iterator it = std::set_difference(
278 segments.begin(), segments.end(), foundSegments.begin(), foundSegments.end(), unassociatedSegments.begin());
279 const MuPatSegment* zero = nullptr;
280 unassociatedSegments.erase(std::find(unassociatedSegments.begin(), unassociatedSegments.end(), zero),
281 unassociatedSegments.end());
282
283 // check whether any pointers found
284 if (it != unassociatedSegments.begin()) {
285 // this should always be one as we required the difference to be one!
286 if (unassociatedSegments.size() != 1) {
287 ATH_MSG_DEBUG("Inconsistent result from set difference: size result "
288 << unassociatedSegments.size() << " candidate " << segments.size() << " found "
289 << foundSegments.size());
290 return nullptr;
291 }
292
293 // check that the result is indeed part of the original set
294 if (!segments.count(unassociatedSegments.front())) {
295 ATH_MSG_DEBUG("Segment point not part of the original set, aborting!");
296 return nullptr;
297 }
298
299 // now check whether the segment is part of the excluded segments
300 std::vector<MuPatSegment*>::const_iterator pos = std::find(
301 candidate->excludedSegments().begin(), candidate->excludedSegments().end(), unassociatedSegments.front());
302 if (pos != candidate->excludedSegments().end()) {
303 ATH_MSG_DEBUG("Segment found in exclusion list, not performing fit");
304 return nullptr;
305 }
306 }
307 }
308 }
309 }
310 }
311
312 // use slFitter for straight line fit, or toroid off, otherwise use normal Fitter
313 if (slFit) return std::unique_ptr<Trk::Track>(m_slFitter->fit(ctx, firstCandidate, secondCandidate, externalPhiHits));
314
315 return m_fitter->fit(ctx, firstCandidate, secondCandidate, externalPhiHits);
316 }
317
318 std::unique_ptr<Trk::Track> MooTrackBuilder::combine(const EventContext& ctx, const Trk::Track& track, const MuonSegment& seg,
319 const PrepVec& externalPhiHits) const {
320
321 // convert segments
322 std::unique_ptr<Trk::Track> inTrack = std::make_unique<Trk::Track>(track);
323 std::unique_ptr<MuPatTrack> candidate(m_candidateHandler->createCandidate(inTrack));
324 if (!candidate) return nullptr;
325 std::unique_ptr<MuPatSegment> segInfo(m_candidateHandler->createSegInfo(ctx, seg));
326 if (!segInfo) { return nullptr; }
327
328 // call fit()
329 return combine(ctx, *candidate, *segInfo, externalPhiHits);
330 }
331
332 std::vector<std::unique_ptr<Trk::Track> > MooTrackBuilder::combineWithSegmentFinding(const EventContext& ctx, const Trk::Track& track, const MuonSegment& seg,
333 const PrepVec& externalPhiHits) const {
334
335 // convert segments
336 std::unique_ptr<Trk::Track> inTrack = std::make_unique<Trk::Track>(track);
337 std::unique_ptr<MuPatTrack> candidate = m_candidateHandler->createCandidate(inTrack);
338 if (!candidate) return {};
339 std::unique_ptr<MuPatSegment> segInfo(m_candidateHandler->createSegInfo(ctx, seg));
340 if (!segInfo) return {};
341 // call fit()
342 return combineWithSegmentFinding(ctx, *candidate, *segInfo, externalPhiHits);
343 }
344
345 std::unique_ptr<Trk::TrackParameters> MooTrackBuilder::findClosestParameters(const Trk::Track& track, const Amg::Vector3D& pos) const {
346 // are we in the endcap?
347 bool isEndcap = m_edmHelperSvc->isEndcap(track);
348
349 // position of segment
350 double posSeg = isEndcap ? pos.z() : pos.perp();
351
352 // position closest parameters
353 double closest = 1e8;
354 const Trk::TrackParameters* closestParameters = nullptr;
355 bool closestIsMeasured = false;
356
357 // loop over track and calculate residuals
358 const Trk::TrackStates* states = track.trackStateOnSurfaces();
359 if (!states) {
360 ATH_MSG_DEBUG(" track without states! ");
361 return nullptr;
362 }
363
364 // loop over TSOSs
365 Trk::TrackStates::const_iterator tsit = states->begin();
366 Trk::TrackStates::const_iterator tsit_end = states->end();
367 for (; tsit != tsit_end; ++tsit) {
368 // check whether state is a measurement
369 const Trk::MeasurementBase* meas = (*tsit)->measurementOnTrack();
370 if (!meas) { continue; }
371
372 const Trk::TrackParameters* pars = (*tsit)->trackParameters();
373 if (!pars) { continue; }
374
375 // check whether measured parameters
376 bool isMeasured = pars->covariance();
377
378 // skip all none measured TrackParameters as soon as we found one with a measurement
379 if (closestIsMeasured && !isMeasured) continue;
380
381 // calculate position parameters and compare with position segment
382 double posPars = isEndcap ? pars->position().z() : pars->position().perp();
383 double diffPos = std::abs(posPars - posSeg);
384
385 // accept if measured parameters or the current accepted parameters are not yet measured
386 if ((isMeasured && !closestIsMeasured) || diffPos < closest) {
387 closest = diffPos;
388 closestParameters = pars;
389 closestIsMeasured = isMeasured;
390
391 // if we are within 100 mm take current
392 if (closest < 100.) { break; }
393 }
394 }
395
396 // return clone of parameters
397 if (closestParameters) return closestParameters->uniqueClone();
398 return nullptr;
399 }
400
401 std::unique_ptr<Trk::TrackParameters> MooTrackBuilder::getClosestParameters(const MuPatCandidateBase& candidate, const Trk::Surface& surf) const {
402 // cast to segment, return segment parameters if cast success
403 const MuPatSegment* segCandidate = dynamic_cast<const MuPatSegment*>(&candidate);
404 if (segCandidate) return segCandidate->entryPars().uniqueClone();
405
406 // for a track candidate, return the closest parameter on the track
407 const MuPatTrack& trkCandidate = dynamic_cast<const MuPatTrack&>(candidate);
408 return getClosestParameters(trkCandidate.track(), surf);
409 }
410
411 std::unique_ptr<Trk::TrackParameters> MooTrackBuilder::getClosestParameters(const Trk::Track& track, const Trk::Surface& surf) const {
413 }
414
415 std::vector<std::unique_ptr<Trk::Track> > MooTrackBuilder::combineWithSegmentFinding(const EventContext& ctx, const Trk::Track& track,
416 const Trk::TrackParameters& pars,
417 const std::set<Identifier>& chIds,
418 const PrepVec& patternPhiHits) const {
419 // convert track
420 std::unique_ptr<Trk::Track> inTrack = std::make_unique<Trk::Track>(track);
421 std::unique_ptr<MuPatTrack> can = m_candidateHandler->createCandidate(inTrack);
422 if (!can) { return {}; }
423 return combineWithSegmentFinding(ctx, *can, pars, chIds, patternPhiHits);
424 }
425
426 std::vector<std::unique_ptr<Trk::Track> > MooTrackBuilder::combineWithSegmentFinding(const EventContext& ctx, const MuPatTrack& candidate,
427 const MuPatSegment& segInfo,
428 const PrepVec& externalPhiHits) const {
434
435 const MuonSegment& seg = *segInfo.segment;
436 std::vector<std::unique_ptr<Trk::Track> > newTracks;
437
438 // get chamber Id of segment
439 std::set<Identifier> chIds = m_edmHelperSvc->chamberIds(seg);
440
441 if (chIds.empty()) return newTracks;
442
443 // for now do not redo segment making for CSCs
444 if (m_idHelperSvc->isCsc(*chIds.begin())) {
445 if (m_candidateMatchingTool->match(ctx, candidate, segInfo, true)) {
446 std::unique_ptr<Trk::Track> newtrack(m_fitter->fit(ctx, candidate, segInfo, externalPhiHits));
447 if (newtrack) newTracks.push_back(std::move(newtrack));
448 return newTracks;
449 } else {
450 return newTracks;
451 }
452 }
453
454 const Trk::Track& track = candidate.track();
455 ATH_MSG_DEBUG(" in combineWithSegmentFinding ");
456 ATH_MSG_VERBOSE(" segment " << m_printer->print(seg));
457
458 // find track parameters on segment surface
459 std::unique_ptr<Trk::TrackParameters> closestPars(findClosestParameters(track, seg.globalPosition()));
460
461 if (!closestPars) {
462 ATH_MSG_WARNING(" unable to find closest TrackParameters ");
463 return newTracks;
464 }
465
466 ATH_MSG_VERBOSE(" closest parameter " << m_printer->print(*closestPars));
467
468 // propagate to segment surface
469 std::unique_ptr<Trk::TrackParameters> exPars(
470 m_propagator->propagate(ctx,*closestPars, seg.associatedSurface(), Trk::anyDirection, false, m_magFieldProperties));
471
472 if (!exPars) {
473 ATH_MSG_WARNING(" Propagation failed!! ");
474 return newTracks;
475 }
476
477 ATH_MSG_VERBOSE(" extrapolated parameter " << m_printer->print(*exPars));
478
479 return combineWithSegmentFinding(ctx, candidate, *exPars, chIds, externalPhiHits);
480 }
481
482 void MooTrackBuilder::removeDuplicateWithReference(std::unique_ptr<Trk::SegmentCollection>& segments,
483 std::vector<const MuonSegment*>& referenceSegments) const {
484 if (referenceSegments.empty()) return;
485
486 ATH_MSG_DEBUG(" Removing duplicates from segment vector of size " << segments->size() << " reference size "
487 << referenceSegments.size());
488
489 CompareMuonSegmentKeys compareSegmentKeys{};
490
491 // create a vector with pairs of MuonSegmentKey and a pointer to the corresponding segment to resolve ambiguities
492 std::vector<std::pair<MuonSegmentKey, Trk::SegmentCollection::iterator> > segKeys;
493 segKeys.reserve(segments->size());
494
495 // loop over reference segments and make keys
496 Trk::SegmentCollection::iterator sit = segments->begin();
497 Trk::SegmentCollection::iterator sit_end = segments->end();
498 for (; sit != sit_end; ++sit) {
499 Trk::Segment* tseg = *sit;
500 MuonSegment* mseg = dynamic_cast<MuonSegment*>(tseg);
501 segKeys.emplace_back(MuonSegmentKey(*mseg), sit);
502 }
503
504 // create a vector with pairs of MuonSegmentKey and a pointer to the corresponding segment to resolve ambiguities
505 std::vector<MuonSegmentKey> referenceSegKeys;
506 referenceSegKeys.reserve(referenceSegments.size());
507
508 // loop over reference segments and make keys
509 std::vector<const MuonSegment*>::iterator vit = referenceSegments.begin();
510 std::vector<const MuonSegment*>::iterator vit_end = referenceSegments.end();
511 for (; vit != vit_end; ++vit) { referenceSegKeys.emplace_back(**vit); }
512
513 // loop over segments and compare the current segment with the reference ones
514 std::vector<std::pair<MuonSegmentKey, Trk::SegmentCollection::iterator> >::iterator skit = segKeys.begin();
515 std::vector<std::pair<MuonSegmentKey, Trk::SegmentCollection::iterator> >::iterator skit_end = segKeys.end();
516 for (; skit != skit_end; ++skit) {
517 bool isDuplicate = false;
518
519 std::vector<MuonSegmentKey>::iterator rskit = referenceSegKeys.begin();
520 std::vector<MuonSegmentKey>::iterator rskit_end = referenceSegKeys.end();
521
522 for (; rskit != rskit_end; ++rskit) {
523 CompareMuonSegmentKeys::OverlapResult overlapResult = compareSegmentKeys(*rskit, skit->first);
524 if (overlapResult == CompareMuonSegmentKeys::Identical) {
525 ATH_MSG_DEBUG(" discarding identical segment");
526 isDuplicate = true;
527 break;
528 } else if (overlapResult == CompareMuonSegmentKeys::SuperSet) {
529 // reference segment superset of current: discard
530 ATH_MSG_DEBUG(" discarding (subset) ");
531 isDuplicate = true;
532 break;
533 }
534 }
535 if (isDuplicate) segments->erase(skit->second);
536 }
537 }
538
539 std::vector<std::unique_ptr<Trk::Track> > MooTrackBuilder::combineWithSegmentFinding(const EventContext& ctx, const MuPatTrack& candidate,
540 const Trk::TrackParameters& pars,
541 const std::set<Identifier>& chIds,
542 const PrepVec& externalPhiHits) const {
543 std::vector<std::unique_ptr<Trk::Track> > newTracks;
544
545 if (chIds.empty()) return newTracks;
546
547 if (!m_idHelperSvc->isMdt(*chIds.begin())) {
548 ATH_MSG_WARNING("combineWithSegmentFinding called with CSC hits!! retuning zero pointer");
549 return newTracks;
550 }
551
552 // redo segment finding
553 std::unique_ptr<Trk::SegmentCollection> segments = m_seededSegmentFinder->find(ctx, pars, chIds);
554
555 // check whether we got segments
556 if (!segments) {
557 ATH_MSG_DEBUG(" failed to find new segments ");
558 return newTracks;
559 }
560 if (segments->empty()) {
561 ATH_MSG_DEBUG(" got empty vector!! ");
562 return newTracks;
563 }
564
565 unsigned int nseg = segments->size();
566 if (m_useExclusionList) {
567 std::vector<const MuonSegment*> referenceSegments;
568 for (std::vector<MuPatSegment*>::const_iterator esit = candidate.excludedSegments().begin();
569 esit != candidate.excludedSegments().end(); ++esit) {
570 if ((*esit)->segment) referenceSegments.push_back((*esit)->segment);
571 }
572 removeDuplicateWithReference(segments, referenceSegments);
573 }
574
575 if (msgLvl(MSG::DEBUG) && segments->size() != nseg) {
576 msg(MSG::DEBUG) << MSG::DEBUG
577 << " Rejected segments based on exclusion list, number of removed segments: " << nseg - segments->size()
578 << " total " << segments->size() << endmsg;
579 }
580
581 if (!segments->empty()) {
582 // loop over segments
583 for (Trk::Segment* tseg : *segments) {
584 if (!tseg) continue;
585 MuonSegment* mseg = dynamic_cast<MuonSegment*>(tseg);
586
587 if (msgLvl(MSG::DEBUG)) {
588 msg(MSG::DEBUG) << MSG::DEBUG << " adding segment " << m_printer->print(*mseg);
589 if (msgLvl(MSG::VERBOSE)) {
590 msg(MSG::DEBUG) << std::endl << m_printer->print(mseg->containedMeasurements()) << endmsg;
591 if (msgLvl(MSG::VERBOSE) && candidate.track().measurementsOnTrack())
592 msg(MSG::DEBUG) << " track " << m_printer->print(candidate.track()) << std::endl
593 << m_printer->print(candidate.track().measurementsOnTrack()->stdcont()) << endmsg;
594 } else {
595 msg(MSG::DEBUG) << endmsg;
596 }
597 }
598 std::unique_ptr<MuPatSegment> segInfo{m_candidateHandler->createSegInfo(ctx, *mseg)};
599
600 if (!m_candidateMatchingTool->match(ctx, candidate, *segInfo, true)) { continue; }
601
602 std::unique_ptr<Trk::Track> segTrack = m_fitter->fit(ctx, candidate, *segInfo, externalPhiHits);
603
604 if (!segTrack) continue;
605
606 ATH_MSG_DEBUG(" found new track " << m_printer->print(*segTrack));
607 newTracks.push_back(std::move(segTrack));
608 }
609 }
610
611 if (!newTracks.empty()) ATH_MSG_DEBUG(" found new tracks for segment " << newTracks.size());
612
613 return newTracks;
614 }
615
616 std::unique_ptr<Trk::Track> MooTrackBuilder::recalibrateHitsOnTrack(const EventContext& ctx, const Trk::Track& track, bool doMdts,
617 bool doCompetingClusters) const {
618 // loop over track and calculate residuals
619 const Trk::TrackStates* states = track.trackStateOnSurfaces();
620 if (!states) {
621 ATH_MSG_DEBUG(" track without states, discarding track ");
622 return nullptr;
623 }
624 if (msgLvl(MSG::DEBUG)) {
625 msg(MSG::DEBUG) << MSG::DEBUG << " recalibrating hits on track " << std::endl << m_printer->print(track);
626
627 if (msgLvl(MSG::VERBOSE)) {
628 if (track.measurementsOnTrack())
629 msg(MSG::DEBUG) << std::endl << m_printer->print(track.measurementsOnTrack()->stdcont()) << endmsg;
630 } else {
631 msg(MSG::DEBUG) << endmsg;
632 }
633 }
634 // vector to store states, the boolean indicated whether the state was create in this routine (true) or belongs to the track (false)
635 // If any new state is created, all states will be cloned and a new track will beformed from them.
636 std::vector<std::unique_ptr<const Trk::TrackStateOnSurface>> newStates;
637 newStates.reserve(states->size() + 5);
638
639 // loop over TSOSs
640 Trk::TrackStates::const_iterator state_itr = states->begin();
641 Trk::TrackStates::const_iterator end_itr = states->end();
642 for (; state_itr != end_itr; ++state_itr) {
643 const Trk::TrackStateOnSurface* tsit = (*state_itr);
644 if (!tsit) continue; // sanity check
645
646 // check whether state is a measurement
647 const Trk::TrackParameters* pars = tsit->trackParameters();
648 if (!pars) {
649 newStates.emplace_back(tsit->clone());
650 continue;
651 }
652
653 // check whether state is a measurement
654 const Trk::MeasurementBase* meas = tsit->measurementOnTrack();
655 if (!meas) {
656 newStates.emplace_back(tsit->clone());
657 continue;
658 }
659
660 Identifier id = m_edmHelperSvc->getIdentifier(*meas);
661
662 // Not a ROT, else it would have had an identifier. Keep the TSOS.
663 if (!id.is_valid() || !m_idHelperSvc->isMuon(id)) {
664 newStates.emplace_back(tsit->clone());
665 continue;
666 }
667
668 ATH_MSG_VERBOSE(" new measurement " << m_idHelperSvc->toString(id));
669
670 if (m_idHelperSvc->isMdt(id)) {
671 if (doMdts) {
672 const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(meas);
673 if (!mdt) {
674 ATH_MSG_WARNING(" Measurement with MDT identifier that is not a MdtDriftCircleOnTrack ");
675 continue;
676 }
677 std::unique_ptr<Trk::RIO_OnTrack> newMdt(m_mdtRotCreator->correct(*mdt->prepRawData(), *pars, ctx));
678 if (!newMdt) {
679 ATH_MSG_WARNING(" Failed to recalibrate MDT ");
680 continue;
681 }
682 std::unique_ptr<Trk::TrackStateOnSurface> tsos = MuonTSOSHelper::createMeasTSOSWithUpdate(
683 *tsit, std::move(newMdt), pars->uniqueClone(),
686 newStates.push_back(std::move(tsos));
687
688 } else {
689 newStates.emplace_back(tsit->clone());
690 }
691
692 } else if (m_idHelperSvc->isCsc(id)) {
693 newStates.emplace_back(tsit->clone());
694
695 } else if (m_idHelperSvc->isTrigger(id)) {
696 if (doCompetingClusters) {
697 state_itr = insertClustersWithCompetingRotCreation(ctx, state_itr, end_itr, newStates);
698 } else {
699 newStates.emplace_back(tsit->clone());
700 }
701
702 } else if (m_idHelperSvc->isMM(id) || m_idHelperSvc->issTgc(id)) {
703 newStates.emplace_back(tsit->clone());
704 } else {
705 ATH_MSG_WARNING(" unknown Identifier ");
706 }
707 }
708
709 ATH_MSG_DEBUG(" original track had " << states->size() << " TSOS, adding " << newStates.size() - states->size() << " new TSOS ");
710
711 // states were added, create a new track
712 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
713 trackStateOnSurfaces->reserve(newStates.size());
714 for (std::unique_ptr<const Trk::TrackStateOnSurface>& new_state : newStates) {
715 // add states. If nit->first is true we have a new state. If it is false the state is from the old track and has to be cloned
716 trackStateOnSurfaces->push_back(std::move(new_state));
717 }
718 return std::make_unique<Trk::Track>(track.info(), std::move(trackStateOnSurfaces),
719 track.fitQuality() ? track.fitQuality()->uniqueClone() : nullptr);
720 }
721
725 std::vector<std::unique_ptr<const Trk::TrackStateOnSurface> >& states) const {
726 // iterator should point to a valid element
727 if (tsit == tsit_end) {
728 ATH_MSG_WARNING(" iterator pointing to end of vector, this should no happen ");
729 return --tsit;
730 }
731
732 // check whether state is a measurement
733 const Trk::MeasurementBase* meas = (*tsit)->measurementOnTrack();
734 const Trk::TrackParameters* pars = (*tsit)->trackParameters();
735 if (!meas || !pars) {
736 ATH_MSG_WARNING(" iterator pointing to a TSOS without a measurement or TrackParameters ");
737 if (tsit + 1 == tsit_end) --tsit;
738 return tsit;
739 }
740
741 ATH_MSG_VERBOSE(" inserting with competing ROT creation ");
742
743 // loop over states until we reached the last tgc hit in this detector element
744 // keep trackof the identifiers and the states
745 std::list<const Trk::PrepRawData*> etaPrds;
746 std::list<const Trk::PrepRawData*> phiPrds;
747 const Trk::TrkDetElementBase* currentDetEl = nullptr;
748 std::vector<std::unique_ptr<const Trk::TrackStateOnSurface> > newStates;
749 // keep track of outliers as we might have to drop them..
750 std::vector<std::pair<bool, const Trk::TrackStateOnSurface*> > outlierStates;
751 bool hasPhi {false}, hasEta{false};
752
753 for (; tsit != tsit_end; ++tsit) {
754 const Trk::TrackStateOnSurface* in_tsos = *tsit;
755 if (!in_tsos) continue;
756
757 // check whether state is a measurement, keep if not
758 const Trk::MeasurementBase* meas = in_tsos->measurementOnTrack();
759 if (!meas) {
760 newStates.emplace_back(in_tsos->clone());
761 continue;
762 }
763
764 // get identifier, keep state if it has no identifier.
765 Identifier id = m_edmHelperSvc->getIdentifier(*meas);
766 if (!id.is_valid()) {
767 newStates.emplace_back(in_tsos->clone());
768 continue;
769 }
770
771 // sanity check, this SHOULD be a RPC, TGC or CSC measurement
772 if (!(m_idHelperSvc->isTrigger(id))) { break; }
773
774 bool measuresPhi = m_idHelperSvc->measuresPhi(id);
775 if (!hasPhi && measuresPhi) hasPhi = true;
776 if (!hasEta && !measuresPhi) hasEta = true;
777
778 // check whether state is a measurement
779 if ((*tsit)->type(Trk::TrackStateOnSurface::Outlier)) {
780 outlierStates.emplace_back(measuresPhi, in_tsos);
781 continue;
782 }
783
784 // check whether we are still in the same chamber, stop loop if not
785
786 ATH_MSG_VERBOSE(" handling " << m_idHelperSvc->toString(id));
787
788 std::list<const Trk::PrepRawData*>& prdList = measuresPhi ? phiPrds : etaPrds;
789 const MuonClusterOnTrack* clus = dynamic_cast<const MuonClusterOnTrack*>(meas);
790 if (clus) {
791 const Trk::TrkDetElementBase* detEl = clus->detectorElement();
792 if (!currentDetEl) currentDetEl = detEl;
793 if (detEl != currentDetEl) {
794 ATH_MSG_VERBOSE(" new detector element stopping ");
795 break;
796 }
797 prdList.push_back(clus->prepRawData());
798 } else {
799 // split competing ROTs into constituents
800 const CompetingMuonClustersOnTrack* comp = dynamic_cast<const CompetingMuonClustersOnTrack*>(meas);
801 if (comp) {
802 const Trk::TrkDetElementBase* detEl = nullptr;
803 if (comp->containedROTs().empty()) {
804 ATH_MSG_WARNING(" CompetingROT without constituents ");
805 break;
806 }
807 detEl = comp->containedROTs().front()->detectorElement();
808 if (!currentDetEl) currentDetEl = detEl;
809 if (detEl != currentDetEl) {
810 ATH_MSG_VERBOSE(" new detector element stopping ");
811 break;
812 }
813 std::ranges::transform(comp->containedROTs(), std::back_inserter(prdList),
814 [](const auto& rot){ return rot->prepRawData();});
815 } else {
816 ATH_MSG_WARNING(" Unknown trigger hit type! ");
817 continue;
818 }
819 }
820 }
821
822 // now that we have the lists of prds we can create the competing rots
823 if (!etaPrds.empty()) {
824 std::unique_ptr<CompetingMuonClustersOnTrack> etaCompRot = m_compRotCreator->createBroadCluster(etaPrds, 0.);
825 if (!etaCompRot) {
826 ATH_MSG_WARNING(" Failed to create CompetingMuonClustersOnTrack for eta hits! ");
827 } else {
828 std::unique_ptr<Trk::TrackParameters> etaPars;;
829 // check whether original parameters are on surface, if so clone original parameters
830 if (etaCompRot->associatedSurface() == pars->associatedSurface()) {
831 etaPars = pars->uniqueClone();
832 } else {
833 // ownership relinquished, should be treated in createMeasTSOS
834 etaPars =
835 m_propagator->propagate(ctx,*pars,
836 etaCompRot->associatedSurface(),
838 }
839 if (!etaPars) {
840 ATH_MSG_WARNING(" Failed to calculate TrackParameters for eta hits! ");
841 } else {
842 std::unique_ptr<Trk::TrackStateOnSurface> tsos =
843 MuonTSOSHelper::createMeasTSOS(std::move(etaCompRot), std::move(etaPars), Trk::TrackStateOnSurface::Measurement);
844 newStates.push_back(std::move(tsos));
845 }
846 }
847 }
848
849 if (!phiPrds.empty()) {
850 std::unique_ptr<CompetingMuonClustersOnTrack> phiCompRot = m_compRotCreator->createBroadCluster(phiPrds, 0.);
851 if (!phiCompRot) {
852 ATH_MSG_WARNING(" Failed to create CompetingMuonClustersOnTrack for phi hits! ");
853 } else {
854 std::unique_ptr<Trk::TrackParameters> phiPars;
855 // check whether original parameters are on surface, if so clone original parameters
856 if (phiCompRot->associatedSurface() == pars->associatedSurface()) {
857 phiPars = pars->uniqueClone();
858 } else {
859 // ownership relinquished, handled in createMeasTSOS
860 phiPars =
861 m_propagator->propagate(ctx, *pars, phiCompRot->associatedSurface(),
863 }
864 if (!phiPars) {
865 ATH_MSG_WARNING(" Failed to calculate TrackParameters for phi hits! ");
866 } else {
867 std::unique_ptr<Trk::TrackStateOnSurface> tsos =
868 MuonTSOSHelper::createMeasTSOS(std::move(phiCompRot), std::move(phiPars), Trk::TrackStateOnSurface::Measurement);
869 newStates.push_back(std::move(tsos));
870 }
871 }
872 }
873
874 // add outliers if there was no measurement on track in the same projection
875 for (const auto& outlier : outlierStates) {
876 if (hasPhi && outlier.first)
877 newStates.emplace_back(outlier.second->clone());
878 else if (hasEta && !outlier.first)
879 newStates.emplace_back(outlier.second->clone());
880 else if (msgLvl(MSG::DEBUG))
881 msg(MSG::DEBUG) << " Dropping outlier " << endmsg;
882 }
883
884 // sort all states in this chamber
885 std::stable_sort(newStates.begin(), newStates.end(), SortTSOSByDistanceToPars(pars));
886
887 // insert the states into
888 states.insert(states.end(), std::make_move_iterator(newStates.begin()),
889 std::make_move_iterator(newStates.end()));
890
891 // iterator should point to the last TGC in this chamber
892 return --tsit;
893 }
894
895 std::pair<std::unique_ptr<Trk::Track>, std::unique_ptr<Trk::Track> > MooTrackBuilder::splitTrack(const EventContext& ctx, const Trk::Track& track) const {
896 // use slFitter for straight line fit, or toroid off, otherwise use normal Fitter
897
898 if (m_edmHelperSvc->isSLTrack(track)) return m_slFitter->splitTrack(ctx, track);
899
900 MagField::AtlasFieldCache fieldCache;
901 // Get field cache object
903 const AtlasFieldCacheCondObj* fieldCondObj{*readHandle};
904
905 if (!fieldCondObj) {
906 ATH_MSG_ERROR("splitTrack: Failed to retrieve AtlasFieldCacheCondObj with key " << m_fieldCacheCondObjInputKey.key());
907 return {};
908 }
909 fieldCondObj->getInitializedCache(fieldCache);
910
911 if (!fieldCache.toroidOn()) return m_slFitter->splitTrack(ctx, track);
912
913 return m_fitter->splitTrack(ctx, track);
914 }
915
916 std::vector<std::unique_ptr<MuPatTrack> > MooTrackBuilder::find(const EventContext& ctx, MuPatCandidateBase& candidate,
917 const std::vector<MuPatSegment*>& segVec) const {
918 std::vector<std::unique_ptr<MuPatTrack> > candidates;
919 // check whether we have segments
920 if (segVec.empty()) return candidates;
921
922 std::set<MuPatSegment*> usedSegments;
923 std::map<MuPatSegment*, MuPatSegment*> slSegments;
924
925 // int looseQualityLevel = 1; // Not used for the moment
926 bool tightQualityCuts = false;
927 ATH_MSG_DEBUG(" find: " << m_candidateHandler->print(candidate, 0) << std::endl << m_candidateHandler->print(segVec, 0));
928
929 // store whether segment was added to at least one candidates
930
931 // vector to store candidate extensions
932 std::vector<std::pair<MuPatSegment*, std::unique_ptr<Trk::Track> > > extensions;
933 extensions.reserve(segVec.size());
934
935 // loop over segments
936 for (MuPatSegment* seg : segVec) {
937 if (usedSegments.count(seg)) continue;
938
939 // check whether chamber is already included in candidate
940 if (candidate.shareChambers(*seg)) {
941 ATH_MSG_VERBOSE("addStationToSeed:: already on candidate " << std::endl << m_printer->print(*seg->segment));
942 continue;
943 }
944
945 if (!m_candidateMatchingTool->match(ctx, candidate, *seg, tightQualityCuts)) {
946 ATH_MSG_VERBOSE(" track/segment combination rejected based on angular matching " << std::endl
947 << m_printer->print(*seg->segment));
948 continue;
949 }
950
951 ATH_MSG_VERBOSE("combining: " << m_printer->print(*seg->segment));
952
953 // try to combine track with segment
954 std::unique_ptr<Trk::Track> track = combine(ctx, candidate, *seg, emptyPhiHits);
955
956 // additional check in case the candidate is a MuPatTrack
957 MuPatTrack* trkCan = dynamic_cast<MuPatTrack*>(&candidate);
958 MuPatSegment* segCan = dynamic_cast<MuPatSegment*>(&candidate);
959 if (trkCan) {
960 if (!track) {
961 trkCan->addExcludedSegment(seg);
962 continue;
963 }
964
965 // is the new track better
966 SortTracksByHitNumber sortTracks;
967 if (!sortTracks(*track, trkCan->track())) {
968 ATH_MSG_VERBOSE(" rejecting track as new segment results in worse fit");
969 continue;
970 }
971
972 // check whether the track cleaner didn't remove one of the already added chamber layers
973 // loop over hits
974 std::set<MuonStationIndex::StIndex> stationLayersOnTrack;
975 for ( const Trk::MeasurementBase* meas : *track->measurementsOnTrack()) {
976 Identifier id = m_edmHelperSvc->getIdentifier(*meas);
977 if (!id.is_valid() || m_idHelperSvc->isTrigger(id)) { continue; }
978 stationLayersOnTrack.insert(m_idHelperSvc->stationIndex(id));
979 }
980
981 bool hasAllLayers = true;
982 for (const MuonStationIndex::StIndex& stIdx :candidate.stations()) {
983 if (!stationLayersOnTrack.count(stIdx)) {
984 ATH_MSG_VERBOSE(" missing layer " << MuonStationIndex::stName(stIdx));
985 hasAllLayers = false;
986 }
987 }
988
989 if (!hasAllLayers) {
990 ATH_MSG_VERBOSE(" rejecting track as one of the chamber layers of the candidate was removed ");
991 continue;
992 }
993 }
994
995 if (!track) { continue; }
996
997 usedSegments.insert(seg);
998
999 // now loop over segments once more and try to add SL overlap if missed
1000 // first check that segment is not an overlap segment
1001 if (!seg->hasSLOverlap()) {
1002 std::unique_ptr<MuPatTrack> newCandidate;
1003 // loop over segments
1004 for (MuPatSegment* seg_1 : segVec) {
1005 // select segments is different chamber
1006 if (seg->chIndex == seg_1->chIndex) continue;
1007
1008 if (!newCandidate) {
1009 std::unique_ptr<Trk::Track> trkTrkCan = std::make_unique<Trk::Track>(*track);
1010 if (trkCan) {
1011 // copy candidate and add segment
1012 newCandidate = std::make_unique<MuPatTrack>(*trkCan);
1013 m_candidateHandler->extendWithSegment(*newCandidate, *seg, trkTrkCan);
1014 } else if (segCan) {
1015 newCandidate = m_candidateHandler->createCandidate(*segCan, *seg, trkTrkCan);
1016 }
1017 if (!newCandidate) break;
1018 }
1019 if (!m_candidateMatchingTool->match(ctx, *newCandidate, *seg_1, tightQualityCuts)) {
1020 ATH_MSG_VERBOSE("track/segment combination rejected based on angular matching "
1021 << std::endl
1022 << m_printer->print(*seg->segment));
1023 continue;
1024 }
1025
1026 ATH_MSG_VERBOSE("adding SL overlap " << m_printer->print(*seg_1->segment));
1027 std::unique_ptr<Trk::Track> slOverlapTrack = combine(ctx, *track, *seg_1->segment, emptyPhiHits);
1028 if (!slOverlapTrack) continue;
1029
1030 // is the new track better
1031 SortTracksByHitNumber sortTracks;
1032 if (!sortTracks(*slOverlapTrack, *track)) {
1033 ATH_MSG_VERBOSE(__FILE__<<":"<<__LINE__<<" rejecting track as new segment results in worse fit");
1034 continue;
1035 }
1036 ATH_MSG_VERBOSE("adding SL overlap ok, new track" << m_printer->print(*slOverlapTrack) << std::endl
1037 << m_printer->printStations(*slOverlapTrack));
1038
1039 track.swap(slOverlapTrack);
1040 usedSegments.insert(seg_1);
1041 slSegments[seg] = seg_1;
1042 break;
1043 }
1044 }
1045
1046 ATH_MSG_VERBOSE(" Track found " << m_printer->print(*track)<<std::endl<<m_printer->printMeasurements(*track));
1047
1048 // add new solution
1049 extensions.emplace_back(seg, std::move(track));
1050
1051 } // for (sit)
1052
1053 // loop over solutions and add them
1054 if (!extensions.empty()) {
1055 candidates.reserve(extensions.size());
1056
1057 // additional check in case the candidate is a MuPatTrack
1058 MuPatTrack* trkCan = dynamic_cast<MuPatTrack*>(&candidate);
1059 MuPatSegment* segCan = dynamic_cast<MuPatSegment*>(&candidate);
1060
1061 // if more than 1 extensions are found, first add the copies
1062 // start from the second one to make copies based on the existing candidates
1063 for (std::pair<MuPatSegment*, std::unique_ptr<Trk::Track> >& ext_itr : extensions) {
1064 std::unique_ptr<MuPatTrack> newCandidate;
1065 if (trkCan) {
1066 // copy candidate and add segment
1067 newCandidate = std::make_unique<MuPatTrack>(*trkCan);
1068 m_candidateHandler->extendWithSegment(*newCandidate, *ext_itr.first, ext_itr.second);
1069 } else if (segCan) {
1070 newCandidate = m_candidateHandler->createCandidate(*segCan, *ext_itr.first, ext_itr.second);
1071 }
1072 ATH_MSG_DEBUG(" " << m_printer->print(*ext_itr.first->segment));
1073 MuPatSegment* slOverlap = slSegments[ext_itr.first];
1074
1075 if (slOverlap) {
1076 ATH_MSG_DEBUG("SLOverlap " << m_printer->print(*slOverlap->segment));
1077 // hack to allow me to add a second segment without changing the track
1078 std::unique_ptr<Trk::Track> nullTrack;
1079 newCandidate->addSegment(slOverlap, nullTrack);
1080 }
1081 candidates.push_back(std::move(newCandidate));
1082
1083 ATH_MSG_DEBUG(" creating new candidate " << candidates.back().get() << std::endl
1084 << m_printer->print(candidates.back()->track()) << std::endl
1085 << m_printer->printStations(candidates.back()->track()));
1086 }
1087 }
1088 return candidates;
1089 }
1090
1091 bool MooTrackBuilder::isSplitTrack(const EventContext& ctx, const Trk::Track& track1, const Trk::Track& track2) const {
1092 // some loose association cuts
1094 if (!parsVec1 || parsVec1->empty()) {
1095 ATH_MSG_WARNING(" isSplitTrack::Track without parameters! ");
1096 return false;
1097 }
1098 const Trk::TrackParameters* pars1 = parsVec1->front();
1099 if (!pars1) {
1100 ATH_MSG_WARNING(" isSplitTrack::Track without NULL pointer in parameter vector! ");
1101 return false;
1102 }
1103
1105 if (!parsVec2 || parsVec2->empty()) {
1106 ATH_MSG_WARNING(" isSplitTrack::Track without parameters! ");
1107 return false;
1108 }
1109 const Trk::TrackParameters* pars2 = parsVec2->front();
1110 if (!pars2) {
1111 ATH_MSG_WARNING(" isSplitTrack::Track without NULL pointer in parameter vector! ");
1112 return false;
1113 }
1114
1115 if (!m_candidateMatchingTool->sameSide(pars1->momentum().unit(), pars1->position(), pars2->position(), true)) {
1116 ATH_MSG_DEBUG(" tracks in opposite hemispheres ");
1117 return false;
1118 }
1119
1120 double sinTheta1 = sin(pars1->momentum().theta());
1121 double sinTheta2 = sin(pars2->momentum().theta());
1122 double deltaSinTheta = sinTheta1 - sinTheta2;
1123 if (std::abs(deltaSinTheta) > 1.) {
1124 ATH_MSG_DEBUG(" too large opening angle in theta " << deltaSinTheta);
1125 // return false;
1126 }
1127 double sinPhi1 = sin(pars1->momentum().phi());
1128 double sinPhi2 = sin(pars2->momentum().phi());
1129 double deltaSinPhi = sinPhi1 - sinPhi2;
1130 if (std::abs(deltaSinPhi) > 1.) {
1131 ATH_MSG_DEBUG(" too large opening angle in phi " << deltaSinPhi);
1132 // return false;
1133 }
1134
1135 const Trk::Track* referenceTrack = nullptr;
1136 const Trk::Track* otherTrack = nullptr;
1137
1138 // first check whether the tracks have a momentum measurement
1139 bool isSL1 = m_edmHelperSvc->isSLTrack(track1);
1140 bool isSL2 = m_edmHelperSvc->isSLTrack(track2);
1141
1142 // now decide which track to use as reference
1143 if (isSL1 && !isSL2) {
1144 referenceTrack = &track2;
1145 otherTrack = &track1;
1146 } else if (!isSL1 && isSL2) {
1147 referenceTrack = &track1;
1148 otherTrack = &track2;
1149 } else {
1150 SortTracksByHitNumber sortTracks;
1151 bool pickFirst = sortTracks(track1, track2);
1152 if (pickFirst) {
1153 referenceTrack = &track1;
1154 otherTrack = &track2;
1155 } else {
1156 referenceTrack = &track2;
1157 otherTrack = &track1;
1158 }
1159 }
1160
1161 ATH_MSG_DEBUG(" close tracks " << std::endl << m_printer->print(*referenceTrack) << std::endl << m_printer->print(*otherTrack));
1162
1163 // get iterators to TSOSs
1164 const Trk::TrackStates* statesRef = referenceTrack->trackStateOnSurfaces();
1165 if (!statesRef) {
1166 ATH_MSG_WARNING(" track without states, cannot perform cleaning ");
1167 return false;
1168 }
1169 Trk::TrackStates::const_iterator refTSOS = statesRef->begin();
1170 Trk::TrackStates::const_iterator refTSOS_end = statesRef->end();
1171
1172 const Trk::TrackStates* statesOther = otherTrack->trackStateOnSurfaces();
1173 if (!statesOther) {
1174 ATH_MSG_WARNING(" track without states, cannot perform cleaning ");
1175 return false;
1176 }
1177 Trk::TrackStates::const_iterator otherTSOS = statesOther->begin();
1178 Trk::TrackStates::const_iterator otherTSOS_end = statesOther->end();
1179
1180 DistanceAlongParameters distAlongPars;
1181
1182 unsigned int nmatching(0);
1183 unsigned int noff(0);
1184
1185 // keep track of previous distance and parameters as well
1186 double prevDist = 1e10;
1187 const Trk::TrackParameters* prevPars = nullptr;
1188
1189 // now loop over the TSOSs of both tracks and compare hit by hit
1190 while (refTSOS != refTSOS_end && otherTSOS != otherTSOS_end) {
1191 const Trk::TrackParameters* parsRef = (*refTSOS)->trackParameters();
1192 if (!parsRef) {
1193 ++refTSOS;
1194 continue;
1195 }
1196
1197 const Trk::TrackParameters* parsOther = (*otherTSOS)->trackParameters();
1198 if (!parsOther) {
1199 ++otherTSOS;
1200 continue;
1201 }
1202
1203 double dist = distAlongPars(*parsRef, *parsOther);
1204
1205 if (dist > 0.) {
1206 prevDist = dist;
1207 prevPars = parsRef;
1208 ++refTSOS;
1209 continue;
1210 } else {
1211 const Trk::TrackParameters* closestPars = nullptr;
1212 if (prevPars && std::abs(prevDist) < std::abs(dist)) {
1213 closestPars = prevPars;
1214 } else {
1215 closestPars = parsRef;
1216 }
1217
1218 // check whether state is a measurement
1219 const Trk::MeasurementBase* meas = (*otherTSOS)->measurementOnTrack();
1220 if (meas && (*otherTSOS)->type(Trk::TrackStateOnSurface::Measurement)) {
1221 Identifier id = m_edmHelperSvc->getIdentifier(*meas);
1222 // skip pseudo measurements
1223 if (!id.is_valid()) {
1224 prevDist = dist;
1225 prevPars = parsRef;
1226 ++otherTSOS;
1227 continue;
1228 }
1229 if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << m_idHelperSvc->toString(id);
1230 // unique ptr ownership retained. Original code deleted impactPars
1231 auto impactPars =
1232 m_propagator->propagate(ctx, *closestPars, meas->associatedSurface(),
1234 if (impactPars) {
1235 double residual = 1e10;
1236 double pull = 1e10;
1237 // pointer to resPull
1238 std::optional<Trk::ResidualPull> resPull =
1239 m_pullCalculator->residualPull(meas, impactPars.get(), Trk::ResidualPull::Unbiased);
1240 if (resPull && resPull->pull().size() == 1) {
1241 if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << " residual " << m_printer->print(*resPull);
1242 residual = resPull->residual().front();
1243 pull = resPull->pull().front();
1244 } else {
1245 ATH_MSG_WARNING("failed to calculate residual and pull");
1246 }
1247
1248 bool inBounds = false;
1249 Amg::Vector2D LocVec2D;
1250 bool ok = meas->associatedSurface().globalToLocal(impactPars->position(), impactPars->momentum(), LocVec2D);
1251 // delete impactPars;
1252 if (ok) {
1253 if (msgLvl(MSG::VERBOSE))
1254 msg(MSG::VERBOSE) << " lpos (" << LocVec2D[Trk::locX] << "," << LocVec2D[Trk::locY] << ")";
1255 double tol1 = 50.;
1256 double tol2 = tol1;
1257 Identifier id = m_edmHelperSvc->getIdentifier(*meas);
1258 if (msgLvl(MSG::VERBOSE) && m_idHelperSvc->isMdt(id)) {
1259 const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(meas);
1260 if (mdt) {
1261 int layer = m_idHelperSvc->mdtIdHelper().tubeLayer(id);
1262 int tube = m_idHelperSvc->mdtIdHelper().tube(id);
1263 double halfTubeLen = 0.5 * mdt->detectorElement()->getActiveTubeLength(layer, tube);
1264 if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << " range " << halfTubeLen;
1265 }
1266 }
1267
1268 // for MM, perform the bound check from the detector element to take into account edge passivation
1269 const MMClusterOnTrack* mmClusterOnTrack = dynamic_cast<const MMClusterOnTrack*>(meas);
1270 if (mmClusterOnTrack) {
1271 inBounds = mmClusterOnTrack->detectorElement()->insideActiveBounds(id, LocVec2D, tol1, tol2);
1272 } else {
1273 inBounds = meas->associatedSurface().insideBounds(LocVec2D, tol1, tol2);
1274 }
1275
1276 if (msgLvl(MSG::VERBOSE)) {
1277 if (inBounds)
1278 msg(MSG::VERBOSE) << " inBounds ";
1279 else
1280 msg(MSG::VERBOSE) << " outBounds ";
1281 }
1282 } else {
1283 ATH_MSG_WARNING("globalToLocal failed");
1284 }
1285
1286 if (inBounds && (std::abs(residual) < 20. || std::abs(pull) < 10.)) {
1287 ATH_MSG_VERBOSE(" --> matching ");
1288 ++nmatching;
1289 } else {
1290 ATH_MSG_VERBOSE(" --> off ");
1291 ++noff;
1292 }
1293
1294 } else {
1295 ATH_MSG_DEBUG("failed to extrapolate parameters to surface");
1296 }
1297 }
1298
1299 prevDist = dist;
1300 prevPars = parsRef;
1301 ++otherTSOS;
1302 continue;
1303 }
1304 }
1305
1306 // if more hits are compatible with reference track than are not consider as split track
1307 return nmatching > noff;
1308 }
1309
1310 TrackCollection* MooTrackBuilder::mergeSplitTracks(const EventContext& ctx, const TrackCollection& tracks) const {
1311 // vector to store good track, boolean is used to identify whether the track was created in this routine or is from the collection
1312 std::vector<std::pair<bool, std::unique_ptr<Trk::Track> > > goodTracks;
1313 goodTracks.reserve(tracks.size());
1314 bool foundSplitTracks = false;
1315
1316 ATH_MSG_DEBUG(" trying to merge split tracks, collection size " << tracks.size());
1317
1318 // loop over tracks
1319 for (const Trk::Track* in_track : tracks) {
1320 // pointer to merged track
1321 std::unique_ptr<Trk::Track> mergedTrack;
1322
1323 // compare them to all good tracks and look for split tracks
1324 for (std::pair<bool, std::unique_ptr<Trk::Track>>& good_trk : goodTracks) {
1325 // check whether track is split
1326 bool isSplit = isSplitTrack(ctx, *good_trk.second, *in_track);
1327 if (isSplit) {
1328 // if we found a potential split track, try to combine them
1329 std::unique_ptr<Trk::Track> track1 = std::make_unique<Trk::Track>(*good_trk.second);
1330 std::unique_ptr<Trk::Track> track2 = std::make_unique<Trk::Track>(*in_track);
1331 std::unique_ptr<MuPatTrack> can1 = m_candidateHandler->createCandidate(track1);
1332 std::unique_ptr<MuPatTrack> can2 = m_candidateHandler->createCandidate(track2);
1333 mergedTrack = combine(ctx, *can1, *can2, emptyPhiHits);
1334
1335 // we have found a split track and have successfully merged it
1336 // replace the track in goodTracks with the new one
1337 if (mergedTrack) {
1338 ATH_MSG_DEBUG(" origninal tracks " << std::endl
1339 << m_printer->print(*good_trk.second) << std::endl
1340 << m_printer->printStations(*good_trk.second) << std::endl
1341 << m_printer->print(*in_track) << std::endl
1342 << m_printer->printStations(*in_track) << std::endl
1343 << " merged track " << std::endl
1344 << m_printer->print(*mergedTrack) << std::endl
1345 << m_printer->printStations(*mergedTrack));
1346 foundSplitTracks = true;
1347 // check whether this is a new track, if so delete the old one before overwriting it
1348 good_trk.first = true;
1349 good_trk.second.swap(mergedTrack);
1350 break;
1351 } else {
1352 ATH_MSG_VERBOSE(" failed to merge tracks " << std::endl
1353 << m_printer->print(*good_trk.second) << std::endl
1354 << m_printer->printStations(*good_trk.second) << std::endl
1355 << m_printer->print(*in_track) << std::endl
1356 << m_printer->printStations(*in_track));
1357 }
1358 }
1359 }
1360
1361 // if this track was not merged with another track insert it into goodTracks
1362 if (!mergedTrack) {
1363 std::unique_ptr<Trk::Track> newTrack = std::make_unique<Trk::Track>(*in_track);
1364 goodTracks.emplace_back(false, std::move(newTrack));
1365 }
1366 }
1367
1368 // did we find any?
1369 if (!foundSplitTracks) return nullptr;
1370 // loop over the new track vector and create a new TrackCollection
1371 TrackCollection* newTracks = new TrackCollection();
1372 newTracks->reserve(goodTracks.size());
1373 for (std::pair<bool, std::unique_ptr<Trk::Track>>& good_trk: goodTracks) {
1374 // TrackCollection will take ownership
1375 newTracks->push_back(std::move(good_trk.second));
1376 }
1377 return newTracks;
1378 }
1379
1380} // namespace Muon
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Timeout singleton.
DataVector< Trk::Track > TrackCollection
This typedef represents a collection of Trk::Track objects.
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
bool msgLvl(const MSG::Level lvl) const
MsgStream & msg() const
static Timeout & instance()
Get reference to Timeout singleton.
Definition Timeout.h:64
void getInitializedCache(MagField::AtlasFieldCache &cache) const
get B field cache for evaluation as a function of 2-d or 3-d position.
Derived DataVector<T>.
Definition DataVector.h:795
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
void reserve(size_type n)
Attempt to preallocate enough memory for a specified number of elements.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
DataModel_detail::iterator< DataVector > iterator
Definition DataVector.h:842
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.
const T * front() const
Access the first element in the collection as an rvalue.
size_type size() const noexcept
Returns the number of elements in the collection.
bool empty() const noexcept
Returns true if the collection is empty.
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h).
bool insideActiveBounds(const Identifier &id, const Amg::Vector2D &locpos, double tol1=0., double tol2=0.) const
boundary check Wrapper Trk::PlaneSurface::insideBounds() taking into account the passivated width
double getActiveTubeLength(const int tubeLayer, const int tube) const
Class for competing MuonClusters, it extends the Trk::CompetingRIOsOnTrack base class.
std::vector< const Trk::PrepRawData * > PrepVec
Class to represent calibrated clusters formed from TGC strips.
virtual const MuonGM::MMReadoutElement * detectorElement() const
Returns the detector element, assoicated with the PRD of this class.
This class represents the corrected MDT measurements, where the corrections include the effects of wi...
virtual const MuonGM::MdtReadoutElement * detectorElement() const override final
Returns the detector element, assoicated with the PRD of this class.
virtual const MdtPrepData * prepRawData() const override final
Returns the PrepRawData used to create this corrected measurement.
virtual std::unique_ptr< Trk::TrackParameters > getClosestParameters(const Trk::Track &track, const Trk::Surface &surf) const override
find closest TrackParameters to the surface.
ToolHandle< MuPatCandidateTool > m_candidateHandler
candidate handler
ToolHandle< IMuonCompetingClustersOnTrackCreator > m_compRotCreator
void removeDuplicateWithReference(std::unique_ptr< Trk::SegmentCollection > &segments, std::vector< const MuonSegment * > &referenceSegments) const
ToolHandle< Trk::IPropagator > m_propagator
bool isSplitTrack(const EventContext &ctx, const Trk::Track &track1, const Trk::Track &track2) const
identify whether two track are split
Trk::MagneticFieldProperties m_magFieldProperties
magnetic field properties
virtual std::vector< std::unique_ptr< MuPatTrack > > find(const EventContext &ctx, MuPatCandidateBase &candidate, const std::vector< MuPatSegment * > &segments) const override
interface for tools to find track in the muon system starting from a vector of segments
ToolHandle< IMuonSeededSegmentFinder > m_seededSegmentFinder
Gaudi::Property< bool > m_recalibrateMDTHits
ToolHandle< IMdtDriftCircleOnTrackCreator > m_mdtRotCreator
PublicToolHandle< MuonEDMPrinterTool > m_printer
tool to print out EDM objects;
Gaudi::Property< bool > m_useTrackingHistory
use history of the track finding up to now to avoid creating duplicates
ServiceHandle< IMuonEDMHelperSvc > m_edmHelperSvc
std::atomic_uint m_ncalls
virtual std::unique_ptr< Trk::TrackParameters > findClosestParameters(const Trk::Track &track, const Amg::Vector3D &pos) const override
find closest TrackParameters to the position.
ToolHandle< MooTrackFitter > m_fitter
virtual void refine(const EventContext &ctx, MuPatTrack &track) const override
interface for tools which refine the hit content of a given track
Gaudi::Property< bool > m_useExclusionList
use exclusion list (bit faster at the price of missing chambers)
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
MooTrackBuilder(const std::string &, const std::string &, const IInterface *)
default AlgTool constructor
ToolHandle< Trk::IExtendedTrackSummaryTool > m_trackSummaryTool
std::atomic_uint m_nTimedOut
ToolHandle< IMuonHoleRecoveryTool > m_muonChamberHoleRecoverTool
ToolHandle< MooCandidateMatchingTool > m_candidateMatchingTool
ToolHandle< MooTrackFitter > m_slFitter
std::vector< std::unique_ptr< Trk::Track > > combineWithSegmentFinding(const EventContext &ctx, const Trk::Track &track, const MuonSegment &seg, const PrepVec &patternPhiHits) const
find tracks by redoing the segment finding in the chamber of the segment
std::unique_ptr< MuonSegment > combineToSegment(const EventContext &ctx, const MuPatCandidateBase &firstEntry, const MuPatCandidateBase &secondEntry, const PrepVec &patternPhiHits) const
Methos is used externally by MuonTrackSteering.cxx:233. Should be revised to put it into an interface...
ToolHandle< IMuonErrorOptimisationTool > m_errorOptimisationTool
virtual StatusCode initialize() override
initialize method, method taken from bass-class AlgTool
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
TrackCollection * mergeSplitTracks(const EventContext &ctx, const TrackCollection &tracks) const
look for split tracks in collection and merge them
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...
ToolHandle< IMuonTrackToSegmentTool > m_trackToSegmentTool
virtual std::unique_ptr< Trk::Track > recalibrateHitsOnTrack(const EventContext &ctx, const Trk::Track &track, bool doMdts, bool doCompetingClusters) const override
recalibrate hits on track
ToolHandle< IMuonTrackExtrapolationTool > m_trackExtrapolationTool
virtual std::unique_ptr< Trk::Track > refit(const EventContext &ctx, Trk::Track &track) const override
refit track
Gaudi::Property< bool > m_doTimeOutChecks
on/off time out check
Trk::TrackStates::const_iterator insertClustersWithCompetingRotCreation(const EventContext &ctx, Trk::TrackStates::const_iterator tsit, Trk::TrackStates::const_iterator tsit_end, std::vector< std::unique_ptr< const Trk::TrackStateOnSurface > > &states) const
ToolHandle< Trk::IResidualPullCalculator > m_pullCalculator
virtual StatusCode finalize() override
finialize method, method taken from bass-class AlgTool
std::unique_ptr< Trk::Track > combine(const EventContext &ctx, const MuPatCandidateBase &firstEntry, const MuPatCandidateBase &secondEntry, const PrepVec &patternPhiHits) const
combine two MCTBCandidateEntries
track candidate entry object.
const std::set< MuonStationIndex::StIndex > & stations() const
returns set with contained stationIndices
bool shareChambers(const MuPatCandidateBase &entry) const
checks whether the two entries contain the same chamber
segment candidate object.
const Trk::TrackParameters & entryPars() const
returns first track parameters
const MuonSegment * segment
track candidate object.
Definition MuPatTrack.h:37
void addExcludedSegment(MuPatSegment *segment)
add segment that does not match the track
Trk::Track & track() const
access to track
Definition MuPatTrack.h:175
const std::vector< MuPatSegment * > & excludedSegments() const
access to segments
Definition MuPatTrack.h:173
const std::vector< MuPatSegment * > & segments() const
access to segments
Definition MuPatTrack.h:167
Base class for Muon cluster RIO_OnTracks.
virtual const MuonGM::MuonClusterReadoutElement * detectorElement() const override=0
Returns the detector element, associated with the PRD of this class.
virtual const MuonCluster * prepRawData() const override=0
Returns the Trk::PrepRawData - is a MuonCluster in this scope.
static std::unique_ptr< Trk::TrackParameters > closestParameters(const Trk::Track &track, const Amg::Vector3D &pos, bool onlyUseMeasured=false)
Class to cache the identifiers on a segment in sets that can later be used to perform an overlap remo...
This is the common class for 3D segments used in the muon spectrometer.
virtual const Amg::Vector3D & globalPosition() const override final
global position
virtual const Trk::PlaneSurface & associatedSurface() const override final
returns the surface for the local to global transformation
static std::unique_ptr< Trk::TrackStateOnSurface > createMeasTSOS(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
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
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.
virtual bool type(MeasurementBaseType::Type type) const =0
Interface method checking the type.
const Amg::Vector3D & momentum() const
Access method for the momentum.
const Amg::Vector3D & position() const
Access method for the position.
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...
@ Unbiased
RP with track state that has measurement not included.
Base class for all TrackSegment implementations, extends the common MeasurementBase.
const std::vector< const Trk::MeasurementBase * > & containedMeasurements() const
returns the vector of Trk::MeasurementBase objects
Abstract Base Class for tracking surfaces.
Definition Surface.h:79
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...
virtual bool insideBounds(const Amg::Vector2D &locpos, double tol1=0., double tol2=0.) const =0
virtual methods to be overwritten by the inherited surfaces
represents the track state (measurement, material, fit parameters and quality) at a surface.
virtual TrackStateOnSurface * clone() const
Pseudo-constructor: needed to avoid excessive RTTI.
const MeasurementBase * measurementOnTrack() const
returns MeasurementBase const overload
const TrackParameters * trackParameters() const
return ptr to trackparameters const overload
bool type(const TrackStateOnSurfaceType type) const
Use this method to find out if the TSoS is of a certain type: i.e.
@ Measurement
This is a measurement, and will at least contain a Trk::MeasurementBase.
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
const Trk::TrackStates * trackStateOnSurfaces() const
return a pointer to a const DataVector of const TrackStateOnSurfaces.
const DataVector< const MeasurementBase > * measurementsOnTrack() const
return a pointer to a vector of MeasurementBase (NOT including any that come from outliers).
const DataVector< const TrackParameters > * trackParameters() const
Return a pointer to a vector of TrackParameters.
This is the base class for all tracking detector elements with read-out relevant information.
holding In fact this class is here in order to allow STL container for all features This class is sho...
void zero(TH2 *h)
zero the contents of a 2d histogram
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
StIndex
enum to classify the different station layers in the muon spectrometer
const std::string & stName(StIndex index)
convert StIndex into a string
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
static const MooTrackBuilder::PrepVec emptyPhiHits
@ anyDirection
DataVector< const Trk::TrackStateOnSurface > TrackStates
@ locY
local cartesian
Definition ParamDefs.h:38
@ locX
Definition ParamDefs.h:37
ParametersBase< TrackParametersDim, Charged > TrackParameters
void stable_sort(DataModel_detail::iterator< DVL > beg, DataModel_detail::iterator< DVL > end)
Specialization of stable_sort for DataVector/List.
OverlapResult
enum for the overlap result