ATLAS Offline Software
Loading...
Searching...
No Matches
CaloCluster_OnTrackBuilder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
7#include "xAODEgamma/Egamma.h"
9
11
13#include "TrkSurfaces/Surface.h"
14
16
17#include "GaudiKernel/SystemOfUnits.h"
19
20namespace {
21
22// cluster E in MeV and absEta returns
23// quick phi variance parametrization
24// sigma^2 where sigma is mrad
25double
26phiVariance(double clusterE, double absEta)
27{
28 // convert from MeV to GeV
29 const double EinGeV = clusterE * 1e-3;
30 // sigma phi = b/E (+) c
31 // E in GeV
32 // and (+) sum in quadrature
33 // we return variance so
34 // sigma^2 = (b*b)/(E*E) + c*c
35 //
36 if (absEta < 0.1) {
37 return (0.14 * 0.14) / (EinGeV * EinGeV) + 0.001 * 0.001;
38 }
39 if (absEta < 0.6) {
40 return (0.15 * 0.15) / (EinGeV * EinGeV) + 0.001 * 0.001;
41 }
42 if (absEta < 0.8) {
43 return (0.19 * 0.19) / (EinGeV * EinGeV) + 0.001 * 0.001;
44 }
45 if (absEta < 1.15) {
46 return (0.26 * 0.26) / (EinGeV * EinGeV) + 0.001 * 0.001;
47 }
48 if (absEta < 1.37) {
49 return (0.36 * 0.36) / (EinGeV * EinGeV) + 0.001 * 0.001;
50 }
51 if (absEta < 1.52) {
52 return (0.52 * 0.52) / (EinGeV * EinGeV) + 0.003 * 0.003;
53 }
54 if (absEta < 1.81) {
55 return (0.46 * 0.46) / (EinGeV * EinGeV) + 0.004 * 0.004;
56 }
57 if (absEta < 2.01) {
58 return (0.35 * 0.35) / (EinGeV * EinGeV) + 0.004 * 0.004;
59 }
60 if (absEta < 2.37) {
61 return (0.38 * 0.38) / (EinGeV * EinGeV) + 0.005 * 0.005;
62 }
63 return (0.47 * 0.47) / (EinGeV * EinGeV) + 0.006 * 0.006;
64}
65}
66
68 const std::string& n,
69 const IInterface* p)
70 : AthAlgTool(t, n, p)
71{
72 declareInterface<ICaloCluster_OnTrackBuilder>(this);
73}
74
75StatusCode
77{
78 m_eg_resol = std::make_unique<eg_resolution>("run2_R21_v1");
79 ATH_CHECK(m_calosurf.retrieve());
80 ATH_CHECK(m_caloMgrKey.initialize());
81 return StatusCode::SUCCESS;
82}
83
84StatusCode
86{
87 return StatusCode::SUCCESS;
88}
89
90std::unique_ptr<Trk::CaloCluster_OnTrack>
92 const EventContext& ctx,
93 const xAOD::CaloCluster* cluster,
94 int charge) const
95{
96
97 ATH_MSG_DEBUG("Building Trk::CaloCluster_OnTrack");
98
100 ATH_MSG_WARNING("CaloCluster_OnTrackBuilder is configured incorrectly");
101 return nullptr;
102 }
103
104 if (!cluster) {
105 return nullptr;
106 }
107
109 const CaloDetDescrManager* caloDDMgr = *caloMgrHandle;
110 std::unique_ptr<Trk::Surface> surface = getCaloSurface(cluster, caloDDMgr);
111
112 if (!surface) {
113 return nullptr;
114 }
115
117 getClusterLocalParameters(cluster, surface.get(), charge);
118
119 Amg::MatrixX em = getClusterErrorMatrix(cluster, *surface, charge);
120
121 return std::make_unique<Trk::CaloCluster_OnTrack>(std::move(lp), std::move(em), *surface);
122
123}
124
125std::unique_ptr<Trk::Surface>
127 const xAOD::CaloCluster* cluster,
128 const CaloDetDescrManager* caloDDMgr) const
129{
130
131 std::unique_ptr<Trk::Surface> destinationSurface = nullptr;
132
133 // Determine if we want to extrapolate to the barrel or endcap. If in the
134 // crack choose the detector with largest amount of energy in the second
135 // sampling layer
136 if (xAOD::EgammaHelpers::isBarrel(cluster)) {
137 destinationSurface.reset(m_calosurf->CreateUserSurface(
138 CaloCell_ID::EMB2, 0., cluster->eta(), caloDDMgr));
139 } else {
140 destinationSurface.reset(m_calosurf->CreateUserSurface(
141 CaloCell_ID::EME2, 0., cluster->eta(), caloDDMgr));
142 }
143 return destinationSurface;
144}
145
148 const xAOD::CaloCluster* cluster,
149 const Trk::Surface* surf,
150 int charge) const
151{
152
153 Amg::Vector3D surfRefPoint = surf->globalReferencePoint();
154 double eta = cluster->eta();
155 double phi = cluster->phi();
156 double clusterQoverE = cluster->e() != 0 ? (double)charge / cluster->e() : 0;
157
158 if (xAOD::EgammaHelpers::isBarrel(cluster)) {
159 // Two corindate in a cyclinder are
160 // Trk::locRPhi = 0 (ie phi)
161 // Trk::locZ = 1(ie z)
162 double r = surfRefPoint.perp();
163 std::vector<Trk::DefinedParameter> defPar;
164 if (m_useClusterPhi) {
166 defPar.push_back(locRPhi);
167 }
168 if (m_useClusterEta) {
169 double theta = 2 * atan(exp(-eta)); // -log(tan(theta/2));
170 double tantheta = tan(theta);
171 double z = tantheta == 0 ? 0. : r / tantheta;
173 defPar.push_back(locZ);
174 }
175 if (m_useClusterEnergy) {
176 Trk::DefinedParameter qOverP(clusterQoverE, Trk::qOverP);
177 defPar.push_back(qOverP);
178 }
179 return {defPar};
180 }
181 // Local paramters of a disk are
182 // Trk::locR = 0
183 // Trk::locPhi = 1
184 double z = surfRefPoint.z();
185 std::vector<Trk::DefinedParameter> defPar;
186 if (m_useClusterEta) {
187 double theta = 2 * atan(exp(-eta)); // -log(tan(theta/2));
188 double tantheta = tan(theta);
189 double r = z * tantheta;
191 defPar.push_back(locR);
192 }
193 if (m_useClusterPhi) {
195 defPar.push_back(locPhi);
196 }
197 if (m_useClusterEnergy) {
198 Trk::DefinedParameter qOverP(clusterQoverE, Trk::qOverP);
199 defPar.push_back(qOverP);
200 }
201
202 return {defPar};
203}
204
207 const xAOD::CaloCluster* cluster,
208 const Trk::Surface& surf,
209 int) const
210{
211 int matrixSize = static_cast<int>(m_useClusterEta) +
212 static_cast<int>(m_useClusterPhi) +
213 static_cast<int>(m_useClusterEnergy);
214 Amg::MatrixX covMatrix(matrixSize, matrixSize);
215 covMatrix.setZero();
216
217 const double clusterE = cluster->e();
218 const double clusterEta = cluster->eta();
219
220 // variance in phi from calorimeter phi resolution
221 double phivariance = phiVariance(clusterE, std::abs(clusterEta));
222 if (phivariance < 1e-5) {
223 // Avoid going too small for very high E
224 phivariance = 1e-5;
225 }
226
227 // q over p variance from sigmaE/E (calo energy resolution)
228 const double sigmaP_over_P = m_eg_resol->getResolution(0, // electron
229 clusterE,
230 clusterEta,
231 2 // 90% quantile
232 );
233 const double qOverP = 1. / clusterE;
234 const double qOverP_variance =
235 (qOverP * qOverP) * (sigmaP_over_P * sigmaP_over_P);
236
237 // Variance in Z
238 // sigma ~ 20 mm large error
239 // As currently we do not want to rely
240 // on the eta side of the cluster.
241 constexpr double zvariance = 400;
242
243 if (xAOD::EgammaHelpers::isBarrel(cluster)) {
244 // The two coordinates for a cyclinder are
245 // Trk::locRPhi = 0 (ie phi)
246 // Trk::locZ = 1(ie z)
247 const Amg::Vector3D& surfRefPoint = surf.globalReferencePoint();
248 double r = surfRefPoint.perp();
249 double r2 = r * r;
250 int indexCount(0);
251 if (m_useClusterPhi) {
252 covMatrix(indexCount, indexCount) = phivariance * r2;
253 ++indexCount;
254 }
255 if (m_useClusterEta) {
256 covMatrix(indexCount, indexCount) = zvariance;
257 ++indexCount;
258 }
259 if (m_useClusterEnergy) {
260 covMatrix(indexCount, indexCount) = qOverP_variance;
261 ++indexCount;
262 }
263 } else {
264 // Local paramters of a disk are
265 // Trk::locR = 0
266 // Trk::locPhi = 1
267 int indexCount(0);
268
269 if (m_useClusterEta) {
270 covMatrix(indexCount, indexCount) = zvariance;
271 ++indexCount;
272 }
273 if (m_useClusterPhi) {
274 covMatrix(indexCount, indexCount) = phivariance;
275 ++indexCount;
276 }
277 if (m_useClusterEnergy) {
278 covMatrix(indexCount, indexCount) = qOverP_variance;
279 ++indexCount;
280 }
281 }
282
283 return covMatrix;
284}
285
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
Scalar theta() const
theta method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
double charge(const T &p)
Definition AtlasPID.h:997
Calculate total energy, position, etc. for a given layer of a cluster.
Handle class for reading from StoreGate.
#define z
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Trk::LocalParameters getClusterLocalParameters(const xAOD::CaloCluster *cluster, const Trk::Surface *surf, int charge) const
Gaudi::Property< bool > m_useClusterEta
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloMgrKey
std::unique_ptr< Trk::Surface > getCaloSurface(const xAOD::CaloCluster *cluster, const CaloDetDescrManager *caloDDMgr) const
Amg::MatrixX getClusterErrorMatrix(const xAOD::CaloCluster *cluster, const Trk::Surface &surf, int charge) const
ToolHandle< ICaloSurfaceBuilder > m_calosurf
Tool to build calorimeter layer surfaces.
virtual StatusCode finalize() override final
virtual StatusCode initialize() override final
Gaudi::Property< bool > m_useClusterEnergy
Which cluster measurements to use in order to add constraints by default we are interested in the one...
Gaudi::Property< bool > m_useClusterPhi
virtual std::unique_ptr< Trk::CaloCluster_OnTrack > buildClusterOnTrack(const EventContext &ctx, const xAOD::CaloCluster *cl, int charge=0) const override final
std::unique_ptr< eg_resolution > m_eg_resol
helper for returning energy resolution
This class provides the client interface for accessing the detector description information common to...
Abstract Base Class for tracking surfaces.
virtual const Amg::Vector3D & globalReferencePoint() const
Returns a global reference point on the surface, for PlaneSurface, StraightLineSurface,...
virtual double eta() const
The pseudorapidity ( ) of the particle.
virtual double e() const
The total energy of the particle.
virtual double phi() const
The azimuthal angle ( ) of the particle.
int r
Definition globals.cxx:22
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Eigen::Matrix< double, 3, 1 > Vector3D
@ locR
Definition ParamDefs.h:44
@ locRPhi
Definition ParamDefs.h:40
@ qOverP
perigee
Definition ParamDefs.h:67
@ locZ
local cylindrical
Definition ParamDefs.h:42
@ locPhi
local polar
Definition ParamDefs.h:45
std::pair< double, ParamDefs > DefinedParameter
Typedef to of a std::pair<double, ParamDefs> to identify a passed-through double as a specific type o...
bool isBarrel(const xAOD::Egamma *eg)
return true if the cluster is in the barrel
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.