ATLAS Offline Software
Loading...
Searching...
No Matches
CorrectPFOTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
5// CorrectPFOTool.cxx
6
10
11#include <cmath>
12
13CorrectPFOTool::CorrectPFOTool(const std::string &name):
15 m_weightPFOTool("",this) {
16
17 // Configuration
18 declareProperty("WeightPFOTool", m_weightPFOTool, "Name of tool that extracts the cPFO weights.");
19 declareProperty("InputIsEM", m_inputIsEM = true, "True if neutral PFOs are EM scale clusters.");
20 declareProperty("CalibratePFO", m_calibrate = false, "True if LC calibration should be applied to EM PFOs.");
21 declareProperty("CorrectNeutral", m_correctneutral = true, "True to use the neutral component of PFlow.");
22 declareProperty("CorrectCharged", m_correctcharged = true, "True if use the charged component of PFlow.");
23 declareProperty("UseChargedWeights",m_useChargedWeights = true, "True if we make use of weighting scheme for charged PFO");
24 declareProperty("DoByVertex", m_doByVertex = false, "True to add vertex-by-vertex corrections for neutral PFOs");
25
26 // Input properties
27 declareProperty("VertexContainerKey",
28 m_vertexContainer_key="PrimaryVertices",
29 "Datahandle key for the primary vertex container");
30}
31
34 ATH_MSG_ERROR("This tool is configured to do nothing!");
35 return StatusCode::FAILURE;
36 }
38 ATH_MSG_ERROR("CorrectPFOTool requires PFO inputs. It cannot operate on objects of type "
39 << m_inputType);
40 return StatusCode::FAILURE;
41 }
43 ATH_CHECK( m_weightPFOTool.retrieve() );
44 }
45 ATH_CHECK( m_vertexContainer_key.initialize() );
46
47 ATH_MSG_INFO("Running CorrectPFOTool by vertex:" << m_doByVertex);
48 return StatusCode::SUCCESS;
49}
50
52 // Type-checking happens in the JetConstituentModifierBase class
53 // so it is safe just to static_cast
55 xAOD::FlowElementContainer* feCont = static_cast<xAOD::FlowElementContainer*>(cont);
56 if(!feCont->empty() && !(feCont->front()->signalType() & xAOD::FlowElement::PFlow)){
57 ATH_MSG_ERROR("CorrectPFOTool received FlowElements that aren't PFOs");
58 return StatusCode::FAILURE;
59 }
60 return m_doByVertex ? correctPFOByVertex(*feCont) : correctPFO(*feCont);
61 }
62 xAOD::PFOContainer* pfoCont = static_cast<xAOD::PFOContainer*> (cont);
63 return m_doByVertex ? correctPFOByVertex(*pfoCont) : correctPFO(*pfoCont);
64}
65
67 // Retrieve Primary Vertices
69 if (!handle.isValid()){
70 ATH_MSG_WARNING(" This event has no primary vertex container" );
71 return nullptr;
72 }
73
74 const xAOD::VertexContainer* pvtxs = handle.cptr();
75 if(pvtxs->empty()){
76 ATH_MSG_WARNING(" Failed to retrieve valid primary vertex container" );
77 return nullptr;
78 }
79
80 //Usually the 0th vertex is the primary one, but this is not always
81 // the case. So we will choose the first vertex of type PriVtx
82 for (const auto *theVertex : *pvtxs) {
83 if (theVertex->vertexType()==xAOD::VxType::PriVtx) {
84 return theVertex;
85 }//If we have a vertex of type primary vertex
86 }//iterate over the vertices and check their type
87
88 // If we failed to find an appropriate vertex, return the dummy vertex
89 ATH_MSG_DEBUG("Could not find a primary vertex in this event " );
90 for (const auto *theVertex : *pvtxs) {
91 if (theVertex->vertexType()==xAOD::VxType::NoVtx) {
92 return theVertex;
93 }
94 }
95
96 // If there is no primary vertex, then we cannot do PV matching.
97 ATH_MSG_WARNING("Primary vertex container was empty");
98 return nullptr;
99}
100
102
103 const xAOD::Vertex* vtx = nullptr;
104 if(m_correctneutral) {
105 vtx = getPrimaryVertex();
106 if(vtx==nullptr) {
107 ATH_MSG_ERROR("Primary vertex container was empty or no valid vertex found!");
108 return StatusCode::FAILURE;
109 } else if (vtx->vertexType()==xAOD::VxType::NoVtx) {
110 ATH_MSG_VERBOSE("No genuine primary vertex found. Will not apply origin correction");
111 }
112 }
113
114 for ( xAOD::PFO* ppfo : cont ) {
115
116 if ( std::abs(ppfo->charge())<FLT_MIN) { // Neutral PFOs
117 if(m_correctneutral) {
118 ATH_CHECK( applyNeutralCorrection(*ppfo, *vtx) );
119 }
120 } else { // Charged PFOs
121 if(m_correctcharged) {
123 }
124 }
125 } // PFO loop
126
127 return StatusCode::SUCCESS;
128}
129
131
132 const xAOD::Vertex* vtx = nullptr;
133 if(m_correctneutral) {
134 vtx = getPrimaryVertex();
135 if(vtx==nullptr) {
136 ATH_MSG_ERROR("Primary vertex container was empty or no valid vertex found!");
137 return StatusCode::FAILURE;
138 } else if (vtx->vertexType()==xAOD::VxType::NoVtx) {
139 ATH_MSG_VERBOSE("No genuine primary vertex found. Will not apply origin correction");
140 }
141 }
142
143 for ( xAOD::FlowElement* ppfo : cont ) {
144
145 if ( !ppfo->isCharged()) { // Neutral PFOs
146 if(m_correctneutral) {
147 ATH_CHECK( applyNeutralCorrection(*ppfo, *vtx) );
148 }
149 } else { // Charged PFOs
150 if(m_correctcharged) {
152 }
153 }
154 } // PFO loop
155
156 return StatusCode::SUCCESS;
157}
158
160 static const SG::AuxElement::Accessor<unsigned> copyIndex("ConstituentCopyIndex");
161 // Retrieve Primary Vertices
163 if (!handle.isValid()){
164 ATH_MSG_WARNING(" This event has no primary vertex container" );
165 return StatusCode::FAILURE;
166 }
167
168 const xAOD::VertexContainer* pvtxs = handle.cptr();
169 if(pvtxs->empty()){
170 ATH_MSG_WARNING(" Failed to retrieve valid primary vertex container" );
171 return StatusCode::FAILURE;
172 }
173
174 for ( xAOD::PFO* ppfo : cont ) {
175
176 if ( std::abs(ppfo->charge())<FLT_MIN) { // Neutral PFOs
177 if(m_correctneutral) {
178 // Neutral PFOs - there are copies, one per vertex, already created
179 // We need to now need to correct each copy to point to the corresponding vertex
180 if (!copyIndex.isAvailable(*ppfo))
181 {
182 ATH_MSG_WARNING("Encountered a neutral per-vertex PFO object without the corresponding vertex index attribute");
183 continue;
184 }
185
186 const unsigned iVtx = copyIndex(*ppfo);
187 if (iVtx >= pvtxs->size())
188 {
189 ATH_MSG_WARNING("Encountered a neutral per-vertex PFO object with an index beyond the size of the vertex container");
190 continue;
191 }
192 const xAOD::Vertex* vtx = pvtxs->at(iVtx);
193 // Determine the correct four-vector interpretation for a neutral PFO associated with this vertex
194 // Cannot use applyNeutralCorrection as that only used VxType::PriVtx, but we want to apply to all primary vertices
195 // As such, extract the relevant parts and modify appropriately here
196 // This is necessary to avoid changing sign of pT for pT<0 PFO
197 if (ppfo->e() < FLT_MIN) {
198 ppfo->setP4(0, 0, 0, 0);
199 }
200 if (!m_inputIsEM || m_calibrate) { // Use LC four-vector
201 ppfo->setP4(ppfo->GetVertexCorrectedFourVec(*vtx));
202 } else { // Use EM four-vector
203 ppfo->setP4(ppfo->GetVertexCorrectedEMFourVec(*vtx));
204 }
205 }
206 } else { // Charged PFOs
207 if(m_correctcharged) {
209 }
210 }
211 } // PFO loop
212
213
214 return StatusCode::SUCCESS;
215}
216
218 static const SG::AuxElement::Accessor<unsigned> copyIndex("ConstituentCopyIndex");
219
220 // Retrieve Primary Vertices
222 if (!handle.isValid()){
223 ATH_MSG_WARNING(" This event has no primary vertex container" );
224 return StatusCode::FAILURE;
225 }
226
227 const xAOD::VertexContainer* pvtxs = handle.cptr();
228 if(pvtxs->empty()){
229 ATH_MSG_WARNING(" Failed to retrieve valid primary vertex container" );
230 return StatusCode::FAILURE;
231 }
232
233 for ( xAOD::FlowElement* ppfo : cont ) {
234
235 if ( !ppfo->isCharged()) { // Neutral PFOs
236 if(m_correctneutral) {
237 // Neutral PFOs - there are copies, one per vertex, already created
238 // We need to now need to correct each copy to point to the corresponding vertex
239 if (!copyIndex.isAvailable(*ppfo))
240 {
241 ATH_MSG_WARNING("Encountered a neutral per-vertex PFO object without the corresponding vertex index attribute");
242 continue;
243 }
244
245 const unsigned iVtx = copyIndex(*ppfo);
246 if (iVtx >= pvtxs->size())
247 {
248 ATH_MSG_WARNING("Encountered a neutral per-vertex PFO object with an index beyond the size of the vertex container");
249 continue;
250 }
251 const xAOD::Vertex* vtx = pvtxs->at(iVtx);
252 // Determine the correct four-vector interpretation for a neutral PFO associated with this vertex
253 // Cannot use applyNeutralCorrection as that only used VxType::PriVtx, but we want to apply to all primary vertices
254 // As such, extract the relevant parts and modify appropriately here
255 // This is necessary to avoid changing sign of pT for pT<0 PFO
256 if (ppfo->e() < FLT_MIN) {
257 ppfo->setP4(0, 0, 0, 0);
258 }
259 ppfo->setP4(FEHelpers::getVertexCorrectedFourVec(*ppfo, *vtx));
260 }
261 } else { // Charged PFOs
262 if(m_correctcharged) {
264 }
265 }
266 } // PFO loop
267
268
269 return StatusCode::SUCCESS;
270}
271
272
274 if (pfo.e() < FLT_MIN) { //This is necessary to avoid changing sign of pT for pT<0 PFO
275 pfo.setP4(0,0,0,0);
276 } else {
277 if ( !m_inputIsEM || m_calibrate ) { // Use LC four-vector
278 // Only correct if we really reconstructed a vertex
280 pfo.setP4(pfo.GetVertexCorrectedFourVec(vtx));
281 }
282 } else { // Use EM four-vector
283 // Only apply origin correction if we really reconstructed a vertex
286 } else {pfo.setP4(pfo.p4EM());} // Just set EM 4-vec
287 }
288 }
289 return StatusCode::SUCCESS;
290}
291
293 if (pfo.e() < FLT_MIN) { //This is necessary to avoid changing sign of pT for pT<0 PFO
294 pfo.setP4(0,0,0,0);
295 }
296 // Only apply origin correction if we really reconstructed a vertex
297 else if(vtx.vertexType() == xAOD::VxType::PriVtx) {
299 }
300 return StatusCode::SUCCESS;
301}
302
305 float weight = 0.0;
306 ATH_CHECK( m_weightPFOTool->fillWeight( pfo, weight ) );
307 ATH_MSG_VERBOSE("Fill pseudojet for CPFO with weighted pt: " << pfo.pt()*weight);
308 pfo.setP4(pfo.p4()*weight);
309 }//if should use charged PFO weighting scheme
310 return StatusCode::SUCCESS;
311}
312
315 float weight = 0.0;
316 ATH_CHECK( m_weightPFOTool->fillWeight( pfo, weight ) );
317 ATH_MSG_VERBOSE("Fill pseudojet for CPFO with weighted pt: " << pfo.pt()*weight);
318 pfo.setP4(pfo.p4()*weight);
319 }//if should use charged PFO weighting scheme
320 return StatusCode::SUCCESS;
321}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Handle class for reading from StoreGate.
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
StatusCode correctPFOByVertex(xAOD::PFOContainer &cont) const
bool m_calibrate
If true EM clusters are used for neutral PFOs.
StatusCode correctPFO(xAOD::PFOContainer &cont) const
StatusCode process_impl(xAOD::IParticleContainer *cont) const override final
SG::ReadHandleKey< xAOD::VertexContainer > m_vertexContainer_key
StatusCode applyChargedCorrection(xAOD::PFO &pfo) const
CorrectPFOTool(const std::string &name)
StatusCode applyNeutralCorrection(xAOD::PFO &pfo, const xAOD::Vertex &vtx) const
ToolHandle< CP::IWeightPFOTool > m_weightPFOTool
const xAOD::Vertex * getPrimaryVertex() const
bool m_correctneutral
If true, EM PFOs are calibrated to LC.
StatusCode initialize() override final
Dummy implementation of the initialisation function.
const T * at(size_type n) const
Access an element, as an rvalue.
const T * front() const
Access the first element in the collection as an rvalue.
size_type size() const noexcept
Returns the number of elements in the collection.
bool empty() const noexcept
Returns true if the collection is empty.
JetConstituentModifierBase(const std::string &name)
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 double pt() const override
void setP4(float pt, float eta, float phi, float m)
signal_t signalType() const
virtual double e() const override
The total energy of the particle.
virtual FourMom_t p4() const override
The full 4-momentum of the particle.
TLorentzVector GetVertexCorrectedFourVec(const xAOD::Vertex &vertexToCorrectTo) const
Correct 4-vector to point at a vertex.
Definition PFO_v1.cxx:722
FourMom_t p4EM() const
get EM scale 4-vector
Definition PFO_v1.cxx:144
virtual FourMom_t p4() const
The full 4-momentum of the particle.
Definition PFO_v1.cxx:95
void setP4(const FourMom_t &vec)
set the 4-vec
Definition PFO_v1.cxx:107
TLorentzVector GetVertexCorrectedEMFourVec(const xAOD::Vertex &vertexToCorrectTo) const
Correct EM scale 4-vector to point at a vertex.
Definition PFO_v1.cxx:737
virtual double e() const
The total energy of the particle.
Definition PFO_v1.cxx:81
virtual double pt() const
The transverse momentum ( ) of the particle.
Definition PFO_v1.cxx:52
VxType::VertexType vertexType() const
The type of the vertex.
TLorentzVector getVertexCorrectedFourVec(const xAOD::FlowElement &fe, const xAOD::Vertex &vertexToCorrectTo)
Definition FEHelpers.cxx:13
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
@ ParticleFlow
The object is a particle-flow object.
Definition ObjectType.h:41
@ FlowElement
The object is a track-calo-cluster.
Definition ObjectType.h:52
@ PriVtx
Primary vertex.
@ NoVtx
Dummy vertex. TrackParticle was not used in vertex fit.
FlowElementContainer_v1 FlowElementContainer
Definition of the current "pfo container version".
PFO_v1 PFO
Definition of the current "pfo version".
Definition PFO.h:17
PFOContainer_v1 PFOContainer
Definition of the current "pfo container version".
FlowElement_v1 FlowElement
Definition of the current "pfo version".
Definition FlowElement.h:16
VertexContainer_v1 VertexContainer
Definition of the current "Vertex container version".
Vertex_v1 Vertex
Define the latest version of the vertex class.
DataVector< IParticle > IParticleContainer
Simple convenience declaration of IParticleContainer.