ATLAS Offline Software
Loading...
Searching...
No Matches
Muon::MooTrackFitter Class Reference

Tool to fit a trajectory using a set of two segments or a track and a segment as input. More...

#include <MooTrackFitter.h>

Inheritance diagram for Muon::MooTrackFitter:
Collaboration diagram for Muon::MooTrackFitter:

Classes

struct  FitterData
struct  StationPhiData

Public Types

typedef std::vector< const Trk::MeasurementBase * > MeasVec
typedef MeasVec::iterator MeasIt
typedef MeasVec::const_iterator MeasCit
typedef std::vector< const Trk::PrepRawData * > PrepVec
typedef PrepVec::iterator PrepIt
typedef PrepVec::const_iterator PrepCit
typedef std::pair< int, int > SmallLargeChambers
typedef std::map< MuonStationIndex::StIndex, SmallLargeChambersSLStationMap
typedef std::vector< std::pair< const Trk::TrackParameters *, const Trk::Layer * > > MaterialLayers

Public Member Functions

 MooTrackFitter (const std::string &, const std::string &, const IInterface *)
 default AlgTool constructor
 ~MooTrackFitter ()=default
 destructor
StatusCode initialize ()
 initialize method, method taken from bass-class AlgTool
StatusCode finalize ()
 finialize method, method taken from bass-class AlgTool
std::unique_ptr< Trk::Trackfit (const EventContext &ctx, const MuPatCandidateBase &firstEntry, const MuPatCandidateBase &secondEntry, const PrepVec &externalPhiHits) const
 fit the hits of two MuPatCandidateBase
std::unique_ptr< Trk::Trackrefit (const EventContext &ctx, const MuPatTrack &trkCan) const
 refit a MuPatTrack
std::unique_ptr< Trk::Trackrefit (const EventContext &ctx, const Trk::Track &track) const
 refit a track
std::unique_ptr< Trk::PerigeecreatePerigee (const EventContext &ctx, const Trk::TrackParameters &firstPars, const Trk::MeasurementBase &firstMeas) const
 create perigee parameter to initialize fit
std::unique_ptr< Trk::Trackfit (const EventContext &ctx, const Trk::Perigee &startPars, MeasVec &hits, Trk::ParticleHypothesis partHypo, bool prefit) const
 fit track
std::unique_ptr< Trk::TrackfitWithRefit (const EventContext &ctx, const Trk::Perigee &startPars, MeasVec &hits) const
 fit track, refit if needed
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 extrapolated to the muon entry record using the MuonTrackExtrapolationTool.
std::unique_ptr< Trk::TrackfitSplitTrack (const EventContext &ctx, const Trk::TrackParameters &startPars, const std::vector< const Trk::TrackStateOnSurface * > &tsos) const
 construct a track from a list of TSOS and a start parameters
ServiceHandle< StoreGateSvc > & evtStore ()
 The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.
const ServiceHandle< StoreGateSvc > & detStore () const
 The standard StoreGateSvc/DetectorStore Returns (kind of) a pointer to the StoreGateSvc.
virtual StatusCode sysInitialize () override
 Perform system initialization for an algorithm.
virtual StatusCode sysStart () override
 Handle START transition.
virtual std::vector< Gaudi::DataHandle * > inputHandles () const override
 Return this algorithm's input handles.
virtual std::vector< Gaudi::DataHandle * > outputHandles () const override
 Return this algorithm's output handles.
Gaudi::Details::PropertyBase & declareProperty (Gaudi::Property< T, V, H > &t)
void updateVHKA (Gaudi::Details::PropertyBase &)
MsgStream & msg () const
bool msgLvl (const MSG::Level lvl) const

Static Public Member Functions

static const InterfaceID & interfaceID ()
 access to tool interface
static double restrictedMomentum (double momentum)
 impose upper and lower bound on momentum

Protected Member Functions

void renounceArray (SG::VarHandleKeyArray &handlesArray)
 remove all handles from I/O resolution
std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > renounce (T &h)
void extraDeps_update_handler (Gaudi::Details::PropertyBase &ExtraDeps)
 Add StoreName to extra input/output deps as needed.

Private Types

typedef ServiceHandle< StoreGateSvcStoreGateSvc_t

Private Member Functions

std::unique_ptr< Trk::TrackcleanAndEvaluateTrack (const EventContext &ctx, Trk::Track &track, const std::set< Identifier > &excludedChambers) const
 clean and evaluate the track,
bool extractData (const MuPatCandidateBase &entry1, const MuPatCandidateBase &entry2, FitterData &fitterData) const
 extract all information needed for the fit from the track
bool extractData (FitterData &fitterData, bool usePreciseHits) const
 extract all information from the HitList of a FitterData object
bool addFakePhiHits (const EventContext &ctx, FitterData &fitterData, const Trk::TrackParameters &referenceParameter) const
 check fitterData, add fake phi hits if needed.
bool corruptEntry (const MuPatCandidateBase &entry) const
 sanity check for entries
bool getMaterial (const Trk::TrackParameters &pars, FitterData &fitterData) const
 get material
void createStartParameters (const EventContext &ctx, FitterData &inputData) const
 create a perigee parameter give the input data
std::shared_ptr< const MuonSegmentsegmentFromEntry (const EventContext &ctx, const MuPatCandidateBase &entry) const
 get segment from entry
unsigned int hasPhiConstrain (FitterData &inputData) const
 check whether data has sufficient phi constraints
unsigned int hasPhiConstrain (Trk::Track *track) const
 check whether data has sufficient phi constraints
std::unique_ptr< Trk::MeasurementBasecreateFakePhiForMeasurement (const Trk::MeasurementBase &measurement, const Amg::Vector3D *overlapPos, const Amg::Vector3D *phiPos, double error) const
 create fake phi hit on the surface of the give measurement
double qOverPFromEntries (const EventContext &ctx, const MuPatCandidateBase &firstEntry, const MuPatCandidateBase &secondEntry) const
 get q/p using angle + position of the two entries
double phiSeeding (const EventContext &ctx, FitterData &fitterData) const
 calculate phi used to for seeding the fit
double thetaSeeding (const MuPatCandidateBase &entry, MeasVec &etaHits) const
 calculate theta used for seeding the fit
bool cleanPhiHits (const EventContext &ctx, double momentum, FitterData &phiHits, const PrepVec &patternPhiHits) const
 clean phi hits, returns true if anything happened during the cleaning
bool validMomentum (const Trk::TrackParameters &pars) const
 check whether mometum of start parameter is ok
bool getMinMaxPhi (FitterData &fitterData) const
 calculate the minimum and maximum phi value a track could have to pass all eta channels
void removeSegmentOutliers (FitterData &fitterData) const
void cleanEntry (const MuPatCandidateBase &entry, std::set< Identifier > &removedIdentifiers) const
void cleanSegment (const MuonSegment &seg, std::set< Identifier > &removedIdentifiers) const
std::pair< double, double > getElementHalfLengths (const Identifier &id, const Trk::TrkDetElementBase *ele) const
Gaudi::Details::PropertyBase & declareGaudiProperty (Gaudi::Property< T, V, H > &hndl, const SG::VarHandleKeyType &)
 specialization for handling Gaudi::Property<SG::VarHandleKey>

Static Private Member Functions

static double qOverPFromEntry (const MuPatCandidateBase &entry)
 get q/p from entry

Private Attributes

ToolHandle< Trk::IPropagatorm_propagator
 propagator
ToolHandle< Trk::ITrackFitterm_trackFitter {this, "Fitter", "Trk::GlobalChi2Fitter/MCTBFitter"}
 fitter
PublicToolHandle< MuPatHitToolm_hitHandler {this, "HitTool", "Muon::MuPatHitTool/MuPatHitTool"}
 hit handler
ToolHandle< IMuonSegmentMomentumEstimatorm_momentumEstimator
 tool to estimate track momentum
Gaudi::Property< Trk::RunOutlierRemovalm_runOutlier {this, "RunOutlier", false, "Switch whether to run outlier logics or not"}
Gaudi::Property< int > m_matEffects {this, "MatEffects", 2, "type of material interaction in extrapolation"}
Trk::ParticleHypothesis m_ParticleHypothesis
 nomen est omen
Trk::TrackInfo::TrackPatternRecoInfo m_patRecInfo {Trk::TrackInfo::Moore}
Trk::MagneticFieldProperties m_magFieldProperties {Trk::FullField}
 magnetic field properties
ServiceHandle< Muon::IMuonIdHelperSvcm_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}
ServiceHandle< IMuonEDMHelperSvcm_edmHelperSvc
 multi purpose helper tool
PublicToolHandle< MuonEDMPrinterToolm_printer
 tool to print out EDM objects
ToolHandle< IMuonTrackToSegmentToolm_trackToSegmentTool
 helper tool to convert tracks into segments
ToolHandle< IMuonHitSelectorm_phiHitSelector
 tool to clean phi hits
ToolHandle< IMuonTrackCleanerm_cleaner {this, "TrackCleaner", "Muon::MuonTrackCleaner/MuonTrackCleaner"}
ToolHandle< IMuonSegmentInOverlapResolvingToolm_overlapResolver
ToolHandle< Trk::ITrackSummaryHelperToolm_trackSummaryTool
Gaudi::Property< bool > m_slFit {this, "SLFit", true, "Perform sl fit"}
Gaudi::Property< bool > m_slProp {this, "SLProp", false, "Enable straight line propagation"}
Gaudi::Property< bool > m_seedWithSegmentTheta {this, "SeedWithSegmentTheta", true, "Seed with theta connecting first + last eta hit"}
Gaudi::Property< bool > m_seedWithAvePhi {this, "SeedWithAvePhi", true, "Seed with average phi of all phi hits"}
Gaudi::Property< bool > m_seedPhiWithEtaHits {this, "SeedPhiWithEtaHits", false, "Seed phi from positions first last eta hit"}
Gaudi::Property< bool > m_usePreciseHits {this, "UsePreciseHits", false, "Use actual measurement error"}
Gaudi::Property< bool > m_usePrefit {this, "UsePrefit", true, "Use prefit"}
Gaudi::Property< bool > m_allowFirstFit {this, "AllowFirstFitResult", false, "Return the result of the prefit is final fit fails"}
Gaudi::Property< double > m_pThreshold
Gaudi::Property< bool > m_cosmics {this, "Cosmics", false, "Special treatment for cosmics"}
Gaudi::Property< bool > m_cleanPhiHits {this, "CleanPhiHits", true, "Special flag to switch off phi hit cleaning"}
Gaudi::Property< unsigned int > m_phiHitsMax
Gaudi::Property< bool > m_seedAtStartOfTrack {this, "SeedAtStartOfTrack", true, "Provide seed parameters at the start of the track"}
Gaudi::Property< bool > m_preciseFirstStation
Gaudi::Property< double > m_openingAngleCut
Gaudi::Property< double > m_preCleanChi2Cut
Gaudi::Property< double > m_chi2Cut {this, "ReducedChi2Cut", 100., "minimum chi2/ndof for a track to be accepted"}
std::atomic_uint m_nfits {0}
std::atomic_uint m_nfailedExtractInital {0}
std::atomic_uint m_nfailedMinMaxPhi {0}
std::atomic_uint m_nfailedParsInital {0}
std::atomic_uint m_nfailedExtractCleaning {0}
std::atomic_uint m_nfailedFakeInitial {0}
std::atomic_uint m_nfailedTubeFit {0}
std::atomic_uint m_noPerigee {0}
std::atomic_uint m_nlowMomentum {0}
std::atomic_uint m_nfailedExtractPrecise {0}
std::atomic_uint m_nfailedFakePrecise {0}
std::atomic_uint m_nfailedFitPrecise {0}
std::atomic_uint m_nsuccess {0}
StoreGateSvc_t m_evtStore
 Pointer to StoreGate (event store by default)
StoreGateSvc_t m_detStore
 Pointer to StoreGate (detector store by default)
std::vector< SG::VarHandleKeyArray * > m_vhka
bool m_varHandleArraysDeclared

Detailed Description

Tool to fit a trajectory using a set of two segments or a track and a segment as input.

The tool can be configured to fit either a straight line or all 5 parameters of the track.

For more details look at the mainpage of this package.

Definition at line 59 of file MooTrackFitter.h.

Member Typedef Documentation

◆ MaterialLayers

typedef std::vector<std::pair<const Trk::TrackParameters*, const Trk::Layer*> > Muon::MooTrackFitter::MaterialLayers

Definition at line 72 of file MooTrackFitter.h.

◆ MeasCit

typedef MeasVec::const_iterator Muon::MooTrackFitter::MeasCit

Definition at line 63 of file MooTrackFitter.h.

◆ MeasIt

typedef MeasVec::iterator Muon::MooTrackFitter::MeasIt

Definition at line 62 of file MooTrackFitter.h.

◆ MeasVec

Definition at line 61 of file MooTrackFitter.h.

◆ PrepCit

typedef PrepVec::const_iterator Muon::MooTrackFitter::PrepCit

Definition at line 67 of file MooTrackFitter.h.

◆ PrepIt

typedef PrepVec::iterator Muon::MooTrackFitter::PrepIt

Definition at line 66 of file MooTrackFitter.h.

◆ PrepVec

typedef std::vector<const Trk::PrepRawData*> Muon::MooTrackFitter::PrepVec

Definition at line 65 of file MooTrackFitter.h.

◆ SLStationMap

◆ SmallLargeChambers

typedef std::pair<int, int> Muon::MooTrackFitter::SmallLargeChambers

Definition at line 69 of file MooTrackFitter.h.

◆ StoreGateSvc_t

typedef ServiceHandle<StoreGateSvc> AthCommonDataStore< AthCommonMsg< AlgTool > >::StoreGateSvc_t
privateinherited

Definition at line 388 of file AthCommonDataStore.h.

Constructor & Destructor Documentation

◆ MooTrackFitter()

Muon::MooTrackFitter::MooTrackFitter ( const std::string & t,
const std::string & n,
const IInterface * p )

default AlgTool constructor

Definition at line 53 of file MooTrackFitter.cxx.

53 : AthAlgTool(t, n, p) {
54 declareInterface<MooTrackFitter>(this);
55 }
AthAlgTool()
Default constructor:

◆ ~MooTrackFitter()

Muon::MooTrackFitter::~MooTrackFitter ( )
default

destructor

Member Function Documentation

◆ addFakePhiHits()

bool Muon::MooTrackFitter::addFakePhiHits ( const EventContext & ctx,
MooTrackFitter::FitterData & fitterData,
const Trk::TrackParameters & referenceParameter ) const
private

check fitterData, add fake phi hits if needed.

If provided the reference parameter will be used to calcualte the fake hits

A small hack putting James last onto the actual stage and not let him fall into the orchestra pit...

Definition at line 513 of file MooTrackFitter.cxx.

513 {
514
515 // check whether we have enough phi constraints
516 unsigned nphiConstraints = hasPhiConstrain(fitterData);
517
518 // do we have enough constraints to fit the track
519 if (nphiConstraints >= 2) {
520 if (fitterData.firstEntry->stations().size() == 1 && fitterData.firstEntry->containsStation(StIndex::EI) &&
521 (fitterData.firstEntry->phiHits().empty() || (fitterData.firstEntry->containsChamber(ChIndex::CSS) ||
522 fitterData.firstEntry->containsChamber(ChIndex::CSL)))) {
523 ATH_MSG_VERBOSE( " Special treatment of the forward region: adding fake at ip ");
524 }
525 return true;
526 }
527
528 // in case of a single station overlap fit, calculate a global position that is more or less located at
529 // the overlap. It is used to decide on which side of the tube the fake should be produced
530 std::unique_ptr<Amg::Vector3D> overlapPos;
531 std::unique_ptr<const Amg::Vector3D> phiPos;
532 if (fitterData.numberOfSLOverlaps() > 0 || (fitterData.numberOfSmallChambers() > 0 && fitterData.numberOfLargeChambers() > 0)) {
533 // in case of SL overlaps, pass average position of the two segments
534 // overlapPos = new Amg::Vector3D( 0.5*(fitterData.firstEntry->etaHits().front()->globalPosition() +
535 // fitterData.secondEntry->etaHits().front()->globalPosition()) );
536 overlapPos = std::make_unique<Amg::Vector3D>(1., 1., 1.);
537 double phi = fitterData.avePhi;
538 double theta = fitterData.secondEntry->etaHits().front()->globalPosition().theta();
539 if (m_cosmics) {
540 if (fitterData.firstEntry->hasSLOverlap()) {
541 theta = fitterData.firstEntry->entryPars().momentum().theta();
542 phi = fitterData.firstEntry->entryPars().momentum().phi();
543 } else {
544 theta = fitterData.secondEntry->entryPars().momentum().theta();
545 phi = fitterData.secondEntry->entryPars().momentum().phi();
546 }
547 }
548 Amg::setThetaPhi(*overlapPos, theta, phi);
549
550 if (fitterData.startPars) {
551 phiPos = std::make_unique<Amg::Vector3D>(fitterData.startPars->momentum());
552 } else {
553 phiPos = std::make_unique<Amg::Vector3D>(*overlapPos);
554 }
555
556 if (msgLvl(MSG::VERBOSE)) {
557 if (fitterData.numberOfSLOverlaps() > 0) {
558 if (fitterData.stations.size() == 1)
559 msg(MSG::VERBOSE) << " one station fit with SL overlap, using overlapPos " << *overlapPos << endmsg;
560 else
561 msg(MSG::VERBOSE) << " multi station fit with SL overlap, using overlapPos " << *overlapPos << endmsg;
562 } else if (fitterData.numberOfSmallChambers() > 0 && fitterData.numberOfLargeChambers() > 0) {
563 msg(MSG::VERBOSE) << " multi station fit, SL overlap not in same station, using overlapPos " << *overlapPos << endmsg;
564 } else
565 ATH_MSG_WARNING(" Unknown overlap type ");
566 }
567 }
568 // add fake phi hit on first and last measurement
569 if (fitterData.phiHits.empty()) {
570 const MuPatSegment* segInfo1 = dynamic_cast<const MuPatSegment*>(fitterData.firstEntry);
571 const MuPatSegment* segInfo2 = dynamic_cast<const MuPatSegment*>(fitterData.secondEntry);
572 if (segInfo1 && segInfo2 && fitterData.stations.size() == 1 && fitterData.numberOfSLOverlaps() == 1) {
573 // only perform SL overlap fit for MDT segments
574 Identifier chId = m_edmHelperSvc->chamberId(*segInfo1->segment);
575 if (!m_idHelperSvc->isMdt(chId)) return false;
576
577 ATH_MSG_VERBOSE(" Special treatment for tracks with one station, a SL overlap and no phi hits ");
578
579 IMuonSegmentInOverlapResolvingTool::SegmentMatchResult result =
580 m_overlapResolver->matchResult(ctx, *segInfo1->segment, *segInfo2->segment);
581
582 if (!result.goodMatch()) {
583 ATH_MSG_VERBOSE(" Match failed ");
584 return false;
585 }
586 // create a track parameter for the segment
587 double locx1 = result.segmentResult1.positionInTube1;
588 double locy1 =
589 segInfo1->segment->localParameters().contains(Trk::locY) ? segInfo1->segment->localParameters()[Trk::locY] : 0.;
590 Trk::AtaPlane segPars1(locx1, locy1, result.phiResult.segmentDirection1.phi(), result.phiResult.segmentDirection1.theta(),
591 0., segInfo1->segment->associatedSurface());
592 // ownership retained, original code deleted exPars1
593 std::unique_ptr<Trk::TrackParameters> exPars1 = m_propagator->propagate(ctx,
594 segPars1, fitterData.measurements.front()->associatedSurface(), Trk::anyDirection,
595 false, m_magFieldProperties);
596 if (exPars1) {
597 Amg::Vector3D position = exPars1->position();
598 std::unique_ptr<Trk::MeasurementBase> fake =
599 createFakePhiForMeasurement(*fitterData.measurements.front(), &position, nullptr, 10.);
600 if (fake) {
601 fitterData.phiHits.push_back(fake.get());
602 fitterData.measurements.insert(fitterData.measurements.begin(), fake.get());
603 fitterData.firstLastMeasurements.insert(fitterData.firstLastMeasurements.begin(), fake.get());
604 fitterData.garbage.push_back(std::move(fake));
605 }
606 } else {
607 ATH_MSG_WARNING(" failed to create fake for first segment ");
608 return false;
609 }
610 double locx2 = result.segmentResult2.positionInTube1;
611 double locy2 =
612 segInfo2->segment->localParameters().contains(Trk::locY) ? segInfo2->segment->localParameters()[Trk::locY] : 0.;
613 Trk::AtaPlane segPars2(locx2, locy2, result.phiResult.segmentDirection2.phi(), result.phiResult.segmentDirection2.theta(),
614 0., segInfo2->segment->associatedSurface());
615 // ownership retained
616 auto exPars2 = m_propagator->propagate(ctx,
617 segPars2, fitterData.measurements.back()->associatedSurface(), Trk::anyDirection,
618 false, m_magFieldProperties);
619 if (exPars2) {
620 Amg::Vector3D position = exPars2->position();
621 std::unique_ptr<Trk::MeasurementBase> fake =
622 createFakePhiForMeasurement(*fitterData.measurements.back(), &position, nullptr, 10.);
623 if (fake) {
624 fitterData.phiHits.push_back(fake.get());
625 fitterData.measurements.push_back(fake.get());
626 fitterData.firstLastMeasurements.push_back(fake.get());
627 fitterData.garbage.push_back(std::move(fake));
628 }
629 } else {
630 ATH_MSG_WARNING(" failed to create fake for second segment ");
631 return false;
632 }
633 } else if (nphiConstraints == 0 || (fitterData.stations.size() == 1) ||
634 (nphiConstraints == 1 && fitterData.numberOfSLOverlaps() == 0 && fitterData.numberOfSmallChambers() > 0 &&
635 fitterData.numberOfLargeChambers() > 0)) {
636 {
637 std::unique_ptr<Trk::MeasurementBase> fake = createFakePhiForMeasurement(*fitterData.measurements.front(),
638 overlapPos.get(), phiPos.get(), 100.);
639 if (fake) {
640 fitterData.phiHits.push_back(fake.get());
641 fitterData.measurements.insert(fitterData.measurements.begin(), fake.get());
642 fitterData.firstLastMeasurements.insert(fitterData.firstLastMeasurements.begin(), fake.get());
643 fitterData.garbage.push_back(std::move(fake));
644 }
645
646 }
647 {
648 std::unique_ptr<Trk::MeasurementBase> fake = createFakePhiForMeasurement(*fitterData.measurements.back(),
649 overlapPos.get(), phiPos.get(), 100.);
650 if (fake) {
651 fitterData.phiHits.push_back(fake.get());
652 fitterData.measurements.push_back(fake.get());
653 fitterData.firstLastMeasurements.push_back(fake.get());
654 fitterData.garbage.push_back(std::move(fake));
655 }
656 }
657
658 } else if (fitterData.numberOfSLOverlaps() == 1) {
659 // there is one overlap, add the fake in the station without the overlap
660 ATH_MSG_VERBOSE(" Special treatment for tracks with one SL overlap and no phi hits ");
661
662 StIndex overlapStation = StIndex::StUnknown;
663 SLStationMap::iterator it = fitterData.smallLargeChambersPerStation.begin();
664 SLStationMap::iterator it_end = fitterData.smallLargeChambersPerStation.end();
665 for (; it != it_end; ++it) {
666 if (it->second.first && it->second.second) {
667 overlapStation = it->first;
668 break;
669 }
670 }
671 if (overlapStation == StIndex::StUnknown) {
672 ATH_MSG_WARNING(" unexpected condition, unknown station type ");
673 return false;
674 }
675
676 Identifier firstId = m_edmHelperSvc->getIdentifier(*fitterData.measurements.front());
677 if (!firstId.is_valid()) {
678 ATH_MSG_WARNING(" unexpected condition, first measurement has no identifier ");
679 return false;
680 }
681 MuonStationIndex::StIndex firstSt = m_idHelperSvc->stationIndex(firstId);
682 if (overlapStation == firstSt) {
683 ATH_MSG_VERBOSE(" Adding fake in same station as overlap ");
684
685 // create pseudo at end of track
686 std::unique_ptr<Trk::MeasurementBase> fake = createFakePhiForMeasurement(*fitterData.measurements.back(),
687 overlapPos.get(), phiPos.get(), 100.);
688 if (fake) {
689 fitterData.phiHits.push_back(fake.get());
690 fitterData.measurements.push_back(fake.get());
691 fitterData.firstLastMeasurements.push_back(fake.get());
692 fitterData.garbage.push_back(std::move(fake));
693 }
694 } else {
695 ATH_MSG_VERBOSE(" Adding fake in other station as overlap ");
696 // create pseudo at begin of track
697 std::unique_ptr<Trk::MeasurementBase> fake = createFakePhiForMeasurement(*fitterData.measurements.front(),
698 overlapPos.get(), phiPos.get(), 100.);
699 if (fake) {
700 fitterData.phiHits.push_back(fake.get());
701 fitterData.measurements.insert(fitterData.measurements.begin(), fake.get());
702 fitterData.firstLastMeasurements.insert(fitterData.firstLastMeasurements.begin(), fake.get());
703 fitterData.garbage.push_back(std::move(fake));
704 }
705 }
706
707 } else {
708 ATH_MSG_WARNING(" unexpected condition, cannot create fakes ");
709 return false;
710 }
711 } else {
712 // calculate distance between first phi/eta hit and last phi/eta hit
713 double distFirstEtaPhi =
714 (fitterData.measurements.front()->globalPosition() - fitterData.phiHits.front()->globalPosition()).mag();
715 double distLastEtaPhi = (fitterData.measurements.back()->globalPosition() - fitterData.phiHits.back()->globalPosition()).mag();
716
717 // if there is one phi, use its phi + IP constraint to calculate position of fake
718 if (!overlapPos && m_seedWithAvePhi) {
719 phiPos = std::make_unique<Amg::Vector3D>(fitterData.phiHits.back()->globalPosition());
720 ATH_MSG_VERBOSE(" using pointing constraint to calculate fake phi hit ");
721 }
722
723 // create a fake on the first and/or last MDT measurement if not near phi hits
724 const Trk::Surface *firstmdtsurf = nullptr, *lastmdtsurf = nullptr;
725 const Trk::TrackParameters *lastmdtpar = nullptr;
726 int indexfirst = 0, indexlast = (int)fitterData.measurements.size();
727 MuPatHitCit hitit = fitterData.hitList.begin();
728 for (; hitit != fitterData.hitList.end(); hitit++) {
729 if ((**hitit).info().measuresPhi) break;
730 if ((**hitit).info().type == MuPatHit::MDT || (**hitit).info().type == MuPatHit::sTGC) {
731 firstmdtsurf = &(**hitit).measurement().associatedSurface();
732 break;
733 }
734 indexfirst++;
735 }
736 hitit = fitterData.hitList.end();
737 hitit--;
738 for (; hitit != fitterData.hitList.begin(); hitit--) {
739 if ((**hitit).info().measuresPhi) break;
740 if ((**hitit).info().type == MuPatHit::MDT) {
741 lastmdtsurf = &(**hitit).measurement().associatedSurface();
742 lastmdtpar = &(**hitit).parameters();
743 break;
744 }
745 indexlast--;
746 }
749 indexlast = std::max(indexlast, 0);
750 bool phifromextrapolation = false;
751 if (!fitterData.secondEntry->phiHits().empty() || !fitterData.firstEntry->phiHits().empty()) phifromextrapolation = true;
752
753 const Trk::Surface *firstphisurf = nullptr, *lastphisurf = nullptr;
754 Amg::Vector3D firstphinormal{Amg::Vector3D::Zero()}, lastphinormal{Amg::Vector3D::Zero()};
755 if (!fitterData.phiHits.empty()) {
756 firstphisurf = &fitterData.phiHits.front()->associatedSurface();
757 lastphisurf = &fitterData.phiHits.back()->associatedSurface();
758 firstphinormal = firstphisurf->normal();
759 lastphinormal = lastphisurf->normal();
760 if (firstphinormal.dot(startpar.momentum()) < 0) firstphinormal = -firstphinormal;
761 if (lastphinormal.dot(startpar.momentum()) < 0) lastphinormal = -lastphinormal;
762 }
763 if (lastmdtsurf && (!firstphisurf || (lastmdtsurf->center() - lastphisurf->center()).dot(lastphinormal) > 1000)) {
764 ATH_MSG_VERBOSE(" Adding fake at last hit: dist first phi/first eta " << distFirstEtaPhi << " dist last phi/last eta "
765 << distLastEtaPhi);
766 std::unique_ptr<Trk::MeasurementBase> fake{};
767 if (fitterData.secondEntry->hasSLOverlap() || phifromextrapolation) {
768 // this scope manages lifetime of mdtpar
769 std::unique_ptr<Trk::TrackParameters> mdtpar{};
770 if (fitterData.secondEntry->hasSLOverlap()){
771 mdtpar = lastmdtpar->uniqueClone();
772 } else {
773 mdtpar = m_propagator->propagateParameters(ctx, startpar, *lastmdtsurf,
775 }
776 if (mdtpar) {
777 Amg::MatrixX cov(1, 1);
778 cov(0, 0) = 100.;
779 fake = std::make_unique<Trk::PseudoMeasurementOnTrack>(
780 Trk::LocalParameters(Trk::DefinedParameter(mdtpar->parameters()[Trk::locY], Trk::locY)),
781 std::move(cov),
782 mdtpar->associatedSurface());
783
784 }
785 } else {
786 fake = createFakePhiForMeasurement(*fitterData.measurements.back(), overlapPos.get(), phiPos.get(), 10.);
787 }
788 if (fake) {
789 fitterData.phiHits.push_back(fake.get());
790 fitterData.measurements.insert(fitterData.measurements.begin() + indexlast, fake.get());
791 fitterData.firstLastMeasurements.push_back(fake.get());
792 fitterData.garbage.push_back(std::move(fake));
793 }
794 }
795
796 if (firstmdtsurf && (!firstphisurf || (firstmdtsurf->center() - firstphisurf->center()).dot(firstphinormal) < -1000)) {
797 ATH_MSG_VERBOSE(" Adding fake at first hit: dist first phi/first eta " << distFirstEtaPhi << " dist last phi/last eta "
798 << distLastEtaPhi);
799 std::unique_ptr<Trk::MeasurementBase> fake{};
800 if (phifromextrapolation) {
801 // lifetime of mdtpar managed here
802 auto mdtpar = m_propagator->propagateParameters(ctx, startpar,
803 *firstmdtsurf, Trk::oppositeMomentum, false, m_magFieldProperties);
804 if (mdtpar) {
805 Amg::MatrixX cov(1, 1);
806 cov(0, 0) = 100.;
807 fake = std::make_unique<Trk::PseudoMeasurementOnTrack>(
808 Trk::LocalParameters(Trk::DefinedParameter(mdtpar->parameters()[Trk::locY], Trk::locY)),
809 std::move(cov),
810 mdtpar->associatedSurface());
811 }
812 } else{
813 fake = createFakePhiForMeasurement(*fitterData.measurements.front(), overlapPos.get(), phiPos.get(), 100.);
814 }
815 if (fake) {
816 fitterData.phiHits.insert(fitterData.phiHits.begin(), fake.get());
817 fitterData.measurements.insert(fitterData.measurements.begin() + indexfirst, fake.get());
818 fitterData.firstLastMeasurements.insert(fitterData.firstLastMeasurements.begin(), fake.get());
819 fitterData.garbage.push_back(std::move(fake));
820 }
821 }
822 }
823 return true;
824 }
Scalar phi() const
phi method
Scalar theta() const
theta method
#define endmsg
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
bool msgLvl(const MSG::Level lvl) const
MsgStream & msg() const
bool is_valid() const
Check if id is in a valid state.
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Trk::MagneticFieldProperties m_magFieldProperties
magnetic field properties
ToolHandle< IMuonSegmentInOverlapResolvingTool > m_overlapResolver
std::unique_ptr< Trk::MeasurementBase > createFakePhiForMeasurement(const Trk::MeasurementBase &measurement, const Amg::Vector3D *overlapPos, const Amg::Vector3D *phiPos, double error) const
create fake phi hit on the surface of the give measurement
Gaudi::Property< bool > m_seedWithAvePhi
Gaudi::Property< bool > m_cosmics
ServiceHandle< IMuonEDMHelperSvc > m_edmHelperSvc
multi purpose helper tool
unsigned int hasPhiConstrain(FitterData &inputData) const
check whether data has sufficient phi constraints
ToolHandle< Trk::IPropagator > m_propagator
propagator
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...
virtual const Amg::Vector3D & normal() const
Returns the normal vector of the Surface (i.e.
const Amg::Vector3D & center() const
Returns the center position of the Surface.
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Eigen::Matrix< double, 3, 1 > Vector3D
void setThetaPhi(Amg::Vector3D &v, double theta, double phi)
sets the theta and phi angle of a vector without changing the magnitude
StIndex
enum to classify the different station layers in the muon spectrometer
MuPatHitList::const_iterator MuPatHitCit
Definition MuPatHit.h:27
@ oppositeMomentum
@ alongMomentum
@ anyDirection
@ locY
local cartesian
Definition ParamDefs.h:38
std::pair< double, ParamDefs > DefinedParameter
Typedef to of a std::pair<double, ParamDefs> to identify a passed-through double as a specific type o...
ParametersBase< TrackParametersDim, Charged > TrackParameters
ParametersT< TrackParametersDim, Charged, PlaneSurface > AtaPlane

◆ cleanAndEvaluateTrack()

std::unique_ptr< Trk::Track > Muon::MooTrackFitter::cleanAndEvaluateTrack ( const EventContext & ctx,
Trk::Track & track,
const std::set< Identifier > & excludedChambers ) const
private

clean and evaluate the track,

Returns
0 if Track does not forfill criteria, a unique_ptr otherwise (could be to a track which is the same as the current)

Definition at line 1840 of file MooTrackFitter.cxx.

1841 {
1842 // preselection to get ride of really bad tracks
1843 if (!m_edmHelperSvc->goodTrack(track, m_preCleanChi2Cut)) {
1844 ATH_MSG_DEBUG(" Track rejected due to large chi2" << std::endl << m_printer->print(track));
1845 return nullptr;
1846 }
1847
1848 // perform cleaning of track
1849 std::unique_ptr<Trk::Track> cleanTrack;
1850 if (excludedChambers.empty())
1851 cleanTrack = m_cleaner->clean(track, ctx);
1852 else {
1853 ATH_MSG_DEBUG(" Cleaning with exclusion list " << excludedChambers.size());
1854 cleanTrack = m_cleaner->clean(track, excludedChambers, ctx);
1855 }
1856 if (!cleanTrack) {
1857 ATH_MSG_DEBUG(" Cleaner returned a zero pointer, reject track ");
1858 return nullptr;
1859 }
1860
1861 // selection to get ride of bad tracks after cleaning
1862 if (!m_edmHelperSvc->goodTrack(*cleanTrack, m_chi2Cut)) {
1863 ATH_MSG_DEBUG(" Track rejected after cleaning " << std::endl << m_printer->print(*cleanTrack));
1864 return nullptr;
1865 }
1866
1867 ATH_MSG_DEBUG(" Track passed selection after cleaning! ");
1868 return cleanTrack;
1869 }
#define ATH_MSG_DEBUG(x)
Gaudi::Property< double > m_chi2Cut
ToolHandle< IMuonTrackCleaner > m_cleaner
Gaudi::Property< double > m_preCleanChi2Cut
PublicToolHandle< MuonEDMPrinterTool > m_printer
tool to print out EDM objects

◆ cleanEntry()

void Muon::MooTrackFitter::cleanEntry ( const MuPatCandidateBase & entry,
std::set< Identifier > & removedIdentifiers ) const
private

Definition at line 1880 of file MooTrackFitter.cxx.

1880 {
1881 // if segment entry use segment directly
1882 const MuPatSegment* segEntry = dynamic_cast<const MuPatSegment*>(&entry);
1883 if (segEntry && segEntry->segment) {
1884 if (entry.hasSmallChamber() && entry.hasLargeChamber()) {
1885 ATH_MSG_DEBUG(" Segment with SL overlap, cannot perform cleaning ");
1886 } else {
1887 cleanSegment(*segEntry->segment, removedIdentifiers);
1888 }
1889 }
1890 }
void cleanSegment(const MuonSegment &seg, std::set< Identifier > &removedIdentifiers) const

◆ cleanPhiHits()

bool Muon::MooTrackFitter::cleanPhiHits ( const EventContext & ctx,
double momentum,
FitterData & phiHits,
const PrepVec & patternPhiHits ) const
private

clean phi hits, returns true if anything happened during the cleaning

do not add CSCs as they really should be on a segment

Definition at line 1687 of file MooTrackFitter.cxx.

1688 {
1689 ATH_MSG_VERBOSE(" cleaning phi hits ");
1690
1691 MeasVec& phiHits = fitterData.phiHits;
1692
1693 // copy phi ROTs into vector, split up competing ROTs
1694 std::vector<const Trk::RIO_OnTrack*> rots;
1695 std::vector<std::unique_ptr<const Trk::RIO_OnTrack>> rotsNSW; // hack as the phi hit cleaning does not work for NSW hits
1696 std::set<Identifier> ids;
1697 std::set<MuonStationIndex::StIndex> stations;
1698 rots.reserve(phiHits.size() + 5);
1699
1700 for (const Trk::MeasurementBase* hit : phiHits) {
1701 const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(hit);
1702 if (rot) {
1703 if (m_idHelperSvc->issTgc(rot->identify())) {
1704 rotsNSW.push_back(rot->uniqueClone());
1705 continue;
1706 }
1707 rots.push_back(rot);
1708 ids.insert(rot->identify());
1709 continue;
1710 }
1711 const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(hit);
1712 if (crot) {
1713 for (const MuonClusterOnTrack* mit : crot->containedROTs()) {
1714 rots.push_back(mit);
1715 ids.insert(mit->identify());
1716 MuonStationIndex::StIndex stIndex = m_idHelperSvc->stationIndex(mit->identify());
1717 stations.insert(stIndex);
1718 }
1719 } else {
1720 ATH_MSG_WARNING(" phi hits should be ROTs or competing ROTs! Dropping hit ");
1721 }
1722 }
1723
1724 if (rots.empty()) return false;
1725
1726 if (rots.size() > m_phiHitsMax) {
1727 ATH_MSG_DEBUG(" too many phi hits, not running cleaning " << rots.size());
1728 return true;
1729 }
1730
1731 if (msgLvl(MSG::VERBOSE)) {
1732 msg(MSG::VERBOSE) << " contained phi hits ";
1733 for (const Trk::RIO_OnTrack* rit : rots) { msg(MSG::DEBUG) << std::endl << " " << m_printer->print(*rit); }
1734 msg(MSG::DEBUG) << endmsg;
1735 }
1736
1737 // if available, extract additional phi hits from the road that were not on the entries
1738 std::vector<const Trk::PrepRawData*> roadPhiHits;
1739 std::copy_if(patternPhiHits.begin(), patternPhiHits.end(), std::back_inserter(roadPhiHits), [&ids, this](const Trk::PrepRawData* prd){
1740 return !(ids.count(prd->identify()) ||
1742 m_idHelperSvc->isCsc(prd->identify()) || m_idHelperSvc->issTgc(prd->identify()));
1743 });
1744
1745
1746 if (roadPhiHits.size() + rots.size() > m_phiHitsMax) {
1747 ATH_MSG_VERBOSE(" too many pattern phi hits, not adding any " << roadPhiHits.size());
1748 roadPhiHits.clear(); // cleaning road hits as we do not want to add them but we do want to clean
1749 }
1750 if (msgLvl(MSG::VERBOSE)) {
1751 if (!roadPhiHits.empty()) {
1752 msg(MSG::VERBOSE) << " additional pattern phi hits " << std::endl;
1753 std::vector<const Trk::PrepRawData*>::const_iterator pit = roadPhiHits.begin();
1754 std::vector<const Trk::PrepRawData*>::const_iterator pit_end = roadPhiHits.end();
1755 for (; pit != pit_end; ++pit) {
1756 msg(MSG::DEBUG) << " " << m_printer->print(**pit);
1757 if (pit + 1 != pit_end)
1758 msg(MSG::DEBUG) << std::endl;
1759 else
1760 msg(MSG::DEBUG) << endmsg;
1761 }
1762 }
1763 }
1764
1765 std::vector<std::unique_ptr<const Trk::MeasurementBase>> newMeasurements{m_phiHitSelector->select_rio(momentum, rots, roadPhiHits)};
1766
1767 newMeasurements.insert(newMeasurements.end(),
1768 std::make_move_iterator(rotsNSW.begin()),
1769 std::make_move_iterator(rotsNSW.end()));
1770
1771 ATH_MSG_VERBOSE(" selected phi hits " << newMeasurements.size());
1772
1773 if (newMeasurements.empty()) {
1774 ATH_MSG_DEBUG(" empty list of phi hits return from phi hit selector: input size " << phiHits.size());
1775 return false;
1776 }
1777
1778 // require the new hits to be within a certain distance of the hits already on the track candidate
1779 DistanceAlongParameters distAlongPars;
1780 constexpr double maxDistCut = 800.;
1781 std::vector<const Trk::MeasurementBase*> measurementsToBeAdded{};
1782 measurementsToBeAdded.reserve(newMeasurements.size());
1783 for (std::unique_ptr<const Trk::MeasurementBase>& meas : newMeasurements) {
1784 const Identifier id = m_edmHelperSvc->getIdentifier(*meas);
1785 if (!id.is_valid()) {
1786 ATH_MSG_WARNING(" Phi measurement without valid Identifier! ");
1787 continue;
1788 }
1789 ATH_MSG_VERBOSE(" Test phi hit - " << m_printer->print(*meas));
1790 // only add hits if the hitList is not empty so we can calculate the distance of the new hit to the first and last hit on the
1791 // track
1792 if (fitterData.hitList.empty()) {
1793 ATH_MSG_VERBOSE(" discarding phi hit due to empty hitList ");
1794 break;
1795 }
1796
1797 // calculate the distance of the phi hit to the first hit. If the phi hit lies before the first hit,
1798 // remove the hit if the distance is too large
1799 double dist = distAlongPars(fitterData.hitList.front()->parameters(), *meas);
1800 if (dist < -maxDistCut) {
1801 ATH_MSG_VERBOSE(" discarded phi hit, distance to first hit too large " << dist);
1802 continue;
1803 }
1804
1805 // calculate the distance of the phi hit to the last hit. If the phi hit lies after the last hit,
1806 // remove the hit if the distance is too large
1807 double distBack = distAlongPars(fitterData.hitList.back()->parameters(), *meas);
1808 if (distBack > maxDistCut) {
1809 ATH_MSG_VERBOSE(" discarded phi hit, distance to last hit too large " << distBack);
1810 continue;
1811 }
1812
1813 ATH_MSG_VERBOSE(" new phi hit, distance from start pars " << dist << " distance to last pars " << distBack);
1814
1815 measurementsToBeAdded.push_back(meas.get());
1816 fitterData.garbage.push_back(std::move(meas));
1817 }
1818
1819 // now remove all previous phi hits and replace them with the new ones
1820
1821 for (const Trk::MeasurementBase* hit : phiHits) {
1822 ATH_MSG_VERBOSE(" Remove phi measurement " << m_printer->print(*hit));
1823 m_hitHandler->remove(*hit, fitterData.hitList);
1824
1825 }
1826
1827 // add the new phi hits to the hit list
1828 if (!measurementsToBeAdded.empty()) {
1829 ATH_MSG_VERBOSE(" adding measurements "<<std::endl<<m_printer->print(measurementsToBeAdded));
1830 MuPatHitList newHitList;
1831 m_hitHandler->create(ctx, fitterData.firstEntry->entryPars(), measurementsToBeAdded, newHitList);
1832 fitterData.hitList = m_hitHandler->merge(newHitList, fitterData.hitList);
1833 }
1834
1835 ATH_MSG_VERBOSE(" done cleaning ");
1836
1837 return true;
1838 }
Gaudi::Property< unsigned int > m_phiHitsMax
ToolHandle< IMuonHitSelector > m_phiHitSelector
tool to clean phi hits
std::vector< const Trk::MeasurementBase * > MeasVec
PublicToolHandle< MuPatHitTool > m_hitHandler
hit handler
Identifier identify() const
return the identifier -extends MeasurementBase
std::unique_ptr< RIO_OnTrack > uniqueClone() const
NVI clone returning unique_ptr.
Definition RIO_OnTrack.h:97
std::vector< MuPatHitPtr > MuPatHitList
Definition MuPatHit.h:26

◆ cleanSegment()

void Muon::MooTrackFitter::cleanSegment ( const MuonSegment & seg,
std::set< Identifier > & removedIdentifiers ) const
private

Definition at line 1892 of file MooTrackFitter.cxx.

1892 {
1894 /* ******** Mdt hits ******** */
1895
1896 const MuonGM::MdtReadoutElement* detEl = nullptr;
1897
1898 Amg::Transform3D gToStation{Amg::Transform3D::Identity()};
1899
1900
1901 float tubeRadius = 14.6;
1902
1903 ATH_MSG_DEBUG("loop through hits for segment");
1904 for ( const Trk::MeasurementBase* meas : seg.containedMeasurements()) {
1905 const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(meas);
1906
1907 if (!mdt) { continue; }
1908 Identifier id = mdt->identify();
1909 if (!detEl) {
1910 detEl = mdt->prepRawData()->detectorElement();
1911 gToStation = detEl->GlobalToAmdbLRSTransform();
1912 }
1913 if (!detEl) {
1914 ATH_MSG_WARNING(" error aborting not detEl found ");
1915 break;
1916 }
1917
1918 ATH_MSG_DEBUG("detector element of station type " << detEl->getStationType());
1919 tubeRadius = detEl->innerTubeRadius();
1920
1921 // calculate local AMDB position
1922 Amg::Vector3D LocVec2D = gToStation * mdt->prepRawData()->globalPosition();
1923 TrkDriftCircleMath::LocVec2D lpos(LocVec2D.y(), LocVec2D.z());
1924
1925 double r = mdt->localParameters()[Trk::locR];
1926 double dr = Amg::error(mdt->localCovariance(), Trk::locR);
1927
1928 // create identifier
1929 TrkDriftCircleMath::MdtId mdtid(m_idHelperSvc->mdtIdHelper().isBarrel(id), m_idHelperSvc->mdtIdHelper().multilayer(id) - 1,
1930 m_idHelperSvc->mdtIdHelper().tubeLayer(id) - 1, m_idHelperSvc->mdtIdHelper().tube(id) - 1);
1931
1932 // create new DriftCircle
1933 TrkDriftCircleMath::DriftCircle dc(lpos, r, dr, TrkDriftCircleMath::DriftCircle::InTime, mdtid, mdt);
1934 TrkDriftCircleMath::DCOnTrack dcOnTrack(dc, 1., 1.);
1935 ATH_MSG_VERBOSE(" new MDT hit " << m_idHelperSvc->toString(id));
1936
1937 dcs.push_back(dcOnTrack);
1938
1939 }
1940
1941 double angleYZ = seg.localDirection().angleYZ();
1942 const Amg::Vector3D lpos = gToStation * seg.globalPosition();
1943
1944 ATH_MSG_DEBUG(" cleaning segment " << m_printer->print(seg) << std::endl
1945 << " local parameters " << lpos.y() << " " << lpos.z() << " phi " << angleYZ << " with "
1946 << dcs.size() << " hits ");
1947
1948 TrkDriftCircleMath::LocVec2D segPos(lpos.y(), lpos.z());
1949 TrkDriftCircleMath::Line segPars(segPos, angleYZ);
1950
1951 TrkDriftCircleMath::Segment segment(TrkDriftCircleMath::Line(0., 0., 0.), TrkDriftCircleMath::DCOnTrackVec());
1952 TrkDriftCircleMath::DCSLFitter fitter;
1953 fitter.fit(segment, segPars, dcs);
1954 segment.hitsOnTrack(dcs.size());
1955 ATH_MSG_DEBUG(" segment after fit " << segment.chi2() << " ndof " << segment.ndof() << " local parameters " << segment.line().x0()
1956 << " " << segment.line().y0() << " phi " << segment.line().phi());
1957
1958 bool hasDroppedHit = false;
1959 unsigned int dropDepth = 0;
1960 TrkDriftCircleMath::SegmentFinder finder;
1961 bool success = finder.dropHits(segment, hasDroppedHit, dropDepth);
1962 if (!success) {
1963 ATH_MSG_DEBUG(" drop hits failed ");
1964 return;
1965 }
1966
1967 if (dcs.size() == segment.ndof() + 2) {
1968 ATH_MSG_DEBUG(" segment unchanges ");
1969 } else if (dcs.size() != segment.ndof() + 3) {
1970 ATH_MSG_DEBUG(" more than one hit removed, keeping old segment ");
1971 } else {
1972 ATH_MSG_DEBUG(" removed single hit, not using it in fit ");
1973
1974 TrkDriftCircleMath::MatchDCWithLine matchDC(segment.line(), 5., TrkDriftCircleMath::MatchDCWithLine::Pull, tubeRadius);
1975 const TrkDriftCircleMath::DCOnTrackVec& matchedDCs = matchDC.match(segment.dcs());
1976
1977 for (const TrkDriftCircleMath::DCOnTrack& dcit: matchedDCs) {
1978 if (dcit.state() == TrkDriftCircleMath::DCOnTrack::OnTrack) continue;
1979 removedIdentifiers.insert(dcit.rot()->identify());
1980 ATH_MSG_VERBOSE("Removing hit "<<m_idHelperSvc->toString(dcit.rot()->identify()));
1981 }
1982 }
1983 }
bool fit(const LArSamples::AbsShape &data, const AbsShape &reference, double &k, double &deltaT, double &chi2, const ScaledErrorData *sed=0) const
virtual const MdtPrepData * prepRawData() const override final
Returns the PrepRawData used to create this corrected measurement.
double innerTubeRadius() const
Returns the inner tube radius excluding the aluminium walls.
virtual const Amg::Vector3D & globalPosition() const override final
global position
@ InTime
drift time too small to be compatible with drift spectrum
Definition DriftCircle.h:27
double angleYZ() const
access method for angle of local YZ projection
const LocalParameters & localParameters() const
Interface method to get the LocalParameters.
const Amg::MatrixX & localCovariance() const
Interface method to get the localError.
const std::vector< const Trk::MeasurementBase * > & containedMeasurements() const
returns the vector of Trk::MeasurementBase objects
int r
Definition globals.cxx:22
double error(const Amg::MatrixX &mat, int index)
return diagonal error of the matrix caller should ensure the matrix is symmetric and the index is in ...
Eigen::Affine3d Transform3D
const ShapeFitter * fitter
std::vector< DCOnTrack > DCOnTrackVec
Definition DCOnTrack.h:59
@ locR
Definition ParamDefs.h:44

◆ corruptEntry()

bool Muon::MooTrackFitter::corruptEntry ( const MuPatCandidateBase & entry) const
private

sanity check for entries

Definition at line 107 of file MooTrackFitter.cxx.

107 {
108 if (entry.hits().size() < entry.etaHits().size()) {
109 ATH_MSG_WARNING(" Corrupt Entry: more eta hits than hits! ");
110 return true;
111 }
112 if (entry.etaHits().size() < 3) { return (entry.ncscHitsEta < 2); }
113 return false;
114 }

◆ createFakePhiForMeasurement()

std::unique_ptr< Trk::MeasurementBase > Muon::MooTrackFitter::createFakePhiForMeasurement ( const Trk::MeasurementBase & measurement,
const Amg::Vector3D * overlapPos,
const Amg::Vector3D * phiPos,
double error ) const
private

create fake phi hit on the surface of the give measurement

Definition at line 826 of file MooTrackFitter.cxx.

828 {
829 // check whether measuring phi
830 Identifier id = m_edmHelperSvc->getIdentifier(meas);
831 if (id == Identifier()) {
832 ATH_MSG_WARNING(" Cannot create fake phi hit from a measurement without Identifier ");
833 return nullptr;
834 }
835 // check whether phi measurement, exit if true
836 if (m_idHelperSvc->measuresPhi(id)) {
837 ATH_MSG_WARNING(" Measurement is a phi measurement! " << m_idHelperSvc->toString(id));
838 return nullptr;
839 }
840
841
842 // the MDT and CSC hits are ROTs
843 const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(&meas);
844 if (!rot) {
845 const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(&meas);
846 // if also to a crot we cannot create a fake phi hit
847 if (!crot || crot->containedROTs().empty()) return nullptr;
848 rot = &crot->rioOnTrack(0);
849 }
850
851
852
853 // get channel length and detector element
854 const Trk::TrkDetElementBase* detEl = rot->detectorElement();
855 if (!detEl) {
856 return nullptr;
857 }
858
859 auto [halfLengthL, halfLengthR] = getElementHalfLengths(id, detEl);
860
861 // error
862 std::optional<Amg::Vector2D> lpos = std::nullopt;
863 if (phiPos) {
864 Amg::Vector3D dir(1., 0., 0.);
865 Amg::setThetaPhi(dir, rot->globalPosition().theta(), phiPos->phi());
866 Amg::Vector3D ip{Amg::Vector3D::Zero()};
867 Trk::Perigee perigee(ip, dir, 0., ip);
868
869 // special treatment of MDTs, intersect with detector element surface instead of wire surface to avoid problem with
870 // shift of phi angle after projection into wire frame
871 const Trk::Surface& measSurf = m_idHelperSvc->isMdt(id) ? detEl->surface() : meas.associatedSurface();
872
873 Trk::Intersection intersect = measSurf.straightLineIntersection(ip, dir);
874 if (!intersect.valid) {
875 ATH_MSG_WARNING(" Intersect with surface failed for measurement "
876 << m_printer->print(meas) << " position " << Amg::toString(ip) << " direction: phi " << dir.phi()
877 << " theta " << dir.theta() << " seed: phi " << phiPos->phi() << " theta "
878 << rot->globalPosition().theta());
879 } else {
880 // now get central phi position on surface of segment
881 lpos = meas.associatedSurface().globalToLocal(intersect.position, 3000.);
882
883 }
884 } else {
885 // now get central phi position on surface of segment
886 lpos = meas.associatedSurface().globalToLocal(detEl->center(), 3000.);
887 if (!lpos){
888 lpos = meas.associatedSurface().globalToLocal(meas.associatedSurface().center(), 3000.);
889 }
890
891 }
892
893 if (!lpos) {
894 ATH_MSG_WARNING(" No local position, cannot make fake phi hit "<<m_idHelperSvc->toString(id)<<" "<<typeid(meas).name());
895 return nullptr;
896 }
897
898 double ly = (*lpos)[Trk::locY];
899 double halfLength = ly < 0 ? halfLengthL : halfLengthR;
900 bool shiftedPos = false;
901
902 if (std::abs(ly) > halfLength) {
903 double lyold = ly;
904 ly = ly < 0 ? -halfLength : halfLength;
905 ATH_MSG_DEBUG(" extrapolated position outside detector, shifting it back: " << lyold << " size " << halfLength << " new pos "
906 << ly);
907 if (phiPos && std::abs(lyold) - halfLength > 1000.) {
908 ATH_MSG_DEBUG(" rejecting track ");
909 return nullptr;
910 }
911 shiftedPos = true;
912 }
913
914 ATH_MSG_VERBOSE("Creating fake measurement using measurement " << m_printer->print(meas));
915
916 const Trk::Surface& surf = meas.associatedSurface();
917
918 // no overlap, put fake phi hit at center of the chamber
919 if (overlapPos) {
920 // overlap, fake hit at 100. mm from the edge, error 100./sqrt(12.)
921
922 // transform estimate of overlap position into surface frame
923 std::optional<Amg::Vector2D> loverlapPos = surf.globalToLocal(*overlapPos, 3000.);
924 if (!loverlapPos) {
925 ATH_MSG_DEBUG(" globalToLocal failed for overlap position: " << surf.transform() * (*overlapPos));
926 // calculate position fake
927 double lyfake = halfLength - 50.;
928 if (ly < 0.) lyfake *= -1.;
929 ly = lyfake;
930 errPos = FiftyOverSqrt12;
931
932 if (msgLvl(MSG::VERBOSE)){
933 Amg::Vector2D LocVec2D_plus(0., lyfake);
934 const Amg::Vector3D fakePos_plus = meas.associatedSurface().localToGlobal(LocVec2D_plus);
935 Amg::Vector2D LocVec2D_min(0., -lyfake);
936 const Amg::Vector3D fakePos_min = meas.associatedSurface().localToGlobal(LocVec2D_min);
937
938 double phi_min = fakePos_min.phi();
939 double phi_plus = fakePos_plus.phi();
940 double phi_overlap = phiPos->phi();
941 ATH_MSG_VERBOSE(" fake lpos " << lyfake << " ch half length " << halfLength << " phi+ " << phi_plus << " phi- " << phi_min
942 << " phi overlap " << phi_overlap << " err " << errPos);
943 }
944
945 } else {
946 ly = (*loverlapPos)[Trk::locY];
947 halfLength = ly < 0 ? halfLengthL : halfLengthR; // safer to redo since ly changed
948 if (std::abs(ly) > halfLength) { ly = ly < 0 ? -halfLength : halfLength; }
949 ATH_MSG_VERBOSE(" fake from overlap: lpos " << ly << " ch half length " << halfLength << " overlapPos " << *overlapPos);
950 }
951 }
952
953 Trk::LocalParameters locPars(Trk::DefinedParameter(ly, Trk::locY));
954 // Error matrix
955 Amg::MatrixX cov(1, 1);
956 cov(0, 0) = errPos * errPos;
957 std::unique_ptr<Trk::PseudoMeasurementOnTrack> fake = std::make_unique<Trk::PseudoMeasurementOnTrack>(std::move(locPars),
958 std::move(cov), surf);
959
960 if (msgLvl(MSG::DEBUG)) {
961 Amg::Vector2D LocVec2D(0., fake->localParameters().get(Trk::locY));
962 const Amg::Vector3D fakePos = meas.associatedSurface().localToGlobal(LocVec2D);
963
964 msg(MSG::DEBUG) << MSG::DEBUG << " createFakePhiForMeasurement for: " << m_idHelperSvc->toStringChamber(id) << " locY " << ly
965 << " errpr " << errPos << " phi " << fakePos.phi() << endmsg;
966
967 if (!shiftedPos && !overlapPos && phiPos && std::abs(phiPos->phi() - fakePos.phi()) > 0.01) {
968 Amg::Transform3D gToLocal = meas.associatedSurface().transform().inverse();
969 Amg::Vector3D locMeas = gToLocal * fake->globalPosition();
970 ATH_MSG_WARNING(" Problem calculating fake from IP seed: phi fake " << fakePos.phi() << " IP phi " << phiPos->phi()
971 << " local meas pos " << locMeas);
972 }
973 }
974 return fake;
975 }
std::pair< double, double > getElementHalfLengths(const Identifier &id, const Trk::TrkDetElementBase *ele) const
virtual const TrkDetElementBase * detectorElement() const =0
returns the detector element, assoicated with the PRD of this class
virtual const Amg::Vector3D & globalPosition() const override=0
Interface method to get the global Position.
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...
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
Intersection straightLineIntersection(const T &pars, bool forceDir=false, const Trk::BoundaryCheck &bchk=false) const
fst straight line intersection schema - templated for charged and neutral parameters
virtual const Amg::Vector3D & center() const =0
Return the center of the element.
virtual const Surface & surface() const =0
Return surface associated with this detector element.
std::optional< double > intersect(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
Calculates the point B' along the line B that's closest to a second line A.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Eigen::Matrix< double, 2, 1 > Vector2D
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee

◆ createPerigee()

std::unique_ptr< Trk::Perigee > Muon::MooTrackFitter::createPerigee ( const EventContext & ctx,
const Trk::TrackParameters & firstPars,
const Trk::MeasurementBase & firstMeas ) const

create perigee parameter to initialize fit

Definition at line 1544 of file MooTrackFitter.cxx.

1544 {
1545 // const Amg::Vector3D& firstPos = firstMeas.globalPosition();
1546
1547 Amg::Vector3D perpos{Amg::Vector3D::Zero()};
1548 // propagate segment parameters to first measurement
1549 const Trk::TrackParameters* exPars = &firstPars;
1550 std::unique_ptr<Trk::TrackParameters> garbage;
1551 double shift = 1.;
1553 // not sure whats going on with ownership here, so let this code take care of it
1554 garbage =
1555 m_propagator->propagate(ctx, firstPars, firstMeas.associatedSurface(), Trk::anyDirection, false, m_magFieldProperties);
1556 if (!exPars) {
1557 ATH_MSG_DEBUG(" Propagation failed in createPerigee!! ");
1558 return nullptr;
1559 }
1560 exPars = garbage.get();
1561 shift = 100.;
1562 }
1563
1564 // small shift towards the ip
1565 double sign = exPars->position().dot(exPars->momentum()) > 0 ? 1. : -1.;
1566 perpos = exPars->position() - shift * sign * exPars->momentum().unit();
1567
1568 // create perigee
1569 double phi = exPars->momentum().phi();
1570 double theta = exPars->momentum().theta();
1571 double qoverp = exPars->charge() / exPars->momentum().mag();
1572 if (m_slFit)
1573 qoverp = 0;
1574 else {
1575 if (!validMomentum(*exPars)) {
1576 return nullptr;
1577 }
1578 }
1579
1580 Trk::PerigeeSurface persurf(perpos);
1581 std::unique_ptr<Trk::Perigee> perigee = std::make_unique<Trk::Perigee>(0, 0, phi, theta, qoverp, persurf);
1582
1583 ATH_MSG_DEBUG( std::setprecision(5) << " creating perigee: phi " << phi << " theta " << theta << " q*mom "
1584 << perigee->charge() * perigee->momentum().mag() << " r " << perigee->position().perp() << " z "
1585 << perigee->position().z() << " input q*mom " << firstPars.charge() * firstPars.momentum().mag());
1586 return perigee;
1587 }
int sign(int a)
bool validMomentum(const Trk::TrackParameters &pars) const
check whether mometum of start parameter is ok
Gaudi::Property< bool > m_slFit
Gaudi::Property< bool > m_seedAtStartOfTrack
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.
double charge() const
Returns the charge.

◆ createStartParameters()

void Muon::MooTrackFitter::createStartParameters ( const EventContext & ctx,
MooTrackFitter::FitterData & fitterData ) const
private

create a perigee parameter give the input data

Definition at line 1439 of file MooTrackFitter.cxx.

1439 {
1440 // get momentum + charge from entry if available, else use MuonSegmentMomentum to estimate the momentum
1441 double qOverP = qOverPFromEntries(ctx, *fitterData.firstEntry, *fitterData.secondEntry);
1442 std::unique_ptr<Trk::Perigee> startPars{nullptr};
1443 const MuPatCandidateBase *entry1 = fitterData.firstEntry, *entry2 = fitterData.secondEntry;
1444
1445 const MuPatTrack* trkEntry1 = dynamic_cast<const MuPatTrack*>(entry1);
1446 const MuPatTrack* trkEntry2 = dynamic_cast<const MuPatTrack*>(entry2);
1447 const MuPatSegment* seg1 = dynamic_cast<const MuPatSegment*>(entry1);
1448 const MuPatSegment* seg2 = dynamic_cast<const MuPatSegment*>(entry2);
1449
1450 Amg::Vector3D dir1{Amg::Vector3D::Zero()}, dir2{Amg::Vector3D::Zero()};
1451 Amg::Vector3D point1{Amg::Vector3D::Zero()}, point2{Amg::Vector3D::Zero()};
1452 if (seg1) {
1453 dir1 = seg1->segment->globalDirection();
1454 point1 = seg1->segment->globalPosition();
1455 } else {
1456 if (trkEntry1->track().perigeeParameters()) {
1457 dir1 = trkEntry1->track().perigeeParameters()->momentum().unit();
1458 point1 = trkEntry1->track().perigeeParameters()->position();
1459 } else {
1460 return;
1461 }
1462 }
1463 if (seg2) {
1464 dir2 = seg2->segment->globalDirection();
1465 point2 = seg2->segment->globalPosition();
1466 } else {
1467 if (trkEntry2->track().perigeeParameters()) {
1468 dir2 = trkEntry2->track().perigeeParameters()->momentum().unit();
1469 point2 = trkEntry2->track().perigeeParameters()->position();
1470 } else {
1471 return;
1472 }
1473 }
1474 if (dir1.dot(point2 - point1) < 0) {
1475 std::swap(point1, point2);
1476 std::swap(dir1, dir2);
1477 entry1 = fitterData.secondEntry;
1478 entry2 = fitterData.firstEntry;
1479 trkEntry1 = dynamic_cast<const MuPatTrack*>(entry1);
1480 trkEntry2 = dynamic_cast<const MuPatTrack*>(entry2);
1481 seg1 = dynamic_cast<const MuPatSegment*>(entry1);
1482 seg2 = dynamic_cast<const MuPatSegment*>(entry2);
1483 }
1484
1485 const MuPatCandidateBase* bestentry = entry1;
1486 double dist1 = -1, dist2 = -1;
1487 MuPatHitPtr firstphi1{nullptr}, lastphi1{nullptr}, firstphi2{nullptr}, lastphi2{nullptr};
1488
1489 for (const MuPatHitPtr& hit : entry1->hitList()) {
1490 if (hit->info().type != MuPatHit::Pseudo && hit->info().measuresPhi) {
1491 if (!firstphi1) firstphi1 = hit;
1492 lastphi1 = hit;
1493 }
1494 }
1495 for (const MuPatHitPtr& hit : entry2->hitList()) {
1496 if (hit->info().type != MuPatHit::Pseudo && hit->info().measuresPhi) {
1497 if (!firstphi2) firstphi2 = hit;
1498 lastphi2 = hit;
1499 }
1500 }
1501 if (firstphi1) dist1 = std::abs((firstphi1->measurement().globalPosition() - lastphi1->measurement().globalPosition()).dot(dir1));
1502 if (firstphi2) dist2 = std::abs((firstphi2->measurement().globalPosition() - lastphi2->measurement().globalPosition()).dot(dir2));
1503 if (dist2 > dist1) { bestentry = entry2; }
1504 const MuPatTrack* besttrkEntry = dynamic_cast<const MuPatTrack*>(bestentry);
1505 const MuPatSegment* bestseg = dynamic_cast<const MuPatSegment*>(bestentry);
1506 if (besttrkEntry) {
1507 const Trk::TrackParameters* mdtpar = nullptr;
1508 for (DataVector<const Trk::TrackParameters>::const_iterator parit = besttrkEntry->track().trackParameters()->begin();
1509 parit != besttrkEntry->track().trackParameters()->end(); ++parit) {
1510 mdtpar = *parit;
1511 if (mdtpar) break;
1512 }
1513 if (!mdtpar) {
1514 ATH_MSG_WARNING("Failed to find valid Trackparameters on track ");
1515 return;
1516 }
1517 Amg::VectorX newpar = mdtpar->parameters(); // besttrkEntry->track().perigeeParameters()->parameters();
1518 newpar[Trk::qOverP] = qOverP;
1519 Trk::PerigeeSurface persurf(mdtpar->position());
1520 startPars = std::make_unique<Trk::Perigee>(0, 0, newpar[Trk::phi], newpar[Trk::theta], qOverP,
1521 persurf); // besttrkEntry->track().perigeeParameters()->cloneToNew(newpar);
1522 }
1523
1524 else {
1525 Trk::PerigeeSurface persurf(bestseg->segment->globalPosition());
1526 double phi = bestseg->segment->globalDirection().phi();
1527 if ((fitterData.firstEntry->containsChamber(ChIndex::CSS) ||
1528 fitterData.firstEntry->containsChamber(ChIndex::CSL)) &&
1529 fitterData.secondEntry->hasSLOverlap())
1530 phi = (fitterData.hitList.back()->parameters().position() - bestseg->segment->globalPosition()).phi();
1531
1532 double theta = bestseg->segment->globalDirection().theta();
1533 // create start parameter
1534 startPars = std::make_unique<Trk::Perigee>(0, 0, phi, theta, qOverP, persurf);
1535
1536 }
1537 if (!startPars) {
1538 ATH_MSG_DEBUG(" failed to create perigee ");
1539 return;
1540 }
1541 fitterData.startPars = std::move(startPars);
1542 }
DataModel_detail::const_iterator< DataVector > const_iterator
Standard const_iterator.
Definition DataVector.h:838
double qOverPFromEntries(const EventContext &ctx, const MuPatCandidateBase &firstEntry, const MuPatCandidateBase &secondEntry) const
get q/p using angle + position of the two entries
Eigen::Matrix< double, Eigen::Dynamic, 1 > VectorX
Dynamic Vector - dynamic allocation.
@ qOverP
perigee
std::shared_ptr< MuPatHit > MuPatHitPtr
Definition MuPatHit.h:25
@ theta
Definition ParamDefs.h:66
@ qOverP
perigee
Definition ParamDefs.h:67
@ phi
Definition ParamDefs.h:75
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)

◆ declareGaudiProperty()

Gaudi::Details::PropertyBase & AthCommonDataStore< AthCommonMsg< AlgTool > >::declareGaudiProperty ( Gaudi::Property< T, V, H > & hndl,
const SG::VarHandleKeyType &  )
inlineprivateinherited

specialization for handling Gaudi::Property<SG::VarHandleKey>

Definition at line 156 of file AthCommonDataStore.h.

158 {
160 hndl.value(),
161 hndl.documentation());
162
163 }
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)

◆ declareProperty()

Gaudi::Details::PropertyBase & AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty ( Gaudi::Property< T, V, H > & t)
inlineinherited

Definition at line 145 of file AthCommonDataStore.h.

145 {
146 typedef typename SG::HandleClassifier<T>::type htype;
148 }
Gaudi::Details::PropertyBase & declareGaudiProperty(Gaudi::Property< T, V, H > &hndl, const SG::VarHandleKeyType &)
specialization for handling Gaudi::Property<SG::VarHandleKey>

◆ detStore()

const ServiceHandle< StoreGateSvc > & AthCommonDataStore< AthCommonMsg< AlgTool > >::detStore ( ) const
inlineinherited

The standard StoreGateSvc/DetectorStore Returns (kind of) a pointer to the StoreGateSvc.

Definition at line 95 of file AthCommonDataStore.h.

◆ evtStore()

ServiceHandle< StoreGateSvc > & AthCommonDataStore< AthCommonMsg< AlgTool > >::evtStore ( )
inlineinherited

The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.

Definition at line 85 of file AthCommonDataStore.h.

◆ extractData() [1/2]

bool Muon::MooTrackFitter::extractData ( const MuPatCandidateBase & entry1,
const MuPatCandidateBase & entry2,
MooTrackFitter::FitterData & fitterData ) const
private

extract all information needed for the fit from the track

Definition at line 327 of file MooTrackFitter.cxx.

328 {
329 // sanity checks on the entries
330 if (corruptEntry(entry1)) {
331 ATH_MSG_DEBUG(" corrupt first entry, cannot perform fit: eta hits " << entry1.etaHits().size());
332 return false;
333 }
334 if (corruptEntry(entry2)) {
335 ATH_MSG_DEBUG(" corrupt second entry, cannot perform fit: eta hits " << entry2.etaHits().size());
336 return false;
337 }
338 // are we in the endcap region?
339 bool isEndcap = entry1.hasEndcap() || entry2.hasEndcap();
340
341
342 // measurement sorting function
343 SortMeasurementsByPosition sortMeasurements(isEndcap);
344
345 bool entry1IsFirst = sortMeasurements(entry1.hits().front(), entry2.hits().front());
346 if (m_cosmics) {
347 DistanceToPars distToPars(&entry1.entryPars());
348 double distToSecond = distToPars(entry2.entryPars().position());
349 if (distToSecond < 0) entry1IsFirst = false;
350 ATH_MSG_DEBUG(" first entry dir " << Amg::toString(entry1.entryPars().momentum())
351 << " pos " << Amg::toString(entry1.entryPars().position()) << " second "
352 << Amg::toString(entry2.entryPars().position()) << " dist " << distToSecond);
353 }
354 const MuPatCandidateBase& firstEntry = entry1IsFirst ? entry1 : entry2;
355 const MuPatCandidateBase& secondEntry = entry1IsFirst ? entry2 : entry1;
356
357 fitterData.firstEntry = &firstEntry;
358 fitterData.secondEntry = &secondEntry;
359
360 // check whether we are dealing with a track or a segment
361 if (dynamic_cast<const MuPatTrack*>(fitterData.firstEntry)) {
362 fitterData.firstIsTrack = true;
363 fitterData.firstHasMomentum = fitterData.firstEntry->hasMomentum();
364 }
365 if (dynamic_cast<const MuPatTrack*>(fitterData.secondEntry)) {
366 fitterData.secondIsTrack = true;
367 fitterData.secondHasMomentum = fitterData.secondEntry->hasMomentum();
368 }
369 // merge hitLists and add them to the fitterData
370 fitterData.hitList = m_hitHandler->merge(entry1.hitList(), entry2.hitList());
371
372 bool usePrecise = m_usePreciseHits || (fitterData.firstHasMomentum || fitterData.secondHasMomentum);
373 if (msgLvl(MSG::DEBUG)) {
374 msg(MSG::DEBUG) << MSG::DEBUG << " entering fitter: etaHits, first entry: ";
375 if (fitterData.firstIsTrack)
376 msg(MSG::DEBUG) << " track ";
377 else
378 msg(MSG::DEBUG) << " segment ";
379 msg(MSG::DEBUG) << fitterData.firstEntry->etaHits().size() << std::endl
380 << m_hitHandler->print(fitterData.firstEntry->hitList()) << std::endl
381 << " second entry: ";
382 if (fitterData.secondIsTrack)
383 msg(MSG::DEBUG) << " track ";
384 else
385 msg(MSG::DEBUG) << " segment ";
386 msg(MSG::DEBUG) << fitterData.secondEntry->etaHits().size() << std::endl
387 << m_hitHandler->print(fitterData.secondEntry->hitList()) << endmsg;
388 }
389
390 if (msgLvl(MSG::DEBUG)) {
391 msg(MSG::DEBUG) << MSG::DEBUG << " merged hit lists, new list size: " << fitterData.hitList.size();
392 if (usePrecise) msg(MSG::DEBUG) << " using precise errors" << endmsg;
393 if (msgLvl(MSG::VERBOSE)) msg(MSG::DEBUG) << std::endl << m_hitHandler->print(fitterData.hitList);
394 msg(MSG::DEBUG) << endmsg;
395 }
396
397 return extractData(fitterData, usePrecise);
398 }
bool corruptEntry(const MuPatCandidateBase &entry) const
sanity check for entries
Gaudi::Property< bool > m_usePreciseHits
bool extractData(const MuPatCandidateBase &entry1, const MuPatCandidateBase &entry2, FitterData &fitterData) const
extract all information needed for the fit from the track

◆ extractData() [2/2]

bool Muon::MooTrackFitter::extractData ( MooTrackFitter::FitterData & fitterData,
bool usePreciseHits ) const
private

extract all information from the HitList of a FitterData object

Definition at line 400 of file MooTrackFitter.cxx.

400 {
401 ATH_MSG_DEBUG(" extracting hits from hit list, using " << (usePreciseHits ? "precise measurements" : "broad measurements"));
402
403 MuPatHitList& hitList = fitterData.hitList;
404 // make sure the vector is sufficiently large
405 unsigned int nhits = hitList.size();
406
407 fitterData.measurements.clear();
408 fitterData.firstLastMeasurements.clear();
409 fitterData.etaHits.clear();
410 fitterData.phiHits.clear();
411 fitterData.measurements.reserve(nhits);
412 fitterData.firstLastMeasurements.reserve(nhits);
413
414 if (usePreciseHits && fitterData.startPars) removeSegmentOutliers(fitterData);
415
416 StIndex firstStation = StIndex::StUnknown;
417 ChIndex currentChIndex = ChIndex::ChUnknown;
418 bool currentMeasPhi = false;
419 MuPatHitPtr previousHit{nullptr};
420
421 // loop over hit list
422 for (const MuPatHitPtr& hit : hitList) {
423 const Identifier& id = hit->info().id;
424 if (hit->info().status != MuPatHit::OnTrack || !id.is_valid()) {
425 ATH_MSG_VERBOSE("Discard outlier "<<m_idHelperSvc->toString(id));
426 continue;
427 }
428 // in theory, there are only MuPatHit objects for MS hits
429 if (!m_idHelperSvc->isMuon(id)) {
430 ATH_MSG_WARNING("given Identifier " << id.get_compact() << " (" << m_idHelperSvc->toString(id)
431 << ") is not a muon Identifier, continuing");
432 continue;
433 }
434
435 ChIndex chIndex = m_idHelperSvc->chamberIndex(id);
437 fitterData.stations.insert(stIndex);
438
439 if (firstStation == StIndex::StUnknown) {
440 firstStation = stIndex;
441 }
442
443 const bool measuresPhi = hit->info().measuresPhi;
444
445 if (!m_idHelperSvc->isTgc(id) && !measuresPhi) {
446 const bool isSmall = m_idHelperSvc->isSmallChamber(id);
447 SmallLargeChambers& stCount = fitterData.smallLargeChambersPerStation[stIndex];
448 stCount.first += isSmall;
449 stCount.second += !isSmall;
450 }
451
452 bool isEndcap = m_idHelperSvc->isEndcap(id);
453 fitterData.hasEndcap |= isEndcap;
454 fitterData.hasBarrel |= !isEndcap;
455
456 const Trk::MeasurementBase* meas = usePreciseHits ? &hit->preciseMeasurement() : &hit->broadMeasurement();
457
458 // special treatment of hits in first stations on the track to stabalise the track fit
459 if (!usePreciseHits && m_preciseFirstStation) { meas = &hit->preciseMeasurement(); }
460
461 if (measuresPhi)
462 fitterData.phiHits.push_back(meas);
463 else
464 fitterData.etaHits.push_back(meas);
465
466 if (msgLvl(MSG::DEBUG)) {
467 double rDrift = meas->localParameters()[Trk::locR];
468 double rError = Amg::error(meas->localCovariance(), Trk::locR);
469 if (usePreciseHits && m_idHelperSvc->isMdt(id) && std::abs(rDrift) < 0.01 && rError > 4.) {
470 ATH_MSG_WARNING(" MDT hit error broad but expected precise error ");
471 }
472 }
473
474 fitterData.measurements.push_back(meas);
475
476 if (!measuresPhi && m_idHelperSvc->isTrigger(id)) continue;
477
478 if (!previousHit) {
479 currentChIndex = chIndex;
480 currentMeasPhi = measuresPhi;
481 fitterData.firstLastMeasurements.push_back(&hit->broadMeasurement());
482 } else if (currentChIndex == chIndex && currentMeasPhi == measuresPhi) {
483 previousHit = hit;
484 } else {
485 currentChIndex = chIndex;
486 currentMeasPhi = measuresPhi;
487 previousHit = hit;
488 fitterData.firstLastMeasurements.push_back(&hit->broadMeasurement());
489 }
490 }
491
492 // add last hit if not already inserted
493 if (previousHit && &previousHit->broadMeasurement() != fitterData.firstLastMeasurements.back())
494 fitterData.firstLastMeasurements.push_back(&previousHit->broadMeasurement());
495
496 // require at least 6 measurements on a track
497 if (fitterData.measurements.size() < 7) {
498 ATH_MSG_VERBOSE(" Too few measurements, cannot perform fit " << fitterData.measurements.size());
499 return false;
500 }
501
502 // require at least 6 measurements on a track
503 if (fitterData.etaHits.size() < 7) {
504 ATH_MSG_VERBOSE(" Too few eta measurements, cannot perform fit " << fitterData.etaHits.size());
505 return false;
506 }
507
508 ATH_MSG_VERBOSE(" Extracted measurements: total " << fitterData.measurements.size() << " eta "
509 << fitterData.etaHits.size() << " phi " << fitterData.phiHits.size()<< std::endl << m_printer->print(fitterData.measurements));
510 return true;
511 }
std::pair< int, int > SmallLargeChambers
Gaudi::Property< bool > m_preciseFirstStation
void removeSegmentOutliers(FitterData &fitterData) const
ChIndex chIndex(const std::string &index)
convert ChIndex name string to enum
StIndex toStationIndex(ChIndex index)
convert ChIndex into StIndex
bool isSmall(const ChIndex index)
Returns true if the chamber index is in a small sector.
ChIndex
enum to classify the different chamber layers in the muon spectrometer

◆ extraDeps_update_handler()

void AthCommonDataStore< AthCommonMsg< AlgTool > >::extraDeps_update_handler ( Gaudi::Details::PropertyBase & ExtraDeps)
protectedinherited

Add StoreName to extra input/output deps as needed.

use the logic of the VarHandleKey to parse the DataObjID keys supplied via the ExtraInputs and ExtraOuputs Properties to add the StoreName if it's not explicitly given

◆ finalize()

StatusCode Muon::MooTrackFitter::finalize ( )

finialize method, method taken from bass-class AlgTool

Definition at line 79 of file MooTrackFitter.cxx.

79 {
80 double nfits = m_nfits.load() > 0 ? m_nfits.load() : 1.;
81 double nfailedExtractInital = m_nfailedExtractInital / nfits;
82 double nfailedMinMaxPhi = m_nfailedMinMaxPhi / nfits;
83 double nfailedParsInital = m_nfailedParsInital / nfits;
84 double nfailedExtractCleaning = m_nfailedExtractCleaning / nfits;
85 double nfailedFakeInitial = m_nfailedFakeInitial / nfits;
86 double nfailedTubeFit = m_nfailedTubeFit / nfits;
87 double noPerigee = m_noPerigee / nfits;
88 double nlowMomentum = m_nlowMomentum / nfits;
89 double nfailedExtractPrecise = m_nfailedExtractPrecise / nfits;
90 double nfailedFakePrecise = m_nfailedFakePrecise / nfits;
91 double nfailedFitPrecise = m_nfailedFitPrecise / nfits;
92 double nsuccess = m_nsuccess / nfits;
93 ATH_MSG_INFO(" Summarizing statistics: nfits "
94 << m_nfits << std::endl
95 << "| extract | phi range | startPars | clean phi | add fake | fit | no perigee | low mom | extract | "
96 "add fake | final fit | passed |"
97 << std::endl
98 << std::setprecision(2) << std::setw(12) << nfailedExtractInital << std::setw(12) << nfailedMinMaxPhi << std::setw(12)
99 << nfailedParsInital << std::setw(12) << nfailedExtractCleaning << std::setw(12) << nfailedFakeInitial << std::setw(12)
100 << nfailedTubeFit << std::setw(13) << noPerigee << std::setw(12) << nlowMomentum << std::setw(12)
101 << nfailedExtractPrecise << std::setw(12) << nfailedFakePrecise << std::setw(12) << nfailedFitPrecise << std::setw(12)
102 << nsuccess);
103
104 return StatusCode::SUCCESS;
105 }
#define ATH_MSG_INFO(x)
std::atomic_uint m_nfailedTubeFit
std::atomic_uint m_nfits
std::atomic_uint m_nsuccess
std::atomic_uint m_nfailedFakePrecise
std::atomic_uint m_nfailedFakeInitial
std::atomic_uint m_nfailedExtractCleaning
std::atomic_uint m_nlowMomentum
std::atomic_uint m_nfailedParsInital
std::atomic_uint m_nfailedExtractPrecise
std::atomic_uint m_nfailedExtractInital
std::atomic_uint m_nfailedMinMaxPhi
std::atomic_uint m_nfailedFitPrecise
std::atomic_uint m_noPerigee

◆ fit() [1/2]

std::unique_ptr< Trk::Track > Muon::MooTrackFitter::fit ( const EventContext & ctx,
const MuPatCandidateBase & firstEntry,
const MuPatCandidateBase & secondEntry,
const PrepVec & externalPhiHits ) const

fit the hits of two MuPatCandidateBase

Parameters
firstEntrythe first entry
secondEntrythe second entry
externalPhiHitsif provided, the external phi hits will be used instead of the phi hits on the segment
Returns
a pointer to the resulting track, will return zero if the fit failed.

Definition at line 176 of file MooTrackFitter.cxx.

177 {
178 ++m_nfits;
179 // internal representation of the track in fitter
180 FitterData fitterData;
181
182 // extract hits and geometrical information
183 if (!extractData(entry1, entry2, fitterData)) {
184 ATH_MSG_DEBUG(" Failed to extract data for initial fit");
185 return nullptr;
186 }
188
189 // get the minimum and maximum phi compatible with all eta hits, don't use for cosmics
190 if (!m_cosmics && !getMinMaxPhi(fitterData)) {
191 ATH_MSG_DEBUG(" Phi range check failed, candidate stations not pointing. Will not fit track");
192 return nullptr;
193 }
194
196
197 // create start parameters
198 createStartParameters(ctx, fitterData);
199 std::unique_ptr<Trk::Perigee>& startPars = fitterData.startPars;
200 if (!startPars) {
201 ATH_MSG_DEBUG(" Creation of start parameters failed ");
202 return nullptr;
203 }
204 ATH_MSG_VERBOSE("Extracted start parameters: "<<Amg::toString(startPars->momentum().unit())<< " "<<Amg::toString(startPars->position()));
206
207 // clean phi hits and reevaluate hits. Do not run for cosmics
208 bool hasCleaned = m_cleanPhiHits && cleanPhiHits(ctx, startPars->momentum().mag(), fitterData, externalPhiHits);
209 if (hasCleaned) {
210 ATH_MSG_DEBUG(" Cleaned phi hits, re-extracting hits");
211 bool usePrecise = m_usePreciseHits || (fitterData.firstHasMomentum || fitterData.secondHasMomentum);
212 ATH_MSG_VERBOSE("Call extract data with usePrecise "<<usePrecise);
213 if (!extractData(fitterData, usePrecise)) {
214 ATH_MSG_DEBUG(" Failed to extract data after phi hit cleaning");
215 return nullptr;
216 }
217 }
219
220 // check whether there are enough phi constraints, if not add fake phi hits
221 if (!addFakePhiHits(ctx, fitterData, *startPars)) {
222 ATH_MSG_DEBUG(" Failed to add fake phi hits for precise fit");
223 return nullptr;
224 }
226
227 // fit track with broad errors, no material
228 bool doPreFit = m_usePrefit;
230 if (fitterData.firstHasMomentum || fitterData.secondHasMomentum) doPreFit = false;
231 if (!doPreFit) particleType = Trk::muon;
232
233 std::unique_ptr<Trk::Track> track = fit(ctx, *startPars, fitterData.measurements, particleType, doPreFit);
234
235 if (!track) {
236 ATH_MSG_DEBUG(" Fit failed ");
237 return nullptr;
238 }
240
241 // create start parameters
242 const Trk::Perigee* pp = track->perigeeParameters();
243 if (!pp) {
244 ATH_MSG_DEBUG(" Track without perigee parameters, exit ");
245 return nullptr;
246 }
247 ++m_noPerigee;
248
249 if (!m_slFit && !validMomentum(*pp)) {
250 ATH_MSG_VERBOSE(" Low momentum, rejected ");
251 return nullptr;
252 }
254
255 if (!fitterData.firstHasMomentum && !fitterData.secondHasMomentum && doPreFit) {
256 ATH_MSG_DEBUG(" Performing second fit ");
257
258 // refit with precise errors
259 FitterData fitterDataRefit{};
260 fitterDataRefit.startPars.reset(pp->clone());
261 fitterDataRefit.firstIsTrack = fitterData.firstIsTrack;
262 fitterDataRefit.secondIsTrack = fitterData.secondIsTrack;
263 fitterDataRefit.firstHasMomentum = fitterData.firstHasMomentum;
264 fitterDataRefit.secondHasMomentum = fitterData.secondHasMomentum;
265 fitterDataRefit.avePhi = fitterData.avePhi;
266 fitterDataRefit.phiMin = fitterData.phiMin;
267 fitterDataRefit.phiMax = fitterData.phiMax;
268 fitterDataRefit.firstEntry = fitterData.firstEntry;
269 fitterDataRefit.secondEntry = fitterData.secondEntry;
270 fitterDataRefit.hitList = fitterData.hitList;
271
272 // extract hits from hit list and add them to fitterData
273 if (!extractData(fitterDataRefit, true)) {
274 ATH_MSG_DEBUG(" Failed to extract data for precise fit");
275 return nullptr;
276 }
278
279 // check whether there are enough phi constraints, if not add fake phi hits
280 if (!addFakePhiHits(ctx, fitterDataRefit, *startPars)) {
281 ATH_MSG_DEBUG(" Failed to add fake phi hits for precise fit");
282 return nullptr;
283 }
285
286 // fit track
287 std::unique_ptr<Trk::Track> newTrack = fit(ctx, *pp, fitterDataRefit.measurements, Trk::muon, false);
288 if (newTrack)
289 track.swap(newTrack);
290 else if (!m_allowFirstFit) {
291 ATH_MSG_DEBUG(" Precise fit failed ");
292 return nullptr;
293 } else {
294 ATH_MSG_DEBUG(" Precise fit failed, keep fit with broad errors");
295 }
297
298 fitterData.garbage.insert(fitterData.garbage.end(), std::make_move_iterator(fitterDataRefit.garbage.begin()),
299 std::make_move_iterator(fitterDataRefit.garbage.end()));
300 fitterDataRefit.garbage.clear();
301 }
302
303 if (track) {
304 // clean and evaluate track
305 std::set<Identifier> excludedChambers;
306 if (fitterData.firstIsTrack && !fitterData.secondIsTrack) {
307 excludedChambers = fitterData.secondEntry->chamberIds();
308 ATH_MSG_VERBOSE(" Using exclusion list of second entry for cleaning");
309 } else if (!fitterData.firstIsTrack && fitterData.secondIsTrack) {
310 excludedChambers = fitterData.firstEntry->chamberIds();
311 ATH_MSG_VERBOSE(" Using exclusion list of first entry for cleaning");
312 }
313 if (!excludedChambers.empty()) { ATH_MSG_DEBUG(" Using exclusion list for cleaning"); }
314 std::unique_ptr<Trk::Track> cleanTrack = cleanAndEvaluateTrack(ctx, *track, excludedChambers);
315 if (cleanTrack) {
316 if (!(*cleanTrack->perigeeParameters() == *track->perigeeParameters())) track.swap(cleanTrack);
317 } else
318 track.reset();
319 }
320
321 if (track) ++m_nsuccess;
322
323 if (msgLvl(MSG::DEBUG) && track) msg(MSG::DEBUG) << MSG::DEBUG << " Track found " << endmsg;
324 return track;
325 }
bool cleanPhiHits(const EventContext &ctx, double momentum, FitterData &phiHits, const PrepVec &patternPhiHits) const
clean phi hits, returns true if anything happened during the cleaning
Gaudi::Property< bool > m_cleanPhiHits
Gaudi::Property< bool > m_allowFirstFit
void createStartParameters(const EventContext &ctx, FitterData &inputData) const
create a perigee parameter give the input data
std::unique_ptr< Trk::Track > fit(const EventContext &ctx, const MuPatCandidateBase &firstEntry, const MuPatCandidateBase &secondEntry, const PrepVec &externalPhiHits) const
fit the hits of two MuPatCandidateBase
bool getMinMaxPhi(FitterData &fitterData) const
calculate the minimum and maximum phi value a track could have to pass all eta channels
Gaudi::Property< bool > m_usePrefit
bool addFakePhiHits(const EventContext &ctx, FitterData &fitterData, const Trk::TrackParameters &referenceParameter) const
check fitterData, add fake phi hits if needed.
std::unique_ptr< Trk::Track > cleanAndEvaluateTrack(const EventContext &ctx, Trk::Track &track, const std::set< Identifier > &excludedChambers) const
clean and evaluate the track,
virtual ParametersT< DIM, T, S > * clone() const override final
Virtual clone.
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
ParticleHypothesis
Enumeration for Particle hypothesis respecting the interaction with material.
std::unique_ptr< Trk::Perigee > startPars

◆ fit() [2/2]

std::unique_ptr< Trk::Track > Muon::MooTrackFitter::fit ( const EventContext & ctx,
const Trk::Perigee & startPars,
MooTrackFitter::MeasVec & hits,
Trk::ParticleHypothesis partHypo,
bool prefit ) const

fit track

Definition at line 1606 of file MooTrackFitter.cxx.

1607 {
1608 if (hits.empty()) return nullptr;
1609 std::unique_ptr<Trk::Perigee> perigee{};
1610 ATH_MSG_VERBOSE(std::setprecision(5) << " track start parameter: phi " << startPars.momentum().phi() << " theta "
1611 << startPars.momentum().theta() << " q*mom " << startPars.charge() * startPars.momentum().mag()
1612 << " r " << startPars.position().perp() << " z " << startPars.position().z() << std::endl
1613 << " start par is a perigee "
1614 << " partHypo " << partHypo << std::endl
1615 << m_printer->print(hits));
1616
1617 const Trk::TrackParameters* pars = &startPars;
1619 DistanceAlongParameters distAlongPars;
1620 double dist = distAlongPars(startPars, *hits.front());
1621
1622 if (dist < 0.) {
1623 ATH_MSG_DEBUG(" start parameters after first hit, shifting them.... ");
1624 perigee = createPerigee(ctx, startPars, *hits.front());
1625 if (perigee) {
1626 pars = perigee.get();
1627 } else {
1628 ATH_MSG_DEBUG(" failed to move start pars, failing fit ");
1629 return nullptr;
1630 }
1631 }
1632 }
1633
1634 // fit track
1635
1636 ATH_MSG_VERBOSE("fit: " << (prefit ? "prefit" : "fit") << "track with hits: " << hits.size() << std::endl
1637 << m_printer->print(hits));
1638 //The 'pars' is from perigee.get(), and the perigee object still exists in the 'garbage' vector
1639 //cppcheck-suppress invalidLifetime
1640 std::unique_ptr<Trk::Track> track{m_trackFitter->fit(ctx, hits, *pars, m_runOutlier, partHypo)};
1641
1642 // 'sign' track
1643 if (track) {
1644 ATH_MSG_VERBOSE("Got back this track:"<<*track);
1645 track->info().setPatternRecognitionInfo(m_patRecInfo);
1646 }
1647
1648 return track;
1649 }
Gaudi::Property< Trk::RunOutlierRemoval > m_runOutlier
ToolHandle< Trk::ITrackFitter > m_trackFitter
fitter
Trk::TrackInfo::TrackPatternRecoInfo m_patRecInfo
std::unique_ptr< Trk::Perigee > createPerigee(const EventContext &ctx, const Trk::TrackParameters &firstPars, const Trk::MeasurementBase &firstMeas) const
create perigee parameter to initialize fit

◆ fitSplitTrack()

std::unique_ptr< Trk::Track > Muon::MooTrackFitter::fitSplitTrack ( const EventContext & ctx,
const Trk::TrackParameters & startPars,
const std::vector< const Trk::TrackStateOnSurface * > & tsos ) const

construct a track from a list of TSOS and a start parameters

Definition at line 2150 of file MooTrackFitter.cxx.

2151 {
2152 // first create track out of the constituent
2153 double phi = startPars.momentum().phi();
2154 double theta = startPars.momentum().theta();
2155 double qoverp = startPars.charge() / startPars.momentum().mag();
2156 if (m_slFit) qoverp = 0;
2157 Trk::PerigeeSurface persurf(startPars.position());
2158 std::unique_ptr<Trk::Perigee> perigee = std::make_unique<Trk::Perigee>(0, 0, phi, theta, qoverp, persurf);
2159
2160 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
2161 trackStateOnSurfaces->reserve(tsos.size() + 1);
2162 trackStateOnSurfaces->push_back(MuonTSOSHelper::createPerigeeTSOS(std::move(perigee)));
2163 for (const Trk::TrackStateOnSurface* tsos : tsos) trackStateOnSurfaces->push_back(tsos->clone());
2164
2165 Trk::TrackInfo trackInfo(Trk::TrackInfo::Unknown, Trk::muon);
2166 std::unique_ptr<Trk::Track> track = std::make_unique<Trk::Track>(trackInfo, std::move(trackStateOnSurfaces), nullptr);
2167
2168 unsigned int nphi = hasPhiConstrain(track.get());
2169
2170 if (nphi > 1) {
2171 ATH_MSG_DEBUG("Track has sufficient phi constraints, fitting ");
2172
2173 } else {
2174 // loop over the track and find the first and last measurement and the phi hit if any
2175 const Trk::TrackStateOnSurface* firstMeas = nullptr;
2176 const Trk::TrackStateOnSurface* lastMeas = nullptr;
2177 const Trk::TrackStateOnSurface* phiMeas = nullptr;
2178
2179 std::vector<const Trk::TrackStateOnSurface*>::const_iterator tit = tsos.begin();
2180 std::vector<const Trk::TrackStateOnSurface*>::const_iterator tit_end = tsos.end();
2181 for (; tit != tit_end; ++tit) {
2182 // require track parameters;
2183 if (!(*tit)->trackParameters()) continue;
2184
2185 const Trk::MeasurementBase* meas = (*tit)->measurementOnTrack();
2186 if (!meas) continue;
2187
2188 Identifier id = m_edmHelperSvc->getIdentifier(*meas);
2189 if (!id.is_valid() || !m_idHelperSvc->isMuon(id)) continue;
2190
2191 if (m_idHelperSvc->isMdt(id)) {
2192 if (!firstMeas) firstMeas = *tit;
2193 lastMeas = *tit;
2194 } else if (m_idHelperSvc->measuresPhi(id)) {
2195 phiMeas = *tit;
2196 }
2197 }
2198
2199 if (!firstMeas) {
2200 ATH_MSG_WARNING(" failed to find first MDT measurement with track parameters");
2201 return nullptr;
2202 }
2203
2204 if (!lastMeas) {
2205 ATH_MSG_WARNING(" failed to find second MDT measurement with track parameters");
2206 return nullptr;
2207 }
2208
2209 if (firstMeas == lastMeas) {
2210 ATH_MSG_WARNING(" first MDT measurement with track parameters equals to second");
2211 return nullptr;
2212 }
2213
2214 const Trk::TrackStateOnSurface* positionFirstFake = nullptr;
2215 const Trk::TrackStateOnSurface* positionSecondFake = nullptr;
2216
2217 if (phiMeas) {
2218 double distFirst = (firstMeas->trackParameters()->position() - phiMeas->trackParameters()->position()).mag();
2219 double distSecond = (lastMeas->trackParameters()->position() - phiMeas->trackParameters()->position()).mag();
2220 ATH_MSG_DEBUG("Track has one phi constraints, adding second: dist to first " << distFirst << " dist to second "
2221 << distSecond);
2222 // add fake at position furthest away from phi measurement
2223 if (distFirst < distSecond) {
2224 positionFirstFake = lastMeas;
2225 } else {
2226 positionFirstFake = firstMeas;
2227 }
2228
2229 } else {
2230 ATH_MSG_DEBUG("Track has no phi constraints, adding one at beginning and one at the end of the track ");
2231
2232 positionFirstFake = firstMeas;
2233 positionSecondFake = lastMeas;
2234 }
2235
2236 // clean up previous track and create new one with fake hits
2237 auto uniquePerigee = std::make_unique<Trk::Perigee>(0, 0, phi, theta, qoverp, persurf);
2238 auto trackStateOnSurfaces = std::make_unique<Trk::TrackStates>();
2239 trackStateOnSurfaces->reserve(tsos.size() + 3);
2240 trackStateOnSurfaces->push_back(MuonTSOSHelper::createPerigeeTSOS(std::move(uniquePerigee)));
2241
2242 tit = tsos.begin();
2243 tit_end = tsos.end();
2244 for (; tit != tit_end; ++tit) {
2245 // remove existing pseudo measurements
2246 const Trk::MeasurementBase* meas = (*tit)->measurementOnTrack();
2247 if (meas && dynamic_cast<const Trk::PseudoMeasurementOnTrack*>(meas)) {
2248 ATH_MSG_DEBUG("removing existing pseudo measurement ");
2249 continue;
2250 }
2251
2252 trackStateOnSurfaces->push_back((*tit)->clone());
2253 if (*tit == positionFirstFake) {
2254 double fakeError = 100.;
2255 if (positionFirstFake->trackParameters()->covariance()) {
2256 fakeError = Amg::error(*positionFirstFake->trackParameters()->covariance(), Trk::loc2);
2257 ATH_MSG_DEBUG(" Using error of parameters " << fakeError);
2258 }
2259
2260 Amg::Vector3D position = positionFirstFake->trackParameters()->position();
2261 std::unique_ptr<Trk::MeasurementBase> fake =
2262 createFakePhiForMeasurement(*(positionFirstFake->measurementOnTrack()), &position, nullptr, fakeError);
2263 if (fake) {
2264 // need to clone as fake is already added to garbage collection
2265 trackStateOnSurfaces->push_back(MuonTSOSHelper::createMeasTSOSWithUpdate(
2266 **tit, std::move(fake), positionFirstFake->trackParameters()->uniqueClone(), Trk::TrackStateOnSurface::Measurement));
2267 } else {
2268 ATH_MSG_WARNING(" failed to create fake at first measurement ");
2269 }
2270 }
2271 if (*tit == positionSecondFake && positionSecondFake) {
2272 double fakeError = 100.;
2273 if (positionSecondFake->trackParameters()->covariance()) {
2274 fakeError = Amg::error(*positionSecondFake->trackParameters()->covariance(), Trk::loc2);
2275 ATH_MSG_DEBUG(" Using error of parameters " << fakeError);
2276 }
2277
2278 Amg::Vector3D position = positionSecondFake->trackParameters()->position();
2279 std::unique_ptr<Trk::MeasurementBase> fake =
2280 createFakePhiForMeasurement(*(positionSecondFake->measurementOnTrack()), &position, nullptr, fakeError);
2281 if (fake) {
2282 // need to clone as fake is already added to garbage collection
2283 trackStateOnSurfaces->push_back(MuonTSOSHelper::createMeasTSOSWithUpdate(
2284 **tit, std::move(fake), positionSecondFake->trackParameters()->uniqueClone(), Trk::TrackStateOnSurface::Measurement));
2285 } else {
2286 ATH_MSG_WARNING(" failed to create fake at second measurement ");
2287 }
2288 }
2289 }
2290
2291 Trk::TrackInfo trackInfo(Trk::TrackInfo::Unknown, Trk::muon);
2292 track = std::make_unique<Trk::Track>(trackInfo, std::move(trackStateOnSurfaces), nullptr);
2293 }
2294
2295 // refit track
2296 std::unique_ptr<Trk::Track> refittedTrack = refit(ctx, *track);
2297 if (refittedTrack) refittedTrack->info().setPatternRecognitionInfo(m_patRecInfo);
2298
2299 return refittedTrack;
2300 }
std::unique_ptr< Trk::Track > refit(const EventContext &ctx, const MuPatTrack &trkCan) const
refit a MuPatTrack
static std::unique_ptr< Trk::TrackStateOnSurface > createPerigeeTSOS(std::unique_ptr< Trk::TrackParameters > perigee)
create a perigee TSOS, takes ownership of the Perigee
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
const MeasurementBase * measurementOnTrack() const
returns MeasurementBase const overload
const TrackParameters * trackParameters() const
return ptr to trackparameters const overload
@ Measurement
This is a measurement, and will at least contain a Trk::MeasurementBase.
@ loc2
generic first and second local coordinate
Definition ParamDefs.h:35

◆ fitWithRefit()

std::unique_ptr< Trk::Track > Muon::MooTrackFitter::fitWithRefit ( const EventContext & ctx,
const Trk::Perigee & startPars,
MooTrackFitter::MeasVec & hits ) const

fit track, refit if needed

Definition at line 1651 of file MooTrackFitter.cxx.

1651 {
1652
1653 std::unique_ptr<Trk::Track> track = fit(ctx, startPars, hits, Trk::muon, false);
1654
1655 // exceptions that are not refitted
1656 if (m_slFit) return track;
1657
1658 // refit track to ensure correct handling of material effects
1659 if (track) {
1660 const Trk::Perigee* pp = track->perigeeParameters();
1661 if (pp) {
1662 ATH_MSG_VERBOSE(" found track: " << m_printer->print(*track));
1663
1664 // refit if absolute difference of the initial momentum and the final momentum is larger than 5 GeV
1665 double difMom = startPars.momentum().mag() - pp->momentum().mag();
1666 if (std::abs(difMom) > 5000.) {
1667 ATH_MSG_DEBUG(" absolute difference in momentum too large, refitting track. Dif momentum= " << difMom);
1668 ATH_MSG_DEBUG("fitWithRefit: refitting track with hits: " << hits.size() << std::endl << m_printer->print(hits));
1669 std::unique_ptr<Trk::Track> refittedTrack(m_trackFitter->fit(ctx, hits, *pp, false, m_ParticleHypothesis));
1670 if (refittedTrack) {
1671 track.swap(refittedTrack);
1672
1673 if (msgLvl(MSG::DEBUG)) {
1674 const Trk::Perigee* pp = track->perigeeParameters();
1675 if (pp) {
1676 ATH_MSG_DEBUG(" refitted track fit perigee: r " << pp->position().perp() << " z " << pp->position().z());
1677 }
1678 }
1679 }
1680 }
1681 }
1682 }
1683
1684 return track;
1685 }
Trk::ParticleHypothesis m_ParticleHypothesis
nomen est omen

◆ getElementHalfLengths()

std::pair< double, double > Muon::MooTrackFitter::getElementHalfLengths ( const Identifier & id,
const Trk::TrkDetElementBase * ele ) const
private

Definition at line 1093 of file MooTrackFitter.cxx.

1093 {
1094 if (m_idHelperSvc->isMdt(id)) {
1095 const MuonGM::MdtReadoutElement* mdtDetEl = dynamic_cast<const MuonGM::MdtReadoutElement*>(ele);
1096 if (!mdtDetEl){ return std::make_pair(0., 0.); }
1097 const double halfLength = 0.5 * mdtDetEl->getActiveTubeLength(m_idHelperSvc->mdtIdHelper().tubeLayer(id),
1098 m_idHelperSvc->mdtIdHelper().tube(id));
1099 return std::make_pair(halfLength, halfLength);
1100
1101 } else if (m_idHelperSvc->isCsc(id)) {
1102 const MuonGM::CscReadoutElement* cscDetEl = dynamic_cast<const MuonGM::CscReadoutElement*>(ele);
1103 if (!cscDetEl) { return std::make_pair(0., 0.);}
1104 const double halfLenghth = 0.5 * cscDetEl->stripLength(id);
1105 return std::make_pair(halfLenghth, halfLenghth);
1106 } else if (m_idHelperSvc->isRpc(id)) {
1107 const MuonGM::RpcReadoutElement* rpcDetEl = dynamic_cast<const MuonGM::RpcReadoutElement*>(ele);
1108 if (!rpcDetEl) { return std::make_pair(0, 0);}
1109 const double halfLength = 0.5 * rpcDetEl->StripLength(false); // eta-strip
1110 return std::make_pair(halfLength, halfLength);
1111 } else if (m_idHelperSvc->isTgc(id)) {
1112 const MuonGM::TgcReadoutElement* tgcDetEl = dynamic_cast<const MuonGM::TgcReadoutElement*>(ele);
1113 if (!tgcDetEl) {return std::make_pair(0.,0.);}
1114 const double halfLength = 0.5 * tgcDetEl->gangCentralWidth(m_idHelperSvc->tgcIdHelper().gasGap(id), m_idHelperSvc->tgcIdHelper().channel(id));
1115 return std::make_pair(halfLength, halfLength);
1116 } else if (m_idHelperSvc->issTgc(id)) {
1117 const MuonGM::sTgcReadoutElement* stgcDetEl = dynamic_cast<const MuonGM::sTgcReadoutElement*>(ele);
1118 if (!stgcDetEl || !stgcDetEl->getDesign(id)) {return std::make_pair(0.,0.);}
1119 const double halfLength = 0.5 * stgcDetEl->getDesign(id)->channelLength(m_idHelperSvc->stgcIdHelper().channel(id));
1120 return std::make_pair(halfLength, halfLength);
1121
1122 } else if (m_idHelperSvc->isMM(id)) {
1123 const MuonGM::MMReadoutElement* mmDetEl = dynamic_cast<const MuonGM::MMReadoutElement*>(ele);
1124 if (mmDetEl) {
1125 return std::make_pair(mmDetEl->stripActiveLengthLeft(id) ,
1126 mmDetEl->stripActiveLengthRight(id)); // components along the local Y axis
1127 }
1128 }
1129 return std::make_pair(0.,0.);
1130 }
double stripLength(int chamberLayer, int measuresPhi, int stripNumber, double &epsilon) const
double stripActiveLengthRight(const Identifier &id) const
double stripActiveLengthLeft(const Identifier &id) const
double getActiveTubeLength(const int tubeLayer, const int tube) const
double StripLength(bool measphi) const
returns the strip length for the phi or eta plane
double gangCentralWidth(int gasGap, int gang) const
Returns the length of the central wire in the gang.
const MuonChannelDesign * getDesign(const Identifier &id) const
returns the MuonChannelDesign class for the given identifier
double channelLength(int channel) const
STRIPS ONLY: calculate channel length for a given strip number.

◆ getMaterial()

bool Muon::MooTrackFitter::getMaterial ( const Trk::TrackParameters & pars,
FitterData & fitterData ) const
private

get material

◆ getMinMaxPhi()

bool Muon::MooTrackFitter::getMinMaxPhi ( FitterData & fitterData) const
private

calculate the minimum and maximum phi value a track could have to pass all eta channels

Definition at line 1131 of file MooTrackFitter.cxx.

1131 {
1132 double phiStart = fitterData.etaHits.front()->globalPosition().phi();
1133 double phiOffset = 0.;
1134 double phiRange = 0.75 * M_PI;
1135 double phiRange2 = 0.25 * M_PI;
1136 if (phiStart > phiRange || phiStart < -phiRange)
1137 phiOffset = 2 * M_PI;
1138 else if (phiStart > -phiRange2 && phiStart < phiRange2)
1139 phiOffset = M_PI;
1140
1141 double phiMin = -999.;
1142 double phiMax = 999.;
1143
1144 for (const Trk::MeasurementBase* meas :fitterData.etaHits) {
1145
1146 const Trk::RIO_OnTrack* rot = dynamic_cast<const Trk::RIO_OnTrack*>(meas);
1147 if (!rot) {
1148 const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(meas);
1149 // if also to a crot we cannot create a fake phi hit
1150 if (!crot || crot->containedROTs().empty()) continue;
1151 rot = crot->containedROTs().front();
1152 }
1153
1154 if (!rot) {
1155 ATH_MSG_WARNING(" Measurement not a ROT ");
1156 continue;
1157 }
1158
1159 Identifier id = rot->identify();
1160 const Trk::Surface& surf = meas->associatedSurface();
1161 double x = rot->localParameters()[Trk::locX];
1162
1163 // distinguishing left-right just to treat the asymmetry of the active region in MM chambers
1164 // getElementHalfLengths
1165 auto [halfLengthL, halfLengthR] = getElementHalfLengths(id, rot->detectorElement());
1166
1167 Amg::Vector2D lpLeft(x, -halfLengthL);
1168 const Amg::Vector3D gposLeft = surf.localToGlobal(lpLeft);
1169 double phiLeft = gposLeft.phi();
1170
1171 Amg::Vector2D lpRight(x, halfLengthR);
1172 const Amg::Vector3D gposRight = surf.localToGlobal(lpRight);
1173 double phiRight = gposRight.phi();
1174
1175 if (phiOffset > 1.5 * M_PI) {
1176 if (phiLeft < 0) phiLeft = phiOffset + phiLeft;
1177 if (phiRight < 0) phiRight = phiOffset + phiRight;
1178 } else if (phiOffset > 0.) {
1179 phiLeft = phiLeft + phiOffset;
1180 phiRight = phiRight + phiOffset;
1181 }
1182
1183 bool leftSmaller = phiLeft < phiRight;
1184
1185 double phiMinMeas = leftSmaller ? phiLeft : phiRight;
1186 double phiMaxMeas = leftSmaller ? phiRight : phiLeft;
1187 double orgPhiMin = phiMinMeas;
1188 double orgPhiMax = phiMaxMeas;
1189
1190 if (phiOffset > 1.5 * M_PI) {
1191 if (orgPhiMin > M_PI) orgPhiMin = orgPhiMin - phiOffset;
1192 if (orgPhiMax > M_PI) orgPhiMax = orgPhiMax - phiOffset;
1193 } else if (phiOffset > 0.) {
1194 orgPhiMin = orgPhiMin - phiOffset;
1195 orgPhiMax = orgPhiMax - phiOffset;
1196 }
1197
1198 if (phiMinMeas > phiMin) { phiMin = phiMinMeas; }
1199 if (phiMaxMeas < phiMax) { phiMax = phiMaxMeas; }
1200 }
1201 if (phiMin < -998 || phiMax > 998) {
1202 ATH_MSG_WARNING(" Could not determine minimum and maximum phi ");
1203 return false;
1204 }
1205
1206 double diffPhi = phiMax - phiMin;
1207 double avePhi = phiMin + 0.5 * diffPhi;
1208
1209 ATH_MSG_VERBOSE("Phi ranges: min " << phiMin << " max " << phiMax << " average phi " << avePhi);
1210
1211 if (diffPhi < 0) {
1212 if (std::abs(diffPhi) > m_openingAngleCut) {
1213 ATH_MSG_VERBOSE(" Inconsistent min/max, rejecting track ");
1214 return false;
1215 }
1216 }
1217
1218 if (!fitterData.phiHits.empty()) {
1219 for (const Trk::MeasurementBase* meas : fitterData.phiHits) {
1220 const double minPhi = std::min(phiMin, phiMax);
1221 const double maxPhi = std::max(phiMin, phiMax);
1222 double phiMeas = meas->globalPosition().phi();
1223 if (phiOffset > 1.5 * M_PI) {
1224 if (phiMeas < 0.) phiMeas = phiOffset + phiMeas;
1225 } else if (phiOffset > 0.) {
1226 phiMeas = phiMeas + phiOffset;
1227 }
1228 double diffMin = phiMeas - minPhi;
1229 double diffMax = phiMeas - maxPhi;
1230 if (diffMin < 0. || diffMax > 0.) {
1231 if (diffMin < -m_openingAngleCut || diffMax > m_openingAngleCut) {
1232 ATH_MSG_VERBOSE(" Phi hits inconsistent with min/max, rejecting track: phi meas " << phiMeas);
1233 return false;
1234 }
1235 }
1236 }
1237 }
1238
1239 if (phiOffset > 1.5 * M_PI) {
1240 if (phiMax > M_PI) phiMax = phiMax - phiOffset;
1241 if (phiMin > M_PI) phiMin = phiMin - phiOffset;
1242 if (avePhi > M_PI) avePhi = avePhi - phiOffset;
1243 } else if (phiOffset > 0.) {
1244 phiMax = phiMax - phiOffset;
1245 phiMin = phiMin - phiOffset;
1246 avePhi = avePhi - phiOffset;
1247 }
1248
1249 fitterData.avePhi = avePhi;
1250 fitterData.phiMin = phiMin;
1251 fitterData.phiMax = phiMax;
1252
1253 return true;
1254 }
#define M_PI
#define x
Gaudi::Property< double > m_openingAngleCut
virtual const Amg::Vector3D & globalPosition() const =0
Interface method to get the global Position.
virtual void localToGlobal(const Amg::Vector2D &locp, const Amg::Vector3D &mom, Amg::Vector3D &glob) const =0
Specified by each surface type: LocalToGlobal method without dynamic memory allocation.
phiRange
Filling Phi ranges.
@ locX
Definition ParamDefs.h:37

◆ hasPhiConstrain() [1/2]

unsigned int Muon::MooTrackFitter::hasPhiConstrain ( MooTrackFitter::FitterData & fitterData) const
private

check whether data has sufficient phi constraints

Definition at line 977 of file MooTrackFitter.cxx.

977 {
978 // check distance between first and last hit to determine whether we need additional phi constrainst
979
980 if ((fitterData.firstEntry->containsChamber(ChIndex::CSS) ||
981 fitterData.firstEntry->containsChamber(ChIndex::CSL)) &&
982 !fitterData.secondEntry->phiHits().empty())
983 return 2;
984
985 unsigned int nphiConstraints = fitterData.phiHits.size();
986 // count SL overlap as one phi constraint
987 // if( fitterData.numberOfSLOverlaps() > 0 ) {
988 // nphiConstraints += fitterData.numberOfSLOverlaps();
989 // ATH_MSG_VERBOSE(" track has small/large overlaps " << fitterData.numberOfSLOverlaps() );
990 // }else if( (fitterData.numberOfSmallChambers() > 0 && fitterData.numberOfLargeChambers() > 0 ) ){
991 // nphiConstraints += 1;
992 // ATH_MSG_VERBOSE(" track has small and large chambers " );
993 // }
994
995 double distanceMin = 400.;
996 double distance = 0.;
997 // we need at least two phis
998 if (fitterData.phiHits.size() > 1) {
999 // assume the hits to be sorted
1000 const Amg::Vector3D& gposFirstPhi = fitterData.phiHits.front()->globalPosition();
1001 const Amg::Vector3D& gposLastPhi = fitterData.phiHits.back()->globalPosition();
1002 double distFirstEtaPhi =
1003 (fitterData.measurements.front()->globalPosition() - fitterData.phiHits.front()->globalPosition()).mag();
1004 double distLastEtaPhi = (fitterData.measurements.back()->globalPosition() - fitterData.phiHits.back()->globalPosition()).mag();
1005
1006 // calculate difference between hits
1007 Amg::Vector3D globalDistance = gposLastPhi - gposFirstPhi;
1008
1009 // calculate 'projective' distance
1010 distance = fitterData.hasEndcap ? std::abs(globalDistance.z()) : globalDistance.perp();
1011
1012 // if the distance between the first and last phi hit is smaller than 1000. count as 1 phi hit
1013 if (distance < distanceMin || distFirstEtaPhi > 1000 || distLastEtaPhi > 1000) {
1014 nphiConstraints -= fitterData.phiHits.size(); // subtract phi hits as they should only count as one phi hit
1015 nphiConstraints += 1; // add one phi hit
1016 ATH_MSG_VERBOSE(" distance between phi hits too small, updating phi constraints ");
1017 } else {
1018 ATH_MSG_VERBOSE(" distance between phi hits sufficient, no fake hits needed ");
1019 }
1020 }
1021 if (msgLvl(MSG::DEBUG)) {
1022 msg(MSG::DEBUG) << MSG::DEBUG << " Check phi: " << std::endl
1023 << " | nphi hits | distance | SL station overlaps | small ch | large ch | nphiConstraints " << std::endl
1024 << std::setw(12) << fitterData.phiHits.size() << std::setw(11) << (int)distance << std::setw(22)
1025 << fitterData.numberOfSLOverlaps() << std::setw(11) << fitterData.numberOfSmallChambers() << std::setw(11)
1026 << fitterData.numberOfLargeChambers() << std::setw(18) << nphiConstraints << endmsg;
1027 }
1028
1029 return nphiConstraints;
1030 }
Scalar perp() const
perp method - perpendicular length
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space

◆ hasPhiConstrain() [2/2]

unsigned int Muon::MooTrackFitter::hasPhiConstrain ( Trk::Track * track) const
private

check whether data has sufficient phi constraints

Definition at line 1032 of file MooTrackFitter.cxx.

1032 {
1033 std::map<MuonStationIndex::StIndex, StationPhiData> stationDataMap;
1034
1035 // Get a MuonTrackSummary.
1036 const Trk::TrackSummary* summary = track->trackSummary();
1037 Trk::MuonTrackSummary muonSummary;
1038 if (summary) {
1039 if (summary->muonTrackSummary()) {
1040 muonSummary = *summary->muonTrackSummary();
1041 } else {
1042 Trk::TrackSummary tmpSum(*summary);
1043 m_trackSummaryTool->addDetailedTrackSummary(*track, tmpSum);
1044 if (tmpSum.muonTrackSummary()) muonSummary = *(tmpSum.muonTrackSummary());
1045 }
1046 } else {
1047 Trk::TrackSummary tmpSummary;
1048 m_trackSummaryTool->addDetailedTrackSummary(*track, tmpSummary);
1049 if (tmpSummary.muonTrackSummary()) muonSummary = *(tmpSummary.muonTrackSummary());
1050 }
1051
1052 std::vector<Trk::MuonTrackSummary::ChamberHitSummary>::const_iterator chit = muonSummary.chamberHitSummary().begin();
1053 std::vector<Trk::MuonTrackSummary::ChamberHitSummary>::const_iterator chit_end = muonSummary.chamberHitSummary().end();
1054 for (; chit != chit_end; ++chit) {
1055 // get station data
1056 const Identifier& chId = chit->chamberId();
1057 MuonStationIndex::StIndex stIndex = m_idHelperSvc->stationIndex(chId);
1058 StationPhiData& stData = stationDataMap[stIndex];
1059 if (chit->isMdt()) {
1060 if (m_idHelperSvc->isSmallChamber(chId))
1061 ++stData.nSmallChambers;
1062 else
1063 ++stData.nLargeChambers;
1064 } else {
1065 if (chit->phiProjection().nhits) ++stData.nphiHits;
1066 }
1067 }
1068
1069 unsigned int phiConstraints = 0;
1070 unsigned int stationsWithSmall = 0;
1071 unsigned int stationsWithLarge = 0;
1072
1073 std::map<MuonStationIndex::StIndex, StationPhiData>::iterator sit = stationDataMap.begin();
1074 std::map<MuonStationIndex::StIndex, StationPhiData>::iterator sit_end = stationDataMap.end();
1075 for (; sit != sit_end; ++sit) {
1076 StationPhiData& stData = sit->second;
1077
1078 // count all stations with phi hits as phi constraint
1079 phiConstraints += stData.nphiHits;
1080
1081 if (stData.nSmallChambers > 0 && stData.nLargeChambers > 0)
1082 ++phiConstraints;
1083 else if (stData.nSmallChambers > 0)
1084 ++stationsWithSmall;
1085 else if (stData.nLargeChambers > 0)
1086 ++stationsWithLarge;
1087 }
1088
1089 if (stationsWithSmall > 0 && stationsWithLarge > 0) { ++phiConstraints; }
1090
1091 return phiConstraints;
1092 }
ToolHandle< Trk::ITrackSummaryHelperTool > m_trackSummaryTool
const std::vector< ChamberHitSummary > & chamberHitSummary() const
access to the vector of chamber hit summaries on the track
const MuonTrackSummary * muonTrackSummary() const
returns a pointer to the MuonTrackSummary if available

◆ initialize()

StatusCode Muon::MooTrackFitter::initialize ( )

initialize method, method taken from bass-class AlgTool

Definition at line 57 of file MooTrackFitter.cxx.

57 {
58 ATH_CHECK(m_propagator.retrieve());
59 ATH_CHECK(m_trackSummaryTool.retrieve());
60 ATH_CHECK(m_cleaner.retrieve());
61 ATH_CHECK(m_overlapResolver.retrieve());
62 ATH_CHECK(m_trackFitter.retrieve());
64 ATH_CHECK(m_idHelperSvc.retrieve());
65 ATH_CHECK(m_edmHelperSvc.retrieve());
66 ATH_CHECK(m_hitHandler.retrieve());
67 ATH_CHECK(m_printer.retrieve());
68
69 // Configuration of the material effects
72
74 ATH_CHECK(m_phiHitSelector.retrieve());
75
76 return StatusCode::SUCCESS;
77 }
#define ATH_CHECK
Evaluate an expression and check for errors.
ToolHandle< IMuonSegmentMomentumEstimator > m_momentumEstimator
tool to estimate track momentum
Gaudi::Property< int > m_matEffects
ToolHandle< IMuonTrackToSegmentTool > m_trackToSegmentTool
helper tool to convert tracks into segments
Gaudi::Property< bool > m_slProp
@ NoField
Field is set to 0., 0., 0.,.
@ FullField
Field is set to be realistic, but within a given Volume.

◆ inputHandles()

virtual std::vector< Gaudi::DataHandle * > AthCommonDataStore< AthCommonMsg< AlgTool > >::inputHandles ( ) const
overridevirtualinherited

Return this algorithm's input handles.

We override this to include handle instances from key arrays if they have not yet been declared. See comments on updateVHKA.

◆ interfaceID()

const InterfaceID & Muon::MooTrackFitter::interfaceID ( )
inlinestatic

access to tool interface

Definition at line 90 of file MooTrackFitter.h.

90 {
91 static const InterfaceID IID_MooTrackFitter("Muon::MooTrackFitter", 1, 0);
92 return IID_MooTrackFitter;
93 }

◆ msg()

MsgStream & AthCommonMsg< AlgTool >::msg ( ) const
inlineinherited

Definition at line 24 of file AthCommonMsg.h.

24 {
25 return this->msgStream();
26 }

◆ msgLvl()

bool AthCommonMsg< AlgTool >::msgLvl ( const MSG::Level lvl) const
inlineinherited

Definition at line 30 of file AthCommonMsg.h.

30 {
31 return this->msgLevel(lvl);
32 }

◆ outputHandles()

virtual std::vector< Gaudi::DataHandle * > AthCommonDataStore< AthCommonMsg< AlgTool > >::outputHandles ( ) const
overridevirtualinherited

Return this algorithm's output handles.

We override this to include handle instances from key arrays if they have not yet been declared. See comments on updateVHKA.

◆ phiSeeding()

double Muon::MooTrackFitter::phiSeeding ( const EventContext & ctx,
MooTrackFitter::FitterData & fitterData ) const
private

calculate phi used to for seeding the fit

Definition at line 1312 of file MooTrackFitter.cxx.

1312 {
1313 if (m_cosmics) {
1314 // check whether the first entry is a track, if not consider the second entry for phi seeding
1315 if (!dynamic_cast<const MuPatTrack*>(fitterData.firstEntry)) {
1316 // if second entry is a track, use its phi value
1317 if (dynamic_cast<const MuPatTrack*>(fitterData.secondEntry)) {
1318 ATH_MSG_DEBUG("Using phi of second entry " << fitterData.secondEntry->entryPars().momentum().phi());
1319 return fitterData.secondEntry->entryPars().momentum().phi();
1320 }
1321 }
1322
1323 // add fake phi hit on first and last measurement
1324 const MuPatSegment* segInfo1 = dynamic_cast<const MuPatSegment*>(fitterData.firstEntry);
1325 const MuPatSegment* segInfo2 = dynamic_cast<const MuPatSegment*>(fitterData.secondEntry);
1326 if (segInfo1 && segInfo2 && fitterData.stations.size() == 1 && fitterData.numberOfSLOverlaps() == 1) {
1327 // only perform SL overlap fit for MDT segments
1328 Identifier chId = m_edmHelperSvc->chamberId(*segInfo1->segment);
1329 if (m_idHelperSvc->isMdt(chId)) {
1330 IMuonSegmentInOverlapResolvingTool::SegmentMatchResult result =
1331 m_overlapResolver->matchResult(ctx, *segInfo1->segment, *segInfo2->segment);
1332
1333 if (!result.goodMatch()) {
1334 ATH_MSG_VERBOSE(" Match failed ");
1335 return false;
1336 }
1337 double overlapPhi = result.phiResult.segmentDirection1.phi();
1338 ATH_MSG_DEBUG(" using overlap phi " << overlapPhi);
1339 return overlapPhi;
1340 }
1341 }
1342
1343 // calculate the difference between the segment positions to estimate the direction of the muon
1344 Amg::Vector3D difPos = fitterData.firstEntry->entryPars().position() - fitterData.secondEntry->entryPars().position();
1345 // check whether the new direction is pointing down
1346 if (difPos.y() > 0) difPos *= -1.;
1347
1348 // calculate difference in angle between phi from segment and the phi of the two new segment positions
1349 const double dphi = fitterData.firstEntry->entryPars().momentum().deltaPhi(difPos);
1350 if (std::abs(dphi) > 0.2) {
1351 ATH_MSG_DEBUG("Large diff between phi of segment direction and of position "
1352 << fitterData.firstEntry->entryPars().momentum().phi() << " from pos " << difPos.phi() << " dphi " << dphi);
1353 return difPos.phi();
1354 }
1355
1356 ATH_MSG_DEBUG("Using phi of first entry " << fitterData.firstEntry->entryPars().momentum().phi() << " phi from position "
1357 << dphi);
1358
1359 return fitterData.firstEntry->entryPars().momentum().phi();
1360 }
1361
1362 double phi(0.);
1363 // update parameters if seeding purely with positions
1365 // use eta of vector connecting first/last hit
1366 MooTrackFitter::MeasVec& etaHits = fitterData.etaHits;
1367 Amg::Vector3D difPos = etaHits.back()->globalPosition() - etaHits.front()->globalPosition();
1368 if (difPos.mag() > 3000) {
1369 ATH_MSG_DEBUG("Seeding phi using average phi of eta hits ");
1370 phi = difPos.phi();
1371 return phi;
1372 }
1373 }
1374
1375 // should have at least one phi hit
1376 MooTrackFitter::MeasVec& phiHits = fitterData.phiHits;
1377
1378 if (phiHits.empty()) {
1379 ATH_MSG_DEBUG("No phi hits, using average phi ");
1380 // use average phi value to seed fit
1381 return fitterData.avePhi;
1382 }
1383
1384 // in this case can't do much...
1385 if (phiHits.size() == 1) { return phiHits.front()->globalPosition().phi(); }
1386
1387 // in endcap, if first segment in EI use its direction
1388 const MuPatSegment* segInfo1 = dynamic_cast<const MuPatSegment*>(fitterData.firstEntry);
1389 if (segInfo1 && segInfo1->containsStation(StIndex::EI) && !segInfo1->phiHits().empty()) {
1390 return segInfo1->segment->globalDirection().phi();
1391 }
1392
1393 // in endcap, if first segment in EM use its direction
1394 if (segInfo1 && segInfo1->containsStation(StIndex::EM) && !segInfo1->phiHits().empty()) {
1395 return segInfo1->segment->globalDirection().phi();
1396 }
1397
1398 if (m_seedWithAvePhi) {
1399 // use average phi value to seed fit
1400 MeasCit hit = phiHits.begin();
1401 MeasCit hit_end = phiHits.end();
1402 Amg::Vector3D avePos(0., 0., 0.);
1403 for (; hit != hit_end; ++hit) avePos += (*hit)->globalPosition();
1404 avePos /= phiHits.size();
1405 phi = avePos.phi();
1406 } else {
1407 // use phi of vector connecting first/last hit
1408 Amg::Vector3D difPos = phiHits.back()->globalPosition() - phiHits.front()->globalPosition();
1409 phi = difPos.phi();
1410 }
1411
1412 return phi;
1413 }
Gaudi::Property< bool > m_seedPhiWithEtaHits
MeasVec::const_iterator MeasCit

◆ qOverPFromEntries()

double Muon::MooTrackFitter::qOverPFromEntries ( const EventContext & ctx,
const MuPatCandidateBase & firstEntry,
const MuPatCandidateBase & secondEntry ) const
private

get q/p using angle + position of the two entries

Definition at line 1277 of file MooTrackFitter.cxx.

1277 {
1278 if (m_slFit) return 0;
1279
1280 double qOverP = 0;
1281 // if available take momentum from entries
1282 if (firstEntry.hasMomentum())
1283 return qOverPFromEntry(firstEntry);
1284 else if (secondEntry.hasMomentum())
1285 return qOverPFromEntry(secondEntry);
1286
1287 // no momentum yet, estimate from segments
1288 std::shared_ptr<const MuonSegment> segFirst = segmentFromEntry(ctx, firstEntry);
1289 if (!segFirst) {
1290 ATH_MSG_WARNING(" failed to get segment for first entry, this should not happen ");
1291 return qOverP;
1292 }
1293
1294 std::shared_ptr<const MuonSegment> segSecond = segmentFromEntry(ctx, secondEntry);
1295 if (!segSecond) {
1296 ATH_MSG_WARNING(" failed to get segment for second entry, this should not happen ");
1297 return qOverP;
1298 }
1299
1300 std::vector<const MuonSegment*> segments{segFirst.get(), segSecond.get()};
1301
1302 double momentum{1.};
1303 m_momentumEstimator->fitMomentumVectorSegments(ctx, segments, momentum);
1304 // momentum = restrictedMomentum(momentum);
1305
1306 if (momentum == 0.) return 0.;
1307
1308 qOverP = 1. / momentum;
1309 return qOverP;
1310 }
static double qOverPFromEntry(const MuPatCandidateBase &entry)
get q/p from entry
std::shared_ptr< const MuonSegment > segmentFromEntry(const EventContext &ctx, const MuPatCandidateBase &entry) const
get segment from entry

◆ qOverPFromEntry()

double Muon::MooTrackFitter::qOverPFromEntry ( const MuPatCandidateBase & entry)
staticprivate

get q/p from entry

Definition at line 1273 of file MooTrackFitter.cxx.

1273 {
1274 return entry.entryPars().charge() / entry.entryPars().momentum().mag();
1275 }

◆ refit() [1/2]

std::unique_ptr< Trk::Track > Muon::MooTrackFitter::refit ( const EventContext & ctx,
const MuPatTrack & trkCan ) const

refit a MuPatTrack

Definition at line 116 of file MooTrackFitter.cxx.

116 {
117
118 // internal representation of the track in fitter
119 FitterData fitterData;
120
121 // copy hit list
122 fitterData.hitList = trkCan.hitList();
123
124 // extract hits from hit list and add them to fitterData
125 if (!extractData(fitterData, true)) return nullptr;
126
127 // create start parameters
128 const Trk::Perigee* pp = trkCan.track().perigeeParameters();
129 if (!pp) return nullptr;
130
131 // fit track
132 std::unique_ptr<Trk::Track> track = fit(ctx, *pp, fitterData.measurements, Trk::muon, false);
133
134 if (track) {
135 // clean and evaluate track
136 std::set<Identifier> excludedChambers;
137 std::unique_ptr<Trk::Track> cleanTrack = cleanAndEvaluateTrack(ctx, *track, excludedChambers);
138 if (cleanTrack && !(*cleanTrack->perigeeParameters() == *track->perigeeParameters())) track.swap(cleanTrack);
139 } else {
140 ATH_MSG_DEBUG(" Fit failed ");
141 }
142 return track;
143 }

◆ refit() [2/2]

std::unique_ptr< Trk::Track > Muon::MooTrackFitter::refit ( const EventContext & ctx,
const Trk::Track & track ) const

refit a track

Definition at line 145 of file MooTrackFitter.cxx.

145 {
146 if (msgLvl(MSG::DEBUG)) {
147 const Trk::TrackStates* states = track.trackStateOnSurfaces();
148 int nStates = 0;
149 if (states) nStates = states->size();
150 msg(MSG::DEBUG) << MSG::DEBUG << "refit: fitting track with hits: " << nStates;
151 if (msgLvl(MSG::VERBOSE)) { msg(MSG::VERBOSE) << std::endl << m_printer->printMeasurements(track); }
152 msg(MSG::DEBUG) << endmsg;
153 }
154 // fit track
155 std::unique_ptr<Trk::Track> newTrack = m_trackFitter->fit(ctx,track, false, m_ParticleHypothesis);
156
157 if (newTrack) {
158 // clean and evaluate track
159 std::set<Identifier> excludedChambers;
160 std::unique_ptr<Trk::Track> cleanTrack = cleanAndEvaluateTrack(ctx, *newTrack, excludedChambers);
161
162 if (cleanTrack) {
163 // check whether cleaner returned same track, if not delete old track
164 if (!(*cleanTrack->perigeeParameters() == *newTrack->perigeeParameters())) newTrack.swap(cleanTrack);
165 } else {
166 ATH_MSG_DEBUG(" Refit failed, rejected by cleaner ");
167 newTrack.reset();
168 }
169 } else {
170 ATH_MSG_DEBUG(" Refit failed ");
171 }
172
173 return newTrack;
174 }
DataVector< const Trk::TrackStateOnSurface > TrackStates

◆ removeSegmentOutliers()

void Muon::MooTrackFitter::removeSegmentOutliers ( FitterData & fitterData) const
private

Definition at line 1985 of file MooTrackFitter.cxx.

1985 {
1986 if (fitterData.startPars->momentum().mag() < 4000.) return;
1987
1988 std::set<Identifier> removedIdentifiers;
1989 if (fitterData.firstEntry) cleanEntry(*fitterData.firstEntry, removedIdentifiers);
1990 if (fitterData.secondEntry) cleanEntry(*fitterData.secondEntry, removedIdentifiers);
1991
1992 ATH_MSG_DEBUG(" removing hits " << removedIdentifiers.size());
1993
1994 for (const Identifier& id : removedIdentifiers) {
1995 ATH_MSG_VERBOSE("Remove hit "<<m_idHelperSvc->toString(id));
1996 m_hitHandler->remove(id, fitterData.hitList);
1997 }
1998 }
void cleanEntry(const MuPatCandidateBase &entry, std::set< Identifier > &removedIdentifiers) const

◆ renounce()

std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > AthCommonDataStore< AthCommonMsg< AlgTool > >::renounce ( T & h)
inlineprotectedinherited

Definition at line 380 of file AthCommonDataStore.h.

381 {
382 h.renounce();
384 }
std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > renounce(T &h)

◆ renounceArray()

void AthCommonDataStore< AthCommonMsg< AlgTool > >::renounceArray ( SG::VarHandleKeyArray & handlesArray)
inlineprotectedinherited

remove all handles from I/O resolution

Definition at line 364 of file AthCommonDataStore.h.

364 {
366 }

◆ restrictedMomentum()

double Muon::MooTrackFitter::restrictedMomentum ( double momentum)
static

impose upper and lower bound on momentum

Definition at line 1589 of file MooTrackFitter.cxx.

1589 {
1590 // restrict range of momenta to 2 GeV / 10 GeV
1591 if (momentum > 0) {
1592 if (momentum > 20000.)
1593 momentum = 20000.;
1594 else if (momentum < 2000)
1595 momentum = 2000;
1596 } else {
1597 if (momentum < -20000.)
1598 momentum = -20000.;
1599 else if (momentum > -2000.)
1600 momentum = -2000.;
1601 }
1602
1603 return momentum;
1604 }

◆ segmentFromEntry()

std::shared_ptr< const MuonSegment > Muon::MooTrackFitter::segmentFromEntry ( const EventContext & ctx,
const MuPatCandidateBase & entry ) const
private

get segment from entry

Definition at line 1256 of file MooTrackFitter.cxx.

1256 {
1257 // if track entry use first segment
1258 const MuPatTrack* trkEntry = dynamic_cast<const MuPatTrack*>(&entry);
1259 if (trkEntry) {
1260 std::shared_ptr<MuonSegment> seg{m_trackToSegmentTool->convert(ctx, trkEntry->track())};
1261 return seg;
1262 }
1263
1264 // if segment entry use segment directly
1265 const MuPatSegment* segEntry = dynamic_cast<const MuPatSegment*>(&entry);
1266 if (segEntry) {
1267 return std::shared_ptr<const MuonSegment> {segEntry->segment, Unowned()};
1268 }
1269
1270 return nullptr;
1271 }

◆ splitTrack()

std::pair< std::unique_ptr< Trk::Track >, std::unique_ptr< Trk::Track > > Muon::MooTrackFitter::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 extrapolated to the muon entry record using the MuonTrackExtrapolationTool.

It uses the double perigee to spot the tracks to be split.

Definition at line 2000 of file MooTrackFitter.cxx.

2000 {
2001
2002 // access TSOS of track
2003 const Trk::TrackStates* oldTSOT = track.trackStateOnSurfaces();
2004 if (!oldTSOT) return std::make_pair<std::unique_ptr<Trk::Track>, std::unique_ptr<Trk::Track>>(nullptr, nullptr);
2005
2006 // check whether the perigee is expressed at the point of closes approach or at muon entry
2007 const Trk::Perigee* perigee = track.perigeeParameters();
2008 if (perigee) {
2009 bool atIP = std::abs(perigee->position().dot(perigee->momentum().unit())) < 10;
2010 if (atIP) {
2011 ATH_MSG_DEBUG(" track extressed at perigee, cannot split it ");
2012 return std::make_pair<std::unique_ptr<Trk::Track>, std::unique_ptr<Trk::Track>>(nullptr, nullptr);
2013 }
2014 }
2015
2016 // loop over content input track and count perigees
2017 unsigned int nperigees(0);
2019 Trk::TrackStates::const_iterator tit_end = oldTSOT->end();
2020 for (; tit != tit_end; ++tit) {
2021 // look whether state is a perigee
2022 if ((*tit)->type(Trk::TrackStateOnSurface::Perigee) && dynamic_cast<const Trk::Perigee*>((*tit)->trackParameters()))
2023 ++nperigees;
2024 }
2025 if (nperigees != 2) {
2026 ATH_MSG_DEBUG(" Number of perigees is not one, cannot split it " << nperigees);
2027 return std::make_pair<std::unique_ptr<Trk::Track>, std::unique_ptr<Trk::Track>>(nullptr, nullptr);
2028 }
2029
2030 struct TrackContent {
2031 TrackContent() : firstParameters(nullptr), tsos(), track() {}
2032 const Trk::TrackParameters* firstParameters;
2033 std::vector<const Trk::TrackStateOnSurface*> tsos;
2034 std::unique_ptr<Trk::Track> track;
2035 std::set<MuonStationIndex::StIndex> stations;
2036 };
2037
2038 // store content of split tracks
2039 TrackContent firstTrack;
2040 firstTrack.tsos.reserve(oldTSOT->size());
2041
2042 TrackContent secondTrack;
2043 secondTrack.tsos.reserve(oldTSOT->size());
2044
2045 // keep track of the current set that is being filled
2046 TrackContent* currentTrack = &firstTrack;
2047
2048 // count perigees on track
2049 nperigees = 0;
2050
2051 // loop over content input track and extract the content of the two split tracks
2052 tit = oldTSOT->begin();
2053 tit_end = oldTSOT->end();
2054 for (; tit != tit_end; ++tit) {
2055 const Trk::TrackParameters* pars = (*tit)->trackParameters();
2056
2057 // look whether state is a perigee
2058 if ((*tit)->type(Trk::TrackStateOnSurface::Perigee) && dynamic_cast<const Trk::Perigee*>(pars)) {
2059 ++nperigees;
2060
2061 if (msgLvl(MSG::DEBUG) && nperigees == 1) msg(MSG::DEBUG) << MSG::DEBUG << " found first perigee on track " << endmsg;
2062
2063 // if this is the second perigee, switch to second part of the track
2064 if (nperigees == 2) {
2065 ATH_MSG_DEBUG(" found second perigee, switch to second track");
2066 currentTrack = &secondTrack;
2067
2068 } else if (nperigees > 2) {
2069 ATH_MSG_WARNING(" Unexpected number of perigees: " << nperigees);
2070 }
2071 }
2072
2073 // we should drop all states inbetween the two perigees
2074 if (nperigees == 1) { ATH_MSG_VERBOSE(" state between the two perigees "); }
2075
2076 // check whether the current TrackContent has firstParameters, if not set them
2077 if (!currentTrack->firstParameters) {
2078 ATH_MSG_VERBOSE(" found first parameters " << m_printer->print(*pars));
2079 currentTrack->firstParameters = pars;
2080 }
2081
2082 // check whether there are track parameters on the current state
2083 if (!pars) {
2084 ATH_MSG_VERBOSE(" adding state without parameters ");
2085 currentTrack->tsos.push_back(*tit);
2086 continue;
2087 }
2088
2089 // check whether state is a measurement, if not continue
2090 const Trk::MeasurementBase* meas = (*tit)->measurementOnTrack();
2091 if (!meas) {
2092 ATH_MSG_VERBOSE(" adding state without measurement " << m_printer->print(*pars));
2093 currentTrack->tsos.push_back(*tit);
2094 continue;
2095 }
2096
2097 // get identifier, if it has no identifier or is not a muon hit continue
2098 Identifier id = m_edmHelperSvc->getIdentifier(*meas);
2099 if (!id.is_valid() || !m_idHelperSvc->isMuon(id)) {
2100 ATH_MSG_VERBOSE(" adding state with measurement without valid identifier " << m_printer->print(*pars));
2101 currentTrack->tsos.push_back(*tit);
2102 continue;
2103 }
2104
2105 if (nperigees == 1) ATH_MSG_WARNING(" found muon measurement inbetween the two perigees, this should not happen ");
2106
2107 // add station index for MDT and CSC hits
2108 if (!m_idHelperSvc->isTrigger(id)) currentTrack->stations.insert(m_idHelperSvc->stationIndex(id));
2109
2110 ATH_MSG_VERBOSE(" adding " << m_printer->print(*meas));
2111
2112 currentTrack->tsos.push_back(*tit);
2113 }
2114
2115 if (firstTrack.firstParameters)
2116 ATH_MSG_DEBUG(" first track content: states " << firstTrack.tsos.size() << " stations " << firstTrack.stations.size() << endmsg
2117 << " first pars " << m_printer->print(*firstTrack.firstParameters));
2118
2119 else if (secondTrack.firstParameters)
2120 ATH_MSG_DEBUG(" second track content: states " << secondTrack.tsos.size() << " stations " << secondTrack.stations.size()
2121 << endmsg << " first pars " << m_printer->print(*secondTrack.firstParameters));
2122
2123 // check whether both tracks have start parameters and sufficient stations
2124 if ((firstTrack.firstParameters && firstTrack.stations.size() > 1) &&
2125 (secondTrack.firstParameters && secondTrack.stations.size() > 1)) {
2126 ATH_MSG_DEBUG(" track candidate can be split, trying to fit split tracks ");
2127 // fit the two tracks
2128 firstTrack.track = fitSplitTrack(ctx, *firstTrack.firstParameters, firstTrack.tsos);
2129 if (firstTrack.track) {
2130 ATH_MSG_DEBUG(" fitted first track, trying second ");
2131
2132 secondTrack.track = fitSplitTrack(ctx, *secondTrack.firstParameters, secondTrack.tsos);
2133
2134 if (secondTrack.track) {
2135 ATH_MSG_DEBUG(" fitted second track ");
2136
2137 } else {
2138 ATH_MSG_DEBUG(" failed to fit second track ");
2139 firstTrack.track.reset();
2140 }
2141 } else {
2142 ATH_MSG_DEBUG(" failed to fit first track ");
2143 }
2144 }
2145
2146 return std::make_pair<std::unique_ptr<Trk::Track>, std::unique_ptr<Trk::Track>>(std::move(firstTrack.track),
2147 std::move(secondTrack.track));
2148 }
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.
std::unique_ptr< Trk::Track > fitSplitTrack(const EventContext &ctx, const Trk::TrackParameters &startPars, const std::vector< const Trk::TrackStateOnSurface * > &tsos) const
construct a track from a list of TSOS and a start parameters
@ Perigee
This represents a perigee, and so will contain a Perigee object only.

◆ sysInitialize()

virtual StatusCode AthCommonDataStore< AthCommonMsg< AlgTool > >::sysInitialize ( )
overridevirtualinherited

Perform system initialization for an algorithm.

We override this to declare all the elements of handle key arrays at the end of initialization. See comments on updateVHKA.

Reimplemented in asg::AsgMetadataTool, AthCheckedComponent< AthAlgTool >, AthCheckedComponent<::AthAlgTool >, and DerivationFramework::CfAthAlgTool.

◆ sysStart()

virtual StatusCode AthCommonDataStore< AthCommonMsg< AlgTool > >::sysStart ( )
overridevirtualinherited

Handle START transition.

We override this in order to make sure that conditions handle keys can cache a pointer to the conditions container.

◆ thetaSeeding()

double Muon::MooTrackFitter::thetaSeeding ( const MuPatCandidateBase & entry,
MooTrackFitter::MeasVec & etaHits ) const
private

calculate theta used for seeding the fit

Definition at line 1415 of file MooTrackFitter.cxx.

1415 {
1416 // should have at least one eta hit
1417 if (etaHits.empty()) {
1418 ATH_MSG_WARNING(" cannot calculate eta seed from empty vector ");
1419 return 0;
1420 }
1421
1422 double theta(0.);
1424 theta = entry.entryPars().momentum().theta();
1425 } else {
1426 // in this case can't do much...
1427 if (etaHits.size() == 1) {
1428 theta = etaHits.front()->globalPosition().theta();
1429 } else {
1430 // use eta of vector connecting first/last hit
1431 Amg::Vector3D difPos = etaHits.back()->globalPosition() - etaHits.front()->globalPosition();
1432 theta = difPos.theta();
1433 }
1434 }
1435
1436 return theta;
1437 }
Gaudi::Property< bool > m_seedWithSegmentTheta

◆ updateVHKA()

void AthCommonDataStore< AthCommonMsg< AlgTool > >::updateVHKA ( Gaudi::Details::PropertyBase & )
inlineinherited

Definition at line 308 of file AthCommonDataStore.h.

308 {
309 // debug() << "updateVHKA for property " << p.name() << " " << p.toString()
310 // << " size: " << m_vhka.size() << endmsg;
311 for (auto &a : m_vhka) {
313 for (auto k : keys) {
314 k->setOwner(this);
315 }
316 }
317 }
std::vector< SG::VarHandleKeyArray * > m_vhka

◆ validMomentum()

bool Muon::MooTrackFitter::validMomentum ( const Trk::TrackParameters & pars) const
private

check whether mometum of start parameter is ok

Definition at line 1871 of file MooTrackFitter.cxx.

1871 {
1872 const double p = pars.momentum().mag();
1873 if (p < m_pThreshold) {
1874 ATH_MSG_DEBUG(" momentum below threshold: momentum " << pars.momentum().mag() << " p " << pars.momentum().perp());
1875 return false;
1876 }
1877 return true;
1878 }
Gaudi::Property< double > m_pThreshold

Member Data Documentation

◆ m_allowFirstFit

Gaudi::Property<bool> Muon::MooTrackFitter::m_allowFirstFit {this, "AllowFirstFitResult", false, "Return the result of the prefit is final fit fails"}
private

Definition at line 297 of file MooTrackFitter.h.

297{this, "AllowFirstFitResult", false, "Return the result of the prefit is final fit fails"};

◆ m_chi2Cut

Gaudi::Property<double> Muon::MooTrackFitter::m_chi2Cut {this, "ReducedChi2Cut", 100., "minimum chi2/ndof for a track to be accepted"}
private

Definition at line 312 of file MooTrackFitter.h.

312{this, "ReducedChi2Cut", 100., "minimum chi2/ndof for a track to be accepted"};

◆ m_cleaner

ToolHandle<IMuonTrackCleaner> Muon::MooTrackFitter::m_cleaner {this, "TrackCleaner", "Muon::MuonTrackCleaner/MuonTrackCleaner"}
private

Definition at line 284 of file MooTrackFitter.h.

284{this, "TrackCleaner", "Muon::MuonTrackCleaner/MuonTrackCleaner"};

◆ m_cleanPhiHits

Gaudi::Property<bool> Muon::MooTrackFitter::m_cleanPhiHits {this, "CleanPhiHits", true, "Special flag to switch off phi hit cleaning"}
private

Definition at line 301 of file MooTrackFitter.h.

301{this, "CleanPhiHits", true, "Special flag to switch off phi hit cleaning"};

◆ m_cosmics

Gaudi::Property<bool> Muon::MooTrackFitter::m_cosmics {this, "Cosmics", false, "Special treatment for cosmics"}
private

Definition at line 300 of file MooTrackFitter.h.

300{this, "Cosmics", false, "Special treatment for cosmics"};

◆ m_detStore

StoreGateSvc_t AthCommonDataStore< AthCommonMsg< AlgTool > >::m_detStore
privateinherited

Pointer to StoreGate (detector store by default)

Definition at line 393 of file AthCommonDataStore.h.

◆ m_edmHelperSvc

ServiceHandle<IMuonEDMHelperSvc> Muon::MooTrackFitter::m_edmHelperSvc
private
Initial value:
{
this, "edmHelper", "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc",
"Handle to the service providing the IMuonEDMHelperSvc interface"}

multi purpose helper tool

Definition at line 273 of file MooTrackFitter.h.

273 {
274 this, "edmHelper", "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc",
275 "Handle to the service providing the IMuonEDMHelperSvc interface"};

◆ m_evtStore

StoreGateSvc_t AthCommonDataStore< AthCommonMsg< AlgTool > >::m_evtStore
privateinherited

Pointer to StoreGate (event store by default)

Definition at line 390 of file AthCommonDataStore.h.

◆ m_hitHandler

PublicToolHandle<MuPatHitTool> Muon::MooTrackFitter::m_hitHandler {this, "HitTool", "Muon::MuPatHitTool/MuPatHitTool"}
private

hit handler

Definition at line 263 of file MooTrackFitter.h.

263{this, "HitTool", "Muon::MuPatHitTool/MuPatHitTool"};

◆ m_idHelperSvc

ServiceHandle<Muon::IMuonIdHelperSvc> Muon::MooTrackFitter::m_idHelperSvc {this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}
private

Definition at line 272 of file MooTrackFitter.h.

272{this, "MuonIdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"};

◆ m_magFieldProperties

Trk::MagneticFieldProperties Muon::MooTrackFitter::m_magFieldProperties {Trk::FullField}
private

magnetic field properties

Definition at line 271 of file MooTrackFitter.h.

◆ m_matEffects

Gaudi::Property<int> Muon::MooTrackFitter::m_matEffects {this, "MatEffects", 2, "type of material interaction in extrapolation"}
private

Definition at line 268 of file MooTrackFitter.h.

268{this, "MatEffects", 2, "type of material interaction in extrapolation"};

◆ m_momentumEstimator

ToolHandle<IMuonSegmentMomentumEstimator> Muon::MooTrackFitter::m_momentumEstimator
private
Initial value:
{
this, "SegmentMomentum", "MuonSegmentMomentum/MuonSegmentMomentum"}

tool to estimate track momentum

Definition at line 264 of file MooTrackFitter.h.

264 {
265 this, "SegmentMomentum", "MuonSegmentMomentum/MuonSegmentMomentum"};

◆ m_nfailedExtractCleaning

std::atomic_uint Muon::MooTrackFitter::m_nfailedExtractCleaning {0}
mutableprivate

Definition at line 318 of file MooTrackFitter.h.

318{0};

◆ m_nfailedExtractInital

std::atomic_uint Muon::MooTrackFitter::m_nfailedExtractInital {0}
mutableprivate

Definition at line 315 of file MooTrackFitter.h.

315{0};

◆ m_nfailedExtractPrecise

std::atomic_uint Muon::MooTrackFitter::m_nfailedExtractPrecise {0}
mutableprivate

Definition at line 323 of file MooTrackFitter.h.

323{0};

◆ m_nfailedFakeInitial

std::atomic_uint Muon::MooTrackFitter::m_nfailedFakeInitial {0}
mutableprivate

Definition at line 319 of file MooTrackFitter.h.

319{0};

◆ m_nfailedFakePrecise

std::atomic_uint Muon::MooTrackFitter::m_nfailedFakePrecise {0}
mutableprivate

Definition at line 324 of file MooTrackFitter.h.

324{0};

◆ m_nfailedFitPrecise

std::atomic_uint Muon::MooTrackFitter::m_nfailedFitPrecise {0}
mutableprivate

Definition at line 325 of file MooTrackFitter.h.

325{0};

◆ m_nfailedMinMaxPhi

std::atomic_uint Muon::MooTrackFitter::m_nfailedMinMaxPhi {0}
mutableprivate

Definition at line 316 of file MooTrackFitter.h.

316{0};

◆ m_nfailedParsInital

std::atomic_uint Muon::MooTrackFitter::m_nfailedParsInital {0}
mutableprivate

Definition at line 317 of file MooTrackFitter.h.

317{0};

◆ m_nfailedTubeFit

std::atomic_uint Muon::MooTrackFitter::m_nfailedTubeFit {0}
mutableprivate

Definition at line 320 of file MooTrackFitter.h.

320{0};

◆ m_nfits

std::atomic_uint Muon::MooTrackFitter::m_nfits {0}
mutableprivate

Definition at line 314 of file MooTrackFitter.h.

314{0};

◆ m_nlowMomentum

std::atomic_uint Muon::MooTrackFitter::m_nlowMomentum {0}
mutableprivate

Definition at line 322 of file MooTrackFitter.h.

322{0};

◆ m_noPerigee

std::atomic_uint Muon::MooTrackFitter::m_noPerigee {0}
mutableprivate

Definition at line 321 of file MooTrackFitter.h.

321{0};

◆ m_nsuccess

std::atomic_uint Muon::MooTrackFitter::m_nsuccess {0}
mutableprivate

Definition at line 326 of file MooTrackFitter.h.

326{0};

◆ m_openingAngleCut

Gaudi::Property<double> Muon::MooTrackFitter::m_openingAngleCut
private
Initial value:
{this, "OpeningAngleCut", 0.3,
"cut on the maximum difference in phi between measurements on the track"}

Definition at line 308 of file MooTrackFitter.h.

308 {this, "OpeningAngleCut", 0.3,
309 "cut on the maximum difference in phi between measurements on the track"};

◆ m_overlapResolver

ToolHandle<IMuonSegmentInOverlapResolvingTool> Muon::MooTrackFitter::m_overlapResolver
private
Initial value:
{
this, "SegmentInOverlapTool", "Muon::MuonSegmentInOverlapResolvingTool/MuonSegmentInOverlapResolvingTool"}

Definition at line 285 of file MooTrackFitter.h.

285 {
286 this, "SegmentInOverlapTool", "Muon::MuonSegmentInOverlapResolvingTool/MuonSegmentInOverlapResolvingTool"};

◆ m_ParticleHypothesis

Trk::ParticleHypothesis Muon::MooTrackFitter::m_ParticleHypothesis
private

nomen est omen

Definition at line 269 of file MooTrackFitter.h.

◆ m_patRecInfo

Trk::TrackInfo::TrackPatternRecoInfo Muon::MooTrackFitter::m_patRecInfo {Trk::TrackInfo::Moore}
private

◆ m_phiHitSelector

ToolHandle<IMuonHitSelector> Muon::MooTrackFitter::m_phiHitSelector
private
Initial value:
{this, "PhiHitSelector",
"MuonPhiHitSelector/MuonPhiHitSelector"}

tool to clean phi hits

Definition at line 282 of file MooTrackFitter.h.

282 {this, "PhiHitSelector",
283 "MuonPhiHitSelector/MuonPhiHitSelector"};

◆ m_phiHitsMax

Gaudi::Property<unsigned int> Muon::MooTrackFitter::m_phiHitsMax
private
Initial value:
{this, "MaxPatternPhiHits", 40,
"If more than maximum number of phi hits on pattern, no hits will be added"}

Definition at line 302 of file MooTrackFitter.h.

302 {this, "MaxPatternPhiHits", 40,
303 "If more than maximum number of phi hits on pattern, no hits will be added"};

◆ m_preciseFirstStation

Gaudi::Property<bool> Muon::MooTrackFitter::m_preciseFirstStation
private
Initial value:
{this, "UsePreciseHitsInFirstStation", false,
"use precise hits in first station to stabalise the fit"}

Definition at line 305 of file MooTrackFitter.h.

305 {this, "UsePreciseHitsInFirstStation", false,
306 "use precise hits in first station to stabalise the fit"};

◆ m_preCleanChi2Cut

Gaudi::Property<double> Muon::MooTrackFitter::m_preCleanChi2Cut
private
Initial value:
{this, "PreCleaningReducedChi2Cut", 500.,
"minimum chi2/ndof for a track to be passed to cleaner"}

Definition at line 310 of file MooTrackFitter.h.

310 {this, "PreCleaningReducedChi2Cut", 500.,
311 "minimum chi2/ndof for a track to be passed to cleaner"};

◆ m_printer

PublicToolHandle<MuonEDMPrinterTool> Muon::MooTrackFitter::m_printer
private
Initial value:
{this, "MuonPrinterTool",
"Muon::MuonEDMPrinterTool/MuonEDMPrinterTool"}

tool to print out EDM objects

Definition at line 276 of file MooTrackFitter.h.

276 {this, "MuonPrinterTool",
277 "Muon::MuonEDMPrinterTool/MuonEDMPrinterTool"};

◆ m_propagator

ToolHandle<Trk::IPropagator> Muon::MooTrackFitter::m_propagator
private
Initial value:
{this, "Propagator",
"Trk::RungeKuttaPropagator/AtlasRungeKuttaPropagator"}

propagator

Definition at line 260 of file MooTrackFitter.h.

260 {this, "Propagator",
261 "Trk::RungeKuttaPropagator/AtlasRungeKuttaPropagator"};

◆ m_pThreshold

Gaudi::Property<double> Muon::MooTrackFitter::m_pThreshold
private
Initial value:
{this, "PThreshold", 500.,
"Momentum cut-off. Seeds below the threshold will not be fitted"}

Definition at line 298 of file MooTrackFitter.h.

298 {this, "PThreshold", 500.,
299 "Momentum cut-off. Seeds below the threshold will not be fitted"}; //<!

◆ m_runOutlier

Gaudi::Property<Trk::RunOutlierRemoval> Muon::MooTrackFitter::m_runOutlier {this, "RunOutlier", false, "Switch whether to run outlier logics or not"}
private

Definition at line 267 of file MooTrackFitter.h.

267{this, "RunOutlier", false, "Switch whether to run outlier logics or not"};

◆ m_seedAtStartOfTrack

Gaudi::Property<bool> Muon::MooTrackFitter::m_seedAtStartOfTrack {this, "SeedAtStartOfTrack", true, "Provide seed parameters at the start of the track"}
private

Definition at line 304 of file MooTrackFitter.h.

304{this, "SeedAtStartOfTrack", true, "Provide seed parameters at the start of the track"};

◆ m_seedPhiWithEtaHits

Gaudi::Property<bool> Muon::MooTrackFitter::m_seedPhiWithEtaHits {this, "SeedPhiWithEtaHits", false, "Seed phi from positions first last eta hit"}
private

Definition at line 294 of file MooTrackFitter.h.

294{this, "SeedPhiWithEtaHits", false, "Seed phi from positions first last eta hit"};

◆ m_seedWithAvePhi

Gaudi::Property<bool> Muon::MooTrackFitter::m_seedWithAvePhi {this, "SeedWithAvePhi", true, "Seed with average phi of all phi hits"}
private

Definition at line 293 of file MooTrackFitter.h.

293{this, "SeedWithAvePhi", true, "Seed with average phi of all phi hits"};

◆ m_seedWithSegmentTheta

Gaudi::Property<bool> Muon::MooTrackFitter::m_seedWithSegmentTheta {this, "SeedWithSegmentTheta", true, "Seed with theta connecting first + last eta hit"}
private

Definition at line 292 of file MooTrackFitter.h.

292{this, "SeedWithSegmentTheta", true, "Seed with theta connecting first + last eta hit"};

◆ m_slFit

Gaudi::Property<bool> Muon::MooTrackFitter::m_slFit {this, "SLFit", true, "Perform sl fit"}
private

Definition at line 290 of file MooTrackFitter.h.

290{this, "SLFit", true, "Perform sl fit"};

◆ m_slProp

Gaudi::Property<bool> Muon::MooTrackFitter::m_slProp {this, "SLProp", false, "Enable straight line propagation"}
private

Definition at line 291 of file MooTrackFitter.h.

291{this, "SLProp", false, "Enable straight line propagation"};

◆ m_trackFitter

ToolHandle<Trk::ITrackFitter> Muon::MooTrackFitter::m_trackFitter {this, "Fitter", "Trk::GlobalChi2Fitter/MCTBFitter"}
private

fitter

Definition at line 262 of file MooTrackFitter.h.

262{this, "Fitter", "Trk::GlobalChi2Fitter/MCTBFitter"};

◆ m_trackSummaryTool

ToolHandle<Trk::ITrackSummaryHelperTool> Muon::MooTrackFitter::m_trackSummaryTool
private
Initial value:
{
this, "TrackSummaryTool", "Muon::MuonTrackSummaryHelperTool/MuonTrackSummaryHelperTool"}

Definition at line 287 of file MooTrackFitter.h.

287 {
288 this, "TrackSummaryTool", "Muon::MuonTrackSummaryHelperTool/MuonTrackSummaryHelperTool"}; //<! muon track summary helper

◆ m_trackToSegmentTool

ToolHandle<IMuonTrackToSegmentTool> Muon::MooTrackFitter::m_trackToSegmentTool
private
Initial value:
{
this, "TrackToSegmentTool",
"Muon::MuonTrackToSegmentTool/MuonTrackToSegmentTool"}

helper tool to convert tracks into segments

Definition at line 278 of file MooTrackFitter.h.

278 {
279 this, "TrackToSegmentTool",
280 "Muon::MuonTrackToSegmentTool/MuonTrackToSegmentTool"};

◆ m_usePreciseHits

Gaudi::Property<bool> Muon::MooTrackFitter::m_usePreciseHits {this, "UsePreciseHits", false, "Use actual measurement error"}
private

Definition at line 295 of file MooTrackFitter.h.

295{this, "UsePreciseHits", false, "Use actual measurement error"};

◆ m_usePrefit

Gaudi::Property<bool> Muon::MooTrackFitter::m_usePrefit {this, "UsePrefit", true, "Use prefit"}
private

Definition at line 296 of file MooTrackFitter.h.

296{this, "UsePrefit", true, "Use prefit"};

◆ m_varHandleArraysDeclared

bool AthCommonDataStore< AthCommonMsg< AlgTool > >::m_varHandleArraysDeclared
privateinherited

Definition at line 399 of file AthCommonDataStore.h.

◆ m_vhka

std::vector<SG::VarHandleKeyArray*> AthCommonDataStore< AthCommonMsg< AlgTool > >::m_vhka
privateinherited

Definition at line 398 of file AthCommonDataStore.h.


The documentation for this class was generated from the following files: