ATLAS Offline Software
METEgammaAssociator.cxx
Go to the documentation of this file.
1 
3 /*
4  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
5 */
6 
7 // METEgammaAssociator.cxx
8 // Implementation file for class METEgammaAssociator
9 //
10 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
11 //
12 // Author: P Loch, S Resconi, TJ Khoo, AS Mete
14 
15 // METReconstruction includes
17 
18 // Egamma EDM
22 
23 // Tracking EDM
24 #include "xAODTracking/Vertex.h"
25 
26 // DeltaR calculation
28 
33 
34 namespace met {
35 
36  using namespace xAOD;
37 
38  // Constructors
41  AsgTool(name),
43  {
44  // 0 is delta-R geometrical matching
45  // 1 is using TopoClusterLink decoration on clusters
46  declareProperty( "TCMatchMethod", m_tcMatch_method = DeltaR );
47  declareProperty( "TCMatchMaxRat", m_tcMatch_maxRat = 1.5 );
48  declareProperty( "TCMatchDeltaR", m_tcMatch_dR = 0.1 );
49  declareProperty( "ExtraTrackMatchDeltaR", m_extraTrkMatch_dR = 0.05 );
50  declareProperty( "CheckUnmatched", m_checkUnmatched = false);
51  }
52 
53  // Destructor
56  = default;
57 
58  // Athena algtool's Hooks
61  {
63  ATH_MSG_VERBOSE ("Initializing " << name() << "...");
64  switch(m_tcMatch_method) {
65  case DeltaR: ATH_MSG_INFO("Egamma-topocluster matching uses DeltaR check."); break;
66  case ClusterLink: ATH_MSG_INFO("Egamma-topocluster matching uses topocluster links."); break;
67  default:
68  ATH_MSG_WARNING( "Invalid topocluster match method configured!" );
69  return StatusCode::FAILURE;
70  }
71 
72  return StatusCode::SUCCESS;
73  }
74 
76  {
77  ATH_MSG_VERBOSE ("Finalizing " << name() << "...");
78  return StatusCode::SUCCESS;
79  }
80 
81 
82  //**********************************************************************
83  // Get Egamma constituents
85  std::vector<const xAOD::IParticle*>& tclist,
86  const met::METAssociator::ConstitHolder& constits) const
87  {
88  const Egamma *eg = static_cast<const Egamma*>(obj);
89  // safe to assume a single SW cluster?
90  // will do so for now...
91  const CaloCluster* swclus = eg->caloCluster();
92 
93  // the matching strategy depends on how the cluster container is sorted
94  // easier if it's sorted in descending pt order
95  // we'll worry about optimisation later
96  std::vector<const IParticle*> inputTC;
97  inputTC.reserve(10);
98 
100  for(const auto *const cl : *constits.tcCont) {
101  // this can probably be done more elegantly
102  if(P4Helpers::isInDeltaR(*swclus,*cl,m_tcMatch_dR,m_useRapidity) && cl->e()>FLT_MIN) {
103  // could consider also requirements on the EM fraction or depth
104  inputTC.push_back(cl);
105  } // match TC in a cone around SW cluster
106  }
107  ATH_MSG_VERBOSE("Found " << inputTC.size() << " nearby topoclusters");
108  std::sort(inputTC.begin(),inputTC.end(),greaterPt);
109  } else if(m_tcMatch_method==ClusterLink) {
110  static const SG::AuxElement::ConstAccessor<std::vector<ElementLink<CaloClusterContainer> > > tcLinkAcc("constituentClusterLinks");
111  // Fill a vector of vectors
112  for(const auto& el : tcLinkAcc(*swclus)) {
113  if(el.isValid())
114  inputTC.push_back(*el);
115  else{
116  ATH_MSG_ERROR("Invalid constituentClusterLinks on input electron/photon!");
117  return StatusCode::FAILURE;
118  }
119  }
120  ATH_MSG_VERBOSE("Found " << inputTC.size() << " linked topoclusters");
121  } else {
122  ATH_MSG_WARNING( "Invalid topocluster match method configured!" );
123  return StatusCode::FAILURE;
124  }
125 
126  ATH_CHECK( selectEgammaClusters(swclus, inputTC, tclist) );
127 
128  return StatusCode::SUCCESS;
129  }
130 
131 
133  std::vector<const xAOD::IParticle*>& constlist,
134  const met::METAssociator::ConstitHolder& constits) const
135  {
136  const xAOD::Egamma *eg = static_cast<const xAOD::Egamma*>(obj);
137  std::set<const xAOD::TrackParticle*> trackset; // use a set for duplicate-free retrieval
138  ATH_CHECK( selectEgammaTracks(eg, constits.trkCont, trackset) );
139  for(const auto& track : trackset) {
140  if(acceptTrack(track,constits.pv) && isGoodEoverP(track)) {
141  constlist.push_back(track);
142  }
143  }
144  return StatusCode::SUCCESS;
145  }
146 
148  std::vector<const xAOD::IParticle*>& pfolist,
149  const met::METAssociator::ConstitHolder& constits,
150  std::map<const IParticle*,MissingETBase::Types::constvec_t> &/*momenta*/) const
151  {
152  const xAOD::Egamma *eg = static_cast<const xAOD::Egamma*>(obj);
153 
154  if (m_usePFOLinks)
155  ATH_CHECK( extractPFOsFromLinks(eg, pfolist,constits) );
156  else
157  ATH_CHECK( extractPFOs(eg, pfolist, constits) );
158 
159  return StatusCode::SUCCESS;
160  }
161 
163  std::vector<const xAOD::IParticle*>& pfolist,
164  const met::METAssociator::ConstitHolder& constits) const
165  {
166 
167  ATH_MSG_DEBUG("Extract PFOs From Links for " << eg->type() << " with pT " << eg->pt());
168 
169  std::vector<PFOLink_t> cPFOLinks;
170  std::vector<PFOLink_t> nPFOLinks;
171 
172  if (eg->type() == xAOD::Type::Electron){
175  nPFOLinks=neutralPFOReadDecorHandle(*eg);
176  cPFOLinks=chargedPFOReadDecorHandle(*eg);
177  }
178  if (eg->type() == xAOD::Type::Photon) {
181  nPFOLinks=neutralPFOReadDecorHandle(*eg);
182  cPFOLinks=chargedPFOReadDecorHandle(*eg);
183  }
184 
185 
186  // Charged PFOs
187  for (const PFOLink_t& pfoLink : cPFOLinks) {
188  if (!pfoLink.isValid()) continue;
189  const xAOD::PFO* pfo_init = *pfoLink;
190  for (const auto *const pfo : *constits.pfoCont){
191  if (pfo->index() == pfo_init->index() && pfo->isCharged()){ //index-based match between JetETmiss and CHSParticleFlow collections
192  const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");
193  if( pfo->isCharged() && PVMatchedAcc(*pfo)&& ( !m_cleanChargedPFO || isGoodEoverP(pfo->track(0)) ) ) {
194  ATH_MSG_DEBUG("Accept cPFO with pt " << pfo->pt() << ", e " << pfo->e() << ", eta " << pfo->eta() << ", phi " << pfo->phi() );
195  if (!m_checkUnmatched || !hasUnmatchedClusters(eg,pfo_init)) pfolist.push_back(pfo);
196  }
197  }
198  }
199  } // end cPFO loop
200 
201  // Neutral PFOs
202  double eg_cl_e = eg->caloCluster()->e();
203  double sumE_pfo = 0.;
204 
205  for (const PFOLink_t& pfoLink : nPFOLinks) {
206  if (!pfoLink.isValid()) continue;
207  const xAOD::PFO* pfo_init = *pfoLink;
208  for (const auto *const pfo : *constits.pfoCont){
209  if (pfo->index() == pfo_init->index() && !pfo->isCharged()){ //index-based match between JetETmiss and CHSParticleFlow collections
210  double pfo_e = pfo->eEM();
211  if( ( !pfo->isCharged()&& pfo->e() > FLT_MIN ) ){
212  sumE_pfo += pfo_e;
213  ATH_MSG_DEBUG("E match with new nPFO: " << fabs(sumE_pfo+pfo_e - eg_cl_e) / eg_cl_e);
214  ATH_MSG_DEBUG("Accept nPFO with pt " << pfo->pt() << ", e " << pfo->e() << ", eta " << pfo->eta() << ", phi " << pfo->phi() << " in sum.");
215  ATH_MSG_DEBUG("Energy ratio of nPFO to eg: " << pfo_e / eg_cl_e);
216  pfolist.push_back(pfo);
217  }
218  }
219  }
220  } // end nPFO links loop
221 
222 
223  return StatusCode::SUCCESS;
224  }
225 
227  std::vector<const xAOD::IParticle*>& pfolist,
228  const met::METAssociator::ConstitHolder& constits) const
229 
230  {
231  // safe to assume a single SW cluster?
232  // will do so for now...
233  const xAOD::IParticle* swclus = eg->caloCluster();
234  ANA_MSG_VERBOSE("Extract PFOs with DeltaR for " << eg->type() << " with pT " << eg->pt());
235 
236  // Preselect PFOs based on proximity: dR<0.4
237  std::vector<const xAOD::PFO*> nearbyPFO;
238  nearbyPFO.reserve(20);
239  for(const auto *const pfo : *constits.pfoCont) {
240  if(P4Helpers::isInDeltaR(*pfo, *swclus, 0.4, m_useRapidity)) {
241  // We set a small -ve pt for cPFOs that were rejected
242  // by the ChargedHadronSubtractionTool
243  const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");
244  if( ( !pfo->isCharged() && pfo->e() > FLT_MIN ) ||
245  ( pfo->isCharged() && PVMatchedAcc(*pfo)
246  && ( !m_cleanChargedPFO || isGoodEoverP(pfo->track(0)) ) )
247  ) {
248  nearbyPFO.push_back(pfo);
249  } // retain +ve E neutral PFOs and charged PFOs passing PV association
250  } // DeltaR check
251  } // PFO loop
252  ATH_MSG_VERBOSE("Found " << nearbyPFO.size() << " nearby pfos");
253 
254  std::set<const xAOD::TrackParticle*> trackset; // use a set for duplicate-free retrieval
255  ATH_CHECK( selectEgammaTracks(eg, constits.trkCont, trackset) );
256  for(const auto& track : trackset) {
257  for(const auto& pfo : nearbyPFO) {
258  if(pfo->isCharged() && pfo->track(0) == track) {
259  pfolist.push_back(pfo);
260  } // PFO/track match
261  } // PFO loop
262  } // Track loop
263  double eg_cl_e = swclus->e();
264 
265  // the matching strategy depends on how the cluster container is sorted
266  // easier if it's sorted in descending pt order
267  // ideally this should be done using cell matching, but we can't use the links from topoclusters reliably
268  // because some PFOs don't correspond to the original TC
269  bool doSum = true;
270  double sumE_pfo = 0.;
271  const IParticle* bestbadmatch = nullptr;
272  std::sort(nearbyPFO.begin(),nearbyPFO.end(),greaterPtPFO);
273  for(const auto& pfo : nearbyPFO) {
274  // Skip charged PFOs, as we already matched them
275  if(pfo->isCharged() || !P4Helpers::isInDeltaR(*pfo, *swclus, m_tcMatch_dR, m_useRapidity)) {continue;}
276  // Handle neutral PFOs like topoclusters
277  double pfo_e = pfo->eEM();
278  // skip cluster if it's above our bad match threshold or outside the matching radius
279  if(pfo_e>m_tcMatch_maxRat*eg_cl_e) {
280  ATH_MSG_VERBOSE("Reject topocluster in sum. Ratio vs eg cluster: " << (pfo_e/eg_cl_e));
281  if( !bestbadmatch || (fabs(pfo_e/eg_cl_e-1.) < fabs(bestbadmatch->e()/eg_cl_e-1.)) ) bestbadmatch = pfo;
282  continue;
283  }
284 
285  ATH_MSG_VERBOSE("E match with new nPFO: " << fabs(sumE_pfo+pfo_e - eg_cl_e) / eg_cl_e);
286  if( (doSum = fabs(sumE_pfo+pfo_e-eg_cl_e) < fabs(sumE_pfo - eg_cl_e)) ) {
287  pfolist.push_back(pfo);
288  sumE_pfo += pfo_e;
289  ATH_MSG_VERBOSE("Accept pfo with pt " << pfo->pt() << ", e " << pfo->e() << " in sum.");
290  ATH_MSG_VERBOSE("Energy ratio of nPFO to eg: " << pfo_e / eg_cl_e);
291  ATH_MSG_VERBOSE("E match with new PFO: " << fabs(sumE_pfo+pfo_e - eg_cl_e) / eg_cl_e);
292  } // if we will retain the topocluster
293  else {break;}
294  } // loop over nearby clusters
295  if(sumE_pfo<FLT_MIN && bestbadmatch) {
296  ATH_MSG_VERBOSE("No better matches found -- add bad match topocluster with pt "
297  << bestbadmatch->pt() << ", e " << bestbadmatch->e() << ".");
298  pfolist.push_back(bestbadmatch);
299  }
300 
301  return StatusCode::SUCCESS;
302  }
303 
305  std::vector<const xAOD::IParticle*>& felist,
306  const met::METAssociator::ConstitHolder& constits,
307  std::map<const IParticle*,MissingETBase::Types::constvec_t> &/*momenta*/) const
308  {
309  const xAOD::Egamma *eg = static_cast<const xAOD::Egamma*>(obj);
310 
311  if (m_useFELinks)
312  ATH_CHECK( extractFEsFromLinks(eg, felist,constits) );
313  else
314  ATH_CHECK( extractFEs(eg, felist, constits) );
315 
316  return StatusCode::SUCCESS;
317  }
318 
319 
321  std::vector<const xAOD::IParticle*>& felist,
322  const met::METAssociator::ConstitHolder& constits) const
323  {
324 
325  ATH_MSG_DEBUG("Extract FEs From Links for " << eg->type() << " with pT " << eg->pt());
326 
327  std::vector<FELink_t> nFELinks;
328  std::vector<FELink_t> cFELinks;
329 
330  if (eg->type() == xAOD::Type::Electron){
333  nFELinks=neutralFEReadDecorHandle(*eg);
334  cFELinks=chargedFEReadDecorHandle(*eg);
335  }
336  if (eg->type() == xAOD::Type::Photon) {
339  nFELinks=neutralFEReadDecorHandle(*eg);
340  cFELinks=chargedFEReadDecorHandle(*eg);
341  }
342 
343 
344  // Charged FEs
345  for (const FELink_t& feLink : cFELinks) {
346  if (!feLink.isValid()) continue;
347  const xAOD::FlowElement* fe_init = *feLink;
348  for (const auto *const fe : *constits.feCont){
349  if (fe->index() == fe_init->index() && fe->isCharged()){ //index-based match between JetETmiss and CHSFlowElements collections
350  const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");
351  if( fe->isCharged() && PVMatchedAcc(*fe)&& ( !m_cleanChargedPFO || isGoodEoverP(static_cast<const xAOD::TrackParticle*>(fe->chargedObject(0))) ) ) {
352  ATH_MSG_DEBUG("Accept cFE with pt " << fe->pt() << ", e " << fe->e() << ", eta " << fe->eta() << ", phi " << fe->phi() );
353  felist.push_back(fe);
354  }
355  }
356  }
357  } // end cFE loop
358 
359  // Neutral FEs
360  double eg_cl_e = eg->caloCluster()->e();
361  double sumE_fe = 0.;
362 
363  for (const FELink_t& feLink : nFELinks) {
364  if (!feLink.isValid()) continue;
365  const xAOD::FlowElement* fe_init = *feLink;
366  for (const auto *const fe : *constits.feCont){
367  if (fe->index() == fe_init->index() && !fe->isCharged()){ //index-based match between JetETmiss and CHSFlowElements collections
368  double fe_e = fe->e();
369  if( ( !fe->isCharged()&& fe->e() > FLT_MIN ) ){
370  sumE_fe += fe_e;
371  ATH_MSG_DEBUG("E match with new nFE: " << fabs(sumE_fe+fe_e - eg_cl_e) / eg_cl_e);
372  ATH_MSG_DEBUG("Accept nFE with pt " << fe->pt() << ", e " << fe->e() << ", eta " << fe->eta() << ", phi " << fe->phi() << " in sum.");
373  ATH_MSG_DEBUG("Energy ratio of nFE to eg: " << fe_e / eg_cl_e);
374  felist.push_back(fe);
375  }
376  }
377  }
378  } // end nFE links loop
379 
380 
381  return StatusCode::SUCCESS;
382  }
383 
385  std::vector<const xAOD::IParticle*>& felist,
386  const met::METAssociator::ConstitHolder& constits) const
387  {
388  ATH_MSG_VERBOSE("Extract FEs From DeltaR for " << eg->type() << " with pT " << eg->pt());
389 
390  // safe to assume a single SW cluster?
391  // will do so for now...
392  const xAOD::IParticle* swclus = eg->caloCluster();
393 
394  // Preselect PFOs based on proximity: dR<0.4
395  std::vector<const xAOD::FlowElement*> nearbyFE;
396  nearbyFE.reserve(20);
397  for(const xAOD::FlowElement* fe : *constits.feCont) {
398  if(!(fe->signalType() & xAOD::FlowElement::PFlow)){
399  ATH_MSG_ERROR("Attempted to extract non-PFlow FlowElements. This is not supported!");
400  return StatusCode::FAILURE;
401  }
402  if(P4Helpers::isInDeltaR(*fe, *swclus, 0.4, m_useRapidity)) {
403  // We set a small -ve pt for cPFOs that were rejected
404  // by the ChargedHadronSubtractionTool
405  const static SG::AuxElement::ConstAccessor<char> PVMatchedAcc("matchedToPV");
406  if( ( !fe->isCharged() && fe->e() > FLT_MIN ) ||
407  ( fe->isCharged() && PVMatchedAcc(*fe)
408  && ( !m_cleanChargedPFO || isGoodEoverP(static_cast<const xAOD::TrackParticle*>(fe->chargedObject(0))) ) )
409  ) {
410  nearbyFE.push_back(fe);
411  } // retain +ve E neutral PFOs and charged PFOs passing PV association
412  } // DeltaR check
413  } // PFO loop
414  ATH_MSG_VERBOSE("Found " << nearbyFE.size() << " nearby FlowElements (PFOs)");
415 
416  std::set<const xAOD::TrackParticle*> trackset; // use a set for duplicate-free retrieval
417  ATH_CHECK( selectEgammaTracks(eg, constits.trkCont, trackset) );
418  for(const xAOD::TrackParticle* track : trackset) {
419  for(const xAOD::FlowElement* fe : nearbyFE) {
420  if(fe->isCharged() && fe->chargedObject(0) == track) {
421  felist.push_back(fe);
422  } // PFO/track match
423  } // PFO loop
424  } // Track loop
425  double eg_cl_e = swclus->e();
426 
427  // the matching strategy depends on how the cluster container is sorted
428  // easier if it's sorted in descending pt order
429  // ideally this should be done using cell matching, but we can't use the links from topoclusters reliably
430  // because some PFOs don't correspond to the original TC
431  bool doSum = true;
432  double sumE_pfo = 0.;
433  const IParticle* bestbadmatch = nullptr;
434  std::sort(nearbyFE.begin(),nearbyFE.end(),greaterPtFE);
435  for(const xAOD::FlowElement* fe : nearbyFE) {
436  // Skip charged PFOs, as we already matched them
437  if(fe->isCharged() || !P4Helpers::isInDeltaR(*fe, *swclus, m_tcMatch_dR, m_useRapidity)) continue;
438  // Handle neutral PFOs like topoclusters
439  // TODO: Use EM-scale energy here in the future? No way to access from FlowElement in general.
440  double pfo_e = fe->e();
441  // skip cluster if it's above our bad match threshold or outside the matching radius
442  if(pfo_e > m_tcMatch_maxRat*eg_cl_e) {
443  ATH_MSG_VERBOSE("Reject topocluster in sum. Ratio vs eg cluster: " << (pfo_e/eg_cl_e));
444  if( !bestbadmatch || (fabs(pfo_e/eg_cl_e-1.) < fabs(bestbadmatch->e()/eg_cl_e-1.)) ) bestbadmatch = fe;
445  continue;
446  }
447 
448  ATH_MSG_VERBOSE("E match with new nPFO: " << fabs(sumE_pfo+pfo_e - eg_cl_e) / eg_cl_e);
449  if( (doSum = fabs(sumE_pfo+pfo_e-eg_cl_e) < fabs(sumE_pfo - eg_cl_e)) ) {
450  felist.push_back(fe);
451  sumE_pfo += pfo_e;
452  ATH_MSG_VERBOSE("Accept pfo with pt " << fe->pt() << ", e " << fe->e() << " in sum.");
453  ATH_MSG_VERBOSE("Energy ratio of nPFO to eg: " << pfo_e / eg_cl_e);
454  ATH_MSG_VERBOSE("E match with new PFO: " << fabs(sumE_pfo+pfo_e - eg_cl_e) / eg_cl_e);
455  } // if we will retain the topocluster
456  else break;
457  } // loop over nearby clusters
458  if(sumE_pfo<FLT_MIN && bestbadmatch) {
459  ATH_MSG_VERBOSE("No better matches found -- add bad match topocluster with pt "
460  << bestbadmatch->pt() << ", e " << bestbadmatch->e() << ".");
461  felist.push_back(bestbadmatch);
462  }
463 
464  return StatusCode::SUCCESS;
465  }
466 
467 
468  //**********************************************************************
469  // Select Egamma tracks & clusters
470 
472  const std::vector<const IParticle*>& inputTC,
473  std::vector<const xAOD::IParticle*>& tclist) const
474  {
475  double eg_cl_e = swclus->e();
476 
477  bool doSum = true;
478  double sumE_tc = 0.;
479  const IParticle* bestbadmatch = nullptr;
480  for(const auto& cl : inputTC) {
481  double tcl_e = cl->e();
482  // skip cluster if it's above our bad match threshold
483  // retain pointer of the closest matching cluster in case no better is found
484  if(tcl_e>m_tcMatch_maxRat*eg_cl_e) {
485  ATH_MSG_VERBOSE("Reject topocluster in sum. Ratio vs eg cluster: " << (tcl_e/eg_cl_e));
486  if( !bestbadmatch || (fabs(tcl_e/eg_cl_e-1.) < fabs(bestbadmatch->e()/eg_cl_e-1.)) ) bestbadmatch = cl;
487  continue;
488  }
489 
490  ATH_MSG_VERBOSE("E match with new cluster: " << fabs(sumE_tc+tcl_e - eg_cl_e) / eg_cl_e);
491  if( (doSum = (fabs(sumE_tc+tcl_e - eg_cl_e) < fabs(sumE_tc - eg_cl_e))) ) {
492  ATH_MSG_VERBOSE("Accept topocluster with pt " << cl->pt() << ", e " << cl->e() << " in sum.");
493  ATH_MSG_VERBOSE("Energy ratio of nPFO to eg: " << tcl_e / eg_cl_e);
494  ATH_MSG_VERBOSE("E match with new cluster: " << fabs(sumE_tc+tcl_e - eg_cl_e) / eg_cl_e);
495  tclist.push_back(cl);
496  sumE_tc += tcl_e;
497  } // if we will retain the topocluster
498  } // loop over nearby clusters
499  if(sumE_tc<FLT_MIN && bestbadmatch) {
500  ATH_MSG_VERBOSE("No better matches found -- add bad match topocluster with pt "
501  << bestbadmatch->pt() << ", e " << bestbadmatch->e() << ".");
502  tclist.push_back(bestbadmatch);
503  }
504  return StatusCode::SUCCESS;
505  }
506 
508  const xAOD::TrackParticleContainer* trkCont,
509  std::set<const xAOD::TrackParticle*>& tracklist) const
510  {
511  // switch to using egamma helpers for track extraction
512  // set ensures that there's no duplication
513  const std::set<const xAOD::TrackParticle*> egtracks = EgammaHelpers::getTrackParticles(eg);
514  for(const auto& track : egtracks) {
515  ATH_MSG_VERBOSE("Accept " << eg->type() << " track " << track << " px, py = " << track->p4().Px() << ", " << track->p4().Py());
516  tracklist.insert(track);
517  } // end initial egamma track loop
518 
519  // for objects with ambiguous author, grab the tracks matched to the counterpart ambiguous object too
520  // set ensures that there's no duplication
521  if (eg->author() & xAOD::EgammaParameters::AuthorAmbiguous && eg->ambiguousObject()) {
522  const std::set<const xAOD::TrackParticle*> ambitracks = EgammaHelpers::getTrackParticles(eg->ambiguousObject());
523  for(const auto& track : egtracks) {
524  ATH_MSG_VERBOSE("Accept ambiguous " << eg->type() << " track " << track << " px, py = " << track->p4().Px() << ", " << track->p4().Py());
525  tracklist.insert(track);
526  }
527  } // end ambiguous track case
528 
529  // in a small dR window, also accept tracks without an IBL hit
530  for(const auto *const track : *trkCont) {
532  // dR check should be faster than track summary retrieval
533  uint8_t expect_innermostHit(false);
534  uint8_t N_innermostHit(false);
535  uint8_t expect_nextToInnermostHit(false);
536  uint8_t N_nextToInnermostHit(false);
537  if( !track->summaryValue(expect_innermostHit, expectInnermostPixelLayerHit)
538  || !track->summaryValue(expect_nextToInnermostHit, expectNextToInnermostPixelLayerHit)) {
539  ATH_MSG_WARNING("Track summary retrieval failed for 'expect(NextTo)InnermostPixelLayerHit'");
540  return StatusCode::FAILURE;
541  }
542  if(expect_innermostHit) {
543  if( !track->summaryValue(N_innermostHit, numberOfInnermostPixelLayerHits) ) {
544  ATH_MSG_WARNING("Track summary retrieval failed for 'numberOfInnermostPixelLayerHits'");
545  return StatusCode::FAILURE;
546  if(N_innermostHit==0 ) {
547  ATH_MSG_VERBOSE("Accept nearby track w/o innermost hit");
548  tracklist.insert(track);
549  }
550  }
551  } else if(expect_nextToInnermostHit) {
552  if( !track->summaryValue(N_nextToInnermostHit, numberOfNextToInnermostPixelLayerHits) ) {
553  ATH_MSG_WARNING("Track summary retrieval failed for 'numberOfNextToInnermostPixelLayerHits'");
554  return StatusCode::FAILURE;
555  if(N_nextToInnermostHit==0 ) {
556  ATH_MSG_VERBOSE("Accept nearby track w/o next-to-innermost hit");
557  tracklist.insert(track);
558  }
559  }
560  }
561 
562  } // end dR check
563  } // end extra track loop
564  return StatusCode::SUCCESS;
565  }
566 
567 
569 
570  bool has_unmatched=false;
571  float totSumpt=0;
572  float unmatchedSumpt=0;
573  float unmatchedE=0;
574  float unmatchedTotEMFrac=0;
575  double emfrac=0;
576 
577  static const SG::AuxElement::Decorator<Float_t> dec_unmatchedFrac("unmatchedFrac");
578  static const SG::AuxElement::Decorator<Float_t> dec_unmatchedFracSumpt("unmatchedFracSumpt");
579  static const SG::AuxElement::Decorator<Float_t> dec_unmatchedFracPt("unmatchedFracPt");
580  static const SG::AuxElement::Decorator<Float_t> dec_unmatchedFracE("unmatchedFracE");
581  static const SG::AuxElement::Decorator<Float_t> dec_unmatchedFracEClusterPFO("unmatchedFracEClusterPFO");
582  static const SG::AuxElement::Decorator<Float_t> dec_unmatchedFracPtClusterPFO("unmatchedFracPtClusterPFO");
583  static const SG::AuxElement::Decorator<Float_t> dec_unmatchedTotEMFrac("unmatchedTotEMFrac");
584 
585  TLorentzVector totVec(0.,0.,0.,0.), unmatchedVec(0.,0.,0.,0.);
586  const std::vector<const xAOD::CaloCluster*> egClusters = xAOD::EgammaHelpers::getAssociatedTopoClusters(eg->caloCluster());
587  std::set<const xAOD::CaloCluster*> cPFOClusters;
588  int nCluscPFO = pfo->nCaloCluster();
589 
590  for (int cl = 0; cl < nCluscPFO; ++cl) {
591  if (pfo->cluster(cl)) cPFOClusters.insert( pfo->cluster(cl) );
592  }
593 
594  std::vector<const xAOD::CaloCluster*> unmatchedClusters;
595  for (const xAOD::CaloCluster* pfoclus : cPFOClusters) {
596  TLorentzVector tmpVec;
597  tmpVec.SetPtEtaPhiE(pfoclus->pt(),pfoclus->eta(),pfoclus->phi(),pfoclus->e());
598  totSumpt+=pfoclus->pt();
599  totVec+=tmpVec;
600  bool inEgamma = false;
601  for (const xAOD::CaloCluster* phclus : egClusters) {
602  if (pfoclus == phclus) {
603  inEgamma = true;
604  }
605  }
606  if (!inEgamma) {
607  unmatchedClusters.push_back(pfoclus);
608  unmatchedSumpt+=pfoclus->pt();
609  unmatchedE+=pfoclus->e();
610  unmatchedVec+=tmpVec;
611  pfoclus->retrieveMoment(xAOD::CaloCluster::ENG_FRAC_EM ,emfrac);
612  unmatchedTotEMFrac=unmatchedTotEMFrac+emfrac*pfoclus->e();
613  }
614 
615  }
616 
617  ATH_MSG_DEBUG("PFO associated to "<<nCluscPFO<< " cluster, of which " << unmatchedClusters.size() << "unmatched one and unmatched pt "<<unmatchedSumpt);
618  dec_unmatchedFrac(*pfo)=nCluscPFO>0 ? float(unmatchedClusters.size())/float(nCluscPFO) : -1;
619  dec_unmatchedFracPt(*pfo)= totVec.Pt()>0 ? float(unmatchedVec.Pt()/totVec.Pt()): -1;
620  dec_unmatchedFracSumpt(*pfo)= totSumpt>0 ? float(unmatchedSumpt/totSumpt): -1;
621  dec_unmatchedFracE(*pfo)= totVec.E()>0 ? float(unmatchedE/totVec.E()): -1;
622  dec_unmatchedTotEMFrac(*pfo)= totVec.E()>0 ? float(unmatchedTotEMFrac/totVec.E()): -1;
623  dec_unmatchedFracEClusterPFO(*pfo)= pfo->e()>0 ? float(unmatchedE/pfo->e()): -1;
624  dec_unmatchedFracPtClusterPFO(*pfo)= pfo->pt()>0 ? float(unmatchedE/pfo->pt()): -1;
625 
626  return has_unmatched;
627  }
628 
629 
630 
631 }
632 
met::METAssociator::greaterPt
static bool greaterPt(const xAOD::IParticle *part1, const xAOD::IParticle *part2)
Definition: METAssociator.h:144
met::METEgammaAssociator::m_checkUnmatched
bool m_checkUnmatched
Definition: METEgammaAssociator.h:114
xAOD::Electron
Electron_v1 Electron
Definition of the current "egamma version".
Definition: Event/xAOD/xAODEgamma/xAODEgamma/Electron.h:17
xAOD::EgammaHelpers::getAssociatedTopoClusters
std::vector< const xAOD::CaloCluster * > getAssociatedTopoClusters(const xAOD::CaloCluster *cluster)
Return a vector of all the topo clusters associated with the egamma cluster.
Definition: EgammaxAODHelpers.cxx:66
xAOD::PFO_v1::pt
virtual double pt() const
The transverse momentum ( ) of the particle.
Definition: PFO_v1.cxx:52
met::METEgammaAssociator::m_tcMatch_maxRat
double m_tcMatch_maxRat
Definition: METEgammaAssociator.h:99
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
xAOD::uint8_t
uint8_t
Definition: Muon_v1.cxx:575
ParticleTest.eg
eg
Definition: ParticleTest.py:29
met::METAssociator::m_useFELinks
bool m_useFELinks
Definition: METAssociator.h:94
xAODP4Helpers.h
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
Egamma
Definition: ClusMomentumPlots.cxx:11
met::METEgammaAssociator::extractFE
StatusCode extractFE(const xAOD::IParticle *obj, std::vector< const xAOD::IParticle * > &felist, const met::METAssociator::ConstitHolder &constits, std::map< const xAOD::IParticle *, MissingETBase::Types::constvec_t > &momenta) const final
Definition: METEgammaAssociator.cxx:304
met::DeltaR
@ DeltaR
Definition: METRecoCommon.h:11
met::METEgammaAssociator::extractTracks
StatusCode extractTracks(const xAOD::IParticle *obj, std::vector< const xAOD::IParticle * > &constlist, const met::METAssociator::ConstitHolder &constits) const final
Definition: METEgammaAssociator.cxx:132
met::METEgammaAssociator::m_tcMatch_method
unsigned short m_tcMatch_method
Definition: METEgammaAssociator.h:100
met::METEgammaAssociator::extractPFO
StatusCode extractPFO(const xAOD::IParticle *obj, std::vector< const xAOD::IParticle * > &pfolist, const met::METAssociator::ConstitHolder &constits, std::map< const xAOD::IParticle *, MissingETBase::Types::constvec_t > &momenta) const final
Definition: METEgammaAssociator.cxx:147
met::METEgammaAssociator::initialize
StatusCode initialize()
Dummy implementation of the initialisation function.
Definition: METEgammaAssociator.cxx:60
met::METAssociator::ConstitHolder::pfoCont
const xAOD::PFOContainer * pfoCont
Definition: METAssociator.h:66
xAOD
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
Definition: ICaloAffectedTool.h:24
xAOD::EgammaHelpers::getTrackParticles
std::set< const xAOD::TrackParticle * > getTrackParticles(const xAOD::Egamma *eg, bool useBremAssoc=true, bool allParticles=true)
Return a list of all or only the best TrackParticle associated to the object.
Definition: EgammaxAODHelpers.cxx:121
xAOD::expectInnermostPixelLayerHit
@ expectInnermostPixelLayerHit
Do we expect a 0th-layer barrel hit for this track?
Definition: TrackingPrimitives.h:236
met::METAssociator::ConstitHolder::feCont
const xAOD::FlowElementContainer * feCont
Definition: METAssociator.h:67
xAOD::Egamma_v1
Definition: Egamma_v1.h:56
SG::ConstAccessor
Helper class to provide constant type-safe access to aux data.
Definition: ConstAccessor.h:54
xAOD::FlowElement_v1::pt
virtual double pt() const override
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
P4Helpers::isInDeltaR
bool isInDeltaR(const I4Momentum &p1, const I4Momentum &p2, double dR)
Check if 2 I4Momentum are in a cone.
Definition: P4Helpers.h:223
METEgammaAssociator.h
xAOD::IParticle
Class providing the definition of the 4-vector interface.
Definition: Event/xAOD/xAODBase/xAODBase/IParticle.h:40
met::METAssociator::m_useRapidity
bool m_useRapidity
Definition: METAssociator.h:105
met::METEgammaAssociator::~METEgammaAssociator
virtual ~METEgammaAssociator()
met::METEgammaAssociator::METEgammaAssociator
METEgammaAssociator()
Default constructor:
met::METEgammaAssociator::m_tcMatch_dR
double m_tcMatch_dR
Definition: METEgammaAssociator.h:98
xAOD::FlowElement_v1::PFlow
@ PFlow
Definition: FlowElement_v1.h:45
met::METEgammaAssociator::extractFEs
StatusCode extractFEs(const xAOD::Egamma *eg, std::vector< const xAOD::IParticle * > &felist, const met::METAssociator::ConstitHolder &constits) const
Definition: METEgammaAssociator.cxx:384
met::METAssociator::ConstitHolder::pv
const xAOD::Vertex * pv
Definition: METAssociator.h:68
xAOD::PFO_v1::e
virtual double e() const
The total energy of the particle.
Definition: PFO_v1.cxx:81
xAOD::FlowElement_v1::isCharged
bool isCharged() const
Definition: FlowElement_v1.cxx:56
met::METEgammaAssociator::selectEgammaTracks
StatusCode selectEgammaTracks(const xAOD::Egamma *el, const xAOD::TrackParticleContainer *trkCont, std::set< const xAOD::TrackParticle * > &tracklist) const
Definition: METEgammaAssociator.cxx:507
met::METAssociator::ConstitHolder::tcCont
const xAOD::IParticleContainer * tcCont
Definition: METAssociator.h:65
xAOD::CaloCluster_v1
Description of a calorimeter cluster.
Definition: CaloCluster_v1.h:59
met::METEgammaAssociator::extractFEsFromLinks
StatusCode extractFEsFromLinks(const xAOD::Egamma *eg, std::vector< const xAOD::IParticle * > &felist, const met::METAssociator::ConstitHolder &constits) const
Definition: METEgammaAssociator.cxx:320
EgammaxAODHelpers.h
met
Definition: IMETSignificance.h:24
met::METAssociator::initialize
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
Definition: METAssociator.cxx:85
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
xAOD::expectNextToInnermostPixelLayerHit
@ expectNextToInnermostPixelLayerHit
Do we expect a 1st-layer barrel hit for this track?
Definition: TrackingPrimitives.h:247
xAOD::PFO_v1::nCaloCluster
unsigned int nCaloCluster() const
Find out how many CaloCluster are linked.
Definition: PFO_v1.cxx:659
SG::ReadDecorHandle
Handle class for reading a decoration on an object.
Definition: StoreGate/StoreGate/ReadDecorHandle.h:94
SG::Decorator
Helper class to provide type-safe access to aux data.
Definition: Decorator.h:58
ElectronContainer.h
met::METEgammaAssociator::m_photonNeutralFEReadDecorKey
SG::ReadDecorHandleKey< xAOD::PhotonContainer > m_photonNeutralFEReadDecorKey
Definition: METEgammaAssociator.h:106
met::METEgammaAssociator::m_photonNeutralPFOReadDecorKey
SG::ReadDecorHandleKey< xAOD::PhotonContainer > m_photonNeutralPFOReadDecorKey
Definition: METEgammaAssociator.h:104
met::METEgammaAssociator::extractPFOsFromLinks
StatusCode extractPFOsFromLinks(const xAOD::Egamma *eg, std::vector< const xAOD::IParticle * > &pfolist, const met::METAssociator::ConstitHolder &constits) const
Definition: METEgammaAssociator.cxx:162
xAOD::EgammaParameters::AuthorAmbiguous
const uint16_t AuthorAmbiguous
Object Reconstructed by standard cluster-based algorithm.
Definition: EgammaDefs.h:32
met::METAssociator::greaterPtPFO
static bool greaterPtPFO(const xAOD::PFO *part1, const xAOD::PFO *part2)
Definition: METAssociator.h:147
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
met::ClusterLink
@ ClusterLink
Definition: METRecoCommon.h:12
xAOD::FlowElement_v1::signalType
signal_t signalType() const
plotIsoValidation.el
el
Definition: plotIsoValidation.py:197
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
SG::AuxElement::index
size_t index() const
Return the index of this element within its container.
met::METEgammaAssociator::m_electronNeutralFEReadDecorKey
SG::ReadDecorHandleKey< xAOD::ElectronContainer > m_electronNeutralFEReadDecorKey
Definition: METEgammaAssociator.h:111
DataVector< xAOD::TrackParticle_v1 >
Vertex.h
met::METEgammaAssociator::m_electronNeutralPFOReadDecorKey
SG::ReadDecorHandleKey< xAOD::ElectronContainer > m_electronNeutralPFOReadDecorKey
Definition: METEgammaAssociator.h:109
xAOD::IParticle::pt
virtual double pt() const =0
The transverse momentum ( ) of the particle.
met::METAssociator
Definition: METAssociator.h:55
xAOD::FlowElement_v1::chargedObject
const xAOD::IParticle * chargedObject(std::size_t i) const
Definition: FlowElement_v1.cxx:127
met::METEgammaAssociator::extractTopoClusters
StatusCode extractTopoClusters(const xAOD::IParticle *obj, std::vector< const xAOD::IParticle * > &tclist, const met::METAssociator::ConstitHolder &constits) const final
Definition: METEgammaAssociator.cxx:84
xAOD::numberOfNextToInnermostPixelLayerHits
@ numberOfNextToInnermostPixelLayerHits
these are the hits in the 1st pixel barrel layer
Definition: TrackingPrimitives.h:248
xAOD::CaloCluster_v1::ENG_FRAC_EM
@ ENG_FRAC_EM
Energy fraction in EM calorimeters.
Definition: CaloCluster_v1.h:139
met::METEgammaAssociator::m_electronChargedFEReadDecorKey
SG::ReadDecorHandleKey< xAOD::ElectronContainer > m_electronChargedFEReadDecorKey
Definition: METEgammaAssociator.h:112
xAOD::PFO_v1::eEM
virtual double eEM() const
get EM scale energy
Definition: PFO_v1.cxx:233
xAOD::PFO_v1
Class describing a particle flow object.
Definition: PFO_v1.h:35
ANA_MSG_VERBOSE
#define ANA_MSG_VERBOSE(xmsg)
Macro printing verbose messages.
Definition: Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h:286
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
xAOD::FlowElement_v1::e
virtual double e() const override
The total energy of the particle.
Definition: FlowElement_v1.cxx:25
met::METAssociator::isGoodEoverP
bool isGoodEoverP(const xAOD::TrackParticle *trk) const
Definition: METAssociator.cxx:367
met::METAssociator::acceptTrack
bool acceptTrack(const xAOD::TrackParticle *trk, const xAOD::Vertex *pv) const
Definition: METAssociator.cxx:359
met::METEgammaAssociator::extractPFOs
StatusCode extractPFOs(const xAOD::Egamma *eg, std::vector< const xAOD::IParticle * > &pfolist, const met::METAssociator::ConstitHolder &constits) const
Definition: METEgammaAssociator.cxx:226
xAOD::Photon
Photon_v1 Photon
Definition of the current "egamma version".
Definition: Event/xAOD/xAODEgamma/xAODEgamma/Photon.h:17
met::METEgammaAssociator::hasUnmatchedClusters
bool hasUnmatchedClusters(const xAOD::Egamma *eg, const xAOD::PFO *pfo) const
Definition: METEgammaAssociator.cxx:568
met::METEgammaAssociator::m_extraTrkMatch_dR
double m_extraTrkMatch_dR
Definition: METEgammaAssociator.h:102
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
met::METAssociator::m_usePFOLinks
bool m_usePFOLinks
Definition: METAssociator.h:93
xAOD::PFO_v1::cluster
const CaloCluster * cluster(unsigned int index) const
Retrieve a const pointer to a CaloCluster.
Definition: PFO_v1.cxx:669
met::METEgammaAssociator::m_photonChargedFEReadDecorKey
SG::ReadDecorHandleKey< xAOD::PhotonContainer > m_photonChargedFEReadDecorKey
Definition: METEgammaAssociator.h:107
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
met::METAssociator::ConstitHolder::trkCont
const xAOD::TrackParticleContainer * trkCont
Definition: METAssociator.h:63
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
met::METEgammaAssociator::selectEgammaClusters
StatusCode selectEgammaClusters(const xAOD::CaloCluster *swclus, const std::vector< const xAOD::IParticle * > &inputTC, std::vector< const xAOD::IParticle * > &tclist) const
Definition: METEgammaAssociator.cxx:471
met::METAssociator::greaterPtFE
static bool greaterPtFE(const xAOD::FlowElement *part1, const xAOD::FlowElement *part2)
Definition: METAssociator.h:153
met::METEgammaAssociator::m_electronChargedPFOReadDecorKey
SG::ReadDecorHandleKey< xAOD::ElectronContainer > m_electronChargedPFOReadDecorKey
Definition: METEgammaAssociator.h:110
python.PyAthena.obj
obj
Definition: PyAthena.py:135
met::METAssociator::m_cleanChargedPFO
bool m_cleanChargedPFO
Definition: METAssociator.h:109
dq_make_web_display.cl
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition: dq_make_web_display.py:26
met::METEgammaAssociator::finalize
StatusCode finalize()
Definition: METEgammaAssociator.cxx:75
PhotonContainer.h
xAOD::CaloCluster_v1::e
virtual double e() const
The total energy of the particle.
Definition: CaloCluster_v1.cxx:265
readCCLHist.float
float
Definition: readCCLHist.py:83
met::METAssociator::ConstitHolder
Definition: METAssociator.h:62
xAOD::IParticle::e
virtual double e() const =0
The total energy of the particle.
xAOD::numberOfInnermostPixelLayerHits
@ numberOfInnermostPixelLayerHits
these are the hits in the 0th pixel barrel layer
Definition: TrackingPrimitives.h:237
met::METEgammaAssociator::m_photonChargedPFOReadDecorKey
SG::ReadDecorHandleKey< xAOD::PhotonContainer > m_photonChargedPFOReadDecorKey
Definition: METEgammaAssociator.h:105
xAOD::FlowElement_v1
A detector object made of other lower level object(s)
Definition: FlowElement_v1.h:25