ATLAS Offline Software
Loading...
Searching...
No Matches
MuonExtrapolationTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4// MuonExtrapolationTool.cxx
10#include "TVector2.h"
11#include <memory>
12
13//**********************************************************************
14
15namespace DerivationFramework {
16
17MuonExtrapolationTool::MuonExtrapolationTool(const std::string &t, const std::string& n, const IInterface* p)
18 :
19 base_class(t, n, p)
20{
21}
22
23//**********************************************************************
24
25
27{
28 ATH_CHECK(m_muonContainerName.initialize());
29 ATH_CHECK(m_extrapolator.retrieve());
30 return StatusCode::SUCCESS;
31}
32
33
34//**********************************************************************
35
36bool MuonExtrapolationTool::extrapolateAndDecorateTrackParticle(const xAOD::TrackParticle* particle, float & eta, float & phi, const EventContext& ctx) const
37{
38
39 // decorators used to access or store the information
40 static const SG::AuxElement::Decorator< char > Decorated ("DecoratedPivotEtaPhi");
41 static const SG::AuxElement::Decorator< float > Eta ("EtaTriggerPivot");
42 static const SG::AuxElement::Decorator< float > Phi ("PhiTriggerPivot");
43
44 if (! Decorated.isAvailable(*particle) || !Decorated(*particle)){
45 // in the athena release, we can run the extrapolation if needed
46 const Trk::TrackParameters* pTag = extrapolateToTriggerPivotPlane(*particle, ctx);
47 if(!pTag) {
48 Decorated(*particle) = false;
49 return false;
50 }
51 Eta(*particle) = pTag->position().eta();
52 Phi(*particle) = pTag->position().phi();
53 Decorated(*particle) = true;
54 delete pTag;
55 }
56 // if we get here, the decoration was either already present or just added by us
57 // so we can finally read the values
58 eta = Eta(*particle);
59 phi = Phi(*particle);
60 return true;
61}
62
63//**********************************************************************
64
66{
67 if (dynamic_cast<const xAOD::TruthParticle*>(muon)){
68 ATH_MSG_WARNING("Pivot plane extrapolation not supported for Truth muons!");
69 return 0;
70 }
71 const xAOD::TrackParticle* muonTrack = dynamic_cast<const xAOD::TrackParticle*>(muon);
72 if(!muonTrack && dynamic_cast<const xAOD::Muon*>(muon)) {
73 const xAOD::Muon* theMuon = dynamic_cast<const xAOD::Muon*>(muon);
74 muonTrack = theMuon->trackParticle( xAOD::Muon::MuonSpectrometerTrackParticle );
75 if(!muonTrack) {
76 muonTrack = theMuon->primaryTrackParticle();
77 if(!muonTrack) {
78 muonTrack = theMuon->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
79 }
80 }
81 }
82 if(!muonTrack){
83 ATH_MSG_WARNING("no valid track found for extrapolating the muon to the pivot plane!");
84 }
85 return muonTrack;
86
87}
88
89StatusCode MuonExtrapolationTool::addBranches(const EventContext& ctx) const
90{
92 if (!muonContainer.isValid()) {
93 ATH_MSG_ERROR("Failed to retrieve MuonContainer with name: " << m_muonContainerName.key());
94 return StatusCode::FAILURE;
95 }
96 for (auto muon : *muonContainer) {
98 float eta, phi = 0;
99 if( !extrapolateAndDecorateTrackParticle( track, eta, phi, ctx )){
100 if( muon->pt() > 3500.){
101 //only complain if the muon has sufficient pT to actually reach the pivot plane
102 //extrapolation will often fail for muons with pT < 3500 MeV
103 ATH_MSG_WARNING("Failed to extrapolate+decorate muon with pivot plane coords - Muon params: pt "<<muon->pt()<<", eta "<< muon->eta()<<", phi "<< muon->phi());
104 }
105 }
106 }
107 return StatusCode::SUCCESS;
108}
109
111{
112 // BARREL
113 const Trk::Perigee& perigee = track.perigeeParameters();
114
115 // create the barrel as a cylinder surface centered at 0,0,0
116 Amg::Vector3D barrelCentre(0., 0., 0.);
117 Amg::Transform3D matrix = Amg::Transform3D(Amg::RotationMatrix3D::Identity(), barrelCentre);
118
119 Trk::CylinderSurface* cylinder =
120 new Trk::CylinderSurface(matrix,
123 if (!cylinder) {
124 ATH_MSG_WARNING("extrapolateToTriggerPivotPlane :: new Trk::CylinderSurface failed.");
125 return nullptr;
126 }
127 // and then attempt to extrapolate our track to this surface, checking for the boundaries of the barrel
128 bool boundaryCheck = true;
129 const Trk::Surface* surface = cylinder;
130 const Trk::TrackParameters* p = m_extrapolator->extrapolate(
131 ctx, perigee, *surface, Trk::alongMomentum, boundaryCheck, Trk::muon).release();
132 delete cylinder;
133 // if the extrapolation worked out (so we are in the barrel) we are done and can return the
134 // track parameters at this surface.
135 if (p) return p;
136
137 // if we get here, the muon did not cross the barrel surface
138 // so we assume it is going into the endcap.
139 // ENDCAP
140
141 // After 2 years of using this code, we realised that ATLAS actually has endcaps on both sides ;-)
142 // So better make sure we place our endcap at the correct side of the detector!
143 // Hopefully no-one will ever read this comment...
144 float SignOfEta = track.eta() > 0 ? 1. : -1.;
145
146 Amg::Vector3D endcapCentre(0., 0., m_endcapPivotPlaneZ);
147 // much better!
148 matrix = Amg::Transform3D(Amg::RotationMatrix3D::Identity(), SignOfEta * endcapCentre);
149
150 std::unique_ptr<Trk::DiscSurface> disc =
151 std::make_unique<Trk::DiscSurface>(matrix,
154 if (!disc) {
155 ATH_MSG_WARNING("extrapolateToTriggerPivotPlane :: new Trk::DiscSurface failed.");
156 return nullptr;
157 }
158
159 // for the endcap, we turn off the boundary check, extending the EC infinitely to catch stuff heading for the transition region
160 boundaryCheck = false;
161 surface = disc.get();
162 p = m_extrapolator->extrapolate(
163 ctx, perigee, *surface, Trk::alongMomentum, boundaryCheck, Trk::muon).release();
164 return p;
165}
166}
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
@ Phi
Definition RPCdef.h:8
@ Eta
Definition RPCdef.h:8
xAOD::MuonContainer * muonContainer
MuonExtrapolationTool(const std::string &t, const std::string &n, const IInterface *p)
const xAOD::TrackParticle * getPreferredTrackParticle(const xAOD::IParticle *probe) const
Gaudi::Property< double > m_endcapPivotPlaneMaximumRadius
SG::ReadHandleKey< xAOD::MuonContainer > m_muonContainerName
Gaudi::Property< double > m_endcapPivotPlaneMinimumRadius
virtual StatusCode addBranches(const EventContext &ctx) const
const Trk::TrackParameters * extrapolateToTriggerPivotPlane(const xAOD::TrackParticle &track, const EventContext &ctx) const
run the extrapolation - only available in full athena
PublicToolHandle< Trk::IExtrapolator > m_extrapolator
bool extrapolateAndDecorateTrackParticle(const xAOD::TrackParticle *particle, float &eta, float &phi, const EventContext &ctx) const
SG::Decorator< T, ALLOC > Decorator
Definition AuxElement.h:575
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
Class for a CylinderSurface in the ATLAS detector.
Abstract Base Class for tracking surfaces.
Class providing the definition of the 4-vector interface.
const TrackParticle * primaryTrackParticle() const
Returns a pointer (which should not usually be NULL, but might be if the muon has been stripped of in...
Definition Muon_v1.cxx:396
const TrackParticle * trackParticle(TrackParticleType type) const
Returns a pointer (which can be NULL) to the TrackParticle used in identification of this muon.
Definition Muon_v1.cxx:482
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
THE reconstruction tool.
@ alongMomentum
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
ParametersBase< TrackParametersDim, Charged > TrackParameters
TrackParticle_v1 TrackParticle
Reference the current persistent version:
TruthParticle_v1 TruthParticle
Typedef to implementation.
Muon_v1 Muon
Reference the current persistent version: