CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
PFEGammaAlgo.cc
Go to the documentation of this file.
23 #include <TFile.h>
24 #include <TVector2.h>
25 #include <iomanip>
26 #include <algorithm>
27 #include <TMath.h>
28 
29 // include combinations header (not yet included in boost)
30 #include "combination.hpp"
31 
32 // just for now do this
33 //#define PFLOW_DEBUG
34 
35 #ifdef PFLOW_DEBUG
36 #define docast(x,y) dynamic_cast<x>(y)
37 #define LOGVERB(x) edm::LogVerbatim(x)
38 #define LOGWARN(x) edm::LogWarning(x)
39 #define LOGERR(x) edm::LogError(x)
40 #define LOGDRESSED(x) edm::LogInfo(x)
41 #else
42 #define docast(x,y) reinterpret_cast<x>(y)
43 #define LOGVERB(x) LogTrace(x)
44 #define LOGWARN(x) edm::LogWarning(x)
45 #define LOGERR(x) edm::LogError(x)
46 #define LOGDRESSED(x) LogDebug(x)
47 #endif
48 
49 using namespace std;
50 using namespace reco;
51 
52 namespace {
53  typedef PFEGammaAlgo::PFSCElement SCElement;
54  typedef PFEGammaAlgo::EEtoPSAssociation EEtoPSAssociation;
55  typedef std::pair<CaloClusterPtr::key_type,CaloClusterPtr> EEtoPSElement;
56  typedef PFEGammaAlgo::PFClusterElement ClusterElement;
57  typedef PFEGammaAlgo::PFFlaggedElement PFFlaggedElement;
58  typedef PFEGammaAlgo::PFSCFlaggedElement SCFlaggedElement;
59  typedef PFEGammaAlgo::PFKFFlaggedElement KFFlaggedElement;
60  typedef PFEGammaAlgo::PFGSFFlaggedElement GSFFlaggedElement;
61  typedef PFEGammaAlgo::PFClusterFlaggedElement ClusterFlaggedElement;
62 
63  typedef std::unary_function<const ClusterFlaggedElement&,
64  bool> ClusterMatcher;
65 
66  typedef std::unary_function<const PFFlaggedElement&,
67  bool> PFFlaggedElementMatcher;
68  typedef std::binary_function<const PFFlaggedElement&,
69  const PFFlaggedElement&,
70  bool> PFFlaggedElementSorter;
71 
72  typedef std::unary_function<const reco::PFBlockElement&,
73  bool> PFElementMatcher;
74 
75  typedef std::unary_function<const PFEGammaAlgo::ProtoEGObject&,
76  bool> POMatcher;
77 
78  typedef std::unary_function<PFFlaggedElement&,
79  ClusterFlaggedElement> ClusterElementConverter;
80 
81  struct SumPSEnergy : public std::binary_function<double,
82  const ClusterFlaggedElement&,
83  double> {
85  SumPSEnergy(reco::PFBlockElement::Type type) : _thetype(type) {}
86  double operator()(double a,
87  const ClusterFlaggedElement& b) {
88 
89  return a + (_thetype == b.first->type())*b.first->clusterRef()->energy();
90  }
91  };
92 
93  bool comparePSMapByKey(const EEtoPSElement& a,
94  const EEtoPSElement& b) {
95  return a.first < b.first;
96  }
97 
98  struct UsableElementToPSCluster : public ClusterElementConverter {
99  ClusterFlaggedElement operator () (PFFlaggedElement& elem) {
100  const ClusterElement* pselemascluster =
101  docast(const ClusterElement*,elem.first);
102  if( reco::PFBlockElement::PS1 != pselemascluster->type() &&
103  reco::PFBlockElement::PS2 != pselemascluster->type() ) {
104  std::stringstream ps_err;
105  pselemascluster->Dump(ps_err,"\t");
106  throw cms::Exception("UseableElementToPSCluster()")
107  << "This element is not a PS cluster!" << std::endl
108  << ps_err.str() << std::endl;
109  }
110  if( elem.second == false ) {
111  std::stringstream ps_err;
112  pselemascluster->Dump(ps_err,"\t");
113  throw cms::Exception("UsableElementToPSCluster()")
114  << "PS Cluster matched to EE is already used! "
115  << "This should be impossible!" << std::endl
116  << ps_err.str() << std::endl;
117  }
118  elem.second = false; // flag as used!
119  return std::make_pair(pselemascluster,true);
120  }
121  };
122 
123  struct SeedMatchesToSCElement : public PFFlaggedElementMatcher {
124  reco::SuperClusterRef _scfromseed;
125  SeedMatchesToSCElement(const reco::ElectronSeedRef& s) {
126  _scfromseed = s->caloCluster().castTo<reco::SuperClusterRef>();
127  }
128  bool operator() (const PFFlaggedElement& elem) {
129  const SCElement* scelem = docast(const SCElement*,elem.first);
130  if( _scfromseed.isNull() || !elem.second || !scelem) return false;
131  return ( _scfromseed->seed()->seed() ==
132  scelem->superClusterRef()->seed()->seed() );
133  }
134  };
135 
136  struct SCSubClusterMatchesToElement : public PFFlaggedElementMatcher {
138  SCSubClusterMatchesToElement(const reco::CaloCluster_iterator& b,
139  const reco::CaloCluster_iterator& e) :
140  begin(b),
141  end(e) { }
142  bool operator() (const PFFlaggedElement& elem) {
143  const ClusterElement* cluselem =
144  docast(const ClusterElement*,elem.first);
145  if( !elem.second || !cluselem) return false;
147  for( ; cl != end; ++cl ) {
148  if((*cl)->seed() == cluselem->clusterRef()->seed()) {
149  return true;
150  }
151  }
152  return false;
153  }
154  };
155 
156  struct SeedMatchesToProtoObject : public POMatcher {
157  reco::SuperClusterRef _scfromseed;
158  bool _ispfsc;
159  SeedMatchesToProtoObject(const reco::ElectronSeedRef& s) {
160  _scfromseed = s->caloCluster().castTo<reco::SuperClusterRef>();
161  _ispfsc = false;
162  if( _scfromseed.isNonnull() ) {
163  const edm::Ptr<reco::PFCluster> testCast(_scfromseed->seed());
164  _ispfsc = testCast.isNonnull();
165  }
166  }
167  bool operator() (const PFEGammaAlgo::ProtoEGObject& po) {
168  if( _scfromseed.isNull() || !po.parentSC ) return false;
169  if( _ispfsc ) {
170  return ( _scfromseed->seed() ==
171  po.parentSC->superClusterRef()->seed() );
172  }
173  return ( _scfromseed->seed()->seed() ==
174  po.parentSC->superClusterRef()->seed()->seed() );
175  }
176  };
177 
178  template<bool useConvs=false>
179  bool elementNotCloserToOther(const reco::PFBlockRef& block,
180  const PFBlockElement::Type& keytype,
181  const size_t key,
182  const PFBlockElement::Type& valtype,
183  const size_t test,
184  const float EoPin_cut = 1.0e6) {
187  // this is inside out but I just want something that works right now
188  switch( keytype ) {
190  {
191  const reco::PFBlockElementGsfTrack* elemasgsf =
193  &(block->elements()[key]));
194  if( elemasgsf && valtype == PFBlockElement::ECAL ) {
195  const ClusterElement* elemasclus =
196  reinterpret_cast<const ClusterElement*>(&(block->elements()[test]));
197  float cluster_e = elemasclus->clusterRef()->correctedEnergy();
198  float trk_pin = elemasgsf->Pin().P();
199  if( cluster_e / trk_pin > EoPin_cut ) return false;
200  }
201  }
202  break;
204  {
205  const reco::PFBlockElementTrack* elemaskf =
207  &(block->elements()[key]));
208  if( elemaskf && valtype == PFBlockElement::ECAL ) {
209  const ClusterElement* elemasclus =
210  reinterpret_cast<const ClusterElement*>(&(block->elements()[test]));
211  float cluster_e = elemasclus->clusterRef()->correctedEnergy();
212  float trk_pin =
213  std::sqrt(elemaskf->trackRef()->innerMomentum().mag2());
214  if( cluster_e / trk_pin > EoPin_cut ) return false;
215  }
216  }
217  break;
218  default:
219  break;
220  }
221 
222  const float dist =
223  block->dist(key,test,block->linkData(),reco::PFBlock::LINKTEST_ALL);
224  if( dist == -1.0f ) return false; // don't associate non-linked elems
225  std::multimap<double, unsigned> dists_to_val;
226  block->associatedElements(test,block->linkData(),dists_to_val,keytype,
228  for( const auto& valdist : dists_to_val ) {
229  const size_t idx = valdist.second;
230  // check track types for conversion info
231  switch( keytype ) {
233  {
234  const reco::PFBlockElementGsfTrack* elemasgsf =
236  &(block->elements()[idx]));
237  if( !useConvs && elemasgsf->trackType(ConvType) ) return false;
238  if( elemasgsf && valtype == PFBlockElement::ECAL ) {
239  const ClusterElement* elemasclus =
240  docast(const ClusterElement*,&(block->elements()[test]));
241  float cluster_e = elemasclus->clusterRef()->correctedEnergy();
242  float trk_pin = elemasgsf->Pin().P();
243  if( cluster_e / trk_pin > EoPin_cut ) continue;
244  }
245  }
246  break;
248  {
249  const reco::PFBlockElementTrack* elemaskf =
251  &(block->elements()[idx]));
252  if( !useConvs && elemaskf->trackType(ConvType) ) return false;
253  if( elemaskf && valtype == PFBlockElement::ECAL ) {
254  const ClusterElement* elemasclus =
255  reinterpret_cast<const ClusterElement*>(&(block->elements()[test]));
256  float cluster_e = elemasclus->clusterRef()->correctedEnergy();
257  float trk_pin =
258  std::sqrt(elemaskf->trackRef()->innerMomentum().mag2());
259  if( cluster_e / trk_pin > EoPin_cut ) continue;
260  }
261  }
262  break;
263  default:
264  break;
265  }
266  if( valdist.first < dist && idx != key ) {
267  return false; // false if closer element of specified type found
268  }
269  }
270  return true;
271  }
272 
273  struct CompatibleEoPOut : public PFFlaggedElementMatcher {
275  CompatibleEoPOut(const reco::PFBlockElementGsfTrack* c) : comp(c) {}
276  bool operator()(const PFFlaggedElement& e) const {
277  if( PFBlockElement::ECAL != e.first->type() ) return false;
278  const ClusterElement* elemascluster =
279  docast(const ClusterElement*,e.first);
280  const float gsf_eta_diff = std::abs(comp->positionAtECALEntrance().eta()-
281  comp->Pout().eta());
282  const reco::PFClusterRef cRef = elemascluster->clusterRef();
283  return ( gsf_eta_diff <= 0.3 && cRef->energy()/comp->Pout().t() <= 5 );
284  }
285  };
286 
287  template<class TrackElementType>
288  struct IsConversionTrack : PFFlaggedElementMatcher {
289  bool operator()(const PFFlaggedElement& e) {
292  const TrackElementType* elemastrk =
293  docast(const TrackElementType*,e.first);
294  return elemastrk->trackType(ConvType);
295  }
296  };
297 
298  template<PFBlockElement::Type keytype,
299  PFBlockElement::Type valtype,
300  bool useConv=false>
301  struct NotCloserToOther : public PFFlaggedElementMatcher {
302  const reco::PFBlockElement* comp;
303  const reco::PFBlockRef& block;
305  const float EoPin_cut;
306  NotCloserToOther(const reco::PFBlockRef& b,
307  const reco::PFBlock::LinkData& l,
308  const PFFlaggedElement* e,
309  const float EoPcut=1.0e6): comp(e->first),
310  block(b),
311  links(l),
312  EoPin_cut(EoPcut) {
313  }
314  NotCloserToOther(const reco::PFBlockRef& b,
315  const reco::PFBlock::LinkData& l,
316  const reco::PFBlockElement* e,
317  const float EoPcut=1.0e6): comp(e),
318  block(b),
319  links(l),
320  EoPin_cut(EoPcut) {
321  }
322  bool operator () (const PFFlaggedElement& e) {
323  if( !e.second || valtype != e.first->type() ) return false;
324  return elementNotCloserToOther<useConv>(block,
325  keytype,comp->index(),
326  valtype,e.first->index(),
327  EoPin_cut);
328  }
329  };
330 
331  struct LesserByDistance : public PFFlaggedElementSorter {
332  const reco::PFBlockElement* comp;
333  const reco::PFBlockRef& block;
335  LesserByDistance(const reco::PFBlockRef& b,
336  const reco::PFBlock::LinkData& l,
337  const PFFlaggedElement* e): comp(e->first),
338  block(b),
339  links(l) {}
340  LesserByDistance(const reco::PFBlockRef& b,
341  const reco::PFBlock::LinkData& l,
342  const reco::PFBlockElement* e): comp(e),
343  block(b),
344  links(l) {}
345  bool operator () (const PFFlaggedElement& e1,
346  const PFFlaggedElement& e2) {
347  double dist1 = block->dist(comp->index(),
348  e1.first->index(),
349  links,
351  double dist2 = block->dist(comp->index(),
352  e2.first->index(),
353  links,
355  dist1 = ( dist1 == -1.0 ? 1e6 : dist1 );
356  dist2 = ( dist2 == -1.0 ? 1e6 : dist2 );
357  return dist1 < dist2;
358  }
359  };
360 
361  bool isROLinkedByClusterOrTrack(const PFEGammaAlgo::ProtoEGObject& RO1,
362  const PFEGammaAlgo::ProtoEGObject& RO2 ) {
363  // also don't allow ROs where both have clusters
364  // and GSF tracks to merge (10 Dec 2013)
365  if(RO1.primaryGSFs.size() && RO2.primaryGSFs.size()) return false;
366  // don't allow EB/EE to mix (11 Sept 2013)
367  if( RO1.ecalclusters.size() && RO2.ecalclusters.size() ) {
368  if(RO1.ecalclusters.front().first->clusterRef()->layer() !=
369  RO2.ecalclusters.front().first->clusterRef()->layer() ) {
370  return false;
371  }
372  }
373  const reco::PFBlockRef& blk = RO1.parentBlock;
374  bool not_closer;
375  // check links track -> cluster
376  for( const auto& cluster: RO1.ecalclusters ) {
377  for( const auto& primgsf : RO2.primaryGSFs ) {
378  not_closer =
379  elementNotCloserToOther(blk,
380  cluster.first->type(),
381  cluster.first->index(),
382  primgsf.first->type(),
383  primgsf.first->index());
384  if( not_closer ) return true;
385  }
386  for( const auto& primkf : RO2.primaryKFs) {
387  not_closer =
388  elementNotCloserToOther(blk,
389  cluster.first->type(),
390  cluster.first->index(),
391  primkf.first->type(),
392  primkf.first->index());
393  if( not_closer ) return true;
394  }
395  for( const auto& secdkf : RO2.secondaryKFs) {
396  not_closer =
397  elementNotCloserToOther(blk,
398  cluster.first->type(),
399  cluster.first->index(),
400  secdkf.first->type(),
401  secdkf.first->index());
402  if( not_closer ) return true;
403  }
404  // check links brem -> cluster
405  for( const auto& brem : RO2.brems ) {
406  not_closer = elementNotCloserToOther(blk,
407  cluster.first->type(),
408  cluster.first->index(),
409  brem.first->type(),
410  brem.first->index());
411  if( not_closer ) return true;
412  }
413  }
414  // check links primary gsf -> secondary kf
415  for( const auto& primgsf : RO1.primaryGSFs ) {
416  for( const auto& secdkf : RO2.secondaryKFs) {
417  not_closer =
418  elementNotCloserToOther(blk,
419  primgsf.first->type(),
420  primgsf.first->index(),
421  secdkf.first->type(),
422  secdkf.first->index());
423  if( not_closer ) return true;
424  }
425  }
426  // check links primary kf -> secondary kf
427  for( const auto& primkf : RO1.primaryKFs ) {
428  for( const auto& secdkf : RO2.secondaryKFs) {
429  not_closer =
430  elementNotCloserToOther(blk,
431  primkf.first->type(),
432  primkf.first->index(),
433  secdkf.first->type(),
434  secdkf.first->index());
435  if( not_closer ) return true;
436  }
437  }
438  // check links secondary kf -> secondary kf
439  for( const auto& secdkf1 : RO1.secondaryKFs ) {
440  for( const auto& secdkf2 : RO2.secondaryKFs) {
441  not_closer =
442  elementNotCloserToOther<true>(blk,
443  secdkf1.first->type(),
444  secdkf1.first->index(),
445  secdkf2.first->type(),
446  secdkf2.first->index());
447  if( not_closer ) return true;
448  }
449  }
450  return false;
451  }
452 
453  struct TestIfROMergableByLink : public POMatcher {
454  const PFEGammaAlgo::ProtoEGObject& comp;
455  TestIfROMergableByLink(const PFEGammaAlgo::ProtoEGObject& RO) :
456  comp(RO) {}
457  bool operator() (const PFEGammaAlgo::ProtoEGObject& ro) {
458  return ( isROLinkedByClusterOrTrack(comp,ro) ||
459  isROLinkedByClusterOrTrack(ro,comp) );
460  }
461  };
462 
463  std::vector<const ClusterElement*>
464  getSCAssociatedECALsSafe(const reco::SuperClusterRef& scref,
465  std::vector<PFFlaggedElement>& ecals) {
466  std::vector<const ClusterElement*> cluster_list;
467  auto sccl = scref->clustersBegin();
468  auto scend = scref->clustersEnd();
469  auto pfc = ecals.begin();
470  auto pfcend = ecals.end();
471  for( ; sccl != scend; ++sccl ) {
472  std::vector<const ClusterElement*> matched_pfcs;
473  const double eg_energy = (*sccl)->energy();
474 
475  for( pfc = ecals.begin(); pfc != pfcend; ++pfc ) {
476  const ClusterElement *pfcel =
477  docast(const ClusterElement*, pfc->first);
478  const bool matched =
479  ClusterClusterMapping::overlap(**sccl,*(pfcel->clusterRef()));
480  // need to protect against high energy clusters being attached
481  // to low-energy SCs
482  if( matched && pfcel->clusterRef()->energy() < 1.2*scref->energy()) {
483  matched_pfcs.push_back(pfcel);
484  }
485  }
486  std::sort(matched_pfcs.begin(),matched_pfcs.end());
487 
488  double min_residual = 1e6;
489  std::vector<const ClusterElement*> best_comb;
490  for( size_t i = 1; i <= matched_pfcs.size(); ++i ) {
491  //now we find the combination of PF-clusters which
492  //has the smallest energy residual with respect to the
493  //EG-cluster we are looking at now
494  do {
495  double energy = std::accumulate(matched_pfcs.begin(),
496  matched_pfcs.begin()+i,
497  0.0,
498  [](const double a,
499  const ClusterElement* c)
500  { return a + c->clusterRef()->energy(); });
501  const double resid = std::abs(energy - eg_energy);
502  if( resid < min_residual ) {
503  best_comb.clear();
504  best_comb.reserve(i);
505  min_residual = resid;
506  best_comb.insert(best_comb.begin(),
507  matched_pfcs.begin(),
508  matched_pfcs.begin()+i);
509  }
510  }while(boost::next_combination(matched_pfcs.begin(),
511  matched_pfcs.begin()+i,
512  matched_pfcs.end()));
513  }
514  for( const auto& clelem : best_comb ) {
515  reco::PFClusterRef clref = clelem->clusterRef();
516  if( std::find(cluster_list.begin(),cluster_list.end(),clelem) ==
517  cluster_list.end() ) {
518  cluster_list.push_back(clelem);
519  }
520  }
521  }
522  return cluster_list;
523  }
524  bool addPFClusterToROSafe(const ClusterElement* cl,
525  PFEGammaAlgo::ProtoEGObject& RO) {
526  if( !RO.ecalclusters.size() ) {
527  RO.ecalclusters.push_back(std::make_pair(cl,true));
528  return true;
529  } else {
530  const PFLayer::Layer clayer = cl->clusterRef()->layer();
531  const PFLayer::Layer blayer =
532  RO.ecalclusters.back().first->clusterRef()->layer();
533  if( clayer == blayer ) {
534  RO.ecalclusters.push_back(std::make_pair(cl,true));
535  return true;
536  }
537  }
538  return false;
539  }
540 
541  // sets the cluster best associated to the GSF track
542  // leave it null if no GSF track
543  void setROElectronCluster(PFEGammaAlgo::ProtoEGObject& RO) {
544  if( !RO.ecalclusters.size() ) return;
545  RO.lateBrem = -1;
546  RO.firstBrem = -1;
547  RO.nBremsWithClusters = -1;
548  const reco::PFBlockElementBrem *firstBrem = NULL, *lastBrem = NULL;
549  const reco::PFBlockElementCluster *bremCluster = NULL, *gsfCluster = NULL,
550  *kfCluster = NULL, *gsfCluster_noassc = NULL;
551  const reco::PFBlockRef& parent = RO.parentBlock;
552  int nBremClusters = 0;
553  constexpr float maxDist = 1e6;
554  float mDist_gsf(maxDist), mDist_gsf_noassc(maxDist), mDist_kf(maxDist);
555  for( const auto& cluster : RO.ecalclusters ) {
556  for( const auto& gsf : RO.primaryGSFs ) {
557  const bool hasclu = elementNotCloserToOther(parent,
558  gsf.first->type(),
559  gsf.first->index(),
560  cluster.first->type(),
561  cluster.first->index());
562  const float deta =
563  std::abs(cluster.first->clusterRef()->positionREP().eta() -
564  gsf.first->positionAtECALEntrance().eta());
565  const float dphi =
567  cluster.first->clusterRef()->positionREP().phi() -
568  gsf.first->positionAtECALEntrance().phi()));
569  const float dist = std::hypot(deta,dphi);
570  if( hasclu && dist < mDist_gsf ) {
571  gsfCluster = cluster.first;
572  mDist_gsf = dist;
573  } else if ( dist < mDist_gsf_noassc ) {
574  gsfCluster_noassc = cluster.first;
575  mDist_gsf_noassc = dist;
576  }
577  }
578  for( const auto& kf : RO.primaryKFs ) {
579  const bool hasclu = elementNotCloserToOther(parent,
580  kf.first->type(),
581  kf.first->index(),
582  cluster.first->type(),
583  cluster.first->index());
584  const float dist = parent->dist(cluster.first->index(),
585  kf.first->index(),
586  parent->linkData(),
588  if( hasclu && dist < mDist_kf ) {
589  kfCluster = cluster.first;
590  mDist_kf = dist;
591  }
592  }
593  for( const auto& brem : RO.brems ) {
594  const bool hasclu = elementNotCloserToOther(parent,
595  brem.first->type(),
596  brem.first->index(),
597  cluster.first->type(),
598  cluster.first->index());
599  if( hasclu ) {
600  ++nBremClusters;
601  if( !firstBrem ||
602  ( firstBrem->indTrajPoint() - 2 >
603  brem.first->indTrajPoint() - 2) ) {
604  firstBrem = brem.first;
605  }
606  if( !lastBrem ||
607  ( lastBrem->indTrajPoint() - 2 <
608  brem.first->indTrajPoint() - 2) ) {
609  lastBrem = brem.first;
610  bremCluster = cluster.first;
611  }
612  }
613  }
614  }
615  if( !gsfCluster && !kfCluster && !bremCluster ) {
616  gsfCluster = gsfCluster_noassc;
617  }
618  RO.nBremsWithClusters = nBremClusters;
619  RO.lateBrem = 0;
620  if( gsfCluster ) {
621  RO.electronClusters.push_back(gsfCluster);
622  } else if ( kfCluster ) {
623  RO.electronClusters.push_back(kfCluster);
624  }
625  if( bremCluster && !gsfCluster && !kfCluster ) {
626  RO.electronClusters.push_back(bremCluster);
627  }
628  if( firstBrem && RO.ecalclusters.size() > 1 ) {
629  RO.firstBrem = firstBrem->indTrajPoint() - 2;
630  if( bremCluster == gsfCluster ) RO.lateBrem = 1;
631  }
632  }
633 }
634 
637  cfg_(cfg),
638  isvalid_(false),
639  verbosityLevel_(Silent),
640  nlost(0.0), nlayers(0.0),
641  chi2(0.0), STIP(0.0), del_phi(0.0),HoverPt(0.0), EoverPt(0.0), track_pt(0.0),
642  mvaValue(0.0),
643  CrysPhi_(0.0), CrysEta_(0.0), VtxZ_(0.0), ClusPhi_(0.0), ClusEta_(0.0),
644  ClusR9_(0.0), Clus5x5ratio_(0.0), PFCrysEtaCrack_(0.0), logPFClusE_(0.0), e3x3_(0.0),
645  CrysIPhi_(0), CrysIEta_(0),
646  CrysX_(0.0), CrysY_(0.0),
647  EB(0.0),
648  eSeed_(0.0), e1x3_(0.0),e3x1_(0.0), e1x5_(0.0), e2x5Top_(0.0), e2x5Bottom_(0.0), e2x5Left_(0.0), e2x5Right_(0.0),
649  etop_(0.0), ebottom_(0.0), eleft_(0.0), eright_(0.0),
650  e2x5Max_(0.0),
651  PFPhoEta_(0.0), PFPhoPhi_(0.0), PFPhoR9_(0.0), PFPhoR9Corr_(0.0), SCPhiWidth_(0.0), SCEtaWidth_(0.0),
652  PFPhoEt_(0.0), RConv_(0.0), PFPhoEtCorr_(0.0), PFPhoE_(0.0), PFPhoECorr_(0.0), MustE_(0.0), E3x3_(0.0),
653  dEta_(0.0), dPhi_(0.0), LowClusE_(0.0), RMSAll_(0.0), RMSMust_(0.0), nPFClus_(0.0),
654  TotPS1_(0.0), TotPS2_(0.0),
655  nVtx_(0.0),
656  x0inner_(0.0), x0middle_(0.0), x0outer_(0.0),
657  excluded_(0.0), Mustache_EtRatio_(0.0), Mustache_Et_out_(0.0)
658 {
659 
660  // Set the tmva reader for electrons
661  tmvaReaderEle_ = new TMVA::Reader("!Color:Silent");
662  tmvaReaderEle_->AddVariable("lnPt_gsf",&lnPt_gsf);
663  tmvaReaderEle_->AddVariable("Eta_gsf",&Eta_gsf);
664  tmvaReaderEle_->AddVariable("dPtOverPt_gsf",&dPtOverPt_gsf);
665  tmvaReaderEle_->AddVariable("DPtOverPt_gsf",&DPtOverPt_gsf);
666  //tmvaReaderEle_->AddVariable("nhit_gsf",&nhit_gsf);
667  tmvaReaderEle_->AddVariable("chi2_gsf",&chi2_gsf);
668  //tmvaReaderEle_->AddVariable("DPtOverPt_kf",&DPtOverPt_kf);
669  tmvaReaderEle_->AddVariable("nhit_kf",&nhit_kf);
670  tmvaReaderEle_->AddVariable("chi2_kf",&chi2_kf);
671  tmvaReaderEle_->AddVariable("EtotPinMode",&EtotPinMode);
672  tmvaReaderEle_->AddVariable("EGsfPoutMode",&EGsfPoutMode);
673  tmvaReaderEle_->AddVariable("EtotBremPinPoutMode",&EtotBremPinPoutMode);
674  tmvaReaderEle_->AddVariable("DEtaGsfEcalClust",&DEtaGsfEcalClust);
675  tmvaReaderEle_->AddVariable("SigmaEtaEta",&SigmaEtaEta);
676  tmvaReaderEle_->AddVariable("HOverHE",&HOverHE);
677 // tmvaReaderEle_->AddVariable("HOverPin",&HOverPin);
678  tmvaReaderEle_->AddVariable("lateBrem",&lateBrem);
679  tmvaReaderEle_->AddVariable("firstBrem",&firstBrem);
680  tmvaReaderEle_->BookMVA("BDT",cfg_.mvaWeightFileEleID.c_str());
681 
682 
683  //Book MVA
684  tmvaReader_ = new TMVA::Reader("!Color:Silent");
685  tmvaReader_->AddVariable("del_phi",&del_phi);
686  tmvaReader_->AddVariable("nlayers", &nlayers);
687  tmvaReader_->AddVariable("chi2",&chi2);
688  tmvaReader_->AddVariable("EoverPt",&EoverPt);
689  tmvaReader_->AddVariable("HoverPt",&HoverPt);
690  tmvaReader_->AddVariable("track_pt", &track_pt);
691  tmvaReader_->AddVariable("STIP",&STIP);
692  tmvaReader_->AddVariable("nlost", &nlost);
693  tmvaReader_->BookMVA("BDT",cfg_.mvaweightfile.c_str());
694 
695  //Material Map
696  TFile *XO_File = new TFile(cfg_.X0_Map.c_str(),"READ");
697  X0_sum = (TH2D*)XO_File->Get("TrackerSum");
698  X0_inner = (TH2D*)XO_File->Get("Inner");
699  X0_middle = (TH2D*)XO_File->Get("Middle");
700  X0_outer = (TH2D*)XO_File->Get("Outer");
701 
702 }
703 
705  std::vector<bool>& active) {
706 
707  fifthStepKfTrack_.clear();
708  convGsfTrack_.clear();
709 
710  egCandidate_.clear();
711  egExtra_.clear();
712 
713  // define how much is printed out for debugging.
714  // ... will be setable via CFG file parameter
715  verbosityLevel_ = Chatty; // Chatty mode.
716 
717  buildAndRefineEGObjects(blockRef);
718 }
719 
721  const reco::Vertex& primaryvtx,
722  unsigned int track_index) {
723  bool convtkfound=false;
724  const reco::PFBlock& block = *blockref;
726  //use this to store linkdata in the associatedElements function below
727  PFBlock::LinkData linkData = block.linkData();
728  //calculate MVA Variables
729  chi2=elements[track_index].trackRef()->chi2()/elements[track_index].trackRef()->ndof();
730  nlost=elements[track_index].trackRef()->trackerExpectedHitsInner().numberOfLostHits();
731  nlayers=elements[track_index].trackRef()->hitPattern().trackerLayersWithMeasurement();
732  track_pt=elements[track_index].trackRef()->pt();
733  STIP=elements[track_index].trackRefPF()->STIP();
734 
735  float linked_e=0;
736  float linked_h=0;
737  std::multimap<double, unsigned int> ecalAssoTrack;
738  block.associatedElements( track_index,linkData,
739  ecalAssoTrack,
742  std::multimap<double, unsigned int> hcalAssoTrack;
743  block.associatedElements( track_index,linkData,
744  hcalAssoTrack,
747  if(ecalAssoTrack.size() > 0) {
748  for(std::multimap<double, unsigned int>::iterator itecal = ecalAssoTrack.begin();
749  itecal != ecalAssoTrack.end(); ++itecal) {
750  linked_e=linked_e+elements[itecal->second].clusterRef()->energy();
751  }
752  }
753  if(hcalAssoTrack.size() > 0) {
754  for(std::multimap<double, unsigned int>::iterator ithcal = hcalAssoTrack.begin();
755  ithcal != hcalAssoTrack.end(); ++ithcal) {
756  linked_h=linked_h+elements[ithcal->second].clusterRef()->energy();
757  }
758  }
759  EoverPt=linked_e/elements[track_index].trackRef()->pt();
760  HoverPt=linked_h/elements[track_index].trackRef()->pt();
761  GlobalVector rvtx(elements[track_index].trackRef()->innerPosition().X()-primaryvtx.x(),
762  elements[track_index].trackRef()->innerPosition().Y()-primaryvtx.y(),
763  elements[track_index].trackRef()->innerPosition().Z()-primaryvtx.z());
764  double vtx_phi=rvtx.phi();
765  //delta Phi between conversion vertex and track
766  del_phi=fabs(deltaPhi(vtx_phi, elements[track_index].trackRef()->innerMomentum().Phi()));
767  mvaValue = tmvaReader_->EvaluateMVA("BDT");
768  if(mvaValue > cfg_.mvaConvCut) convtkfound=true;
769  return convtkfound;
770 }
771 
773  switch( pfbe.type() ) {
775  {
776  auto& elements = _currentblock->elements();
777  std::multimap<double,unsigned> tks;
778  _currentblock->associatedElements(pfbe.index(),
780  tks,
783  for( const auto& tk : tks ) {
784  if( PFMuonAlgo::isMuon(elements[tk.second]) ) {
785  return true;
786  }
787  }
788  }
789  break;
791  return PFMuonAlgo::isMuon(pfbe);
792  break;
793  default:
794  break;
795  }
796  return false;
797 }
798 
800  LOGVERB("PFEGammaAlgo")
801  << "Resetting PFEGammaAlgo for new block and running!" << std::endl;
802  _splayedblock.clear();
803  _recoveredlinks.clear();
804  _refinableObjects.clear();
805  _finalCandidates.clear();
806  _splayedblock.resize(12); // make sure that we always have the SC entry
807 
809  _currentlinks = block->linkData();
810  LOGDRESSED("PFEGammaAlgo") << *_currentblock << std::endl;
811  LOGVERB("PFEGammaAlgo") << "Splaying block" << std::endl;
812  //unwrap the PF block into a fast access map
813  for( const auto& pfelement : _currentblock->elements() ) {
814  if( isAMuon(pfelement) ) continue; // don't allow muons in our element list
815  const size_t itype = (size_t)pfelement.type();
816  if( itype >= _splayedblock.size() ) _splayedblock.resize(itype+1);
817  _splayedblock[itype].push_back(std::make_pair(&pfelement,true));
818  }
819 
820  // show the result of splaying the tree if it's really *really* needed
821 #ifdef PFLOW_DEBUG
822  std::stringstream splayout;
823  for( size_t itype = 0; itype < _splayedblock.size(); ++itype ) {
824  splayout << "\tType: " << itype << " indices: ";
825  for( const auto& flaggedelement : _splayedblock[itype] ) {
826  splayout << flaggedelement.first->index() << ' ';
827  }
828  if( itype != _splayedblock.size() - 1 ) splayout << std::endl;
829  }
830  LOGVERB("PFEGammaAlgo") << splayout.str();
831 #endif
832 
833  // precleaning of the ECAL clusters with respect to primary KF tracks
834  // we don't allow clusters in super clusters to be locked out this way
836 
838  LOGDRESSED("PFEGammaAlgo")
839  << "Initialized " << _refinableObjects.size() << " proto-EGamma objects"
840  << std::endl;
842 
843  //
844  // now we start the refining steps
845  //
846  //
847 
848  // --- Primary Linking Step ---
849  // since this is particle flow and we try to work from the pixels out
850  // we start by linking the tracks together and finding the ECAL clusters
851  for( auto& RO : _refinableObjects ) {
852  // find the KF tracks associated to GSF primary tracks
854  // do the same for HCAL clusters associated to the GSF
856  // link secondary KF tracks associated to primary KF tracks
858  // pick up clusters that are linked to the GSF primary
860  // link associated KF to ECAL (ECAL part grabs PS clusters too if able)
862  // now finally look for clusters associated to brem tangents
864  }
865 
866  LOGDRESSED("PFEGammaAlgo")
867  << "Dumping after GSF and KF Track (Primary) Linking : " << std::endl;
869 
870  // merge objects after primary linking
871  mergeROsByAnyLink(_refinableObjects);
872 
873  LOGDRESSED("PFEGammaAlgo")
874  << "Dumping after first merging operation : " << std::endl;
876 
877  // --- Secondary Linking Step ---
878  // after this we go through the ECAL clusters on the remaining tracks
879  // and try to link those in...
880  for( auto& RO : _refinableObjects ) {
881  // look for conversion legs
884  // look for tracks that complement conversion legs
886  // look again for ECAL clusters (this time with an e/p cut)
888  }
889 
890  LOGDRESSED("PFEGammaAlgo")
891  << "Dumping after ECAL to Track (Secondary) Linking : " << std::endl;
893 
894  // merge objects after primary linking
895  mergeROsByAnyLink(_refinableObjects);
896 
897  LOGDRESSED("PFEGammaAlgo")
898  << "There are " << _refinableObjects.size()
899  << " after the 2nd merging step." << std::endl;
901 
902  // -- unlinking and proto-object vetos, final sorting
903  for( auto& RO : _refinableObjects ) {
904  // remove secondary KFs (and possibly ECALs) matched to HCAL clusters
906  // remove secondary KFs and ECALs linked to them that have bad E/p_in
907  // and spoil the resolution
909  // put things back in order after partitioning
910  std::sort(RO.ecalclusters.begin(), RO.ecalclusters.end(),
911  [](const PFClusterFlaggedElement& a,
912  const PFClusterFlaggedElement& b)
913  { return ( a.first->clusterRef()->correctedEnergy() >
914  b.first->clusterRef()->correctedEnergy() ) ; });
915  setROElectronCluster(RO);
916  }
917 
918  LOGDRESSED("PFEGammaAlgo")
919  << "There are " << _refinableObjects.size()
920  << " after the unlinking and vetos step." << std::endl;
922 
923  // fill the PF candidates and then build the refined SC
924  fillPFCandidates(_refinableObjects,outcands_,outcandsextra_);
925 
926 }
927 
928 void PFEGammaAlgo::
929 initializeProtoCands(std::list<PFEGammaAlgo::ProtoEGObject>& egobjs) {
930  // step 1: build SC based proto-candidates
931  // in the future there will be an SC Et requirement made here to control
932  // block size
933  for( auto& element : _splayedblock[PFBlockElement::SC] ) {
934  LOGDRESSED("PFEGammaAlgo")
935  << "creating SC-based proto-object" << std::endl
936  << "\tSC at index: " << element.first->index()
937  << " has type: " << element.first->type() << std::endl;
938  element.second = false;
939  ProtoEGObject fromSC;
940  fromSC.nBremsWithClusters = -1;
941  fromSC.firstBrem = -1;
942  fromSC.lateBrem = -1;
943  fromSC.parentBlock = _currentblock;
944  fromSC.parentSC = docast(const PFSCElement*,element.first);
945  // splay the supercluster so we can knock out used elements
946  bool sc_success =
947  unwrapSuperCluster(fromSC.parentSC,fromSC.ecalclusters,fromSC.ecal2ps);
948  if( sc_success ) _refinableObjects.push_back(fromSC);
949  }
950  // step 2: build GSF-seed-based proto-candidates
951  reco::GsfTrackRef gsfref_forextra;
952  reco::TrackExtraRef gsftrk_extra;
953  reco::ElectronSeedRef theseedref;
954  std::list<ProtoEGObject>::iterator objsbegin, objsend;
955  for( auto& element : _splayedblock[PFBlockElement::GSF] ) {
956  LOGDRESSED("PFEGammaAlgo")
957  << "creating GSF-based proto-object" << std::endl
958  << "\tGSF at index: " << element.first->index()
959  << " has type: " << element.first->type() << std::endl;
960  const PFGSFElement* elementAsGSF =
961  docast(const PFGSFElement*,element.first);
963  continue; // for now, do not allow dedicated brems to make proto-objects
964  }
965  element.second = false;
966 
967  ProtoEGObject fromGSF;
968  fromGSF.nBremsWithClusters = -1;
969  fromGSF.firstBrem = -1;
970  fromGSF.lateBrem = 0;
971  gsfref_forextra = elementAsGSF->GsftrackRef();
972  gsftrk_extra = ( gsfref_forextra.isAvailable() ?
973  gsfref_forextra->extra() : reco::TrackExtraRef() );
974  theseedref = ( gsftrk_extra.isAvailable() ?
975  gsftrk_extra->seedRef().castTo<reco::ElectronSeedRef>() :
977  fromGSF.electronSeed = theseedref;
978  // exception if there's no seed
979  if(fromGSF.electronSeed.isNull() || !fromGSF.electronSeed.isAvailable()) {
980  std::stringstream gsf_err;
981  elementAsGSF->Dump(gsf_err,"\t");
982  throw cms::Exception("PFEGammaAlgo::initializeProtoCands()")
983  << "Found a GSF track with no seed! This should not happen!"
984  << std::endl << gsf_err.str() << std::endl;
985  }
986  // flag this GSF element as globally used and push back the track ref
987  // into the protocand
988  element.second = false;
989  fromGSF.parentBlock = _currentblock;
990  fromGSF.primaryGSFs.push_back(std::make_pair(elementAsGSF,true));
991  // add the directly matched brem tangents
992  for( auto& brem : _splayedblock[PFBlockElement::BREM] ) {
993  float dist = _currentblock->dist(elementAsGSF->index(),
994  brem.first->index(),
997  if( dist == 0.001f ) {
998  const PFBremElement* eAsBrem =
999  docast(const PFBremElement*,brem.first);
1000  fromGSF.brems.push_back(std::make_pair(eAsBrem,true));
1001  fromGSF.localMap.push_back( ElementMap::value_type(eAsBrem,elementAsGSF) );
1002  fromGSF.localMap.push_back( ElementMap::value_type(elementAsGSF,eAsBrem) );
1003  brem.second = false;
1004  }
1005  }
1006  // if this track is ECAL seeded reset links or import cluster
1007  // tracker (this is pixel only, right?) driven seeds just get the GSF
1008  // track associated since this only branches for ECAL Driven seeds
1009  if( fromGSF.electronSeed->isEcalDriven() ) {
1010  // step 2a: either merge with existing ProtoEG object with SC or add
1011  // SC directly to this proto EG object if not present
1012  LOGDRESSED("PFEGammaAlgo")
1013  << "GSF-based proto-object is ECAL driven, merging SC-cand"
1014  << std::endl;
1015  LOGVERB("PFEGammaAlgo")
1016  << "ECAL Seed Ptr: " << fromGSF.electronSeed.get()
1017  << " isAvailable: " << fromGSF.electronSeed.isAvailable()
1018  << " isNonnull: " << fromGSF.electronSeed.isNonnull()
1019  << std::endl;
1020  SeedMatchesToProtoObject sctoseedmatch(fromGSF.electronSeed);
1021  objsbegin = _refinableObjects.begin();
1022  objsend = _refinableObjects.end();
1023  // this auto is a std::list<ProtoEGObject>::iterator
1024  auto clusmatch = std::find_if(objsbegin,objsend,sctoseedmatch);
1025  if( clusmatch != objsend ) {
1026  fromGSF.parentSC = clusmatch->parentSC;
1027  fromGSF.ecalclusters = std::move(clusmatch->ecalclusters);
1028  fromGSF.ecal2ps = std::move(clusmatch->ecal2ps);
1029  _refinableObjects.erase(clusmatch);
1030  } else if (fromGSF.electronSeed.isAvailable() &&
1031  fromGSF.electronSeed.isNonnull()) {
1032  // link tests in the gap region can current split a gap electron
1033  // HEY THIS IS A WORK AROUND FOR A KNOWN BUG IN PFBLOCKALGO
1034  // MAYBE WE SHOULD FIX IT??????????????????????????????????
1035  LOGERR("PFEGammaAlgo")
1036  << "Encountered the known GSF-SC splitting bug "
1037  << " in PFBlockAlgo! We should really fix this!" << std::endl;
1038  } else { // SC was not in a earlier proto-object
1039  std::stringstream gsf_err;
1040  elementAsGSF->Dump(gsf_err,"\t");
1041  throw cms::Exception("PFEGammaAlgo::initializeProtoCands()")
1042  << "Expected SuperCluster from ECAL driven GSF seed "
1043  << "was not found in the block!" << std::endl
1044  << gsf_err.str() << std::endl;
1045  } // supercluster in block
1046  } // is ECAL driven seed?
1047  _refinableObjects.push_back(fromGSF);
1048  } // end loop on GSF elements of block
1049  }
1050 
1051  bool PFEGammaAlgo::
1053  std::vector<PFClusterFlaggedElement>& ecalclusters,
1054  ClusterMap& ecal2ps) {
1055  ecalclusters.clear();
1056  ecal2ps.clear();
1057  LOGVERB("PFEGammaAlgo")
1058  << "Pointer to SC element: 0x"
1059  << std::hex << thesc << std::dec << std::endl
1060  << "cleared ecalclusters and ecal2ps!" << std::endl;
1061  auto ecalbegin = _splayedblock[reco::PFBlockElement::ECAL].begin();
1062  auto ecalend = _splayedblock[reco::PFBlockElement::ECAL].end();
1063  if( ecalbegin == ecalend ) {
1064  LOGERR("PFEGammaAlgo::unwrapSuperCluster()")
1065  << "There are no ECAL elements in a block with imported SC!"
1066  << " This is a bug we should fix this!"
1067  << std::endl;
1068  return false;
1069  }
1070  reco::SuperClusterRef scref = thesc->superClusterRef();
1071  const bool is_pf_sc = thesc->fromPFSuperCluster();
1072  if( !(scref.isAvailable() && scref.isNonnull()) ) {
1073  throw cms::Exception("PFEGammaAlgo::unwrapSuperCluster()")
1074  << "SuperCluster pointed to by block element is null!"
1075  << std::endl;
1076  }
1077  LOGDRESSED("PFEGammaAlgo")
1078  << "Got a valid super cluster ref! 0x"
1079  << std::hex << scref.get() << std::dec << std::endl;
1080  const size_t nscclusters = scref->clustersSize();
1081  const size_t nscpsclusters = scref->preshowerClustersSize();
1082  size_t npfpsclusters = 0;
1083  size_t npfclusters = 0;
1084  LOGDRESSED("PFEGammaAlgo")
1085  << "Precalculated cluster multiplicities: "
1086  << nscclusters << ' ' << nscpsclusters << std::endl;
1087  NotCloserToOther<reco::PFBlockElement::SC,reco::PFBlockElement::ECAL>
1088  ecalClustersInSC(_currentblock,_currentlinks,thesc);
1089  auto firstnotinsc = std::partition(ecalbegin,ecalend,ecalClustersInSC);
1090  //reset the begin and end iterators
1091  ecalbegin = _splayedblock[reco::PFBlockElement::ECAL].begin();
1092  ecalend = _splayedblock[reco::PFBlockElement::ECAL].end();
1093 
1094  //get list of associated clusters by det id and energy matching
1095  //(only needed when using non-pf supercluster)
1096  std::vector<const ClusterElement*> safePFClusters = is_pf_sc ? std::vector<const ClusterElement*>() : getSCAssociatedECALsSafe(scref,_splayedblock[reco::PFBlockElement::ECAL]);
1097 
1098  if( firstnotinsc == ecalbegin ) {
1099  LOGERR("PFEGammaAlgo::unwrapSuperCluster()")
1100  << "No associated block elements to SuperCluster!"
1101  << " This is a bug we should fix!"
1102  << std::endl;
1103  return false;
1104  }
1105  npfclusters = std::distance(ecalbegin,firstnotinsc);
1106  // ensure we have found the correct number of PF ecal clusters in the case
1107  // that this is a PF supercluster, otherwise all bets are off
1108  if( is_pf_sc && nscclusters != npfclusters ) {
1109  std::stringstream sc_err;
1110  thesc->Dump(sc_err,"\t");
1111  throw cms::Exception("PFEGammaAlgo::unwrapSuperCluster()")
1112  << "The number of found ecal elements ("
1113  << nscclusters << ") in block is not the same as"
1114  << " the number of ecal PF clusters reported by the PFSuperCluster"
1115  << " itself (" << npfclusters
1116  << ")! This should not happen!" << std::endl
1117  << sc_err.str() << std::endl;
1118  }
1119  for( auto ecalitr = ecalbegin; ecalitr != firstnotinsc; ++ecalitr ) {
1120  const PFClusterElement* elemascluster =
1121  docast(const PFClusterElement*,ecalitr->first);
1122 
1123  // reject clusters that really shouldn't be associated to the SC
1124  // (only needed when using non-pf-supercluster)
1125  if(!is_pf_sc && std::find(safePFClusters.begin(),safePFClusters.end(),elemascluster) ==
1126  safePFClusters.end() ) continue;
1127 
1128  //add cluster
1129  ecalclusters.push_back(std::make_pair(elemascluster,true));
1130  //mark cluster as used
1131  ecalitr->second = false;
1132 
1133  // process the ES elements
1134  // auto is a pair<Iterator,bool> here, bool is false when placing fails
1135  auto emplaceresult = ecal2ps.emplace(elemascluster,
1136  ClusterMap::mapped_type());
1137  if( !emplaceresult.second ) {
1138  std::stringstream clus_err;
1139  elemascluster->Dump(clus_err,"\t");
1140  throw cms::Exception("PFEGammaAlgo::unwrapSuperCluster()")
1141  << "List of pointers to ECAL block elements contains non-unique items!"
1142  << " This is very bad!" << std::endl
1143  << "cluster ptr = 0x" << std::hex << elemascluster << std::dec
1144  << std::endl << clus_err.str() << std::endl;
1145  }
1146  ClusterMap::mapped_type& eslist = emplaceresult.first->second;
1147  npfpsclusters += attachPSClusters(elemascluster,eslist);
1148  } // loop over ecal elements
1149 
1150  /*
1151  if( is_pf_sc && nscpsclusters != npfpsclusters) {
1152  std::stringstream sc_err;
1153  thesc->Dump(sc_err,"\t");
1154  throw cms::Exception("PFEGammaAlgo::unwrapSuperCluster()")
1155  << "The number of found PF preshower elements ("
1156  << npfpsclusters << ") in block is not the same as"
1157  << " the number of preshower clusters reported by the PFSuperCluster"
1158  << " itself (" << nscpsclusters << ")! This should not happen!"
1159  << std::endl
1160  << sc_err.str() << std::endl;
1161  }
1162  */
1163 
1164  LOGDRESSED("PFEGammaAlgo")
1165  << " Unwrapped SC has " << npfclusters << " ECAL sub-clusters"
1166  << " and " << npfpsclusters << " PreShower layers 1 & 2 clusters!"
1167  << std::endl;
1168  return true;
1169  }
1170 
1171 
1172 
1173  int PFEGammaAlgo::attachPSClusters(const ClusterElement* ecalclus,
1174  ClusterMap::mapped_type& eslist) {
1175  if( ecalclus->clusterRef()->layer() == PFLayer::ECAL_BARREL ) return 0;
1176  edm::Ptr<reco::PFCluster> clusptr = refToPtr(ecalclus->clusterRef());
1177  EEtoPSElement ecalkey = std::make_pair(clusptr.key(),clusptr);
1178  auto assc_ps = std::equal_range(eetops_->cbegin(),
1179  eetops_->cend(),
1180  ecalkey,
1181  comparePSMapByKey);
1182  for( const auto& ps1 : _splayedblock[reco::PFBlockElement::PS1] ) {
1183  edm::Ptr<reco::PFCluster> temp = refToPtr(ps1.first->clusterRef());
1184  for( auto pscl = assc_ps.first; pscl != assc_ps.second; ++pscl ) {
1185  if( pscl->second == temp ) {
1186  const ClusterElement* pstemp =
1187  docast(const ClusterElement*,ps1.first);
1188  eslist.push_back( PFClusterFlaggedElement(pstemp,true) );
1189  }
1190  }
1191  }
1192  for( const auto& ps2 : _splayedblock[reco::PFBlockElement::PS2] ) {
1193  edm::Ptr<reco::PFCluster> temp = refToPtr(ps2.first->clusterRef());
1194  for( auto pscl = assc_ps.first; pscl != assc_ps.second; ++pscl ) {
1195  if( pscl->second == temp ) {
1196  const ClusterElement* pstemp =
1197  docast(const ClusterElement*,ps2.first);
1198  eslist.push_back( PFClusterFlaggedElement(pstemp,true) );
1199  }
1200  }
1201  }
1202  return eslist.size();
1203  }
1204 
1206  #ifdef PFLOW_DEBUG
1207  edm::LogVerbatim("PFEGammaAlgo")
1208  //<< "Dumping current block: " << std::endl << *_currentblock << std::endl
1209  << "Dumping " << _refinableObjects.size()
1210  << " refinable objects for this block: " << std::endl;
1211  for( const auto& ro : _refinableObjects ) {
1212  std::stringstream info;
1213  info << "Refinable Object:" << std::endl;
1214  if( ro.parentSC ) {
1215  info << "\tSuperCluster element attached to object:" << std::endl
1216  << '\t';
1217  ro.parentSC->Dump(info,"\t");
1218  info << std::endl;
1219  }
1220  if( ro.electronSeed.isNonnull() ) {
1221  info << "\tGSF element attached to object:" << std::endl;
1222  ro.primaryGSFs.front().first->Dump(info,"\t");
1223  info << std::endl;
1224  info << "firstBrem : " << ro.firstBrem
1225  << " lateBrem : " << ro.lateBrem
1226  << " nBrems with cluster : " << ro.nBremsWithClusters
1227  << std::endl;;
1228  if( ro.electronClusters.size() && ro.electronClusters[0] ) {
1229  info << "electron cluster : ";
1230  ro.electronClusters[0]->Dump(info,"\t");
1231  info << std::endl;
1232  } else {
1233  info << " no electron cluster." << std::endl;
1234  }
1235  }
1236  if( ro.primaryKFs.size() ) {
1237  info << "\tPrimary KF tracks attached to object: " << std::endl;
1238  for( const auto& kf : ro.primaryKFs ) {
1239  kf.first->Dump(info,"\t");
1240  info << std::endl;
1241  }
1242  }
1243  if( ro.secondaryKFs.size() ) {
1244  info << "\tSecondary KF tracks attached to object: " << std::endl;
1245  for( const auto& kf : ro.secondaryKFs ) {
1246  kf.first->Dump(info,"\t");
1247  info << std::endl;
1248  }
1249  }
1250  if( ro.brems.size() ) {
1251  info << "\tBrem tangents attached to object: " << std::endl;
1252  for( const auto& brem : ro.brems ) {
1253  brem.first->Dump(info,"\t");
1254  info << std::endl;
1255  }
1256  }
1257  if( ro.ecalclusters.size() ) {
1258  info << "\tECAL clusters attached to object: " << std::endl;
1259  for( const auto& clus : ro.ecalclusters ) {
1260  clus.first->Dump(info,"\t");
1261  info << std::endl;
1262  if( ro.ecal2ps.find(clus.first) != ro.ecal2ps.end() ) {
1263  for( const auto& psclus : ro.ecal2ps.at(clus.first) ) {
1264  info << "\t\t Attached PS Cluster: ";
1265  psclus.first->Dump(info,"");
1266  info << std::endl;
1267  }
1268  }
1269  }
1270  }
1271  edm::LogVerbatim("PFEGammaAlgo") << info.str();
1272  }
1273  #endif
1274  }
1275 
1276  // look through our KF tracks in this block and match
1277  void PFEGammaAlgo::
1281  std::multimap<double, unsigned> matchedGSFs, matchedECALs;
1282  for( auto& kftrack : _splayedblock[reco::PFBlockElement::TRACK] ) {
1283  matchedGSFs.clear();
1284  _currentblock->associatedElements(kftrack.first->index(), _currentlinks,
1285  matchedGSFs,
1288  if( !matchedGSFs.size() ) { // only run this is we aren't associated to GSF
1289  LesserByDistance closestTrackToECAL(_currentblock,_currentlinks,
1290  &kftrack);
1291  auto ecalbegin = _splayedblock[reco::PFBlockElement::ECAL].begin();
1292  auto ecalend = _splayedblock[reco::PFBlockElement::ECAL].end();
1293  std::partial_sort(ecalbegin,ecalbegin+1,ecalend,closestTrackToECAL);
1294  PFFlaggedElement& closestECAL =
1296  const float dist = _currentblock->dist(kftrack.first->index(),
1297  closestECAL.first->index(),
1298  _currentlinks,
1300  bool inSC = false;
1301  for( auto& sc : _splayedblock[reco::PFBlockElement::SC] ) {
1302  float dist_sc = _currentblock->dist(sc.first->index(),
1303  closestECAL.first->index(),
1304  _currentlinks,
1306  if( dist_sc != -1.0f) { inSC = true; break; }
1307  }
1308 
1309  if( dist != -1.0f && closestECAL.second ) {
1310  bool gsflinked = false;
1311  // check that this cluster is not associated to a GSF track
1312  for(const auto& gsfflag : _splayedblock[reco::PFBlockElement::GSF]) {
1313  const reco::PFBlockElementGsfTrack* elemasgsf =
1314  docast(const reco::PFBlockElementGsfTrack*,gsfflag.first);
1316  continue; // keep clusters that have a found conversion GSF near
1317  }
1318  matchedECALs.clear();
1319  _currentblock->associatedElements(elemasgsf->index(), _currentlinks,
1320  matchedECALs,
1323  if( matchedECALs.size() ) {
1324  if( matchedECALs.begin()->second == closestECAL.first->index() ) {
1325  gsflinked = true;
1326  break;
1327  }
1328  }
1329  } // loop over primary GSF tracks
1330  if( !gsflinked && !inSC) {
1331  // determine if we should remove the matched cluster
1332  const reco::PFBlockElementTrack * kfEle =
1333  docast(const reco::PFBlockElementTrack*,kftrack.first);
1334  const reco::TrackRef trackref = kfEle->trackRef();
1335  const unsigned Algo = trackref->algo();
1336  const int nexhits =
1337  trackref->trackerExpectedHitsInner().numberOfLostHits();
1338  bool fromprimaryvertex = false;
1339  for( auto vtxtks = cfg_.primaryVtx->tracks_begin();
1340  vtxtks != cfg_.primaryVtx->tracks_end(); ++ vtxtks ) {
1341  if( trackref == vtxtks->castTo<reco::TrackRef>() ) {
1342  fromprimaryvertex = true;
1343  break;
1344  }
1345  }// loop over tracks in primary vertex
1346  // if associated to good non-GSF matched track remove this cluster
1347  if( Algo < 9 && nexhits == 0 && fromprimaryvertex ) {
1348  closestECAL.second = false;
1349  } else { // otherwise associate the cluster and KF track
1350  _recoveredlinks.push_back( ElementMap::value_type(closestECAL.first,kftrack.first) );
1351  _recoveredlinks.push_back( ElementMap::value_type(kftrack.first,closestECAL.first) );
1352  }
1353  }
1354  } // found a good closest ECAL match
1355  } // no GSF track matched to KF
1356  } // loop over KF elements
1357  }
1358 
1359  void PFEGammaAlgo::
1360  mergeROsByAnyLink(std::list<PFEGammaAlgo::ProtoEGObject>& ROs) {
1361  if( ROs.size() < 2 ) return; // nothing to do with one or zero ROs
1362  bool check_for_merge = true;
1363  while( check_for_merge ) {
1364  ProtoEGObject& thefront = ROs.front();
1365  TestIfROMergableByLink mergeTest(thefront);
1366  auto mergestart = ROs.begin(); ++mergestart;
1367  auto nomerge = std::partition(mergestart,ROs.end(),mergeTest);
1368  if( nomerge != mergestart ) {
1369  LOGDRESSED("PFEGammaAlgo::mergeROsByAnyLink()")
1370  << "Found objects to merge by links to the front!" << std::endl;
1371  for( auto roToMerge = mergestart; roToMerge != nomerge; ++roToMerge) {
1372  thefront.ecalclusters.insert(thefront.ecalclusters.end(),
1373  roToMerge->ecalclusters.begin(),
1374  roToMerge->ecalclusters.end());
1375  thefront.ecal2ps.insert(roToMerge->ecal2ps.begin(),
1376  roToMerge->ecal2ps.end());
1377  thefront.secondaryKFs.insert(thefront.secondaryKFs.end(),
1378  roToMerge->secondaryKFs.begin(),
1379  roToMerge->secondaryKFs.end());
1380 
1381  thefront.localMap.insert(thefront.localMap.end(),
1382  roToMerge->localMap.begin(),
1383  roToMerge->localMap.end());
1384  // TO FIX -> use best (E_gsf - E_clustersum)/E_GSF
1385  if( !thefront.parentSC && roToMerge->parentSC ) {
1386  thefront.parentSC = roToMerge->parentSC;
1387  }
1388  if( thefront.electronSeed.isNull() &&
1389  roToMerge->electronSeed.isNonnull() ) {
1390  thefront.electronSeed = roToMerge->electronSeed;
1391  thefront.primaryGSFs.insert(thefront.primaryGSFs.end(),
1392  roToMerge->primaryGSFs.begin(),
1393  roToMerge->primaryGSFs.end());
1394  thefront.primaryKFs.insert(thefront.primaryKFs.end(),
1395  roToMerge->primaryKFs.begin(),
1396  roToMerge->primaryKFs.end());
1397  thefront.brems.insert(thefront.brems.end(),
1398  roToMerge->brems.begin(),
1399  roToMerge->brems.end());
1400  thefront.electronClusters = roToMerge->electronClusters;
1401  thefront.nBremsWithClusters = roToMerge->nBremsWithClusters;
1402  thefront.firstBrem = roToMerge->firstBrem;
1403  thefront.lateBrem = roToMerge->lateBrem;
1404  } else if ( thefront.electronSeed.isNonnull() &&
1405  roToMerge->electronSeed.isNonnull()) {
1406  LOGWARN("PFEGammaAlgo::mergeROsByAnyLink")
1407  << "Need to implement proper merging of two gsf candidates!"
1408  << std::endl;
1409  }
1410  }
1411  ROs.erase(mergestart,nomerge);
1412  // put the merged element in the back of the cleaned list
1413  ROs.push_back(ROs.front());
1414  ROs.pop_front();
1415  } else {
1416  check_for_merge = false;
1417  }
1418  }
1419  LOGDRESSED("PFEGammaAlgo::mergeROsByAnyLink()")
1420  << "After merging by links there are: " << ROs.size()
1421  << " refinable EGamma objects!" << std::endl;
1422  }
1423 
1424 // pull in KF tracks associated to the RO but not closer to another
1425 // NB: in initializeProtoCands() we forced the GSF tracks not to be
1426 // from a conversion, but we will leave a protection here just in
1427 // case things change in the future
1428 void PFEGammaAlgo::
1433  auto KFbegin = _splayedblock[reco::PFBlockElement::TRACK].begin();
1434  auto KFend = _splayedblock[reco::PFBlockElement::TRACK].end();
1435  for( auto& gsfflagged : RO.primaryGSFs ) {
1436  const PFGSFElement* seedtk = gsfflagged.first;
1437  // don't process SC-only ROs or secondary seeded ROs
1438  if( RO.electronSeed.isNull() || seedtk->trackType(convType) ) continue;
1439  NotCloserToOther<reco::PFBlockElement::GSF,reco::PFBlockElement::TRACK>
1440  gsfTrackToKFs(_currentblock,_currentlinks,seedtk);
1441  // get KF tracks not closer to another and not already used
1442  auto notlinked = std::partition(KFbegin,KFend,gsfTrackToKFs);
1443  // attach tracks and set as used
1444  for( auto kft = KFbegin; kft != notlinked; ++kft ) {
1445  const PFKFElement* elemaskf =
1446  docast(const PFKFElement*,kft->first);
1447  // don't care about things that aren't primaries or directly
1448  // associated secondary tracks
1449  if( isPrimaryTrack(*elemaskf,*seedtk) &&
1450  !elemaskf->trackType(convType) ) {
1451  kft->second = false;
1452  RO.primaryKFs.push_back(std::make_pair(elemaskf,true));
1453  RO.localMap.push_back( ElementMap::value_type(seedtk,elemaskf) );
1454  RO.localMap.push_back( ElementMap::value_type(elemaskf,seedtk) );
1455  } else if ( elemaskf->trackType(convType) ) {
1456  kft->second = false;
1457  RO.secondaryKFs.push_back(std::make_pair(elemaskf,true));
1458  RO.localMap.push_back( ElementMap::value_type(seedtk,elemaskf) );
1459  RO.localMap.push_back( ElementMap::value_type(elemaskf,seedtk) );
1460  }
1461  }// loop on closest KFs not closer to other GSFs
1462  } // loop on GSF primaries on RO
1463 }
1464 
1465 void PFEGammaAlgo::
1470  auto KFbegin = _splayedblock[reco::PFBlockElement::TRACK].begin();
1471  auto KFend = _splayedblock[reco::PFBlockElement::TRACK].end();
1472  for( auto& kfflagged : RO.primaryKFs ) {
1473  const PFKFElement* primkf = kfflagged.first;
1474  // don't process SC-only ROs or secondary seeded ROs
1475  if( primkf->trackType(convType) ) {
1476  throw cms::Exception("PFEGammaAlgo::linkRefinableObjectPrimaryKFsToSecondaryKFs()")
1477  << "A KF track from conversion has been assigned as a primary!!"
1478  << std::endl;
1479  }
1480  NotCloserToOther<reco::PFBlockElement::TRACK,reco::PFBlockElement::TRACK,true>
1481  kfTrackToKFs(_currentblock,_currentlinks,primkf);
1482  // get KF tracks not closer to another and not already used
1483  auto notlinked = std::partition(KFbegin,KFend,kfTrackToKFs);
1484  // attach tracks and set as used
1485  for( auto kft = KFbegin; kft != notlinked; ++kft ) {
1486  const PFKFElement* elemaskf =
1487  docast(const PFKFElement*,kft->first);
1488  // don't care about things that aren't primaries or directly
1489  // associated secondary tracks
1490  if( elemaskf->trackType(convType) ) {
1491  kft->second = false;
1492  RO.secondaryKFs.push_back(std::make_pair(elemaskf,true));
1493  RO.localMap.push_back( ElementMap::value_type(primkf,elemaskf) );
1494  RO.localMap.push_back( ElementMap::value_type(elemaskf,primkf) );
1495  }
1496  }// loop on closest KFs not closer to other KFs
1497  } // loop on KF primaries on RO
1498 }
1499 
1500 // try to associate the tracks to cluster elements which are not used
1501 void PFEGammaAlgo::
1504  RO.electronClusters.push_back(NULL);
1505  return;
1506  }
1507  auto ECALbegin = _splayedblock[reco::PFBlockElement::ECAL].begin();
1508  auto ECALend = _splayedblock[reco::PFBlockElement::ECAL].end();
1509  for( auto& primgsf : RO.primaryGSFs ) {
1510  NotCloserToOther<reco::PFBlockElement::GSF,reco::PFBlockElement::ECAL>
1511  gsfTracksToECALs(_currentblock,_currentlinks,primgsf.first);
1512  CompatibleEoPOut eoverp_test(primgsf.first);
1513  // get set of matching ecals not already in SC
1514  auto notmatched_blk = std::partition(ECALbegin,ECALend,gsfTracksToECALs);
1515  notmatched_blk = std::partition(ECALbegin,notmatched_blk,eoverp_test);
1516  // get set of matching ecals already in the RO
1517  auto notmatched_sc = std::partition(RO.ecalclusters.begin(),
1518  RO.ecalclusters.end(),
1519  gsfTracksToECALs);
1520  notmatched_sc = std::partition(RO.ecalclusters.begin(),
1521  notmatched_sc,
1522  eoverp_test);
1523  // look inside the SC for the ECAL cluster
1524  for( auto ecal = RO.ecalclusters.begin(); ecal != notmatched_sc; ++ecal ) {
1525  const PFClusterElement* elemascluster =
1526  docast(const PFClusterElement*,ecal->first);
1527  PFClusterFlaggedElement temp(elemascluster,true);
1528  LOGDRESSED("PFEGammaAlgo::linkGSFTracktoECAL()")
1529  << "Found a cluster already in RO by GSF extrapolation"
1530  << " at ECAL surface!" << std::endl
1531  << *elemascluster << std::endl;
1532 
1533  RO.localMap.push_back(ElementMap::value_type(primgsf.first,temp.first));
1534  RO.localMap.push_back(ElementMap::value_type(temp.first,primgsf.first));
1535  }
1536  // look outside the SC for the ecal cluster
1537  for( auto ecal = ECALbegin; ecal != notmatched_blk; ++ecal ) {
1538  const PFClusterElement* elemascluster =
1539  docast(const PFClusterElement*,ecal->first);
1540  LOGDRESSED("PFEGammaAlgo::linkGSFTracktoECAL()")
1541  << "Found a cluster not already in RO by GSF extrapolation"
1542  << " at ECAL surface!" << std::endl
1543  << *elemascluster << std::endl;
1544  if( addPFClusterToROSafe(elemascluster,RO) ) {
1545  attachPSClusters(elemascluster,RO.ecal2ps[elemascluster]);
1546  RO.localMap.push_back(ElementMap::value_type(primgsf.first,elemascluster));
1547  RO.localMap.push_back(ElementMap::value_type(elemascluster,primgsf.first));
1548  ecal->second = false;
1549  }
1550  }
1551  }
1552 }
1553 
1554 // try to associate the tracks to cluster elements which are not used
1555 void PFEGammaAlgo::
1557  if( !_splayedblock[reco::PFBlockElement::HCAL].size() ) return;
1558  auto HCALbegin = _splayedblock[reco::PFBlockElement::HCAL].begin();
1559  auto HCALend = _splayedblock[reco::PFBlockElement::HCAL].end();
1560  for( auto& primgsf : RO.primaryGSFs ) {
1561  NotCloserToOther<reco::PFBlockElement::GSF,reco::PFBlockElement::HCAL>
1562  gsfTracksToHCALs(_currentblock,_currentlinks,primgsf.first);
1563  CompatibleEoPOut eoverp_test(primgsf.first);
1564  auto notmatched = std::partition(HCALbegin,HCALend,gsfTracksToHCALs);
1565  for( auto hcal = HCALbegin; hcal != notmatched; ++hcal ) {
1566  const PFClusterElement* elemascluster =
1567  docast(const PFClusterElement*,hcal->first);
1568  PFClusterFlaggedElement temp(elemascluster,true);
1569  LOGDRESSED("PFEGammaAlgo::linkGSFTracktoECAL()")
1570  << "Found an HCAL cluster associated to GSF extrapolation"
1571  << std::endl;
1572  RO.hcalClusters.push_back(temp);
1573  RO.localMap.push_back( ElementMap::value_type(primgsf.first,temp.first) );
1574  RO.localMap.push_back( ElementMap::value_type(temp.first,primgsf.first) );
1575  hcal->second = false;
1576  }
1577  }
1578 }
1579 
1580 // try to associate the tracks to cluster elements which are not used
1581 void PFEGammaAlgo::
1583  if( !_splayedblock[reco::PFBlockElement::ECAL].size() ) return;
1584  for( auto& primkf : RO.primaryKFs ) linkKFTrackToECAL(primkf,RO);
1585  for( auto& secdkf : RO.secondaryKFs ) linkKFTrackToECAL(secdkf,RO);
1586 }
1587 
1588 void
1589 PFEGammaAlgo::linkKFTrackToECAL(const KFFlaggedElement& kfflagged,
1590  ProtoEGObject& RO) {
1591  std::vector<PFClusterFlaggedElement>& currentECAL = RO.ecalclusters;
1592  auto ECALbegin = _splayedblock[reco::PFBlockElement::ECAL].begin();
1593  auto ECALend = _splayedblock[reco::PFBlockElement::ECAL].end();
1594  NotCloserToOther<reco::PFBlockElement::TRACK,reco::PFBlockElement::ECAL>
1595  kfTrackToECALs(_currentblock,_currentlinks,kfflagged.first);
1596  NotCloserToOther<reco::PFBlockElement::GSF,reco::PFBlockElement::ECAL>
1597  kfTrackGSFToECALs(_currentblock,_currentlinks,kfflagged.first);
1598  //get the ECAL elements not used and not closer to another KF
1599  auto notmatched_sc = std::partition(currentECAL.begin(),
1600  currentECAL.end(),
1601  kfTrackToECALs);
1602  //get subset ECAL elements not used or closer to another GSF of any type
1603  notmatched_sc = std::partition(currentECAL.begin(),
1604  notmatched_sc,
1605  kfTrackGSFToECALs);
1606  for( auto ecalitr = currentECAL.begin(); ecalitr != notmatched_sc;
1607  ++ecalitr ) {
1608  const PFClusterElement* elemascluster =
1609  docast(const PFClusterElement*,ecalitr->first);
1610  PFClusterFlaggedElement flaggedclus(elemascluster,true);
1611 
1612  LOGDRESSED("PFEGammaAlgo::linkKFTracktoECAL()")
1613  << "Found a cluster already in RO by KF extrapolation"
1614  << " at ECAL surface!" << std::endl
1615  << *elemascluster << std::endl;
1616  RO.localMap.push_back(ElementMap::value_type(elemascluster,
1617  kfflagged.first));
1618  RO.localMap.push_back(ElementMap::value_type(kfflagged.first,
1619  elemascluster));
1620  }
1621  //get the ECAL elements not used and not closer to another KF
1622  auto notmatched_blk = std::partition(ECALbegin,ECALend,kfTrackToECALs);
1623  //get subset ECAL elements not used or closer to another GSF of any type
1624  notmatched_blk = std::partition(ECALbegin,notmatched_blk,kfTrackGSFToECALs);
1625  for( auto ecalitr = ECALbegin; ecalitr != notmatched_blk; ++ecalitr ) {
1626  const PFClusterElement* elemascluster =
1627  docast(const PFClusterElement*,ecalitr->first);
1628  if( addPFClusterToROSafe(elemascluster,RO) ) {
1629  attachPSClusters(elemascluster,RO.ecal2ps[elemascluster]);
1630  ecalitr->second = false;
1631 
1632  LOGDRESSED("PFEGammaAlgo::linkKFTracktoECAL()")
1633  << "Found a cluster not in RO by KF extrapolation"
1634  << " at ECAL surface!" << std::endl
1635  << *elemascluster << std::endl;
1636  RO.localMap.push_back(ElementMap::value_type(elemascluster,
1637  kfflagged.first));
1638  RO.localMap.push_back( ElementMap::value_type(kfflagged.first,
1639  elemascluster));
1640  }
1641  }
1642 }
1643 
1644 void PFEGammaAlgo::
1646  if( !RO.brems.size() ) return;
1647  int FirstBrem = -1;
1648  int TrajPos = -1;
1649  int lastBremTrajPos = -1;
1650  for( auto& bremflagged : RO.brems ) {
1651  bool has_clusters = false;
1652  TrajPos = (bremflagged.first->indTrajPoint())-2;
1653  auto ECALbegin = _splayedblock[reco::PFBlockElement::ECAL].begin();
1654  auto ECALend = _splayedblock[reco::PFBlockElement::ECAL].end();
1655  NotCloserToOther<reco::PFBlockElement::BREM,reco::PFBlockElement::ECAL>
1656  BremToECALs(_currentblock,_currentlinks,bremflagged.first);
1657  // check for late brem using clusters already in the SC
1658  auto RSCBegin = RO.ecalclusters.begin();
1659  auto RSCEnd = RO.ecalclusters.end();
1660  auto notmatched_rsc = std::partition(RSCBegin,RSCEnd,BremToECALs);
1661  for( auto ecal = RSCBegin; ecal != notmatched_rsc; ++ecal ) {
1662  float deta =
1663  std::abs( ecal->first->clusterRef()->positionREP().eta() -
1664  bremflagged.first->positionAtECALEntrance().eta() );
1665  if( deta < 0.015 ) {
1666  has_clusters = true;
1667  if( lastBremTrajPos == -1 || lastBremTrajPos < TrajPos ) {
1668  lastBremTrajPos = TrajPos;
1669  }
1670  if( FirstBrem == -1 || TrajPos < FirstBrem ) { // set brem information
1671  FirstBrem = TrajPos;
1672  RO.firstBrem = TrajPos;
1673  }
1674  LOGDRESSED("PFEGammaAlgo::linkBremToECAL()")
1675  << "Found a cluster already in SC linked to brem extrapolation"
1676  << " at ECAL surface!" << std::endl;
1677  RO.localMap.push_back( ElementMap::value_type(ecal->first,bremflagged.first) );
1678  RO.localMap.push_back( ElementMap::value_type(bremflagged.first,ecal->first) );
1679  }
1680  }
1681  // grab new clusters from the block (ensured to not be late brem)
1682  auto notmatched_block = std::partition(ECALbegin,ECALend,BremToECALs);
1683  for( auto ecal = ECALbegin; ecal != notmatched_block; ++ecal ) {
1684  float deta =
1685  std::abs( ecal->first->clusterRef()->positionREP().eta() -
1686  bremflagged.first->positionAtECALEntrance().eta() );
1687  if( deta < 0.015 ) {
1688  has_clusters = true;
1689  if( lastBremTrajPos == -1 || lastBremTrajPos < TrajPos ) {
1690  lastBremTrajPos = TrajPos;
1691  }
1692  if( FirstBrem == -1 || TrajPos < FirstBrem ) { // set brem information
1693 
1694  FirstBrem = TrajPos;
1695  RO.firstBrem = TrajPos;
1696  }
1697  const PFClusterElement* elemasclus =
1698  docast(const PFClusterElement*,ecal->first);
1699  if( addPFClusterToROSafe(elemasclus,RO) ) {
1700  attachPSClusters(elemasclus,RO.ecal2ps[elemasclus]);
1701 
1702  RO.localMap.push_back( ElementMap::value_type(ecal->first,bremflagged.first) );
1703  RO.localMap.push_back( ElementMap::value_type(bremflagged.first,ecal->first) );
1704  ecal->second = false;
1705  LOGDRESSED("PFEGammaAlgo::linkBremToECAL()")
1706  << "Found a cluster not already associated by brem extrapolation"
1707  << " at ECAL surface!" << std::endl;
1708  }
1709 
1710  }
1711  }
1712  if(has_clusters) {
1713  if( RO.nBremsWithClusters == -1 ) RO.nBremsWithClusters = 0;
1714  ++RO.nBremsWithClusters;
1715  }
1716  }
1717 }
1718 
1719 void PFEGammaAlgo::
1721  IsConversionTrack<reco::PFBlockElementTrack> isConvKf;
1722  auto KFbegin = _splayedblock[reco::PFBlockElement::TRACK].begin();
1723  auto KFend = _splayedblock[reco::PFBlockElement::TRACK].end();
1724  auto BeginROskfs = RO.secondaryKFs.begin();
1725  auto EndROskfs = RO.secondaryKFs.end();
1726  auto ronotconv = std::partition(BeginROskfs,EndROskfs,isConvKf);
1727  size_t convkfs_end = std::distance(BeginROskfs,ronotconv);
1728  for( size_t idx = 0; idx < convkfs_end; ++idx ) {
1729  const PFKFFlaggedElement& ro_skf = RO.secondaryKFs[idx];
1730  NotCloserToOther<reco::PFBlockElement::TRACK,
1732  true>
1733  TracksToTracks(_currentblock,_currentlinks, ro_skf.first);
1734  auto notmatched = std::partition(KFbegin,KFend,TracksToTracks);
1735  notmatched = std::partition(KFbegin,notmatched,isConvKf);
1736  for( auto kf = KFbegin; kf != notmatched; ++kf ) {
1737  const reco::PFBlockElementTrack* elemaskf =
1738  docast(const reco::PFBlockElementTrack*,kf->first);
1739  RO.secondaryKFs.push_back( std::make_pair(elemaskf,true) );
1740  RO.localMap.push_back( ElementMap::value_type(ro_skf.first,kf->first) );
1741  RO.localMap.push_back( ElementMap::value_type(kf->first,ro_skf.first) );
1742  kf->second = false;
1743  }
1744  }
1745 }
1746 
1747 void PFEGammaAlgo::
1749  IsConversionTrack<reco::PFBlockElementTrack> isConvKf;
1750  auto KFbegin = _splayedblock[reco::PFBlockElement::TRACK].begin();
1751  auto KFend = _splayedblock[reco::PFBlockElement::TRACK].end();
1752  for( auto& ecal : RO.ecalclusters ) {
1753  NotCloserToOther<reco::PFBlockElement::ECAL,
1755  true>
1756  ECALToTracks(_currentblock,_currentlinks,ecal.first);
1757  auto notmatchedkf = std::partition(KFbegin,KFend,ECALToTracks);
1758  auto notconvkf = std::partition(KFbegin,notmatchedkf,isConvKf);
1759  // add identified KF conversion tracks
1760  for( auto kf = KFbegin; kf != notconvkf; ++kf ) {
1761  const reco::PFBlockElementTrack* elemaskf =
1762  docast(const reco::PFBlockElementTrack*,kf->first);
1763  RO.secondaryKFs.push_back( std::make_pair(elemaskf,true) );
1764  RO.localMap.push_back( ElementMap::value_type(ecal.first,elemaskf) );
1765  RO.localMap.push_back( ElementMap::value_type(elemaskf,ecal.first) );
1766  kf->second = false;
1767  }
1768  // go through non-conv-identified kfs and check MVA to add conversions
1769  for( auto kf = notconvkf; kf != notmatchedkf; ++kf ) {
1771  kf->first->index()) ) {
1772  const reco::PFBlockElementTrack* elemaskf =
1773  docast(const reco::PFBlockElementTrack*,kf->first);
1774  RO.secondaryKFs.push_back( std::make_pair(elemaskf,true) );
1775  RO.localMap.push_back( ElementMap::value_type(ecal.first,elemaskf) );
1776  RO.localMap.push_back( ElementMap::value_type(elemaskf,ecal.first) );
1777  kf->second = false;
1778  }
1779  }
1780  }
1781 }
1782 
1783 void PFEGammaAlgo::
1785  auto ECALbegin = _splayedblock[reco::PFBlockElement::ECAL].begin();
1786  auto ECALend = _splayedblock[reco::PFBlockElement::ECAL].end();
1787  for( auto& skf : RO.secondaryKFs ) {
1788  NotCloserToOther<reco::PFBlockElement::TRACK,
1790  false>
1791  TracksToECALwithCut(_currentblock,_currentlinks,skf.first,1.5f);
1792  auto notmatched = std::partition(ECALbegin,ECALend,TracksToECALwithCut);
1793  for( auto ecal = ECALbegin; ecal != notmatched; ++ecal ) {
1794  const reco::PFBlockElementCluster* elemascluster =
1795  docast(const reco::PFBlockElementCluster*,ecal->first);
1796  if( addPFClusterToROSafe(elemascluster,RO) ) {
1797  attachPSClusters(elemascluster,RO.ecal2ps[elemascluster]);
1798  RO.localMap.push_back(ElementMap::value_type(skf.first,elemascluster));
1799  RO.localMap.push_back(ElementMap::value_type(elemascluster,skf.first));
1800  ecal->second = false;
1801  }
1802  }
1803  }
1804 }
1805 
1806 void PFEGammaAlgo::
1807 fillPFCandidates(const std::list<PFEGammaAlgo::ProtoEGObject>& ROs,
1808  reco::PFCandidateCollection& egcands,
1810  // reset output collections
1811  egcands.clear();
1812  egxs.clear();
1813  refinedscs_.clear();
1814  egcands.reserve(ROs.size());
1815  egxs.reserve(ROs.size());
1816  refinedscs_.reserve(ROs.size());
1817  for( auto& RO : ROs ) {
1818  if( RO.ecalclusters.size() == 0 &&
1820 
1821  reco::PFCandidate cand;
1823  if( RO.primaryGSFs.size() || RO.primaryKFs.size() ) {
1824  cand.setPdgId(-11); // anything with a primary track is an electron
1825  } else {
1826  cand.setPdgId(22); // anything with no primary track is a photon
1827  }
1828  if( RO.primaryKFs.size() ) {
1829  cand.setCharge(RO.primaryKFs[0].first->trackRef()->charge());
1830  xtra.setKfTrackRef(RO.primaryKFs[0].first->trackRef());
1831  cand.setTrackRef(RO.primaryKFs[0].first->trackRef());
1832  cand.addElementInBlock(_currentblock,RO.primaryKFs[0].first->index());
1833  }
1834  if( RO.primaryGSFs.size() ) {
1835  cand.setCharge(RO.primaryGSFs[0].first->GsftrackRef()->chargeMode());
1836  xtra.setGsfTrackRef(RO.primaryGSFs[0].first->GsftrackRef());
1837  cand.setGsfTrackRef(RO.primaryGSFs[0].first->GsftrackRef());
1838  cand.addElementInBlock(_currentblock,RO.primaryGSFs[0].first->index());
1839  }
1840  if( RO.parentSC ) {
1841  xtra.setSuperClusterPFECALRef(RO.parentSC->superClusterRef());
1842  // we'll set to the refined supercluster back up in the producer
1843  cand.setSuperClusterRef(RO.parentSC->superClusterRef());
1844  xtra.setSuperClusterRef(RO.parentSC->superClusterRef());
1845  cand.addElementInBlock(_currentblock,RO.parentSC->index());
1846  }
1847  // add brems
1848  for( const auto& bremflagged : RO.brems ) {
1849  const PFBremElement* brem = bremflagged.first;
1850  cand.addElementInBlock(_currentblock,brem->index());
1851  }
1852  // add clusters and ps clusters
1853  for( const auto& ecal : RO.ecalclusters ) {
1854  const PFClusterElement* clus = ecal.first;
1855  cand.addElementInBlock(_currentblock,clus->index());
1856  for( auto& ps : RO.ecal2ps.at(clus) ) {
1857  const PFClusterElement* psclus = ps.first;
1858  cand.addElementInBlock(_currentblock,psclus->index());
1859  }
1860  }
1861  // add secondary tracks
1862  for( const auto& secdkf : RO.secondaryKFs ) {
1863  const PFKFElement* kf = secdkf.first;
1865  reco::ConversionRef convref = kf->convRef();
1866  if( convref.isNonnull() && convref.isAvailable() ) {
1867  xtra.addConversionRef(convref);
1868  } else {
1869  xtra.addSingleLegConvTrackRef(kf->trackRef());
1870  // just hack it for now FIXME
1871  xtra.addSingleLegConvMva(-999.9f);
1872  }
1873  }
1874 
1875  // build the refined supercluster from those clusters left in the cand
1876  refinedscs_.push_back(buildRefinedSuperCluster(RO));
1877 
1878  const reco::SuperCluster& the_sc = refinedscs_.back();
1879  // with the refined SC in hand we build a naive candidate p4
1880  // and set the candidate ECAL position to either the barycenter of the
1881  // supercluster (if super-cluster present) or the seed of the
1882  // new SC generated by the EGAlgo
1883  const double scE = the_sc.energy();
1884  if( scE != 0.0 ) {
1885  const math::XYZPoint& seedPos = the_sc.seed()->position();
1886  math::XYZVector egDir = the_sc.position()-cfg_.primaryVtx->position();
1887  egDir = egDir.Unit();
1888  cand.setP4(math::XYZTLorentzVector(scE*egDir.x(),
1889  scE*egDir.y(),
1890  scE*egDir.z(),
1891  scE ));
1892  math::XYZPointF ecalPOS_f(seedPos.x(),seedPos.y(),seedPos.z());
1893  cand.setPositionAtECALEntrance(ecalPOS_f);
1894  cand.setEcalEnergy(the_sc.rawEnergy(),the_sc.energy());
1895  } else if ( cfg_.produceEGCandsWithNoSuperCluster &&
1896  RO.primaryGSFs.size() ) {
1897  const PFGSFElement* gsf = RO.primaryGSFs[0].first;
1898  reco::GsfTrackRef gref = gsf->GsftrackRef();
1899  math::XYZTLorentzVector p4(gref->pxMode(),gref->pyMode(),
1900  gref->pzMode(),gref->pMode());
1901  cand.setP4(p4);
1903  } else if ( cfg_.produceEGCandsWithNoSuperCluster &&
1904  RO.primaryKFs.size() ) {
1905  const PFKFElement* kf = RO.primaryKFs[0].first;
1906  reco::TrackRef kref = RO.primaryKFs[0].first->trackRef();
1907  math::XYZTLorentzVector p4(kref->px(),kref->py(),kref->pz(),kref->p());
1908  cand.setP4(p4);
1910  }
1911  const float ele_mva_value = calculate_ele_mva(RO,xtra);
1912  fill_extra_info(RO,xtra);
1913  //std::cout << "PFEG ele_mva: " << ele_mva_value << std::endl;
1914  xtra.setMVA(ele_mva_value);
1915  cand.set_mva_e_pi(ele_mva_value);
1916  egcands.push_back(cand);
1917  egxs.push_back(xtra);
1918  }
1919 }
1920 
1921 float PFEGammaAlgo::
1924  if( !RO.primaryGSFs.size() ) return -2.0f;
1925  const PFGSFElement* gsfElement = RO.primaryGSFs.front().first;
1926  const PFKFElement* kfElement = NULL;
1927  if( RO.primaryKFs.size() ) kfElement = RO.primaryKFs.front().first;
1928  reco::GsfTrackRef RefGSF= gsfElement->GsftrackRef();
1929  reco::TrackRef RefKF;
1930  constexpr float m_el = 0.000511;
1931  const double Ein_gsf = std::hypot(RefGSF->pMode(),m_el);
1932  double deta_gsfecal = 1e6;
1933  double sigmaEtaEta = 1e-14;
1934  const double Ene_hcalgsf = std::accumulate(RO.hcalClusters.begin(),
1935  RO.hcalClusters.end(),
1936  0.0,
1937  [](const double a,
1938  const PFClusterFlaggedElement& b)
1939  { return a + b.first->clusterRef()->energy(); }
1940  );
1941  if( RO.primaryKFs.size() ) {
1942  RefKF = RO.primaryKFs.front().first->trackRef();
1943  }
1944  const double Eout_gsf = gsfElement->Pout().t();
1945  const double Etaout_gsf = gsfElement->positionAtECALEntrance().eta();
1946  double FirstEcalGsfEnergy(0.0), OtherEcalGsfEnergy(0.0), EcalBremEnergy(0.0);
1947  //shower shape of cluster closest to gsf track
1948  std::vector<const reco::PFCluster*> gsfcluster;
1949  for( const auto& ecal : RO.ecalclusters ) {
1950  const double cenergy = ecal.first->clusterRef()->correctedEnergy();
1951  ElementMap::value_type gsfToEcal(gsfElement,ecal.first);
1952  ElementMap::value_type kfToEcal(kfElement,ecal.first);
1953  bool hasgsf =
1954  ( std::find(RO.localMap.begin(), RO.localMap.end(), gsfToEcal) ==
1955  RO.localMap.end() );
1956  bool haskf =
1957  ( std::find(RO.localMap.begin(), RO.localMap.end(), kfToEcal) ==
1958  RO.localMap.end() );
1959  bool hasbrem = false;
1960  for( const auto& brem : RO.brems ) {
1961  ElementMap::value_type bremToEcal(brem.first,ecal.first);
1962  if( std::find(RO.localMap.begin(), RO.localMap.end(), bremToEcal) !=
1963  RO.localMap.end() ) {
1964  hasbrem = true;
1965  }
1966  }
1967  if( hasbrem && ecal.first != RO.electronClusters[0] ) {
1968  EcalBremEnergy += cenergy;
1969  }
1970  if( !hasbrem && ecal.first != RO.electronClusters[0] ) {
1971  if( hasgsf ) OtherEcalGsfEnergy += cenergy;
1972  if( haskf ) EcalBremEnergy += cenergy; // from conv. brem!
1973  if( !(hasgsf || haskf) ) OtherEcalGsfEnergy += cenergy; // stuff from SC
1974  }
1975  }
1976 
1977  if( RO.electronClusters[0] ) {
1978  reco::PFClusterRef cref = RO.electronClusters[0]->clusterRef();
1980  FirstEcalGsfEnergy = cref->correctedEnergy();
1981  deta_gsfecal = cref->positionREP().eta() - Etaout_gsf;
1982  gsfcluster.push_back(&*cref);
1983  PFClusterWidthAlgo pfwidth(gsfcluster);
1984  sigmaEtaEta = pfwidth.pflowSigmaEtaEta();
1985  }
1986 
1987  // brem sequence information
1988  lateBrem = firstBrem = earlyBrem = -1.0f;
1989  if(RO.nBremsWithClusters > 0) {
1990  if (RO.lateBrem == 1) lateBrem = 1.0f;
1991  else lateBrem = 0.0f;
1992  firstBrem = RO.firstBrem;
1993  if(RO.firstBrem < 4) earlyBrem = 1.0f;
1994  else earlyBrem = 0.0f;
1995  }
1996  xtra.setEarlyBrem(earlyBrem);
1997  xtra.setLateBrem(lateBrem);
1998  if( FirstEcalGsfEnergy > 0.0 ) {
1999  if( RefGSF.isNonnull() ) {
2000  xtra.setGsfTrackPout(gsfElement->Pout());
2001  // normalization observables
2002  const float Pt_gsf = RefGSF->ptMode();
2003  lnPt_gsf = std::log(Pt_gsf);
2004  Eta_gsf = RefGSF->etaMode();
2005  // tracking observables
2006  const double ptModeErrorGsf = RefGSF->ptModeError();
2007  dPtOverPt_gsf = (ptModeErrorGsf > 0. ? ptModeErrorGsf/Pt_gsf : 1.0);
2008  nhit_gsf = RefGSF->hitPattern().trackerLayersWithMeasurement();
2009  chi2_gsf = RefGSF->normalizedChi2();
2010  DPtOverPt_gsf = (Pt_gsf - gsfElement->Pout().pt())/Pt_gsf;
2011  // kalman filter vars
2012  nhit_kf = 0;
2013  chi2_kf = -0.01;
2014  DPtOverPt_kf = -0.01;
2015  if( RefKF.isNonnull() ) {
2016  nhit_kf = RefKF->hitPattern().trackerLayersWithMeasurement();
2017  chi2_kf = RefKF->normalizedChi2();
2018  // not used for moment, weird behavior of variable
2019  // DPtOverPt_kf = (RefKF->pt() - RefKF->outerPt())/RefKF->pt();
2020  }
2021  //tracker + calorimetry observables
2022  const double EcalETot =
2023  (FirstEcalGsfEnergy+OtherEcalGsfEnergy+EcalBremEnergy);
2024  EtotPinMode = EcalETot / Ein_gsf;
2025  EGsfPoutMode = FirstEcalGsfEnergy / Eout_gsf;
2026  EtotBremPinPoutMode = ( (EcalBremEnergy + OtherEcalGsfEnergy) /
2027  (Ein_gsf - Eout_gsf) );
2028  DEtaGsfEcalClust = std::abs(deta_gsfecal);
2029  SigmaEtaEta = std::log(sigmaEtaEta);
2031  xtra.setSigmaEtaEta(sigmaEtaEta);
2032 
2033  HOverHE = Ene_hcalgsf/(Ene_hcalgsf + FirstEcalGsfEnergy);
2034  HOverPin = Ene_hcalgsf / Ein_gsf;
2035  xtra.setHadEnergy(Ene_hcalgsf);
2036 
2037  // Apply bounds to variables and calculate MVA
2041  chi2_gsf = std::min(chi2_gsf,10.0f);
2044  chi2_kf = std::min(chi2_kf,10.0f);
2052  SigmaEtaEta = std::max(SigmaEtaEta,-14.0f);
2053  HOverPin = std::max(HOverPin,0.0f);
2054  HOverPin = std::min(HOverPin,5.0f);
2055  /*
2056  std::cout << " **** PFEG BDT observables ****" << endl;
2057  std::cout << " < Normalization > " << endl;
2058  std::cout << " Pt_gsf " << Pt_gsf << " Pin " << Ein_gsf
2059  << " Pout " << Eout_gsf << " Eta_gsf " << Eta_gsf << endl;
2060  std::cout << " < PureTracking > " << endl;
2061  std::cout << " dPtOverPt_gsf " << dPtOverPt_gsf
2062  << " DPtOverPt_gsf " << DPtOverPt_gsf
2063  << " chi2_gsf " << chi2_gsf
2064  << " nhit_gsf " << nhit_gsf
2065  << " DPtOverPt_kf " << DPtOverPt_kf
2066  << " chi2_kf " << chi2_kf
2067  << " nhit_kf " << nhit_kf << endl;
2068  std::cout << " < track-ecal-hcal-ps " << endl;
2069  std::cout << " EtotPinMode " << EtotPinMode
2070  << " EGsfPoutMode " << EGsfPoutMode
2071  << " EtotBremPinPoutMode " << EtotBremPinPoutMode
2072  << " DEtaGsfEcalClust " << DEtaGsfEcalClust
2073  << " SigmaEtaEta " << SigmaEtaEta
2074  << " HOverHE " << HOverHE << " Hcal energy " << Ene_hcalgsf
2075  << " HOverPin " << HOverPin
2076  << " lateBrem " << lateBrem
2077  << " firstBrem " << firstBrem << endl;
2078  */
2079 
2080  return tmvaReaderEle_->EvaluateMVA("BDT");
2081  }
2082  }
2083  return -2.0f;
2084 }
2085 
2088  // add tracks associated to clusters that are not T_FROM_GAMMACONV
2089  // info about single-leg convs is already save, so just veto in loops
2090  IsConversionTrack<reco::PFBlockElementTrack> isConvKf;
2091  auto KFbegin = _splayedblock[reco::PFBlockElement::TRACK].begin();
2092  auto KFend = _splayedblock[reco::PFBlockElement::TRACK].end();
2093  for( auto& ecal : RO.ecalclusters ) {
2094  NotCloserToOther<reco::PFBlockElement::ECAL,
2096  true>
2097  ECALToTracks(_currentblock,_currentlinks,ecal.first);
2098  auto notmatchedkf = std::partition(KFbegin,KFend,ECALToTracks);
2099  auto notconvkf = std::partition(KFbegin,notmatchedkf,isConvKf);
2100  // go through non-conv-identified kfs and check MVA to add conversions
2101  for( auto kf = notconvkf; kf != notmatchedkf; ++kf ) {
2102  const reco::PFBlockElementTrack* elemaskf =
2103  docast(const reco::PFBlockElementTrack*,kf->first);
2104  xtra.addExtraNonConvTrack(_currentblock,*elemaskf);
2105  }
2106  }
2107 }
2108 
2109 // currently stolen from PFECALSuperClusterAlgo, we should
2110 // try to factor this correctly since the operation is the same in
2111 // both places...
2114  if( !RO.ecalclusters.size() ) {
2115  return reco::SuperCluster(0.0,math::XYZPoint(0,0,0));
2116  }
2117 
2118  SumPSEnergy sumps1(reco::PFBlockElement::PS1),
2119  sumps2(reco::PFBlockElement::PS2);
2120 
2121  bool isEE = false;
2122  edm::Ptr<reco::PFCluster> clusptr;
2123  // need the vector of raw pointers for a PF width class
2124  std::vector<const reco::PFCluster*> bare_ptrs;
2125  // calculate necessary parameters and build the SC
2126  double posX(0), posY(0), posZ(0),
2127  rawSCEnergy(0), corrSCEnergy(0), corrPSEnergy(0),
2128  PS1_clus_sum(0), PS2_clus_sum(0),
2129  ePS1(0), ePS2(0), ps1_energy(0.0), ps2_energy(0.0);
2130  for( auto& clus : RO.ecalclusters ) {
2131  ePS1 = 0;
2132  ePS2 = 0;
2133  isEE = PFLayer::ECAL_ENDCAP == clus.first->clusterRef()->layer();
2134  clusptr =
2135  edm::refToPtr<reco::PFClusterCollection>(clus.first->clusterRef());
2136  bare_ptrs.push_back(clusptr.get());
2137 
2138  const double cluseraw = clusptr->energy();
2139  double cluscalibe = clusptr->correctedEnergy();
2140  const math::XYZPoint& cluspos = clusptr->position();
2141  posX += cluseraw * cluspos.X();
2142  posY += cluseraw * cluspos.Y();
2143  posZ += cluseraw * cluspos.Z();
2144  // update EE calibrated super cluster energies
2145  if( isEE ) {
2146  const auto& psclusters = RO.ecal2ps.at(clus.first);
2147  PS1_clus_sum = std::accumulate(psclusters.begin(),psclusters.end(),
2148  0.0,sumps1);
2149  PS2_clus_sum = std::accumulate(psclusters.begin(),psclusters.end(),
2150  0.0,sumps2);
2151  cluscalibe =
2152  cfg_.thePFEnergyCalibration->energyEm(*clusptr,
2153  PS1_clus_sum,PS2_clus_sum,
2154  ePS1, ePS2,
2156  }
2157 
2158  rawSCEnergy += cluseraw;
2159  corrSCEnergy += cluscalibe;
2160  ps1_energy += ePS1;
2161  ps2_energy += ePS2;
2162  corrPSEnergy += ePS1 + ePS2;
2163  }
2164  posX /= rawSCEnergy;
2165  posY /= rawSCEnergy;
2166  posZ /= rawSCEnergy;
2167 
2168  // now build the supercluster
2169  reco::SuperCluster new_sc(corrSCEnergy,math::XYZPoint(posX,posY,posZ));
2170 
2171  clusptr =
2172  edm::refToPtr<reco::PFClusterCollection>(RO.ecalclusters.front().
2173  first->clusterRef());
2174  new_sc.setCorrectedEnergy(corrSCEnergy);
2175  new_sc.setSeed(clusptr);
2176  new_sc.setPreshowerEnergyPlane1(ps1_energy);
2177  new_sc.setPreshowerEnergyPlane2(ps2_energy);
2178  new_sc.setPreshowerEnergy(corrPSEnergy);
2179  for( const auto& clus : RO.ecalclusters ) {
2180  clusptr =
2181  edm::refToPtr<reco::PFClusterCollection>(clus.first->clusterRef());
2182  new_sc.addCluster(clusptr);
2183  auto& hits_and_fractions = clusptr->hitsAndFractions();
2184  for( auto& hit_and_fraction : hits_and_fractions ) {
2185  new_sc.addHitAndFraction(hit_and_fraction.first,hit_and_fraction.second);
2186  }
2187  // put the preshower stuff back in later
2188  const auto& cluspsassociation = RO.ecal2ps.at(clus.first);
2189  // EE rechits should be uniquely matched to sets of pre-shower
2190  // clusters at this point, so we throw an exception if otherwise
2191  // now wrapped in EDM debug flags
2192  for( const auto& pscluselem : cluspsassociation ) {
2193  edm::Ptr<reco::PFCluster> psclus =
2194  edm::refToPtr<reco::PFClusterCollection>(pscluselem.first->
2195  clusterRef());
2196 #ifdef PFFLOW_DEBUG
2197  auto found_pscluster = std::find(new_sc.preshowerClustersBegin(),
2198  new_sc.preshowerClustersEnd(),
2199  reco::CaloClusterPtr(psclus));
2200  if( found_pscluster == new_sc.preshowerClustersEnd() ) {
2201 #endif
2202  new_sc.addPreshowerCluster(psclus);
2203 #ifdef PFFLOW_DEBUG
2204  } else {
2205  throw cms::Exception("PFECALSuperClusterAlgo::buildSuperCluster")
2206  << "Found a PS cluster matched to more than one EE cluster!"
2207  << std::endl << std::hex << psclus.get() << " == "
2208  << found_pscluster->get() << std::dec << std::endl;
2209  }
2210 #endif
2211  }
2212  }
2213 
2214  // calculate linearly weighted cluster widths
2215  PFClusterWidthAlgo pfwidth(bare_ptrs);
2216  new_sc.setEtaWidth(pfwidth.pflowEtaWidth());
2217  new_sc.setPhiWidth(pfwidth.pflowPhiWidth());
2218 
2219  // cache the value of the raw energy
2220  new_sc.rawEnergy();
2221 
2222  return new_sc;
2223 }
2224 
2225 void PFEGammaAlgo::
2227  // this only means something for ROs with a primary GSF track
2228  if( !RO.primaryGSFs.size() ) return;
2229  // need energy sums to tell if we've added crap or not
2230  const double Pin_gsf = RO.primaryGSFs.front().first->GsftrackRef()->pMode();
2231  const double gsfOuterEta =
2232  RO.primaryGSFs.front().first->positionAtECALEntrance().Eta();
2233  double tot_ecal= 0.0;
2234  std::vector<double> min_brem_dists;
2235  std::vector<double> closest_brem_eta;
2236  // first get the total ecal energy (we should replace this with a cache)
2237  for( const auto& ecal : RO.ecalclusters ) {
2238  tot_ecal += ecal.first->clusterRef()->correctedEnergy();
2239  // we also need to look at the minimum distance to brems
2240  // since energetic brems will be closer to the brem than the track
2241  double min_brem_dist = 5000.0;
2242  double eta = -999.0;
2243  for( const auto& brem : RO.brems ) {
2244  const float dist = _currentblock->dist(brem.first->index(),
2245  ecal.first->index(),
2246  _currentlinks,
2248  if( dist < min_brem_dist && dist != -1.0f ) {
2249  min_brem_dist = dist;
2250  eta = brem.first->positionAtECALEntrance().Eta();
2251  }
2252  }
2253  min_brem_dists.push_back(min_brem_dist);
2254  closest_brem_eta.push_back(eta);
2255  }
2256 
2257  // loop through the ECAL clusters and remove ECAL clusters matched to
2258  // secondary track either in *or* out of the SC if the E/pin is bad
2259  for( auto secd_kf = RO.secondaryKFs.begin();
2260  secd_kf != RO.secondaryKFs.end(); ++secd_kf ) {
2261  reco::TrackRef trkRef = secd_kf->first->trackRef();
2262  const float secpin = secd_kf->first->trackRef()->p();
2263  bool remove_this_kf = false;
2264  for( auto ecal = RO.ecalclusters.begin();
2265  ecal != RO.ecalclusters.end(); ++ecal ) {
2266  size_t bremidx = std::distance(RO.ecalclusters.begin(),ecal);
2267  const float minbremdist = min_brem_dists[bremidx];
2268  const double ecalenergy = ecal->first->clusterRef()->correctedEnergy();
2269  const double Epin = ecalenergy/secpin;
2270  const double detaGsf =
2271  std::abs(gsfOuterEta - ecal->first->clusterRef()->positionREP().Eta());
2272  const double detaBrem =
2273  std::abs(closest_brem_eta[bremidx] -
2274  ecal->first->clusterRef()->positionREP().Eta());
2275 
2276  ElementMap::value_type check_match(ecal->first,secd_kf->first);
2277  auto kf_matched = std::find(RO.localMap.begin(),
2278  RO.localMap.end(),
2279  check_match);
2280 
2281  const float tkdist = _currentblock->dist(secd_kf->first->index(),
2282  ecal->first->index(),
2283  _currentlinks,
2285 
2286  // do not reject this track if it is closer to a brem than the
2287  // secondary track, or if it lies in the delta-eta plane with the
2288  // gsf track or if it is in the dEta plane with the brems
2289  if( Epin > 3 && kf_matched != RO.localMap.end() &&
2290  tkdist != -1.0f && tkdist < minbremdist &&
2291  detaGsf > 0.05 && detaBrem > 0.015) {
2292  double res_with = std::abs((tot_ecal-Pin_gsf)/Pin_gsf);
2293  double res_without = std::abs((tot_ecal-ecalenergy-Pin_gsf)/Pin_gsf);
2294  if(res_without < res_with) {
2295  LOGDRESSED("PFEGammaAlgo")
2296  << " REJECTED_RES totenergy " << tot_ecal
2297  << " Pin_gsf " << Pin_gsf
2298  << " cluster to secondary " << ecalenergy
2299  << " res_with " << res_with
2300  << " res_without " << res_without << std::endl;
2301  tot_ecal -= ecalenergy;
2302  remove_this_kf = true;
2303  ecal = RO.ecalclusters.erase(ecal);
2304  if( ecal == RO.ecalclusters.end() ) break;
2305  }
2306  }
2307  }
2308  if( remove_this_kf ) {
2309  secd_kf = RO.secondaryKFs.erase(secd_kf);
2310  if( secd_kf == RO.secondaryKFs.end() ) break;
2311  }
2312  }
2313 }
2314 
2315 void PFEGammaAlgo::
2317  bool removeFreeECAL,
2318  bool removeSCEcal) {
2319  std::vector<bool> cluster_in_sc;
2320  auto ecal_begin = RO.ecalclusters.begin();
2321  auto ecal_end = RO.ecalclusters.end();
2322  auto hcal_begin = _splayedblock[reco::PFBlockElement::HCAL].begin();
2323  auto hcal_end = _splayedblock[reco::PFBlockElement::HCAL].end();
2324  for( auto secd_kf = RO.secondaryKFs.begin();
2325  secd_kf != RO.secondaryKFs.end(); ++secd_kf ) {
2326  bool remove_this_kf = false;
2327  NotCloserToOther<reco::PFBlockElement::TRACK,reco::PFBlockElement::HCAL>
2328  tracksToHCALs(_currentblock,_currentlinks,secd_kf->first);
2329  reco::TrackRef trkRef = secd_kf->first->trackRef();
2330  const unsigned int Algo = whichTrackAlgo(trkRef);
2331  const float secpin = trkRef->p();
2332 
2333  for( auto ecal = ecal_begin; ecal != ecal_end; ++ecal ) {
2334  const double ecalenergy = ecal->first->clusterRef()->correctedEnergy();
2335  // first check if the cluster is in the SC (use dist calc for fastness)
2336  const size_t clus_idx = std::distance(ecal_begin,ecal);
2337  if( cluster_in_sc.size() < clus_idx + 1) {
2338  float dist = -1.0f;
2339  if( RO.parentSC ) {
2340  dist = _currentblock->dist(secd_kf->first->index(),
2341  ecal->first->index(),
2342  _currentlinks,
2344  }
2345  cluster_in_sc.push_back(dist != -1.0f);
2346  }
2347 
2348  ElementMap::value_type check_match(ecal->first,secd_kf->first);
2349  auto kf_matched = std::find(RO.localMap.begin(),
2350  RO.localMap.end(),
2351  check_match);
2352  // if we've found a secondary KF that matches this ecal cluster
2353  // now we see if it is matched to HCAL
2354  // if it is matched to an HCAL cluster we take different
2355  // actions if the cluster was in an SC or not
2356  if( kf_matched != RO.localMap.end() ) {
2357  auto hcal_matched = std::partition(hcal_begin,hcal_end,tracksToHCALs);
2358  for( auto hcalclus = hcal_begin;
2359  hcalclus != hcal_matched;
2360  ++hcalclus ) {
2361  const reco::PFBlockElementCluster * clusthcal =
2362  dynamic_cast<const reco::PFBlockElementCluster*>(hcalclus->first);
2363  const double hcalenergy = clusthcal->clusterRef()->energy();
2364  const double hpluse = ecalenergy+hcalenergy;
2365  const bool isHoHE = ( (hcalenergy / hpluse ) > 0.1 && Algo < 3 );
2366  const bool isHoE = ( hcalenergy > ecalenergy );
2367  const bool isPoHE = ( secpin > hpluse );
2368  if( cluster_in_sc[clus_idx] ) {
2369  if(isHoE || isPoHE) {
2370  LOGDRESSED("PFEGammaAlgo")
2371  << "REJECTED TRACK FOR H/E or P/(H+E), CLUSTER IN SC"
2372  << " H/H+E " << (hcalenergy / hpluse)
2373  << " H/E " << (hcalenergy > ecalenergy)
2374  << " P/(H+E) " << (secpin/hpluse)
2375  << " HCAL ENE " << hcalenergy
2376  << " ECAL ENE " << ecalenergy
2377  << " secPIN " << secpin
2378  << " Algo Track " << Algo << std::endl;
2379  remove_this_kf = true;
2380  }
2381  } else {
2382  if(isHoHE){
2383  LOGDRESSED("PFEGammaAlgo")
2384  << "REJECTED TRACK FOR H/H+E, CLUSTER NOT IN SC"
2385  << " H/H+E " << (hcalenergy / hpluse)
2386  << " H/E " << (hcalenergy > ecalenergy)
2387  << " P/(H+E) " << (secpin/hpluse)
2388  << " HCAL ENE " << hcalenergy
2389  << " ECAL ENE " << ecalenergy
2390  << " secPIN " << secpin
2391  << " Algo Track " << Algo << std::endl;
2392  remove_this_kf = true;
2393  }
2394  }
2395  }
2396  }
2397  }
2398  if( remove_this_kf ) {
2399  secd_kf = RO.secondaryKFs.erase(secd_kf);
2400  if( secd_kf == RO.secondaryKFs.end() ) break;
2401  }
2402  }
2403 }
2404 
2405 
2406 unsigned int PFEGammaAlgo::whichTrackAlgo(const reco::TrackRef& trackRef) {
2407  unsigned int Algo = 0;
2408  switch (trackRef->algo()) {
2409  case TrackBase::ctf:
2410  case TrackBase::iter0:
2411  case TrackBase::iter1:
2412  case TrackBase::iter2:
2413  Algo = 0;
2414  break;
2415  case TrackBase::iter3:
2416  Algo = 1;
2417  break;
2418  case TrackBase::iter4:
2419  Algo = 2;
2420  break;
2421  case TrackBase::iter5:
2422  Algo = 3;
2423  break;
2424  case TrackBase::iter6:
2425  Algo = 4;
2426  break;
2427  default:
2428  Algo = 5;
2429  break;
2430  }
2431  return Algo;
2432 }
2434  const reco::PFBlockElementGsfTrack& GsfEl) {
2435  bool isPrimary = false;
2436 
2437  GsfPFRecTrackRef gsfPfRef = GsfEl.GsftrackRefPF();
2438 
2439  if(gsfPfRef.isNonnull()) {
2440  PFRecTrackRef kfPfRef = KfEl.trackRefPF();
2441  PFRecTrackRef kfPfRef_fromGsf = (*gsfPfRef).kfPFRecTrackRef();
2442  if(kfPfRef.isNonnull() && kfPfRef_fromGsf.isNonnull()) {
2443  reco::TrackRef kfref= (*kfPfRef).trackRef();
2444  reco::TrackRef kfref_fromGsf = (*kfPfRef_fromGsf).trackRef();
2445  if(kfref.isNonnull() && kfref_fromGsf.isNonnull()) {
2446  if(kfref == kfref_fromGsf)
2447  isPrimary = true;
2448  }
2449  }
2450  }
2451 
2452  return isPrimary;
2453 }
float EtotBremPinPoutMode
Definition: PFEGammaAlgo.h:306
type
Definition: HCALResponse.h:21
const math::XYZTLorentzVector & Pout() const
double mvaValue
Definition: PFEGammaAlgo.h:347
Abstract base class for a PFBlock element (track, cluster...)
const math::XYZPoint & position() const
cluster centroid position
Definition: CaloCluster.h:124
CaloCluster_iterator preshowerClustersBegin() const
fist iterator over PreshowerCluster constituents
Definition: SuperCluster.h:81
bool EvaluateSingleLegMVA(const reco::PFBlockRef &blockref, const reco::Vertex &primaryvtx, unsigned int track_index)
int i
Definition: DBlmapReader.cc:9
unsigned int whichTrackAlgo(const reco::TrackRef &trackRef)
virtual void setCharge(Charge q) GCC11_FINAL
set electric charge
void addSingleLegConvMva(const float &mvasingleleg)
add Single Leg Conversion mva
static const TGPicture * info(bool iBackgroundIsBlack)
std::vector< PFClusterFlaggedElement > ecalclusters
Definition: PFEGammaAlgo.h:81
static bool overlap(const reco::CaloCluster &sc1, const reco::CaloCluster &sc, float minfrac=0.01, bool debug=false)
void Dump(std::ostream &out=std::cout, const char *tab=" ") const
print the object inside the element
void setSuperClusterRef(reco::SuperClusterRef sc)
set reference to the corresponding supercluster
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
list parent
Definition: dbtoconf.py:74
reco::PFCandidateEGammaExtraCollection egExtra_
Definition: PFEGammaAlgo.h:381
std::vector< std::pair< unsigned int, unsigned int > > fifthStepKfTrack_
Definition: PFEGammaAlgo.h:286
reco::SuperClusterCollection refinedscs_
Definition: PFEGammaAlgo.h:175
void addHitAndFraction(DetId id, float fraction)
Definition: CaloCluster.h:183
void addSingleLegConvTrackRef(const reco::TrackRef &trackref)
add Single Leg Conversion TrackRef
void RunPFEG(const reco::PFBlockRef &blockRef, std::vector< bool > &active)
reco::PFBlockRef parentBlock
Definition: PFEGammaAlgo.h:75
void unlinkRefinableObjectKFandECALWithBadEoverP(ProtoEGObject &)
trackRef_iterator tracks_end() const
last iterator over tracks
Definition: Vertex.cc:44
static bool isMuon(const reco::PFBlockElement &elt)
Definition: PFMuonAlgo.cc:153
void setPositionAtECALEntrance(const math::XYZPointF &pos)
set position at ECAL entrance
Definition: PFCandidate.h:330
void setGsfElectronClusterRef(const reco::PFBlockRef &blk, const reco::PFBlockElementCluster &ref)
set gsf electron cluster ref
float EGsfPoutMode
Definition: PFEGammaAlgo.h:306
PFClusterRef clusterRef() const
void setPreshowerEnergyPlane2(double preshowerEnergy2)
Definition: SuperCluster.h:61
std::pair< const PFClusterElement *, bool > PFClusterFlaggedElement
Definition: PFEGammaAlgo.h:64
double y() const
y coordinate
Definition: Vertex.h:96
void setHadEnergy(float val)
set the had energy. The cluster energies should be entered before
const math::XYZPointF & positionAtECALEntrance() const
std::shared_ptr< PFEnergyCalibration > thePFEnergyCalibration
Definition: PFEGammaAlgo.h:104
Type type() const
std::map< unsigned int, Link > LinkData
Definition: PFBlock.h:46
Geom::Phi< T > phi() const
Definition: PV3DBase.h:69
double pflowPhiWidth() const
std::vector< PFClusterFlaggedElement > hcalClusters
Definition: PFEGammaAlgo.h:92
bool isPrimaryTrack(const reco::PFBlockElementTrack &KfEl, const reco::PFBlockElementGsfTrack &GsfEl)
float DEtaGsfEcalClust
Definition: PFEGammaAlgo.h:307
#define X(str)
Definition: MuonsGrabber.cc:48
void linkRefinableObjectPrimaryGSFTrackToECAL(ProtoEGObject &)
list elements
Definition: asciidump.py:414
#define NULL
Definition: scimark2.h:8
const edm::OwnVector< reco::PFBlockElement > & elements() const
Definition: PFBlock.h:107
double Phi_mpi_pi(double x)
Definition: JetUtil.h:24
edm::Ref< TrackExtraCollection > TrackExtraRef
persistent reference to a TrackExtra
Definition: TrackExtraFwd.h:13
std::vector< const PFClusterElement * > electronClusters
Definition: PFEGammaAlgo.h:96
unsigned int index
index type
Definition: Vertex.h:49
const LinkData & linkData() const
Definition: PFBlock.h:112
std::vector< std::vector< PFFlaggedElement > > _splayedblock
Definition: PFEGammaAlgo.h:184
void setSeed(const CaloClusterPtr &r)
list of used xtals by DetId // now inherited by CaloCluster
Definition: SuperCluster.h:96
const math::XYZTLorentzVector & Pin() const
std::pair< const PFGSFElement *, bool > PFGSFFlaggedElement
Definition: PFEGammaAlgo.h:62
edm::Ptr< CaloCluster > CaloClusterPtr
void linkRefinableObjectBremTangentsToECAL(ProtoEGObject &)
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< float > > XYZPointF
point in space with cartesian internal representation
Definition: Point3D.h:10
bool isAvailable() const
Definition: Ref.h:276
TH2D * X0_outer
Definition: PFEGammaAlgo.h:370
const reco::Vertex * primaryVtx
Definition: PFEGammaAlgo.h:121
T eta() const
unsigned int indTrajPoint() const
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
reco::PFBlockRef _currentblock
Definition: PFEGammaAlgo.h:180
void setGsfTrackRef(const reco::GsfTrackRef &ref)
set gsftrack reference
std::pair< const reco::PFBlockElement *, bool > PFFlaggedElement
Definition: PFEGammaAlgo.h:59
void setPhiWidth(double pw)
Definition: SuperCluster.h:62
const Point & position() const
position
Definition: Vertex.h:92
double pflowEtaWidth() const
std::pair< const PFSCElement *, bool > PFSCFlaggedElement
Definition: PFEGammaAlgo.h:60
const math::XYZPointF & positionAtECALEntrance() const
PFEGConfigInfo cfg_
Definition: PFEGammaAlgo.h:289
void set_mva_e_pi(float mva)
Definition: PFCandidate.h:291
float DPtOverPt_gsf
Definition: PFEGammaAlgo.h:300
void linkRefinableObjectECALToSingleLegConv(ProtoEGObject &)
edm::Handle< reco::PFCluster::EEtoPSAssociation > eetops_
Definition: PFEGammaAlgo.h:179
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:250
#define LOGERR(x)
Definition: PFEGammaAlgo.cc:45
std::vector< PFKFFlaggedElement > secondaryKFs
Definition: PFEGammaAlgo.h:90
void setEtaWidth(double ew)
Definition: SuperCluster.h:63
void setSigmaEtaEta(float val)
set the sigmaetaeta
#define LOGVERB(x)
Definition: PFEGammaAlgo.cc:43
#define LOGDRESSED(x)
Definition: PFEGammaAlgo.cc:46
void dumpCurrentRefinableObjects() const
bool isNull() const
Checks for null.
Definition: Ref.h:247
void initializeProtoCands(std::list< ProtoEGObject > &)
T const * get() const
Returns C++ pointer to the item.
Definition: Ptr.h:143
void linkRefinableObjectPrimaryKFsToSecondaryKFs(ProtoEGObject &)
unsigned index() const
const T & max(const T &a, const T &b)
bool unwrapSuperCluster(const reco::PFBlockElementSuperCluster *, std::vector< PFClusterFlaggedElement > &, ClusterMap &)
double pflowSigmaEtaEta() const
void setCorrectedEnergy(double cenergy)
Definition: CaloCluster.h:109
void addElementInBlock(const reco::PFBlockRef &blockref, unsigned elementIndex)
add an element to the current PFCandidate
Definition: PFCandidate.cc:207
reco::PFCluster::EEtoPSAssociation EEtoPSAssociation
Definition: PFEGammaAlgo.h:53
T sqrt(T t)
Definition: SSEVec.h:48
double p4[4]
Definition: TauolaWrapper.h:92
PFEGammaAlgo(const PFEGConfigInfo &)
reco::GsfTrackRef GsftrackRef() const
const PFSCElement * parentSC
Definition: PFEGammaAlgo.h:76
std::vector< reco::PFCandidateEGammaExtra > PFCandidateEGammaExtraCollection
collection of PFCandidateEGammaExtras
std::vector< PFBremFlaggedElement > brems
Definition: PFEGammaAlgo.h:87
void setEarlyBrem(float val)
set EarlyBrem
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double z() const
y coordinate
Definition: Vertex.h:98
float DPtOverPt_kf
Definition: PFEGammaAlgo.h:300
void setGsfTrackPout(const math::XYZTLorentzVector &pout)
set the pout (not trivial to get from the GSF track)
float dPtOverPt_gsf
Definition: PFEGammaAlgo.h:300
double f[11][100]
double energy() const
cluster energy
Definition: CaloCluster.h:120
#define end
Definition: vmac.h:37
std::list< ProtoEGObject > _refinableObjects
Definition: PFEGammaAlgo.h:198
bool first
Definition: L1TdeRCT.cc:79
virtual bool trackType(TrackType trType) const
Container::value_type value_type
reco::PFCandidateEGammaExtraCollection outcandsextra_
Definition: PFEGammaAlgo.h:174
void linkKFTrackToECAL(const PFKFFlaggedElement &, ProtoEGObject &)
void buildAndRefineEGObjects(const reco::PFBlockRef &block)
void setEcalEnergy(float eeRaw, float eeCorr)
set corrected Ecal energy
Definition: PFCandidate.h:200
Layer
layer definition
Definition: PFLayer.h:31
reco::PFBlock::LinkData _currentlinks
Definition: PFEGammaAlgo.h:181
Float e1
Definition: deltaR.h:22
std::vector< reco::PFCandidate > PFCandidateCollection
collection of PFCandidates
double x() const
x coordinate
Definition: Vertex.h:94
key_type key() const
Definition: Ptr.h:169
virtual bool trackType(TrackType trType) const
double rawEnergy() const
raw uncorrected energy (sum of energies of component BasicClusters)
Definition: SuperCluster.h:47
void fill_extra_info(const ProtoEGObject &, reco::PFCandidateEGammaExtra &)
reco::PFCandidateCollection egCandidate_
Definition: PFEGammaAlgo.h:377
bool isAMuon(const reco::PFBlockElement &)
void setDeltaEta(float val)
set the delta eta
void setGsfTrackRef(const reco::GsfTrackRef &ref)
set gsftrack reference
Definition: PFCandidate.cc:450
reco::ElectronSeedRef electronSeed
Definition: PFEGammaAlgo.h:77
float calculate_ele_mva(const ProtoEGObject &, reco::PFCandidateEGammaExtra &)
PFRecTrackRef trackRefPF() const
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:30
void associatedElements(unsigned i, const LinkData &linkData, std::multimap< double, unsigned > &sortedAssociates, reco::PFBlockElement::Type type=PFBlockElement::NONE, LinkTest test=LINKTEST_RECHIT) const
Definition: PFBlock.cc:75
XYZPointD XYZPoint
point in space with cartesian internal representation
Definition: Point3D.h:12
tuple idx
DEBUGGING if hasattr(process,&quot;trackMonIterativeTracking2012&quot;): print &quot;trackMonIterativeTracking2012 D...
void addPreshowerCluster(const CaloClusterPtr &r)
add reference to constituent BasicCluster
Definition: SuperCluster.h:114
float SigmaEtaEta
Definition: PFEGammaAlgo.h:308
double b
Definition: hdecay.h:120
#define docast(x, y)
Definition: PFEGammaAlgo.cc:42
void linkRefinableObjectGSFTracksToKFs(ProtoEGObject &)
std::vector< std::pair< unsigned int, unsigned int > > convGsfTrack_
Definition: PFEGammaAlgo.h:287
void setSuperClusterPFECALRef(reco::SuperClusterRef sc)
set reference to the corresponding supercluster
void addConversionRef(const reco::ConversionRef &convref)
add Conversions from PF
TMVA::Reader * tmvaReaderEle_
Definition: PFEGammaAlgo.h:291
reco::TrackRef trackRef() const
std::vector< PFKFFlaggedElement > primaryKFs
Definition: PFEGammaAlgo.h:86
Float e2
Definition: deltaR.h:23
std::unordered_map< const PFClusterElement *, std::vector< PFClusterFlaggedElement > > ClusterMap
Definition: PFEGammaAlgo.h:71
float EtotPinMode
Definition: PFEGammaAlgo.h:306
void addCluster(const CaloClusterPtr &r)
add reference to constituent BasicCluster
Definition: SuperCluster.h:108
void Dump(std::ostream &out=std::cout, const char *tab=" ") const
print the object inside the element
ElementMap _recoveredlinks
Definition: PFEGammaAlgo.h:185
void removeOrLinkECALClustersToKFTracks()
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:38
#define begin
Definition: vmac.h:30
void Dump(std::ostream &out=std::cout, const char *tab=" ") const
print the object inside the element
list key
Definition: combine.py:13
#define LOGWARN(x)
Definition: PFEGammaAlgo.cc:44
reco::SuperCluster buildRefinedSuperCluster(const ProtoEGObject &)
TH2D * X0_inner
Definition: PFEGammaAlgo.h:368
void unlinkRefinableObjectKFandECALMatchedToHCAL(ProtoEGObject &, bool removeFreeECAL=false, bool removeSCECAL=false)
virtual void setP4(const LorentzVector &p4) GCC11_FINAL
set 4-momentum
double a
Definition: hdecay.h:121
std::pair< const PFKFElement *, bool > PFKFFlaggedElement
Definition: PFEGammaAlgo.h:63
void mergeROsByAnyLink(std::list< ProtoEGObject > &)
GsfPFRecTrackRef GsftrackRefPF() const
void setSuperClusterRef(const reco::SuperClusterRef &scRef)
Definition: PFCandidate.cc:616
int attachPSClusters(const PFClusterElement *, ClusterMap::mapped_type &)
key_type index() const
Definition: Ref.h:269
void linkRefinableObjectKFTracksToECAL(ProtoEGObject &)
void setKfTrackRef(const reco::TrackRef &ref)
set kf track reference
const CaloClusterPtr & seed() const
seed BasicCluster
Definition: SuperCluster.h:66
void setMVA(float val)
set the result (mostly for debugging)
volatile std::atomic< bool > shutdown_flag false
TMVA::Reader * tmvaReader_
Definition: PFEGammaAlgo.h:327
void linkRefinableObjectSecondaryKFsToECAL(ProtoEGObject &)
void setLateBrem(float val)
set LateBrem
trackRef_iterator tracks_begin() const
first iterator over tracks
Definition: Vertex.cc:39
reco::PFCandidateCollection _finalCandidates
Definition: PFEGammaAlgo.h:200
TH2D * X0_middle
Definition: PFEGammaAlgo.h:369
void linkRefinableObjectConvSecondaryKFsToSecondaryKFs(ProtoEGObject &)
verbosityLevel verbosityLevel_
Definition: PFEGammaAlgo.h:320
T const * get() const
Returns C++ pointer to the item.
Definition: Ref.h:242
void setTrackRef(const reco::TrackRef &ref)
set track reference
Definition: PFCandidate.cc:412
virtual void setPdgId(int pdgId) GCC11_FINAL
reco::PFCandidateCollection outcands_
Definition: PFEGammaAlgo.h:173
ConversionRef convRef() const
void fillPFCandidates(const std::list< ProtoEGObject > &, reco::PFCandidateCollection &, reco::PFCandidateEGammaExtraCollection &)
bool next_combination(BidIt n_begin, BidIt n_end, BidIt r_begin, BidIt r_end)
Definition: combination.h:22
void setPreshowerEnergyPlane1(double preshowerEnergy1)
Definition: SuperCluster.h:60
std::vector< PFGSFFlaggedElement > primaryGSFs
Definition: PFEGammaAlgo.h:84
tuple size
Write out results.
Definition: fakeMenu.h:4
#define constexpr
CaloCluster_iterator preshowerClustersEnd() const
last iterator over PreshowerCluster constituents
Definition: SuperCluster.h:84
void addExtraNonConvTrack(const reco::PFBlockRef &blk, const reco::PFBlockElementTrack &tkref)
track counting for electrons and photons
void setPreshowerEnergy(double preshowerEnergy)
Definition: SuperCluster.h:59
void linkRefinableObjectPrimaryGSFTrackToHCAL(ProtoEGObject &)
Block of elements.
Definition: PFBlock.h:30