CMS 3D CMS Logo

PFEGammaAlgo.cc
Go to the documentation of this file.
21 
22 #include <TFile.h>
23 #include <TVector2.h>
24 #include <iomanip>
25 #include <algorithm>
26 #include <functional>
27 #include <numeric>
28 #include <TMath.h>
29 
30 // include combinations header (was never incorporated in boost)
31 #include "combination.hpp"
32 
33 // just for now do this
34 //#define PFLOW_DEBUG
35 
36 #ifdef PFLOW_DEBUG
37 #define docast(x, y) dynamic_cast<x>(y)
38 #define LOGVERB(x) edm::LogVerbatim(x)
39 #define LOGWARN(x) edm::LogWarning(x)
40 #define LOGERR(x) edm::LogError(x)
41 #define LOGDRESSED(x) edm::LogInfo(x)
42 #else
43 #define docast(x, y) static_cast<x>(y)
44 #define LOGVERB(x) LogTrace(x)
45 #define LOGWARN(x) edm::LogWarning(x)
46 #define LOGERR(x) edm::LogError(x)
47 #define LOGDRESSED(x) LogDebug(x)
48 #endif
49 
50 using namespace std;
51 using namespace reco;
52 using namespace std::placeholders; // for _1, _2, _3...
53 
54 namespace {
55  typedef PFEGammaAlgo::PFSCElement SCElement;
56  typedef PFEGammaAlgo::EEtoPSAssociation EEtoPSAssociation;
57  typedef std::pair<CaloClusterPtr::key_type, CaloClusterPtr> EEtoPSElement;
58  typedef PFEGammaAlgo::PFClusterElement ClusterElement;
59 
60  class SeedMatchesToProtoObject {
61  public:
62  SeedMatchesToProtoObject(const reco::ElectronSeedRef& s)
63  : scfromseed_(s->caloCluster().castTo<reco::SuperClusterRef>()) {
64  ispfsc_ = false;
65  if (scfromseed_.isNonnull()) {
66  const edm::Ptr<reco::PFCluster> testCast(scfromseed_->seed());
67  ispfsc_ = testCast.isNonnull();
68  }
69  }
70  bool operator()(const PFEGammaAlgo::ProtoEGObject& po) {
71  if (scfromseed_.isNull() || !po.parentSC)
72  return false;
73  if (ispfsc_) {
74  return (scfromseed_->seed() == po.parentSC->superClusterRef()->seed());
75  }
76  return (scfromseed_->seed()->seed() == po.parentSC->superClusterRef()->seed()->seed());
77  }
78 
79  private:
80  const reco::SuperClusterRef scfromseed_;
81  bool ispfsc_;
82  };
83 
84  template <bool useConvs = false>
85  bool elementNotCloserToOther(const reco::PFBlockRef& block,
86  const PFBlockElement::Type& keytype,
87  const size_t key,
88  const PFBlockElement::Type& valtype,
89  const size_t test,
90  const float EoPin_cut = 1.0e6) {
92  auto elemkey = &(block->elements()[key]);
93  // this is inside out but I just want something that works right now
94  switch (elemkey->type()) {
96  const reco::PFBlockElementGsfTrack* elemasgsf = docast(const reco::PFBlockElementGsfTrack*, elemkey);
97  if (elemasgsf && valtype == PFBlockElement::ECAL) {
98  const ClusterElement* elemasclus = static_cast<const ClusterElement*>(&(block->elements()[test]));
99  float cluster_e = elemasclus->clusterRef()->correctedEnergy();
100  float trk_pin = elemasgsf->Pin().P();
101  if (cluster_e / trk_pin > EoPin_cut) {
102  LOGDRESSED("elementNotCloserToOther") << "GSF track failed EoP cut to match with cluster!";
103  return false;
104  }
105  }
106  } break;
108  const reco::PFBlockElementTrack* elemaskf = docast(const reco::PFBlockElementTrack*, elemkey);
109  if (elemaskf && valtype == PFBlockElement::ECAL) {
110  const ClusterElement* elemasclus = static_cast<const ClusterElement*>(&(block->elements()[test]));
111  float cluster_e = elemasclus->clusterRef()->correctedEnergy();
112  float trk_pin = std::sqrt(elemaskf->trackRef()->innerMomentum().mag2());
113  if (cluster_e / trk_pin > EoPin_cut) {
114  LOGDRESSED("elementNotCloserToOther") << "KF track failed EoP cut to match with cluster!";
115  return false;
116  }
117  }
118  } break;
119  default:
120  break;
121  }
122 
123  const float dist = block->dist(key, test, block->linkData(), reco::PFBlock::LINKTEST_ALL);
124  if (dist == -1.0f)
125  return false; // don't associate non-linked elems
126  std::multimap<double, unsigned> dists_to_val;
127  block->associatedElements(test, block->linkData(), dists_to_val, keytype, reco::PFBlock::LINKTEST_ALL);
128 
129  for (const auto& valdist : dists_to_val) {
130  const size_t idx = valdist.second;
131  // check track types for conversion info
132  switch (keytype) {
134  const reco::PFBlockElementGsfTrack* elemasgsf =
135  docast(const reco::PFBlockElementGsfTrack*, &(block->elements()[idx]));
136  if (!useConvs && elemasgsf->trackType(ConvType))
137  return false;
138  if (elemasgsf && valtype == PFBlockElement::ECAL) {
139  const ClusterElement* elemasclus = docast(const ClusterElement*, &(block->elements()[test]));
140  float cluster_e = elemasclus->clusterRef()->correctedEnergy();
141  float trk_pin = elemasgsf->Pin().P();
142  if (cluster_e / trk_pin > EoPin_cut)
143  continue;
144  }
145  } break;
147  const reco::PFBlockElementTrack* elemaskf =
148  docast(const reco::PFBlockElementTrack*, &(block->elements()[idx]));
149  if (!useConvs && elemaskf->trackType(ConvType))
150  return false;
151  if (elemaskf && valtype == PFBlockElement::ECAL) {
152  const ClusterElement* elemasclus = static_cast<const ClusterElement*>(&(block->elements()[test]));
153  float cluster_e = elemasclus->clusterRef()->correctedEnergy();
154  float trk_pin = std::sqrt(elemaskf->trackRef()->innerMomentum().mag2());
155  if (cluster_e / trk_pin > EoPin_cut)
156  continue;
157  }
158  } break;
159  default:
160  break;
161  }
162  if (valdist.first < dist && idx != key) {
163  LOGDRESSED("elementNotCloserToOther")
164  << "key element of type " << keytype << " is closer to another element of type" << valtype << std::endl;
165  return false; // false if closer element of specified type found
166  }
167  }
168  return true;
169  }
170 
171  template <class Element1, class Element2>
172  bool compatibleEoPOut(const Element1& e, const Element2& comp) {
173  if (PFBlockElement::ECAL != e.type()) {
174  return false;
175  }
176  const ClusterElement& elemascluster = docast(ClusterElement const&, e);
177  const float gsf_eta_diff = std::abs(comp.positionAtECALEntrance().eta() - comp.Pout().eta());
178  const reco::PFClusterRef& cRef = elemascluster.clusterRef();
179  return (gsf_eta_diff <= 0.3 && cRef->energy() / comp.Pout().t() <= 5);
180  }
181 
183 
184  template <PFBlockElement::Type keytype, PFBlockElement::Type valtype, bool useConv = false>
185 
186  struct NotCloserToOther {
187  const reco::PFBlockElement* comp;
188  const reco::PFBlockRef& block;
189  const float EoPin_cut;
190  NotCloserToOther(const reco::PFBlockRef& b, const reco::PFBlockElement* e, const float EoPcut = 1.0e6)
191  : comp(e), block(b), EoPin_cut(EoPcut) {}
192  template <class T>
193  bool operator()(const T& e) {
194  if (!e.flag() || valtype != e->type())
195  return false;
196  return elementNotCloserToOther<useConv>(block, keytype, comp->index(), valtype, e->index(), EoPin_cut);
197  }
198  };
199 
200  struct LesserByDistance {
201  const reco::PFBlockElement* comp;
202  const reco::PFBlockRef& block;
204  LesserByDistance(const reco::PFBlockRef& b, const reco::PFBlock::LinkData& l, const reco::PFBlockElement* e)
205  : comp(e), block(b), links(l) {}
206  bool operator()(FlaggedPtr<const reco::PFBlockElement> const& e1,
208  double dist1 = block->dist(comp->index(), e1->index(), links, reco::PFBlock::LINKTEST_ALL);
209  double dist2 = block->dist(comp->index(), e2->index(), links, reco::PFBlock::LINKTEST_ALL);
210  dist1 = (dist1 == -1.0 ? 1e6 : dist1);
211  dist2 = (dist2 == -1.0 ? 1e6 : dist2);
212  return dist1 < dist2;
213  }
214  };
215 
216  bool isROLinkedByClusterOrTrack(const PFEGammaAlgo::ProtoEGObject& RO1, const PFEGammaAlgo::ProtoEGObject& RO2) {
217  // also don't allow ROs where both have clusters
218  // and GSF tracks to merge (10 Dec 2013)
219  if (!RO1.primaryGSFs.empty() && !RO2.primaryGSFs.empty()) {
220  LOGDRESSED("isROLinkedByClusterOrTrack") << "cannot merge, both have GSFs!" << std::endl;
221  return false;
222  }
223  // don't allow EB/EE to mix (11 Sept 2013)
224  if (!RO1.ecalclusters.empty() && !RO2.ecalclusters.empty()) {
225  if (RO1.ecalclusters.front()->clusterRef()->layer() != RO2.ecalclusters.front()->clusterRef()->layer()) {
226  LOGDRESSED("isROLinkedByClusterOrTrack") << "cannot merge, different ECAL types!" << std::endl;
227  return false;
228  }
229  }
230  const reco::PFBlockRef& blk = RO1.parentBlock;
231  bool not_closer;
232  // check links track -> cluster
233  for (const auto& cluster : RO1.ecalclusters) {
234  for (const auto& primgsf : RO2.primaryGSFs) {
235  not_closer = elementNotCloserToOther(blk, cluster->type(), cluster->index(), primgsf->type(), primgsf->index());
236  if (not_closer) {
237  LOGDRESSED("isROLinkedByClusterOrTrack") << "merged by cluster to primary GSF" << std::endl;
238  return true;
239  } else {
240  LOGDRESSED("isROLinkedByClusterOrTrack") << "cluster to primary GSF failed since"
241  << " cluster closer to another GSF" << std::endl;
242  }
243  }
244  for (const auto& primkf : RO2.primaryKFs) {
245  not_closer = elementNotCloserToOther(blk, cluster->type(), cluster->index(), primkf->type(), primkf->index());
246  if (not_closer) {
247  LOGDRESSED("isROLinkedByClusterOrTrack") << "merged by cluster to primary KF" << std::endl;
248  return true;
249  }
250  }
251  for (const auto& secdkf : RO2.secondaryKFs) {
252  not_closer = elementNotCloserToOther(blk, cluster->type(), cluster->index(), secdkf->type(), secdkf->index());
253  if (not_closer) {
254  LOGDRESSED("isROLinkedByClusterOrTrack") << "merged by cluster to secondary KF" << std::endl;
255  return true;
256  }
257  }
258  // check links brem -> cluster
259  for (const auto& brem : RO2.brems) {
260  not_closer = elementNotCloserToOther(blk, cluster->type(), cluster->index(), brem->type(), brem->index());
261  if (not_closer) {
262  LOGDRESSED("isROLinkedByClusterOrTrack") << "merged by cluster to brem KF" << std::endl;
263  return true;
264  }
265  }
266  }
267  // check links primary gsf -> secondary kf
268  for (const auto& primgsf : RO1.primaryGSFs) {
269  for (const auto& secdkf : RO2.secondaryKFs) {
270  not_closer = elementNotCloserToOther(blk, primgsf->type(), primgsf->index(), secdkf->type(), secdkf->index());
271  if (not_closer) {
272  LOGDRESSED("isROLinkedByClusterOrTrack") << "merged by GSF to secondary KF" << std::endl;
273  return true;
274  }
275  }
276  }
277  // check links primary kf -> secondary kf
278  for (const auto& primkf : RO1.primaryKFs) {
279  for (const auto& secdkf : RO2.secondaryKFs) {
280  not_closer = elementNotCloserToOther(blk, primkf->type(), primkf->index(), secdkf->type(), secdkf->index());
281  if (not_closer) {
282  LOGDRESSED("isROLinkedByClusterOrTrack") << "merged by primary KF to secondary KF" << std::endl;
283  return true;
284  }
285  }
286  }
287  // check links secondary kf -> secondary kf
288  for (const auto& secdkf1 : RO1.secondaryKFs) {
289  for (const auto& secdkf2 : RO2.secondaryKFs) {
290  not_closer =
291  elementNotCloserToOther<true>(blk, secdkf1->type(), secdkf1->index(), secdkf2->type(), secdkf2->index());
292  if (not_closer) {
293  LOGDRESSED("isROLinkedByClusterOrTrack") << "merged by secondary KF to secondary KF" << std::endl;
294  return true;
295  }
296  }
297  }
298  return false;
299  }
300 
301  bool testIfROMergableByLink(const PFEGammaAlgo::ProtoEGObject& ro, PFEGammaAlgo::ProtoEGObject& comp) {
302  const bool result = (isROLinkedByClusterOrTrack(comp, ro) || isROLinkedByClusterOrTrack(ro, comp));
303  return result;
304  }
305 
306  std::vector<const ClusterElement*> getSCAssociatedECALsSafe(
308  std::vector<const ClusterElement*> cluster_list;
309  auto sccl = scref->clustersBegin();
310  auto scend = scref->clustersEnd();
311  auto pfc = ecals.begin();
312  auto pfcend = ecals.end();
313  for (; sccl != scend; ++sccl) {
314  std::vector<const ClusterElement*> matched_pfcs;
315  const double eg_energy = (*sccl)->energy();
316 
317  for (pfc = ecals.begin(); pfc != pfcend; ++pfc) {
318  const ClusterElement* pfcel = docast(const ClusterElement*, pfc->get());
319  const bool matched = ClusterClusterMapping::overlap(**sccl, *(pfcel->clusterRef()));
320  // need to protect against high energy clusters being attached
321  // to low-energy SCs
322  if (matched && pfcel->clusterRef()->energy() < 1.2 * scref->energy()) {
323  matched_pfcs.push_back(pfcel);
324  }
325  }
326  std::sort(matched_pfcs.begin(), matched_pfcs.end());
327 
328  double min_residual = 1e6;
329  std::vector<const ClusterElement*> best_comb;
330  for (size_t i = 1; i <= matched_pfcs.size(); ++i) {
331  //now we find the combination of PF-clusters which
332  //has the smallest energy residual with respect to the
333  //EG-cluster we are looking at now
334  do {
335  double energy = std::accumulate(
336  matched_pfcs.begin(), matched_pfcs.begin() + i, 0.0, [](const double a, const ClusterElement* c) {
337  return a + c->clusterRef()->energy();
338  });
339  const double resid = std::abs(energy - eg_energy);
340  if (resid < min_residual) {
341  best_comb.clear();
342  best_comb.reserve(i);
343  min_residual = resid;
344  best_comb.insert(best_comb.begin(), matched_pfcs.begin(), matched_pfcs.begin() + i);
345  }
346  } while (notboost::next_combination(matched_pfcs.begin(), matched_pfcs.begin() + i, matched_pfcs.end()));
347  }
348  for (const auto& clelem : best_comb) {
349  if (std::find(cluster_list.begin(), cluster_list.end(), clelem) == cluster_list.end()) {
350  cluster_list.push_back(clelem);
351  }
352  }
353  }
354  return cluster_list;
355  }
356  bool addPFClusterToROSafe(const ClusterElement* cl, PFEGammaAlgo::ProtoEGObject& RO) {
357  if (RO.ecalclusters.empty()) {
358  RO.ecalclusters.emplace_back(cl, true);
359  return true;
360  } else {
361  const PFLayer::Layer clayer = cl->clusterRef()->layer();
362  const PFLayer::Layer blayer = RO.ecalclusters.back()->clusterRef()->layer();
363  if (clayer == blayer) {
364  RO.ecalclusters.emplace_back(cl, true);
365  return true;
366  }
367  }
368  return false;
369  }
370 
371  // sets the cluster best associated to the GSF track
372  // leave it null if no GSF track
373  void setROElectronCluster(PFEGammaAlgo::ProtoEGObject& RO) {
374  if (RO.ecalclusters.empty())
375  return;
376  RO.lateBrem = -1;
377  RO.firstBrem = -1;
378  RO.nBremsWithClusters = -1;
379  const reco::PFBlockElementBrem *firstBrem = nullptr, *lastBrem = nullptr;
380  const reco::PFBlockElementCluster *bremCluster = nullptr, *gsfCluster = nullptr, *kfCluster = nullptr,
381  *gsfCluster_noassc = nullptr;
382  const reco::PFBlockRef& parent = RO.parentBlock;
383  int nBremClusters = 0;
384  constexpr float maxDist = 1e6;
385  float mDist_gsf(maxDist), mDist_gsf_noassc(maxDist), mDist_kf(maxDist);
386  for (const auto& cluster : RO.ecalclusters) {
387  for (const auto& gsf : RO.primaryGSFs) {
388  const bool hasclu =
389  elementNotCloserToOther(parent, gsf->type(), gsf->index(), cluster->type(), cluster->index());
390  const float deta = std::abs(cluster->clusterRef()->positionREP().eta() - gsf->positionAtECALEntrance().eta());
391  const float dphi = std::abs(
392  TVector2::Phi_mpi_pi(cluster->clusterRef()->positionREP().phi() - gsf->positionAtECALEntrance().phi()));
393  const float dist = std::hypot(deta, dphi);
394  if (hasclu && dist < mDist_gsf) {
395  gsfCluster = cluster.get();
396  mDist_gsf = dist;
397  } else if (dist < mDist_gsf_noassc) {
398  gsfCluster_noassc = cluster.get();
399  mDist_gsf_noassc = dist;
400  }
401  }
402  for (const auto& kf : RO.primaryKFs) {
403  const bool hasclu = elementNotCloserToOther(parent, kf->type(), kf->index(), cluster->type(), cluster->index());
404  const float dist = parent->dist(cluster->index(), kf->index(), parent->linkData(), reco::PFBlock::LINKTEST_ALL);
405  if (hasclu && dist < mDist_kf) {
406  kfCluster = cluster.get();
407  mDist_kf = dist;
408  }
409  }
410  for (const auto& brem : RO.brems) {
411  const bool hasclu =
412  elementNotCloserToOther(parent, brem->type(), brem->index(), cluster->type(), cluster->index());
413  if (hasclu) {
414  ++nBremClusters;
415  if (!firstBrem || (firstBrem->indTrajPoint() - 2 > brem->indTrajPoint() - 2)) {
416  firstBrem = brem;
417  }
418  if (!lastBrem || (lastBrem->indTrajPoint() - 2 < brem->indTrajPoint() - 2)) {
419  lastBrem = brem;
420  bremCluster = cluster.get();
421  }
422  }
423  }
424  }
425  if (!gsfCluster && !kfCluster && !bremCluster) {
426  gsfCluster = gsfCluster_noassc;
427  }
428  RO.nBremsWithClusters = nBremClusters;
429  RO.lateBrem = 0;
430  if (gsfCluster) {
431  RO.electronClusters.push_back(gsfCluster);
432  } else if (kfCluster) {
433  RO.electronClusters.push_back(kfCluster);
434  }
435  if (bremCluster && !gsfCluster && !kfCluster) {
436  RO.electronClusters.push_back(bremCluster);
437  }
438  if (firstBrem && RO.ecalclusters.size() > 1) {
439  RO.firstBrem = firstBrem->indTrajPoint() - 2;
440  if (bremCluster == gsfCluster)
441  RO.lateBrem = 1;
442  }
443  }
444 } // namespace
445 
447  GBRForests const& gbrForests,
448  EEtoPSAssociation const& eetops,
449  ESEEIntercalibConstants const& esEEInterCalib,
450  ESChannelStatus const& channelStatus,
452  : gbrForests_(gbrForests),
453  eetops_(eetops),
454  cfg_(cfg),
455  primaryVertex_(primaryVertex),
456  channelStatus_(channelStatus) {
458 }
459 
461  const reco::Vertex& primaryVtx,
462  unsigned int trackIndex) {
463  const reco::PFBlock& block = *blockRef;
465  //use this to store linkdata in the associatedElements function below
466  const PFBlock::LinkData& linkData = block.linkData();
467  //calculate MVA Variables
468  const float chi2 = elements[trackIndex].trackRef()->chi2() / elements[trackIndex].trackRef()->ndof();
469  const float nlost = elements[trackIndex].trackRef()->missingInnerHits();
470  const float nLayers = elements[trackIndex].trackRef()->hitPattern().trackerLayersWithMeasurement();
471  const float trackPt = elements[trackIndex].trackRef()->pt();
472  const float stip = elements[trackIndex].trackRefPF()->STIP();
473 
474  float linkedE = 0;
475  float linkedH = 0;
476  std::multimap<double, unsigned int> ecalAssoTrack;
477  block.associatedElements(
478  trackIndex, linkData, ecalAssoTrack, reco::PFBlockElement::ECAL, reco::PFBlock::LINKTEST_ALL);
479  std::multimap<double, unsigned int> hcalAssoTrack;
480  block.associatedElements(
481  trackIndex, linkData, hcalAssoTrack, reco::PFBlockElement::HCAL, reco::PFBlock::LINKTEST_ALL);
482  if (!ecalAssoTrack.empty()) {
483  for (auto& itecal : ecalAssoTrack) {
484  linkedE = linkedE + elements[itecal.second].clusterRef()->energy();
485  }
486  }
487  if (!hcalAssoTrack.empty()) {
488  for (auto& ithcal : hcalAssoTrack) {
489  linkedH = linkedH + elements[ithcal.second].clusterRef()->energy();
490  }
491  }
492  const float eOverPt = linkedE / elements[trackIndex].trackRef()->pt();
493  const float hOverPt = linkedH / elements[trackIndex].trackRef()->pt();
494  GlobalVector rvtx(elements[trackIndex].trackRef()->innerPosition().X() - primaryVtx.x(),
495  elements[trackIndex].trackRef()->innerPosition().Y() - primaryVtx.y(),
496  elements[trackIndex].trackRef()->innerPosition().Z() - primaryVtx.z());
497  double vtxPhi = rvtx.phi();
498  //delta Phi between conversion vertex and track
499  float delPhi = fabs(deltaPhi(vtxPhi, elements[trackIndex].trackRef()->innerMomentum().Phi()));
500 
501  float vars[] = {delPhi, nLayers, chi2, eOverPt, hOverPt, trackPt, stip, nlost};
502 
503  return gbrForests_.singleLeg_->GetAdaBoostClassifier(vars);
504 }
505 
507  switch (pfbe.type()) {
509  auto& elements = _currentblock->elements();
510  std::multimap<double, unsigned> tks;
511  _currentblock->associatedElements(
513  for (const auto& tk : tks) {
514  if (PFMuonAlgo::isMuon(elements[tk.second])) {
515  return true;
516  }
517  }
518  } break;
520  return PFMuonAlgo::isMuon(pfbe);
521  break;
522  default:
523  break;
524  }
525  return false;
526 }
527 
529  LOGVERB("PFEGammaAlgo") << "Resetting PFEGammaAlgo for new block and running!" << std::endl;
530 
531  // candidate collections:
532  // this starts off as an inclusive list of prototype objects built from
533  // supercluster/ecal-driven seeds and tracker driven seeds in a block
534  // it is then refined through by various cleanings, determining the energy
535  // flow.
536  // use list for constant-time removals
537  std::list<ProtoEGObject> refinableObjects;
538 
539  _splayedblock.clear();
540  _splayedblock.resize(13); // make sure that we always have the HGCAL entry
541 
543  _currentlinks = block->linkData();
544  //LOGDRESSED("PFEGammaAlgo") << *_currentblock << std::endl;
545  LOGVERB("PFEGammaAlgo") << "Splaying block" << std::endl;
546  //unwrap the PF block into a fast access map
547  for (const auto& pfelement : _currentblock->elements()) {
548  if (isMuon(pfelement))
549  continue; // don't allow muons in our element list
550  if (pfelement.type() == PFBlockElement::HCAL && pfelement.clusterRef()->flags() & reco::CaloCluster::badHcalMarker)
551  continue; // skip also dead area markers for now
552  const size_t itype = (size_t)pfelement.type();
553  if (itype >= _splayedblock.size())
554  _splayedblock.resize(itype + 1);
555  _splayedblock[itype].emplace_back(&pfelement, true);
556  }
557 
558  // show the result of splaying the tree if it's really *really* needed
559 #ifdef PFLOW_DEBUG
560  std::stringstream splayout;
561  for (size_t itype = 0; itype < _splayedblock.size(); ++itype) {
562  splayout << "\tType: " << itype << " indices: ";
563  for (const auto& flaggedelement : _splayedblock[itype]) {
564  splayout << flaggedelement->index() << ' ';
565  }
566  if (itype != _splayedblock.size() - 1)
567  splayout << std::endl;
568  }
569  LOGVERB("PFEGammaAlgo") << splayout.str();
570 #endif
571 
572  // precleaning of the ECAL clusters with respect to primary KF tracks
573  // we don't allow clusters in super clusters to be locked out this way
575 
576  initializeProtoCands(refinableObjects);
577  LOGDRESSED("PFEGammaAlgo") << "Initialized " << refinableObjects.size() << " proto-EGamma objects" << std::endl;
579 
580  //
581  // now we start the refining steps
582  //
583  //
584 
585  // --- Primary Linking Step ---
586  // since this is particle flow and we try to work from the pixels out
587  // we start by linking the tracks together and finding the ECAL clusters
588  for (auto& RO : refinableObjects) {
589  // find the KF tracks associated to GSF primary tracks
591  // do the same for HCAL clusters associated to the GSF
593  // link secondary KF tracks associated to primary KF tracks
595  // pick up clusters that are linked to the GSF primary
597  // link associated KF to ECAL (ECAL part grabs PS clusters too if able)
599  // now finally look for clusters associated to brem tangents
601  }
602 
603  LOGDRESSED("PFEGammaAlgo") << "Dumping after GSF and KF Track (Primary) Linking : " << std::endl;
605 
606  // merge objects after primary linking
607  mergeROsByAnyLink(refinableObjects);
608 
609  LOGDRESSED("PFEGammaAlgo") << "Dumping after first merging operation : " << std::endl;
611 
612  // --- Secondary Linking Step ---
613  // after this we go through the ECAL clusters on the remaining tracks
614  // and try to link those in...
615  for (auto& RO : refinableObjects) {
616  // look for conversion legs
619  // look for tracks that complement conversion legs
621  // look again for ECAL clusters (this time with an e/p cut)
623  }
624 
625  LOGDRESSED("PFEGammaAlgo") << "Dumping after ECAL to Track (Secondary) Linking : " << std::endl;
627 
628  // merge objects after primary linking
629  mergeROsByAnyLink(refinableObjects);
630 
631  LOGDRESSED("PFEGammaAlgo") << "There are " << refinableObjects.size() << " after the 2nd merging step." << std::endl;
633 
634  // -- unlinking and proto-object vetos, final sorting
635  for (auto& RO : refinableObjects) {
636  // remove secondary KFs (and possibly ECALs) matched to HCAL clusters
638  // remove secondary KFs and ECALs linked to them that have bad E/p_in
639  // and spoil the resolution
641  // put things back in order after partitioning
642  std::sort(RO.ecalclusters.begin(), RO.ecalclusters.end(), [](auto const& a, auto const& b) {
643  return (a->clusterRef()->correctedEnergy() > b->clusterRef()->correctedEnergy());
644  });
645  setROElectronCluster(RO);
646  }
647 
648  LOGDRESSED("PFEGammaAlgo") << "There are " << refinableObjects.size() << " after the unlinking and vetos step."
649  << std::endl;
651 
652  // fill the PF candidates and then build the refined SC
653  return fillPFCandidates(refinableObjects);
654 }
655 
656 void PFEGammaAlgo::initializeProtoCands(std::list<PFEGammaAlgo::ProtoEGObject>& egobjs) {
657  // step 1: build SC based proto-candidates
658  // in the future there will be an SC Et requirement made here to control
659  // block size
660  for (auto& element : _splayedblock[PFBlockElement::SC]) {
661  LOGDRESSED("PFEGammaAlgo") << "creating SC-based proto-object" << std::endl
662  << "\tSC at index: " << element->index() << " has type: " << element->type()
663  << std::endl;
664  element.setFlag(false);
665  ProtoEGObject fromSC;
666  fromSC.nBremsWithClusters = -1;
667  fromSC.firstBrem = -1;
668  fromSC.lateBrem = -1;
669  fromSC.parentBlock = _currentblock;
670  fromSC.parentSC = docast(const PFSCElement*, element.get());
671  // splay the supercluster so we can knock out used elements
672  bool sc_success = unwrapSuperCluster(fromSC.parentSC, fromSC.ecalclusters, fromSC.ecal2ps);
673  if (sc_success) {
674  /*
675  auto ins_pos = std::lower_bound(refinableObjects.begin(),
676  refinableObjects.end(),
677  fromSC,
678  [&](const ProtoEGObject& a,
679  const ProtoEGObject& b){
680  const double a_en =
681  a.parentSC->superClusterRef()->energy();
682  const double b_en =
683  b.parentSC->superClusterRef()->energy();
684  return a_en < b_en;
685  });
686  */
687  egobjs.insert(egobjs.end(), fromSC);
688  }
689  }
690  // step 2: build GSF-seed-based proto-candidates
691  reco::GsfTrackRef gsfref_forextra;
692  reco::TrackExtraRef gsftrk_extra;
693  reco::ElectronSeedRef theseedref;
694  for (auto& element : _splayedblock[PFBlockElement::GSF]) {
695  LOGDRESSED("PFEGammaAlgo") << "creating GSF-based proto-object" << std::endl
696  << "\tGSF at index: " << element->index() << " has type: " << element->type()
697  << std::endl;
698  const PFGSFElement* elementAsGSF = docast(const PFGSFElement*, element.get());
700  continue; // for now, do not allow dedicated brems to make proto-objects
701  }
702  element.setFlag(false);
703 
704  ProtoEGObject fromGSF;
705  fromGSF.nBremsWithClusters = -1;
706  fromGSF.firstBrem = -1;
707  fromGSF.lateBrem = 0;
708  gsfref_forextra = elementAsGSF->GsftrackRef();
709  gsftrk_extra = (gsfref_forextra.isAvailable() ? gsfref_forextra->extra() : reco::TrackExtraRef());
710  theseedref = (gsftrk_extra.isAvailable() ? gsftrk_extra->seedRef().castTo<reco::ElectronSeedRef>()
712  fromGSF.electronSeed = theseedref;
713  // exception if there's no seed
714  if (fromGSF.electronSeed.isNull() || !fromGSF.electronSeed.isAvailable()) {
715  std::stringstream gsf_err;
716  elementAsGSF->Dump(gsf_err, "\t");
717  throw cms::Exception("PFEGammaAlgo::initializeProtoCands()")
718  << "Found a GSF track with no seed! This should not happen!" << std::endl
719  << gsf_err.str() << std::endl;
720  }
721  // flag this GSF element as globally used and push back the track ref
722  // into the protocand
723  element.setFlag(false);
724  fromGSF.parentBlock = _currentblock;
725  fromGSF.primaryGSFs.push_back(elementAsGSF);
726  // add the directly matched brem tangents
727  for (auto& brem : _splayedblock[PFBlockElement::BREM]) {
728  float dist =
729  _currentblock->dist(elementAsGSF->index(), brem->index(), _currentlinks, reco::PFBlock::LINKTEST_ALL);
730  if (dist == 0.001f) {
731  const PFBremElement* eAsBrem = docast(const PFBremElement*, brem.get());
732  fromGSF.brems.push_back(eAsBrem);
733  fromGSF.localMap.insert(eAsBrem, elementAsGSF);
734  brem.setFlag(false);
735  }
736  }
737  // if this track is ECAL seeded reset links or import cluster
738  // tracker (this is pixel only, right?) driven seeds just get the GSF
739  // track associated since this only branches for ECAL Driven seeds
740  if (fromGSF.electronSeed->isEcalDriven()) {
741  // step 2a: either merge with existing ProtoEG object with SC or add
742  // SC directly to this proto EG object if not present
743  LOGDRESSED("PFEGammaAlgo") << "GSF-based proto-object is ECAL driven, merging SC-cand" << std::endl;
744  LOGVERB("PFEGammaAlgo") << "ECAL Seed Ptr: " << fromGSF.electronSeed.get()
745  << " isAvailable: " << fromGSF.electronSeed.isAvailable()
746  << " isNonnull: " << fromGSF.electronSeed.isNonnull() << std::endl;
747  SeedMatchesToProtoObject sctoseedmatch(fromGSF.electronSeed);
748  auto objsbegin = egobjs.begin();
749  auto objsend = egobjs.end();
750  // this auto is a std::list<ProtoEGObject>::iterator
751  auto clusmatch = std::find_if(objsbegin, objsend, sctoseedmatch);
752  if (clusmatch != objsend) {
753  fromGSF.parentSC = clusmatch->parentSC;
754  fromGSF.ecalclusters = std::move(clusmatch->ecalclusters);
755  fromGSF.ecal2ps = std::move(clusmatch->ecal2ps);
756  egobjs.erase(clusmatch);
757  } else if (fromGSF.electronSeed.isAvailable() && fromGSF.electronSeed.isNonnull()) {
758  // link tests in the gap region can current split a gap electron
759  // HEY THIS IS A WORK AROUND FOR A KNOWN BUG IN PFBLOCKALGO
760  // MAYBE WE SHOULD FIX IT??????????????????????????????????
761  LOGDRESSED("PFEGammaAlgo") << "Encountered the known GSF-SC splitting bug "
762  << " in PFBlockAlgo! We should really fix this!" << std::endl;
763  } else { // SC was not in a earlier proto-object
764  std::stringstream gsf_err;
765  elementAsGSF->Dump(gsf_err, "\t");
766  throw cms::Exception("PFEGammaAlgo::initializeProtoCands()")
767  << "Expected SuperCluster from ECAL driven GSF seed "
768  << "was not found in the block!" << std::endl
769  << gsf_err.str() << std::endl;
770  } // supercluster in block
771  } // is ECAL driven seed?
772 
773  egobjs.insert(egobjs.end(), fromGSF);
774  } // end loop on GSF elements of block
775 }
776 
779  ClusterMap& ecal2ps) {
780  ecalclusters.clear();
781  ecal2ps.clear();
782  LOGVERB("PFEGammaAlgo") << "Pointer to SC element: 0x" << std::hex << thesc << std::dec << std::endl
783  << "cleared ecalclusters and ecal2ps!" << std::endl;
784  auto ecalbegin = _splayedblock[reco::PFBlockElement::ECAL].begin();
785  auto ecalend = _splayedblock[reco::PFBlockElement::ECAL].end();
786  auto hgcalbegin = _splayedblock[reco::PFBlockElement::HGCAL].begin();
787  auto hgcalend = _splayedblock[reco::PFBlockElement::HGCAL].end();
788  if (ecalbegin == ecalend && hgcalbegin == hgcalend) {
789  LOGERR("PFEGammaAlgo::unwrapSuperCluster()") << "There are no ECAL elements in a block with imported SC!"
790  << " This is a bug we should fix this!" << std::endl;
791  return false;
792  }
793  reco::SuperClusterRef scref = thesc->superClusterRef();
794  const bool is_pf_sc = thesc->fromPFSuperCluster();
795  if (!(scref.isAvailable() && scref.isNonnull())) {
796  throw cms::Exception("PFEGammaAlgo::unwrapSuperCluster()")
797  << "SuperCluster pointed to by block element is null!" << std::endl;
798  }
799  LOGDRESSED("PFEGammaAlgo") << "Got a valid super cluster ref! 0x" << std::hex << scref.get() << std::dec << std::endl;
800  const size_t nscclusters = scref->clustersSize();
801  const size_t nscpsclusters = scref->preshowerClustersSize();
802  size_t npfpsclusters = 0;
803  size_t npfclusters = 0;
804  LOGDRESSED("PFEGammaAlgo") << "Precalculated cluster multiplicities: " << nscclusters << ' ' << nscpsclusters
805  << std::endl;
806  NotCloserToOther<reco::PFBlockElement::SC, reco::PFBlockElement::ECAL> ecalClustersInSC(_currentblock, thesc);
807  NotCloserToOther<reco::PFBlockElement::SC, reco::PFBlockElement::HGCAL> hgcalClustersInSC(_currentblock, thesc);
808  auto ecalfirstnotinsc = std::partition(ecalbegin, ecalend, ecalClustersInSC);
809  auto hgcalfirstnotinsc = std::partition(hgcalbegin, hgcalend, hgcalClustersInSC);
810  //reset the begin and end iterators
811  ecalbegin = _splayedblock[reco::PFBlockElement::ECAL].begin();
812  ecalend = _splayedblock[reco::PFBlockElement::ECAL].end();
813 
814  hgcalbegin = _splayedblock[reco::PFBlockElement::HGCAL].begin();
815  hgcalend = _splayedblock[reco::PFBlockElement::HGCAL].end();
816 
817  //get list of associated clusters by det id and energy matching
818  //(only needed when using non-pf supercluster)
819  std::vector<const ClusterElement*> safePFClusters =
820  is_pf_sc ? std::vector<const ClusterElement*>()
821  : getSCAssociatedECALsSafe(scref, _splayedblock[reco::PFBlockElement::ECAL]);
822 
823  if (ecalfirstnotinsc == ecalbegin && hgcalfirstnotinsc == hgcalbegin) {
824  LOGERR("PFEGammaAlgo::unwrapSuperCluster()") << "No associated block elements to SuperCluster!"
825  << " This is a bug we should fix!" << std::endl;
826  return false;
827  }
828  npfclusters = std::distance(ecalbegin, ecalfirstnotinsc) + std::distance(hgcalbegin, hgcalfirstnotinsc);
829  // ensure we have found the correct number of PF ecal clusters in the case
830  // that this is a PF supercluster, otherwise all bets are off
831  if (is_pf_sc && nscclusters != npfclusters) {
832  std::stringstream sc_err;
833  thesc->Dump(sc_err, "\t");
834  throw cms::Exception("PFEGammaAlgo::unwrapSuperCluster()")
835  << "The number of found ecal elements (" << nscclusters << ") in block is not the same as"
836  << " the number of ecal PF clusters reported by the PFSuperCluster"
837  << " itself (" << npfclusters << ")! This should not happen!" << std::endl
838  << sc_err.str() << std::endl;
839  }
840  for (auto ecalitr = ecalbegin; ecalitr != ecalfirstnotinsc; ++ecalitr) {
841  const PFClusterElement* elemascluster = docast(const PFClusterElement*, ecalitr->get());
842 
843  // reject clusters that really shouldn't be associated to the SC
844  // (only needed when using non-pf-supercluster)
845  if (!is_pf_sc && std::find(safePFClusters.begin(), safePFClusters.end(), elemascluster) == safePFClusters.end())
846  continue;
847 
848  //add cluster
849  ecalclusters.emplace_back(elemascluster, true);
850  //mark cluster as used
851  ecalitr->setFlag(false);
852 
853  // process the ES elements
854  // auto is a pair<Iterator,bool> here, bool is false when placing fails
855  auto emplaceresult = ecal2ps.emplace(elemascluster, ClusterMap::mapped_type());
856  if (!emplaceresult.second) {
857  std::stringstream clus_err;
858  elemascluster->Dump(clus_err, "\t");
859  throw cms::Exception("PFEGammaAlgo::unwrapSuperCluster()")
860  << "List of pointers to ECAL block elements contains non-unique items!"
861  << " This is very bad!" << std::endl
862  << "cluster ptr = 0x" << std::hex << elemascluster << std::dec << std::endl
863  << clus_err.str() << std::endl;
864  }
865  ClusterMap::mapped_type& eslist = emplaceresult.first->second;
866  npfpsclusters += attachPSClusters(elemascluster, eslist);
867  } // loop over ecal elements
868 
869  for (auto hgcalitr = hgcalbegin; hgcalitr != hgcalfirstnotinsc; ++hgcalitr) {
870  const PFClusterElement* elemascluster = docast(const PFClusterElement*, hgcalitr->get());
871 
872  // reject clusters that really shouldn't be associated to the SC
873  // (only needed when using non-pf-supercluster)
874  if (!is_pf_sc && std::find(safePFClusters.begin(), safePFClusters.end(), elemascluster) == safePFClusters.end())
875  continue;
876 
877  //add cluster
878  ecalclusters.emplace_back(elemascluster, true);
879  //mark cluster as used
880  hgcalitr->setFlag(false);
881  } // loop over ecal elements
882 
883  /*
884  if( is_pf_sc && nscpsclusters != npfpsclusters) {
885  std::stringstream sc_err;
886  thesc->Dump(sc_err,"\t");
887  throw cms::Exception("PFEGammaAlgo::unwrapSuperCluster()")
888  << "The number of found PF preshower elements ("
889  << npfpsclusters << ") in block is not the same as"
890  << " the number of preshower clusters reported by the PFSuperCluster"
891  << " itself (" << nscpsclusters << ")! This should not happen!"
892  << std::endl
893  << sc_err.str() << std::endl;
894  }
895  */
896 
897  LOGDRESSED("PFEGammaAlgo") << " Unwrapped SC has " << npfclusters << " ECAL sub-clusters"
898  << " and " << npfpsclusters << " PreShower layers 1 & 2 clusters!" << std::endl;
899  return true;
900 }
901 
902 int PFEGammaAlgo::attachPSClusters(const ClusterElement* ecalclus, ClusterMap::mapped_type& eslist) {
903  if (ecalclus->clusterRef()->layer() == PFLayer::ECAL_BARREL)
904  return 0;
905  edm::Ptr<reco::PFCluster> clusptr = refToPtr(ecalclus->clusterRef());
906  EEtoPSElement ecalkey(clusptr.key(), clusptr);
907  auto assc_ps =
908  std::equal_range(eetops_.cbegin(), eetops_.cend(), ecalkey, [](const EEtoPSElement& a, const EEtoPSElement& b) {
909  return a.first < b.first;
910  });
911  for (const auto& ps1 : _splayedblock[reco::PFBlockElement::PS1]) {
912  edm::Ptr<reco::PFCluster> temp = refToPtr(ps1->clusterRef());
913  for (auto pscl = assc_ps.first; pscl != assc_ps.second; ++pscl) {
914  if (pscl->second == temp) {
915  const ClusterElement* pstemp = docast(const ClusterElement*, ps1.get());
916  eslist.emplace_back(pstemp);
917  }
918  }
919  }
920  for (const auto& ps2 : _splayedblock[reco::PFBlockElement::PS2]) {
921  edm::Ptr<reco::PFCluster> temp = refToPtr(ps2->clusterRef());
922  for (auto pscl = assc_ps.first; pscl != assc_ps.second; ++pscl) {
923  if (pscl->second == temp) {
924  const ClusterElement* pstemp = docast(const ClusterElement*, ps2.get());
925  eslist.emplace_back(pstemp);
926  }
927  }
928  }
929  return eslist.size();
930 }
931 
933 #ifdef PFLOW_DEBUG
934  edm::LogVerbatim("PFEGammaAlgo")
935  //<< "Dumping current block: " << std::endl << *_currentblock << std::endl
936  << "Dumping " << refinableObjects.size() << " refinable objects for this block: " << std::endl;
937  for (const auto& ro : refinableObjects) {
938  std::stringstream info;
939  info << "Refinable Object:" << std::endl;
940  if (ro.parentSC) {
941  info << "\tSuperCluster element attached to object:" << std::endl << '\t';
942  ro.parentSC->Dump(info, "\t");
943  info << std::endl;
944  }
945  if (ro.electronSeed.isNonnull()) {
946  info << "\tGSF element attached to object:" << std::endl;
947  ro.primaryGSFs.front()->Dump(info, "\t");
948  info << std::endl;
949  info << "firstBrem : " << ro.firstBrem << " lateBrem : " << ro.lateBrem
950  << " nBrems with cluster : " << ro.nBremsWithClusters << std::endl;
951  ;
952  if (ro.electronClusters.size() && ro.electronClusters[0]) {
953  info << "electron cluster : ";
954  ro.electronClusters[0]->Dump(info, "\t");
955  info << std::endl;
956  } else {
957  info << " no electron cluster." << std::endl;
958  }
959  }
960  if (ro.primaryKFs.size()) {
961  info << "\tPrimary KF tracks attached to object: " << std::endl;
962  for (const auto& kf : ro.primaryKFs) {
963  kf->Dump(info, "\t");
964  info << std::endl;
965  }
966  }
967  if (ro.secondaryKFs.size()) {
968  info << "\tSecondary KF tracks attached to object: " << std::endl;
969  for (const auto& kf : ro.secondaryKFs) {
970  kf->Dump(info, "\t");
971  info << std::endl;
972  }
973  }
974  if (ro.brems.size()) {
975  info << "\tBrem tangents attached to object: " << std::endl;
976  for (const auto& brem : ro.brems) {
977  brem->Dump(info, "\t");
978  info << std::endl;
979  }
980  }
981  if (ro.ecalclusters.size()) {
982  info << "\tECAL clusters attached to object: " << std::endl;
983  for (const auto& clus : ro.ecalclusters) {
984  clus->Dump(info, "\t");
985  info << std::endl;
986  if (ro.ecal2ps.find(clus) != ro.ecal2ps.end()) {
987  for (const auto& psclus : ro.ecal2ps.at(clus)) {
988  info << "\t\t Attached PS Cluster: ";
989  psclus->Dump(info, "");
990  info << std::endl;
991  }
992  }
993  }
994  }
995  edm::LogVerbatim("PFEGammaAlgo") << info.str();
996  }
997 #endif
998 }
999 
1000 // look through our KF tracks in this block and match
1002  typedef std::multimap<double, unsigned> MatchedMap;
1003  typedef const reco::PFBlockElementGsfTrack* GsfTrackElementPtr;
1005  return;
1006  MatchedMap matchedGSFs, matchedECALs;
1007  std::unordered_map<GsfTrackElementPtr, MatchedMap> gsf_ecal_cache;
1008  for (auto& kftrack : _splayedblock[reco::PFBlockElement::TRACK]) {
1009  matchedGSFs.clear();
1010  _currentblock->associatedElements(
1011  kftrack->index(), _currentlinks, matchedGSFs, reco::PFBlockElement::GSF, reco::PFBlock::LINKTEST_ALL);
1012  if (matchedGSFs.empty()) { // only run this if we aren't associated to GSF
1013  LesserByDistance closestTrackToECAL(_currentblock, _currentlinks, kftrack.get());
1014  auto ecalbegin = _splayedblock[reco::PFBlockElement::ECAL].begin();
1015  auto ecalend = _splayedblock[reco::PFBlockElement::ECAL].end();
1016  std::partial_sort(ecalbegin, ecalbegin + 1, ecalend, closestTrackToECAL);
1017  auto& closestECAL = _splayedblock[reco::PFBlockElement::ECAL].front();
1018  const float dist =
1019  _currentblock->dist(kftrack->index(), closestECAL->index(), _currentlinks, reco::PFBlock::LINKTEST_ALL);
1020  bool inSC = false;
1021  for (auto& sc : _splayedblock[reco::PFBlockElement::SC]) {
1022  float dist_sc =
1023  _currentblock->dist(sc->index(), closestECAL->index(), _currentlinks, reco::PFBlock::LINKTEST_ALL);
1024  if (dist_sc != -1.0f) {
1025  inSC = true;
1026  break;
1027  }
1028  }
1029 
1030  if (dist != -1.0f && closestECAL.flag()) {
1031  bool gsflinked = false;
1032  // check that this cluster is not associated to a GSF track
1033  for (const auto& gsfflag : _splayedblock[reco::PFBlockElement::GSF]) {
1034  const reco::PFBlockElementGsfTrack* elemasgsf = docast(const reco::PFBlockElementGsfTrack*, gsfflag.get());
1036  continue; // keep clusters that have a found conversion GSF near
1037  }
1038  // make sure cache exists
1039  if (!gsf_ecal_cache.count(elemasgsf)) {
1040  matchedECALs.clear();
1041  _currentblock->associatedElements(elemasgsf->index(),
1042  _currentlinks,
1043  matchedECALs,
1046  gsf_ecal_cache.emplace(elemasgsf, matchedECALs);
1047  MatchedMap().swap(matchedECALs);
1048  }
1049  const MatchedMap& ecal_matches = gsf_ecal_cache[elemasgsf];
1050  if (!ecal_matches.empty()) {
1051  if (ecal_matches.begin()->second == closestECAL->index()) {
1052  gsflinked = true;
1053  break;
1054  }
1055  }
1056  } // loop over primary GSF tracks
1057  if (!gsflinked && !inSC) {
1058  // determine if we should remove the matched cluster
1059  const reco::PFBlockElementTrack* kfEle = docast(const reco::PFBlockElementTrack*, kftrack.get());
1060  const reco::TrackRef& trackref = kfEle->trackRef();
1061 
1062  const int nexhits = trackref->missingInnerHits();
1063  bool fromprimaryvertex = false;
1064  for (auto vtxtks = primaryVertex_.tracks_begin(); vtxtks != primaryVertex_.tracks_end(); ++vtxtks) {
1065  if (trackref == vtxtks->castTo<reco::TrackRef>()) {
1066  fromprimaryvertex = true;
1067  break;
1068  }
1069  } // loop over tracks in primary vertex
1070  // if associated to good non-GSF matched track remove this cluster
1071  if (PFTrackAlgoTools::isGoodForEGMPrimary(trackref->algo()) && nexhits == 0 && fromprimaryvertex) {
1072  closestECAL.setFlag(false);
1073  }
1074  }
1075  } // found a good closest ECAL match
1076  } // no GSF track matched to KF
1077  } // loop over KF elements
1078 }
1079 
1080 void PFEGammaAlgo::mergeROsByAnyLink(std::list<PFEGammaAlgo::ProtoEGObject>& ROs) {
1081  if (ROs.size() < 2)
1082  return; // nothing to do with one or zero ROs
1083  bool check_for_merge = true;
1084  while (check_for_merge) {
1085  // bugfix for early termination merging loop (15 April 2014)
1086  // check all pairwise combinations in the list
1087  // if one has a merge shuffle it to the front of the list
1088  // if there are no merges left to do we can terminate
1089  for (auto it1 = ROs.begin(); it1 != ROs.end(); ++it1) {
1090  auto find_start = it1;
1091  ++find_start;
1092  auto has_merge = std::find_if(find_start, ROs.end(), std::bind(testIfROMergableByLink, _1, *it1));
1093  if (has_merge != ROs.end() && it1 != ROs.begin()) {
1094  std::swap(*(ROs.begin()), *it1);
1095  break;
1096  }
1097  } // ensure mergables are shuffled to the front
1098  ProtoEGObject& thefront = ROs.front();
1099  auto mergestart = ROs.begin();
1100  ++mergestart;
1101  auto nomerge = std::partition(mergestart, ROs.end(), std::bind(testIfROMergableByLink, _1, thefront));
1102  if (nomerge != mergestart) {
1103  LOGDRESSED("PFEGammaAlgo::mergeROsByAnyLink()")
1104  << "Found objects " << std::distance(mergestart, nomerge) << " to merge by links to the front!" << std::endl;
1105  for (auto roToMerge = mergestart; roToMerge != nomerge; ++roToMerge) {
1106  //bugfix! L.Gray 14 Jan 2016
1107  // -- check that the front is still mergeable!
1108  if (!thefront.ecalclusters.empty() && !roToMerge->ecalclusters.empty()) {
1109  if (thefront.ecalclusters.front()->clusterRef()->layer() !=
1110  roToMerge->ecalclusters.front()->clusterRef()->layer()) {
1111  LOGWARN("PFEGammaAlgo::mergeROsByAnyLink") << "Tried to merge EB and EE clusters! Skipping!";
1112  ROs.push_back(*roToMerge);
1113  continue;
1114  }
1115  }
1116  //end bugfix
1117  thefront.ecalclusters.insert(
1118  thefront.ecalclusters.end(), roToMerge->ecalclusters.begin(), roToMerge->ecalclusters.end());
1119  thefront.ecal2ps.insert(roToMerge->ecal2ps.begin(), roToMerge->ecal2ps.end());
1120  thefront.secondaryKFs.insert(
1121  thefront.secondaryKFs.end(), roToMerge->secondaryKFs.begin(), roToMerge->secondaryKFs.end());
1122 
1123  thefront.localMap.concatenate(roToMerge->localMap);
1124  // TO FIX -> use best (E_gsf - E_clustersum)/E_GSF
1125  if (!thefront.parentSC && roToMerge->parentSC) {
1126  thefront.parentSC = roToMerge->parentSC;
1127  }
1128  if (thefront.electronSeed.isNull() && roToMerge->electronSeed.isNonnull()) {
1129  thefront.electronSeed = roToMerge->electronSeed;
1130  thefront.primaryGSFs.insert(
1131  thefront.primaryGSFs.end(), roToMerge->primaryGSFs.begin(), roToMerge->primaryGSFs.end());
1132  thefront.primaryKFs.insert(
1133  thefront.primaryKFs.end(), roToMerge->primaryKFs.begin(), roToMerge->primaryKFs.end());
1134  thefront.brems.insert(thefront.brems.end(), roToMerge->brems.begin(), roToMerge->brems.end());
1135  thefront.electronClusters = roToMerge->electronClusters;
1136  thefront.nBremsWithClusters = roToMerge->nBremsWithClusters;
1137  thefront.firstBrem = roToMerge->firstBrem;
1138  thefront.lateBrem = roToMerge->lateBrem;
1139  } else if (thefront.electronSeed.isNonnull() && roToMerge->electronSeed.isNonnull()) {
1140  LOGDRESSED("PFEGammaAlgo::mergeROsByAnyLink")
1141  << "Need to implement proper merging of two gsf candidates!" << std::endl;
1142  }
1143  }
1144  ROs.erase(mergestart, nomerge);
1145  // put the merged element in the back of the cleaned list
1146  ROs.push_back(ROs.front());
1147  ROs.pop_front();
1148  } else {
1149  check_for_merge = false;
1150  }
1151  }
1152  LOGDRESSED("PFEGammaAlgo::mergeROsByAnyLink()")
1153  << "After merging by links there are: " << ROs.size() << " refinable EGamma objects!" << std::endl;
1154 }
1155 
1156 // pull in KF tracks associated to the RO but not closer to another
1157 // NB: in initializeProtoCands() we forced the GSF tracks not to be
1158 // from a conversion, but we will leave a protection here just in
1159 // case things change in the future
1163  return;
1164  auto KFbegin = _splayedblock[reco::PFBlockElement::TRACK].begin();
1165  auto KFend = _splayedblock[reco::PFBlockElement::TRACK].end();
1166  for (auto& gsfflagged : RO.primaryGSFs) {
1167  const PFGSFElement* seedtk = gsfflagged;
1168  // don't process SC-only ROs or secondary seeded ROs
1169  if (RO.electronSeed.isNull() || seedtk->trackType(convType))
1170  continue;
1171  NotCloserToOther<reco::PFBlockElement::GSF, reco::PFBlockElement::TRACK> gsfTrackToKFs(_currentblock, seedtk);
1172  // get KF tracks not closer to another and not already used
1173  auto notlinked = std::partition(KFbegin, KFend, gsfTrackToKFs);
1174  // attach tracks and set as used
1175  for (auto kft = KFbegin; kft != notlinked; ++kft) {
1176  const PFKFElement* elemaskf = docast(const PFKFElement*, kft->get());
1177  // don't care about things that aren't primaries or directly
1178  // associated secondary tracks
1179  if (isPrimaryTrack(*elemaskf, *seedtk) && !elemaskf->trackType(convType)) {
1180  kft->setFlag(false);
1181  RO.primaryKFs.push_back(elemaskf);
1182  RO.localMap.insert(seedtk, elemaskf);
1183  } else if (elemaskf->trackType(convType)) {
1184  kft->setFlag(false);
1185  RO.secondaryKFs.push_back(elemaskf);
1186  RO.localMap.insert(seedtk, elemaskf);
1187  }
1188  } // loop on closest KFs not closer to other GSFs
1189  } // loop on GSF primaries on RO
1190 }
1191 
1195  return;
1196  auto KFbegin = _splayedblock[reco::PFBlockElement::TRACK].begin();
1197  auto KFend = _splayedblock[reco::PFBlockElement::TRACK].end();
1198  for (auto& primkf : RO.primaryKFs) {
1199  // don't process SC-only ROs or secondary seeded ROs
1200  if (primkf->trackType(convType)) {
1201  throw cms::Exception("PFEGammaAlgo::linkRefinableObjectPrimaryKFsToSecondaryKFs()")
1202  << "A KF track from conversion has been assigned as a primary!!" << std::endl;
1203  }
1204  NotCloserToOther<reco::PFBlockElement::TRACK, reco::PFBlockElement::TRACK, true> kfTrackToKFs(_currentblock,
1205  primkf);
1206  // get KF tracks not closer to another and not already used
1207  auto notlinked = std::partition(KFbegin, KFend, kfTrackToKFs);
1208  // attach tracks and set as used
1209  for (auto kft = KFbegin; kft != notlinked; ++kft) {
1210  const PFKFElement* elemaskf = docast(const PFKFElement*, kft->get());
1211  // don't care about things that aren't primaries or directly
1212  // associated secondary tracks
1213  if (elemaskf->trackType(convType)) {
1214  kft->setFlag(false);
1215  RO.secondaryKFs.push_back(elemaskf);
1216  RO.localMap.insert(primkf, elemaskf);
1217  }
1218  } // loop on closest KFs not closer to other KFs
1219  } // loop on KF primaries on RO
1220 }
1221 
1222 // try to associate the tracks to cluster elements which are not used
1225  RO.electronClusters.push_back(nullptr);
1226  return;
1227  }
1228  auto ECALbegin = _splayedblock[reco::PFBlockElement::ECAL].begin();
1229  auto ECALend = _splayedblock[reco::PFBlockElement::ECAL].end();
1230  for (auto& primgsf : RO.primaryGSFs) {
1231  NotCloserToOther<reco::PFBlockElement::GSF, reco::PFBlockElement::ECAL> gsfTracksToECALs(_currentblock, primgsf);
1232  // get set of matching ecals not already in SC
1233  auto notmatched_blk = std::partition(ECALbegin, ECALend, gsfTracksToECALs);
1234  notmatched_blk =
1235  std::partition(ECALbegin, notmatched_blk, [&primgsf](auto const& x) { return compatibleEoPOut(*x, *primgsf); });
1236  // get set of matching ecals already in the RO
1237  auto notmatched_sc = std::partition(RO.ecalclusters.begin(), RO.ecalclusters.end(), gsfTracksToECALs);
1238  notmatched_sc = std::partition(
1239  RO.ecalclusters.begin(), notmatched_sc, [&primgsf](auto const& x) { return compatibleEoPOut(*x, *primgsf); });
1240  // look inside the SC for the ECAL cluster
1241  for (auto ecal = RO.ecalclusters.begin(); ecal != notmatched_sc; ++ecal) {
1242  const PFClusterElement* elemascluster = docast(const PFClusterElement*, ecal->get());
1243  FlaggedPtr<const PFClusterElement> temp(elemascluster, true);
1244  LOGDRESSED("PFEGammaAlgo::linkGSFTracktoECAL()") << "Found a cluster already in RO by GSF extrapolation"
1245  << " at ECAL surface!" << std::endl
1246  << *elemascluster << std::endl;
1247 
1248  RO.localMap.insert(primgsf, temp.get());
1249  }
1250  // look outside the SC for the ecal cluster
1251  for (auto ecal = ECALbegin; ecal != notmatched_blk; ++ecal) {
1252  const PFClusterElement* elemascluster = docast(const PFClusterElement*, ecal->get());
1253  LOGDRESSED("PFEGammaAlgo::linkGSFTracktoECAL()") << "Found a cluster not already in RO by GSF extrapolation"
1254  << " at ECAL surface!" << std::endl
1255  << *elemascluster << std::endl;
1256  if (addPFClusterToROSafe(elemascluster, RO)) {
1257  attachPSClusters(elemascluster, RO.ecal2ps[elemascluster]);
1258  RO.localMap.insert(primgsf, elemascluster);
1259  ecal->setFlag(false);
1260  }
1261  }
1262  }
1263 }
1264 
1265 // try to associate the tracks to cluster elements which are not used
1268  return;
1269  auto HCALbegin = _splayedblock[reco::PFBlockElement::HCAL].begin();
1270  auto HCALend = _splayedblock[reco::PFBlockElement::HCAL].end();
1271  for (auto& primgsf : RO.primaryGSFs) {
1272  NotCloserToOther<reco::PFBlockElement::GSF, reco::PFBlockElement::HCAL> gsfTracksToHCALs(_currentblock, primgsf);
1273  auto notmatched = std::partition(HCALbegin, HCALend, gsfTracksToHCALs);
1274  for (auto hcal = HCALbegin; hcal != notmatched; ++hcal) {
1275  const PFClusterElement* elemascluster = docast(const PFClusterElement*, hcal->get());
1276  FlaggedPtr<const PFClusterElement> temp(elemascluster, true);
1277  LOGDRESSED("PFEGammaAlgo::linkGSFTracktoECAL()")
1278  << "Found an HCAL cluster associated to GSF extrapolation" << std::endl;
1279  RO.hcalClusters.push_back(temp.get());
1280  RO.localMap.insert(primgsf, temp.get());
1281  hcal->setFlag(false);
1282  }
1283  }
1284 }
1285 
1286 // try to associate the tracks to cluster elements which are not used
1289  return;
1290  for (auto& primkf : RO.primaryKFs)
1291  linkKFTrackToECAL(primkf, RO);
1292  for (auto& secdkf : RO.secondaryKFs)
1293  linkKFTrackToECAL(secdkf, RO);
1294 }
1295 
1297  std::vector<FlaggedPtr<const PFClusterElement>>& currentECAL = RO.ecalclusters;
1298  auto ECALbegin = _splayedblock[reco::PFBlockElement::ECAL].begin();
1299  auto ECALend = _splayedblock[reco::PFBlockElement::ECAL].end();
1300  NotCloserToOther<reco::PFBlockElement::TRACK, reco::PFBlockElement::ECAL> kfTrackToECALs(_currentblock, kfflagged);
1301  NotCloserToOther<reco::PFBlockElement::GSF, reco::PFBlockElement::ECAL> kfTrackGSFToECALs(_currentblock, kfflagged);
1302  //get the ECAL elements not used and not closer to another KF
1303  auto notmatched_sc = std::partition(currentECAL.begin(), currentECAL.end(), kfTrackToECALs);
1304  //get subset ECAL elements not used or closer to another GSF of any type
1305  notmatched_sc = std::partition(currentECAL.begin(), notmatched_sc, kfTrackGSFToECALs);
1306  for (auto ecalitr = currentECAL.begin(); ecalitr != notmatched_sc; ++ecalitr) {
1307  const PFClusterElement* elemascluster = docast(const PFClusterElement*, ecalitr->get());
1308  FlaggedPtr<const PFClusterElement> flaggedclus(elemascluster, true);
1309 
1310  LOGDRESSED("PFEGammaAlgo::linkKFTracktoECAL()") << "Found a cluster already in RO by KF extrapolation"
1311  << " at ECAL surface!" << std::endl
1312  << *elemascluster << std::endl;
1313  RO.localMap.insert(elemascluster, kfflagged);
1314  }
1315  //get the ECAL elements not used and not closer to another KF
1316  auto notmatched_blk = std::partition(ECALbegin, ECALend, kfTrackToECALs);
1317  //get subset ECAL elements not used or closer to another GSF of any type
1318  notmatched_blk = std::partition(ECALbegin, notmatched_blk, kfTrackGSFToECALs);
1319  for (auto ecalitr = ECALbegin; ecalitr != notmatched_blk; ++ecalitr) {
1320  const PFClusterElement* elemascluster = docast(const PFClusterElement*, ecalitr->get());
1321  if (addPFClusterToROSafe(elemascluster, RO)) {
1322  attachPSClusters(elemascluster, RO.ecal2ps[elemascluster]);
1323  ecalitr->setFlag(false);
1324 
1325  LOGDRESSED("PFEGammaAlgo::linkKFTracktoECAL()") << "Found a cluster not in RO by KF extrapolation"
1326  << " at ECAL surface!" << std::endl
1327  << *elemascluster << std::endl;
1328  RO.localMap.insert(elemascluster, kfflagged);
1329  }
1330  }
1331 }
1332 
1334  if (RO.brems.empty())
1335  return;
1336  int FirstBrem = -1;
1337  int TrajPos = -1;
1338  int lastBremTrajPos = -1;
1339  for (auto& brem : RO.brems) {
1340  bool has_clusters = false;
1341  TrajPos = (brem->indTrajPoint()) - 2;
1342  auto ECALbegin = _splayedblock[reco::PFBlockElement::ECAL].begin();
1343  auto ECALend = _splayedblock[reco::PFBlockElement::ECAL].end();
1344  NotCloserToOther<reco::PFBlockElement::BREM, reco::PFBlockElement::ECAL> BremToECALs(_currentblock, brem);
1345  // check for late brem using clusters already in the SC
1346  auto RSCBegin = RO.ecalclusters.begin();
1347  auto RSCEnd = RO.ecalclusters.end();
1348  auto notmatched_rsc = std::partition(RSCBegin, RSCEnd, BremToECALs);
1349  for (auto ecal = RSCBegin; ecal != notmatched_rsc; ++ecal) {
1350  float deta = std::abs((*ecal)->clusterRef()->positionREP().eta() - brem->positionAtECALEntrance().eta());
1351  if (deta < 0.015) {
1352  has_clusters = true;
1353  if (lastBremTrajPos == -1 || lastBremTrajPos < TrajPos) {
1354  lastBremTrajPos = TrajPos;
1355  }
1356  if (FirstBrem == -1 || TrajPos < FirstBrem) { // set brem information
1357  FirstBrem = TrajPos;
1358  RO.firstBrem = TrajPos;
1359  }
1360  LOGDRESSED("PFEGammaAlgo::linkBremToECAL()") << "Found a cluster already in SC linked to brem extrapolation"
1361  << " at ECAL surface!" << std::endl;
1362  RO.localMap.insert(ecal->get(), brem);
1363  }
1364  }
1365  // grab new clusters from the block (ensured to not be late brem)
1366  auto notmatched_block = std::partition(ECALbegin, ECALend, BremToECALs);
1367  for (auto ecal = ECALbegin; ecal != notmatched_block; ++ecal) {
1368  float deta = std::abs((*ecal)->clusterRef()->positionREP().eta() - brem->positionAtECALEntrance().eta());
1369  if (deta < 0.015) {
1370  has_clusters = true;
1371  if (lastBremTrajPos == -1 || lastBremTrajPos < TrajPos) {
1372  lastBremTrajPos = TrajPos;
1373  }
1374  if (FirstBrem == -1 || TrajPos < FirstBrem) { // set brem information
1375 
1376  FirstBrem = TrajPos;
1377  RO.firstBrem = TrajPos;
1378  }
1379  const PFClusterElement* elemasclus = docast(const PFClusterElement*, ecal->get());
1380  if (addPFClusterToROSafe(elemasclus, RO)) {
1381  attachPSClusters(elemasclus, RO.ecal2ps[elemasclus]);
1382 
1383  RO.localMap.insert(ecal->get(), brem);
1384  ecal->setFlag(false);
1385  LOGDRESSED("PFEGammaAlgo::linkBremToECAL()") << "Found a cluster not already associated by brem extrapolation"
1386  << " at ECAL surface!" << std::endl;
1387  }
1388  }
1389  }
1390  if (has_clusters) {
1391  if (RO.nBremsWithClusters == -1)
1392  RO.nBremsWithClusters = 0;
1393  ++RO.nBremsWithClusters;
1394  }
1395  }
1396 }
1397 
1399  auto KFbegin = _splayedblock[reco::PFBlockElement::TRACK].begin();
1400  auto KFend = _splayedblock[reco::PFBlockElement::TRACK].end();
1401  auto BeginROskfs = RO.secondaryKFs.begin();
1402  auto EndROskfs = RO.secondaryKFs.end();
1403  auto ronotconv = std::partition(BeginROskfs, EndROskfs, [](auto const& x) { return x->trackType(ConvType); });
1404  size_t convkfs_end = std::distance(BeginROskfs, ronotconv);
1405  for (size_t idx = 0; idx < convkfs_end; ++idx) {
1406  auto const& secKFs =
1407  RO.secondaryKFs; //we want the entry at the index but we allocate to secondaryKFs in loop which invalidates all iterators, references and pointers, hence we need to get the entry fresh each time
1408  NotCloserToOther<reco::PFBlockElement::TRACK, reco::PFBlockElement::TRACK, true> TracksToTracks(_currentblock,
1409  secKFs[idx]);
1410  auto notmatched = std::partition(KFbegin, KFend, TracksToTracks);
1411  notmatched = std::partition(KFbegin, notmatched, [](auto const& x) { return x->trackType(ConvType); });
1412  for (auto kf = KFbegin; kf != notmatched; ++kf) {
1413  const reco::PFBlockElementTrack* elemaskf = docast(const reco::PFBlockElementTrack*, kf->get());
1414  RO.secondaryKFs.push_back(elemaskf);
1415  RO.localMap.insert(secKFs[idx], kf->get());
1416  kf->setFlag(false);
1417  }
1418  }
1419 }
1420 
1422  auto KFbegin = _splayedblock[reco::PFBlockElement::TRACK].begin();
1423  auto KFend = _splayedblock[reco::PFBlockElement::TRACK].end();
1424  for (auto& ecal : RO.ecalclusters) {
1425  NotCloserToOther<reco::PFBlockElement::ECAL, reco::PFBlockElement::TRACK, true> ECALToTracks(_currentblock,
1426  ecal.get());
1427  auto notmatchedkf = std::partition(KFbegin, KFend, ECALToTracks);
1428  auto notconvkf = std::partition(KFbegin, notmatchedkf, [](auto const& x) { return x->trackType(ConvType); });
1429  // add identified KF conversion tracks
1430  for (auto kf = KFbegin; kf != notconvkf; ++kf) {
1431  const reco::PFBlockElementTrack* elemaskf = docast(const reco::PFBlockElementTrack*, kf->get());
1432  RO.secondaryKFs.push_back(elemaskf);
1433  RO.localMap.insert(ecal.get(), elemaskf);
1434  kf->setFlag(false);
1435  }
1436  // go through non-conv-identified kfs and check MVA to add conversions
1437  for (auto kf = notconvkf; kf != notmatchedkf; ++kf) {
1438  float mvaval = evaluateSingleLegMVA(_currentblock, primaryVertex_, (*kf)->index());
1439  if (mvaval > cfg_.mvaConvCut) {
1440  const reco::PFBlockElementTrack* elemaskf = docast(const reco::PFBlockElementTrack*, kf->get());
1441  RO.secondaryKFs.push_back(elemaskf);
1442  RO.localMap.insert(ecal.get(), elemaskf);
1443  kf->setFlag(false);
1444 
1445  RO.singleLegConversionMvaMap.emplace(elemaskf, mvaval);
1446  }
1447  }
1448  }
1449 }
1450 
1452  auto ECALbegin = _splayedblock[reco::PFBlockElement::ECAL].begin();
1453  auto ECALend = _splayedblock[reco::PFBlockElement::ECAL].end();
1454  for (auto& skf : RO.secondaryKFs) {
1455  NotCloserToOther<reco::PFBlockElement::TRACK, reco::PFBlockElement::ECAL, false> TracksToECALwithCut(
1456  _currentblock, skf, 1.5f);
1457  auto notmatched = std::partition(ECALbegin, ECALend, TracksToECALwithCut);
1458  for (auto ecal = ECALbegin; ecal != notmatched; ++ecal) {
1459  const reco::PFBlockElementCluster* elemascluster = docast(const reco::PFBlockElementCluster*, ecal->get());
1460  if (addPFClusterToROSafe(elemascluster, RO)) {
1461  attachPSClusters(elemascluster, RO.ecal2ps[elemascluster]);
1462  RO.localMap.insert(skf, elemascluster);
1463  ecal->setFlag(false);
1464  }
1465  }
1466  }
1467 }
1468 
1469 PFEGammaAlgo::EgammaObjects PFEGammaAlgo::fillPFCandidates(const std::list<PFEGammaAlgo::ProtoEGObject>& ROs) {
1471 
1472  // reserve output collections
1473  output.candidates.reserve(ROs.size());
1474  output.candidateExtras.reserve(ROs.size());
1475  output.refinedSuperClusters.reserve(ROs.size());
1476 
1477  for (auto& RO : ROs) {
1478  if (RO.ecalclusters.empty() && !cfg_.produceEGCandsWithNoSuperCluster)
1479  continue;
1480 
1483  if (!RO.primaryGSFs.empty() || !RO.primaryKFs.empty()) {
1484  cand.setPdgId(-11); // anything with a primary track is an electron
1485  } else {
1486  cand.setPdgId(22); // anything with no primary track is a photon
1487  }
1488  if (!RO.primaryKFs.empty()) {
1489  cand.setCharge(RO.primaryKFs[0]->trackRef()->charge());
1490  xtra.setKfTrackRef(RO.primaryKFs[0]->trackRef());
1491  cand.setTrackRef(RO.primaryKFs[0]->trackRef());
1492  cand.setVertex(RO.primaryKFs[0]->trackRef()->vertex());
1493  cand.addElementInBlock(_currentblock, RO.primaryKFs[0]->index());
1494  }
1495  if (!RO.primaryGSFs.empty()) {
1496  cand.setCharge(RO.primaryGSFs[0]->GsftrackRef()->chargeMode());
1497  xtra.setGsfTrackRef(RO.primaryGSFs[0]->GsftrackRef());
1498  cand.setGsfTrackRef(RO.primaryGSFs[0]->GsftrackRef());
1499  cand.setVertex(RO.primaryGSFs[0]->GsftrackRef()->vertex());
1500  cand.addElementInBlock(_currentblock, RO.primaryGSFs[0]->index());
1501  }
1502  if (RO.parentSC) {
1503  xtra.setSuperClusterPFECALRef(RO.parentSC->superClusterRef());
1504  // we'll set to the refined supercluster back up in the producer
1505  cand.setSuperClusterRef(RO.parentSC->superClusterRef());
1506  xtra.setSuperClusterRef(RO.parentSC->superClusterRef());
1507  cand.addElementInBlock(_currentblock, RO.parentSC->index());
1508  }
1509  // add brems
1510  for (const auto& brem : RO.brems) {
1511  cand.addElementInBlock(_currentblock, brem->index());
1512  }
1513  // add clusters and ps clusters
1514  for (const auto& ecal : RO.ecalclusters) {
1515  const PFClusterElement* clus = ecal.get();
1516  cand.addElementInBlock(_currentblock, clus->index());
1517  if (RO.ecal2ps.count(clus)) {
1518  for (auto& psclus : RO.ecal2ps.at(clus)) {
1519  cand.addElementInBlock(_currentblock, psclus->index());
1520  }
1521  }
1522  }
1523  // add secondary tracks
1524  for (const auto& kf : RO.secondaryKFs) {
1525  cand.addElementInBlock(_currentblock, kf->index());
1526  const reco::ConversionRefVector& convrefs = kf->convRefs();
1527  bool no_conv_ref = true;
1528  for (const auto& convref : convrefs) {
1529  if (convref.isNonnull() && convref.isAvailable()) {
1530  xtra.addConversionRef(convref);
1531  no_conv_ref = false;
1532  }
1533  }
1534  if (no_conv_ref) {
1535  //single leg conversions
1536 
1537  //look for stored mva value in map or else recompute
1538  const auto& mvavalmapped = RO.singleLegConversionMvaMap.find(kf);
1539  //FIXME: Abuse single mva value to store both provenance and single leg mva score
1540  //by storing 3.0 + mvaval
1541  float mvaval = (mvavalmapped != RO.singleLegConversionMvaMap.end()
1542  ? mvavalmapped->second
1544 
1545  xtra.addSingleLegConvTrackRefMva(std::make_pair(kf->trackRef(), mvaval));
1546  }
1547  }
1548 
1549  // build the refined supercluster from those clusters left in the cand
1550  output.refinedSuperClusters.push_back(buildRefinedSuperCluster(RO));
1551 
1552  //*TODO* cluster time is not reliable at the moment, so only use track timing
1553  float trkTime = 0, trkTimeErr = -1;
1554  if (!RO.primaryGSFs.empty() && RO.primaryGSFs[0]->isTimeValid()) {
1555  trkTime = RO.primaryGSFs[0]->time();
1556  trkTimeErr = RO.primaryGSFs[0]->timeError();
1557  } else if (!RO.primaryKFs.empty() && RO.primaryKFs[0]->isTimeValid()) {
1558  trkTime = RO.primaryKFs[0]->time();
1559  trkTimeErr = RO.primaryKFs[0]->timeError();
1560  }
1561  if (trkTimeErr >= 0) {
1562  cand.setTime(trkTime, trkTimeErr);
1563  }
1564 
1565  const reco::SuperCluster& the_sc = output.refinedSuperClusters.back();
1566  // with the refined SC in hand we build a naive candidate p4
1567  // and set the candidate ECAL position to either the barycenter of the
1568  // supercluster (if super-cluster present) or the seed of the
1569  // new SC generated by the EGAlgo
1570  const double scE = the_sc.energy();
1571  if (scE != 0.0) {
1572  const math::XYZPoint& seedPos = the_sc.seed()->position();
1573  math::XYZVector egDir = the_sc.position() - primaryVertex_.position();
1574  egDir = egDir.Unit();
1575  cand.setP4(math::XYZTLorentzVector(scE * egDir.x(), scE * egDir.y(), scE * egDir.z(), scE));
1576  math::XYZPointF ecalPOS_f(seedPos.x(), seedPos.y(), seedPos.z());
1577  cand.setPositionAtECALEntrance(ecalPOS_f);
1578  cand.setEcalEnergy(the_sc.rawEnergy(), the_sc.energy());
1579  } else if (cfg_.produceEGCandsWithNoSuperCluster && !RO.primaryGSFs.empty()) {
1580  const PFGSFElement* gsf = RO.primaryGSFs[0];
1581  const reco::GsfTrackRef& gref = gsf->GsftrackRef();
1582  math::XYZTLorentzVector p4(gref->pxMode(), gref->pyMode(), gref->pzMode(), gref->pMode());
1583  cand.setP4(p4);
1584  cand.setPositionAtECALEntrance(gsf->positionAtECALEntrance());
1585  } else if (cfg_.produceEGCandsWithNoSuperCluster && !RO.primaryKFs.empty()) {
1586  const PFKFElement* kf = RO.primaryKFs[0];
1587  reco::TrackRef kref = RO.primaryKFs[0]->trackRef();
1588  math::XYZTLorentzVector p4(kref->px(), kref->py(), kref->pz(), kref->p());
1589  cand.setP4(p4);
1590  cand.setPositionAtECALEntrance(kf->positionAtECALEntrance());
1591  }
1592  const float eleMVAValue = calculateEleMVA(RO, xtra);
1593  fillExtraInfo(RO, xtra);
1594  //std::cout << "PFEG eleMVA: " << eleMVAValue << std::endl;
1595  xtra.setMVA(eleMVAValue);
1596  cand.set_mva_e_pi(eleMVAValue);
1597  output.candidates.push_back(cand);
1598  output.candidateExtras.push_back(xtra);
1599  }
1600 
1601  return output;
1602 }
1603 
1605  if (ro.primaryGSFs.empty()) {
1606  return -2.0f;
1607  }
1608  const PFGSFElement* gsfElement = ro.primaryGSFs.front();
1609  const PFKFElement* kfElement = nullptr;
1610  if (!ro.primaryKFs.empty()) {
1611  kfElement = ro.primaryKFs.front();
1612  }
1613  auto const& refGsf = gsfElement->GsftrackRef();
1614  reco::TrackRef refKf;
1615  constexpr float mEl = 0.000511;
1616  const double eInGsf = std::hypot(refGsf->pMode(), mEl);
1617  double dEtGsfEcal = 1e6;
1618  double sigmaEtaEta = 1e-14;
1619  const double eneHcalGsf =
1620  std::accumulate(ro.hcalClusters.begin(), ro.hcalClusters.end(), 0.0, [](const double a, auto const& b) {
1621  return a + b->clusterRef()->energy();
1622  });
1623  if (!ro.primaryKFs.empty()) {
1624  refKf = ro.primaryKFs.front()->trackRef();
1625  }
1626  const double eOutGsf = gsfElement->Pout().t();
1627  const double etaOutGsf = gsfElement->positionAtECALEntrance().eta();
1628  double firstEcalGsfEnergy{0.0};
1629  double otherEcalGsfEnergy{0.0};
1630  double ecalBremEnergy{0.0};
1631  //shower shape of cluster closest to gsf track
1632  std::vector<const reco::PFCluster*> gsfCluster;
1633  for (const auto& ecal : ro.ecalclusters) {
1634  const double cenergy = ecal->clusterRef()->correctedEnergy();
1635  bool hasgsf = ro.localMap.contains(gsfElement, ecal.get());
1636  bool haskf = ro.localMap.contains(kfElement, ecal.get());
1637  bool hasbrem = false;
1638  for (const auto& brem : ro.brems) {
1639  if (ro.localMap.contains(brem, ecal.get())) {
1640  hasbrem = true;
1641  }
1642  }
1643  if (hasbrem && ecal.get() != ro.electronClusters[0]) {
1644  ecalBremEnergy += cenergy;
1645  }
1646  if (!hasbrem && ecal.get() != ro.electronClusters[0]) {
1647  if (hasgsf)
1648  otherEcalGsfEnergy += cenergy;
1649  if (haskf)
1650  ecalBremEnergy += cenergy; // from conv. brem!
1651  if (!(hasgsf || haskf))
1652  otherEcalGsfEnergy += cenergy; // stuff from SC
1653  }
1654  }
1655 
1656  if (ro.electronClusters[0]) {
1657  reco::PFClusterRef cref = ro.electronClusters[0]->clusterRef();
1659  firstEcalGsfEnergy = cref->correctedEnergy();
1660  dEtGsfEcal = cref->positionREP().eta() - etaOutGsf;
1661  gsfCluster.push_back(cref.get());
1662  PFClusterWidthAlgo pfwidth(gsfCluster);
1663  sigmaEtaEta = pfwidth.pflowSigmaEtaEta();
1664  }
1665 
1666  // brem sequence information
1667  float firstBrem{-1.0f};
1668  float earlyBrem{-1.0f};
1669  float lateBrem{-1.0f};
1670  if (ro.nBremsWithClusters > 0) {
1671  firstBrem = ro.firstBrem;
1672  earlyBrem = ro.firstBrem < 4 ? 1.0f : 0.0f;
1673  lateBrem = ro.lateBrem == 1 ? 1.0f : 0.0f;
1674  }
1675  xtra.setEarlyBrem(earlyBrem);
1676  xtra.setLateBrem(lateBrem);
1677  if (firstEcalGsfEnergy > 0.0) {
1678  if (refGsf.isNonnull()) {
1679  xtra.setGsfTrackPout(gsfElement->Pout());
1680  // normalization observables
1681  const float ptGsf = refGsf->ptMode();
1682  const float etaGsf = refGsf->etaMode();
1683  // tracking observables
1684  const double ptModeErrorGsf = refGsf->ptModeError();
1685  float ptModeErrOverPtGsf = (ptModeErrorGsf > 0. ? ptModeErrorGsf / ptGsf : 1.0);
1686  float chi2Gsf = refGsf->normalizedChi2();
1687  float dPtOverPtGsf = (ptGsf - gsfElement->Pout().pt()) / ptGsf;
1688  // kalman filter vars
1689  float nHitKf = refKf.isNonnull() ? refKf->hitPattern().trackerLayersWithMeasurement() : 0;
1690  float chi2Kf = refKf.isNonnull() ? refKf->normalizedChi2() : -0.01;
1691 
1692  //tracker + calorimetry observables
1693  float eTotPinMode = (firstEcalGsfEnergy + otherEcalGsfEnergy + ecalBremEnergy) / eInGsf;
1694  float eGsfPoutMode = firstEcalGsfEnergy / eOutGsf;
1695  float eTotBremPinPoutMode = (ecalBremEnergy + otherEcalGsfEnergy) / (eInGsf - eOutGsf);
1696  float dEtaGsfEcalClust = std::abs(dEtGsfEcal);
1697  float logSigmaEtaEta = std::log(sigmaEtaEta);
1698  float hOverHe = eneHcalGsf / (eneHcalGsf + firstEcalGsfEnergy);
1699 
1700  xtra.setDeltaEta(dEtaGsfEcalClust);
1702  xtra.setHadEnergy(eneHcalGsf);
1703 
1704  // Apply bounds to variables and calculate MVA
1705  dPtOverPtGsf = std::clamp(dPtOverPtGsf, -0.2f, 1.0f);
1706  ptModeErrOverPtGsf = std::min(ptModeErrOverPtGsf, 0.3f);
1707  chi2Gsf = std::min(chi2Gsf, 10.0f);
1708  chi2Kf = std::min(chi2Kf, 10.0f);
1709  eTotPinMode = std::clamp(eTotPinMode, 0.0f, 5.0f);
1710  eGsfPoutMode = std::clamp(eGsfPoutMode, 0.0f, 5.0f);
1711  eTotBremPinPoutMode = std::clamp(eTotBremPinPoutMode, 0.0f, 5.0f);
1712  dEtaGsfEcalClust = std::min(dEtaGsfEcalClust, 0.1f);
1713  logSigmaEtaEta = std::max(logSigmaEtaEta, -14.0f);
1714 
1715  // not used for moment, weird behavior of variable
1716  //float dPtOverPtKf = refKf.isNonnull() ? (refKf->pt() - refKf->outerPt())/refKf->pt() : -0.01;
1717  //dPtOverPtKf = std::clamp(dPtOverPtKf,-0.2f, 1.0f);
1718 
1719  /*
1720  * To be used for debugging:
1721  * pretty-print the PFEgamma electron MVA input variables
1722  *
1723  * std::cout << " **** PFEG BDT observables ****" << endl;
1724  * std::cout << " < Normalization > " << endl;
1725  * std::cout << " ptGsf " << ptGsf << " Pin " << eInGsf
1726  * << " Pout " << eOutGsf << " etaGsf " << etaGsf << endl;
1727  * std::cout << " < PureTracking > " << endl;
1728  * std::cout << " ptModeErrOverPtGsf " << ptModeErrOverPtGsf
1729  * << " dPtOverPtGsf " << dPtOverPtGsf
1730  * << " chi2Gsf " << chi2Gsf
1731  * << " nhit_gsf " << nhit_gsf
1732  * << " dPtOverPtKf " << dPtOverPtKf
1733  * << " chi2Kf " << chi2Kf
1734  * << " nHitKf " << nHitKf << endl;
1735  * std::cout << " < track-ecal-hcal-ps " << endl;
1736  * std::cout << " eTotPinMode " << eTotPinMode
1737  * << " eGsfPoutMode " << eGsfPoutMode
1738  * << " eTotBremPinPoutMode " << eTotBremPinPoutMode
1739  * << " dEtaGsfEcalClust " << dEtaGsfEcalClust
1740  * << " logSigmaEtaEta " << logSigmaEtaEta
1741  * << " hOverHe " << hOverHe << " Hcal energy " << eneHcalGsf
1742  * << " lateBrem " << lateBrem
1743  * << " firstBrem " << firstBrem << endl;
1744  */
1745 
1746  float vars[] = {std::log(ptGsf),
1747  etaGsf,
1748  ptModeErrOverPtGsf,
1749  dPtOverPtGsf,
1750  chi2Gsf,
1751  nHitKf,
1752  chi2Kf,
1753  eTotPinMode,
1754  eGsfPoutMode,
1755  eTotBremPinPoutMode,
1756  dEtaGsfEcalClust,
1757  logSigmaEtaEta,
1758  hOverHe,
1759  lateBrem,
1760  firstBrem};
1761 
1762  return gbrForests_.ele_->GetAdaBoostClassifier(vars);
1763  }
1764  }
1765  return -2.0f;
1766 }
1767 
1769  // add tracks associated to clusters that are not T_FROM_GAMMACONV
1770  // info about single-leg convs is already save, so just veto in loops
1771  auto KFbegin = _splayedblock[reco::PFBlockElement::TRACK].begin();
1772  auto KFend = _splayedblock[reco::PFBlockElement::TRACK].end();
1773  for (auto& ecal : RO.ecalclusters) {
1774  NotCloserToOther<reco::PFBlockElement::ECAL, reco::PFBlockElement::TRACK, true> ECALToTracks(_currentblock,
1775  ecal.get());
1776  auto notmatchedkf = std::partition(KFbegin, KFend, ECALToTracks);
1777  auto notconvkf = std::partition(KFbegin, notmatchedkf, [](auto const& x) { return x->trackType(ConvType); });
1778  // go through non-conv-identified kfs and check MVA to add conversions
1779  for (auto kf = notconvkf; kf != notmatchedkf; ++kf) {
1780  const reco::PFBlockElementTrack* elemaskf = docast(const reco::PFBlockElementTrack*, kf->get());
1781  xtra.addExtraNonConvTrack(_currentblock, *elemaskf);
1782  }
1783  }
1784 }
1785 
1786 // currently stolen from PFECALSuperClusterAlgo, we should
1787 // try to factor this correctly since the operation is the same in
1788 // both places...
1790  if (RO.ecalclusters.empty()) {
1791  return reco::SuperCluster(0.0, math::XYZPoint(0, 0, 0));
1792  }
1793 
1794  bool isEE = false;
1795  // need the vector of raw pointers for a PF width class
1796  std::vector<const reco::PFCluster*> bare_ptrs;
1797  // calculate necessary parameters and build the SC
1798  double posX(0), posY(0), posZ(0), rawSCEnergy(0), corrSCEnergy(0), corrPSEnergy(0), ps1_energy(0.0), ps2_energy(0.0);
1799  for (auto& clus : RO.ecalclusters) {
1800  double ePS1 = 0;
1801  double ePS2 = 0;
1802  isEE = PFLayer::ECAL_ENDCAP == clus->clusterRef()->layer();
1803  auto clusptr = edm::refToPtr<reco::PFClusterCollection>(clus->clusterRef());
1804  bare_ptrs.push_back(clusptr.get());
1805 
1806  const double cluseraw = clusptr->energy();
1807  double cluscalibe = clusptr->correctedEnergy();
1808  const math::XYZPoint& cluspos = clusptr->position();
1809  posX += cluseraw * cluspos.X();
1810  posY += cluseraw * cluspos.Y();
1811  posZ += cluseraw * cluspos.Z();
1812  // update EE calibrated super cluster energies
1813  if (isEE && RO.ecal2ps.count(clus.get())) {
1814  const auto& psclusters = RO.ecal2ps.at(clus.get());
1815 
1816  std::vector<reco::PFCluster const*> psClusterPointers;
1817  psClusterPointers.reserve(psclusters.size());
1818  for (auto const& psc : psclusters) {
1819  psClusterPointers.push_back(psc->clusterRef().get());
1820  }
1821  auto calibratedEnergies = thePFEnergyCalibration_.calibrateEndcapClusterEnergies(
1822  *clusptr, psClusterPointers, channelStatus_, cfg_.applyCrackCorrections);
1823  cluscalibe = calibratedEnergies.clusterEnergy;
1824  ePS1 = calibratedEnergies.ps1Energy;
1825  ePS2 = calibratedEnergies.ps2Energy;
1826  }
1827  if (ePS1 == -1.)
1828  ePS1 = 0;
1829  if (ePS2 == -1.)
1830  ePS2 = 0;
1831 
1832  rawSCEnergy += cluseraw;
1833  corrSCEnergy += cluscalibe;
1834  ps1_energy += ePS1;
1835  ps2_energy += ePS2;
1836  corrPSEnergy += ePS1 + ePS2;
1837  }
1838  posX /= rawSCEnergy;
1839  posY /= rawSCEnergy;
1840  posZ /= rawSCEnergy;
1841 
1842  // now build the supercluster
1843  reco::SuperCluster new_sc(corrSCEnergy, math::XYZPoint(posX, posY, posZ));
1844 
1845  auto clusptr = edm::refToPtr<reco::PFClusterCollection>(RO.ecalclusters.front()->clusterRef());
1846  new_sc.setCorrectedEnergy(corrSCEnergy);
1847  new_sc.setSeed(clusptr);
1848  new_sc.setPreshowerEnergyPlane1(ps1_energy);
1849  new_sc.setPreshowerEnergyPlane2(ps2_energy);
1850  new_sc.setPreshowerEnergy(corrPSEnergy);
1851  for (const auto& clus : RO.ecalclusters) {
1852  clusptr = edm::refToPtr<reco::PFClusterCollection>(clus->clusterRef());
1853  new_sc.addCluster(clusptr);
1854  auto& hits_and_fractions = clusptr->hitsAndFractions();
1855  for (auto& hit_and_fraction : hits_and_fractions) {
1856  new_sc.addHitAndFraction(hit_and_fraction.first, hit_and_fraction.second);
1857  }
1858  // put the preshower stuff back in later
1859  if (RO.ecal2ps.count(clus.get())) {
1860  const auto& cluspsassociation = RO.ecal2ps.at(clus.get());
1861  // EE rechits should be uniquely matched to sets of pre-shower
1862  // clusters at this point, so we throw an exception if otherwise
1863  // now wrapped in EDM debug flags
1864  for (const auto& pscluselem : cluspsassociation) {
1865  edm::Ptr<reco::PFCluster> psclus = edm::refToPtr<reco::PFClusterCollection>(pscluselem->clusterRef());
1866 #ifdef PFFLOW_DEBUG
1867  auto found_pscluster =
1869  if (found_pscluster == new_sc.preshowerClustersEnd()) {
1870 #endif
1871  new_sc.addPreshowerCluster(psclus);
1872 #ifdef PFFLOW_DEBUG
1873  } else {
1874  throw cms::Exception("PFECALSuperClusterAlgo::buildSuperCluster")
1875  << "Found a PS cluster matched to more than one EE cluster!" << std::endl
1876  << std::hex << psclus.get() << " == " << found_pscluster->get() << std::dec << std::endl;
1877  }
1878 #endif
1879  }
1880  }
1881  }
1882 
1883  // calculate linearly weighted cluster widths
1884  PFClusterWidthAlgo pfwidth(bare_ptrs);
1885  new_sc.setEtaWidth(pfwidth.pflowEtaWidth());
1886  new_sc.setPhiWidth(pfwidth.pflowPhiWidth());
1887 
1888  // cache the value of the raw energy
1889  new_sc.rawEnergy();
1890 
1891  return new_sc;
1892 }
1893 
1895  // this only means something for ROs with a primary GSF track
1896  if (RO.primaryGSFs.empty())
1897  return;
1898  // need energy sums to tell if we've added crap or not
1899  const double Pin_gsf = RO.primaryGSFs.front()->GsftrackRef()->pMode();
1900  const double gsfOuterEta = RO.primaryGSFs.front()->positionAtECALEntrance().Eta();
1901  double tot_ecal = 0.0;
1902  std::vector<double> min_brem_dists;
1903  std::vector<double> closest_brem_eta;
1904  // first get the total ecal energy (we should replace this with a cache)
1905  for (const auto& ecal : RO.ecalclusters) {
1906  tot_ecal += ecal->clusterRef()->correctedEnergy();
1907  // we also need to look at the minimum distance to brems
1908  // since energetic brems will be closer to the brem than the track
1909  double min_brem_dist = 5000.0;
1910  double eta = -999.0;
1911  for (const auto& brem : RO.brems) {
1912  const float dist = _currentblock->dist(brem->index(), ecal->index(), _currentlinks, reco::PFBlock::LINKTEST_ALL);
1913  if (dist < min_brem_dist && dist != -1.0f) {
1914  min_brem_dist = dist;
1915  eta = brem->positionAtECALEntrance().Eta();
1916  }
1917  }
1918  min_brem_dists.push_back(min_brem_dist);
1919  closest_brem_eta.push_back(eta);
1920  }
1921 
1922  // loop through the ECAL clusters and remove ECAL clusters matched to
1923  // secondary track either in *or* out of the SC if the E/pin is bad
1924  for (auto secd_kf = RO.secondaryKFs.begin(); secd_kf != RO.secondaryKFs.end(); ++secd_kf) {
1925  reco::TrackRef trkRef = (*secd_kf)->trackRef();
1926  const float secpin = (*secd_kf)->trackRef()->p();
1927  bool remove_this_kf = false;
1928  for (auto ecal = RO.ecalclusters.begin(); ecal != RO.ecalclusters.end(); ++ecal) {
1929  size_t bremidx = std::distance(RO.ecalclusters.begin(), ecal);
1930  const float minbremdist = min_brem_dists[bremidx];
1931  const double ecalenergy = (*ecal)->clusterRef()->correctedEnergy();
1932  const double Epin = ecalenergy / secpin;
1933  const double detaGsf = std::abs(gsfOuterEta - (*ecal)->clusterRef()->positionREP().Eta());
1934  const double detaBrem = std::abs(closest_brem_eta[bremidx] - (*ecal)->clusterRef()->positionREP().Eta());
1935 
1936  bool kf_matched = RO.localMap.contains(ecal->get(), *secd_kf);
1937 
1938  const float tkdist =
1939  _currentblock->dist((*secd_kf)->index(), (*ecal)->index(), _currentlinks, reco::PFBlock::LINKTEST_ALL);
1940 
1941  // do not reject this track if it is closer to a brem than the
1942  // secondary track, or if it lies in the delta-eta plane with the
1943  // gsf track or if it is in the dEta plane with the brems
1944  if (Epin > 3 && kf_matched && tkdist != -1.0f && tkdist < minbremdist && detaGsf > 0.05 && detaBrem > 0.015) {
1945  double res_with = std::abs((tot_ecal - Pin_gsf) / Pin_gsf);
1946  double res_without = std::abs((tot_ecal - ecalenergy - Pin_gsf) / Pin_gsf);
1947  if (res_without < res_with) {
1948  LOGDRESSED("PFEGammaAlgo") << " REJECTED_RES totenergy " << tot_ecal << " Pin_gsf " << Pin_gsf
1949  << " cluster to secondary " << ecalenergy << " res_with " << res_with
1950  << " res_without " << res_without << std::endl;
1951  tot_ecal -= ecalenergy;
1952  remove_this_kf = true;
1953  ecal = RO.ecalclusters.erase(ecal);
1954  if (ecal == RO.ecalclusters.end())
1955  break;
1956  }
1957  }
1958  }
1959  if (remove_this_kf) {
1960  secd_kf = RO.secondaryKFs.erase(secd_kf);
1961  if (secd_kf == RO.secondaryKFs.end())
1962  break;
1963  }
1964  }
1965 }
1966 
1968  bool removeFreeECAL,
1969  bool removeSCEcal) {
1970  std::vector<bool> cluster_in_sc;
1971  auto ecal_begin = RO.ecalclusters.begin();
1972  auto ecal_end = RO.ecalclusters.end();
1973  auto hcal_begin = _splayedblock[reco::PFBlockElement::HCAL].begin();
1974  auto hcal_end = _splayedblock[reco::PFBlockElement::HCAL].end();
1975  for (auto secd_kf = RO.secondaryKFs.begin(); secd_kf != RO.secondaryKFs.end(); ++secd_kf) {
1976  bool remove_this_kf = false;
1977  NotCloserToOther<reco::PFBlockElement::TRACK, reco::PFBlockElement::HCAL> tracksToHCALs(_currentblock, *secd_kf);
1978  reco::TrackRef trkRef = (*secd_kf)->trackRef();
1979 
1980  bool goodTrack = PFTrackAlgoTools::isGoodForEGM(trkRef->algo());
1981  const float secpin = trkRef->p();
1982 
1983  for (auto ecal = ecal_begin; ecal != ecal_end; ++ecal) {
1984  const double ecalenergy = (*ecal)->clusterRef()->correctedEnergy();
1985  // first check if the cluster is in the SC (use dist calc for fastness)
1986  const size_t clus_idx = std::distance(ecal_begin, ecal);
1987  if (cluster_in_sc.size() < clus_idx + 1) {
1988  float dist = -1.0f;
1989  if (RO.parentSC) {
1990  dist = _currentblock->dist((*secd_kf)->index(), (*ecal)->index(), _currentlinks, reco::PFBlock::LINKTEST_ALL);
1991  }
1992  cluster_in_sc.push_back(dist != -1.0f);
1993  }
1994 
1995  // if we've found a secondary KF that matches this ecal cluster
1996  // now we see if it is matched to HCAL
1997  // if it is matched to an HCAL cluster we take different
1998  // actions if the cluster was in an SC or not
1999  if (RO.localMap.contains(ecal->get(), *secd_kf)) {
2000  auto hcal_matched = std::partition(hcal_begin, hcal_end, tracksToHCALs);
2001  for (auto hcalclus = hcal_begin; hcalclus != hcal_matched; ++hcalclus) {
2002  const reco::PFBlockElementCluster* clusthcal = docast(const reco::PFBlockElementCluster*, hcalclus->get());
2003  const double hcalenergy = clusthcal->clusterRef()->energy();
2004  const double hpluse = ecalenergy + hcalenergy;
2005  const bool isHoHE = ((hcalenergy / hpluse) > 0.1 && goodTrack);
2006  const bool isHoE = (hcalenergy > ecalenergy);
2007  const bool isPoHE = (secpin > hpluse);
2008  if (cluster_in_sc[clus_idx]) {
2009  if (isHoE || isPoHE) {
2010  LOGDRESSED("PFEGammaAlgo") << "REJECTED TRACK FOR H/E or P/(H+E), CLUSTER IN SC"
2011  << " H/H+E " << (hcalenergy / hpluse) << " H/E " << (hcalenergy > ecalenergy)
2012  << " P/(H+E) " << (secpin / hpluse) << " HCAL ENE " << hcalenergy
2013  << " ECAL ENE " << ecalenergy << " secPIN " << secpin << " Algo Track "
2014  << trkRef->algo() << std::endl;
2015  remove_this_kf = true;
2016  }
2017  } else {
2018  if (isHoHE) {
2019  LOGDRESSED("PFEGammaAlgo") << "REJECTED TRACK FOR H/H+E, CLUSTER NOT IN SC"
2020  << " H/H+E " << (hcalenergy / hpluse) << " H/E " << (hcalenergy > ecalenergy)
2021  << " P/(H+E) " << (secpin / hpluse) << " HCAL ENE " << hcalenergy
2022  << " ECAL ENE " << ecalenergy << " secPIN " << secpin << " Algo Track "
2023  << trkRef->algo() << std::endl;
2024  remove_this_kf = true;
2025  }
2026  }
2027  }
2028  }
2029  }
2030  if (remove_this_kf) {
2031  secd_kf = RO.secondaryKFs.erase(secd_kf);
2032  if (secd_kf == RO.secondaryKFs.end())
2033  break;
2034  }
2035  }
2036 }
2037 
2039  bool isPrimary = false;
2040 
2041  const GsfPFRecTrackRef& gsfPfRef = GsfEl.GsftrackRefPF();
2042 
2043  if (gsfPfRef.isNonnull()) {
2044  const PFRecTrackRef& kfPfRef = KfEl.trackRefPF();
2045  PFRecTrackRef kfPfRef_fromGsf = (*gsfPfRef).kfPFRecTrackRef();
2046  if (kfPfRef.isNonnull() && kfPfRef_fromGsf.isNonnull()) {
2047  reco::TrackRef kfref = (*kfPfRef).trackRef();
2048  reco::TrackRef kfref_fromGsf = (*kfPfRef_fromGsf).trackRef();
2049  if (kfref.isNonnull() && kfref_fromGsf.isNonnull()) {
2050  if (kfref == kfref_fromGsf)
2051  isPrimary = true;
2052  }
2053  }
2054  }
2055 
2056  return isPrimary;
2057 }
Vector3DBase
Definition: Vector3DBase.h:8
muonTagProbeFilters_cff.matched
matched
Definition: muonTagProbeFilters_cff.py:62
reco::PFBlockElementTrack::trackType
bool trackType(TrackType trType) const override
Definition: PFBlockElementTrack.h:28
reco::PFCandidateEGammaExtra::setHadEnergy
void setHadEnergy(float val)
set the had energy. The cluster energies should be entered before
Definition: PFCandidateEGammaExtra.cc:74
PFEGammaAlgo::linkRefinableObjectPrimaryGSFTrackToECAL
void linkRefinableObjectPrimaryGSFTrackToECAL(ProtoEGObject &)
Definition: PFEGammaAlgo.cc:1223
reco::PFBlockElementGsfTrack::GsftrackRef
const reco::GsfTrackRef & GsftrackRef() const
Definition: PFBlockElementGsfTrack.h:49
reco::PFBlockElementGsfTrack::trackType
bool trackType(TrackType trType) const override
Definition: PFBlockElementGsfTrack.h:31
PFEGammaAlgo::mergeROsByAnyLink
void mergeROsByAnyLink(std::list< ProtoEGObject > &)
Definition: PFEGammaAlgo.cc:1080
AlCaHLTBitMon_QueryRunRegistry.comp
string comp
Definition: AlCaHLTBitMon_QueryRunRegistry.py:249
PFEGammaAlgo::_splayedblock
std::vector< std::vector< FlaggedPtr< const reco::PFBlockElement > > > _splayedblock
Definition: PFEGammaAlgo.h:148
LOGERR
#define LOGERR(x)
Definition: PFEGammaAlgo.cc:46
mps_fire.i
i
Definition: mps_fire.py:428
PFEGammaAlgo::ProtoEGObject::ecal2ps
ClusterMap ecal2ps
Definition: PFEGammaAlgo.h:92
PFClusterWidthAlgo::pflowEtaWidth
double pflowEtaWidth() const
Definition: PFClusterWidthAlgo.h:15
PFEGammaAlgo::linkRefinableObjectConvSecondaryKFsToSecondaryKFs
void linkRefinableObjectConvSecondaryKFsToSecondaryKFs(ProtoEGObject &)
Definition: PFEGammaAlgo.cc:1398
PFEGammaAlgo::ProtoEGObject::parentSC
const PFSCElement * parentSC
Definition: PFEGammaAlgo.h:86
MessageLogger.h
PFMuonAlgo.h
CommutativePairs::contains
bool contains(T const &a, T const &b) const
Definition: CommutativePairs.h:20
PFEGammaAlgo::ProtoEGObject::electronSeed
reco::ElectronSeedRef electronSeed
Definition: PFEGammaAlgo.h:87
f
double f[11][100]
Definition: MuScleFitUtils.cc:78
reco::PFCandidateEGammaExtra::setDeltaEta
void setDeltaEta(float val)
set the delta eta
Definition: PFCandidateEGammaExtra.cc:85
PFEGammaAlgo::EgammaObjects
Definition: PFEGammaAlgo.h:117
PFEGammaAlgo::cfg_
PFEGConfigInfo const & cfg_
Definition: PFEGammaAlgo.h:221
convertSQLitetoXML_cfg.output
output
Definition: convertSQLitetoXML_cfg.py:72
reco::SuperCluster
Definition: SuperCluster.h:18
PFEGammaAlgo::ProtoEGObject::brems
std::vector< PFBremElement const * > brems
Definition: PFEGammaAlgo.h:96
X
#define X(str)
Definition: MuonsGrabber.cc:38
edm::Ref::isAvailable
bool isAvailable() const
Definition: Ref.h:537
min
T min(T a, T b)
Definition: MathUtil.h:58
reco::Vertex::z
double z() const
z coordinate
Definition: Vertex.h:133
reco::PFCandidateEGammaExtra::addExtraNonConvTrack
void addExtraNonConvTrack(const reco::PFBlockRef &blk, const reco::PFBlockElementTrack &tkref)
track counting for electrons and photons
Definition: PFCandidateEGammaExtra.h:177
deltaPhi.h
PFEGammaAlgo::channelStatus_
ESChannelStatus const & channelStatus_
Definition: PFEGammaAlgo.h:224
hcal
Definition: ConfigurationDatabase.cc:13
edm::Ref::isNull
bool isNull() const
Checks for null.
Definition: Ref.h:235
reco::PFBlockElementBrem::indTrajPoint
unsigned int indTrajPoint() const
Definition: PFBlockElementBrem.h:38
reco::CaloCluster::setCorrectedEnergy
void setCorrectedEnergy(double cenergy)
Definition: CaloCluster.h:137
reco::PFBlockElementSuperCluster
Cluster Element.
Definition: PFBlockElementSuperCluster.h:15
PFEGammaAlgo::linkRefinableObjectECALToSingleLegConv
void linkRefinableObjectECALToSingleLegConv(ProtoEGObject &)
Definition: PFEGammaAlgo.cc:1421
reco::PFBlock
Block of elements.
Definition: PFBlock.h:26
PFEGammaAlgo::ProtoEGObject::electronClusters
std::vector< const PFClusterElement * > electronClusters
Definition: PFEGammaAlgo.h:106
reco::SuperCluster::setEtaWidth
void setEtaWidth(double ew)
Definition: SuperCluster.h:74
EBDetId.h
EEDetId.h
reco::PFBlockElement::SC
Definition: PFBlockElement.h:41
reco::PFCandidateEGammaExtra::addConversionRef
void addConversionRef(const reco::ConversionRef &convref)
add Conversions from PF
Definition: PFCandidateEGammaExtra.cc:143
PFEGammaAlgo::PFEGConfigInfo::applyCrackCorrections
bool applyCrackCorrections
Definition: PFEGammaAlgo.h:112
reco::PFBlockElementTrack::trackRef
const reco::TrackRef & trackRef() const override
Definition: PFBlockElementTrack.h:49
edm::Ref::get
T const * get() const
Returns C++ pointer to the item.
Definition: Ref.h:232
info
static const TGPicture * info(bool iBackgroundIsBlack)
Definition: FWCollectionSummaryWidget.cc:153
PFEGammaAlgo::ProtoEGObject::nBremsWithClusters
int nBremsWithClusters
Definition: PFEGammaAlgo.h:107
PFEGammaAlgo::gbrForests_
GBRForests const & gbrForests_
Definition: PFEGammaAlgo.h:135
reco::Vertex::position
const Point & position() const
position
Definition: Vertex.h:127
PFEGammaAlgo::ProtoEGObject::ecalclusters
std::vector< FlaggedPtr< const PFClusterElement > > ecalclusters
Definition: PFEGammaAlgo.h:91
spr::goodTrack
bool goodTrack(const reco::Track *pTrack, math::XYZPoint leadPV, trackSelectionParameters parameters, bool debug=false)
Definition: TrackSelection.cc:10
reco::PFBlockElement::HCAL
Definition: PFBlockElement.h:36
edm::Ptr::get
T const * get() const
Returns C++ pointer to the item.
Definition: Ptr.h:139
PFEGammaAlgo::ProtoEGObject::localMap
CommutativePairs< const reco::PFBlockElement * > localMap
Definition: PFEGammaAlgo.h:103
DDAxes::x
edm::RefVector< ConversionCollection >
reco::Vertex::tracks_end
trackRef_iterator tracks_end() const
last iterator over tracks
Definition: Vertex.h:110
ESDetId.h
reco::PFBlockElement::HGCAL
Definition: PFBlockElement.h:43
reco
fixed size matrix
Definition: AlignmentAlgorithmBase.h:46
PFEGammaAlgo::evaluateSingleLegMVA
float evaluateSingleLegMVA(const reco::PFBlockRef &blockref, const reco::Vertex &primaryVtx, unsigned int trackIndex)
Definition: PFEGammaAlgo.cc:460
hltPixelTracks_cff.chi2
chi2
Definition: hltPixelTracks_cff.py:25
reco::SuperCluster::setPreshowerEnergy
void setPreshowerEnergy(double preshowerEnergy)
Definition: SuperCluster.h:70
edm::Ptr::key
key_type key() const
Definition: Ptr.h:163
spr::find
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
ecal
Definition: ElectronicsMappingGPU.h:13
edm::Ref::index
key_type index() const
Definition: Ref.h:253
groupFilesInBlocks.temp
list temp
Definition: groupFilesInBlocks.py:142
reco::PFCandidateEGammaExtra
Definition: PFCandidateEGammaExtra.h:25
reco::PFCandidateEGammaExtra::setSuperClusterRef
void setSuperClusterRef(reco::SuperClusterRef sc)
set reference to the corresponding supercluster
Definition: PFCandidateEGammaExtra.h:108
reco::CaloClusterPtr
edm::Ptr< CaloCluster > CaloClusterPtr
Definition: CaloClusterFwd.h:21
reco::PFBlockElementGsfTrack::Pout
const math::XYZTLorentzVector & Pout() const
Definition: PFBlockElementGsfTrack.h:57
PFRecHit.h
reco::PFCandidateEGammaExtra::setMVA
void setMVA(float val)
set the result (mostly for debugging)
Definition: PFCandidateEGammaExtra.cc:116
reco::PFBlockElementSuperCluster::Dump
void Dump(std::ostream &out=std::cout, const char *tab=" ") const override
print the object inside the element
Definition: PFBlockElementSuperCluster.cc:11
Mustache.h
edm::Ref< ElectronSeedCollection >
hltEgammaHLTExtra_cfi.hcal
hcal
Definition: hltEgammaHLTExtra_cfi.py:42
reco::PFBlockElementGsfTrack::positionAtECALEntrance
const math::XYZPointF & positionAtECALEntrance() const
Definition: PFBlockElementGsfTrack.h:52
PFLayer::ECAL_BARREL
Definition: PFLayer.h:33
reco::PFCandidateEGammaExtra::setEarlyBrem
void setEarlyBrem(float val)
set EarlyBrem
Definition: PFCandidateEGammaExtra.cc:69
reco::PFBlockElement::Type
Type
Definition: PFBlockElement.h:30
PFClusterWidthAlgo::pflowPhiWidth
double pflowPhiWidth() const
Definition: PFClusterWidthAlgo.h:14
heavyIonCSV_trainingSettings.idx
idx
Definition: heavyIonCSV_trainingSettings.py:5
PFEGammaAlgo::unlinkRefinableObjectKFandECALWithBadEoverP
void unlinkRefinableObjectKFandECALWithBadEoverP(ProtoEGObject &)
Definition: PFEGammaAlgo.cc:1894
PFLayer.h
reco::SuperCluster::addCluster
void addCluster(const CaloClusterPtr &r)
add reference to constituent BasicCluster
Definition: SuperCluster.h:122
edm::refToPtr
Ptr< typename C::value_type > refToPtr(Ref< C, typename C::value_type, refhelper::FindUsingAdvance< C, typename C::value_type > > const &ref)
Definition: RefToPtr.h:18
reco::SuperCluster::setSeed
void setSeed(const CaloClusterPtr &r)
list of used xtals by DetId // now inherited by CaloCluster
Definition: SuperCluster.h:107
reco::SuperCluster::preshowerClustersBegin
CaloCluster_iterator preshowerClustersBegin() const
fist iterator over PreshowerCluster constituents
Definition: SuperCluster.h:92
GetRecoTauVFromDQM_MC_cff.cl
cl
Definition: GetRecoTauVFromDQM_MC_cff.py:38
BeamMonitor_cff.primaryVertex
primaryVertex
hltOfflineBeamSpot for HLTMON
Definition: BeamMonitor_cff.py:7
PFEGammaAlgo::ProtoEGObject::primaryGSFs
std::vector< PFGSFElement const * > primaryGSFs
Definition: PFEGammaAlgo.h:94
reco::PFCandidateEGammaExtra::setGsfElectronClusterRef
void setGsfElectronClusterRef(const reco::PFBlockRef &blk, const reco::PFBlockElementCluster &ref)
set gsf electron cluster ref
Definition: PFCandidateEGammaExtra.h:88
PFEnergyCalibration.h
Photon.h
reco::PFCandidateEGammaExtra::setKfTrackRef
void setKfTrackRef(const reco::TrackRef &ref)
set kf track reference
Definition: PFCandidateEGammaExtra.cc:51
ECAL
Definition: HCALResponse.h:21
alignCSCRings.s
s
Definition: alignCSCRings.py:92
test
Definition: SmallWORMDict.h:13
ctpps_dqm_sourceclient-live_cfg.test
test
Definition: ctpps_dqm_sourceclient-live_cfg.py:7
PFEGammaAlgo::primaryVertex_
reco::Vertex const & primaryVertex_
Definition: PFEGammaAlgo.h:222
PFEGammaAlgo::isPrimaryTrack
bool isPrimaryTrack(const reco::PFBlockElementTrack &KfEl, const reco::PFBlockElementGsfTrack &GsfEl)
Definition: PFEGammaAlgo.cc:2038
reco::PFCandidateEGammaExtra::setGsfTrackPout
void setGsfTrackPout(const math::XYZTLorentzVector &pout)
set the pout (not trivial to get from the GSF track)
Definition: PFCandidateEGammaExtra.cc:49
std::swap
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
Definition: DataFrameContainer.h:209
reco::PFBlockElementTrack::trackRefPF
const PFRecTrackRef & trackRefPF() const override
Definition: PFBlockElementTrack.h:46
SiPixelRawToDigiRegional_cfi.deltaPhi
deltaPhi
Definition: SiPixelRawToDigiRegional_cfi.py:9
LOGDRESSED
#define LOGDRESSED(x)
Definition: PFEGammaAlgo.cc:47
vars
vars
Definition: DeepTauId.cc:164
PFEGammaAlgo::calculateEleMVA
float calculateEleMVA(const ProtoEGObject &, reco::PFCandidateEGammaExtra &) const
Definition: PFEGammaAlgo.cc:1604
reco::PFBlockElement::TRACK
Definition: PFBlockElement.h:32
PVValHelper::eta
Definition: PVValidationHelpers.h:70
mathSSE::sqrt
T sqrt(T t)
Definition: SSEVec.h:19
PFEGammaAlgo::GBRForests::ele_
const std::unique_ptr< const GBRForest > ele_
Definition: PFEGammaAlgo.h:80
PFEGammaAlgo::ClusterMap
std::unordered_map< PFClusterElement const *, std::vector< PFClusterElement const * > > ClusterMap
Definition: PFEGammaAlgo.h:72
CommutativePairs::concatenate
void concatenate(CommutativePairs< T > const &other)
Add the pairs from another CommutativePairs to this.
Definition: CommutativePairs.h:40
PFCluster.h
reco::CaloCluster::badHcalMarker
Definition: CaloCluster.h:50
PFEGammaAlgo::_currentblock
reco::PFBlockRef _currentblock
Definition: PFEGammaAlgo.h:144
reco::PFBlockElementBrem
Track Element.
Definition: PFBlockElementBrem.h:17
RecoTauValidation_cfi.posX
posX
Definition: RecoTauValidation_cfi.py:287
HCALHighEnergyHPDFilter_cfi.energy
energy
Definition: HCALHighEnergyHPDFilter_cfi.py:5
reco::PFCandidateEGammaExtra::setLateBrem
void setLateBrem(float val)
set LateBrem
Definition: PFCandidateEGammaExtra.cc:64
PFEGammaAlgo::fillExtraInfo
void fillExtraInfo(const ProtoEGObject &, reco::PFCandidateEGammaExtra &)
Definition: PFEGammaAlgo.cc:1768
VtxSmearedParameters_cfi.Phi
Phi
Definition: VtxSmearedParameters_cfi.py:112
PFClusterWidthAlgo::pflowSigmaEtaEta
double pflowSigmaEtaEta() const
Definition: PFClusterWidthAlgo.h:16
PFClusterWidthAlgo.h
HCAL
Definition: HCALResponse.h:21
b
double b
Definition: hdecay.h:118
PFEGammaAlgo::linkRefinableObjectBremTangentsToECAL
void linkRefinableObjectBremTangentsToECAL(ProtoEGObject &)
Definition: PFEGammaAlgo.cc:1333
reco::SuperCluster::setPreshowerEnergyPlane1
void setPreshowerEnergyPlane1(double preshowerEnergy1)
Definition: SuperCluster.h:71
PFEnergyCalibration::initAlphaGamma_ESplanes_fromDB
void initAlphaGamma_ESplanes_fromDB(const ESEEIntercalibConstants *esEEInterCalib)
Definition: PFEnergyCalibration.h:67
ClusterClusterMapping::overlap
static bool overlap(const reco::CaloCluster &sc1, const reco::CaloCluster &sc, float minfrac=0.01, bool debug=false)
Definition: ClusterClusterMapping.cc:4
PFLayer::Layer
Layer
layer definition
Definition: PFLayer.h:29
reco::PFCandidateEGammaExtra::setGsfTrackRef
void setGsfTrackRef(const reco::GsfTrackRef &ref)
set gsftrack reference
Definition: PFCandidateEGammaExtra.cc:47
MuonTCMETValueMapProducer_cff.nLayers
nLayers
Definition: MuonTCMETValueMapProducer_cff.py:38
reco::PFBlockElement::TrackType
TrackType
Definition: PFBlockElement.h:47
reco::Vertex::tracks_begin
trackRef_iterator tracks_begin() const
first iterator over tracks
Definition: Vertex.h:108
LOGWARN
#define LOGWARN(x)
Definition: PFEGammaAlgo.cc:45
PFEGammaAlgo::ProtoEGObject::hcalClusters
std::vector< PFClusterElement const * > hcalClusters
Definition: PFEGammaAlgo.h:102
PFEGammaAlgo::linkRefinableObjectGSFTracksToKFs
void linkRefinableObjectGSFTracksToKFs(ProtoEGObject &)
Definition: PFEGammaAlgo.cc:1160
reco::PFCandidateEGammaExtra::setSuperClusterPFECALRef
void setSuperClusterPFECALRef(reco::SuperClusterRef sc)
set reference to the corresponding supercluster
Definition: PFCandidateEGammaExtra.h:111
PFTrackAlgoTools.h
PFEGammaAlgo::ProtoEGObject::singleLegConversionMvaMap
KFValMap singleLegConversionMvaMap
Definition: PFEGammaAlgo.h:100
reco::PFBlockElementTrack::positionAtECALEntrance
const math::XYZPointF & positionAtECALEntrance() const
Definition: PFBlockElementTrack.h:42
math::XYZPoint
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
delPhi
static double delPhi(const double phi1, const double phi2)
Definition: FFTGenericScaleCalculator.cc:20
a
double a
Definition: hdecay.h:119
reco::SuperCluster::seed
const CaloClusterPtr & seed() const
seed BasicCluster
Definition: SuperCluster.h:77
reco::PFCandidateEGammaExtra::setSigmaEtaEta
void setSigmaEtaEta(float val)
set the sigmaetaeta
Definition: PFCandidateEGammaExtra.cc:80
PFEGammaAlgo::PFEGConfigInfo
Definition: PFEGammaAlgo.h:110
reco::PFBlockElement::GSF
Definition: PFBlockElement.h:37
deltaR.h
SiStripPI::max
Definition: SiStripPayloadInspectorHelper.h:169
PFEGammaAlgo::initializeProtoCands
void initializeProtoCands(std::list< ProtoEGObject > &)
Definition: PFEGammaAlgo.cc:656
phase2tkutil::isPrimary
bool isPrimary(const SimTrack &simTrk, const PSimHit *simHit)
Definition: TrackerPhase2ValidationUtil.cc:2
jetUpdater_cfi.sort
sort
Definition: jetUpdater_cfi.py:29
reco::Vertex::x
double x() const
x coordinate
Definition: Vertex.h:129
edm::Ref::isNonnull
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:238
PFTrackAlgoTools::isGoodForEGMPrimary
bool isGoodForEGMPrimary(const reco::TrackBase::TrackAlgorithm &)
Definition: PFTrackAlgoTools.cc:144
reco::CaloCluster::addHitAndFraction
void addHitAndFraction(DetId id, float fraction)
Definition: CaloCluster.h:203
PFEGammaAlgo::linkRefinableObjectPrimaryKFsToSecondaryKFs
void linkRefinableObjectPrimaryKFsToSecondaryKFs(ProtoEGObject &)
Definition: PFEGammaAlgo.cc:1192
StorageManager_cfg.e1
e1
Definition: StorageManager_cfg.py:16
math::XYZVector
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:31
FlaggedPtr
Definition: FlaggedPtr.h:5
reco::TrackExtraRef
edm::Ref< TrackExtraCollection > TrackExtraRef
persistent reference to a TrackExtra
Definition: TrackExtraFwd.h:16
reco::PFBlockElement::ECAL
Definition: PFBlockElement.h:35
cand
Definition: decayParser.h:32
RefToPtr.h
PFEGammaAlgo::GBRForests::singleLeg_
const std::unique_ptr< const GBRForest > singleLeg_
Definition: PFEGammaAlgo.h:81
p4
double p4[4]
Definition: TauolaWrapper.h:92
PFEGammaAlgo::removeOrLinkECALClustersToKFTracks
void removeOrLinkECALClustersToKFTracks()
Definition: PFEGammaAlgo.cc:1001
reco::PFBlockElement::T_FROM_GAMMACONV
Definition: PFBlockElement.h:47
trackerHitRTTI::vector
Definition: trackerHitRTTI.h:21
reco::PFCandidateEGammaExtra::addSingleLegConvTrackRefMva
void addSingleLegConvTrackRefMva(const std::pair< reco::TrackRef, float > &trackrefmva)
add Single Leg Conversion TrackRef
Definition: PFCandidateEGammaExtra.cc:139
PFEGammaAlgo::attachPSClusters
int attachPSClusters(const PFClusterElement *, ClusterMap::mapped_type &)
Definition: PFEGammaAlgo.cc:902
ntupleEnum.gsf
gsf
Definition: ntupleEnum.py:48
groupFilesInBlocks.block
block
Definition: groupFilesInBlocks.py:150
PFEGammaAlgo::linkRefinableObjectKFTracksToECAL
void linkRefinableObjectKFTracksToECAL(ProtoEGObject &)
Definition: PFEGammaAlgo.cc:1287
CommutativePairs::insert
void insert(T const &a, T const &b)
Definition: CommutativePairs.h:17
PFEGammaAlgo::EEtoPSAssociation
reco::PFCluster::EEtoPSAssociation EEtoPSAssociation
Definition: PFEGammaAlgo.h:64
reco::SuperCluster::addPreshowerCluster
void addPreshowerCluster(const CaloClusterPtr &r)
add reference to constituent BasicCluster
Definition: SuperCluster.h:128
PFEGammaAlgo::linkRefinableObjectSecondaryKFsToECAL
void linkRefinableObjectSecondaryKFsToECAL(ProtoEGObject &)
Definition: PFEGammaAlgo.cc:1451
reco::PFBlock::LinkData
std::map< unsigned int, Link > LinkData
Definition: PFBlock.h:39
reco::PFBlock::LINKTEST_ALL
Definition: PFBlock.h:41
ESCondObjectContainer
Definition: ESCondObjectContainer.h:11
PFEGammaAlgo::GBRForests
Definition: PFEGammaAlgo.h:74
reco::PFBlockElement
Abstract base class for a PFBlock element (track, cluster...)
Definition: PFBlockElement.h:26
reco::PFBlockElementSuperCluster::superClusterRef
const SuperClusterRef & superClusterRef() const
Definition: PFBlockElementSuperCluster.h:36
cmsLHEtoEOSManager.l
l
Definition: cmsLHEtoEOSManager.py:204
reco::CaloCluster::position
const math::XYZPoint & position() const
cluster centroid position
Definition: CaloCluster.h:154
PFRecHitFraction.h
edm::Ptr< reco::PFCluster >
looper.cfg
cfg
Definition: looper.py:296
TtFullHadJetPartonMatch_cfi.maxDist
maxDist
Definition: TtFullHadJetPartonMatch_cfi.py:35
reco::SuperCluster::setPreshowerEnergyPlane2
void setPreshowerEnergyPlane2(double preshowerEnergy2)
Definition: SuperCluster.h:72
PFEGammaAlgo::ProtoEGObject::primaryKFs
std::vector< PFKFElement const * > primaryKFs
Definition: PFEGammaAlgo.h:95
reco::PFBlockElementGsfTrack
Track Element.
Definition: PFBlockElementGsfTrack.h:18
bookConverter.elements
elements
Definition: bookConverter.py:147
eostools.move
def move(src, dest)
Definition: eostools.py:511
std
Definition: JetResolutionObject.h:76
stdcomb::next_combination
bool next_combination(BidIt n_begin, BidIt n_end, BidIt r_begin, BidIt r_end)
Definition: combination.h:19
reco::Vertex::y
double y() const
y coordinate
Definition: Vertex.h:131
ClusterClusterMapping.h
PFMuonAlgo::isMuon
static bool isMuon(const reco::PFBlockElement &elt)
Definition: PFMuonAlgo.cc:48
PFEnergyResolution.h
PFEGammaAlgo::linkKFTrackToECAL
void linkKFTrackToECAL(PFKFElement const *, ProtoEGObject &)
Definition: PFEGammaAlgo.cc:1296
PFEGammaAlgo::ProtoEGObject::lateBrem
int lateBrem
Definition: PFEGammaAlgo.h:107
edm::LogVerbatim
Log< level::Info, true > LogVerbatim
Definition: MessageLogger.h:128
T
long double T
Definition: Basic3DVectorLD.h:48
math::XYZTLorentzVector
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
PFEGammaAlgo::linkRefinableObjectPrimaryGSFTrackToHCAL
void linkRefinableObjectPrimaryGSFTrackToHCAL(ProtoEGObject &)
Definition: PFEGammaAlgo.cc:1266
PFEGammaAlgo::ProtoEGObject::secondaryKFs
std::vector< PFKFElement const * > secondaryKFs
Definition: PFEGammaAlgo.h:99
PFTrackAlgoTools::isGoodForEGM
bool isGoodForEGM(const reco::TrackBase::TrackAlgorithm &)
Definition: PFTrackAlgoTools.cc:117
reco::SuperCluster::rawEnergy
double rawEnergy() const
raw uncorrected energy (sum of energies of component BasicClusters)
Definition: SuperCluster.h:58
relativeConstraints.empty
bool empty
Definition: relativeConstraints.py:46
reco::PFBlockElementCluster
Cluster Element.
Definition: PFBlockElementCluster.h:16
Exception
Definition: hltDiff.cc:245
PFEGammaAlgo::_currentlinks
reco::PFBlock::LinkData _currentlinks
Definition: PFEGammaAlgo.h:145
PFClusterWidthAlgo
Definition: PFClusterWidthAlgo.h:6
electronStore.links
links
Definition: electronStore.py:149
PFEGammaAlgo.h
reco::PFBlockElementTrack
Track Element.
Definition: PFBlockElementTrack.h:17
reco::SuperCluster::preshowerClustersEnd
CaloCluster_iterator preshowerClustersEnd() const
last iterator over PreshowerCluster constituents
Definition: SuperCluster.h:95
PFEGammaAlgo::ProtoEGObject::firstBrem
int firstBrem
Definition: PFEGammaAlgo.h:107
PFEGammaAlgo::isMuon
bool isMuon(const reco::PFBlockElement &)
Definition: PFEGammaAlgo.cc:506
reco::SuperCluster::setPhiWidth
void setPhiWidth(double pw)
Definition: SuperCluster.h:73
PFEGammaAlgo::PFEGConfigInfo::mvaConvCut
double mvaConvCut
Definition: PFEGammaAlgo.h:114
edm::Ptr::isNonnull
bool isNonnull() const
Checks for non-null.
Definition: Ptr.h:146
reco::PFBlockElementGsfTrack::GsftrackRefPF
const GsfPFRecTrackRef & GsftrackRefPF() const
Definition: PFBlockElementGsfTrack.h:46
reco::PFBlockElementCluster::clusterRef
const PFClusterRef & clusterRef() const override
Definition: PFBlockElementCluster.h:29
PFEGammaAlgo::ProtoEGObject::parentBlock
reco::PFBlockRef parentBlock
Definition: PFEGammaAlgo.h:85
dqm-mbProfile.log
log
Definition: dqm-mbProfile.py:17
PFEnergyCalibration::CalibratedEndcapPFClusterEnergies::clusterEnergy
double clusterEnergy
Definition: PFEnergyCalibration.h:50
reco::PFBlockElement::type
Type type() const
Definition: PFBlockElement.h:69
bsc_activity_cfg.ecal
ecal
Definition: bsc_activity_cfg.py:25
LOGVERB
#define LOGVERB(x)
Definition: PFEGammaAlgo.cc:44
electronIdCutBasedExt_cfi.sigmaEtaEta
sigmaEtaEta
Definition: electronIdCutBasedExt_cfi.py:123
PFEGammaAlgo::eetops_
reco::PFCluster::EEtoPSAssociation const & eetops_
Definition: PFEGammaAlgo.h:143
reco::PFCandidate
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:41
mps_fire.result
result
Definition: mps_fire.py:311
reco::PFBlockElementGsfTrack::Dump
void Dump(std::ostream &out=std::cout, const char *tab=" ") const override
print the object inside the element
Definition: PFBlockElementGsfTrack.cc:30
ESEEIntercalibConstants
Definition: ESEEIntercalibConstants.h:7
reco::PFBlockElementGsfTrack::Pin
const math::XYZTLorentzVector & Pin() const
Definition: PFBlockElementGsfTrack.h:56
PFEGammaAlgo::unwrapSuperCluster
bool unwrapSuperCluster(const reco::PFBlockElementSuperCluster *, std::vector< FlaggedPtr< const PFClusterElement >> &, ClusterMap &)
Definition: PFEGammaAlgo.cc:777
funct::abs
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
reco::PFBlockElement::PS1
Definition: PFBlockElement.h:33
PFEGammaAlgo::operator()
EgammaObjects operator()(const reco::PFBlockRef &block)
Definition: PFEGammaAlgo.cc:528
reco::Vertex::index
unsigned int index
index type
Definition: Vertex.h:54
c
auto & c
Definition: CAHitNtupletGeneratorKernelsImpl.h:56
PFEnergyCalibration::calibrateEndcapClusterEnergies
CalibratedEndcapPFClusterEnergies calibrateEndcapClusterEnergies(reco::PFCluster const &eeCluster, std::vector< reco::PFCluster const * > const &psClusterPointers, ESChannelStatus const &channelStatus, bool applyCrackCorrections) const
Definition: PFEnergyCalibration.cc:154
reco::PFBlockElement::index
unsigned index() const
Definition: PFBlockElement.h:86
math::XYZPointF
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< float > > XYZPointF
point in space with cartesian internal representation
Definition: Point3D.h:10
PFLayer::ECAL_ENDCAP
Definition: PFLayer.h:32
docast
#define docast(x, y)
Definition: PFEGammaAlgo.cc:43
HLT_FULL_cff.distance
distance
Definition: HLT_FULL_cff.py:7746
crabWrapper.key
key
Definition: crabWrapper.py:19
PFEGammaAlgo::PFEGammaAlgo
PFEGammaAlgo(const PFEGConfigInfo &, GBRForests const &gbrForests, EEtoPSAssociation const &eetops, ESEEIntercalibConstants const &esEEInterCalib, ESChannelStatus const &channelStatus, reco::Vertex const &primaryVertex)
Definition: PFEGammaAlgo.cc:446
PFEGammaAlgo::dumpCurrentRefinableObjects
void dumpCurrentRefinableObjects() const
Definition: PFEGammaAlgo.cc:932
PFEGammaAlgo::ProtoEGObject
Definition: PFEGammaAlgo.h:84
class-composition.parent
parent
Definition: class-composition.py:98
listHistos.trackPt
trackPt
Definition: listHistos.py:120
reco::CaloCluster::energy
double energy() const
cluster energy
Definition: CaloCluster.h:149
TauDecayModes.dec
dec
Definition: TauDecayModes.py:142
PV3DBase::phi
Geom::Phi< T > phi() const
Definition: PV3DBase.h:66
PFEGammaAlgo::buildRefinedSuperCluster
reco::SuperCluster buildRefinedSuperCluster(const ProtoEGObject &)
Definition: PFEGammaAlgo.cc:1789
reco::PFBlockElementSuperCluster::fromPFSuperCluster
bool fromPFSuperCluster() const
Definition: PFBlockElementSuperCluster.h:86
PFEGammaAlgo::fillPFCandidates
EgammaObjects fillPFCandidates(const std::list< ProtoEGObject > &)
Definition: PFEGammaAlgo.cc:1469
PFEGammaAlgo::unlinkRefinableObjectKFandECALMatchedToHCAL
void unlinkRefinableObjectKFandECALMatchedToHCAL(ProtoEGObject &, bool removeFreeECAL=false, bool removeSCECAL=false)
Definition: PFEGammaAlgo.cc:1967
reco::Vertex
Definition: Vertex.h:35
RecoTauValidation_cfi.posY
posY
Definition: RecoTauValidation_cfi.py:288
PFEGammaAlgo::PFEGConfigInfo::produceEGCandsWithNoSuperCluster
bool produceEGCandsWithNoSuperCluster
Definition: PFEGammaAlgo.h:113
reco::PFBlockElementCluster::Dump
void Dump(std::ostream &out=std::cout, const char *tab=" ") const override
print the object inside the element
Definition: PFBlockElementCluster.cc:11
reco::PFBlockElement::PS2
Definition: PFBlockElement.h:34
edm::OwnVector< reco::PFBlockElement >
MillePedeFileConverter_cfg.e
e
Definition: MillePedeFileConverter_cfg.py:37
PFEGammaAlgo::thePFEnergyCalibration_
PFEnergyCalibration thePFEnergyCalibration_
Definition: PFEGammaAlgo.h:137