CMS 3D CMS Logo

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