CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
PFElectronAlgo.cc
Go to the documentation of this file.
1 //
2 // Original Author: Daniele Benedetti: daniele.benedetti@cern.ch
3 //
4 
7 //#include "DataFormats/ParticleFlowReco/interface/PFBlockElementGsfTrack.h"
26 
27 #include <iomanip>
28 #include <algorithm>
29 
30 using namespace std;
31 using namespace reco;
32 PFElectronAlgo::PFElectronAlgo(const double mvaEleCut,
33  string mvaWeightFileEleID,
34  const boost::shared_ptr<PFSCEnergyCalibration>& thePFSCEnergyCalibration,
35  const boost::shared_ptr<PFEnergyCalibration>& thePFEnergyCalibration,
37  bool usePFSCEleCalib,
38  bool useEGElectrons,
45  unsigned int nTrackIsoForEgammaSC,
47  mvaEleCut_(mvaEleCut),
48  thePFSCEnergyCalibration_(thePFSCEnergyCalibration),
49  thePFEnergyCalibration_(thePFEnergyCalibration),
50  applyCrackCorrections_(applyCrackCorrections),
51  usePFSCEleCalib_(usePFSCEleCalib),
52  useEGElectrons_(useEGElectrons),
53  useEGammaSupercluster_(useEGammaSupercluster),
54  sumEtEcalIsoForEgammaSC_barrel_(sumEtEcalIsoForEgammaSC_barrel),
55  sumEtEcalIsoForEgammaSC_endcap_(sumEtEcalIsoForEgammaSC_endcap),
56  coneEcalIsoForEgammaSC_(coneEcalIsoForEgammaSC),
57  sumPtTrackIsoForEgammaSC_barrel_(sumPtTrackIsoForEgammaSC_barrel),
58  sumPtTrackIsoForEgammaSC_endcap_(sumPtTrackIsoForEgammaSC_endcap),
59  nTrackIsoForEgammaSC_(nTrackIsoForEgammaSC),
60  coneTrackIsoForEgammaSC_(coneTrackIsoForEgammaSC)
61 {
62  // Set the tmva reader
63  tmvaReader_ = new TMVA::Reader("!Color:Silent");
64  tmvaReader_->AddVariable("lnPt_gsf",&lnPt_gsf);
65  tmvaReader_->AddVariable("Eta_gsf",&Eta_gsf);
66  tmvaReader_->AddVariable("dPtOverPt_gsf",&dPtOverPt_gsf);
67  tmvaReader_->AddVariable("DPtOverPt_gsf",&DPtOverPt_gsf);
68  //tmvaReader_->AddVariable("nhit_gsf",&nhit_gsf);
69  tmvaReader_->AddVariable("chi2_gsf",&chi2_gsf);
70  //tmvaReader_->AddVariable("DPtOverPt_kf",&DPtOverPt_kf);
71  tmvaReader_->AddVariable("nhit_kf",&nhit_kf);
72  tmvaReader_->AddVariable("chi2_kf",&chi2_kf);
73  tmvaReader_->AddVariable("EtotPinMode",&EtotPinMode);
74  tmvaReader_->AddVariable("EGsfPoutMode",&EGsfPoutMode);
75  tmvaReader_->AddVariable("EtotBremPinPoutMode",&EtotBremPinPoutMode);
76  tmvaReader_->AddVariable("DEtaGsfEcalClust",&DEtaGsfEcalClust);
77  tmvaReader_->AddVariable("SigmaEtaEta",&SigmaEtaEta);
78  tmvaReader_->AddVariable("HOverHE",&HOverHE);
79 // tmvaReader_->AddVariable("HOverPin",&HOverPin);
80  tmvaReader_->AddVariable("lateBrem",&lateBrem);
81  tmvaReader_->AddVariable("firstBrem",&firstBrem);
82  tmvaReader_->BookMVA("BDT",mvaWeightFileEleID.c_str());
83 }
85  std::vector<bool>& active,
86  const reco::Vertex & primaryVertex) {
87 
88  // the maps are initialized
89  AssMap associatedToGsf;
90  AssMap associatedToBrems;
91  AssMap associatedToEcal;
92 
93  // should be cleaned as often as often as possible
94  elCandidate_.clear();
95  electronExtra_.clear();
96  allElCandidate_.clear();
97  electronConstituents_.clear();
98  fifthStepKfTrack_.clear();
99  convGsfTrack_.clear();
100  // SetLinks finds all the elements (kf,ecal,ps,hcal,brems)
101  // associated to each gsf track
102  bool blockHasGSF = SetLinks(blockRef,associatedToGsf,
103  associatedToBrems,associatedToEcal,
104  active, primaryVertex);
105 
106  // check if there is at least a gsf track in the block.
107  if (blockHasGSF) {
108 
109  BDToutput_.clear();
110 
111  lockExtraKf_.clear();
112  // For each GSF track is initialized a BDT value = -1
113  BDToutput_.assign(associatedToGsf.size(),-1.);
114  lockExtraKf_.assign(associatedToGsf.size(),true);
115 
116  // The FinalID is run and BDToutput values is assigned
117  SetIDOutputs(blockRef,associatedToGsf,associatedToBrems,associatedToEcal,primaryVertex);
118 
119  // For each GSF track that pass the BDT configurable cut a pf candidate electron is created.
120  // This function finds also the best estimation of the initial electron 4-momentum.
121 
122  SetCandidates(blockRef,associatedToGsf,associatedToBrems,associatedToEcal);
123  if (elCandidate_.size() > 0 ){
124  isvalid_ = true;
125  // when a pfelectron candidate is created all the elements associated to the
126  // electron are locked.
127  SetActive(blockRef,associatedToGsf,associatedToBrems,associatedToEcal,active);
128  }
129  } // endif blockHasGSF
130 }
132  AssMap& associatedToGsf_,
133  AssMap& associatedToBrems_,
134  AssMap& associatedToEcal_,
135  std::vector<bool>& active,
136  const reco::Vertex & primaryVertex) {
137  unsigned int CutIndex = 100000;
138  double CutGSFECAL = 10000. ;
139  // no other cut are not used anymore. We use the default of PFBlockAlgo
140  //PFEnergyCalibration pfcalib_;
141  bool DebugSetLinksSummary = false;
142  bool DebugSetLinksDetailed = false;
143 
144  const reco::PFBlock& block = *blockRef;
146  PFBlock::LinkData linkData = block.linkData();
147 
148  bool IsThereAGSFTrack = false;
149  bool IsThereAGoodGSFTrack = false;
150 
151  vector<unsigned int> trackIs(0);
152  vector<unsigned int> gsfIs(0);
153  vector<unsigned int> ecalIs(0);
154 
155  std::vector<bool> localactive(elements.size(),true);
156 
157 
158  // Save the elements in shorter vectors like in PFAlgo.
159  std::multimap<double, unsigned int> kfElems;
160  for(unsigned int iEle=0; iEle<elements.size(); iEle++) {
161  localactive[iEle] = active[iEle];
162  bool thisIsAMuon = false;
163  PFBlockElement::Type type = elements[iEle].type();
164  switch( type ) {
165  case PFBlockElement::TRACK:
166  // Check if the track is already identified as a muon
167  thisIsAMuon = PFMuonAlgo::isMuon(elements[iEle]);
168  // Otherwise store index
169  if ( !thisIsAMuon && active[iEle] ) {
170  trackIs.push_back( iEle );
171  if (DebugSetLinksDetailed)
172  cout<<"TRACK, stored index, continue "<< iEle << endl;
173  }
174  continue;
175  case PFBlockElement::GSF:
176  // Check if the track has a KF partner identified as a muon
177  block.associatedElements( iEle,linkData,
178  kfElems,
181  thisIsAMuon = kfElems.size() ?
182  PFMuonAlgo::isMuon(elements[kfElems.begin()->second]) : false;
183  // Otherwise store index
184  if ( !thisIsAMuon && active[iEle] ) {
185  IsThereAGSFTrack = true;
186  gsfIs.push_back( iEle );
187  if (DebugSetLinksDetailed)
188  cout<<"GSF, stored index, continue "<< iEle << endl;
189  }
190  continue;
191  case PFBlockElement::ECAL:
192  if ( active[iEle] ) {
193  ecalIs.push_back( iEle );
194  if (DebugSetLinksDetailed)
195  cout<<"ECAL, stored index, continue "<< iEle << endl;
196  }
197  continue;
198  default:
199  continue;
200  }
201  }
202  // ******************* Start Link *****************************
203  // Do something only if a gsf track is found in the block
204  if(IsThereAGSFTrack) {
205 
206 
207  // LocalLock the Elements associated to a Kf tracks and not to a Gsf
208  // The clusters associated both to a kf track and to a brem tangend
209  // are then assigned only to the kf track
210  // Could be improved doing this after.
211 
212  // 19 Mar 2010 adding the KF track from Gamma Conv.
213  // They are linked to the GSF tracks they are not considered
214  // anymore in the following ecal cluster locking
215  if (DebugSetLinksDetailed) {
216  cout<<"#########################################################"<<endl;
217  cout<<"##### Process Block: #####"<<endl;
218  cout<<"#########################################################"<<endl;
219  cout<<block<<endl;
220  }
221 
222 
223  for(unsigned int iEle=0; iEle<trackIs.size(); iEle++) {
224  std::multimap<double, unsigned int> gsfElems;
225  block.associatedElements( trackIs[iEle], linkData,
226  gsfElems ,
229  if(gsfElems.size() == 0){
230  // This means that the considered kf is *not* associated
231  // to any gsf track
232  std::multimap<double, unsigned int> ecalKfElems;
233  block.associatedElements( trackIs[iEle],linkData,
234  ecalKfElems,
237  if(ecalKfElems.size() > 0) {
238  unsigned int ecalKf_index = ecalKfElems.begin()->second;
239  if(localactive[ecalKf_index]==true) {
240  // Check if this clusters is however well linked to a primary gsf track
241  // if this the case the cluster is not locked.
242 
243  bool isGsfLinked = false;
244  for(unsigned int iGsf=0; iGsf<gsfIs.size(); iGsf++) {
245  // if the ecal cluster is associated contemporary to a KF track
246  // and to a GSF track from conv, it is assigned to the KF track
247  // In this way we can loose some cluster but it is safer for double counting.
248  const reco::PFBlockElementGsfTrack * GsfEl =
249  dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[gsfIs[iGsf]]));
251 
252  std::multimap<double, unsigned int> ecalGsfElems;
253  block.associatedElements( gsfIs[iGsf],linkData,
254  ecalGsfElems,
257  if(ecalGsfElems.size() > 0) {
258  if (ecalGsfElems.begin()->second == ecalKf_index) {
259  isGsfLinked = true;
260  }
261  }
262  }
263  if(isGsfLinked == false) {
264  // add protection against energy loss because
265  // of the tracking fifth step
266  const reco::PFBlockElementTrack * kfEle =
267  dynamic_cast<const reco::PFBlockElementTrack*>((&elements[(trackIs[iEle])]));
268  reco::TrackRef refKf = kfEle->trackRef();
269 
270  int nexhits = refKf->hitPattern().numberOfLostHits(HitPattern::MISSING_INNER_HITS);
271 
273  if (refKf.isNonnull())
274  Algo = refKf->algo();
275 
276  bool trackIsFromPrimaryVertex = false;
277  for (Vertex::trackRef_iterator trackIt = primaryVertex.tracks_begin(); trackIt != primaryVertex.tracks_end(); ++trackIt) {
278  if ( (*trackIt).castTo<TrackRef>() == refKf ) {
279  trackIsFromPrimaryVertex = true;
280  break;
281  }
282  }
283 
284  if((Algo == reco::TrackBase::undefAlgorithm ||
285  Algo == reco::TrackBase::ctf ||
286  Algo == reco::TrackBase::rs ||
287  Algo == reco::TrackBase::cosmics ||
293  && nexhits == 0 && trackIsFromPrimaryVertex) {
294  localactive[ecalKf_index] = false;
295  } else {
296  fifthStepKfTrack_.push_back(make_pair(ecalKf_index,trackIs[iEle]));
297  }
298  }
299  }
300  }
301  } // gsfElems.size()
302  } // loop on kf tracks
303 
304 
305  // start loop on gsf tracks
306  for(unsigned int iEle=0; iEle<gsfIs.size(); iEle++) {
307 
308  if (!localactive[(gsfIs[iEle])]) continue;
309 
310  localactive[gsfIs[iEle]] = false;
311  bool ClosestEcalWithKf = false;
312 
313  if (DebugSetLinksDetailed) cout << " Gsf Index " << gsfIs[iEle] << endl;
314 
315  const reco::PFBlockElementGsfTrack * GsfEl =
316  dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[(gsfIs[iEle])]));
317 
318  // if GsfTrack fron converted bremsstralung continue
320  IsThereAGoodGSFTrack = true;
321  float eta_gsf = GsfEl->positionAtECALEntrance().eta();
322  float etaOut_gsf = GsfEl->Pout().eta();
323  float diffOutEcalEta = fabs(eta_gsf-etaOut_gsf);
324  reco::GsfTrackRef RefGSF = GsfEl->GsftrackRef();
325  float Pin_gsf = 0.01;
326  if (RefGSF.isNonnull() )
327  Pin_gsf = RefGSF->pMode();
328 
329 
330  // Find Associated Kf Track elements and Ecal to KF elements
331  unsigned int KfGsf_index = CutIndex;
332  unsigned int KfGsf_secondIndex = CutIndex;
333  std::multimap<double, unsigned int> kfElems;
334  block.associatedElements( gsfIs[iEle],linkData,
335  kfElems,
338  std::multimap<double, unsigned int> ecalKfElems;
339  if (kfElems.size() > 0) {
340  // 19 Mar 2010 now a loop is needed because > 1 KF track could
341  // be associated to the same GSF track
342 
343  for(std::multimap<double, unsigned int>::iterator itkf = kfElems.begin();
344  itkf != kfElems.end(); ++itkf) {
345  const reco::PFBlockElementTrack * TrkEl =
346  dynamic_cast<const reco::PFBlockElementTrack*>((&elements[itkf->second]));
347 
348  bool isPrim = isPrimaryTrack(*TrkEl,*GsfEl);
349  if(!isPrim)
350  continue;
351 
352  if(localactive[itkf->second] == true) {
353 
354  KfGsf_index = itkf->second;
355  localactive[KfGsf_index] = false;
356  // Find clusters associated to kftrack using linkbyrechit
357  block.associatedElements( KfGsf_index, linkData,
358  ecalKfElems ,
361  }
362  else {
363  KfGsf_secondIndex = itkf->second;
364  }
365  }
366  }
367 
368  // Find the closest Ecal clusters associated to this Gsf
369  std::multimap<double, unsigned int> ecalGsfElems;
370  block.associatedElements( gsfIs[iEle],linkData,
371  ecalGsfElems,
374  double ecalGsf_dist = CutGSFECAL;
375  unsigned int ClosestEcalGsf_index = CutIndex;
376  if (ecalGsfElems.size() > 0) {
377  if(localactive[(ecalGsfElems.begin()->second)] == true) {
378  // check energy compatibility for outer eta != ecal entrance, looping tracks
379  bool compatibleEPout = true;
380  if(diffOutEcalEta > 0.3) {
381  reco::PFClusterRef clusterRef = elements[(ecalGsfElems.begin()->second)].clusterRef();
382  float EoPout = (clusterRef->energy())/(GsfEl->Pout().t());
383  if(EoPout > 5)
384  compatibleEPout = false;
385  }
386  if(compatibleEPout) {
387  ClosestEcalGsf_index = ecalGsfElems.begin()->second;
388  ecalGsf_dist = block.dist(gsfIs[iEle],ClosestEcalGsf_index,
389  linkData,reco::PFBlock::LINKTEST_ALL);
390 
391  // Check that this cluster is not closer to another primary Gsf track
392 
393  std::multimap<double, unsigned int> ecalOtherGsfElems;
394  block.associatedElements( ClosestEcalGsf_index,linkData,
395  ecalOtherGsfElems,
398 
399  if(ecalOtherGsfElems.size()>0) {
400  // get if it is closed to a conv brem gsf tracks
401  const reco::PFBlockElementGsfTrack * gsfCheck =
402  dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[ecalOtherGsfElems.begin()->second]));
403 
404  if(ecalOtherGsfElems.begin()->second != gsfIs[iEle]&&
405  gsfCheck->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) == false) {
406  ecalGsf_dist = CutGSFECAL;
407  ClosestEcalGsf_index = CutIndex;
408  }
409  }
410  }
411  // do not lock at the moment we need this for the late brem
412  }
413  }
414  // if any cluster is found with the gsf-ecal link, try with kf-ecal
415  else if(ecalKfElems.size() > 0) {
416  if(localactive[(ecalKfElems.begin()->second)] == true) {
417  ClosestEcalGsf_index = ecalKfElems.begin()->second;
418  ecalGsf_dist = block.dist(gsfIs[iEle],ClosestEcalGsf_index,
419  linkData,reco::PFBlock::LINKTEST_ALL);
420  ClosestEcalWithKf = true;
421 
422  // Check if this cluster is not closer to another Gsf track
423  std::multimap<double, unsigned int> ecalOtherGsfElems;
424  block.associatedElements( ClosestEcalGsf_index,linkData,
425  ecalOtherGsfElems,
428  if(ecalOtherGsfElems.size() > 0) {
429  const reco::PFBlockElementGsfTrack * gsfCheck =
430  dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[ecalOtherGsfElems.begin()->second]));
431 
432  if(ecalOtherGsfElems.begin()->second != gsfIs[iEle] &&
434  ecalGsf_dist = CutGSFECAL;
435  ClosestEcalGsf_index = CutIndex;
436  ClosestEcalWithKf = false;
437  }
438  }
439  }
440  }
441 
442  if (DebugSetLinksDetailed)
443  cout << " Closest Ecal to the Gsf/Kf: index " << ClosestEcalGsf_index
444  << " dist " << ecalGsf_dist << endl;
445 
446 
447 
448  // Find the brems associated to this Gsf
449  std::multimap<double, unsigned int> bremElems;
450  block.associatedElements( gsfIs[iEle],linkData,
451  bremElems,
454 
455 
456  multimap<unsigned int,unsigned int> cleanedEcalBremElems;
457  vector<unsigned int> keyBremIndex(0);
458  unsigned int latestBrem_trajP = 0;
459  unsigned int latestBrem_index = CutIndex;
460  for(std::multimap<double, unsigned int>::iterator ieb = bremElems.begin();
461  ieb != bremElems.end(); ++ieb ) {
462  unsigned int brem_index = ieb->second;
463  if(localactive[brem_index] == false) continue;
464 
465 
466  // Find the ecal clusters associated to the brems
467  std::multimap<double, unsigned int> ecalBremsElems;
468 
469  block.associatedElements( brem_index, linkData,
470  ecalBremsElems,
473 
474  for (std::multimap<double, unsigned int>::iterator ie = ecalBremsElems.begin();
475  ie != ecalBremsElems.end();ie++) {
476  unsigned int ecalBrem_index = ie->second;
477  if(localactive[ecalBrem_index] == false) continue;
478 
479  //to be changed, using the distance
480  float ecalBrem_dist = block.dist(brem_index,ecalBrem_index,
481  linkData,reco::PFBlock::LINKTEST_ALL);
482 
483 
484  if (ecalBrem_index == ClosestEcalGsf_index && (ecalBrem_dist + 0.0012) > ecalGsf_dist) continue;
485 
486  // Find the closest brem
487  std::multimap<double, unsigned int> sortedBremElems;
488  block.associatedElements( ecalBrem_index,linkData,
489  sortedBremElems,
492  // check that this brem is that one coming from the same *primary* gsf
493  bool isGoodBrem = false;
494  unsigned int sortedBrem_index = CutIndex;
495  for (std::multimap<double, unsigned int>::iterator ibs = sortedBremElems.begin();
496  ibs != sortedBremElems.end();ibs++) {
497  unsigned int temp_sortedBrem_index = ibs->second;
498  std::multimap<double, unsigned int> sortedGsfElems;
499  block.associatedElements( temp_sortedBrem_index,linkData,
500  sortedGsfElems,
503  bool enteredInPrimaryGsf = false;
504  for (std::multimap<double, unsigned int>::iterator igs = sortedGsfElems.begin();
505  igs != sortedGsfElems.end();igs++) {
506  const reco::PFBlockElementGsfTrack * gsfCheck =
507  dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[igs->second]));
508 
509  if(gsfCheck->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) == false) {
510  if(igs->second == gsfIs[iEle]) {
511  isGoodBrem = true;
512  sortedBrem_index = temp_sortedBrem_index;
513  }
514  enteredInPrimaryGsf = true;
515  break;
516  }
517  }
518  if(enteredInPrimaryGsf)
519  break;
520  }
521 
522  if(isGoodBrem) {
523 
524  // Check that this cluster is not closer to another Gsf Track
525  // The check is not performed on KF track because the ecal clusters are aready locked.
526  std::multimap<double, unsigned int> ecalOtherGsfElems;
527  block.associatedElements( ecalBrem_index,linkData,
528  ecalOtherGsfElems,
531  if (ecalOtherGsfElems.size() > 0) {
532  const reco::PFBlockElementGsfTrack * gsfCheck =
533  dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[ecalOtherGsfElems.begin()->second]));
534  if(ecalOtherGsfElems.begin()->second != gsfIs[iEle] &&
536  continue;
537  }
538  }
539 
540  const reco::PFBlockElementBrem * BremEl =
541  dynamic_cast<const reco::PFBlockElementBrem*>((&elements[sortedBrem_index]));
542 
543  reco::PFClusterRef clusterRef =
544  elements[ecalBrem_index].clusterRef();
545 
546 
547  float sortedBremEcal_deta = fabs(clusterRef->position().eta() - BremEl->positionAtECALEntrance().eta());
548  // Triangular cut on plan chi2:deta -> OLD
549  //if((0.0075*sortedBremEcal_chi2 + 100.*sortedBremEcal_deta -1.5) < 0.) {
550  if(sortedBremEcal_deta < 0.015) {
551 
552  cleanedEcalBremElems.insert(pair<unsigned int,unsigned int>(sortedBrem_index,ecalBrem_index));
553 
554  unsigned int BremTrajP = BremEl->indTrajPoint();
555  if (BremTrajP > latestBrem_trajP) {
556  latestBrem_trajP = BremTrajP;
557  latestBrem_index = sortedBrem_index;
558  }
559  if (DebugSetLinksDetailed)
560  cout << " brem Index " << sortedBrem_index
561  << " associated cluster " << ecalBrem_index << " BremTrajP " << BremTrajP <<endl;
562 
563  // > 1 ecal clusters could be associated to the same brem twice: allowed N-1 link.
564  // But the brem need to be stored once.
565  // locallock the brem and the ecal clusters
566  localactive[ecalBrem_index] = false; // the cluster
567  bool alreadyfound = false;
568  for(unsigned int ii=0;ii<keyBremIndex.size();ii++) {
569  if (sortedBrem_index == keyBremIndex[ii]) alreadyfound = true;
570  }
571  if (alreadyfound == false) {
572  keyBremIndex.push_back(sortedBrem_index);
573  localactive[sortedBrem_index] = false; // the brem
574  }
575  }
576  }
577  }
578  }
579 
580 
581  // Find Possible Extra Cluster associated to the gsf/kf
582  vector<unsigned int> GsfElemIndex(0);
583  vector<unsigned int> EcalIndex(0);
584 
585  // locallock the ecal cluster associated to the gsf
586  if (ClosestEcalGsf_index < CutIndex) {
587  GsfElemIndex.push_back(ClosestEcalGsf_index);
588  localactive[ClosestEcalGsf_index] = false;
589  for (std::multimap<double, unsigned int>::iterator ii = ecalGsfElems.begin();
590  ii != ecalGsfElems.end();ii++) {
591  if(localactive[ii->second]) {
592  // Check that this cluster is not closer to another Gsf Track
593  std::multimap<double, unsigned int> ecalOtherGsfElems;
594  block.associatedElements( ii->second,linkData,
595  ecalOtherGsfElems,
598  if(ecalOtherGsfElems.size()) {
599  if(ecalOtherGsfElems.begin()->second != gsfIs[iEle]) continue;
600  }
601 
602  // get the cluster only if the deta (ecal-gsf) < 0.05
603  reco::PFClusterRef clusterRef = elements[(ii->second)].clusterRef();
604  float etacl = clusterRef->eta();
605  if( fabs(eta_gsf-etacl) < 0.05) {
606  GsfElemIndex.push_back(ii->second);
607  localactive[ii->second] = false;
608  if (DebugSetLinksDetailed)
609  cout << " ExtraCluster From Gsf " << ii->second << endl;
610  }
611  }
612  }
613  }
614 
615  //Add the possibility to link other ecal clusters from kf.
616 
617 // for (std::multimap<double, unsigned int>::iterator ii = ecalKfElems.begin();
618 // ii != ecalKfElems.end();ii++) {
619 // if(localactive[ii->second]) {
620 // // Check that this cluster is not closer to another Gsf Track
621 // std::multimap<double, unsigned int> ecalOtherGsfElems;
622 // block.associatedElements( ii->second,linkData,
623 // ecalOtherGsfElems,
624 // reco::PFBlockElement::GSF,
625 // reco::PFBlock::LINKTEST_CHI2);
626 // if(ecalOtherGsfElems.size()) {
627 // if(ecalOtherGsfElems.begin()->second != gsfIs[iEle]) continue;
628 // }
629 // GsfElemIndex.push_back(ii->second);
630 // reco::PFClusterRef clusterRef = elements[(ii->second)].clusterRef();
631 // float etacl = clusterRef->eta();
632 // if( fabs(eta_gsf-etacl) < 0.05) {
633 // localactive[ii->second] = false;
634 // if (DebugSetLinksDetailed)
635 // cout << " ExtraCluster From KF " << ii->second << endl;
636 // }
637 // }
638 // }
639 
640  //****************** Fill Maps *************************
641 
642  // The GsfMap
643 
644  // if any clusters have been associated to the gsf track
645  // use the Ecal clusters associated to the latest brem and associate it to the gsf
646  if(GsfElemIndex.size() == 0){
647  if(latestBrem_index < CutIndex) {
648  unsigned int ckey = cleanedEcalBremElems.count(latestBrem_index);
649  if(ckey == 1) {
650  unsigned int temp_cal =
651  cleanedEcalBremElems.find(latestBrem_index)->second;
652  GsfElemIndex.push_back(temp_cal);
653  if (DebugSetLinksDetailed)
654  cout << "******************** Gsf Cluster From Brem " << temp_cal
655  << " Latest Brem index " << latestBrem_index
656  << " ************************* " << endl;
657  }
658  else{
659  pair<multimap<unsigned int,unsigned int>::iterator,multimap<unsigned int,unsigned int>::iterator> ret;
660  ret = cleanedEcalBremElems.equal_range(latestBrem_index);
661  multimap<unsigned int,unsigned int>::iterator it;
662  for(it=ret.first; it!=ret.second; ++it) {
663  GsfElemIndex.push_back((*it).second);
664  if (DebugSetLinksDetailed)
665  cout << "******************** Gsf Cluster From Brem " << (*it).second
666  << " Latest Brem index " << latestBrem_index
667  << " ************************* " << endl;
668  }
669  }
670  // erase the brem.
671  unsigned int elToErase = 0;
672  for(unsigned int i = 0; i<keyBremIndex.size();i++) {
673  if(latestBrem_index == keyBremIndex[i]) {
674  elToErase = i;
675  }
676  }
677  keyBremIndex.erase(keyBremIndex.begin()+elToErase);
678  }
679  }
680 
681  // Get Extra Clusters from converted brem gsf tracks. The locallock method
682  // tells me if the ecal cluster has been already assigned to the primary
683  // gsf track or to a brem
684 
685  for(unsigned int iConv=0; iConv<gsfIs.size(); iConv++) {
686  if(iConv != iEle) {
687 
688  const reco::PFBlockElementGsfTrack * gsfConv =
689  dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[(gsfIs[iConv])]));
690 
691  // look at only to secondary gsf tracks
693  if (DebugSetLinksDetailed)
694  cout << " PFElectronAlgo:: I'm running on convGsfBrem " << endl;
695  // check if they are linked to the primary
696  float conv_dist = block.dist(gsfIs[iConv],gsfIs[iEle],
697  linkData,reco::PFBlock::LINKTEST_ALL);
698  if(conv_dist > 0.) {
699  // find the closest ecal cluster associated to conversions
700 
701  std::multimap<double, unsigned int> ecalConvElems;
702  block.associatedElements( gsfIs[iConv],linkData,
703  ecalConvElems,
706  if(ecalConvElems.size() > 0) {
707  // the ecal cluster is still active?
708  if(localactive[(ecalConvElems.begin()->second)] == true) {
709  if (DebugSetLinksDetailed)
710  cout << " PFElectronAlgo:: convGsfBrem has a ECAL cluster linked and free" << endl;
711  // Check that this cluster is not closer to another primary Gsf track
712  std::multimap<double, unsigned int> ecalOtherGsfPrimElems;
713  block.associatedElements( ecalConvElems.begin()->second,linkData,
714  ecalOtherGsfPrimElems,
717  if(ecalOtherGsfPrimElems.size()>0) {
718  unsigned int gsfprimcheck_index = ecalOtherGsfPrimElems.begin()->second;
719  const reco::PFBlockElementGsfTrack * gsfCheck =
720  dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[gsfprimcheck_index]));
721  if(gsfCheck->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) == false) continue;
722 
723  reco::PFClusterRef clusterRef = elements[ecalConvElems.begin()->second].clusterRef();
724  if (DebugSetLinksDetailed)
725  cout << " PFElectronAlgo: !!!!!!! convGsfBrem ECAL cluster has been stored !!!!!!! "
726  << " Energy " << clusterRef->energy() << " eta,phi " << clusterRef->position().eta()
727  <<", " << clusterRef->position().phi() << endl;
728 
729  GsfElemIndex.push_back(ecalConvElems.begin()->second);
730  convGsfTrack_.push_back(make_pair(ecalConvElems.begin()->second,gsfIs[iConv]));
731  localactive[ecalConvElems.begin()->second] = false;
732 
733  }
734  }
735  }
736  }
737  }
738  }
739  }
740 
741 
742 
743  EcalIndex.insert(EcalIndex.end(),GsfElemIndex.begin(),GsfElemIndex.end());
744 
745 
746 
747  // The BremMap
748  for(unsigned int i =0;i<keyBremIndex.size();i++) {
749  unsigned int ikey = keyBremIndex[i];
750  unsigned int ckey = cleanedEcalBremElems.count(ikey);
751  vector<unsigned int> BremElemIndex(0);
752  if(ckey == 1) {
753  unsigned int temp_cal =
754  cleanedEcalBremElems.find(ikey)->second;
755  BremElemIndex.push_back(temp_cal);
756  }
757  else{
758  pair<multimap<unsigned int,unsigned int>::iterator,multimap<unsigned int,unsigned int>::iterator> ret;
759  ret = cleanedEcalBremElems.equal_range(ikey);
760  multimap<unsigned int,unsigned int>::iterator it;
761  for(it=ret.first; it!=ret.second; ++it) {
762  BremElemIndex.push_back((*it).second);
763  }
764  }
765  EcalIndex.insert(EcalIndex.end(),BremElemIndex.begin(),BremElemIndex.end());
766  associatedToBrems_.insert(pair<unsigned int,vector<unsigned int> >(ikey,BremElemIndex));
767  }
768 
769 
770  // 19 Mar 2010: add KF and ECAL elements from converted brem photons
771  vector<unsigned int> convBremKFTrack;
772  convBremKFTrack.clear();
773  if (kfElems.size() > 0) {
774  for(std::multimap<double, unsigned int>::iterator itkf = kfElems.begin();
775  itkf != kfElems.end(); ++itkf) {
776  const reco::PFBlockElementTrack * TrkEl =
777  dynamic_cast<const reco::PFBlockElementTrack*>((&elements[itkf->second]));
778  bool isPrim = isPrimaryTrack(*TrkEl,*GsfEl);
779 
780  if(!isPrim) {
781 
782  // search for linked ECAL clusters
783  std::multimap<double, unsigned int> ecalConvElems;
784  block.associatedElements( itkf->second,linkData,
785  ecalConvElems,
788  if(ecalConvElems.size() > 0) {
789  // Further Cleaning: DANIELE This could be improved!
790  TrackRef trkRef = TrkEl->trackRef();
791  // iter0, iter1, iter2, iter3 = Algo < 3
792  unsigned int Algo = whichTrackAlgo(trkRef);
793 
794  float secpin = trkRef->p();
795 
796  const reco::PFBlockElementCluster * clust =
797  dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(ecalConvElems.begin()->second)]));
798  float eneclust =clust->clusterRef()->energy();
799 
800  //1) ******* Reject secondary KF tracks linked to also an HCAL cluster with H/(E+H) > 0.1
801  // This is applied also to KF linked to locked ECAL cluster
802  // NOTE: trusting the H/(E+H) and not the conv brem selection increse the number
803  // of charged hadrons around the electron. DANIELE? re-think about this.
804  std::multimap<double, unsigned int> hcalConvElems;
805  block.associatedElements( itkf->second,linkData,
806  hcalConvElems,
809 
810  bool isHoHE = false;
811  bool isHoE = false;
812  bool isPoHE = false;
813 
814  float enehcalclust = -1;
815  if(hcalConvElems.size() > 0) {
816  const reco::PFBlockElementCluster * clusthcal =
817  dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(hcalConvElems.begin()->second)]));
818  enehcalclust =clusthcal->clusterRef()->energy();
819  // NOTE: DANIELE? Are you sure you want to use the Algo type here?
820  if( (enehcalclust / (enehcalclust+eneclust) ) > 0.1 && Algo < 3) {
821  isHoHE = true;
822  if(enehcalclust > eneclust)
823  isHoE = true;
824  if(secpin > (enehcalclust+eneclust) )
825  isPoHE = true;
826  }
827  }
828 
829 
830  if(localactive[(ecalConvElems.begin()->second)] == false) {
831 
832  if(isHoE || isPoHE) {
833  if (DebugSetLinksDetailed)
834  cout << "PFElectronAlgo:: LOCKED ECAL REJECTED TRACK FOR H/E or P/(H+E) "
835  << " H/H+E " << enehcalclust/(enehcalclust+eneclust)
836  << " H/E " << enehcalclust/eneclust
837  << " P/(H+E) " << secpin/(enehcalclust+eneclust)
838  << " HCAL ENE " << enehcalclust
839  << " ECAL ENE " << eneclust
840  << " secPIN " << secpin
841  << " Algo Track " << Algo << endl;
842  continue;
843  }
844 
845  // check if this track has been alread assigned to an ECAL cluster
846  for(unsigned int iecal =0; iecal < EcalIndex.size(); iecal++) {
847  // in case this track is already assigned to a locked ECAL cluster
848  // the secondary kf track is also saved for further lock
849  if(EcalIndex[iecal] == ecalConvElems.begin()->second) {
850  if (DebugSetLinksDetailed)
851  cout << " PFElectronAlgo:: Conv Brem Recovery locked cluster and I will lock also the KF track " << endl;
852  convBremKFTrack.push_back(itkf->second);
853  }
854  }
855  }
856  else{
857  // ECAL cluster free
858 
859  //
860  if(isHoHE){
861  if (DebugSetLinksDetailed)
862  cout << "PFElectronAlgo:: FREE ECAL REJECTED TRACK FOR H/H+E "
863  << " H/H+E " << (enehcalclust / (enehcalclust+eneclust) )
864  << " H/E " << enehcalclust/eneclust
865  << " P/(H+E) " << secpin/(enehcalclust+eneclust)
866  << " HCAL ENE " << enehcalclust
867  << " ECAL ENE " << eneclust
868  << " secPIN " << secpin
869  << " Algo Track " << Algo << endl;
870  continue;
871  }
872 
873  // check that this cluster is not cluser to another KF track (primary)
874  std::multimap<double, unsigned int> ecalOtherKFPrimElems;
875  block.associatedElements( ecalConvElems.begin()->second,linkData,
876  ecalOtherKFPrimElems,
879  if(ecalOtherKFPrimElems.size() > 0) {
880 
881  // check that this ECAL clusters is the best associated to at least one of the KF tracks
882  // linked to the considered GSF track
883  bool isFromGSF = false;
884  for(std::multimap<double, unsigned int>::iterator itclos = kfElems.begin();
885  itclos != kfElems.end(); ++itclos) {
886  if(ecalOtherKFPrimElems.begin()->second == itclos->second) {
887  isFromGSF = true;
888  break;
889  }
890  }
891  if(isFromGSF){
892 
893  // Further Cleaning: DANIELE This could be improved!
894 
895 
896  float Epin = eneclust/secpin;
897 
898  // compute the pfsupercluster energy till now
899  float totenergy = 0.;
900  for(unsigned int ikeyecal = 0;
901  ikeyecal<EcalIndex.size(); ikeyecal++){
902  // EcalIndex can have the same cluster save twice (because of the late brem cluster).
903  bool foundcluster = false;
904  if(ikeyecal > 0) {
905  for(unsigned int i2 = 0; i2<ikeyecal-1; i2++) {
906  if(EcalIndex[ikeyecal] == EcalIndex[i2])
907  foundcluster = true;
908  }
909  }
910  if(foundcluster) continue;
911  const reco::PFBlockElementCluster * clusasso =
912  dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(EcalIndex[ikeyecal])]));
913  totenergy += clusasso->clusterRef()->energy();
914  }
915 
916  // Further Cleaning: DANIELE This could be improved!
917  //2) ***** Do not consider secondary tracks if the GSF and brems have failed in finding ECAL clusters
918  if(totenergy == 0.) {
919  if (DebugSetLinksDetailed)
920  cout << "PFElectronAlgo:: REJECTED_NULLTOT totenergy " << totenergy << endl;
921  continue;
922  }
923 
924  //3) ****** Reject secondary KF tracks that have an high E/secPin and that make worse the Etot/pin
925  if(Epin > 3) {
926  double res_before = fabs((totenergy-Pin_gsf)/Pin_gsf);
927  double res_after = fabs(((totenergy+eneclust)-Pin_gsf)/Pin_gsf);
928 
929  if(res_before < res_after) {
930  if (DebugSetLinksDetailed)
931  cout << "PFElectronAlgo::REJECTED_RES totenergy " << totenergy << " Pin_gsf " << Pin_gsf << " cluster to secondary " << eneclust
932  << " Res before " << res_before << " res_after " << res_after << endl;
933  continue;
934  }
935  }
936 
937  if (DebugSetLinksDetailed)
938  cout << "PFElectronAlgo:: conv brem found asso to ECAL linked to a secondary KF " << endl;
939  convBremKFTrack.push_back(itkf->second);
940  GsfElemIndex.push_back(ecalConvElems.begin()->second);
941  EcalIndex.push_back(ecalConvElems.begin()->second);
942  localactive[(ecalConvElems.begin()->second)] = false;
943  localactive[(itkf->second)] = false;
944  }
945  }
946  }
947  }
948  }
949  }
950  }
951 
952  // 4May import EG supercluster
953  if(EcalIndex.size() > 0 && useEGammaSupercluster_) {
954  double sumEtEcalInTheCone = 0.;
955 
956  // Position of the first cluster
957  const reco::PFBlockElementCluster * clust =
958  dynamic_cast<const reco::PFBlockElementCluster*>((&elements[EcalIndex[0]]));
959  double PhiFC = clust->clusterRef()->position().Phi();
960  double EtaFC = clust->clusterRef()->position().Eta();
961 
962  // Compute ECAL isolation ->
963  for(unsigned int iEcal=0; iEcal<ecalIs.size(); iEcal++) {
964  bool foundcluster = false;
965  for(unsigned int ikeyecal = 0;
966  ikeyecal<EcalIndex.size(); ikeyecal++){
967  if(ecalIs[iEcal] == EcalIndex[ikeyecal])
968  foundcluster = true;
969  }
970 
971  // -> only for clusters not already in the PFSCCluster
972  if(foundcluster == false) {
973  const reco::PFBlockElementCluster * clustExt =
974  dynamic_cast<const reco::PFBlockElementCluster*>((&elements[ecalIs[iEcal]]));
975  double eta_clust = clustExt->clusterRef()->position().Eta();
976  double phi_clust = clustExt->clusterRef()->position().Phi();
977  double theta_clust = clustExt->clusterRef()->position().Theta();
978  double deta_clust = eta_clust - EtaFC;
979  double dphi_clust = phi_clust - PhiFC;
980  if ( dphi_clust < -M_PI )
981  dphi_clust = dphi_clust + 2.*M_PI;
982  else if ( dphi_clust > M_PI )
983  dphi_clust = dphi_clust - 2.*M_PI;
984  double DR = sqrt(deta_clust*deta_clust+
985  dphi_clust*dphi_clust);
986 
987  //Jurassic veto in deta
988  if(fabs(deta_clust) > 0.05 && DR < coneEcalIsoForEgammaSC_) {
989  vector<double> ps1Ene(0);
990  vector<double> ps2Ene(0);
991  double ps1,ps2;
992  ps1=ps2=0.;
993  double EE_calib = thePFEnergyCalibration_->energyEm(*(clustExt->clusterRef()),ps1Ene,ps2Ene,ps1,ps2,applyCrackCorrections_);
994  double ET_calib = EE_calib*sin(theta_clust);
995  sumEtEcalInTheCone += ET_calib;
996  }
997  }
998  } //EndLoop Additional ECAL clusters in the block
999 
1000  // Compute track isolation: number of tracks && sumPt
1001  unsigned int sumNTracksInTheCone = 0;
1002  double sumPtTracksInTheCone = 0.;
1003  for(unsigned int iTrack=0; iTrack<trackIs.size(); iTrack++) {
1004  // the track from the electron are already locked at this stage
1005  if(localactive[(trackIs[iTrack])]==true) {
1006  const reco::PFBlockElementTrack * kfEle =
1007  dynamic_cast<const reco::PFBlockElementTrack*>((&elements[(trackIs[iTrack])]));
1008  reco::TrackRef trkref = kfEle->trackRef();
1009  if (trkref.isNonnull()) {
1010  double deta_trk = trkref->eta() - RefGSF->etaMode();
1011  double dphi_trk = trkref->phi() - RefGSF->phiMode();
1012  if ( dphi_trk < -M_PI )
1013  dphi_trk = dphi_trk + 2.*M_PI;
1014  else if ( dphi_trk > M_PI )
1015  dphi_trk = dphi_trk - 2.*M_PI;
1016  double DR = sqrt(deta_trk*deta_trk+
1017  dphi_trk*dphi_trk);
1018 
1019  int NValPixelHit = trkref->hitPattern().numberOfValidPixelHits();
1020 
1021  if(DR < coneTrackIsoForEgammaSC_ && NValPixelHit >=3) {
1022  sumNTracksInTheCone++;
1023  sumPtTracksInTheCone+=trkref->pt();
1024  }
1025  }
1026  }
1027  }
1028 
1029 
1030  bool isBarrelIsolated = false;
1031  if( fabs(EtaFC < 1.478) &&
1032  (sumEtEcalInTheCone < sumEtEcalIsoForEgammaSC_barrel_ &&
1033  (sumNTracksInTheCone < nTrackIsoForEgammaSC_ || sumPtTracksInTheCone < sumPtTrackIsoForEgammaSC_barrel_)))
1034  isBarrelIsolated = true;
1035 
1036 
1037  bool isEndcapIsolated = false;
1038  if( fabs(EtaFC >= 1.478) &&
1039  (sumEtEcalInTheCone < sumEtEcalIsoForEgammaSC_endcap_ &&
1040  (sumNTracksInTheCone < nTrackIsoForEgammaSC_ || sumPtTracksInTheCone < sumPtTrackIsoForEgammaSC_endcap_)))
1041  isEndcapIsolated = true;
1042 
1043 
1044  // only print out
1045  if(DebugSetLinksDetailed) {
1046  if(fabs(EtaFC < 1.478) && isBarrelIsolated == false) {
1047  cout << "**** PFElectronAlgo:: SUPERCLUSTER FOUND BUT FAILS ISOLATION:BARREL *** "
1048  << " sumEtEcalInTheCone " <<sumEtEcalInTheCone
1049  << " sumNTracksInTheCone " << sumNTracksInTheCone
1050  << " sumPtTracksInTheCone " << sumPtTracksInTheCone << endl;
1051  }
1052  if(fabs(EtaFC >= 1.478) && isEndcapIsolated == false) {
1053  cout << "**** PFElectronAlgo:: SUPERCLUSTER FOUND BUT FAILS ISOLATION:ENDCAP *** "
1054  << " sumEtEcalInTheCone " <<sumEtEcalInTheCone
1055  << " sumNTracksInTheCone " << sumNTracksInTheCone
1056  << " sumPtTracksInTheCone " << sumPtTracksInTheCone << endl;
1057  }
1058  }
1059 
1060 
1061 
1062 
1063  if(isBarrelIsolated || isEndcapIsolated ) {
1064 
1065 
1066  // Compute TotEnergy
1067  double totenergy = 0.;
1068  for(unsigned int ikeyecal = 0;
1069  ikeyecal<EcalIndex.size(); ikeyecal++){
1070  // EcalIndex can have the same cluster save twice (because of the late brem cluster).
1071  bool foundcluster = false;
1072  if(ikeyecal > 0) {
1073  for(unsigned int i2 = 0; i2<ikeyecal-1; i2++) {
1074  if(EcalIndex[ikeyecal] == EcalIndex[i2])
1075  foundcluster = true;;
1076  }
1077  }
1078  if(foundcluster) continue;
1079  const reco::PFBlockElementCluster * clusasso =
1080  dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(EcalIndex[ikeyecal])]));
1081  totenergy += clusasso->clusterRef()->energy();
1082  }
1083  // End copute TotEnergy
1084 
1085 
1086  // Find extra cluster from e/g importing
1087  for(unsigned int ikeyecal = 0;
1088  ikeyecal<EcalIndex.size(); ikeyecal++){
1089  // EcalIndex can have the same cluster save twice (because of the late brem cluster).
1090  bool foundcluster = false;
1091  if(ikeyecal > 0) {
1092  for(unsigned int i2 = 0; i2<ikeyecal-1; i2++) {
1093  if(EcalIndex[ikeyecal] == EcalIndex[i2])
1094  foundcluster = true;
1095  }
1096  }
1097  if(foundcluster) continue;
1098 
1099 
1100  std::multimap<double, unsigned int> ecalFromSuperClusterElems;
1101  block.associatedElements( EcalIndex[ikeyecal],linkData,
1102  ecalFromSuperClusterElems,
1105  if(ecalFromSuperClusterElems.size() > 0) {
1106  for(std::multimap<double, unsigned int>::iterator itsc = ecalFromSuperClusterElems.begin();
1107  itsc != ecalFromSuperClusterElems.end(); ++itsc) {
1108  if(localactive[itsc->second] == false) {
1109  continue;
1110  }
1111 
1112  std::multimap<double, unsigned int> ecalOtherKFPrimElems;
1113  block.associatedElements( itsc->second,linkData,
1114  ecalOtherKFPrimElems,
1117  if(ecalOtherKFPrimElems.size() > 0) {
1118  if(localactive[ecalOtherKFPrimElems.begin()->second] == true) {
1119  if (DebugSetLinksDetailed)
1120  cout << "**** PFElectronAlgo:: SUPERCLUSTER FOUND BUT FAILS KF VETO *** " << endl;
1121  continue;
1122  }
1123  }
1124  bool isInTheEtaRange = false;
1125  const reco::PFBlockElementCluster * clustToAdd =
1126  dynamic_cast<const reco::PFBlockElementCluster*>((&elements[itsc->second]));
1127  double deta_clustToAdd = clustToAdd->clusterRef()->position().Eta() - EtaFC;
1128  double ene_clustToAdd = clustToAdd->clusterRef()->energy();
1129 
1130  if(fabs(deta_clustToAdd) < 0.05)
1131  isInTheEtaRange = true;
1132 
1133  // check for both KF and GSF
1134  bool isBetterEpin = false;
1135  if(isInTheEtaRange == false ) {
1136  if (DebugSetLinksDetailed)
1137  cout << "**** PFElectronAlgo:: SUPERCLUSTER FOUND BUT FAILS GAMMA DETA RANGE *** "
1138  << fabs(deta_clustToAdd) << endl;
1139 
1140  if(KfGsf_index < CutIndex) {
1141  //GSF
1142  double res_before_gsf = fabs((totenergy-Pin_gsf)/Pin_gsf);
1143  double res_after_gsf = fabs(((totenergy+ene_clustToAdd)-Pin_gsf)/Pin_gsf);
1144 
1145  //KF
1146  const reco::PFBlockElementTrack * trackEl =
1147  dynamic_cast<const reco::PFBlockElementTrack*>((&elements[KfGsf_index]));
1148  double Pin_kf = trackEl->trackRef()->p();
1149  double res_before_kf = fabs((totenergy-Pin_kf)/Pin_kf);
1150  double res_after_kf = fabs(((totenergy+ene_clustToAdd)-Pin_kf)/Pin_kf);
1151 
1152  // The new cluster improve both the E/pin?
1153  if(res_after_gsf < res_before_gsf && res_after_kf < res_before_kf ) {
1154  isBetterEpin = true;
1155  }
1156  else {
1157  if (DebugSetLinksDetailed)
1158  cout << "**** PFElectronAlgo:: SUPERCLUSTER FOUND AND FAILS ALSO RES_EPIN"
1159  << " tot energy " << totenergy
1160  << " Pin_gsf " << Pin_gsf
1161  << " Pin_kf " << Pin_kf
1162  << " cluster from SC to ADD " << ene_clustToAdd
1163  << " Res before GSF " << res_before_gsf << " res_after_gsf " << res_after_gsf
1164  << " Res before KF " << res_before_kf << " res_after_kf " << res_after_kf << endl;
1165  }
1166  }
1167  }
1168 
1169  if(isInTheEtaRange || isBetterEpin) {
1170  if (DebugSetLinksDetailed)
1171  cout << "!!!! PFElectronAlgo:: ECAL from SUPERCLUSTER FOUND !!!!! " << endl;
1172  GsfElemIndex.push_back(itsc->second);
1173  EcalIndex.push_back(itsc->second);
1174  localactive[(itsc->second)] = false;
1175  }
1176  }
1177  }
1178  }
1179  } // END ISOLATION IF
1180  }
1181 
1182 
1183  if(KfGsf_index < CutIndex)
1184  GsfElemIndex.push_back(KfGsf_index);
1185  else if(KfGsf_secondIndex < CutIndex)
1186  GsfElemIndex.push_back(KfGsf_secondIndex);
1187 
1188  // insert the secondary KF tracks
1189  GsfElemIndex.insert(GsfElemIndex.end(),convBremKFTrack.begin(),convBremKFTrack.end());
1190  GsfElemIndex.insert(GsfElemIndex.end(),keyBremIndex.begin(),keyBremIndex.end());
1191  associatedToGsf_.insert(pair<unsigned int, vector<unsigned int> >(gsfIs[iEle],GsfElemIndex));
1192 
1193  // The EcalMap
1194  for(unsigned int ikeyecal = 0;
1195  ikeyecal<EcalIndex.size(); ikeyecal++){
1196 
1197 
1198  vector<unsigned int> EcalElemsIndex(0);
1199 
1200  std::multimap<double, unsigned int> PS1Elems;
1201  block.associatedElements( EcalIndex[ikeyecal],linkData,
1202  PS1Elems,
1205  for( std::multimap<double, unsigned int>::iterator it = PS1Elems.begin();
1206  it != PS1Elems.end();it++) {
1207  unsigned int index = it->second;
1208  if(localactive[index] == true) {
1209 
1210  // Check that this cluster is not closer to another ECAL cluster
1211  std::multimap<double, unsigned> sortedECAL;
1212  block.associatedElements( index, linkData,
1213  sortedECAL,
1216  unsigned jEcal = sortedECAL.begin()->second;
1217  if ( jEcal != EcalIndex[ikeyecal]) continue;
1218 
1219 
1220  EcalElemsIndex.push_back(index);
1221  localactive[index] = false;
1222  }
1223  }
1224 
1225  std::multimap<double, unsigned int> PS2Elems;
1226  block.associatedElements( EcalIndex[ikeyecal],linkData,
1227  PS2Elems,
1230  for( std::multimap<double, unsigned int>::iterator it = PS2Elems.begin();
1231  it != PS2Elems.end();it++) {
1232  unsigned int index = it->second;
1233  if(localactive[index] == true) {
1234  // Check that this cluster is not closer to another ECAL cluster
1235  std::multimap<double, unsigned> sortedECAL;
1236  block.associatedElements( index, linkData,
1237  sortedECAL,
1240  unsigned jEcal = sortedECAL.begin()->second;
1241  if ( jEcal != EcalIndex[ikeyecal]) continue;
1242 
1243  EcalElemsIndex.push_back(index);
1244  localactive[index] = false;
1245  }
1246  }
1247  if(ikeyecal == 0) {
1248  // The first cluster is that one coming from the Gsf.
1249  // Only for this one is found the HCAL cluster using the Track-HCAL link
1250  // and not the Ecal-Hcal not well tested yet.
1251  std::multimap<double, unsigned int> hcalGsfElems;
1252  block.associatedElements( gsfIs[iEle],linkData,
1253  hcalGsfElems,
1256  for( std::multimap<double, unsigned int>::iterator it = hcalGsfElems.begin();
1257  it != hcalGsfElems.end();it++) {
1258  unsigned int index = it->second;
1259  // if(localactive[index] == true) {
1260 
1261  // Check that this cluster is not closer to another GSF
1262  // remove in high energetic jets this is dangerous.
1263 // std::multimap<double, unsigned> sortedGsf;
1264 // block.associatedElements( index, linkData,
1265 // sortedGsf,
1266 // reco::PFBlockElement::GSF,
1267 // reco::PFBlock::LINKTEST_ALL );
1268 // unsigned jGsf = sortedGsf.begin()->second;
1269 // if ( jGsf != gsfIs[iEle]) continue;
1270 
1271  EcalElemsIndex.push_back(index);
1272  localactive[index] = false;
1273 
1274  // }
1275  }
1276  // if the closest ecal cluster has been link with the KF, check KF - HCAL link
1277  if(hcalGsfElems.size() == 0 && ClosestEcalWithKf == true) {
1278  std::multimap<double, unsigned int> hcalKfElems;
1279  block.associatedElements( KfGsf_index,linkData,
1280  hcalKfElems,
1283  for( std::multimap<double, unsigned int>::iterator it = hcalKfElems.begin();
1284  it != hcalKfElems.end();it++) {
1285  unsigned int index = it->second;
1286  if(localactive[index] == true) {
1287 
1288  // Check that this cluster is not closer to another KF
1289  std::multimap<double, unsigned> sortedKf;
1290  block.associatedElements( index, linkData,
1291  sortedKf,
1294  unsigned jKf = sortedKf.begin()->second;
1295  if ( jKf != KfGsf_index) continue;
1296  EcalElemsIndex.push_back(index);
1297  localactive[index] = false;
1298  }
1299  }
1300  }
1301  // Find Other Primary Tracks Associated to the same Gsf Clusters
1302  std::multimap<double, unsigned int> kfEtraElems;
1303  block.associatedElements( EcalIndex[ikeyecal],linkData,
1304  kfEtraElems,
1307  if(kfEtraElems.size() > 0) {
1308  for( std::multimap<double, unsigned int>::iterator it = kfEtraElems.begin();
1309  it != kfEtraElems.end();it++) {
1310  unsigned int index = it->second;
1311 
1312  // 19 Mar 2010 do not consider here tracks from gamma conv
1313  // const reco::PFBlockElementTrack * kfTk =
1314  // dynamic_cast<const reco::PFBlockElementTrack*>((&elements[index]));
1315  // DANIELE ? It is not need because of the local locking
1316  // if(kfTk->isLinkedToDisplacedVertex()) continue;
1317 
1318  bool thisIsAMuon = false;
1319  thisIsAMuon = PFMuonAlgo::isMuon(elements[index]);
1320  if (DebugSetLinksDetailed && thisIsAMuon)
1321  cout << " This is a Muon: index " << index << endl;
1322  if(localactive[index] == true && !thisIsAMuon) {
1323  if(index != KfGsf_index) {
1324  // Check that this track is not closer to another ECAL cluster
1325  // Not Sure here I need this step
1326  std::multimap<double, unsigned> sortedECAL;
1327  block.associatedElements( index, linkData,
1328  sortedECAL,
1331  unsigned jEcal = sortedECAL.begin()->second;
1332  if ( jEcal != EcalIndex[ikeyecal]) continue;
1333  EcalElemsIndex.push_back(index);
1334  localactive[index] = false;
1335  }
1336  }
1337  }
1338  }
1339 
1340  }
1341  associatedToEcal_.insert(pair<unsigned int,vector<unsigned int> >(EcalIndex[ikeyecal],EcalElemsIndex));
1342  }
1343  }// end type GSF
1344  } // endis there a gsf track
1345 
1346  // ******************* End Link *****************************
1347 
1348  //
1349  // Below is only for debugging printout
1350  if (DebugSetLinksSummary) {
1351  if(IsThereAGoodGSFTrack) {
1352  if (DebugSetLinksSummary) cout << " -- The Link Summary --" << endl;
1353  for(map<unsigned int,vector<unsigned int> >::iterator it = associatedToGsf_.begin();
1354  it != associatedToGsf_.end(); it++) {
1355 
1356  if (DebugSetLinksSummary) cout << " AssoGsf " << it->first << endl;
1357  vector<unsigned int> eleasso = it->second;
1358  for(unsigned int i=0;i<eleasso.size();i++) {
1359  PFBlockElement::Type type = elements[eleasso[i]].type();
1360  if(type == reco::PFBlockElement::BREM) {
1361  if (DebugSetLinksSummary)
1362  cout << " AssoGsfElements BREM " << eleasso[i] << endl;
1363  }
1364  else if(type == reco::PFBlockElement::ECAL) {
1365  if (DebugSetLinksSummary)
1366  cout << " AssoGsfElements ECAL " << eleasso[i] << endl;
1367  }
1368  else if(type == reco::PFBlockElement::TRACK) {
1369  if (DebugSetLinksSummary)
1370  cout << " AssoGsfElements KF " << eleasso[i] << endl;
1371  }
1372  else {
1373  if (DebugSetLinksSummary)
1374  cout << " AssoGsfElements ????? " << eleasso[i] << endl;
1375  }
1376  }
1377  }
1378 
1379  for(map<unsigned int,vector<unsigned int> >::iterator it = associatedToBrems_.begin();
1380  it != associatedToBrems_.end(); it++) {
1381  if (DebugSetLinksSummary) cout << " AssoBrem " << it->first << endl;
1382  vector<unsigned int> eleasso = it->second;
1383  for(unsigned int i=0;i<eleasso.size();i++) {
1384  PFBlockElement::Type type = elements[eleasso[i]].type();
1385  if(type == reco::PFBlockElement::ECAL) {
1386  if (DebugSetLinksSummary)
1387  cout << " AssoBremElements ECAL " << eleasso[i] << endl;
1388  }
1389  else {
1390  if (DebugSetLinksSummary)
1391  cout << " AssoBremElements ????? " << eleasso[i] << endl;
1392  }
1393  }
1394  }
1395 
1396  for(map<unsigned int,vector<unsigned int> >::iterator it = associatedToEcal_.begin();
1397  it != associatedToEcal_.end(); it++) {
1398  if (DebugSetLinksSummary) cout << " AssoECAL " << it->first << endl;
1399  vector<unsigned int> eleasso = it->second;
1400  for(unsigned int i=0;i<eleasso.size();i++) {
1401  PFBlockElement::Type type = elements[eleasso[i]].type();
1402  if(type == reco::PFBlockElement::PS1) {
1403  if (DebugSetLinksSummary)
1404  cout << " AssoECALElements PS1 " << eleasso[i] << endl;
1405  }
1406  else if(type == reco::PFBlockElement::PS2) {
1407  if (DebugSetLinksSummary)
1408  cout << " AssoECALElements PS2 " << eleasso[i] << endl;
1409  }
1410  else if(type == reco::PFBlockElement::HCAL) {
1411  if (DebugSetLinksSummary)
1412  cout << " AssoECALElements HCAL " << eleasso[i] << endl;
1413  }
1414  else {
1415  if (DebugSetLinksSummary)
1416  cout << " AssoHCALElements ????? " << eleasso[i] << endl;
1417  }
1418  }
1419  }
1420  if (DebugSetLinksSummary)
1421  cout << "-- End Summary --" << endl;
1422  }
1423 
1424  }
1425  // EndPrintOut
1426  return IsThereAGoodGSFTrack;
1427 }
1428 // This function get the associatedToGsf and associatedToBrems maps and run the final electronID.
1430  AssMap& associatedToGsf_,
1431  AssMap& associatedToBrems_,
1432  AssMap& associatedToEcal_,
1433  const reco::Vertex & primaryVertex){
1434  //PFEnergyCalibration pfcalib_;
1435  const reco::PFBlock& block = *blockRef;
1436  PFBlock::LinkData linkData = block.linkData();
1438  bool DebugIDOutputs = false;
1439  if(DebugIDOutputs) cout << " ######## Enter in SetIDOutputs #########" << endl;
1440 
1441  unsigned int cgsf=0;
1442  for (map<unsigned int,vector<unsigned int> >::iterator igsf = associatedToGsf_.begin();
1443  igsf != associatedToGsf_.end(); igsf++,cgsf++) {
1444 
1445  float Ene_ecalgsf = 0.;
1446  float Ene_hcalgsf = 0.;
1447  double sigmaEtaEta = 0.;
1448  float deta_gsfecal = 0.;
1449  float Ene_ecalbrem = 0.;
1450  float Ene_extraecalgsf = 0.;
1451  bool LateBrem = false;
1452  // bool EarlyBrem = false;
1453  int FirstBrem = 1000;
1454  unsigned int ecalGsf_index = 100000;
1455  unsigned int kf_index = 100000;
1456  // unsigned int nhits_gsf = 0;
1457  int NumBrem = 0;
1458  reco::TrackRef RefKF;
1459  double posX=0.;
1460  double posY=0.;
1461  double posZ=0.;
1462 
1463  unsigned int gsf_index = igsf->first;
1464  const reco::PFBlockElementGsfTrack * GsfEl =
1465  dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[gsf_index]));
1466  reco::GsfTrackRef RefGSF = GsfEl->GsftrackRef();
1467  float Ein_gsf = 0.;
1468  if (RefGSF.isNonnull()) {
1469  float m_el=0.00051;
1470  Ein_gsf =sqrt(RefGSF->pMode()*
1471  RefGSF->pMode()+m_el*m_el);
1472  // nhits_gsf = RefGSF->hitPattern().trackerLayersWithMeasurement();
1473  }
1474  float Eout_gsf = GsfEl->Pout().t();
1475  float Etaout_gsf = GsfEl->positionAtECALEntrance().eta();
1476 
1477 
1478  if (DebugIDOutputs)
1479  cout << " setIdOutput! GSF Track: Ein " << Ein_gsf
1480  << " eta,phi " << Etaout_gsf
1481  <<", " << GsfEl->positionAtECALEntrance().phi() << endl;
1482 
1483 
1484  vector<unsigned int> assogsf_index = igsf->second;
1485  bool FirstEcalGsf = true;
1486  for (unsigned int ielegsf=0;ielegsf<assogsf_index.size();ielegsf++) {
1487  PFBlockElement::Type assoele_type = elements[(assogsf_index[ielegsf])].type();
1488 
1489 
1490  // The RefKf is needed to build pure tracking observables
1491  if(assoele_type == reco::PFBlockElement::TRACK) {
1492  const reco::PFBlockElementTrack * KfTk =
1493  dynamic_cast<const reco::PFBlockElementTrack*>((&elements[(assogsf_index[ielegsf])]));
1494  // 19 Mar 2010 do not consider here track from gamma conv
1495 
1496  bool isPrim = isPrimaryTrack(*KfTk,*GsfEl);
1497  if(!isPrim) continue;
1498  RefKF = KfTk->trackRef();
1499  kf_index = assogsf_index[ielegsf];
1500  }
1501 
1502 
1503  if (assoele_type == reco::PFBlockElement::ECAL) {
1504  unsigned int keyecalgsf = assogsf_index[ielegsf];
1505  vector<unsigned int> assoecalgsf_index = associatedToEcal_.find(keyecalgsf)->second;
1506 
1507  vector<double> ps1Ene(0);
1508  vector<double> ps2Ene(0);
1509  for(unsigned int ips =0; ips<assoecalgsf_index.size();ips++) {
1510  PFBlockElement::Type typeassoecal = elements[(assoecalgsf_index[ips])].type();
1511  if (typeassoecal == reco::PFBlockElement::PS1) {
1512  PFClusterRef psref = elements[(assoecalgsf_index[ips])].clusterRef();
1513  ps1Ene.push_back(psref->energy());
1514  }
1515  if (typeassoecal == reco::PFBlockElement::PS2) {
1516  PFClusterRef psref = elements[(assoecalgsf_index[ips])].clusterRef();
1517  ps2Ene.push_back(psref->energy());
1518  }
1519  if (typeassoecal == reco::PFBlockElement::HCAL) {
1520  const reco::PFBlockElementCluster * clust =
1521  dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(assoecalgsf_index[ips])]));
1522  Ene_hcalgsf+=clust->clusterRef()->energy();
1523  }
1524  }
1525  if (FirstEcalGsf) {
1526  FirstEcalGsf = false;
1527  ecalGsf_index = assogsf_index[ielegsf];
1528  reco::PFClusterRef clusterRef = elements[(assogsf_index[ielegsf])].clusterRef();
1529  double ps1,ps2;
1530  ps1=ps2=0.;
1531  // Ene_ecalgsf = pfcalib_.energyEm(*clusterRef,ps1Ene,ps2Ene);
1532  Ene_ecalgsf = thePFEnergyCalibration_->energyEm(*clusterRef,ps1Ene,ps2Ene,ps1,ps2,applyCrackCorrections_);
1533  // std::cout << "Test " << Ene_ecalgsf << " PS1 / PS2 " << ps1 << " " << ps2 << std::endl;
1534  posX += Ene_ecalgsf * clusterRef->position().X();
1535  posY += Ene_ecalgsf * clusterRef->position().Y();
1536  posZ += Ene_ecalgsf * clusterRef->position().Z();
1537 
1538  if (DebugIDOutputs)
1539  cout << " setIdOutput! GSF ECAL Cluster E " << Ene_ecalgsf
1540  << " eta,phi " << clusterRef->position().eta()
1541  <<", " << clusterRef->position().phi() << endl;
1542 
1543  deta_gsfecal = clusterRef->position().eta() - Etaout_gsf;
1544 
1545  vector< const reco::PFCluster * > pfClust_vec(0);
1546  pfClust_vec.clear();
1547  pfClust_vec.push_back(&(*clusterRef));
1548 
1549  PFClusterWidthAlgo pfwidth(pfClust_vec);
1550  sigmaEtaEta = pfwidth.pflowSigmaEtaEta();
1551 
1552 
1553  }
1554  else {
1555  reco::PFClusterRef clusterRef = elements[(assogsf_index[ielegsf])].clusterRef();
1556  float TempClus_energy = thePFEnergyCalibration_->energyEm(*clusterRef,ps1Ene,ps2Ene,applyCrackCorrections_);
1557  Ene_extraecalgsf += TempClus_energy;
1558  posX += TempClus_energy * clusterRef->position().X();
1559  posY += TempClus_energy * clusterRef->position().Y();
1560  posZ += TempClus_energy * clusterRef->position().Z();
1561 
1562  if (DebugIDOutputs)
1563  cout << " setIdOutput! Extra ECAL Cluster E "
1564  << TempClus_energy << " Tot " << Ene_extraecalgsf << endl;
1565  }
1566  } // end type Ecal
1567 
1568 
1569  if (assoele_type == reco::PFBlockElement::BREM) {
1570  unsigned int brem_index = assogsf_index[ielegsf];
1571  const reco::PFBlockElementBrem * BremEl =
1572  dynamic_cast<const reco::PFBlockElementBrem*>((&elements[brem_index]));
1573  int TrajPos = (BremEl->indTrajPoint())-2;
1574  //if (TrajPos <= 3) EarlyBrem = true;
1575  if (TrajPos < FirstBrem) FirstBrem = TrajPos;
1576 
1577  vector<unsigned int> assobrem_index = associatedToBrems_.find(brem_index)->second;
1578  for (unsigned int ibrem = 0; ibrem < assobrem_index.size(); ibrem++){
1579  if (elements[(assobrem_index[ibrem])].type() == reco::PFBlockElement::ECAL) {
1580  unsigned int keyecalbrem = assobrem_index[ibrem];
1581  vector<unsigned int> assoelebrem_index = associatedToEcal_.find(keyecalbrem)->second;
1582  vector<double> ps1EneFromBrem(0);
1583  vector<double> ps2EneFromBrem(0);
1584  for (unsigned int ielebrem=0; ielebrem<assoelebrem_index.size();ielebrem++) {
1585  if (elements[(assoelebrem_index[ielebrem])].type() == reco::PFBlockElement::PS1) {
1586  PFClusterRef psref = elements[(assoelebrem_index[ielebrem])].clusterRef();
1587  ps1EneFromBrem.push_back(psref->energy());
1588  }
1589  if (elements[(assoelebrem_index[ielebrem])].type() == reco::PFBlockElement::PS2) {
1590  PFClusterRef psref = elements[(assoelebrem_index[ielebrem])].clusterRef();
1591  ps2EneFromBrem.push_back(psref->energy());
1592  }
1593  }
1594  // check if it is a compatible cluster also with the gsf track
1595  if( assobrem_index[ibrem] != ecalGsf_index) {
1596  reco::PFClusterRef clusterRef =
1597  elements[(assobrem_index[ibrem])].clusterRef();
1598  float BremClus_energy = thePFEnergyCalibration_->energyEm(*clusterRef,ps1EneFromBrem,ps2EneFromBrem,applyCrackCorrections_);
1599  Ene_ecalbrem += BremClus_energy;
1600  posX += BremClus_energy * clusterRef->position().X();
1601  posY += BremClus_energy * clusterRef->position().Y();
1602  posZ += BremClus_energy * clusterRef->position().Z();
1603 
1604  NumBrem++;
1605  if (DebugIDOutputs) cout << " setIdOutput::BREM Cluster "
1606  << BremClus_energy << " eta,phi "
1607  << clusterRef->position().eta() <<", "
1608  << clusterRef->position().phi() << endl;
1609  }
1610  else {
1611  LateBrem = true;
1612  }
1613  }
1614  }
1615  }
1616  }
1617  if (Ene_ecalgsf > 0.) {
1618  // here build the new BDT observables
1619 
1620  // ***** Normalization observables ****
1621  if(RefGSF.isNonnull()) {
1622  PFCandidateElectronExtra myExtra(RefGSF) ;
1623  myExtra.setGsfTrackPout(GsfEl->Pout());
1624  myExtra.setKfTrackRef(RefKF);
1625  float Pt_gsf = RefGSF->ptMode();
1626  lnPt_gsf = log(Pt_gsf);
1627  Eta_gsf = RefGSF->etaMode();
1628 
1629  // **** Pure tracking observables.
1630  if(RefGSF->ptModeError() > 0.)
1631  dPtOverPt_gsf = RefGSF->ptModeError()/Pt_gsf;
1632 
1633  nhit_gsf= RefGSF->hitPattern().trackerLayersWithMeasurement();
1634  chi2_gsf = RefGSF->normalizedChi2();
1635  // change GsfEl->Pout().pt() as soon the PoutMode is on the GsfTrack DataFormat
1636  DPtOverPt_gsf = (RefGSF->ptMode() - GsfEl->Pout().pt())/RefGSF->ptMode();
1637 
1638 
1639  nhit_kf = 0;
1640  chi2_kf = -0.01;
1641  DPtOverPt_kf = -0.01;
1642  if (RefKF.isNonnull()) {
1643  nhit_kf= RefKF->hitPattern().trackerLayersWithMeasurement();
1644  chi2_kf = RefKF->normalizedChi2();
1645  // Not used, strange behaviour to be checked. And Kf->OuterPt is
1646  // in track extra.
1647  //DPtOverPt_kf =
1648  // (RefKF->pt() - RefKF->outerPt())/RefKF->pt();
1649 
1650  }
1651 
1652  // **** Tracker-Ecal-Hcal observables
1653  EtotPinMode = (Ene_ecalgsf + Ene_ecalbrem + Ene_extraecalgsf) / Ein_gsf;
1654  EGsfPoutMode = Ene_ecalgsf/Eout_gsf;
1655  EtotBremPinPoutMode = Ene_ecalbrem /(Ein_gsf - Eout_gsf);
1656  DEtaGsfEcalClust = fabs(deta_gsfecal);
1657  myExtra.setSigmaEtaEta(sigmaEtaEta);
1658  myExtra.setDeltaEta(DEtaGsfEcalClust);
1659  SigmaEtaEta = log(sigmaEtaEta);
1660 
1661  lateBrem = -1;
1662  firstBrem = -1;
1663  earlyBrem = -1;
1664  if(NumBrem > 0) {
1665  if (LateBrem) lateBrem = 1;
1666  else lateBrem = 0;
1667  firstBrem = FirstBrem;
1668  if(FirstBrem < 4) earlyBrem = 1;
1669  else earlyBrem = 0;
1670  }
1671 
1672  HOverHE = Ene_hcalgsf/(Ene_hcalgsf + Ene_ecalgsf);
1673  HOverPin = Ene_hcalgsf / Ein_gsf;
1674  myExtra.setHadEnergy(Ene_hcalgsf);
1675  myExtra.setEarlyBrem(earlyBrem);
1676  myExtra.setLateBrem(lateBrem);
1677  // std::cout<< " Inserting in extra " << electronExtra_.size() << std::endl;
1678 
1679  // Put cuts and access the BDT output
1680  if(DPtOverPt_gsf < -0.2) DPtOverPt_gsf = -0.2;
1681  if(DPtOverPt_gsf > 1.) DPtOverPt_gsf = 1.;
1682 
1683  if(dPtOverPt_gsf > 0.3) dPtOverPt_gsf = 0.3;
1684 
1685  if(chi2_gsf > 10.) chi2_gsf = 10.;
1686 
1687  if(DPtOverPt_kf < -0.2) DPtOverPt_kf = -0.2;
1688  if(DPtOverPt_kf > 1.) DPtOverPt_kf = 1.;
1689 
1690  if(chi2_kf > 10.) chi2_kf = 10.;
1691 
1692  if(EtotPinMode < 0.) EtotPinMode = 0.;
1693  if(EtotPinMode > 5.) EtotPinMode = 5.;
1694 
1695  if(EGsfPoutMode < 0.) EGsfPoutMode = 0.;
1696  if(EGsfPoutMode > 5.) EGsfPoutMode = 5.;
1697 
1698  if(EtotBremPinPoutMode < 0.) EtotBremPinPoutMode = 0.01;
1700 
1701  if(DEtaGsfEcalClust > 0.1) DEtaGsfEcalClust = 0.1;
1702 
1703  if(SigmaEtaEta < -14) SigmaEtaEta = -14;
1704 
1705  if(HOverPin < 0.) HOverPin = 0.;
1706  if(HOverPin > 5.) HOverPin = 5.;
1707  double mvaValue = tmvaReader_->EvaluateMVA("BDT");
1708 
1709  // add output observables
1710  BDToutput_[cgsf] = mvaValue;
1711  myExtra.setMVA(mvaValue);
1712  electronExtra_.push_back(myExtra);
1713 
1714 
1715  // IMPORTANT Additional conditions
1716  if(mvaValue > mvaEleCut_) {
1717  // Check if the ecal cluster is isolated.
1718  //
1719  // If there is at least one extra track and H/H+E > 0.05 or SumP(ExtraKf)/EGsf or
1720  // #Tracks > 3 I leave this job to PFAlgo, otherwise I lock those extra tracks.
1721  // Note:
1722  // The tracks coming from the 4 step of the iterative tracking are not considered,
1723  // because they can come from secondary converted brems.
1724  // They are locked to avoid double counting.
1725  // The lock is done in SetActivate function.
1726  // All this can improved but it is already a good step.
1727 
1728 
1729  // Find if the cluster is isolated.
1730  unsigned int iextratrack = 0;
1731  unsigned int itrackHcalLinked = 0;
1732  float SumExtraKfP = 0.;
1733 
1734 
1735  double Etotal = Ene_ecalgsf + Ene_ecalbrem + Ene_extraecalgsf;
1736  posX /=Etotal;
1737  posY /=Etotal;
1738  posZ /=Etotal;
1739  math::XYZPoint sc_pflow(posX,posY,posZ);
1740  double ETtotal = Etotal*sin(sc_pflow.Theta());
1741  double phiTrack = RefGSF->phiMode();
1742  double dphi_normalsc = sc_pflow.Phi() - phiTrack;
1743  if ( dphi_normalsc < -M_PI )
1744  dphi_normalsc = dphi_normalsc + 2.*M_PI;
1745  else if ( dphi_normalsc > M_PI )
1746  dphi_normalsc = dphi_normalsc - 2.*M_PI;
1747  dphi_normalsc = fabs(dphi_normalsc);
1748 
1749 
1750  if(ecalGsf_index < 100000) {
1751  vector<unsigned int> assoecalgsf_index = associatedToEcal_.find(ecalGsf_index)->second;
1752  for(unsigned int itrk =0; itrk<assoecalgsf_index.size();itrk++) {
1753  PFBlockElement::Type typeassoecal = elements[(assoecalgsf_index[itrk])].type();
1754  if(typeassoecal == reco::PFBlockElement::TRACK) {
1755  const reco::PFBlockElementTrack * kfTk =
1756  dynamic_cast<const reco::PFBlockElementTrack*>((&elements[(assoecalgsf_index[itrk])]));
1757  // 19 Mar 2010 do not consider here tracks from gamma conv
1758  // This should be not needed because the seleted extra tracks from GammaConv
1759  // will be locked and can not be associated to the ecal elements
1760  //if(kfTk->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)) continue;
1761 
1762 
1763  reco::TrackRef trackref = kfTk->trackRef();
1764  unsigned int Algo = whichTrackAlgo(trackref);
1765  // iter0, iter1, iter2, iter3 = Algo < 3
1766  // algo 4,5,6,7
1767  int nexhits = trackref->hitPattern().numberOfLostHits(HitPattern::MISSING_INNER_HITS);
1768 
1769  bool trackIsFromPrimaryVertex = false;
1770  for (Vertex::trackRef_iterator trackIt = primaryVertex.tracks_begin(); trackIt != primaryVertex.tracks_end(); ++trackIt) {
1771  if ( (*trackIt).castTo<TrackRef>() == trackref ) {
1772  trackIsFromPrimaryVertex = true;
1773  break;
1774  }
1775  }
1776 
1777  // probably we could now remove the algo request??
1778  if(Algo < 3 && nexhits == 0 && trackIsFromPrimaryVertex) {
1779  //if(Algo < 3)
1780  if(DebugIDOutputs)
1781  cout << " The ecalGsf cluster is not isolated: >0 KF extra with algo < 3" << endl;
1782 
1783  float p_trk = trackref->p();
1784 
1785  // expected number of inner hits
1786 
1787  if(DebugIDOutputs)
1788  cout << " p_trk " << p_trk
1789  << " nexhits " << nexhits << endl;
1790 
1791  SumExtraKfP += p_trk;
1792  iextratrack++;
1793  // Check if these extra tracks are HCAL linked
1794  std::multimap<double, unsigned int> hcalKfElems;
1795  block.associatedElements( assoecalgsf_index[itrk],linkData,
1796  hcalKfElems,
1799  if(hcalKfElems.size() > 0) {
1800  itrackHcalLinked++;
1801  }
1802  }
1803  }
1804  }
1805  }
1806  if( iextratrack > 0) {
1807  //if(iextratrack > 3 || HOverHE > 0.05 || (SumExtraKfP/Ene_ecalgsf) > 1.
1808  if(iextratrack > 3 || Ene_hcalgsf > 10 || (SumExtraKfP/Ene_ecalgsf) > 1.
1809  || (ETtotal > 50. && iextratrack > 1 && (Ene_hcalgsf/Ene_ecalgsf) > 0.1) ) {
1810  if(DebugIDOutputs)
1811  cout << " *****This electron candidate is discarded: Non isolated # tracks "
1812  << iextratrack << " HOverHE " << HOverHE
1813  << " SumExtraKfP/Ene_ecalgsf " << SumExtraKfP/Ene_ecalgsf
1814  << " SumExtraKfP " << SumExtraKfP
1815  << " Ene_ecalgsf " << Ene_ecalgsf
1816  << " ETtotal " << ETtotal
1817  << " Ene_hcalgsf/Ene_ecalgsf " << Ene_hcalgsf/Ene_ecalgsf
1818  << endl;
1819 
1820  BDToutput_[cgsf] = mvaValue-2.;
1821  lockExtraKf_[cgsf] = false;
1822  }
1823  // if the Ecluster ~ Ptrack and the extra tracks are HCAL linked
1824  // the electron is retained and the kf tracks are not locked
1825  if( (fabs(1.-EtotPinMode) < 0.2 && (fabs(Eta_gsf) < 1.0 || fabs(Eta_gsf) > 2.0)) ||
1826  ((EtotPinMode < 1.1 && EtotPinMode > 0.6) && (fabs(Eta_gsf) >= 1.0 && fabs(Eta_gsf) <= 2.0))) {
1827  if( fabs(1.-EGsfPoutMode) < 0.5 &&
1828  (itrackHcalLinked == iextratrack) &&
1829  kf_index < 100000 ) {
1830 
1831  BDToutput_[cgsf] = mvaValue;
1832  lockExtraKf_[cgsf] = false;
1833  if(DebugIDOutputs)
1834  cout << " *****This electron is reactivated # tracks "
1835  << iextratrack << " #tracks hcal linked " << itrackHcalLinked
1836  << " SumExtraKfP/Ene_ecalgsf " << SumExtraKfP/Ene_ecalgsf
1837  << " EtotPinMode " << EtotPinMode << " EGsfPoutMode " << EGsfPoutMode
1838  << " eta gsf " << fabs(Eta_gsf) << " kf index " << kf_index <<endl;
1839  }
1840  }
1841  }
1842  // This is a pion:
1843  if (HOverPin > 1. && HOverHE > 0.1 && EtotPinMode < 0.5) {
1844  if(DebugIDOutputs)
1845  cout << " *****This electron candidate is discarded HCAL ENERGY "
1846  << " HOverPin " << HOverPin << " HOverHE " << HOverHE << " EtotPinMode" << EtotPinMode << endl;
1847  BDToutput_[cgsf] = mvaValue-4.;
1848  lockExtraKf_[cgsf] = false;
1849  }
1850 
1851  // Reject Crazy E/p values... to be understood in the future how to train a
1852  // BDT in order to avoid to select this bad electron candidates.
1853 
1854  if( EtotPinMode < 0.2 && EGsfPoutMode < 0.2 ) {
1855  if(DebugIDOutputs)
1856  cout << " *****This electron candidate is discarded Low ETOTPIN "
1857  << " EtotPinMode " << EtotPinMode << " EGsfPoutMode " << EGsfPoutMode << endl;
1858  BDToutput_[cgsf] = mvaValue-6.;
1859  }
1860 
1861  // For not-preselected Gsf Tracks ET > 50 GeV, apply dphi preselection
1862  if(ETtotal > 50. && dphi_normalsc > 0.1 ) {
1863  if(DebugIDOutputs)
1864  cout << " *****This electron candidate is discarded Large ANGLE "
1865  << " ETtotal " << ETtotal << " EGsfPoutMode " << dphi_normalsc << endl;
1866  BDToutput_[cgsf] = mvaValue-6.;
1867  }
1868  }
1869 
1870 
1871  if (DebugIDOutputs) {
1872  cout << " **** BDT observables ****" << endl;
1873  cout << " < Normalization > " << endl;
1874  cout << " Pt_gsf " << Pt_gsf << " Pin " << Ein_gsf << " Pout " << Eout_gsf
1875  << " Eta_gsf " << Eta_gsf << endl;
1876  cout << " < PureTracking > " << endl;
1877  cout << " dPtOverPt_gsf " << dPtOverPt_gsf
1878  << " DPtOverPt_gsf " << DPtOverPt_gsf
1879  << " chi2_gsf " << chi2_gsf
1880  << " nhit_gsf " << nhit_gsf
1881  << " DPtOverPt_kf " << DPtOverPt_kf
1882  << " chi2_kf " << chi2_kf
1883  << " nhit_kf " << nhit_kf << endl;
1884  cout << " < track-ecal-hcal-ps " << endl;
1885  cout << " EtotPinMode " << EtotPinMode
1886  << " EGsfPoutMode " << EGsfPoutMode
1887  << " EtotBremPinPoutMode " << EtotBremPinPoutMode
1888  << " DEtaGsfEcalClust " << DEtaGsfEcalClust
1889  << " SigmaEtaEta " << SigmaEtaEta
1890  << " HOverHE " << HOverHE << " Hcal energy " << Ene_hcalgsf
1891  << " HOverPin " << HOverPin
1892  << " lateBrem " << lateBrem
1893  << " firstBrem " << firstBrem << endl;
1894  cout << " !!!!!!!!!!!!!!!! the BDT output !!!!!!!!!!!!!!!!!: direct " << mvaValue
1895  << " corrected " << BDToutput_[cgsf] << endl;
1896 
1897  }
1898  }
1899  else {
1900  if (DebugIDOutputs)
1901  cout << " Gsf Ref isNULL " << endl;
1902  BDToutput_[cgsf] = -2.;
1903  }
1904  } else {
1905  if (DebugIDOutputs)
1906  cout << " No clusters associated to the gsf " << endl;
1907  BDToutput_[cgsf] = -2.;
1908  }
1909  DebugIDOutputs = false;
1910  } // End Loop on Map1
1911  return;
1912 }
1913 // This function get the associatedToGsf and associatedToBrems maps and
1914 // compute the electron 4-mom and set the pf candidate, for
1915 // the gsf track with a BDTcut > mvaEleCut_
1917  AssMap& associatedToGsf_,
1918  AssMap& associatedToBrems_,
1919  AssMap& associatedToEcal_){
1920 
1921  const reco::PFBlock& block = *blockRef;
1922  PFBlock::LinkData linkData = block.linkData();
1924  PFEnergyResolution pfresol_;
1925  //PFEnergyCalibration pfcalib_;
1926 
1927  bool DebugIDCandidates = false;
1928 // vector<reco::PFCluster> pfClust_vec(0);
1929 // pfClust_vec.clear();
1930 
1931  unsigned int cgsf=0;
1932  for (map<unsigned int,vector<unsigned int> >::iterator igsf = associatedToGsf_.begin();
1933  igsf != associatedToGsf_.end(); igsf++,cgsf++) {
1934  unsigned int gsf_index = igsf->first;
1935 
1936 
1937 
1938  // They should be reset for each gsf track
1939  int eecal=0;
1940  int hcal=0;
1941  int charge =0;
1942  // bool goodphi=true;
1943  math::XYZTLorentzVector momentum_kf,momentum_gsf,momentum,momentum_mean;
1944  float dpt=0; float dpt_gsf=0;
1945  float Eene=0; float dene=0; float Hene=0.;
1946  float RawEene = 0.;
1947  double posX=0.;
1948  double posY=0.;
1949  double posZ=0.;
1950  std::vector<float> bremEnergyVec;
1951 
1952  std::vector<const PFCluster*> pfSC_Clust_vec;
1953 
1954  float de_gs = 0., de_me = 0., de_kf = 0.;
1955  float m_el=0.00051;
1956  int nhit_kf=0; int nhit_gsf=0;
1957  bool has_gsf=false;
1958  bool has_kf=false;
1959  math::XYZTLorentzVector newmomentum;
1960  float ps1TotEne = 0;
1961  float ps2TotEne = 0;
1962  vector<unsigned int> elementsToAdd(0);
1963  reco::TrackRef RefKF;
1964 
1965 
1966 
1967  elementsToAdd.push_back(gsf_index);
1968  const reco::PFBlockElementGsfTrack * GsfEl =
1969  dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[gsf_index]));
1970  const math::XYZPointF& posGsfEcalEntrance = GsfEl->positionAtECALEntrance();
1971  reco::GsfTrackRef RefGSF = GsfEl->GsftrackRef();
1972  if (RefGSF.isNonnull()) {
1973 
1974  has_gsf=true;
1975 
1976  charge= RefGSF->chargeMode();
1977  nhit_gsf= RefGSF->hitPattern().trackerLayersWithMeasurement();
1978 
1979  momentum_gsf.SetPx(RefGSF->pxMode());
1980  momentum_gsf.SetPy(RefGSF->pyMode());
1981  momentum_gsf.SetPz(RefGSF->pzMode());
1982  float ENE=sqrt(RefGSF->pMode()*
1983  RefGSF->pMode()+m_el*m_el);
1984 
1985  if( DebugIDCandidates )
1986  cout << "SetCandidates:: GsfTrackRef: Ene " << ENE
1987  << " charge " << charge << " nhits " << nhit_gsf <<endl;
1988 
1989  momentum_gsf.SetE(ENE);
1990  dpt_gsf=RefGSF->ptModeError()*
1991  (RefGSF->pMode()/RefGSF->ptMode());
1992 
1993  momentum_mean.SetPx(RefGSF->px());
1994  momentum_mean.SetPy(RefGSF->py());
1995  momentum_mean.SetPz(RefGSF->pz());
1996  float ENEm=sqrt(RefGSF->p()*
1997  RefGSF->p()+m_el*m_el);
1998  momentum_mean.SetE(ENEm);
1999  // dpt_mean=RefGSF->ptError()*
2000  // (RefGSF->p()/RefGSF->pt());
2001  }
2002  else {
2003  if( DebugIDCandidates )
2004  cout << "SetCandidates:: !!!! NULL GSF Track Ref " << endl;
2005  }
2006 
2007  // vector<unsigned int> assogsf_index = associatedToGsf_[igsf].second;
2008  vector<unsigned int> assogsf_index = igsf->second;
2009  unsigned int ecalGsf_index = 100000;
2010  bool FirstEcalGsf = true;
2011  for (unsigned int ielegsf=0;ielegsf<assogsf_index.size();ielegsf++) {
2012  PFBlockElement::Type assoele_type = elements[(assogsf_index[ielegsf])].type();
2013  if (assoele_type == reco::PFBlockElement::TRACK) {
2014  elementsToAdd.push_back((assogsf_index[ielegsf])); // Daniele
2015  const reco::PFBlockElementTrack * KfTk =
2016  dynamic_cast<const reco::PFBlockElementTrack*>((&elements[(assogsf_index[ielegsf])]));
2017  // 19 Mar 2010 do not consider here track from gamam conv
2018  bool isPrim = isPrimaryTrack(*KfTk,*GsfEl);
2019  if(!isPrim) continue;
2020 
2021  RefKF = KfTk->trackRef();
2022  if (RefKF.isNonnull()) {
2023  has_kf = true;
2024  // dpt_kf=(RefKF->ptError()*RefKF->ptError());
2025  nhit_kf=RefKF->hitPattern().trackerLayersWithMeasurement();
2026  momentum_kf.SetPx(RefKF->px());
2027  momentum_kf.SetPy(RefKF->py());
2028  momentum_kf.SetPz(RefKF->pz());
2029  float ENE=sqrt(RefKF->p()*RefKF->p()+m_el*m_el);
2030  if( DebugIDCandidates )
2031  cout << "SetCandidates:: KFTrackRef: Ene " << ENE << " nhits " << nhit_kf << endl;
2032 
2033  momentum_kf.SetE(ENE);
2034  }
2035  else {
2036  if( DebugIDCandidates )
2037  cout << "SetCandidates:: !!!! NULL KF Track Ref " << endl;
2038  }
2039  }
2040 
2041  if (assoele_type == reco::PFBlockElement::ECAL) {
2042  unsigned int keyecalgsf = assogsf_index[ielegsf];
2043  vector<unsigned int> assoecalgsf_index = associatedToEcal_.find(keyecalgsf)->second;
2044  vector<double> ps1Ene(0);
2045  vector<double> ps2Ene(0);
2046  // Important is the PS clusters are not saved before the ecal one, these
2047  // energy are not correctly assigned
2048  // For the moment I get only the closest PS clusters: this has to be changed
2049  for(unsigned int ips =0; ips<assoecalgsf_index.size();ips++) {
2050  PFBlockElement::Type typeassoecal = elements[(assoecalgsf_index[ips])].type();
2051  if (typeassoecal == reco::PFBlockElement::PS1) {
2052  PFClusterRef psref = elements[(assoecalgsf_index[ips])].clusterRef();
2053  ps1Ene.push_back(psref->energy());
2054  elementsToAdd.push_back((assoecalgsf_index[ips]));
2055  }
2056  if (typeassoecal == reco::PFBlockElement::PS2) {
2057  PFClusterRef psref = elements[(assoecalgsf_index[ips])].clusterRef();
2058  ps2Ene.push_back(psref->energy());
2059  elementsToAdd.push_back((assoecalgsf_index[ips]));
2060  }
2061  if (typeassoecal == reco::PFBlockElement::HCAL) {
2062  const reco::PFBlockElementCluster * clust =
2063  dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(assoecalgsf_index[ips])]));
2064  elementsToAdd.push_back((assoecalgsf_index[ips]));
2065  Hene+=clust->clusterRef()->energy();
2066  hcal++;
2067  }
2068  }
2069  elementsToAdd.push_back((assogsf_index[ielegsf]));
2070 
2071 
2072  const reco::PFBlockElementCluster * clust =
2073  dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(assogsf_index[ielegsf])]));
2074 
2075  eecal++;
2076 
2077  const reco::PFCluster& cl(*clust->clusterRef());
2078  //pfClust_vec.push_back((*clust->clusterRef()));
2079 
2080  // The electron RAW energy is the energy of the corrected GSF cluster
2081  double ps1,ps2;
2082  ps1=ps2=0.;
2083  // float EE=pfcalib_.energyEm(cl,ps1Ene,ps2Ene);
2084  float EE = thePFEnergyCalibration_->energyEm(cl,ps1Ene,ps2Ene,ps1,ps2,applyCrackCorrections_);
2085  // float RawEE = cl.energy();
2086 
2087  float ceta=cl.position().eta();
2088  float cphi=cl.position().phi();
2089 
2090  /*
2091  float mphi=-2.97025;
2092  if (ceta<0) mphi+=0.00638;
2093 
2094  for (int ip=1; ip<19; ip++){
2095  float df= cphi - (mphi+(ip*6.283185/18));
2096  if (fabs(df)<0.01) goodphi=false;
2097  }
2098  */
2099 
2100  float dE=pfresol_.getEnergyResolutionEm(EE,cl.position().eta());
2101  if( DebugIDCandidates )
2102  cout << "SetCandidates:: EcalCluster: EneNoCalib " << clust->clusterRef()->energy()
2103  << " eta,phi " << ceta << "," << cphi << " Calib " << EE << " dE " << dE <<endl;
2104 
2105  bool elecCluster=false;
2106  if (FirstEcalGsf) {
2107  FirstEcalGsf = false;
2108  elecCluster=true;
2109  ecalGsf_index = assogsf_index[ielegsf];
2110  // std::cout << " PFElectronAlgo / Seed " << EE << std::endl;
2111  RawEene += EE;
2112  }
2113 
2114  // create a photon/electron candidate
2115  math::XYZTLorentzVector clusterMomentum;
2116  math::XYZPoint direction=cl.position()/cl.position().R();
2117  clusterMomentum.SetPxPyPzE(EE*direction.x(),
2118  EE*direction.y(),
2119  EE*direction.z(),
2120  EE);
2121  reco::PFCandidate cluster_Candidate((elecCluster)?charge:0,
2122  clusterMomentum,
2124 
2125  cluster_Candidate.setPs1Energy(ps1);
2126  cluster_Candidate.setPs2Energy(ps2);
2127  // The Raw Ecal energy will be the energy of the basic cluster.
2128  // It will be the corrected energy without the preshower
2129  cluster_Candidate.setEcalEnergy(EE-ps1-ps2,EE);
2130  // std::cout << " PFElectronAlgo, adding Brem (1) " << EE << std::endl;
2131  cluster_Candidate.setPositionAtECALEntrance(math::XYZPointF(cl.position()));
2132  cluster_Candidate.addElementInBlock(blockRef,assogsf_index[ielegsf]);
2133  // store the photon candidate
2134  std::map<unsigned int,std::vector<reco::PFCandidate> >::iterator itcheck=
2135  electronConstituents_.find(cgsf);
2136  if(itcheck==electronConstituents_.end())
2137  {
2138  // beurk
2139  std::vector<reco::PFCandidate> tmpVec;
2140  tmpVec.push_back(cluster_Candidate);
2141  electronConstituents_.insert(std::pair<unsigned int, std::vector<reco::PFCandidate> >
2142  (cgsf,tmpVec));
2143  }
2144  else
2145  {
2146  itcheck->second.push_back(cluster_Candidate);
2147  }
2148 
2149  Eene+=EE;
2150  posX += EE * cl.position().X();
2151  posY += EE * cl.position().Y();
2152  posZ += EE * cl.position().Z();
2153  ps1TotEne+=ps1;
2154  ps2TotEne+=ps2;
2155  dene+=dE*dE;
2156 
2157  //MM Add cluster to the vector pfSC_Clust_vec needed for brem corrections
2158  pfSC_Clust_vec.push_back( &cl );
2159 
2160  }
2161 
2162 
2163 
2164  // Important: Add energy from the brems
2165  if (assoele_type == reco::PFBlockElement::BREM) {
2166  unsigned int brem_index = assogsf_index[ielegsf];
2167  vector<unsigned int> assobrem_index = associatedToBrems_.find(brem_index)->second;
2168  elementsToAdd.push_back(brem_index);
2169  for (unsigned int ibrem = 0; ibrem < assobrem_index.size(); ibrem++){
2170  if (elements[(assobrem_index[ibrem])].type() == reco::PFBlockElement::ECAL) {
2171  // brem emission is from the considered gsf track
2172  if( assobrem_index[ibrem] != ecalGsf_index) {
2173  unsigned int keyecalbrem = assobrem_index[ibrem];
2174  const vector<unsigned int>& assoelebrem_index = associatedToEcal_.find(keyecalbrem)->second;
2175  vector<double> ps1EneFromBrem(0);
2176  vector<double> ps2EneFromBrem(0);
2177  for (unsigned int ielebrem=0; ielebrem<assoelebrem_index.size();ielebrem++) {
2178  if (elements[(assoelebrem_index[ielebrem])].type() == reco::PFBlockElement::PS1) {
2179  PFClusterRef psref = elements[(assoelebrem_index[ielebrem])].clusterRef();
2180  ps1EneFromBrem.push_back(psref->energy());
2181  elementsToAdd.push_back(assoelebrem_index[ielebrem]);
2182  }
2183  if (elements[(assoelebrem_index[ielebrem])].type() == reco::PFBlockElement::PS2) {
2184  PFClusterRef psref = elements[(assoelebrem_index[ielebrem])].clusterRef();
2185  ps2EneFromBrem.push_back(psref->energy());
2186  elementsToAdd.push_back(assoelebrem_index[ielebrem]);
2187  }
2188  }
2189  elementsToAdd.push_back(assobrem_index[ibrem]);
2190  reco::PFClusterRef clusterRef = elements[(assobrem_index[ibrem])].clusterRef();
2191  //pfClust_vec.push_back(*clusterRef);
2192  // to get a calibrated PS energy
2193  double ps1=0;
2194  double ps2=0;
2195  float EE = thePFEnergyCalibration_->energyEm(*clusterRef,ps1EneFromBrem,ps2EneFromBrem,ps1,ps2,applyCrackCorrections_);
2196  bremEnergyVec.push_back(EE);
2197  // float RawEE = clusterRef->energy();
2198  float ceta = clusterRef->position().eta();
2199  // float cphi = clusterRef->position().phi();
2200  float dE=pfresol_.getEnergyResolutionEm(EE,ceta);
2201  if( DebugIDCandidates )
2202  cout << "SetCandidates:: BremCluster: Ene " << EE << " dE " << dE <<endl;
2203 
2204  Eene+=EE;
2205  posX += EE * clusterRef->position().X();
2206  posY += EE * clusterRef->position().Y();
2207  posZ += EE * clusterRef->position().Z();
2208  ps1TotEne+=ps1;
2209  ps2TotEne+=ps2;
2210  // Removed 4 March 2009. Florian. The Raw energy is the (corrected) one of the GSF cluster only
2211  // RawEene += RawEE;
2212  dene+=dE*dE;
2213 
2214  //MM Add cluster to the vector pfSC_Clust_vec needed for brem corrections
2215  pfSC_Clust_vec.push_back( clusterRef.get() );
2216 
2217  // create a PFCandidate out of it. Watch out, it is for the e/gamma and tau only
2218  // not to be used by the PFAlgo
2219  math::XYZTLorentzVector photonMomentum;
2220  math::XYZPoint direction=clusterRef->position()/clusterRef->position().R();
2221 
2222  photonMomentum.SetPxPyPzE(EE*direction.x(),
2223  EE*direction.y(),
2224  EE*direction.z(),
2225  EE);
2226  reco::PFCandidate photon_Candidate(0,photonMomentum, reco::PFCandidate::gamma);
2227 
2228  photon_Candidate.setPs1Energy(ps1);
2229  photon_Candidate.setPs2Energy(ps2);
2230  // yes, EE, we want the raw ecal energy of the daugther to have the same definition
2231  // as the GSF cluster
2232  photon_Candidate.setEcalEnergy(EE-ps1-ps2,EE);
2233  // std::cout << " PFElectronAlgo, adding Brem " << EE << std::endl;
2234  photon_Candidate.setPositionAtECALEntrance(math::XYZPointF(clusterRef->position()));
2235  photon_Candidate.addElementInBlock(blockRef,assobrem_index[ibrem]);
2236 
2237  // store the photon candidate
2238  std::map<unsigned int,std::vector<reco::PFCandidate> >::iterator itcheck=
2239  electronConstituents_.find(cgsf);
2240  if(itcheck==electronConstituents_.end())
2241  {
2242  // beurk
2243  std::vector<reco::PFCandidate> tmpVec;
2244  tmpVec.push_back(photon_Candidate);
2245  electronConstituents_.insert(std::pair<unsigned int, std::vector<reco::PFCandidate> >
2246  (cgsf,tmpVec));
2247  }
2248  else
2249  {
2250  itcheck->second.push_back(photon_Candidate);
2251  }
2252  }
2253  }
2254  }
2255  }
2256  } // End Loop On element associated to the GSF tracks
2257  if (has_gsf) {
2258 
2259  // SuperCluster energy corrections
2260  double unCorrEene = Eene;
2261  double absEta = fabs(momentum_gsf.Eta());
2262  double emTheta = momentum_gsf.Theta();
2263  PFClusterWidthAlgo pfSCwidth(pfSC_Clust_vec);
2264  double brLinear = pfSCwidth.pflowPhiWidth()/pfSCwidth.pflowEtaWidth();
2265  pfSC_Clust_vec.clear();
2266 
2267  if( DebugIDCandidates )
2268  cout << "PFEelectronAlgo:: absEta " << absEta << " theta " << emTheta
2269  << " EneRaw " << Eene << " Err " << dene;
2270 
2271  // The calibrations are provided till ET = 200 GeV //No longer a such cut MM
2272  // Protection on at least 1 GeV energy...avoid possible divergencies at very low energy.
2273  if(usePFSCEleCalib_ && unCorrEene > 0.) {
2274  if( absEta < 1.5) {
2275  double Etene = Eene*sin(emTheta);
2276  double emBR_e = thePFSCEnergyCalibration_->SCCorrFBremBarrel(Eene, Etene, brLinear);
2277  double emBR_et = emBR_e*sin(emTheta);
2278  double emCorrFull_et = thePFSCEnergyCalibration_->SCCorrEtEtaBarrel(emBR_et, absEta);
2279  Eene = emCorrFull_et/sin(emTheta);
2280  }
2281  else {
2282  // double Etene = Eene*sin(emTheta); //not needed anymore for endcaps MM
2283  double emBR_e = thePFSCEnergyCalibration_->SCCorrFBremEndcap(Eene, absEta, brLinear);
2284  double emBR_et = emBR_e*sin(emTheta);
2285  double emCorrFull_et = thePFSCEnergyCalibration_->SCCorrEtEtaEndcap(emBR_et, absEta);
2286  Eene = emCorrFull_et/sin(emTheta);
2287  }
2288  dene = sqrt(dene)*(Eene/unCorrEene);
2289  dene = dene*dene;
2290  }
2291 
2292  if( DebugIDCandidates )
2293  cout << " EneCorrected " << Eene << " Err " << dene << endl;
2294 
2295  // charge determination with the majority method
2296  // if the kf track exists: 2 among 3 of supercluster barycenter position
2297  // gsf track and kf track
2298  if(has_kf && unCorrEene > 0.) {
2299  posX /=unCorrEene;
2300  posY /=unCorrEene;
2301  posZ /=unCorrEene;
2302  math::XYZPoint sc_pflow(posX,posY,posZ);
2303 
2304  std::multimap<double, unsigned int> bremElems;
2305  block.associatedElements( gsf_index,linkData,
2306  bremElems,
2309 
2310  double phiTrack = RefGSF->phiMode();
2311  if(bremElems.size()>0) {
2312  unsigned int brem_index = bremElems.begin()->second;
2313  const reco::PFBlockElementBrem * BremEl =
2314  dynamic_cast<const reco::PFBlockElementBrem*>((&elements[brem_index]));
2315  phiTrack = BremEl->positionAtECALEntrance().phi();
2316  }
2317 
2318  double dphi_normalsc = sc_pflow.Phi() - phiTrack;
2319  if ( dphi_normalsc < -M_PI )
2320  dphi_normalsc = dphi_normalsc + 2.*M_PI;
2321  else if ( dphi_normalsc > M_PI )
2322  dphi_normalsc = dphi_normalsc - 2.*M_PI;
2323 
2324  int chargeGsf = RefGSF->chargeMode();
2325  int chargeKf = RefKF->charge();
2326 
2327  int chargeSC = 0;
2328  if(dphi_normalsc < 0.)
2329  chargeSC = 1;
2330  else
2331  chargeSC = -1;
2332 
2333  if(chargeKf == chargeGsf)
2334  charge = chargeGsf;
2335  else if(chargeGsf == chargeSC)
2336  charge = chargeGsf;
2337  else
2338  charge = chargeKf;
2339 
2340  if( DebugIDCandidates )
2341  cout << "PFElectronAlgo:: charge determination "
2342  << " charge GSF " << chargeGsf
2343  << " charge KF " << chargeKf
2344  << " charge SC " << chargeSC
2345  << " Final Charge " << charge << endl;
2346 
2347  }
2348 
2349  // Think about this...
2350  if ((nhit_gsf<8) && (has_kf)){
2351 
2352  // Use Hene if some condition....
2353 
2354  momentum=momentum_kf;
2355  float Fe=Eene;
2356  float scale= Fe/momentum.E();
2357 
2358  // Daniele Changed
2359  if (Eene < 0.0001) {
2360  Fe = momentum.E();
2361  scale = 1.;
2362  }
2363 
2364 
2365  newmomentum.SetPxPyPzE(scale*momentum.Px(),
2366  scale*momentum.Py(),
2367  scale*momentum.Pz(),Fe);
2368  if( DebugIDCandidates )
2369  cout << "SetCandidates:: (nhit_gsf<8) && (has_kf):: pt " << newmomentum.pt() << " Ene " << Fe <<endl;
2370 
2371 
2372  }
2373  if ((nhit_gsf>7) || (has_kf==false)){
2374  if(Eene > 0.0001) {
2375  de_gs=1-momentum_gsf.E()/Eene;
2376  de_me=1-momentum_mean.E()/Eene;
2377  de_kf=1-momentum_kf.E()/Eene;
2378  }
2379 
2380  momentum=momentum_gsf;
2381  dpt=1/(dpt_gsf*dpt_gsf);
2382 
2383  if(dene > 0.)
2384  dene= 1./dene;
2385 
2386  float Fe = 0.;
2387  if(Eene > 0.0001) {
2388  Fe =((dene*Eene) +(dpt*momentum.E()))/(dene+dpt);
2389  }
2390  else {
2391  Fe=momentum.E();
2392  }
2393 
2394  if ((de_gs>0.05)&&(de_kf>0.05)){
2395  Fe=Eene;
2396  }
2397  if ((de_gs<-0.1)&&(de_me<-0.1) &&(de_kf<0.) &&
2398  (momentum.E()/dpt_gsf) > 5. && momentum_gsf.pt() < 30.){
2399  Fe=momentum.E();
2400  }
2401  float scale= Fe/momentum.E();
2402 
2403  newmomentum.SetPxPyPzE(scale*momentum.Px(),
2404  scale*momentum.Py(),
2405  scale*momentum.Pz(),Fe);
2406  if( DebugIDCandidates )
2407  cout << "SetCandidates::(nhit_gsf>7) || (has_kf==false) " << newmomentum.pt() << " Ene " << Fe <<endl;
2408 
2409 
2410  }
2411  if (newmomentum.pt()>0.5){
2412 
2413  // the pf candidate are created: we need to set something more?
2414  // IMPORTANT -> We need the gsftrackRef, not only the TrackRef??
2415 
2416  if( DebugIDCandidates )
2417  cout << "SetCandidates:: I am before doing candidate " <<endl;
2418 
2419  //vector with the cluster energies (for the extra)
2420  std::vector<float> clusterEnergyVec;
2421  clusterEnergyVec.push_back(RawEene);
2422  clusterEnergyVec.insert(clusterEnergyVec.end(),bremEnergyVec.begin(),bremEnergyVec.end());
2423 
2424  // add the information in the extra
2425  std::vector<reco::PFCandidateElectronExtra>::iterator itextra;
2426  PFElectronExtraEqual myExtraEqual(RefGSF);
2427  itextra=find_if(electronExtra_.begin(),electronExtra_.end(),myExtraEqual);
2428  if(itextra!=electronExtra_.end()) {
2429  itextra->setClusterEnergies(clusterEnergyVec);
2430  }
2431  else {
2432  if(RawEene>0.)
2433  std::cout << " There is a big problem with the electron extra, PFElectronAlgo should crash soon " << RawEene << std::endl;
2434  }
2435 
2438  reco::PFCandidate temp_Candidate;
2439  temp_Candidate = PFCandidate(charge,newmomentum,particleType);
2440  temp_Candidate.set_mva_e_pi(BDToutput_[cgsf]);
2441  temp_Candidate.setEcalEnergy(RawEene,Eene);
2442  // Note the Hcal energy is set but the element is never locked
2443  temp_Candidate.setHcalEnergy(Hene,Hene);
2444  temp_Candidate.setPs1Energy(ps1TotEne);
2445  temp_Candidate.setPs2Energy(ps2TotEne);
2446  temp_Candidate.setTrackRef(RefKF);
2447  // This reference could be NULL it is needed a protection?
2448  temp_Candidate.setGsfTrackRef(RefGSF);
2449  temp_Candidate.setPositionAtECALEntrance(posGsfEcalEntrance);
2450  // Add Vertex
2451  temp_Candidate.setVertexSource(PFCandidate::kGSFVertex);
2452 
2453  // save the superclusterRef when available
2454  if(RefGSF->extra().isAvailable() && RefGSF->extra()->seedRef().isAvailable()) {
2455  reco::ElectronSeedRef seedRef= RefGSF->extra()->seedRef().castTo<reco::ElectronSeedRef>();
2456  if(seedRef.isAvailable() && seedRef->isEcalDriven()) {
2457  reco::SuperClusterRef scRef = seedRef->caloCluster().castTo<reco::SuperClusterRef>();
2458  if(scRef.isNonnull())
2459  temp_Candidate.setSuperClusterRef(scRef);
2460  }
2461  }
2462 
2463  if( DebugIDCandidates )
2464  cout << "SetCandidates:: I am after doing candidate " <<endl;
2465 
2466  for (unsigned int elad=0; elad<elementsToAdd.size();elad++){
2467  temp_Candidate.addElementInBlock(blockRef,elementsToAdd[elad]);
2468  }
2469 
2470  // now add the photons to this candidate
2471  std::map<unsigned int, std::vector<reco::PFCandidate> >::const_iterator itcluster=
2472  electronConstituents_.find(cgsf);
2473  if(itcluster!=electronConstituents_.end())
2474  {
2475  const std::vector<reco::PFCandidate> & theClusters=itcluster->second;
2476  unsigned nclus=theClusters.size();
2477  // std::cout << " PFElectronAlgo " << nclus << " daugthers to add" << std::endl;
2478  for(unsigned iclus=0;iclus<nclus;++iclus)
2479  {
2480  temp_Candidate.addDaughter(theClusters[iclus]);
2481  }
2482  }
2483 
2484  // By-pass the mva is the electron has been pre-selected
2485  bool bypassmva=false;
2486  if(useEGElectrons_) {
2487  GsfElectronEqual myEqual(RefGSF);
2488  std::vector<reco::GsfElectron>::const_iterator itcheck=find_if(theGsfElectrons_->begin(),theGsfElectrons_->end(),myEqual);
2489  if(itcheck!=theGsfElectrons_->end()) {
2490  if(BDToutput_[cgsf] >= -1.) {
2491  // bypass the mva only if the reconstruction went fine
2492  bypassmva=true;
2493 
2494  if( DebugIDCandidates ) {
2495  if(BDToutput_[cgsf] < -0.1) {
2496  float esceg = itcheck->caloEnergy();
2497  cout << " Attention By pass the mva " << BDToutput_[cgsf]
2498  << " SuperClusterEnergy " << esceg
2499  << " PF Energy " << Eene << endl;
2500 
2501  cout << " hoe " << itcheck->hcalOverEcal()
2502  << " tkiso04 " << itcheck->dr04TkSumPt()
2503  << " ecaliso04 " << itcheck->dr04EcalRecHitSumEt()
2504  << " hcaliso04 " << itcheck->dr04HcalTowerSumEt()
2505  << " tkiso03 " << itcheck->dr03TkSumPt()
2506  << " ecaliso03 " << itcheck->dr03EcalRecHitSumEt()
2507  << " hcaliso03 " << itcheck->dr03HcalTowerSumEt() << endl;
2508  }
2509  } // end DebugIDCandidates
2510  }
2511  }
2512  }
2513 
2514  bool mvaSelected = (BDToutput_[cgsf] >= mvaEleCut_);
2515  if( mvaSelected || bypassmva ) {
2516  elCandidate_.push_back(temp_Candidate);
2517  if(itextra!=electronExtra_.end())
2518  itextra->setStatus(PFCandidateElectronExtra::Selected,true);
2519  }
2520  else {
2521  if(itextra!=electronExtra_.end())
2522  itextra->setStatus(PFCandidateElectronExtra::Rejected,true);
2523  }
2524  allElCandidate_.push_back(temp_Candidate);
2525 
2526  // save the status information
2527  if(itextra!=electronExtra_.end()) {
2528  itextra->setStatus(PFCandidateElectronExtra::ECALDrivenPreselected,bypassmva);
2529  itextra->setStatus(PFCandidateElectronExtra::MVASelected,mvaSelected);
2530  }
2531 
2532 
2533  }
2534  else {
2535  BDToutput_[cgsf] = -1.; // if the momentum is < 0.5 ID = false, but not sure
2536  // it could be misleading.
2537  if( DebugIDCandidates )
2538  cout << "SetCandidates:: No Candidate Produced because of Pt cut: 0.5 " <<endl;
2539  }
2540  }
2541  else {
2542  BDToutput_[cgsf] = -1.; // if gsf ref does not exist
2543  if( DebugIDCandidates )
2544  cout << "SetCandidates:: No Candidate Produced because of No GSF Track Ref " <<endl;
2545  }
2546  } // End Loop On GSF tracks
2547  return;
2548 }
2549 // // This function get the associatedToGsf and associatedToBrems maps and for each pfelectron candidate
2550 // // the element used are set active == false.
2551 // // note: the HCAL cluster are not used for the moments and also are not locked.
2553  AssMap& associatedToGsf_,
2554  AssMap& associatedToBrems_,
2555  AssMap& associatedToEcal_,
2556  std::vector<bool>& active){
2557  const reco::PFBlock& block = *blockRef;
2558  PFBlock::LinkData linkData = block.linkData();
2559 
2561 
2562  unsigned int cgsf=0;
2563  for (map<unsigned int,vector<unsigned int> >::iterator igsf = associatedToGsf_.begin();
2564  igsf != associatedToGsf_.end(); igsf++,cgsf++) {
2565 
2566  unsigned int gsf_index = igsf->first;
2567  const reco::PFBlockElementGsfTrack * GsfEl =
2568  dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[gsf_index]));
2569  reco::GsfTrackRef RefGSF = GsfEl->GsftrackRef();
2570 
2571  // lock only the elements that pass the BDT cut
2572  bool bypassmva=false;
2573  if(useEGElectrons_) {
2574  GsfElectronEqual myEqual(RefGSF);
2575  std::vector<reco::GsfElectron>::const_iterator itcheck=find_if(theGsfElectrons_->begin(),theGsfElectrons_->end(),myEqual);
2576  if(itcheck!=theGsfElectrons_->end()) {
2577  if(BDToutput_[cgsf] >= -1.)
2578  bypassmva=true;
2579  }
2580  }
2581 
2582  if(BDToutput_[cgsf] < mvaEleCut_ && bypassmva == false) continue;
2583 
2584 
2585  active[gsf_index] = false; // lock the gsf
2586  vector<unsigned int> assogsf_index = igsf->second;
2587  for (unsigned int ielegsf=0;ielegsf<assogsf_index.size();ielegsf++) {
2588  PFBlockElement::Type assoele_type = elements[(assogsf_index[ielegsf])].type();
2589  // lock the elements associated to the gsf: ECAL, Brems
2590  active[(assogsf_index[ielegsf])] = false;
2591  if (assoele_type == reco::PFBlockElement::ECAL) {
2592  unsigned int keyecalgsf = assogsf_index[ielegsf];
2593 
2594  // added protection against fifth step
2595  if(fifthStepKfTrack_.size() > 0) {
2596  for(unsigned int itr = 0; itr < fifthStepKfTrack_.size(); itr++) {
2597  if(fifthStepKfTrack_[itr].first == keyecalgsf) {
2598  active[(fifthStepKfTrack_[itr].second)] = false;
2599  }
2600  }
2601  }
2602 
2603  // added locking for conv gsf tracks and kf tracks
2604  if(convGsfTrack_.size() > 0) {
2605  for(unsigned int iconv = 0; iconv < convGsfTrack_.size(); iconv++) {
2606  if(convGsfTrack_[iconv].first == keyecalgsf) {
2607  // lock the GSF track
2608  active[(convGsfTrack_[iconv].second)] = false;
2609  // lock also the KF track associated
2610  std::multimap<double, unsigned> convKf;
2611  block.associatedElements( convGsfTrack_[iconv].second,
2612  linkData,
2613  convKf,
2616  if(convKf.size() > 0) {
2617  active[convKf.begin()->second] = false;
2618  }
2619  }
2620  }
2621  }
2622 
2623 
2624  vector<unsigned int> assoecalgsf_index = associatedToEcal_.find(keyecalgsf)->second;
2625  for(unsigned int ips =0; ips<assoecalgsf_index.size();ips++) {
2626  // lock the elements associated to ECAL: PS1,PS2, for the moment not HCAL
2627  if (elements[(assoecalgsf_index[ips])].type() == reco::PFBlockElement::PS1)
2628  active[(assoecalgsf_index[ips])] = false;
2629  if (elements[(assoecalgsf_index[ips])].type() == reco::PFBlockElement::PS2)
2630  active[(assoecalgsf_index[ips])] = false;
2631  if (elements[(assoecalgsf_index[ips])].type() == reco::PFBlockElement::TRACK) {
2632  if(lockExtraKf_[cgsf] == true) {
2633  active[(assoecalgsf_index[ips])] = false;
2634  }
2635  }
2636  }
2637  } // End if ECAL
2638  if (assoele_type == reco::PFBlockElement::BREM) {
2639  unsigned int brem_index = assogsf_index[ielegsf];
2640  vector<unsigned int> assobrem_index = associatedToBrems_.find(brem_index)->second;
2641  for (unsigned int ibrem = 0; ibrem < assobrem_index.size(); ibrem++){
2642  if (elements[(assobrem_index[ibrem])].type() == reco::PFBlockElement::ECAL) {
2643  unsigned int keyecalbrem = assobrem_index[ibrem];
2644  // lock the ecal cluster associated to the brem
2645  active[(assobrem_index[ibrem])] = false;
2646 
2647  // add protection against fifth step
2648  if(fifthStepKfTrack_.size() > 0) {
2649  for(unsigned int itr = 0; itr < fifthStepKfTrack_.size(); itr++) {
2650  if(fifthStepKfTrack_[itr].first == keyecalbrem) {
2651  active[(fifthStepKfTrack_[itr].second)] = false;
2652  }
2653  }
2654  }
2655 
2656  vector<unsigned int> assoelebrem_index = associatedToEcal_.find(keyecalbrem)->second;
2657  // lock the elements associated to ECAL: PS1,PS2, for the moment not HCAL
2658  for (unsigned int ielebrem=0; ielebrem<assoelebrem_index.size();ielebrem++) {
2659  if (elements[(assoelebrem_index[ielebrem])].type() == reco::PFBlockElement::PS1)
2660  active[(assoelebrem_index[ielebrem])] = false;
2661  if (elements[(assoelebrem_index[ielebrem])].type() == reco::PFBlockElement::PS2)
2662  active[(assoelebrem_index[ielebrem])] = false;
2663  }
2664  }
2665  }
2666  } // End if BREM
2667  } // End loop on elements from gsf track
2668  } // End loop on gsf track
2669  return;
2670 }
2672  theGsfElectrons_ = & egelectrons;
2673 }
2674 unsigned int PFElectronAlgo::whichTrackAlgo(const reco::TrackRef& trackRef) {
2675  unsigned int Algo = 0;
2676  switch (trackRef->algo()) {
2677  case TrackBase::ctf:
2679  case TrackBase::lowPtTripletStep:
2680  case TrackBase::pixelPairStep:
2681  case TrackBase::jetCoreRegionalStep:
2682  case TrackBase::muonSeededStepInOut:
2683  case TrackBase::muonSeededStepOutIn:
2684  Algo = 0;
2685  break;
2687  Algo = 1;
2688  break;
2690  Algo = 2;
2691  break;
2693  Algo = 3;
2694  break;
2695  case TrackBase::tobTecStep:
2696  Algo = 4;
2697  break;
2698  default:
2699  Algo = 5;
2700  break;
2701  }
2702  return Algo;
2703 }
2705  const reco::PFBlockElementGsfTrack& GsfEl) {
2706  bool isPrimary = false;
2707 
2708  GsfPFRecTrackRef gsfPfRef = GsfEl.GsftrackRefPF();
2709 
2710  if(gsfPfRef.isNonnull()) {
2711  PFRecTrackRef kfPfRef = KfEl.trackRefPF();
2712  PFRecTrackRef kfPfRef_fromGsf = (*gsfPfRef).kfPFRecTrackRef();
2713  if(kfPfRef.isNonnull() && kfPfRef_fromGsf.isNonnull()) {
2714  reco::TrackRef kfref= (*kfPfRef).trackRef();
2715  reco::TrackRef kfref_fromGsf = (*kfPfRef_fromGsf).trackRef();
2716  if(kfref.isNonnull() && kfref_fromGsf.isNonnull()) {
2717  if(kfref == kfref_fromGsf)
2718  isPrimary = true;
2719  }
2720  }
2721  }
2722 
2723  return isPrimary;
2724 }
std::vector< std::pair< unsigned int, unsigned int > > fifthStepKfTrack_
bool isAvailable() const
Definition: Ref.h:576
type
Definition: HCALResponse.h:21
const math::XYZTLorentzVector & Pout() const
void setPs2Energy(float e2)
set corrected PS2 energy
Definition: PFCandidate.h:279
const math::XYZPointF & positionAtECALEntrance() const
int i
Definition: DBlmapReader.cc:9
const reco::TrackRef & trackRef() const
bool SetLinks(const reco::PFBlockRef &blockRef, AssMap &associatedToGsf_, AssMap &associatedToBrems_, AssMap &associatedToEcal_, std::vector< bool > &active, const reco::Vertex &primaryVertex)
std::map< unsigned int, std::vector< unsigned int > > AssMap
const reco::GsfTrackRef & GsftrackRef() const
void setPs1Energy(float e1)
set corrected PS1 energy
Definition: PFCandidate.h:273
ParticleType
particle types
Definition: PFCandidate.h:44
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:252
void setMVA(float val)
set the result (mostly for debugging)
void setLateBrem(float val)
set LateBrem
Particle flow cluster, see clustering algorithm in PFClusterAlgo.
Definition: PFCluster.h:47
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:348
float EtotBremPinPoutMode
void SetCandidates(const reco::PFBlockRef &blockRef, AssMap &associatedToGsf_, AssMap &associatedToBrems_, AssMap &associatedToEcal_)
std::vector< std::pair< unsigned int, unsigned int > > convGsfTrack_
void setSigmaEtaEta(float val)
set the sigmaetaeta
void setGsfTrackPout(const math::XYZTLorentzVector &pout)
set the pout (not trivial to get from the GSF track)
const math::XYZPointF & positionAtECALEntrance() const
std::vector< reco::PFCandidateElectronExtra > electronExtra_
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
std::map< unsigned int, Link > LinkData
Definition: PFBlock.h:46
size_type size() const
Definition: OwnVector.h:254
double pflowPhiWidth() const
void setEarlyBrem(float val)
set EarlyBrem
list elements
Definition: asciidump.py:414
const std::vector< reco::GsfElectron > * theGsfElectrons_
bool isPrimaryTrack(const reco::PFBlockElementTrack &KfEl, const reco::PFBlockElementGsfTrack &GsfEl)
const GsfPFRecTrackRef & GsftrackRefPF() const
const PFClusterRef & clusterRef() const
const edm::OwnVector< reco::PFBlockElement > & elements() const
Definition: PFBlock.h:107
const LinkData & linkData() const
Definition: PFBlock.h:112
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< float > > XYZPointF
point in space with cartesian internal representation
Definition: Point3D.h:10
unsigned int indTrajPoint() const
int ii
Definition: cuy.py:588
double pflowEtaWidth() const
std::vector< GsfElectron > GsfElectronCollection
collection of GsfElectron objects
double coneEcalIsoForEgammaSC_
TMVA::Reader * tmvaReader_
TrackAlgorithm
track algorithm
Definition: TrackBase.h:99
U second(std::pair< T, U > const &p)
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
void set_mva_e_pi(float mvaNI)
Definition: PFCandidate.h:311
void SetActive(const reco::PFBlockRef &blockRef, AssMap &associatedToGsf_, AssMap &associatedToBrems_, AssMap &associatedToEcal_, std::vector< bool > &active)
void setVertexSource(PFVertexType vt)
Definition: PFCandidate.h:406
double getEnergyResolutionEm(double CorrectedEnergy, double eta) const
double pflowSigmaEtaEta() const
void addElementInBlock(const reco::PFBlockRef &blockref, unsigned elementIndex)
add an element to the current PFCandidate
Definition: PFCandidate.cc:211
T sqrt(T t)
Definition: SSEVec.h:48
double sumEtEcalIsoForEgammaSC_barrel_
std::vector< bool > lockExtraKf_
std::vector< double > BDToutput_
void setDeltaEta(float val)
set the delta eta
double sumEtEcalIsoForEgammaSC_endcap_
T const * get() const
Returns C++ pointer to the item.
Definition: Ref.h:244
void SetIDOutputs(const reco::PFBlockRef &blockRef, AssMap &associatedToGsf_, AssMap &associatedToBrems_, AssMap &associatedToEcal_, const reco::Vertex &primaryVertex)
virtual bool trackType(TrackType trType) const
#define M_PI
void addDaughter(const Candidate &, const std::string &s="")
add a clone of the passed candidate as daughter
std::map< unsigned int, std::vector< reco::PFCandidate > > electronConstituents_
void setEcalEnergy(float eeRaw, float eeCorr)
set corrected Ecal energy
Definition: PFCandidate.h:217
void setKfTrackRef(const reco::TrackRef &ref)
set kf track reference
double sumPtTrackIsoForEgammaSC_endcap_
unsigned int whichTrackAlgo(const reco::TrackRef &trackRef)
void setGsfTrackRef(const reco::GsfTrackRef &ref)
set gsftrack reference
Definition: PFCandidate.cc:454
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
boost::shared_ptr< PFSCEnergyCalibration > thePFSCEnergyCalibration_
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:39
const PFRecTrackRef & trackRefPF() const
std::vector< TrackBaseRef >::const_iterator trackRef_iterator
The iteratator for the vector&lt;TrackRef&gt;
Definition: Vertex.h:37
PFElectronAlgo(const double mvaEleCut, std::string mvaWeightFileEleID, const boost::shared_ptr< PFSCEnergyCalibration > &thePFSCEnergyCalibration, const boost::shared_ptr< PFEnergyCalibration > &thePFEnergyCalibration, bool applyCrackCorrections, bool usePFSCEleCalib, bool useEGElectrons, bool useEGammaSupercluster, double sumEtEcalIsoForEgammaSC_barrel, double sumEtEcalIsoForEgammaSC_endcap, double coneEcalIsoForEgammaSC, double sumPtTrackIsoForEgammaSC_barrel, double sumPtTrackIsoForEgammaSC_endcap, unsigned int nTrackIsoForEgammaSC, double coneTrackIsoForEgammaSC)
double sumPtTrackIsoForEgammaSC_barrel_
void setSuperClusterRef(const reco::SuperClusterRef &scRef)
Definition: PFCandidate.cc:620
tuple cout
Definition: gather_cfg.py:121
double dist(unsigned ie1, unsigned ie2, const LinkData &linkData, LinkTest test) const
Definition: PFBlock.h:94
trackRef_iterator tracks_begin() const
first iterator over tracks
Definition: Vertex.cc:39
unsigned int nTrackIsoForEgammaSC_
void setTrackRef(const reco::TrackRef &ref)
set track reference
Definition: PFCandidate.cc:416
void RunPFElectron(const reco::PFBlockRef &blockRef, std::vector< bool > &active, const reco::Vertex &primaryVertex)
void setHadEnergy(float val)
set the had energy. The cluster energies should be entered before
Definition: fakeMenu.h:6
void setHcalEnergy(float ehRaw, float ehCorr)
set corrected Hcal energy
Definition: PFCandidate.h:227
boost::shared_ptr< PFEnergyCalibration > thePFEnergyCalibration_
std::vector< reco::PFCandidate > elCandidate_
bool applyCrackCorrections_
void setEGElectronCollection(const reco::GsfElectronCollection &egelectrons)
bool useEGammaSupercluster_
Block of elements.
Definition: PFBlock.h:30
std::vector< reco::PFCandidate > allElCandidate_