CMS 3D CMS Logo

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