ATLAS Offline Software
Loading...
Searching...
No Matches
EMConversionBuilder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3*/
4
5/********************************************************************
6NAME: EMConversionBuilder.cxx
7PACKAGE: offline/Reconstruction/egamma/egammaRec
8
9AUTHORS: D. Zerwas, B. Lenzi , C. Anastopoulos
10CREATED: Jul, 2005
11CHANGES: Mar, 2014 (BL) xAOD migration
12CHANGES: 2020 (CA) Athena MT migration
13
14PURPOSE: subAlgorithm which creates an EMConversion object.
15
16********************************************************************/
17
18// INCLUDE HEADER FILES:
19
20#include "EMConversionBuilder.h"
22#include "GaudiKernel/EventContext.h"
27#include "xAODTracking/Vertex.h"
29
30// END OF HEADER FILES INCLUDE
31
33
34namespace {
46bool
47ConvVxSorter(const xAOD::Vertex& vx1, const xAOD::Vertex& vx2)
48{
53
54 if (convType1 != convType2) {
55 // Different conversion type, preference to vertices with Si tracks
56 int nSi1 = xAOD::EgammaHelpers::numberOfSiTracks(convType1);
57 int nSi2 = xAOD::EgammaHelpers::numberOfSiTracks(convType2);
58 if (nSi1 != nSi2)
59 return nSi1 > nSi2;
60
61 // Same number of Si tracks: either 0 or 1 (Si+TRT vs. Si single)
62 // For 1 Si track, preference to Si+TRT
63 if (nSi1 != 0)
64 return convType1 == xAOD::EgammaParameters::doubleSiTRT;
65
66 // No Si track, preference to doubleTRT over single TRT
67 return convType1 == xAOD::EgammaParameters::doubleTRT;
68 }
69
70 // Same conversion type, preference to lower radius
71 return (vx1.position().perp() < vx2.position().perp());
72}
73} // end of namespace
74
75using namespace xAOD::EgammaParameters;
76
78 const std::string& name,
79 const IInterface* parent)
80 : AthAlgTool(type, name, parent)
81{
82
83 // declare interface
84 declareInterface<IEMConversionBuilder>(this);
85}
86
87StatusCode
89{
90
91 ATH_MSG_DEBUG("Initializing EMConversionBuilder");
92
94
95 // the extrapolation tool
96 if (m_extrapolationTool.retrieve().isFailure()) {
97 ATH_MSG_ERROR("Cannot retrieve extrapolationTool " << m_extrapolationTool);
98 return StatusCode::FAILURE;
99 }
100 ATH_MSG_DEBUG("Retrieved extrapolationTool " << m_extrapolationTool);
101
102 return StatusCode::SUCCESS;
103}
104
105StatusCode
106EMConversionBuilder::executeRec(const EventContext& ctx, egammaRec* egRec) const
107{
108 // retrieve Conversion Container
109
111 ctx);
112
113 // only for serial running; remove for MT
114 ATH_CHECK(conversions.isValid());
115 // reset the vertices
116 std::vector<ElementLink<xAOD::VertexContainer>> vertices;
117 egRec->setVertices(vertices);
118 ATH_CHECK(vertexExecute(ctx, egRec, conversions.cptr()));
119 return StatusCode::SUCCESS;
120}
121
122StatusCode
124 const EventContext& ctx,
125 egammaRec* egRec,
126 const xAOD::VertexContainer* conversions) const
127{
128
129 if (!egRec || !conversions) {
131 "trackExecute: NULL pointer to egammaRec or VertexContainer");
132 return StatusCode::SUCCESS;
133 }
134
135 static const SG::AuxElement::Accessor<float> accetaAtCalo("etaAtCalo");
136 static const SG::AuxElement::Accessor<float> accphiAtCalo("phiAtCalo");
137
138 float etaAtCalo(0);
139 float phiAtCalo(0);
140 for (unsigned int iVtx = 0; iVtx < conversions->size(); ++iVtx) {
141
142 const xAOD::Vertex* vertex = conversions->at(iVtx);
143 // Check if vertex was already decorated with etaAtCalo, phiAtCalo
144 if (accetaAtCalo.isAvailable(*vertex) &&
145 accphiAtCalo.isAvailable(*vertex)) {
146 etaAtCalo = accetaAtCalo(*vertex);
147 phiAtCalo = accphiAtCalo(*vertex);
148 }
149 // check extrapolation, skip vertex in case of failure
150 else if (!m_extrapolationTool->getEtaPhiAtCalo(
151 ctx, vertex, &etaAtCalo, &phiAtCalo)) {
152 continue;
153 }
154 const xAOD::CaloCluster* cluster = egRec->caloCluster();
155 if (!passPtAndEoverP(ctx, *vertex, *cluster)) {
156 continue;
157 }
158 if (!m_extrapolationTool->matchesAtCalo(
159 cluster, vertex, etaAtCalo, phiAtCalo)) {
160 continue;
161 }
162 const ElementLink<xAOD::VertexContainer> vertexLink(*conversions, iVtx, ctx);
163
164 // If this is the best (or the first) vertex, push front and keep deltaEta,
165 // deltaPhi
166 if (!egRec->getNumberOfVertices() ||
167 ConvVxSorter(*vertex, *egRec->vertex())) {
168 egRec->pushFrontVertex(vertexLink);
169 egRec->setDeltaEtaVtx(cluster->etaBE(2) - etaAtCalo);
170 egRec->setDeltaPhiVtx(P4Helpers::deltaPhi(cluster->phiBE(2), phiAtCalo));
171 } else { // Not the best vertex, push back
172 egRec->pushBackVertex(vertexLink);
173 }
174 }
175 return StatusCode::SUCCESS;
176}
177
178bool
180 const xAOD::Vertex& vertex,
181 const xAOD::CaloCluster& cluster) const
182{
183 Amg::Vector3D momentum =
184 m_extrapolationTool->getMomentumAtVertex(ctx, vertex);
185 float pt = momentum.perp();
186 float EoverP = cluster.e() / momentum.mag();
187
188 auto convType = xAOD::EgammaHelpers::conversionType(&vertex);
189 bool isSingle = (convType == singleTRT || convType == singleSi);
190 bool isTRT =
191 (convType == singleTRT || convType == xAOD::EgammaParameters::doubleTRT);
192 float EoverPcut = m_maxEoverP_singleTrack *
193 (1 + m_maxEoverP_singleTrack_EtSf * cluster.et() * 1e-3);
194
195 // Check TRT tube hit fraction
196 float tubeHitFraction = getMaxTRTTubeHitFraction(vertex);
197 if (isTRT && tubeHitFraction > m_maxTRTTubeHitFraction) {
198 ATH_MSG_DEBUG("Conversion failed cut on TRT tube hit fraction: "
199 << tubeHitFraction << " vs. " << m_maxTRTTubeHitFraction);
200 return false;
201 }
202
203 bool reject =
204 ((isTRT && m_rejectAllTRT) || (isSingle && pt < m_minPt_singleTrack) ||
205 (!isSingle && pt < m_minSumPt_double) ||
206 (isSingle && EoverP > EoverPcut) ||
207 (convType == singleTRT && pt < m_minPt_singleTRT) ||
208 (convType == doubleTRT && pt < m_minSumPt_doubleTRT));
209
210 if (reject) {
211 ATH_MSG_DEBUG("Conversion failed pt or E/p cuts");
212 }
213 return !reject;
214}
215
216float
218{
219 auto getTRTTubeHitFraction = [](const xAOD::TrackParticle* trk) {
220 uint8_t nTRT;
221 uint8_t nTRTTube;
222 if (!trk || !trk->summaryValue(nTRT, xAOD::numberOfTRTHits) || !nTRT)
223 return 0.;
224 return trk->summaryValue(nTRTTube, xAOD::numberOfTRTTubeHits)
225 ? 1. * nTRTTube / nTRT
226 : 0.;
227 };
228
229 float maxTubeHitFraction = 0.;
230 for (unsigned int i = 0; i < vertex.nTrackParticles(); ++i) {
231 if (!vertex.trackParticle(i)) {
232 ATH_MSG_WARNING("NULL pointer to track particle in conversion vertex");
233 } else {
234 float tubeHitFraction = getTRTTubeHitFraction(vertex.trackParticle(i));
235 if (tubeHitFraction > maxTubeHitFraction) {
236 maxTubeHitFraction = tubeHitFraction;
237 }
238 }
239 }
240 return maxTubeHitFraction;
241}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Handle class for reading from StoreGate.
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
const T * at(size_type n) const
Access an element, as an rvalue.
size_type size() const noexcept
Returns the number of elements in the collection.
Gaudi::Property< float > m_minPt_singleTrack
minimum pT for single-track conversion vertices
float getMaxTRTTubeHitFraction(const xAOD::Vertex &vertex) const
Return the maximum fraction of TRT tube hits among the tracks.
StatusCode vertexExecute(const EventContext &ctx, egammaRec *egRec, const xAOD::VertexContainer *conversions) const
actual implementation method
bool passPtAndEoverP(const EventContext &ctx, const xAOD::Vertex &, const xAOD::CaloCluster &) const
Return true if vertex and cluster pass Pt and E/p cuts.
Gaudi::Property< float > m_maxEoverP_singleTrack
maximum E/p for single track conversion vertices (E is not calibrated)
StatusCode initialize() override final
initialize method
Gaudi::Property< float > m_minSumPt_doubleTRT
minimum sum pT for double TRT track conversion vertices
Gaudi::Property< bool > m_rejectAllTRT
Ignore all conversion vertices that contain exclusively TRT-only tracks.
EMConversionBuilder(const std::string &type, const std::string &name, const IInterface *parent)
Default constructor.
Gaudi::Property< float > m_minSumPt_double
minimum sum pT for double track conversion vertices
Gaudi::Property< float > m_minPt_singleTRT
minimum pT for TRT-only single-track conversion vertices
SG::ReadHandleKey< xAOD::VertexContainer > m_conversionContainerKey
Name of conversion container.
Gaudi::Property< float > m_maxTRTTubeHitFraction
"Maximum fraction of tube hits for vertices with TRT tracks
ToolHandle< IEMExtrapolationTools > m_extrapolationTool
EMExtrapolationTools.
Gaudi::Property< float > m_maxEoverP_singleTrack_EtSf
Scale maxEoverP_singleTrack by 1+sf*Et(cluster)/GeV.
virtual StatusCode executeRec(const EventContext &ctx, egammaRec *egRec) const override final
execute method
SG::Accessor< T, ALLOC > Accessor
Definition AuxElement.h:572
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
Represent an egamma object for internal egamma usage during reconstruction.
Definition egammaRec.h:31
void pushBackVertex(const ElementLink< xAOD::VertexContainer > &vertexElementLink)
Push back another vertex.
Definition egammaRec.cxx:76
void pushFrontVertex(const ElementLink< xAOD::VertexContainer > &vertexElementLink)
Push front another vertex.
Definition egammaRec.cxx:82
const xAOD::Vertex * vertex(size_t index=0) const
Pointer to the xAOD::Vertex/es that match the photon candidate.
Definition egammaRec.cxx:54
void setDeltaPhiVtx(float value)
set deltaPhiVtx
void setVertices(const std::vector< ElementLink< xAOD::VertexContainer > > &links)
set Pointer to the xAOD::vertex/vertices that match the photon candidate
const xAOD::CaloCluster * caloCluster(size_t index=0) const
Pointer to the xAOD::CaloCluster/s that define the electron candidate.
Definition egammaRec.cxx:8
void setDeltaEtaVtx(float value)
set deltaEtaVtx
size_t getNumberOfVertices() const
Return the number xAOD::Vertex/vertices that match the photon candidate.
float phiBE(const unsigned layer) const
Get the phi in one layer of the EM Calo.
virtual double e() const
The total energy of the particle.
float etaBE(const unsigned layer) const
Get the eta in one layer of the EM Calo.
const Amg::Vector3D & position() const
Returns the 3-pos.
Eigen::Matrix< double, 3, 1 > Vector3D
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[
Definition P4Helpers.h:34
std::size_t numberOfSiTracks(const xAOD::Photon *eg)
return the number of Si tracks in the conversion
xAOD::EgammaParameters::ConversionType conversionType(const xAOD::Photon *ph)
return the photon conversion type (see EgammaEnums)
@ singleSi
one track only, with Si hits
@ doubleTRT
two tracks, none with Si hits (TRT only)
@ singleTRT
one track only, no Si hits (TRT only)
@ doubleSiTRT
two tracks, only one with Si hits
setRcore setEtHad setFside pt
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
TrackParticle_v1 TrackParticle
Reference the current persistent version:
VertexContainer_v1 VertexContainer
Definition of the current "Vertex container version".
Vertex_v1 Vertex
Define the latest version of the vertex class.
@ numberOfTRTHits
number of TRT hits [unit8_t].
@ numberOfTRTTubeHits
number of TRT tube hits [unit8_t].