ATLAS Offline Software
Loading...
Searching...
No Matches
MuidTrackIsolation.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6// MuidTrackIsolation
7// AlgTool for estimating the number, total charged momentum and most
8// energetic inner detector tracks in a cone surrounding a muon
9//
11
12#include "MuidTrackIsolation.h"
13
14#include <cmath>
15#include <iomanip>
16
18#include "GaudiKernel/SystemOfUnits.h"
23#include "TrkSurfaces/Surface.h"
24#include "TrkTrack/Track.h"
26namespace Rec {
27
29 ATH_MSG_INFO("MuidTrackIsolation::initialize()");
30
31 // get the Tools
32 ATH_CHECK(m_intersector.retrieve());
34 // create the calo barrel surfaces (cylinder) and 2 endcap discs)
35 double radius = 2.0 * Gaudi::Units::meter;
36 double halfLength = 4.0 * Gaudi::Units::meter;
37 Amg::Transform3D transform{Amg::Transform3D::Identity()};
38 m_caloCylinder = std::make_unique<Trk::CylinderSurface>(transform, radius, halfLength);
39
40 // the corresponding max barrel cotTheta
41 m_barrelCotTheta = halfLength / radius;
42
43 // and the forward/backward endcap disks
44 Amg::Transform3D discRotation{Amg::Transform3D::Identity()};
45 Amg::Vector3D forwardDiscPosition(0., 0., halfLength);
46 auto transform1 = std::make_unique<Amg::Transform3D>(discRotation * forwardDiscPosition);
47 m_caloForwardDisc = std::make_unique<Trk::DiscSurface>(*transform1, 0., radius);
48 Amg::Vector3D backwardDiscPosition(0., 0., -halfLength);
49 auto transform2 = std::make_unique<Amg::Transform3D>(discRotation * backwardDiscPosition);
50 m_caloBackwardDisc = std::make_unique<Trk::DiscSurface>(*transform2, 0., radius);
51
52 ATH_CHECK(m_inDetTracksLocation.initialize());
53 ATH_CHECK(m_trackLinkKey.initialize());
54 return StatusCode::SUCCESS;
55 }
56 std::pair<int, double> MuidTrackIsolation::trackIsolation(const EventContext& ctx, double eta, double phi) const {
57 // debug input quantities
58 ATH_MSG_DEBUG(" MuidTrackIsolation:: " << std::setiosflags(std::ios::fixed)
59 << (m_trackExtrapolation ? "applied after extrapolation to calo, " : "applied at perigee, ")
60 << " for muon at calo with eta,phi " << std::setw(8) << std::setprecision(3) << eta
61 << std::setw(8) << std::setprecision(3) << phi);
62
63 // set initial state
64 std::pair<int, double> isolation{0, 0.};
65
66 // retrieve track collection
67 const xAOD::TrackParticleContainer* inDetTracks{};
68 if (!SG::get(inDetTracks, m_inDetTracksLocation, ctx).isSuccess()) {
69 return std::make_pair(0, 0.);
70 }
71
72 // evaluate isolation according to configuration
74 isolation = trackExtrapolated(inDetTracks, eta, phi);
75 } else {
76 isolation = trackVertex(inDetTracks, eta, phi);
77 }
78
79 // debug result
80 ATH_MSG_DEBUG("Found " << isolation.first << std::setiosflags(std::ios::fixed) << " InDet tracks with total momentum "
81 << std::setw(8) << std::setprecision(1) << isolation.second / Gaudi::Units::GeV << " GeV");
82
83 return isolation;
84 }
85
86 std::pair<int, double> MuidTrackIsolation::trackVertex(const xAOD::TrackParticleContainer* inDetTracks, double eta, double phi) const {
87 // set initial state
88 double sumP = 0.;
89 int numberTracks = 0;
90
91 // choose tracks in cone
92 for (const xAOD::TrackParticle* idTrack : *inDetTracks) {
93 const Trk::Track* id = idTrack->track();
94 const Trk::Perigee& perigee = *id->perigeeParameters();
95 if (id->info().trackProperties(Trk::TrackInfo::StraightTrack) || perigee.pT() < m_minPt) continue;
96
97 double inDetPhi = perigee.parameters()[Trk::phi];
98 double inDetEta = perigee.eta();
99
100 double diffEta = std::abs(eta - inDetEta);
101 double diffPhi = xAOD::P4Helpers::deltaPhi(phi, inDetPhi);
102
103 ATH_MSG_DEBUG(std::endl
104 << std::setiosflags(std::ios::fixed) << " Id track: momentum " << std::setw(8) << std::setprecision(1)
105 << perigee.momentum().mag() / Gaudi::Units::GeV << " with perigee eta and difference " << std::setw(8)
106 << std::setprecision(3) << perigee.eta() << std::setw(8) << std::setprecision(3) << diffEta
107 << " and same for phi " << std::setw(8) << std::setprecision(3) << perigee.parameters()[Trk::phi] << std::setw(8)
108 << std::setprecision(3) << diffPhi);
109
110 if ((diffPhi * diffPhi + diffEta * diffEta) > m_trackCone2) continue;
111 ++numberTracks;
112 const double p = perigee.momentum().mag();
113 sumP += p;
114
115 ATH_MSG_VERBOSE("inside cone, track#" << std::setw(3) << numberTracks);
116 }
117
118 return std::make_pair(numberTracks, sumP);
119 }
120
121 std::pair<int, double> MuidTrackIsolation::trackExtrapolated(const xAOD::TrackParticleContainer* inDetTracks, double eta, double phi) const {
122 // set initial state
123 double sumP = 0.;
124 int numberTracks = 0;
125
126 // extrapolate close in eta tracks to calorimeter surface
127 for (const xAOD::TrackParticle* idTrack : *inDetTracks) {
128
129 const Trk::Track* id = idTrack->track();
130 const Trk::Perigee& perigee = *id->perigeeParameters();
131 if (id->info().trackProperties(Trk::TrackInfo::StraightTrack) || perigee.pT() < m_minPt) continue;
132
133 double inDetEta = perigee.eta();
134 if (std::abs(eta - inDetEta) > m_trackCone + m_etaSafetyFactor) continue;
135
136 // track has sufficient momentum and is close in eta:
137 // find intersection at calo surface
138 double qOverP = perigee.parameters()[Trk::qOverP];
140 double cotTheta = std::tan(M_PI_2 - perigee.parameters()[Trk::theta]);
141 Amg::Vector3D direction(std::cos(perigee.parameters()[Trk::phi]), std::sin(perigee.parameters()[Trk::phi]), cotTheta);
142 direction /= direction.mag();
143
144 const Trk::TrackSurfaceIntersection idIntersection(perigee.position(), direction, 0.);
145 const Trk::Surface* surface = m_caloCylinder.get();
146 if (cotTheta > m_barrelCotTheta) {
147 surface = m_caloForwardDisc.get();
148 } else if (cotTheta < -m_barrelCotTheta) {
149 surface = m_caloBackwardDisc.get();
150 }
151 std::optional<Trk::TrackSurfaceIntersection> caloIntersection(
152 m_intersector->intersectSurface(*surface, idIntersection, qOverP));
153
154 // no intersection - should never happen !
155 if (!caloIntersection) {
156 ATH_MSG_DEBUG(" track didn't find intersection !!! "
157 << std::setiosflags(std::ios::fixed) << " Id track: momentum " << std::setw(8) << std::setprecision(1)
158 << perigee.momentum().mag() / Gaudi::Units::GeV << " with initial eta " << std::setw(8)
159 << std::setprecision(3) << perigee.eta() << " and phi " << std::setw(8) << std::setprecision(3)
160 << perigee.parameters()[Trk::phi]);
161
162 continue;
163 }
164
165 double diffEta = eta - caloIntersection->position().eta();
166 double diffPhi = xAOD::P4Helpers::deltaPhi(phi, caloIntersection->position().phi());
167 ATH_MSG_VERBOSE(std::endl
168 << std::setiosflags(std::ios::fixed) << " Id track: momentum " << std::setw(8) << std::setprecision(1)
169 << perigee.momentum().mag() / Gaudi::Units::GeV << " with initial,extrapolated and calo difference for eta "
170 << std::setw(8) << std::setprecision(3) << perigee.eta() << std::setw(8) << std::setprecision(3)
171 << caloIntersection->position().eta() << std::setw(8) << std::setprecision(3) << diffEta << " and phi "
172 << std::setw(8) << std::setprecision(3) << perigee.parameters()[Trk::phi] << std::setw(8)
173 << std::setprecision(3) << caloIntersection->position().phi() << std::setw(8) << std::setprecision(3)
174 << diffPhi);
175
176 // check if inside cone
177 if ((diffPhi * diffPhi + diffEta * diffEta) < m_trackCone2) {
178 ++numberTracks;
179 const double p = perigee.momentum().mag();
180 sumP += p;
181
182 ATH_MSG_VERBOSE(" inside cone, track#" << std::setw(3) << numberTracks);
183 }
184 }
185
186 return std::make_pair(numberTracks, sumP);
187 }
188
189} // namespace Rec
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
std::pair< int, double > trackIsolation(const EventContext &ctx, double eta, double phi) const override
IMuidTrackIsolation interface: get the number of tracks and summed momentum in a cone at the producti...
Gaudi::Property< double > m_minPt
std::unique_ptr< const Trk::Surface > m_caloForwardDisc
std::unique_ptr< const Trk::Surface > m_caloBackwardDisc
Gaudi::Property< double > m_trackCone
ToolHandle< Trk::IIntersector > m_intersector
Gaudi::Property< bool > m_trackExtrapolation
std::pair< int, double > trackVertex(const xAOD::TrackParticleContainer *indetTracks, double eta, double phi) const
std::pair< int, double > trackExtrapolated(const xAOD::TrackParticleContainer *indetTracks, double eta, double phi) const
SG::ReadDecorHandleKey< xAOD::TrackParticleContainer > m_trackLinkKey
std::unique_ptr< const Trk::Surface > m_caloCylinder
StatusCode initialize() override
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_inDetTracksLocation
double eta() const
Access method for pseudorapidity - from momentum.
const Amg::Vector3D & momentum() const
Access method for the momentum.
const Amg::Vector3D & position() const
Access method for the position.
double pT() const
Access method for transverse momentum.
Abstract Base Class for tracking surfaces.
Definition Surface.h:79
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
Gaudi Tools.
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
TrackSurfaceIntersection(const Amg::Vector3D &pos, const Amg::Vector3D &dir, double path)
Constructor.
@ theta
Definition ParamDefs.h:66
@ qOverP
perigee
Definition ParamDefs.h:67
@ phi
Definition ParamDefs.h:75
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[
TrackParticle_v1 TrackParticle
Reference the current persistent version:
TrackParticleContainer_v1 TrackParticleContainer
Definition of the current "TrackParticle container version".