ATLAS Offline Software
PseudoJetGetter.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
15 
16 #ifndef PSEUDOJETGETTER_H
17 #define PSEUDOJETGETTER_H
18 
19 #include "fastjet/PseudoJet.hh"
20 #include "xAODBase/IParticle.h"
21 
22 #ifndef GENERATIONBASE
24 #include "xAODPFlow/PFO.h"
25 #include "xAODPFlow/FlowElement.h"
27 #include "xAODTracking/Vertex.h"
28 #include "JetEDM/LabelIndex.h"
30 #endif
31 
32 namespace PseudoJetGetter {
33 
35  bool null{false};
36  bool negativeE{false};
37  bool skipNegativeEnergy{false};
38 
40  }
41 
42  bool operator()(const xAOD::IParticle* ip) {
43  null = (ip == 0);
44  negativeE = skipNegativeEnergy && ip->e() <= 0.0;
45  return (null || negativeE);
46  }
47  };
48 
49 
50  std::vector<fastjet::PseudoJet>
51  IParticlesToPJs(const xAOD::IParticleContainer& ips, bool skipNegativeEnergy) {
52 
53  IParticleRejecter rejecter(skipNegativeEnergy);
54 
55  std::vector<fastjet::PseudoJet> vpj;
56  int index = -1;
57 
58  // loop over the input iparticles, select and convert to pseudojets
59  for(const xAOD::IParticle* ip: ips) {
60  ++index;
61  if(rejecter(ip)){continue;}
62 
63  // Create a Pseudojet with the momentum of the selected IParticles.
64  fastjet::PseudoJet psj(ip->p4());
65 
66  // user index is used to identify the xAOD object used for the PseudoJet
67  psj.set_user_index(index);
68  vpj.push_back(psj);
69 
70  }
71  return vpj;
72  }
73 
74  //**********************************************************************
75 
76 #ifndef GENERATIONBASE
77 
80 
82  cluster = dynamic_cast<const xAOD::CaloCluster*>(ip);
83  return cluster == 0; // reject if not a cluster
84  }
85  };
86 
87  std::vector<fastjet::PseudoJet>
88  EMToposToPJs(const xAOD::IParticleContainer& ips, bool skipNegativeEnergy) {
89 
90  // helper objects for selecting iparticles to be converted to pseudojets
91  IParticleRejecter ipRejecter(skipNegativeEnergy);
92  EMTopoRejecter emRejecter;
93 
94  std::vector<fastjet::PseudoJet> vpj;
95  int index = -1;
96 
97  // loop over iparticles, select and convert to pseudojets
98 
99  for(const xAOD::IParticle* ip: ips) {
100  ++index;
101  if(ipRejecter(ip) or emRejecter(ip)){continue;}
102 
103  // Create a Pseudojet with the momentum of the cluster.
104  fastjet::PseudoJet
105  psj(emRejecter.cluster->p4(xAOD::CaloCluster::UNCALIBRATED));
106 
107  // user index is used to identify the xAOD object used for the PseudoJet
108  psj.set_user_index(index);
109  vpj.push_back(psj);
110  }
111  return vpj;
112  }
113 
114  //**********************************************************************
115 
117 
118  bool skipNegativeEnergy{false};
119  bool useChargedPFOs{true};
120  bool useNeutralPFOs{true};
121  bool useChargedPV{true};
122  bool useChargedPUsideband{false};
123  bool inputIsUFO{false};
124 
125  PFlowRejecter(bool skip, bool useCharged, bool useNeutral, bool chargedPV, bool chargedPUsideband, bool isUFO):
127  useChargedPFOs(useCharged),
128  useNeutralPFOs(useNeutral),
129  useChargedPV(chargedPV),
130  useChargedPUsideband(chargedPUsideband),
131  inputIsUFO(isUFO){
132  }
133 
135 
136  bool reject = false;
137 
138  // Reject PJs with invalid energy --- they will lead
139  // to crashes in fastjet. See ATLASRECTS-7137.
140  float e = ip->e();
141  if (std::isinf(e) || std::isnan(e)) return true;
142 
143  if(ip->type() == xAOD::Type::FlowElement){
144  const xAOD::FlowElement* pfo = dynamic_cast<const xAOD::FlowElement*>(ip);
145 
146  reject = (skipNegativeEnergy && e<FLT_MIN);
147 
148  if(!inputIsUFO){
149  if( pfo->isCharged() ){
150  if(!useChargedPFOs) reject = true;
151  const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");
152  if(useChargedPV && !PVMatchedAcc(*pfo)) reject = true;
153  const static SG::AuxElement::ConstAccessor<char> PUsidebandMatchedAcc("matchedToPUsideband");
154  if (useChargedPUsideband && !PUsidebandMatchedAcc(*pfo)) reject = true;
155  }
156  else{
157  if(!useNeutralPFOs) reject = true;
158  }
159  }
160  else{
161  if(pfo->signalType() == xAOD::FlowElement::SignalType::Charged && !useChargedPFOs) reject = true;
162  if(pfo->signalType() == xAOD::FlowElement::SignalType::Neutral && !useNeutralPFOs) reject = true;
163  }
164  return reject;
165  }
166 
167  const xAOD::PFO* pfo = dynamic_cast<const xAOD::PFO*>(ip);
168 
169  // keep charged PFOs with energy==0 because for MET TST with PFlow,
170  // there may be high pt
171  // charged PFOs that receive a weight of 0 due to being in dense
172  // showers, but need to be present for overlap removal, because they
173  // don't retain these weights when added to the TST
174 
175  reject = (skipNegativeEnergy && e<FLT_MIN);
176 
177  if( pfo->isCharged() ) {
178  if(!useChargedPFOs) reject = true;
179  const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");
180  if(useChargedPV && !PVMatchedAcc(*pfo)) reject = true;
181  const static SG::AuxElement::ConstAccessor<char> PUsidebandMatchedAcc("matchedToPUsideband");
182  if (useChargedPUsideband && !PUsidebandMatchedAcc(*pfo)) reject = true;
183  }
184  else{
185  if(!useNeutralPFOs) reject = true;
186  }
187  return reject;
188  }
189  };
190 
191 
192  std::vector<fastjet::PseudoJet>
193  PFlowsToPJs(const xAOD::IParticleContainer& ips, bool skipNegativeEnergy, bool useChargedPFOs, bool useNeutralPFOs, bool useChargedPV, bool useChargedPUsideband, bool isUFO) {
194 
195  PFlowRejecter rejecter(skipNegativeEnergy, useChargedPFOs, useNeutralPFOs, useChargedPV, useChargedPUsideband, isUFO);
196  std::vector<fastjet::PseudoJet> vpj;
197  int index = -1;
198 
199  // loop over the input iparticles, select and convert to pseudojets
200 
201  for(const xAOD::IParticle* ip: ips) {
202  ++index;
203  if(rejecter(ip)){continue;}
204 
205  // Create a PSeudojet with the momentum of the selected IParticles.
206  fastjet::PseudoJet psj(ip->p4());
207 
208  // user index is used to identify the xAOD object used for the PSeudoJet
209  psj.set_user_index(index);
210 
211  vpj.push_back(psj);
212  }
213  return vpj;
214  }
215 
216  std::vector<fastjet::PseudoJet>
217  ByVertexPFlowsToPJs(const xAOD::IParticleContainer& ips, const xAOD::VertexContainer* pvs, bool skipNegativeEnergy, bool useChargedPFOs, bool useNeutralPFOs, bool isUFO) {
218 
219  const static SG::AuxElement::Accessor< unsigned > copyIndex("ConstituentCopyIndex"); // For neutral PFOs
220  const static SG::AuxElement::Accessor< std::vector<unsigned> > matchedPVs("MatchingPVs"); // For charged PFOs
221  const static SG::AuxElement::Accessor< std::vector<unsigned> > matchedPUSBs("MatchingPUsidebands"); // For charged PFOs
222  PFlowRejecter rejecter(skipNegativeEnergy, useChargedPFOs, useNeutralPFOs, false, false, isUFO);
223  std::vector<fastjet::PseudoJet> vpj;
224  int index = -1;
225 
226  // loop over the input iparticles, select and convert to pseudojets
227  for(const xAOD::IParticle* ip: ips) {
228 
229  const xAOD::FlowElement* pfo = dynamic_cast<const xAOD::FlowElement*>(ip);
230  ++index;
231  if(rejecter(ip)){
232  continue;
233  }
234 
235  unsigned vertexIndex{0};
236  if (pfo->isCharged())
237  {
238  // Charged PFOs - use the vertex matched to the track
239  if (matchedPVs.isAvailable(*pfo) && matchedPVs(*pfo).size())
240  {
241  // A charged PFO can potentially match multiple vertices, depending on the matching criteria used
242  // For now, just use the first match, to be further optimised later -- TODO
243  // Also add the part for PU sidebands -- TODO
244  vertexIndex = matchedPVs(*pfo).at(0);
245  }
246  else{
247  continue;
248  }
249  }
250  else
251  {
252  // Neutral PFOs - there is one neutral PFO corrected to point to each vertex of interest
253  // As such, just get the vertex index that this neutral PFO corresponds to
254  if (copyIndex.isAvailable(*pfo)){
255  vertexIndex = copyIndex(*pfo);
256  }
257  else{
258  continue;
259  }
260  }
261 
262  // Create a Pseudojet with the momentum of the selected IParticles.
263  fastjet::PseudoJet psj(ip->p4());
264 
265 
266  // Get the specified vertex and build the VertexIndexedConstituentUserInfo
267  for (const xAOD::Vertex* vertex : *pvs)
268  if (vertex->index() == vertexIndex){
269  // vertex indexed constituent info associated to the pseudojet
270  psj.set_user_info(new jet::VertexIndexedConstituentUserInfo(vertex));
271 
272  // user index is used to identify the xAOD object used for the PSeudoJet
273  psj.set_user_index(index);
274 
275  vpj.push_back(psj);
276  }
277  }
278  return vpj;
279  }
280 
281 #endif
282 
283 }
284 
285 #endif
VertexIndexedConstituentUserInfo.h
PseudoJetGetter::PFlowsToPJs
std::vector< fastjet::PseudoJet > PFlowsToPJs(const xAOD::IParticleContainer &ips, bool skipNegativeEnergy, bool useChargedPFOs, bool useNeutralPFOs, bool useChargedPV, bool useChargedPUsideband, bool isUFO)
Definition: PseudoJetGetter.h:193
PseudoJetGetter::PFlowRejecter
Definition: PseudoJetGetter.h:116
PseudoJetGetter::PFlowRejecter::skipNegativeEnergy
bool skipNegativeEnergy
Definition: PseudoJetGetter.h:118
IParticle.h
SG::Accessor
Helper class to provide type-safe access to aux data.
Definition: Control/AthContainers/AthContainers/Accessor.h:66
PseudoJetGetter::IParticleRejecter::negativeE
bool negativeE
Definition: PseudoJetGetter.h:36
index
Definition: index.py:1
PseudoJetGetter
Implementations of concrete input-to-PseudoJet conversions Separated from PseudoJetAlgorithm for read...
Definition: PseudoJetGetter.h:32
PseudoJetGetter::EMTopoRejecter
Definition: PseudoJetGetter.h:78
SG::ConstAccessor
Helper class to provide constant type-safe access to aux data.
Definition: ConstAccessor.h:54
xAOD::IParticle
Class providing the definition of the 4-vector interface.
Definition: Event/xAOD/xAODBase/xAODBase/IParticle.h:40
PUClassification.Charged
Charged
Definition: PUClassification.py:16
PseudoJetGetter::IParticleRejecter::skipNegativeEnergy
bool skipNegativeEnergy
Definition: PseudoJetGetter.h:37
xAOD::FlowElement_v1::isCharged
bool isCharged() const
Definition: FlowElement_v1.cxx:56
PFO.h
PseudoJetGetter::PFlowRejecter::operator()
bool operator()(const xAOD::IParticle *ip)
Definition: PseudoJetGetter.h:134
xAOD::CaloCluster_v1
Description of a calorimeter cluster.
Definition: CaloCluster_v1.h:59
PseudoJetGetter::EMToposToPJs
std::vector< fastjet::PseudoJet > EMToposToPJs(const xAOD::IParticleContainer &ips, bool skipNegativeEnergy)
Definition: PseudoJetGetter.h:88
FlowElement.h
CaloCluster.h
PseudoJetGetter::IParticleRejecter::IParticleRejecter
IParticleRejecter(bool skip)
Definition: PseudoJetGetter.h:39
PseudoJetGetter::ByVertexPFlowsToPJs
std::vector< fastjet::PseudoJet > ByVertexPFlowsToPJs(const xAOD::IParticleContainer &ips, const xAOD::VertexContainer *pvs, bool skipNegativeEnergy, bool useChargedPFOs, bool useNeutralPFOs, bool isUFO)
Definition: PseudoJetGetter.h:217
xAOD::FlowElement
FlowElement_v1 FlowElement
Definition of the current "pfo version".
Definition: FlowElement.h:16
PseudoJetGetter::EMTopoRejecter::operator()
bool operator()(const xAOD::IParticle *ip)
Definition: PseudoJetGetter.h:81
PseudoJetGetter::PFlowRejecter::useChargedPV
bool useChargedPV
Definition: PseudoJetGetter.h:121
PseudoJetGetter::PFlowRejecter::useChargedPUsideband
bool useChargedPUsideband
Definition: PseudoJetGetter.h:122
xAOD::FlowElement_v1::signalType
signal_t signalType() const
PseudoJetGetter::PFlowRejecter::inputIsUFO
bool inputIsUFO
Definition: PseudoJetGetter.h:123
find_tgc_unfilled_channelids.ip
ip
Definition: find_tgc_unfilled_channelids.py:3
jet::VertexIndexedConstituentUserInfo
Definition: VertexIndexedConstituentUserInfo.h:16
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
Vertex.h
PseudoJetGetter::EMTopoRejecter::cluster
const xAOD::CaloCluster * cluster
Definition: PseudoJetGetter.h:79
xAOD::PFO_v1::isCharged
bool isCharged() const
is a charged PFO
Definition: PFO_v1.cxx:251
xAOD::CaloCluster_v1::p4
virtual FourMom_t p4() const
The full 4-momentum of the particle.
Definition: CaloCluster_v1.cxx:465
xAOD::CaloCluster_v1::UNCALIBRATED
@ UNCALIBRATED
Definition: CaloCluster_v1.h:306
xAOD::PFO_v1
Class describing a particle flow object.
Definition: PFO_v1.h:35
PseudoJetGetter::IParticleRejecter
Definition: PseudoJetGetter.h:34
PseudoJetGetter::IParticlesToPJs
std::vector< fastjet::PseudoJet > IParticlesToPJs(const xAOD::IParticleContainer &ips, bool skipNegativeEnergy)
Definition: PseudoJetGetter.h:51
LabelIndex.h
Trk::vertex
@ vertex
Definition: MeasurementType.h:21
DeMoScan.index
string index
Definition: DeMoScan.py:362
VertexContainer.h
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
PseudoJetGetter::PFlowRejecter::PFlowRejecter
PFlowRejecter(bool skip, bool useCharged, bool useNeutral, bool chargedPV, bool chargedPUsideband, bool isUFO)
Definition: PseudoJetGetter.h:125
SG::ConstAccessor< T, AuxAllocator_t< T > >::isAvailable
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
skip
bool skip
Definition: TrigGlobEffCorrValidation.cxx:190
PseudoJetGetter::IParticleRejecter::operator()
bool operator()(const xAOD::IParticle *ip)
Definition: PseudoJetGetter.h:42
PseudoJetGetter::PFlowRejecter::useNeutralPFOs
bool useNeutralPFOs
Definition: PseudoJetGetter.h:120
PseudoJetGetter::PFlowRejecter::useChargedPFOs
bool useChargedPFOs
Definition: PseudoJetGetter.h:119
xAOD::FlowElement_v1
A detector object made of other lower level object(s)
Definition: FlowElement_v1.h:25