CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_2_7_hltpatch2/src/RecoParticleFlow/PFProducer/src/PFElectronAlgo.cc

Go to the documentation of this file.
00001 //
00002 // Original Author: Daniele Benedetti: daniele.benedetti@cern.ch
00003 //
00004 
00005 #include "RecoParticleFlow/PFProducer/interface/PFElectronAlgo.h"
00006 #include "RecoParticleFlow/PFProducer/interface/PFMuonAlgo.h"
00007 //#include "DataFormats/ParticleFlowReco/interface/PFBlockElementGsfTrack.h"
00008 #include "DataFormats/ParticleFlowReco/interface/PFBlockElementCluster.h"
00009 #include "DataFormats/ParticleFlowReco/interface/PFBlockElementBrem.h"
00010 #include "DataFormats/ParticleFlowReco/interface/PFRecHitFraction.h"
00011 #include "DataFormats/ParticleFlowReco/interface/PFRecHitFwd.h" 
00012 #include "DataFormats/ParticleFlowReco/interface/PFRecHit.h"
00013 #include "DataFormats/ParticleFlowReco/interface/PFCluster.h"
00014 #include "DataFormats/GsfTrackReco/interface/GsfTrack.h"
00015 #include "DataFormats/GsfTrackReco/interface/GsfTrackFwd.h"
00016 #include "RecoParticleFlow/PFProducer/interface/PFElectronExtraEqual.h"
00017 #include "RecoParticleFlow/PFProducer/interface/GsfElectronEqual.h"
00018 #include "RecoParticleFlow/PFClusterTools/interface/PFEnergyCalibration.h"
00019 #include "RecoParticleFlow/PFClusterTools/interface/PFSCEnergyCalibration.h"
00020 #include "RecoParticleFlow/PFClusterTools/interface/PFEnergyResolution.h"
00021 #include "RecoParticleFlow/PFClusterTools/interface/PFClusterWidthAlgo.h"
00022 #include "DataFormats/ParticleFlowReco/interface/PFRecTrack.h"
00023 #include "DataFormats/ParticleFlowReco/interface/GsfPFRecTrack.h"
00024 #include "DataFormats/EgammaReco/interface/ElectronSeedFwd.h"
00025 #include "DataFormats/EgammaReco/interface/ElectronSeed.h"
00026 
00027 #include <iomanip>
00028 #include <algorithm>
00029 
00030 using namespace std;
00031 using namespace reco;
00032 PFElectronAlgo::PFElectronAlgo(const double mvaEleCut,
00033                                string mvaWeightFileEleID,
00034                                const boost::shared_ptr<PFSCEnergyCalibration>& thePFSCEnergyCalibration,
00035                                const boost::shared_ptr<PFEnergyCalibration>& thePFEnergyCalibration,
00036                                bool applyCrackCorrections,
00037                                bool usePFSCEleCalib,
00038                                bool useEGElectrons,
00039                                bool useEGammaSupercluster,
00040                                double sumEtEcalIsoForEgammaSC_barrel,
00041                                double sumEtEcalIsoForEgammaSC_endcap,
00042                                double coneEcalIsoForEgammaSC,
00043                                double sumPtTrackIsoForEgammaSC_barrel,
00044                                double sumPtTrackIsoForEgammaSC_endcap,
00045                                unsigned int nTrackIsoForEgammaSC,
00046                                double coneTrackIsoForEgammaSC):
00047   mvaEleCut_(mvaEleCut),
00048   thePFSCEnergyCalibration_(thePFSCEnergyCalibration),
00049   thePFEnergyCalibration_(thePFEnergyCalibration),
00050   applyCrackCorrections_(applyCrackCorrections),
00051   usePFSCEleCalib_(usePFSCEleCalib),
00052   useEGElectrons_(useEGElectrons),
00053   useEGammaSupercluster_(useEGammaSupercluster),
00054   sumEtEcalIsoForEgammaSC_barrel_(sumEtEcalIsoForEgammaSC_barrel),
00055   sumEtEcalIsoForEgammaSC_endcap_(sumEtEcalIsoForEgammaSC_endcap),
00056   coneEcalIsoForEgammaSC_(coneEcalIsoForEgammaSC),
00057   sumPtTrackIsoForEgammaSC_barrel_(sumPtTrackIsoForEgammaSC_barrel),
00058   sumPtTrackIsoForEgammaSC_endcap_(sumPtTrackIsoForEgammaSC_endcap),
00059   nTrackIsoForEgammaSC_(nTrackIsoForEgammaSC),
00060   coneTrackIsoForEgammaSC_(coneTrackIsoForEgammaSC)                                                                
00061 {
00062   // Set the tmva reader
00063   tmvaReader_ = new TMVA::Reader("!Color:Silent");
00064   tmvaReader_->AddVariable("lnPt_gsf",&lnPt_gsf);
00065   tmvaReader_->AddVariable("Eta_gsf",&Eta_gsf);
00066   tmvaReader_->AddVariable("dPtOverPt_gsf",&dPtOverPt_gsf);
00067   tmvaReader_->AddVariable("DPtOverPt_gsf",&DPtOverPt_gsf);
00068   //tmvaReader_->AddVariable("nhit_gsf",&nhit_gsf);
00069   tmvaReader_->AddVariable("chi2_gsf",&chi2_gsf);
00070   //tmvaReader_->AddVariable("DPtOverPt_kf",&DPtOverPt_kf);
00071   tmvaReader_->AddVariable("nhit_kf",&nhit_kf);
00072   tmvaReader_->AddVariable("chi2_kf",&chi2_kf);
00073   tmvaReader_->AddVariable("EtotPinMode",&EtotPinMode);
00074   tmvaReader_->AddVariable("EGsfPoutMode",&EGsfPoutMode);
00075   tmvaReader_->AddVariable("EtotBremPinPoutMode",&EtotBremPinPoutMode);
00076   tmvaReader_->AddVariable("DEtaGsfEcalClust",&DEtaGsfEcalClust);
00077   tmvaReader_->AddVariable("SigmaEtaEta",&SigmaEtaEta);
00078   tmvaReader_->AddVariable("HOverHE",&HOverHE);
00079 //   tmvaReader_->AddVariable("HOverPin",&HOverPin);
00080   tmvaReader_->AddVariable("lateBrem",&lateBrem);
00081   tmvaReader_->AddVariable("firstBrem",&firstBrem);
00082   tmvaReader_->BookMVA("BDT",mvaWeightFileEleID.c_str());
00083 }
00084 void PFElectronAlgo::RunPFElectron(const reco::PFBlockRef&  blockRef,
00085                                    std::vector<bool>& active){
00086 
00087   // the maps are initialized 
00088   AssMap associatedToGsf;
00089   AssMap associatedToBrems;
00090   AssMap associatedToEcal;
00091 
00092   // should be cleaned as often as often as possible
00093   elCandidate_.clear();
00094   electronExtra_.clear();
00095   allElCandidate_.clear();
00096   electronConstituents_.clear();
00097   fifthStepKfTrack_.clear();
00098   convGsfTrack_.clear();
00099   // SetLinks finds all the elements (kf,ecal,ps,hcal,brems) 
00100   // associated to each gsf track
00101   bool blockHasGSF = SetLinks(blockRef,associatedToGsf,
00102                               associatedToBrems,associatedToEcal,
00103                               active);
00104   
00105   // check if there is at least a gsf track in the block. 
00106   if (blockHasGSF) {
00107     
00108     BDToutput_.clear();
00109 
00110     lockExtraKf_.clear();
00111     // For each GSF track is initialized a BDT value = -1
00112     BDToutput_.assign(associatedToGsf.size(),-1.);
00113     lockExtraKf_.assign(associatedToGsf.size(),true);
00114 
00115     // The FinalID is run and BDToutput values is assigned 
00116     SetIDOutputs(blockRef,associatedToGsf,associatedToBrems,associatedToEcal);  
00117 
00118     // For each GSF track that pass the BDT configurable cut a pf candidate electron is created. 
00119     // This function finds also the best estimation of the initial electron 4-momentum.
00120 
00121     SetCandidates(blockRef,associatedToGsf,associatedToBrems,associatedToEcal);
00122     if (elCandidate_.size() > 0 ){
00123       isvalid_ = true;
00124       // when a pfelectron candidate is created all the elements associated to the
00125       // electron are locked. 
00126       SetActive(blockRef,associatedToGsf,associatedToBrems,associatedToEcal,active);
00127     }
00128   } // endif blockHasGSF
00129 }
00130 bool PFElectronAlgo::SetLinks(const reco::PFBlockRef&  blockRef,
00131                               AssMap& associatedToGsf_,
00132                               AssMap& associatedToBrems_,
00133                               AssMap& associatedToEcal_,     
00134                               std::vector<bool>& active){
00135   unsigned int CutIndex = 100000;
00136   double CutGSFECAL = 10000. ;  
00137   // no other cut are not used anymore. We use the default of PFBlockAlgo
00138   //PFEnergyCalibration pfcalib_;  
00139   bool DebugSetLinksSummary = false;
00140   bool DebugSetLinksDetailed = false;
00141 
00142   const reco::PFBlock& block = *blockRef;
00143   const edm::OwnVector< reco::PFBlockElement >&  elements = block.elements();
00144   PFBlock::LinkData linkData =  block.linkData();  
00145   
00146   bool IsThereAGSFTrack = false;
00147   bool IsThereAGoodGSFTrack = false;
00148 
00149   vector<unsigned int> trackIs(0);
00150   vector<unsigned int> gsfIs(0);
00151   vector<unsigned int> ecalIs(0);
00152 
00153   std::vector<bool> localactive(elements.size(),true);
00154  
00155 
00156   // Save the elements in shorter vectors like in PFAlgo.
00157   std::multimap<double, unsigned int> kfElems;
00158   for(unsigned int iEle=0; iEle<elements.size(); iEle++) {
00159     localactive[iEle] = active[iEle];
00160     bool thisIsAMuon = false;
00161     PFBlockElement::Type type = elements[iEle].type();
00162     switch( type ) {
00163     case PFBlockElement::TRACK:
00164       // Check if the track is already identified as a muon
00165       thisIsAMuon =  PFMuonAlgo::isMuon(elements[iEle]);
00166       // Otherwise store index
00167       if ( !thisIsAMuon && active[iEle] ) { 
00168         trackIs.push_back( iEle );
00169         if (DebugSetLinksDetailed) 
00170           cout<<"TRACK, stored index, continue "<< iEle << endl;
00171       }
00172       continue;
00173     case PFBlockElement::GSF:
00174       // Check if the track has a KF partner identified as a muon
00175       block.associatedElements( iEle,linkData,
00176                                 kfElems,
00177                                 reco::PFBlockElement::TRACK,
00178                                 reco::PFBlock::LINKTEST_ALL );
00179       thisIsAMuon = kfElems.size() ? 
00180       PFMuonAlgo::isMuon(elements[kfElems.begin()->second]) : false;
00181       // Otherwise store index
00182       if ( !thisIsAMuon && active[iEle] ) { 
00183         IsThereAGSFTrack = true;    
00184         gsfIs.push_back( iEle );
00185         if (DebugSetLinksDetailed) 
00186           cout<<"GSF, stored index, continue "<< iEle << endl;
00187       }
00188       continue;
00189     case PFBlockElement::ECAL: 
00190       if ( active[iEle]  ) { 
00191         ecalIs.push_back( iEle );
00192         if (DebugSetLinksDetailed) 
00193           cout<<"ECAL, stored index, continue "<< iEle << endl;
00194       }
00195       continue;
00196     default:
00197       continue;
00198     }
00199   }
00200   // ******************* Start Link *****************************
00201   // Do something only if a gsf track is found in the block
00202   if(IsThereAGSFTrack) {
00203     
00204 
00205     // LocalLock the Elements associated to a Kf tracks and not to a Gsf
00206     // The clusters associated both to a kf track and to a brem tangend 
00207     // are then assigned only to the kf track
00208     // Could be improved doing this after. 
00209 
00210     // 19 Mar 2010 adding the KF track from Gamma Conv. 
00211     // They are linked to the GSF tracks they are not considered
00212     // anymore in the following ecal cluster locking 
00213     if (DebugSetLinksDetailed) {
00214       cout<<"#########################################################"<<endl;
00215       cout<<"#####           Process Block:                      #####"<<endl;
00216       cout<<"#########################################################"<<endl;
00217       cout<<block<<endl;
00218     }      
00219 
00220 
00221     for(unsigned int iEle=0; iEle<trackIs.size(); iEle++) {
00222       std::multimap<double, unsigned int> gsfElems;
00223       block.associatedElements( trackIs[iEle],  linkData,
00224                                 gsfElems ,
00225                                 reco::PFBlockElement::GSF,
00226                                 reco::PFBlock::LINKTEST_ALL );
00227       if(gsfElems.size() == 0){
00228         // This means that the considered kf is *not* associated
00229         // to any gsf track
00230         std::multimap<double, unsigned int> ecalKfElems;
00231         block.associatedElements( trackIs[iEle],linkData,
00232                                   ecalKfElems,
00233                                   reco::PFBlockElement::ECAL,
00234                                   reco::PFBlock::LINKTEST_ALL );
00235         if(ecalKfElems.size() > 0) { 
00236           unsigned int ecalKf_index = ecalKfElems.begin()->second;
00237           if(localactive[ecalKf_index]==true) {
00238             // Check if this clusters is however well linked to a primary gsf track
00239             // if this the case the cluster is not locked.
00240             
00241             bool isGsfLinked = false;
00242             for(unsigned int iGsf=0; iGsf<gsfIs.size(); iGsf++) {  
00243               // if the ecal cluster is associated contemporary to a KF track
00244               // and to a GSF track from conv, it is assigned to the KF track 
00245               // In this way we can loose some cluster but it is safer for double counting. 
00246               const reco::PFBlockElementGsfTrack * GsfEl  =  
00247                 dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[gsfIs[iGsf]]));
00248               if(GsfEl->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)) continue;
00249 
00250               std::multimap<double, unsigned int> ecalGsfElems;
00251               block.associatedElements( gsfIs[iGsf],linkData,
00252                                         ecalGsfElems,
00253                                         reco::PFBlockElement::ECAL,
00254                                         reco::PFBlock::LINKTEST_ALL );
00255               if(ecalGsfElems.size() > 0) {
00256                 if (ecalGsfElems.begin()->second == ecalKf_index) {
00257                   isGsfLinked = true;
00258                 }
00259               }
00260             }
00261             if(isGsfLinked == false) {
00262               // add protection against energy loss because
00263               // of the tracking fifth step
00264               const reco::PFBlockElementTrack * kfEle =  
00265                 dynamic_cast<const reco::PFBlockElementTrack*>((&elements[(trackIs[iEle])]));   
00266               reco::TrackRef refKf = kfEle->trackRef();
00267               // add nExHits = 0
00268               int nexhits = refKf->trackerExpectedHitsInner().numberOfLostHits();  
00269 
00270               unsigned int Algo = 0;
00271               if (refKf.isNonnull()) 
00272                 Algo = refKf->algo(); 
00273               // if(Algo < 9) {
00274               if(Algo < 9 && nexhits == 0) {
00275                 localactive[ecalKf_index] = false;
00276               }
00277               else {
00278                 fifthStepKfTrack_.push_back(make_pair(ecalKf_index,trackIs[iEle]));
00279               }
00280             }
00281           }
00282         }
00283       } // gsfElems.size()
00284     } // loop on kf tracks
00285 
00286 
00287     // start loop on gsf tracks
00288     for(unsigned int iEle=0; iEle<gsfIs.size(); iEle++) {  
00289 
00290       if (!localactive[(gsfIs[iEle])]) continue;  
00291 
00292       localactive[gsfIs[iEle]] = false;
00293       bool ClosestEcalWithKf = false;
00294 
00295       if (DebugSetLinksDetailed) cout << " Gsf Index " << gsfIs[iEle] << endl;
00296 
00297       const reco::PFBlockElementGsfTrack * GsfEl  =  
00298         dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[(gsfIs[iEle])]));
00299 
00300       // if GsfTrack fron converted bremsstralung continue
00301       if(GsfEl->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)) continue;
00302       IsThereAGoodGSFTrack = true;
00303       float eta_gsf = GsfEl->positionAtECALEntrance().eta();
00304       float etaOut_gsf = GsfEl->Pout().eta();
00305       float diffOutEcalEta =  fabs(eta_gsf-etaOut_gsf);
00306       reco::GsfTrackRef RefGSF = GsfEl->GsftrackRef();
00307       float Pin_gsf   = 0.01;
00308       if (RefGSF.isNonnull() ) 
00309         Pin_gsf = RefGSF->pMode();
00310       
00311 
00312       // Find Associated Kf Track elements and Ecal to KF elements
00313       unsigned int KfGsf_index = CutIndex;
00314       unsigned int KfGsf_secondIndex = CutIndex; 
00315       std::multimap<double, unsigned int> kfElems;
00316       block.associatedElements( gsfIs[iEle],linkData,
00317                                 kfElems,
00318                                 reco::PFBlockElement::TRACK,
00319                                 reco::PFBlock::LINKTEST_ALL );
00320       std::multimap<double, unsigned int> ecalKfElems;
00321       if (kfElems.size() > 0) {
00322         // 19 Mar 2010 now a loop is needed because > 1 KF track could
00323         // be associated to the same GSF track
00324 
00325         for(std::multimap<double, unsigned int>::iterator itkf = kfElems.begin();
00326             itkf != kfElems.end(); ++itkf) {
00327           const reco::PFBlockElementTrack * TrkEl  =  
00328             dynamic_cast<const reco::PFBlockElementTrack*>((&elements[itkf->second]));
00329           
00330           bool isPrim = isPrimaryTrack(*TrkEl,*GsfEl);
00331           if(!isPrim) 
00332             continue;
00333           
00334           if(localactive[itkf->second] == true) {
00335 
00336             KfGsf_index = itkf->second;
00337             localactive[KfGsf_index] = false;
00338             // Find clusters associated to kftrack using linkbyrechit
00339             block.associatedElements( KfGsf_index,  linkData,
00340                                       ecalKfElems ,
00341                                       reco::PFBlockElement::ECAL,
00342                                       reco::PFBlock::LINKTEST_ALL );  
00343           }
00344           else {          
00345             KfGsf_secondIndex = itkf->second;
00346           }
00347         }
00348       }
00349       
00350       // Find the closest Ecal clusters associated to this Gsf
00351       std::multimap<double, unsigned int> ecalGsfElems;
00352       block.associatedElements( gsfIs[iEle],linkData,
00353                                 ecalGsfElems,
00354                                 reco::PFBlockElement::ECAL,
00355                                 reco::PFBlock::LINKTEST_ALL );    
00356       double ecalGsf_dist = CutGSFECAL;
00357       unsigned int ClosestEcalGsf_index = CutIndex;
00358       if (ecalGsfElems.size() > 0) {    
00359         if(localactive[(ecalGsfElems.begin()->second)] == true) {
00360           // check energy compatibility for outer eta != ecal entrance, looping tracks
00361           bool compatibleEPout = true;
00362           if(diffOutEcalEta > 0.3) {
00363             reco::PFClusterRef clusterRef = elements[(ecalGsfElems.begin()->second)].clusterRef();      
00364             float EoPout = (clusterRef->energy())/(GsfEl->Pout().t());
00365             if(EoPout > 5) 
00366               compatibleEPout = false;
00367           }
00368           if(compatibleEPout) {
00369             ClosestEcalGsf_index = ecalGsfElems.begin()->second;
00370             ecalGsf_dist = block.dist(gsfIs[iEle],ClosestEcalGsf_index,
00371                                       linkData,reco::PFBlock::LINKTEST_ALL);
00372             
00373             // Check that this cluster is not closer to another primary Gsf track
00374             
00375             std::multimap<double, unsigned int> ecalOtherGsfElems;
00376             block.associatedElements( ClosestEcalGsf_index,linkData,
00377                                       ecalOtherGsfElems,
00378                                       reco::PFBlockElement::GSF,
00379                                       reco::PFBlock::LINKTEST_ALL);
00380             
00381             if(ecalOtherGsfElems.size()>0) {
00382               // get if it is closed to a conv brem gsf tracks
00383               const reco::PFBlockElementGsfTrack * gsfCheck  =  
00384                 dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[ecalOtherGsfElems.begin()->second]));
00385               
00386               if(ecalOtherGsfElems.begin()->second != gsfIs[iEle]&&
00387                  gsfCheck->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) == false) {             
00388                 ecalGsf_dist = CutGSFECAL;
00389                 ClosestEcalGsf_index = CutIndex;
00390               }
00391             }
00392           }
00393           // do not lock at the moment we need this for the late brem
00394         }
00395       }
00396       // if any cluster is found with the gsf-ecal link, try with kf-ecal
00397       else if(ecalKfElems.size() > 0) {
00398         if(localactive[(ecalKfElems.begin()->second)] == true) {
00399           ClosestEcalGsf_index = ecalKfElems.begin()->second;     
00400           ecalGsf_dist = block.dist(gsfIs[iEle],ClosestEcalGsf_index,
00401                                     linkData,reco::PFBlock::LINKTEST_ALL);
00402           ClosestEcalWithKf = true;
00403           
00404           // Check if this cluster is not closer to another Gsf track
00405           std::multimap<double, unsigned int> ecalOtherGsfElems;
00406           block.associatedElements( ClosestEcalGsf_index,linkData,
00407                                     ecalOtherGsfElems,
00408                                     reco::PFBlockElement::GSF,
00409                                     reco::PFBlock::LINKTEST_ALL);
00410           if(ecalOtherGsfElems.size() > 0) {
00411             const reco::PFBlockElementGsfTrack * gsfCheck  =  
00412               dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[ecalOtherGsfElems.begin()->second]));
00413 
00414             if(ecalOtherGsfElems.begin()->second != gsfIs[iEle] &&
00415                gsfCheck->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) == false) {
00416               ecalGsf_dist = CutGSFECAL;
00417               ClosestEcalGsf_index = CutIndex;
00418               ClosestEcalWithKf = false;
00419             }
00420           }
00421         }
00422       }
00423 
00424       if (DebugSetLinksDetailed) 
00425         cout << " Closest Ecal to the Gsf/Kf: index " << ClosestEcalGsf_index 
00426              << " dist " << ecalGsf_dist << endl;
00427       
00428       
00429       
00430       //  Find the brems associated to this Gsf
00431       std::multimap<double, unsigned int> bremElems;
00432       block.associatedElements( gsfIs[iEle],linkData,
00433                                 bremElems,
00434                                 reco::PFBlockElement::BREM,
00435                                 reco::PFBlock::LINKTEST_ALL );
00436       
00437       
00438       multimap<unsigned int,unsigned int> cleanedEcalBremElems;
00439       vector<unsigned int> keyBremIndex(0);
00440       unsigned int latestBrem_trajP = 0;     
00441       unsigned int latestBrem_index = CutIndex;
00442       for(std::multimap<double, unsigned int>::iterator ieb = bremElems.begin(); 
00443           ieb != bremElems.end(); ++ieb ) {
00444         unsigned int brem_index = ieb->second;
00445         if(localactive[brem_index] == false) continue;
00446 
00447 
00448         // Find the ecal clusters associated to the brems
00449         std::multimap<double, unsigned int> ecalBremsElems;
00450 
00451         block.associatedElements( brem_index,  linkData,
00452                                   ecalBremsElems,
00453                                   reco::PFBlockElement::ECAL,
00454                                   reco::PFBlock::LINKTEST_ALL );
00455 
00456         for (std::multimap<double, unsigned int>::iterator ie = ecalBremsElems.begin();
00457              ie != ecalBremsElems.end();ie++) {
00458           unsigned int ecalBrem_index = ie->second;
00459           if(localactive[ecalBrem_index] == false) continue;
00460 
00461           //to be changed, using the distance
00462           float ecalBrem_dist = block.dist(brem_index,ecalBrem_index,
00463                                            linkData,reco::PFBlock::LINKTEST_ALL); 
00464           
00465           
00466           if (ecalBrem_index == ClosestEcalGsf_index && (ecalBrem_dist + 0.0012) > ecalGsf_dist) continue;
00467 
00468           // Find the closest brem
00469           std::multimap<double, unsigned int> sortedBremElems;
00470           block.associatedElements( ecalBrem_index,linkData,
00471                                     sortedBremElems,
00472                                     reco::PFBlockElement::BREM,
00473                                     reco::PFBlock::LINKTEST_ALL);
00474           // check that this brem is that one coming from the same *primary* gsf
00475           bool isGoodBrem = false;
00476           unsigned int sortedBrem_index =  CutIndex;
00477           for (std::multimap<double, unsigned int>::iterator ibs = sortedBremElems.begin();
00478                ibs != sortedBremElems.end();ibs++) {
00479             unsigned int temp_sortedBrem_index = ibs->second;
00480             std::multimap<double, unsigned int> sortedGsfElems;
00481             block.associatedElements( temp_sortedBrem_index,linkData,
00482                                       sortedGsfElems,
00483                                       reco::PFBlockElement::GSF,
00484                                       reco::PFBlock::LINKTEST_ALL);
00485             bool enteredInPrimaryGsf = false;
00486             for (std::multimap<double, unsigned int>::iterator igs = sortedGsfElems.begin();
00487                  igs != sortedGsfElems.end();igs++) {
00488               const reco::PFBlockElementGsfTrack * gsfCheck  =  
00489                 dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[igs->second]));
00490 
00491               if(gsfCheck->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) == false) {
00492                 if(igs->second ==  gsfIs[iEle]) {
00493                   isGoodBrem = true;
00494                   sortedBrem_index = temp_sortedBrem_index;
00495                 }
00496                 enteredInPrimaryGsf = true;
00497                 break;
00498               }
00499             }
00500             if(enteredInPrimaryGsf)
00501               break;
00502           }
00503 
00504           if(isGoodBrem) { 
00505 
00506             //  Check that this cluster is not closer to another Gsf Track
00507             // The check is not performed on KF track because the ecal clusters are aready locked.
00508             std::multimap<double, unsigned int> ecalOtherGsfElems;
00509             block.associatedElements( ecalBrem_index,linkData,
00510                                       ecalOtherGsfElems,
00511                                       reco::PFBlockElement::GSF,
00512                                       reco::PFBlock::LINKTEST_ALL);
00513             if (ecalOtherGsfElems.size() > 0) {
00514               const reco::PFBlockElementGsfTrack * gsfCheck  =  
00515                 dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[ecalOtherGsfElems.begin()->second]));
00516               if(ecalOtherGsfElems.begin()->second != gsfIs[iEle] &&
00517                  gsfCheck->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) == false) {
00518                 continue;
00519               }
00520             }
00521 
00522             const reco::PFBlockElementBrem * BremEl  =  
00523               dynamic_cast<const reco::PFBlockElementBrem*>((&elements[sortedBrem_index]));
00524 
00525             reco::PFClusterRef clusterRef = 
00526               elements[ecalBrem_index].clusterRef();
00527             
00528 
00529             float sortedBremEcal_deta = fabs(clusterRef->position().eta() - BremEl->positionAtECALEntrance().eta());
00530             // Triangular cut on plan chi2:deta -> OLD
00531             //if((0.0075*sortedBremEcal_chi2 + 100.*sortedBremEcal_deta -1.5) < 0.) {
00532             if(sortedBremEcal_deta < 0.015) {
00533             
00534               cleanedEcalBremElems.insert(pair<unsigned int,unsigned int>(sortedBrem_index,ecalBrem_index));
00535               
00536               unsigned int BremTrajP = BremEl->indTrajPoint();
00537               if (BremTrajP > latestBrem_trajP) {
00538                 latestBrem_trajP = BremTrajP;
00539                 latestBrem_index = sortedBrem_index;
00540               }
00541               if (DebugSetLinksDetailed)
00542                 cout << " brem Index " <<  sortedBrem_index 
00543                      << " associated cluster " << ecalBrem_index << " BremTrajP " << BremTrajP <<endl;
00544               
00545               // > 1 ecal clusters could be associated to the same brem twice: allowed N-1 link. 
00546               // But the brem need to be stored once. 
00547               // locallock the brem and the ecal clusters
00548               localactive[ecalBrem_index] = false;  // the cluster
00549               bool  alreadyfound = false;
00550               for(unsigned int ii=0;ii<keyBremIndex.size();ii++) {
00551                 if (sortedBrem_index == keyBremIndex[ii]) alreadyfound = true;
00552               }
00553               if (alreadyfound == false) {
00554                 keyBremIndex.push_back(sortedBrem_index);
00555                 localactive[sortedBrem_index] = false;   // the brem
00556               }
00557             }
00558           }
00559         }
00560       }
00561 
00562       
00563       // Find Possible Extra Cluster associated to the gsf/kf
00564       vector<unsigned int> GsfElemIndex(0);
00565       vector<unsigned int> EcalIndex(0);
00566 
00567       // locallock the ecal cluster associated to the gsf
00568       if (ClosestEcalGsf_index < CutIndex) {
00569         GsfElemIndex.push_back(ClosestEcalGsf_index);
00570         localactive[ClosestEcalGsf_index] = false;
00571         for (std::multimap<double, unsigned int>::iterator ii = ecalGsfElems.begin();
00572              ii != ecalGsfElems.end();ii++) {   
00573           if(localactive[ii->second]) {
00574             // Check that this cluster is not closer to another Gsf Track
00575             std::multimap<double, unsigned int> ecalOtherGsfElems;
00576             block.associatedElements( ii->second,linkData,
00577                                       ecalOtherGsfElems,
00578                                       reco::PFBlockElement::GSF,
00579                                       reco::PFBlock::LINKTEST_ALL);
00580             if(ecalOtherGsfElems.size()) {
00581               if(ecalOtherGsfElems.begin()->second != gsfIs[iEle]) continue;
00582             } 
00583             
00584             // get the cluster only if the deta (ecal-gsf) < 0.05
00585             reco::PFClusterRef clusterRef = elements[(ii->second)].clusterRef();
00586             float etacl =  clusterRef->eta();
00587             if( fabs(eta_gsf-etacl) < 0.05) {       
00588               GsfElemIndex.push_back(ii->second);
00589               localactive[ii->second] = false;
00590               if (DebugSetLinksDetailed)
00591                 cout << " ExtraCluster From Gsf " << ii->second << endl;
00592             }
00593           }
00594         }
00595       }
00596 
00597       //Add the possibility to link other ecal clusters from kf. 
00598      
00599 //       for (std::multimap<double, unsigned int>::iterator ii = ecalKfElems.begin();
00600 //         ii != ecalKfElems.end();ii++) {
00601 //      if(localactive[ii->second]) {
00602 //         // Check that this cluster is not closer to another Gsf Track    
00603 //        std::multimap<double, unsigned int> ecalOtherGsfElems;
00604 //        block.associatedElements( ii->second,linkData,
00605 //                                  ecalOtherGsfElems,
00606 //                                  reco::PFBlockElement::GSF,
00607 //                                  reco::PFBlock::LINKTEST_CHI2);
00608 //        if(ecalOtherGsfElems.size()) {
00609 //          if(ecalOtherGsfElems.begin()->second != gsfIs[iEle]) continue;
00610 //        } 
00611 //        GsfElemIndex.push_back(ii->second);
00612 //        reco::PFClusterRef clusterRef = elements[(ii->second)].clusterRef();
00613 //        float etacl =  clusterRef->eta();
00614 //        if( fabs(eta_gsf-etacl) < 0.05) {         
00615 //          localactive[ii->second] = false;
00616 //          if (DebugSetLinksDetailed)
00617 //            cout << " ExtraCluster From KF " << ii->second << endl;
00618 //        }
00619 //      }
00620 //       }
00621       
00622       //****************** Fill Maps *************************
00623 
00624       // The GsfMap    
00625 
00626       // if any clusters have been associated to the gsf track    
00627       // use the Ecal clusters associated to the latest brem and associate it to the gsf
00628        if(GsfElemIndex.size() == 0){
00629         if(latestBrem_index < CutIndex) {
00630           unsigned int ckey = cleanedEcalBremElems.count(latestBrem_index);
00631           if(ckey == 1) {
00632             unsigned int temp_cal = 
00633               cleanedEcalBremElems.find(latestBrem_index)->second;
00634             GsfElemIndex.push_back(temp_cal);
00635             if (DebugSetLinksDetailed)
00636               cout << "******************** Gsf Cluster From Brem " << temp_cal 
00637                    << " Latest Brem index " << latestBrem_index 
00638                    << " ************************* " << endl;
00639           }
00640           else{
00641             pair<multimap<unsigned int,unsigned int>::iterator,multimap<unsigned int,unsigned int>::iterator> ret;
00642             ret = cleanedEcalBremElems.equal_range(latestBrem_index);
00643             multimap<unsigned int,unsigned int>::iterator it;
00644             for(it=ret.first; it!=ret.second; ++it) {
00645               GsfElemIndex.push_back((*it).second);
00646               if (DebugSetLinksDetailed)
00647                 cout << "******************** Gsf Cluster From Brem " << (*it).second 
00648                      << " Latest Brem index " << latestBrem_index 
00649                      << " ************************* " << endl;
00650             }
00651           }
00652           // erase the brem. 
00653           unsigned int elToErase = 0;
00654           for(unsigned int i = 0; i<keyBremIndex.size();i++) {
00655             if(latestBrem_index == keyBremIndex[i]) {
00656               elToErase = i;
00657             }
00658           }
00659           keyBremIndex.erase(keyBremIndex.begin()+elToErase);
00660         }       
00661       }
00662 
00663       // Get Extra Clusters from converted brem gsf tracks. The locallock method
00664       // tells me if the ecal cluster has been already assigned to the primary
00665       // gsf track or to a brem
00666 
00667       for(unsigned int iConv=0; iConv<gsfIs.size(); iConv++) {  
00668         if(iConv != iEle) {
00669 
00670           const reco::PFBlockElementGsfTrack * gsfConv  =  
00671             dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[(gsfIs[iConv])]));
00672           
00673           // look at only to secondary gsf tracks
00674           if(gsfConv->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)){
00675             if (DebugSetLinksDetailed)
00676               cout << "  PFElectronAlgo:: I'm running on convGsfBrem " << endl;
00677             // check if they are linked to the primary
00678             float conv_dist = block.dist(gsfIs[iConv],gsfIs[iEle],
00679                                          linkData,reco::PFBlock::LINKTEST_ALL);
00680             if(conv_dist > 0.) {
00681               // find the closest ecal cluster associated to conversions
00682 
00683               std::multimap<double, unsigned int> ecalConvElems;
00684               block.associatedElements( gsfIs[iConv],linkData,
00685                                         ecalConvElems,
00686                                         reco::PFBlockElement::ECAL,
00687                                         reco::PFBlock::LINKTEST_ALL );    
00688               if(ecalConvElems.size() > 0) {
00689                 // the ecal cluster is still active?
00690                 if(localactive[(ecalConvElems.begin()->second)] == true) {
00691                   if (DebugSetLinksDetailed)
00692                     cout << "  PFElectronAlgo:: convGsfBrem has a ECAL cluster linked and free" << endl;
00693                   // Check that this cluster is not closer to another primary Gsf track
00694                   std::multimap<double, unsigned int> ecalOtherGsfPrimElems;
00695                   block.associatedElements( ecalConvElems.begin()->second,linkData,
00696                                             ecalOtherGsfPrimElems,
00697                                             reco::PFBlockElement::GSF,
00698                                             reco::PFBlock::LINKTEST_ALL);
00699                   if(ecalOtherGsfPrimElems.size()>0) {
00700                     unsigned int gsfprimcheck_index = ecalOtherGsfPrimElems.begin()->second;
00701                     const reco::PFBlockElementGsfTrack * gsfCheck  =  
00702                       dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[gsfprimcheck_index]));
00703                     if(gsfCheck->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) == false) continue;
00704                     
00705                     reco::PFClusterRef clusterRef = elements[ecalConvElems.begin()->second].clusterRef();
00706                     if (DebugSetLinksDetailed)
00707                       cout << " PFElectronAlgo: !!!!!!! convGsfBrem ECAL cluster has been stored !!!!!!! "
00708                            << " Energy " << clusterRef->energy() << " eta,phi "  << clusterRef->position().eta()
00709                            <<", " <<  clusterRef->position().phi() << endl;
00710                  
00711                     GsfElemIndex.push_back(ecalConvElems.begin()->second);
00712                     convGsfTrack_.push_back(make_pair(ecalConvElems.begin()->second,gsfIs[iConv]));
00713                     localactive[ecalConvElems.begin()->second] = false;
00714                     
00715                   }
00716                 }
00717               }
00718             }
00719           }
00720         }
00721       }
00722 
00723 
00724       
00725       EcalIndex.insert(EcalIndex.end(),GsfElemIndex.begin(),GsfElemIndex.end());
00726       
00727       
00728 
00729       // The BremMap
00730       for(unsigned int i =0;i<keyBremIndex.size();i++) {
00731         unsigned int ikey = keyBremIndex[i];
00732         unsigned int ckey = cleanedEcalBremElems.count(ikey);
00733         vector<unsigned int> BremElemIndex(0);
00734         if(ckey == 1) {
00735           unsigned int temp_cal = 
00736             cleanedEcalBremElems.find(ikey)->second;
00737           BremElemIndex.push_back(temp_cal);
00738         }
00739         else{
00740           pair<multimap<unsigned int,unsigned int>::iterator,multimap<unsigned int,unsigned int>::iterator> ret;
00741           ret = cleanedEcalBremElems.equal_range(ikey);
00742           multimap<unsigned int,unsigned int>::iterator it;
00743           for(it=ret.first; it!=ret.second; ++it) {
00744             BremElemIndex.push_back((*it).second);
00745           }
00746         }
00747         EcalIndex.insert(EcalIndex.end(),BremElemIndex.begin(),BremElemIndex.end());
00748         associatedToBrems_.insert(pair<unsigned int,vector<unsigned int> >(ikey,BremElemIndex));
00749       }
00750 
00751       
00752       // 19 Mar 2010: add KF and ECAL elements from converted brem photons
00753       vector<unsigned int> convBremKFTrack;
00754       convBremKFTrack.clear();
00755       if (kfElems.size() > 0) {
00756         for(std::multimap<double, unsigned int>::iterator itkf = kfElems.begin();
00757             itkf != kfElems.end(); ++itkf) {
00758           const reco::PFBlockElementTrack * TrkEl  =  
00759             dynamic_cast<const reco::PFBlockElementTrack*>((&elements[itkf->second]));
00760           bool isPrim = isPrimaryTrack(*TrkEl,*GsfEl);
00761 
00762           if(!isPrim) {
00763 
00764             // search for linked ECAL clusters
00765             std::multimap<double, unsigned int> ecalConvElems;
00766             block.associatedElements( itkf->second,linkData,
00767                                       ecalConvElems,
00768                                       reco::PFBlockElement::ECAL,
00769                                       reco::PFBlock::LINKTEST_ALL );
00770             if(ecalConvElems.size() > 0) {
00771               // Further Cleaning: DANIELE This could be improved!
00772               TrackRef trkRef =   TrkEl->trackRef();
00773               // iter0, iter1, iter2, iter3 = Algo < 3
00774               unsigned int Algo = whichTrackAlgo(trkRef);
00775 
00776               float secpin = trkRef->p();       
00777               
00778               const reco::PFBlockElementCluster * clust =  
00779                 dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(ecalConvElems.begin()->second)])); 
00780               float eneclust  =clust->clusterRef()->energy();
00781 
00782               //1)  ******* Reject secondary KF tracks linked to also an HCAL cluster with H/(E+H) > 0.1
00783               //            This is applied also to KF linked to locked ECAL cluster
00784               //            NOTE: trusting the H/(E+H) and not the conv brem selection increse the number
00785               //                  of charged hadrons around the electron. DANIELE? re-think about this. 
00786               std::multimap<double, unsigned int> hcalConvElems;
00787               block.associatedElements( itkf->second,linkData,
00788                                         hcalConvElems,
00789                                         reco::PFBlockElement::HCAL,
00790                                         reco::PFBlock::LINKTEST_ALL );
00791 
00792               bool isHoHE = false;
00793               bool isHoE = false;
00794               bool isPoHE = false;
00795 
00796               float enehcalclust = -1;
00797               if(hcalConvElems.size() > 0) {
00798                 const reco::PFBlockElementCluster * clusthcal =  
00799                   dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(hcalConvElems.begin()->second)])); 
00800                 enehcalclust  =clusthcal->clusterRef()->energy();
00801                 // NOTE: DANIELE? Are you sure you want to use the Algo type here? 
00802                 if( (enehcalclust / (enehcalclust+eneclust) ) > 0.1 && Algo < 3) {
00803                   isHoHE = true;
00804                   if(enehcalclust > eneclust) 
00805                     isHoE = true;
00806                   if(secpin > (enehcalclust+eneclust) )
00807                     isPoHE = true;
00808                 }
00809               }
00810               
00811 
00812               if(localactive[(ecalConvElems.begin()->second)] == false) {
00813                 
00814                 if(isHoE || isPoHE) {
00815                   if (DebugSetLinksDetailed)
00816                     cout << "PFElectronAlgo:: LOCKED ECAL REJECTED TRACK FOR H/E or P/(H+E) "
00817                          << " H/H+E " << enehcalclust/(enehcalclust+eneclust)                 
00818                          << " H/E " <<  enehcalclust/eneclust
00819                          << " P/(H+E) " << secpin/(enehcalclust+eneclust) 
00820                          << " HCAL ENE " << enehcalclust 
00821                          << " ECAL ENE " << eneclust 
00822                          << " secPIN " << secpin 
00823                          << " Algo Track " << Algo << endl;
00824                   continue;
00825                 }
00826 
00827                 // check if this track has been alread assigned to an ECAL cluster
00828                 for(unsigned int iecal =0; iecal < EcalIndex.size(); iecal++) {
00829                   // in case this track is already assigned to a locked ECAL cluster
00830                   // the secondary kf track is also saved for further lock
00831                   if(EcalIndex[iecal] == ecalConvElems.begin()->second) {
00832                     if (DebugSetLinksDetailed)
00833                       cout << " PFElectronAlgo:: Conv Brem Recovery locked cluster and I will lock also the KF track " << endl; 
00834                     convBremKFTrack.push_back(itkf->second);
00835                   }
00836                 }
00837               }       
00838               else{
00839                 // ECAL cluster free
00840                 
00841                 // 
00842                 if(isHoHE){
00843                   if (DebugSetLinksDetailed)
00844                     cout << "PFElectronAlgo:: FREE ECAL REJECTED TRACK FOR H/H+E " 
00845                          << " H/H+E " <<  (enehcalclust / (enehcalclust+eneclust) ) 
00846                          << " H/E " <<  enehcalclust/eneclust
00847                          << " P/(H+E) " << secpin/(enehcalclust+eneclust) 
00848                          << " HCAL ENE " << enehcalclust 
00849                          << " ECAL ENE " << eneclust 
00850                          << " secPIN " << secpin 
00851                          << " Algo Track " << Algo << endl;
00852                   continue;
00853                 }
00854 
00855                 // check that this cluster is not cluser to another KF track (primary)
00856                 std::multimap<double, unsigned int> ecalOtherKFPrimElems;
00857                 block.associatedElements( ecalConvElems.begin()->second,linkData,
00858                                           ecalOtherKFPrimElems,
00859                                           reco::PFBlockElement::TRACK,
00860                                           reco::PFBlock::LINKTEST_ALL);
00861                 if(ecalOtherKFPrimElems.size() > 0) {
00862                   
00863                   // check that this ECAL clusters is the best associated to at least one of the  KF tracks
00864                   // linked to the considered GSF track
00865                   bool isFromGSF = false;
00866                   for(std::multimap<double, unsigned int>::iterator itclos = kfElems.begin();
00867                       itclos != kfElems.end(); ++itclos) {
00868                     if(ecalOtherKFPrimElems.begin()->second == itclos->second) {
00869                       isFromGSF = true;
00870                       break;
00871                     }
00872                   }
00873                   if(isFromGSF){
00874 
00875                     // Further Cleaning: DANIELE This could be improved!                                    
00876                   
00877                                           
00878                     float Epin = eneclust/secpin;
00879                     
00880                     // compute the pfsupercluster energy till now
00881                     float totenergy = 0.;
00882                     for(unsigned int ikeyecal = 0; 
00883                         ikeyecal<EcalIndex.size(); ikeyecal++){
00884                       // EcalIndex can have the same cluster save twice (because of the late brem cluster).
00885                       bool foundcluster = false;
00886                       if(ikeyecal > 0) {
00887                         for(unsigned int i2 = 0; i2<ikeyecal-1; i2++) {
00888                           if(EcalIndex[ikeyecal] == EcalIndex[i2]) 
00889                             foundcluster = true;
00890                         }
00891                       }
00892                       if(foundcluster) continue;
00893                       const reco::PFBlockElementCluster * clusasso =  
00894                         dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(EcalIndex[ikeyecal])])); 
00895                       totenergy += clusasso->clusterRef()->energy();
00896                     }
00897                     
00898                     // Further Cleaning: DANIELE This could be improved! 
00899                     //2) *****  Do not consider secondary tracks if the GSF and brems have failed in finding ECAL clusters
00900                     if(totenergy == 0.) {
00901                       if (DebugSetLinksDetailed)
00902                         cout << "PFElectronAlgo:: REJECTED_NULLTOT totenergy " << totenergy << endl;
00903                       continue;
00904                     }
00905                     
00906                     //3) ****** Reject secondary KF tracks that have an high E/secPin and that make worse the Etot/pin 
00907                     if(Epin > 3) {
00908                       double res_before = fabs((totenergy-Pin_gsf)/Pin_gsf);
00909                       double res_after = fabs(((totenergy+eneclust)-Pin_gsf)/Pin_gsf);
00910                       
00911                       if(res_before < res_after) {
00912                         if (DebugSetLinksDetailed)
00913                           cout << "PFElectronAlgo::REJECTED_RES totenergy " << totenergy << " Pin_gsf " << Pin_gsf << " cluster to secondary " <<  eneclust 
00914                                << " Res before " <<  res_before << " res_after " << res_after << endl;
00915                         continue;
00916                       }
00917                     }
00918                     
00919                     if (DebugSetLinksDetailed)
00920                       cout << "PFElectronAlgo:: conv brem found asso to ECAL linked to a secondary KF " << endl;
00921                     convBremKFTrack.push_back(itkf->second);
00922                     GsfElemIndex.push_back(ecalConvElems.begin()->second);
00923                     EcalIndex.push_back(ecalConvElems.begin()->second);
00924                     localactive[(ecalConvElems.begin()->second)] = false;
00925                     localactive[(itkf->second)] = false;
00926                   }
00927                 }
00928               }
00929             }
00930           }
00931         }
00932       }
00933  
00934       // 4May import EG supercluster
00935       if(EcalIndex.size() > 0 && useEGammaSupercluster_) {
00936         double sumEtEcalInTheCone  = 0.;
00937         
00938         // Position of the first cluster
00939         const reco::PFBlockElementCluster * clust =  
00940           dynamic_cast<const reco::PFBlockElementCluster*>((&elements[EcalIndex[0]])); 
00941         double PhiFC  = clust->clusterRef()->position().Phi();
00942         double EtaFC =  clust->clusterRef()->position().Eta();
00943 
00944         // Compute ECAL isolation ->
00945         for(unsigned int iEcal=0; iEcal<ecalIs.size(); iEcal++) {
00946           bool foundcluster = false;
00947           for(unsigned int ikeyecal = 0; 
00948               ikeyecal<EcalIndex.size(); ikeyecal++){
00949             if(ecalIs[iEcal] == EcalIndex[ikeyecal])
00950               foundcluster = true;
00951           }
00952           
00953           // -> only for clusters not already in the PFSCCluster
00954           if(foundcluster == false) {
00955             const reco::PFBlockElementCluster * clustExt =  
00956               dynamic_cast<const reco::PFBlockElementCluster*>((&elements[ecalIs[iEcal]])); 
00957             double eta_clust =  clustExt->clusterRef()->position().Eta();
00958             double phi_clust =  clustExt->clusterRef()->position().Phi();
00959             double theta_clust =  clustExt->clusterRef()->position().Theta();
00960             double deta_clust = eta_clust - EtaFC;
00961             double dphi_clust = phi_clust - PhiFC;
00962             if ( dphi_clust < -M_PI ) 
00963               dphi_clust = dphi_clust + 2.*M_PI;
00964             else if ( dphi_clust > M_PI ) 
00965               dphi_clust = dphi_clust - 2.*M_PI;
00966             double  DR = sqrt(deta_clust*deta_clust+
00967                               dphi_clust*dphi_clust);             
00968             
00969             //Jurassic veto in deta
00970             if(fabs(deta_clust) > 0.05 && DR < coneEcalIsoForEgammaSC_) {
00971               vector<double> ps1Ene(0);
00972               vector<double> ps2Ene(0);
00973               double ps1,ps2;
00974               ps1=ps2=0.;
00975               double EE_calib = thePFEnergyCalibration_->energyEm(*(clustExt->clusterRef()),ps1Ene,ps2Ene,ps1,ps2,applyCrackCorrections_);
00976               double ET_calib = EE_calib*sin(theta_clust);
00977               sumEtEcalInTheCone += ET_calib;
00978             }
00979           }
00980         } //EndLoop Additional ECAL clusters in the block
00981         
00982         // Compute track isolation: number of tracks && sumPt
00983         unsigned int sumNTracksInTheCone = 0;
00984         double sumPtTracksInTheCone = 0.;
00985         for(unsigned int iTrack=0; iTrack<trackIs.size(); iTrack++) {
00986           // the track from the electron are already locked at this stage
00987           if(localactive[(trackIs[iTrack])]==true) {
00988             const reco::PFBlockElementTrack * kfEle =  
00989               dynamic_cast<const reco::PFBlockElementTrack*>((&elements[(trackIs[iTrack])]));   
00990             reco::TrackRef trkref = kfEle->trackRef();
00991             if (trkref.isNonnull()) {
00992               double deta_trk =  trkref->eta() - RefGSF->etaMode();
00993               double dphi_trk =  trkref->phi() - RefGSF->phiMode();
00994               if ( dphi_trk < -M_PI ) 
00995                 dphi_trk = dphi_trk + 2.*M_PI;
00996               else if ( dphi_trk > M_PI ) 
00997                 dphi_trk = dphi_trk - 2.*M_PI;
00998               double  DR = sqrt(deta_trk*deta_trk+
00999                                 dphi_trk*dphi_trk);
01000               
01001               reco::HitPattern kfHitPattern = trkref->hitPattern();
01002               int NValPixelHit = kfHitPattern.numberOfValidPixelHits();
01003               
01004               if(DR < coneTrackIsoForEgammaSC_ && NValPixelHit >=3) {
01005                 sumNTracksInTheCone++;
01006                 sumPtTracksInTheCone+=trkref->pt();
01007               }
01008             }
01009           }
01010         }
01011 
01012         
01013         bool isBarrelIsolated = false;
01014         if( fabs(EtaFC < 1.478) && 
01015             (sumEtEcalInTheCone < sumEtEcalIsoForEgammaSC_barrel_ && 
01016              (sumNTracksInTheCone < nTrackIsoForEgammaSC_  || sumPtTracksInTheCone < sumPtTrackIsoForEgammaSC_barrel_)))
01017           isBarrelIsolated = true;
01018         
01019         
01020         bool isEndcapIsolated = false;
01021         if( fabs(EtaFC >= 1.478) && 
01022             (sumEtEcalInTheCone < sumEtEcalIsoForEgammaSC_endcap_ &&  
01023              (sumNTracksInTheCone < nTrackIsoForEgammaSC_  || sumPtTracksInTheCone < sumPtTrackIsoForEgammaSC_endcap_)))
01024           isEndcapIsolated = true;
01025         
01026 
01027         // only print out
01028         if(DebugSetLinksDetailed) {
01029           if(fabs(EtaFC < 1.478) && isBarrelIsolated == false) {
01030             cout << "**** PFElectronAlgo:: SUPERCLUSTER FOUND BUT FAILS ISOLATION:BARREL *** " 
01031                  << " sumEtEcalInTheCone " <<sumEtEcalInTheCone 
01032                  << " sumNTracksInTheCone " << sumNTracksInTheCone 
01033                  << " sumPtTracksInTheCone " << sumPtTracksInTheCone << endl;
01034           }
01035           if(fabs(EtaFC >= 1.478) && isEndcapIsolated == false) {
01036             cout << "**** PFElectronAlgo:: SUPERCLUSTER FOUND BUT FAILS ISOLATION:ENDCAP *** " 
01037                  << " sumEtEcalInTheCone " <<sumEtEcalInTheCone 
01038                  << " sumNTracksInTheCone " << sumNTracksInTheCone 
01039                  << " sumPtTracksInTheCone " << sumPtTracksInTheCone << endl;
01040           }
01041         }
01042 
01043 
01044 
01045         
01046         if(isBarrelIsolated || isEndcapIsolated ) {
01047           
01048           
01049           // Compute TotEnergy
01050           double totenergy = 0.;
01051           for(unsigned int ikeyecal = 0; 
01052               ikeyecal<EcalIndex.size(); ikeyecal++){
01053             // EcalIndex can have the same cluster save twice (because of the late brem cluster).
01054             bool foundcluster = false;
01055             if(ikeyecal > 0) {
01056               for(unsigned int i2 = 0; i2<ikeyecal-1; i2++) {
01057                 if(EcalIndex[ikeyecal] == EcalIndex[i2]) 
01058                   foundcluster = true;;
01059               }
01060             }
01061             if(foundcluster) continue;
01062             const reco::PFBlockElementCluster * clusasso =  
01063               dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(EcalIndex[ikeyecal])])); 
01064             totenergy += clusasso->clusterRef()->energy();
01065           }
01066           // End copute TotEnergy
01067 
01068 
01069           // Find extra cluster from e/g importing
01070           for(unsigned int ikeyecal = 0; 
01071               ikeyecal<EcalIndex.size(); ikeyecal++){
01072             // EcalIndex can have the same cluster save twice (because of the late brem cluster).
01073             bool foundcluster = false;
01074             if(ikeyecal > 0) {
01075               for(unsigned int i2 = 0; i2<ikeyecal-1; i2++) {
01076                 if(EcalIndex[ikeyecal] == EcalIndex[i2]) 
01077                   foundcluster = true;
01078               }
01079             }     
01080             if(foundcluster) continue;
01081             
01082             
01083             std::multimap<double, unsigned int> ecalFromSuperClusterElems;
01084             block.associatedElements( EcalIndex[ikeyecal],linkData,
01085                                       ecalFromSuperClusterElems,
01086                                       reco::PFBlockElement::ECAL,
01087                                       reco::PFBlock::LINKTEST_ALL);
01088             if(ecalFromSuperClusterElems.size() > 0) {
01089               for(std::multimap<double, unsigned int>::iterator itsc = ecalFromSuperClusterElems.begin();
01090                   itsc != ecalFromSuperClusterElems.end(); ++itsc) {
01091                 if(localactive[itsc->second] == false) {
01092                   continue;
01093                 }
01094                 
01095                 std::multimap<double, unsigned int> ecalOtherKFPrimElems;
01096                 block.associatedElements( itsc->second,linkData,
01097                                           ecalOtherKFPrimElems,
01098                                           reco::PFBlockElement::TRACK,
01099                                           reco::PFBlock::LINKTEST_ALL);
01100                 if(ecalOtherKFPrimElems.size() > 0) {
01101                   if(localactive[ecalOtherKFPrimElems.begin()->second] == true) {
01102                     if (DebugSetLinksDetailed)
01103                       cout << "**** PFElectronAlgo:: SUPERCLUSTER FOUND BUT FAILS KF VETO *** " << endl;
01104                     continue;
01105                   }
01106                 }
01107                 bool isInTheEtaRange = false;
01108                 const reco::PFBlockElementCluster * clustToAdd =  
01109                   dynamic_cast<const reco::PFBlockElementCluster*>((&elements[itsc->second])); 
01110                 double deta_clustToAdd = clustToAdd->clusterRef()->position().Eta() - EtaFC;
01111                 double ene_clustToAdd = clustToAdd->clusterRef()->energy();
01112                 
01113                 if(fabs(deta_clustToAdd) < 0.05)
01114                   isInTheEtaRange = true;
01115                 
01116                 // check for both KF and GSF
01117                 bool isBetterEpin = false;
01118                 if(isInTheEtaRange == false ) {
01119                   if (DebugSetLinksDetailed)
01120                     cout << "**** PFElectronAlgo:: SUPERCLUSTER FOUND BUT FAILS GAMMA DETA RANGE  *** " 
01121                          << fabs(deta_clustToAdd) << endl;
01122                   
01123                   if(KfGsf_index < CutIndex) {              
01124                     //GSF
01125                     double res_before_gsf = fabs((totenergy-Pin_gsf)/Pin_gsf);
01126                     double res_after_gsf = fabs(((totenergy+ene_clustToAdd)-Pin_gsf)/Pin_gsf);
01127 
01128                     //KF
01129                     const reco::PFBlockElementTrack * trackEl =  
01130                       dynamic_cast<const reco::PFBlockElementTrack*>((&elements[KfGsf_index])); 
01131                     double Pin_kf = trackEl->trackRef()->p();
01132                     double res_before_kf = fabs((totenergy-Pin_kf)/Pin_kf);
01133                     double res_after_kf = fabs(((totenergy+ene_clustToAdd)-Pin_kf)/Pin_kf);                           
01134                     
01135                     // The new cluster improve both the E/pin?
01136                     if(res_after_gsf < res_before_gsf && res_after_kf < res_before_kf ) {
01137                       isBetterEpin = true;
01138                     }
01139                     else {
01140                       if (DebugSetLinksDetailed)
01141                         cout << "**** PFElectronAlgo:: SUPERCLUSTER FOUND AND FAILS ALSO RES_EPIN" 
01142                              << " tot energy " << totenergy 
01143                              << " Pin_gsf " << Pin_gsf 
01144                              << " Pin_kf " << Pin_kf 
01145                              << " cluster from SC to ADD " <<  ene_clustToAdd 
01146                              << " Res before GSF " <<  res_before_gsf << " res_after_gsf " << res_after_gsf 
01147                              << " Res before KF " <<  res_before_kf << " res_after_kf " << res_after_kf  << endl;
01148                     }
01149                   }
01150                 }
01151                 
01152                 if(isInTheEtaRange || isBetterEpin) {           
01153                   if (DebugSetLinksDetailed)
01154                     cout << "!!!! PFElectronAlgo:: ECAL from SUPERCLUSTER FOUND !!!!! " << endl;
01155                   GsfElemIndex.push_back(itsc->second);
01156                   EcalIndex.push_back(itsc->second);
01157                   localactive[(itsc->second)] = false;
01158                 }
01159               }
01160             }
01161           }
01162         } // END ISOLATION IF
01163       }
01164 
01165 
01166       if(KfGsf_index < CutIndex) 
01167         GsfElemIndex.push_back(KfGsf_index);
01168       else if(KfGsf_secondIndex < CutIndex) 
01169         GsfElemIndex.push_back(KfGsf_secondIndex);
01170       
01171       // insert the secondary KF tracks
01172       GsfElemIndex.insert(GsfElemIndex.end(),convBremKFTrack.begin(),convBremKFTrack.end());
01173       GsfElemIndex.insert(GsfElemIndex.end(),keyBremIndex.begin(),keyBremIndex.end());
01174       associatedToGsf_.insert(pair<unsigned int, vector<unsigned int> >(gsfIs[iEle],GsfElemIndex));
01175 
01176       // The EcalMap
01177       for(unsigned int ikeyecal = 0; 
01178           ikeyecal<EcalIndex.size(); ikeyecal++){
01179         
01180 
01181         vector<unsigned int> EcalElemsIndex(0);
01182 
01183         std::multimap<double, unsigned int> PS1Elems;
01184         block.associatedElements( EcalIndex[ikeyecal],linkData,
01185                                   PS1Elems,
01186                                   reco::PFBlockElement::PS1,
01187                                   reco::PFBlock::LINKTEST_ALL );
01188         for( std::multimap<double, unsigned int>::iterator it = PS1Elems.begin();
01189              it != PS1Elems.end();it++) {
01190           unsigned int index = it->second;
01191           if(localactive[index] == true) {
01192             
01193             // Check that this cluster is not closer to another ECAL cluster
01194             std::multimap<double, unsigned> sortedECAL;
01195             block.associatedElements( index,  linkData,
01196                                       sortedECAL,
01197                                       reco::PFBlockElement::ECAL,
01198                                       reco::PFBlock::LINKTEST_ALL );
01199             unsigned jEcal = sortedECAL.begin()->second;
01200             if ( jEcal != EcalIndex[ikeyecal]) continue; 
01201 
01202 
01203             EcalElemsIndex.push_back(index);
01204             localactive[index] = false;
01205           }
01206         }
01207         
01208         std::multimap<double, unsigned int> PS2Elems;
01209         block.associatedElements( EcalIndex[ikeyecal],linkData,
01210                                   PS2Elems,
01211                                   reco::PFBlockElement::PS2,
01212                                   reco::PFBlock::LINKTEST_ALL );
01213         for( std::multimap<double, unsigned int>::iterator it = PS2Elems.begin();
01214              it != PS2Elems.end();it++) {
01215           unsigned int index = it->second;
01216           if(localactive[index] == true) {
01217             // Check that this cluster is not closer to another ECAL cluster
01218             std::multimap<double, unsigned> sortedECAL;
01219             block.associatedElements( index,  linkData,
01220                                       sortedECAL,
01221                                       reco::PFBlockElement::ECAL,
01222                                       reco::PFBlock::LINKTEST_ALL );
01223             unsigned jEcal = sortedECAL.begin()->second;
01224             if ( jEcal != EcalIndex[ikeyecal]) continue; 
01225             
01226             EcalElemsIndex.push_back(index);
01227             localactive[index] = false;
01228           }
01229         }
01230         if(ikeyecal == 0) {
01231           // The first cluster is that one coming from the Gsf. 
01232           // Only for this one is found the HCAL cluster using the Track-HCAL link
01233           // and not the Ecal-Hcal not well tested yet.
01234           std::multimap<double, unsigned int> hcalGsfElems;
01235           block.associatedElements( gsfIs[iEle],linkData,
01236                                     hcalGsfElems,
01237                                     reco::PFBlockElement::HCAL,
01238                                     reco::PFBlock::LINKTEST_ALL );      
01239           for( std::multimap<double, unsigned int>::iterator it = hcalGsfElems.begin();
01240                it != hcalGsfElems.end();it++) {
01241             unsigned int index = it->second;
01242             //  if(localactive[index] == true) {
01243 
01244               // Check that this cluster is not closer to another GSF
01245               // remove in high energetic jets this is dangerous. 
01246 //            std::multimap<double, unsigned> sortedGsf;
01247 //            block.associatedElements( index,  linkData,
01248 //                                      sortedGsf,
01249 //                                      reco::PFBlockElement::GSF,
01250 //                                      reco::PFBlock::LINKTEST_ALL );
01251 //            unsigned jGsf = sortedGsf.begin()->second;
01252 //            if ( jGsf != gsfIs[iEle]) continue; 
01253 
01254               EcalElemsIndex.push_back(index);
01255               localactive[index] = false;
01256               
01257               // }
01258           }
01259           // if the closest ecal cluster has been link with the KF, check KF - HCAL link
01260           if(hcalGsfElems.size() == 0 && ClosestEcalWithKf == true) {
01261             std::multimap<double, unsigned int> hcalKfElems;
01262             block.associatedElements( KfGsf_index,linkData,
01263                                       hcalKfElems,
01264                                       reco::PFBlockElement::HCAL,
01265                                       reco::PFBlock::LINKTEST_ALL );    
01266             for( std::multimap<double, unsigned int>::iterator it = hcalKfElems.begin();
01267                  it != hcalKfElems.end();it++) {
01268               unsigned int index = it->second;
01269               if(localactive[index] == true) {
01270                 
01271                 // Check that this cluster is not closer to another KF
01272                 std::multimap<double, unsigned> sortedKf;
01273                 block.associatedElements( index,  linkData,
01274                                           sortedKf,
01275                                           reco::PFBlockElement::TRACK,
01276                                           reco::PFBlock::LINKTEST_ALL );
01277                 unsigned jKf = sortedKf.begin()->second;
01278                 if ( jKf != KfGsf_index) continue; 
01279                 EcalElemsIndex.push_back(index);
01280                 localactive[index] = false;
01281               }
01282             }
01283           }
01284           // Find Other Primary Tracks Associated to the same Gsf Clusters
01285           std::multimap<double, unsigned int> kfEtraElems;
01286           block.associatedElements( EcalIndex[ikeyecal],linkData,
01287                                     kfEtraElems,
01288                                     reco::PFBlockElement::TRACK,
01289                                     reco::PFBlock::LINKTEST_ALL );
01290           if(kfEtraElems.size() > 0) {
01291             for( std::multimap<double, unsigned int>::iterator it = kfEtraElems.begin();
01292                  it != kfEtraElems.end();it++) {
01293               unsigned int index = it->second;
01294 
01295               // 19 Mar 2010 do not consider here tracks from gamma conv
01296              //  const reco::PFBlockElementTrack * kfTk =  
01297              //  dynamic_cast<const reco::PFBlockElementTrack*>((&elements[index]));         
01298               // DANIELE ?  It is not need because of the local locking 
01299               //   if(kfTk->isLinkedToDisplacedVertex()) continue;
01300 
01301               bool thisIsAMuon = false;
01302               thisIsAMuon =  PFMuonAlgo::isMuon(elements[index]);
01303               if (DebugSetLinksDetailed && thisIsAMuon)
01304                 cout << " This is a Muon: index " << index << endl;
01305               if(localactive[index] == true && !thisIsAMuon) {
01306                 if(index != KfGsf_index) {
01307                   // Check that this track is not closer to another ECAL cluster
01308                   // Not Sure here I need this step
01309                   std::multimap<double, unsigned> sortedECAL;
01310                   block.associatedElements( index,  linkData,
01311                                             sortedECAL,
01312                                             reco::PFBlockElement::ECAL,
01313                                             reco::PFBlock::LINKTEST_ALL );
01314                   unsigned jEcal = sortedECAL.begin()->second;
01315                   if ( jEcal != EcalIndex[ikeyecal]) continue; 
01316                   EcalElemsIndex.push_back(index);
01317                   localactive[index] = false;
01318                 }
01319               }
01320             }
01321           }       
01322 
01323         }
01324         associatedToEcal_.insert(pair<unsigned int,vector<unsigned int> >(EcalIndex[ikeyecal],EcalElemsIndex));
01325       }
01326     }// end type GSF
01327   } // endis there a gsf track
01328   
01329   // ******************* End Link *****************************
01330 
01331   // 
01332   // Below is only for debugging printout 
01333   if (DebugSetLinksSummary) {
01334     if(IsThereAGoodGSFTrack) {
01335       if (DebugSetLinksSummary) cout << " -- The Link Summary --" << endl;
01336       for(map<unsigned int,vector<unsigned int> >::iterator it = associatedToGsf_.begin();
01337           it != associatedToGsf_.end(); it++) {
01338         
01339         if (DebugSetLinksSummary) cout << " AssoGsf " << it->first << endl;
01340         vector<unsigned int> eleasso = it->second;
01341         for(unsigned int i=0;i<eleasso.size();i++) {
01342           PFBlockElement::Type type = elements[eleasso[i]].type();
01343           if(type == reco::PFBlockElement::BREM) {
01344             if (DebugSetLinksSummary) 
01345               cout << " AssoGsfElements BREM " <<  eleasso[i] <<  endl;
01346           }
01347           else if(type == reco::PFBlockElement::ECAL) {
01348             if (DebugSetLinksSummary) 
01349               cout << " AssoGsfElements ECAL " <<  eleasso[i] <<  endl;
01350           }
01351           else if(type == reco::PFBlockElement::TRACK) {
01352             if (DebugSetLinksSummary) 
01353               cout << " AssoGsfElements KF " <<  eleasso[i] <<  endl;
01354           }
01355           else {
01356             if (DebugSetLinksSummary) 
01357               cout << " AssoGsfElements ????? " <<  eleasso[i] <<  endl;
01358           }
01359         }
01360       }
01361       
01362       for(map<unsigned int,vector<unsigned int> >::iterator it = associatedToBrems_.begin();
01363           it != associatedToBrems_.end(); it++) {
01364         if (DebugSetLinksSummary) cout << " AssoBrem " << it->first << endl;
01365         vector<unsigned int> eleasso = it->second;
01366         for(unsigned int i=0;i<eleasso.size();i++) {
01367           PFBlockElement::Type type = elements[eleasso[i]].type();
01368           if(type == reco::PFBlockElement::ECAL) {
01369             if (DebugSetLinksSummary) 
01370               cout << " AssoBremElements ECAL " <<  eleasso[i] <<  endl;
01371           }
01372           else {
01373             if (DebugSetLinksSummary) 
01374               cout << " AssoBremElements ????? " <<  eleasso[i] <<  endl;
01375           }
01376         }
01377       }
01378       
01379       for(map<unsigned int,vector<unsigned int> >::iterator it = associatedToEcal_.begin();
01380           it != associatedToEcal_.end(); it++) {
01381         if (DebugSetLinksSummary) cout << " AssoECAL " << it->first << endl;
01382         vector<unsigned int> eleasso = it->second;
01383         for(unsigned int i=0;i<eleasso.size();i++) {
01384           PFBlockElement::Type type = elements[eleasso[i]].type();
01385           if(type == reco::PFBlockElement::PS1) {
01386             if (DebugSetLinksSummary) 
01387               cout << " AssoECALElements PS1  " <<  eleasso[i] <<  endl;
01388           }
01389           else if(type == reco::PFBlockElement::PS2) {
01390             if (DebugSetLinksSummary) 
01391               cout << " AssoECALElements PS2  " <<  eleasso[i] <<  endl;
01392           }
01393           else if(type == reco::PFBlockElement::HCAL) {
01394             if (DebugSetLinksSummary) 
01395               cout << " AssoECALElements HCAL  " <<  eleasso[i] <<  endl;
01396           }
01397           else {
01398             if (DebugSetLinksSummary) 
01399               cout << " AssoHCALElements ????? " <<  eleasso[i] <<  endl;
01400           }
01401         }
01402       }
01403       if (DebugSetLinksSummary) 
01404         cout << "-- End Summary --" <<  endl;
01405     }
01406     
01407   }
01408   // EndPrintOut
01409   return IsThereAGoodGSFTrack;
01410 }
01411 // This function get the associatedToGsf and associatedToBrems maps and run the final electronID. 
01412 void PFElectronAlgo::SetIDOutputs(const reco::PFBlockRef&  blockRef,
01413                                         AssMap& associatedToGsf_,
01414                                         AssMap& associatedToBrems_,
01415                                         AssMap& associatedToEcal_){
01416   //PFEnergyCalibration pfcalib_;  
01417   const reco::PFBlock& block = *blockRef;
01418   PFBlock::LinkData linkData =  block.linkData();     
01419   const edm::OwnVector< reco::PFBlockElement >&  elements = block.elements();
01420   bool DebugIDOutputs = false;
01421   if(DebugIDOutputs) cout << " ######## Enter in SetIDOutputs #########" << endl;
01422   
01423   unsigned int cgsf=0;
01424   for (map<unsigned int,vector<unsigned int> >::iterator igsf = associatedToGsf_.begin();
01425        igsf != associatedToGsf_.end(); igsf++,cgsf++) {
01426 
01427     float Ene_ecalgsf = 0.;
01428     float Ene_hcalgsf = 0.;
01429     double sigmaEtaEta = 0.;
01430     float deta_gsfecal = 0.;
01431     float Ene_ecalbrem = 0.;
01432     float Ene_extraecalgsf = 0.;
01433     bool LateBrem = false;
01434     // bool EarlyBrem = false;
01435     int FirstBrem = 1000;
01436     unsigned int ecalGsf_index = 100000;
01437     unsigned int kf_index = 100000;
01438     // unsigned int nhits_gsf = 0;
01439     int NumBrem = 0;
01440     reco::TrackRef RefKF;  
01441     double posX=0.;
01442     double posY=0.;
01443     double posZ=0.;
01444 
01445     unsigned int gsf_index =  igsf->first;
01446     const reco::PFBlockElementGsfTrack * GsfEl  =  
01447       dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[gsf_index]));
01448     reco::GsfTrackRef RefGSF = GsfEl->GsftrackRef();
01449     float Ein_gsf   = 0.;
01450     if (RefGSF.isNonnull()) {
01451       float m_el=0.00051;
01452       Ein_gsf =sqrt(RefGSF->pMode()*
01453                     RefGSF->pMode()+m_el*m_el);
01454       // nhits_gsf = RefGSF->hitPattern().trackerLayersWithMeasurement();
01455     }
01456     float Eout_gsf = GsfEl->Pout().t();
01457     float Etaout_gsf = GsfEl->positionAtECALEntrance().eta();
01458 
01459 
01460     if (DebugIDOutputs)  
01461       cout << " setIdOutput! GSF Track: Ein " <<  Ein_gsf 
01462            << " eta,phi " <<  Etaout_gsf
01463            <<", " << GsfEl->positionAtECALEntrance().phi() << endl;
01464     
01465 
01466     vector<unsigned int> assogsf_index = igsf->second;
01467     bool FirstEcalGsf = true;
01468     for  (unsigned int ielegsf=0;ielegsf<assogsf_index.size();ielegsf++) {
01469       PFBlockElement::Type assoele_type = elements[(assogsf_index[ielegsf])].type();
01470       
01471       
01472       // The RefKf is needed to build pure tracking observables
01473       if(assoele_type == reco::PFBlockElement::TRACK) {
01474         const reco::PFBlockElementTrack * KfTk =  
01475           dynamic_cast<const reco::PFBlockElementTrack*>((&elements[(assogsf_index[ielegsf])]));
01476         // 19 Mar 2010 do not consider here track from gamma conv
01477         
01478         bool isPrim = isPrimaryTrack(*KfTk,*GsfEl);
01479         if(!isPrim) continue;
01480         RefKF = KfTk->trackRef();
01481         kf_index = assogsf_index[ielegsf];
01482       }
01483       
01484    
01485       if  (assoele_type == reco::PFBlockElement::ECAL) {
01486         unsigned int keyecalgsf = assogsf_index[ielegsf];
01487         vector<unsigned int> assoecalgsf_index = associatedToEcal_.find(keyecalgsf)->second;
01488         
01489         vector<double> ps1Ene(0);
01490         vector<double> ps2Ene(0);
01491         for(unsigned int ips =0; ips<assoecalgsf_index.size();ips++) {
01492           PFBlockElement::Type typeassoecal = elements[(assoecalgsf_index[ips])].type();
01493           if  (typeassoecal == reco::PFBlockElement::PS1) {  
01494             PFClusterRef  psref = elements[(assoecalgsf_index[ips])].clusterRef();
01495             ps1Ene.push_back(psref->energy());
01496           }
01497           if  (typeassoecal == reco::PFBlockElement::PS2) {  
01498             PFClusterRef  psref = elements[(assoecalgsf_index[ips])].clusterRef();
01499             ps2Ene.push_back(psref->energy());
01500           }
01501           if  (typeassoecal == reco::PFBlockElement::HCAL) {
01502             const reco::PFBlockElementCluster * clust =  
01503               dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(assoecalgsf_index[ips])])); 
01504             Ene_hcalgsf+=clust->clusterRef()->energy();
01505           }
01506         }
01507         if (FirstEcalGsf) {
01508           FirstEcalGsf = false;
01509           ecalGsf_index = assogsf_index[ielegsf];
01510           reco::PFClusterRef clusterRef = elements[(assogsf_index[ielegsf])].clusterRef();        
01511           double ps1,ps2;
01512           ps1=ps2=0.;
01513           //      Ene_ecalgsf = pfcalib_.energyEm(*clusterRef,ps1Ene,ps2Ene);     
01514           Ene_ecalgsf = thePFEnergyCalibration_->energyEm(*clusterRef,ps1Ene,ps2Ene,ps1,ps2,applyCrackCorrections_);      
01515           //      std::cout << "Test " << Ene_ecalgsf <<  " PS1 / PS2 " << ps1 << " " << ps2 << std::endl;
01516           posX += Ene_ecalgsf * clusterRef->position().X();
01517           posY += Ene_ecalgsf * clusterRef->position().Y();
01518           posZ += Ene_ecalgsf * clusterRef->position().Z();
01519 
01520           if (DebugIDOutputs)  
01521             cout << " setIdOutput! GSF ECAL Cluster E " << Ene_ecalgsf
01522                  << " eta,phi " << clusterRef->position().eta()
01523                  <<", " <<  clusterRef->position().phi() << endl;
01524           
01525           deta_gsfecal = clusterRef->position().eta() - Etaout_gsf;
01526           
01527           vector< const reco::PFCluster * > pfClust_vec(0);
01528           pfClust_vec.clear();
01529           pfClust_vec.push_back(&(*clusterRef));
01530           
01531           PFClusterWidthAlgo pfwidth(pfClust_vec);
01532           sigmaEtaEta = pfwidth.pflowSigmaEtaEta();
01533 
01534 
01535         }
01536         else {
01537           reco::PFClusterRef clusterRef = elements[(assogsf_index[ielegsf])].clusterRef();                
01538           float TempClus_energy = thePFEnergyCalibration_->energyEm(*clusterRef,ps1Ene,ps2Ene,applyCrackCorrections_);   
01539           Ene_extraecalgsf += TempClus_energy;
01540           posX += TempClus_energy * clusterRef->position().X();
01541           posY += TempClus_energy * clusterRef->position().Y();
01542           posZ += TempClus_energy * clusterRef->position().Z();   
01543 
01544           if (DebugIDOutputs)
01545             cout << " setIdOutput! Extra ECAL Cluster E " 
01546                  << TempClus_energy << " Tot " <<  Ene_extraecalgsf << endl;
01547         }
01548       } // end type Ecal
01549 
01550       
01551       if  (assoele_type == reco::PFBlockElement::BREM) {
01552         unsigned int brem_index = assogsf_index[ielegsf];
01553         const reco::PFBlockElementBrem * BremEl  =  
01554           dynamic_cast<const reco::PFBlockElementBrem*>((&elements[brem_index]));
01555         int TrajPos = (BremEl->indTrajPoint())-2;
01556         //if (TrajPos <= 3) EarlyBrem = true;
01557         if (TrajPos < FirstBrem) FirstBrem = TrajPos;
01558 
01559         vector<unsigned int> assobrem_index = associatedToBrems_.find(brem_index)->second;
01560         for (unsigned int ibrem = 0; ibrem < assobrem_index.size(); ibrem++){
01561           if (elements[(assobrem_index[ibrem])].type() == reco::PFBlockElement::ECAL) {
01562             unsigned int keyecalbrem = assobrem_index[ibrem];
01563             vector<unsigned int> assoelebrem_index = associatedToEcal_.find(keyecalbrem)->second;
01564             vector<double> ps1EneFromBrem(0);
01565             vector<double> ps2EneFromBrem(0);
01566             for (unsigned int ielebrem=0; ielebrem<assoelebrem_index.size();ielebrem++) {
01567               if (elements[(assoelebrem_index[ielebrem])].type() == reco::PFBlockElement::PS1) {
01568                 PFClusterRef  psref = elements[(assoelebrem_index[ielebrem])].clusterRef();
01569                 ps1EneFromBrem.push_back(psref->energy());
01570               }
01571               if (elements[(assoelebrem_index[ielebrem])].type() == reco::PFBlockElement::PS2) {
01572                 PFClusterRef  psref = elements[(assoelebrem_index[ielebrem])].clusterRef();
01573                 ps2EneFromBrem.push_back(psref->energy());
01574               }        
01575             }
01576             // check if it is a compatible cluster also with the gsf track
01577             if( assobrem_index[ibrem] !=  ecalGsf_index) {
01578               reco::PFClusterRef clusterRef = 
01579                 elements[(assobrem_index[ibrem])].clusterRef();
01580               float BremClus_energy = thePFEnergyCalibration_->energyEm(*clusterRef,ps1EneFromBrem,ps2EneFromBrem,applyCrackCorrections_);
01581               Ene_ecalbrem += BremClus_energy;
01582               posX +=  BremClus_energy * clusterRef->position().X();
01583               posY +=  BremClus_energy * clusterRef->position().Y();
01584               posZ +=  BremClus_energy * clusterRef->position().Z();      
01585               
01586               NumBrem++;
01587               if (DebugIDOutputs) cout << " setIdOutput::BREM Cluster " 
01588                                        <<  BremClus_energy << " eta,phi " 
01589                                        <<  clusterRef->position().eta()  <<", " 
01590                                        << clusterRef->position().phi() << endl;
01591             }
01592             else {
01593               LateBrem = true;
01594             }
01595           }
01596         }
01597       }    
01598     } 
01599     if (Ene_ecalgsf > 0.) {
01600       // here build the new BDT observables
01601       
01602       //  ***** Normalization observables ****
01603       if(RefGSF.isNonnull()) {
01604         PFCandidateElectronExtra myExtra(RefGSF) ;
01605         myExtra.setGsfTrackPout(GsfEl->Pout());
01606         myExtra.setKfTrackRef(RefKF);
01607         float Pt_gsf = RefGSF->ptMode();
01608         lnPt_gsf = log(Pt_gsf);
01609         Eta_gsf = RefGSF->etaMode();
01610         
01611         // **** Pure tracking observables. 
01612         if(RefGSF->ptModeError() > 0.)
01613           dPtOverPt_gsf = RefGSF->ptModeError()/Pt_gsf;
01614         
01615         nhit_gsf= RefGSF->hitPattern().trackerLayersWithMeasurement();
01616         chi2_gsf = RefGSF->normalizedChi2();
01617         // change GsfEl->Pout().pt() as soon the PoutMode is on the GsfTrack DataFormat
01618         DPtOverPt_gsf =  (RefGSF->ptMode() - GsfEl->Pout().pt())/RefGSF->ptMode();
01619         
01620         
01621         nhit_kf = 0;
01622         chi2_kf = -0.01;
01623         DPtOverPt_kf = -0.01;
01624         if (RefKF.isNonnull()) {
01625           nhit_kf= RefKF->hitPattern().trackerLayersWithMeasurement();
01626           chi2_kf = RefKF->normalizedChi2();
01627           // Not used, strange behaviour to be checked. And Kf->OuterPt is 
01628           // in track extra. 
01629           //DPtOverPt_kf = 
01630           //  (RefKF->pt() - RefKF->outerPt())/RefKF->pt();
01631           
01632         }
01633         
01634         // **** Tracker-Ecal-Hcal observables 
01635         EtotPinMode        =  (Ene_ecalgsf + Ene_ecalbrem + Ene_extraecalgsf) / Ein_gsf; 
01636         EGsfPoutMode       =  Ene_ecalgsf/Eout_gsf;
01637         EtotBremPinPoutMode = Ene_ecalbrem /(Ein_gsf - Eout_gsf);
01638         DEtaGsfEcalClust  = fabs(deta_gsfecal);
01639         myExtra.setSigmaEtaEta(sigmaEtaEta);
01640         myExtra.setDeltaEta(DEtaGsfEcalClust);
01641         SigmaEtaEta = log(sigmaEtaEta);
01642         
01643         lateBrem = -1;
01644         firstBrem = -1;
01645         earlyBrem = -1;
01646         if(NumBrem > 0) {
01647           if (LateBrem) lateBrem = 1;
01648           else lateBrem = 0;
01649           firstBrem = FirstBrem;
01650           if(FirstBrem < 4) earlyBrem = 1;
01651           else earlyBrem = 0;
01652         }      
01653         
01654         HOverHE = Ene_hcalgsf/(Ene_hcalgsf + Ene_ecalgsf);
01655         HOverPin = Ene_hcalgsf / Ein_gsf;
01656         myExtra.setHadEnergy(Ene_hcalgsf);
01657         myExtra.setEarlyBrem(earlyBrem);
01658         myExtra.setLateBrem(lateBrem);
01659         //      std::cout<< " Inserting in extra " << electronExtra_.size() << std::endl;
01660 
01661         // Put cuts and access the BDT output
01662         if(DPtOverPt_gsf < -0.2) DPtOverPt_gsf = -0.2;
01663         if(DPtOverPt_gsf > 1.) DPtOverPt_gsf = 1.;
01664         
01665         if(dPtOverPt_gsf > 0.3) dPtOverPt_gsf = 0.3;
01666         
01667         if(chi2_gsf > 10.) chi2_gsf = 10.;
01668         
01669         if(DPtOverPt_kf < -0.2) DPtOverPt_kf = -0.2;
01670         if(DPtOverPt_kf > 1.) DPtOverPt_kf = 1.;
01671         
01672         if(chi2_kf > 10.) chi2_kf = 10.;
01673         
01674         if(EtotPinMode < 0.) EtotPinMode = 0.;
01675         if(EtotPinMode > 5.) EtotPinMode = 5.;
01676         
01677         if(EGsfPoutMode < 0.) EGsfPoutMode = 0.;
01678         if(EGsfPoutMode > 5.) EGsfPoutMode = 5.;
01679         
01680         if(EtotBremPinPoutMode < 0.) EtotBremPinPoutMode = 0.01;
01681         if(EtotBremPinPoutMode > 5.) EtotBremPinPoutMode = 5.;
01682         
01683         if(DEtaGsfEcalClust > 0.1) DEtaGsfEcalClust = 0.1;
01684         
01685         if(SigmaEtaEta < -14) SigmaEtaEta = -14;
01686         
01687         if(HOverPin < 0.) HOverPin = 0.;
01688         if(HOverPin > 5.) HOverPin = 5.;
01689         double mvaValue = tmvaReader_->EvaluateMVA("BDT");
01690         
01691         // add output observables 
01692         BDToutput_[cgsf] = mvaValue;
01693         myExtra.setMVA(mvaValue);
01694         electronExtra_.push_back(myExtra);
01695 
01696 
01697         // IMPORTANT Additional conditions
01698         if(mvaValue > mvaEleCut_) {
01699           // Check if the ecal cluster is isolated. 
01700           //
01701           // If there is at least one extra track and H/H+E > 0.05 or SumP(ExtraKf)/EGsf or  
01702           // #Tracks > 3 I leave this job to PFAlgo, otherwise I lock those extra tracks. 
01703           // Note:
01704           // The tracks coming from the 4 step of the iterative tracking are not considered, 
01705           // because they can come from secondary converted brems. 
01706           // They are locked to avoid double counting.
01707           // The lock is done in SetActivate function. 
01708           // All this can improved but it is already a good step. 
01709           
01710           
01711           // Find if the cluster is isolated. 
01712           unsigned int iextratrack = 0;
01713           unsigned int itrackHcalLinked = 0;
01714           float SumExtraKfP = 0.;
01715 
01716 
01717           double Etotal = Ene_ecalgsf + Ene_ecalbrem + Ene_extraecalgsf;
01718           posX /=Etotal;
01719           posY /=Etotal;
01720           posZ /=Etotal;
01721           math::XYZPoint sc_pflow(posX,posY,posZ);
01722           double ETtotal = Etotal*sin(sc_pflow.Theta());
01723           double phiTrack = RefGSF->phiMode();
01724           double dphi_normalsc = sc_pflow.Phi() - phiTrack;
01725           if ( dphi_normalsc < -M_PI ) 
01726             dphi_normalsc = dphi_normalsc + 2.*M_PI;
01727           else if ( dphi_normalsc > M_PI ) 
01728             dphi_normalsc = dphi_normalsc - 2.*M_PI;
01729           dphi_normalsc = fabs(dphi_normalsc);
01730         
01731   
01732           if(ecalGsf_index < 100000) {
01733             vector<unsigned int> assoecalgsf_index = associatedToEcal_.find(ecalGsf_index)->second;
01734             for(unsigned int itrk =0; itrk<assoecalgsf_index.size();itrk++) {
01735               PFBlockElement::Type typeassoecal = elements[(assoecalgsf_index[itrk])].type();
01736               if(typeassoecal == reco::PFBlockElement::TRACK) {
01737                 const reco::PFBlockElementTrack * kfTk =  
01738                   dynamic_cast<const reco::PFBlockElementTrack*>((&elements[(assoecalgsf_index[itrk])]));
01739                 // 19 Mar 2010 do not consider here tracks from gamma conv
01740                 // This should be not needed because the seleted extra tracks from GammaConv
01741                 // will be locked and can not be associated to the ecal elements 
01742                 //if(kfTk->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)) continue;
01743                 
01744 
01745                 reco::TrackRef trackref =  kfTk->trackRef();
01746                 unsigned int Algo = whichTrackAlgo(trackref);
01747                 // iter0, iter1, iter2, iter3 = Algo < 3
01748                 // algo 4,5,6,7
01749                 int nexhits = trackref->trackerExpectedHitsInner().numberOfLostHits();  
01750                 // probably we could now remove the algo request?? 
01751                 if(Algo < 3 && nexhits == 0) {
01752                   //if(Algo < 3) {
01753                   if(DebugIDOutputs) 
01754                     cout << " The ecalGsf cluster is not isolated: >0 KF extra with algo < 3" << endl;
01755 
01756                   float p_trk = trackref->p();
01757 
01758                   // expected number of inner hits
01759                 
01760                   if(DebugIDOutputs) 
01761                     cout << "  p_trk " <<  p_trk
01762                          << " nexhits " << nexhits << endl;
01763 
01764                   SumExtraKfP += p_trk;
01765                   iextratrack++;
01766                   // Check if these extra tracks are HCAL linked
01767                   std::multimap<double, unsigned int> hcalKfElems;
01768                   block.associatedElements( assoecalgsf_index[itrk],linkData,
01769                                             hcalKfElems,
01770                                             reco::PFBlockElement::HCAL,
01771                                             reco::PFBlock::LINKTEST_ALL );
01772                   if(hcalKfElems.size() > 0) {
01773                     itrackHcalLinked++;
01774                   }
01775                 }
01776               } 
01777             }
01778           }
01779           if( iextratrack > 0) {
01780             if(iextratrack > 3 || HOverHE > 0.05 || (SumExtraKfP/Ene_ecalgsf) > 1. 
01781                || (ETtotal > 50. && iextratrack > 1 && (Ene_hcalgsf/Ene_ecalgsf) > 0.1) ) {
01782               if(DebugIDOutputs) 
01783                 cout << " *****This electron candidate is discarded: Non isolated  # tracks "           
01784                      << iextratrack << " HOverHE " << HOverHE 
01785                      << " SumExtraKfP/Ene_ecalgsf " << SumExtraKfP/Ene_ecalgsf 
01786                      << " SumExtraKfP " << SumExtraKfP 
01787                      << " Ene_ecalgsf " << Ene_ecalgsf
01788                      << " ETtotal " << ETtotal
01789                      << " Ene_hcalgsf/Ene_ecalgsf " << Ene_hcalgsf/Ene_ecalgsf
01790                      << endl;
01791 
01792               BDToutput_[cgsf] = mvaValue-2.;
01793               lockExtraKf_[cgsf] = false;
01794             }
01795             // if the Ecluster ~ Ptrack and the extra tracks are HCAL linked 
01796             // the electron is retained and the kf tracks are not locked
01797             if( (fabs(1.-EtotPinMode) < 0.2 && (fabs(Eta_gsf) < 1.0 || fabs(Eta_gsf) > 2.0)) ||
01798                 ((EtotPinMode < 1.1 && EtotPinMode > 0.6) && (fabs(Eta_gsf) >= 1.0 && fabs(Eta_gsf) <= 2.0))) {
01799               if( fabs(1.-EGsfPoutMode) < 0.5 && 
01800                   (itrackHcalLinked == iextratrack) && 
01801                   kf_index < 100000 ) {
01802 
01803                 BDToutput_[cgsf] = mvaValue;
01804                 lockExtraKf_[cgsf] = false;
01805                 if(DebugIDOutputs)
01806                   cout << " *****This electron is reactivated  # tracks "               
01807                        << iextratrack << " #tracks hcal linked " << itrackHcalLinked 
01808                        << " SumExtraKfP/Ene_ecalgsf " << SumExtraKfP/Ene_ecalgsf  
01809                        << " EtotPinMode " << EtotPinMode << " EGsfPoutMode " << EGsfPoutMode 
01810                        << " eta gsf " << fabs(Eta_gsf) << " kf index " << kf_index <<endl;
01811               }
01812             }
01813           }
01814           // This is a pion:
01815           if (HOverPin > 1. && HOverHE > 0.1 && EtotPinMode < 0.5) {
01816             if(DebugIDOutputs) 
01817               cout << " *****This electron candidate is discarded  HCAL ENERGY "        
01818                    << " HOverPin " << HOverPin << " HOverHE " << HOverHE  << " EtotPinMode" << EtotPinMode << endl;
01819             BDToutput_[cgsf] = mvaValue-4.;
01820             lockExtraKf_[cgsf] = false;
01821           }
01822           
01823           // Reject Crazy E/p values... to be understood in the future how to train a 
01824           // BDT in order to avoid to select this bad electron candidates. 
01825         
01826           if( EtotPinMode < 0.2 && EGsfPoutMode < 0.2 ) {
01827             if(DebugIDOutputs) 
01828               cout << " *****This electron candidate is discarded  Low ETOTPIN "
01829                    << " EtotPinMode " << EtotPinMode << " EGsfPoutMode " << EGsfPoutMode << endl;
01830             BDToutput_[cgsf] = mvaValue-6.;
01831           }
01832           
01833           // For not-preselected Gsf Tracks ET > 50 GeV, apply dphi preselection
01834           if(ETtotal > 50. && dphi_normalsc > 0.1 ) {
01835             if(DebugIDOutputs) 
01836               cout << " *****This electron candidate is discarded  Large ANGLE "
01837                    << " ETtotal " << ETtotal << " EGsfPoutMode " << dphi_normalsc << endl;
01838             BDToutput_[cgsf] =  mvaValue-6.;
01839           }
01840         }
01841 
01842 
01843         if (DebugIDOutputs) {
01844           cout << " **** BDT observables ****" << endl;
01845           cout << " < Normalization > " << endl;
01846           cout << " Pt_gsf " << Pt_gsf << " Pin " << Ein_gsf  << " Pout " << Eout_gsf
01847                << " Eta_gsf " << Eta_gsf << endl;
01848           cout << " < PureTracking > " << endl;
01849           cout << " dPtOverPt_gsf " << dPtOverPt_gsf 
01850                << " DPtOverPt_gsf " << DPtOverPt_gsf
01851                << " chi2_gsf " << chi2_gsf
01852                << " nhit_gsf " << nhit_gsf
01853                << " DPtOverPt_kf " << DPtOverPt_kf
01854                << " chi2_kf " << chi2_kf 
01855                << " nhit_kf " << nhit_kf <<  endl;
01856           cout << " < track-ecal-hcal-ps " << endl;
01857           cout << " EtotPinMode " << EtotPinMode 
01858                << " EGsfPoutMode " << EGsfPoutMode
01859                << " EtotBremPinPoutMode " << EtotBremPinPoutMode
01860                << " DEtaGsfEcalClust " << DEtaGsfEcalClust 
01861                << " SigmaEtaEta " << SigmaEtaEta
01862                << " HOverHE " << HOverHE << " Hcal energy " << Ene_hcalgsf
01863                << " HOverPin " << HOverPin 
01864                << " lateBrem " << lateBrem
01865                << " firstBrem " << firstBrem << endl;
01866           cout << " !!!!!!!!!!!!!!!! the BDT output !!!!!!!!!!!!!!!!!: direct " << mvaValue 
01867                << " corrected " << BDToutput_[cgsf] <<  endl; 
01868           
01869         }
01870       }
01871       else {
01872         if (DebugIDOutputs) 
01873           cout << " Gsf Ref isNULL " << endl;
01874         BDToutput_[cgsf] = -2.;
01875       }
01876     } else {
01877       if (DebugIDOutputs) 
01878         cout << " No clusters associated to the gsf " << endl;
01879       BDToutput_[cgsf] = -2.;      
01880     }  
01881     DebugIDOutputs = false;
01882   } // End Loop on Map1   
01883   return;
01884 }
01885 // This function get the associatedToGsf and associatedToBrems maps and  
01886 // compute the electron 4-mom and set the pf candidate, for
01887 // the gsf track with a BDTcut > mvaEleCut_
01888 void PFElectronAlgo::SetCandidates(const reco::PFBlockRef&  blockRef,
01889                                          AssMap& associatedToGsf_,
01890                                          AssMap& associatedToBrems_,
01891                                          AssMap& associatedToEcal_){
01892   
01893   const reco::PFBlock& block = *blockRef;
01894   PFBlock::LinkData linkData =  block.linkData();     
01895   const edm::OwnVector< reco::PFBlockElement >&  elements = block.elements();
01896   PFEnergyResolution pfresol_;
01897   //PFEnergyCalibration pfcalib_;
01898 
01899   bool DebugIDCandidates = false;
01900 //   vector<reco::PFCluster> pfClust_vec(0);
01901 //   pfClust_vec.clear();
01902 
01903   unsigned int cgsf=0;
01904   for (map<unsigned int,vector<unsigned int> >::iterator igsf = associatedToGsf_.begin();
01905        igsf != associatedToGsf_.end(); igsf++,cgsf++) {
01906     unsigned int gsf_index =  igsf->first;
01907            
01908     
01909 
01910     // They should be reset for each gsf track
01911     int eecal=0;
01912     int hcal=0;
01913     int charge =0; 
01914     // bool goodphi=true;
01915     math::XYZTLorentzVector momentum_kf,momentum_gsf,momentum,momentum_mean;
01916     float dpt=0; float dpt_gsf=0;
01917     float Eene=0; float dene=0; float Hene=0.;
01918     float RawEene = 0.;
01919     double posX=0.;
01920     double posY=0.;
01921     double posZ=0.;
01922     std::vector<float> bremEnergyVec;
01923 
01924     std::vector<const PFCluster*> pfSC_Clust_vec; 
01925 
01926     float de_gs = 0., de_me = 0., de_kf = 0.; 
01927     float m_el=0.00051;
01928     int nhit_kf=0; int nhit_gsf=0;
01929     bool has_gsf=false;
01930     bool has_kf=false;
01931     math::XYZTLorentzVector newmomentum;
01932     float ps1TotEne = 0;
01933     float ps2TotEne = 0;
01934     vector<unsigned int> elementsToAdd(0);
01935     reco::TrackRef RefKF;  
01936 
01937 
01938 
01939     elementsToAdd.push_back(gsf_index);
01940     const reco::PFBlockElementGsfTrack * GsfEl  =  
01941       dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[gsf_index]));
01942     const math::XYZPointF& posGsfEcalEntrance = GsfEl->positionAtECALEntrance();
01943     reco::GsfTrackRef RefGSF = GsfEl->GsftrackRef();
01944     if (RefGSF.isNonnull()) {
01945       
01946       has_gsf=true;
01947      
01948       charge= RefGSF->chargeMode();
01949       nhit_gsf= RefGSF->hitPattern().trackerLayersWithMeasurement();
01950       
01951       momentum_gsf.SetPx(RefGSF->pxMode());
01952       momentum_gsf.SetPy(RefGSF->pyMode());
01953       momentum_gsf.SetPz(RefGSF->pzMode());
01954       float ENE=sqrt(RefGSF->pMode()*
01955                      RefGSF->pMode()+m_el*m_el);
01956       
01957       if( DebugIDCandidates ) 
01958         cout << "SetCandidates:: GsfTrackRef: Ene " << ENE 
01959              << " charge " << charge << " nhits " << nhit_gsf <<endl;
01960       
01961       momentum_gsf.SetE(ENE);       
01962       dpt_gsf=RefGSF->ptModeError()*
01963         (RefGSF->pMode()/RefGSF->ptMode());
01964       
01965       momentum_mean.SetPx(RefGSF->px());
01966       momentum_mean.SetPy(RefGSF->py());
01967       momentum_mean.SetPz(RefGSF->pz());
01968       float ENEm=sqrt(RefGSF->p()*
01969                       RefGSF->p()+m_el*m_el);
01970       momentum_mean.SetE(ENEm);       
01971       //       dpt_mean=RefGSF->ptError()*
01972       //        (RefGSF->p()/RefGSF->pt());  
01973     }
01974     else {
01975       if( DebugIDCandidates ) 
01976         cout <<  "SetCandidates:: !!!!  NULL GSF Track Ref " << endl;   
01977     } 
01978 
01979     //    vector<unsigned int> assogsf_index =  associatedToGsf_[igsf].second;
01980     vector<unsigned int> assogsf_index = igsf->second;
01981     unsigned int ecalGsf_index = 100000;
01982     bool FirstEcalGsf = true;
01983     for  (unsigned int ielegsf=0;ielegsf<assogsf_index.size();ielegsf++) {
01984       PFBlockElement::Type assoele_type = elements[(assogsf_index[ielegsf])].type();
01985       if  (assoele_type == reco::PFBlockElement::TRACK) {
01986         elementsToAdd.push_back((assogsf_index[ielegsf])); // Daniele
01987         const reco::PFBlockElementTrack * KfTk =  
01988           dynamic_cast<const reco::PFBlockElementTrack*>((&elements[(assogsf_index[ielegsf])]));
01989         // 19 Mar 2010 do not consider here track from gamam conv
01990         bool isPrim = isPrimaryTrack(*KfTk,*GsfEl);
01991         if(!isPrim) continue;
01992         
01993         RefKF = KfTk->trackRef();
01994         if (RefKF.isNonnull()) {
01995           has_kf = true;
01996           // dpt_kf=(RefKF->ptError()*RefKF->ptError());
01997           nhit_kf=RefKF->hitPattern().trackerLayersWithMeasurement();
01998           momentum_kf.SetPx(RefKF->px());
01999           momentum_kf.SetPy(RefKF->py());
02000           momentum_kf.SetPz(RefKF->pz());
02001           float ENE=sqrt(RefKF->p()*RefKF->p()+m_el*m_el);
02002           if( DebugIDCandidates ) 
02003             cout << "SetCandidates:: KFTrackRef: Ene " << ENE << " nhits " << nhit_kf << endl;
02004           
02005           momentum_kf.SetE(ENE);
02006         }
02007         else {
02008           if( DebugIDCandidates ) 
02009             cout <<  "SetCandidates:: !!!! NULL KF Track Ref " << endl;
02010         }
02011       } 
02012 
02013       if  (assoele_type == reco::PFBlockElement::ECAL) {
02014         unsigned int keyecalgsf = assogsf_index[ielegsf];
02015         vector<unsigned int> assoecalgsf_index = associatedToEcal_.find(keyecalgsf)->second;
02016         vector<double> ps1Ene(0);
02017         vector<double> ps2Ene(0);
02018         // Important is the PS clusters are not saved before the ecal one, these
02019         // energy are not correctly assigned 
02020         // For the moment I get only the closest PS clusters: this has to be changed
02021         for(unsigned int ips =0; ips<assoecalgsf_index.size();ips++) {
02022           PFBlockElement::Type typeassoecal = elements[(assoecalgsf_index[ips])].type();
02023           if  (typeassoecal == reco::PFBlockElement::PS1) {  
02024             PFClusterRef  psref = elements[(assoecalgsf_index[ips])].clusterRef();
02025             ps1Ene.push_back(psref->energy());
02026             elementsToAdd.push_back((assoecalgsf_index[ips]));
02027           }
02028           if  (typeassoecal == reco::PFBlockElement::PS2) {  
02029             PFClusterRef  psref = elements[(assoecalgsf_index[ips])].clusterRef();
02030             ps2Ene.push_back(psref->energy());
02031             elementsToAdd.push_back((assoecalgsf_index[ips]));
02032           }
02033           if  (typeassoecal == reco::PFBlockElement::HCAL) {
02034             const reco::PFBlockElementCluster * clust =  
02035               dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(assoecalgsf_index[ips])])); 
02036             elementsToAdd.push_back((assoecalgsf_index[ips])); 
02037             Hene+=clust->clusterRef()->energy();
02038             hcal++;
02039           }
02040         }
02041         elementsToAdd.push_back((assogsf_index[ielegsf]));
02042 
02043 
02044         const reco::PFBlockElementCluster * clust =  
02045           dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(assogsf_index[ielegsf])]));
02046         
02047         eecal++;
02048         
02049         const reco::PFCluster& cl(*clust->clusterRef());
02050         //pfClust_vec.push_back((*clust->clusterRef()));
02051 
02052         // The electron RAW energy is the energy of the corrected GSF cluster   
02053         double ps1,ps2;
02054         ps1=ps2=0.;
02055         //      float EE=pfcalib_.energyEm(cl,ps1Ene,ps2Ene);
02056         float EE = thePFEnergyCalibration_->energyEm(cl,ps1Ene,ps2Ene,ps1,ps2,applyCrackCorrections_);    
02057         //      float RawEE = cl.energy();
02058 
02059         float ceta=cl.position().eta();
02060         float cphi=cl.position().phi();
02061         
02062         /*
02063           float mphi=-2.97025;
02064           if (ceta<0) mphi+=0.00638;
02065           
02066           for (int ip=1; ip<19; ip++){
02067           float df= cphi - (mphi+(ip*6.283185/18));
02068           if (fabs(df)<0.01) goodphi=false;
02069           }
02070         */
02071 
02072         float dE=pfresol_.getEnergyResolutionEm(EE,cl.position().eta());
02073         if( DebugIDCandidates ) 
02074           cout << "SetCandidates:: EcalCluster: EneNoCalib " << clust->clusterRef()->energy()  
02075                << " eta,phi " << ceta << "," << cphi << " Calib " <<  EE << " dE " <<  dE <<endl;
02076 
02077         bool elecCluster=false;
02078         if (FirstEcalGsf) {
02079           FirstEcalGsf = false;
02080           elecCluster=true;
02081           ecalGsf_index = assogsf_index[ielegsf];
02082           //      std::cout << " PFElectronAlgo / Seed " << EE << std::endl;
02083           RawEene += EE;
02084         }
02085         
02086         // create a photon/electron candidate
02087         math::XYZTLorentzVector clusterMomentum;
02088         math::XYZPoint direction=cl.position()/cl.position().R();
02089         clusterMomentum.SetPxPyPzE(EE*direction.x(),
02090                                    EE*direction.y(),
02091                                    EE*direction.z(),
02092                                    EE);
02093         reco::PFCandidate cluster_Candidate((elecCluster)?charge:0,
02094                                             clusterMomentum, 
02095                                             (elecCluster)? reco::PFCandidate::e : reco::PFCandidate::gamma);
02096         
02097         cluster_Candidate.setPs1Energy(ps1);
02098         cluster_Candidate.setPs2Energy(ps2);
02099         // The Raw Ecal energy will be the energy of the basic cluster. 
02100         // It will be the corrected energy without the preshower
02101         cluster_Candidate.setEcalEnergy(EE-ps1-ps2,EE);
02102         //            std::cout << " PFElectronAlgo, adding Brem (1) " << EE << std::endl;
02103         cluster_Candidate.setPositionAtECALEntrance(math::XYZPointF(cl.position()));
02104         cluster_Candidate.addElementInBlock(blockRef,assogsf_index[ielegsf]);
02105         // store the photon candidate
02106         std::map<unsigned int,std::vector<reco::PFCandidate> >::iterator itcheck=
02107           electronConstituents_.find(cgsf);
02108         if(itcheck==electronConstituents_.end())
02109           {               
02110             // beurk
02111             std::vector<reco::PFCandidate> tmpVec;
02112             tmpVec.push_back(cluster_Candidate);
02113             electronConstituents_.insert(std::pair<unsigned int, std::vector<reco::PFCandidate> >
02114                                          (cgsf,tmpVec));
02115           }
02116         else
02117           {
02118             itcheck->second.push_back(cluster_Candidate);
02119           }
02120         
02121         Eene+=EE;
02122         posX +=  EE * cl.position().X();
02123         posY +=  EE * cl.position().Y();
02124         posZ +=  EE * cl.position().Z();          
02125         ps1TotEne+=ps1;
02126         ps2TotEne+=ps2;
02127         dene+=dE*dE;
02128         
02129         //MM Add cluster to the vector pfSC_Clust_vec needed for brem corrections
02130         pfSC_Clust_vec.push_back( &cl );
02131 
02132       }
02133       
02134 
02135 
02136       // Important: Add energy from the brems
02137       if  (assoele_type == reco::PFBlockElement::BREM) {
02138         unsigned int brem_index = assogsf_index[ielegsf];
02139         vector<unsigned int> assobrem_index = associatedToBrems_.find(brem_index)->second;
02140         elementsToAdd.push_back(brem_index);
02141         for (unsigned int ibrem = 0; ibrem < assobrem_index.size(); ibrem++){
02142           if (elements[(assobrem_index[ibrem])].type() == reco::PFBlockElement::ECAL) {
02143             // brem emission is from the considered gsf track
02144             unsigned int keyecalbrem = assobrem_index[ibrem];
02145             const vector<unsigned int>& assoelebrem_index = associatedToEcal_.find(keyecalbrem)->second;
02146             vector<double> ps1EneFromBrem(0);
02147             vector<double> ps2EneFromBrem(0);
02148             float ps1EneFromBremTot=0.;
02149             float ps2EneFromBremTot=0.;
02150             for (unsigned int ielebrem=0; ielebrem<assoelebrem_index.size();ielebrem++) {
02151               if (elements[(assoelebrem_index[ielebrem])].type() == reco::PFBlockElement::PS1) {
02152                 PFClusterRef  psref = elements[(assoelebrem_index[ielebrem])].clusterRef();
02153                 ps1EneFromBrem.push_back(psref->energy());
02154                 ps1EneFromBremTot+=psref->energy();
02155                 elementsToAdd.push_back(assoelebrem_index[ielebrem]);
02156               }
02157               if (elements[(assoelebrem_index[ielebrem])].type() == reco::PFBlockElement::PS2) {
02158                 PFClusterRef  psref = elements[(assoelebrem_index[ielebrem])].clusterRef();
02159                 ps2EneFromBrem.push_back(psref->energy());
02160                 ps2EneFromBremTot+=psref->energy();
02161                 elementsToAdd.push_back(assoelebrem_index[ielebrem]);
02162               }   
02163             }
02164             
02165 
02166             if( assobrem_index[ibrem] !=  ecalGsf_index) {
02167               elementsToAdd.push_back(assobrem_index[ibrem]);
02168               reco::PFClusterRef clusterRef = elements[(assobrem_index[ibrem])].clusterRef();
02169               //pfClust_vec.push_back(*clusterRef);
02170               // to get a calibrated PS energy 
02171               double ps1=0;
02172               double ps2=0;
02173               float EE = thePFEnergyCalibration_->energyEm(*clusterRef,ps1EneFromBrem,ps2EneFromBrem,ps1,ps2,applyCrackCorrections_);
02174               bremEnergyVec.push_back(EE);
02175               // float RawEE  = clusterRef->energy();
02176               float ceta = clusterRef->position().eta();
02177               // float cphi = clusterRef->position().phi();
02178               float dE=pfresol_.getEnergyResolutionEm(EE,ceta);
02179               if( DebugIDCandidates ) 
02180                 cout << "SetCandidates:: BremCluster: Ene " << EE << " dE " <<  dE <<endl;        
02181 
02182               Eene+=EE;
02183               posX +=  EE * clusterRef->position().X();
02184               posY +=  EE * clusterRef->position().Y();
02185               posZ +=  EE * clusterRef->position().Z();   
02186               ps1TotEne+=ps1;
02187               ps2TotEne+=ps2;
02188               // Removed 4 March 2009. Florian. The Raw energy is the (corrected) one of the GSF cluster only
02189               //              RawEene += RawEE;
02190               dene+=dE*dE;
02191 
02192               //MM Add cluster to the vector pfSC_Clust_vec needed for brem corrections
02193               pfSC_Clust_vec.push_back( clusterRef.get() );
02194 
02195               // create a PFCandidate out of it. Watch out, it is for the e/gamma and tau only
02196               // not to be used by the PFAlgo
02197               math::XYZTLorentzVector photonMomentum;
02198               math::XYZPoint direction=clusterRef->position()/clusterRef->position().R();
02199               
02200               photonMomentum.SetPxPyPzE(EE*direction.x(),
02201                                         EE*direction.y(),
02202                                         EE*direction.z(),
02203                                         EE);
02204               reco::PFCandidate photon_Candidate(0,photonMomentum, reco::PFCandidate::gamma);
02205               
02206               photon_Candidate.setPs1Energy(ps1);
02207               photon_Candidate.setPs2Energy(ps2);
02208               // yes, EE, we want the raw ecal energy of the daugther to have the same definition
02209               // as the GSF cluster
02210               photon_Candidate.setEcalEnergy(EE-ps1-ps2,EE);
02211               //              std::cout << " PFElectronAlgo, adding Brem " << EE << std::endl;
02212               photon_Candidate.setPositionAtECALEntrance(math::XYZPointF(clusterRef->position()));
02213               photon_Candidate.addElementInBlock(blockRef,assobrem_index[ibrem]);
02214 
02215               // store the photon candidate
02216               std::map<unsigned int,std::vector<reco::PFCandidate> >::iterator itcheck=
02217                 electronConstituents_.find(cgsf);
02218               if(itcheck==electronConstituents_.end())
02219                 {                 
02220                   // beurk
02221                   std::vector<reco::PFCandidate> tmpVec;
02222                   tmpVec.push_back(photon_Candidate);
02223                   electronConstituents_.insert(std::pair<unsigned int, std::vector<reco::PFCandidate> >
02224                                            (cgsf,tmpVec));
02225                 }
02226               else
02227                 {
02228                   itcheck->second.push_back(photon_Candidate);
02229                 }
02230             }
02231           } 
02232         }
02233       }
02234     } // End Loop On element associated to the GSF tracks
02235     if (has_gsf) {
02236       
02237       // SuperCluster energy corrections
02238       double unCorrEene = Eene;
02239       double absEta = fabs(momentum_gsf.Eta());
02240       double emTheta = momentum_gsf.Theta();
02241       PFClusterWidthAlgo pfSCwidth(pfSC_Clust_vec); 
02242       double brLinear = pfSCwidth.pflowPhiWidth()/pfSCwidth.pflowEtaWidth(); 
02243       pfSC_Clust_vec.clear();
02244       
02245       if( DebugIDCandidates ) 
02246         cout << "PFEelectronAlgo:: absEta " << absEta  << " theta " << emTheta 
02247              << " EneRaw " << Eene << " Err " << dene;
02248       
02249       // The calibrations are provided till ET = 200 GeV //No longer a such cut MM
02250       // Protection on at least 1 GeV energy...avoid possible divergencies at very low energy.
02251       if(usePFSCEleCalib_ && unCorrEene > 0.) { 
02252         if( absEta < 1.5) {
02253           double Etene = Eene*sin(emTheta);
02254           double emBR_e = thePFSCEnergyCalibration_->SCCorrFBremBarrel(Eene, Etene, brLinear); 
02255           double emBR_et = emBR_e*sin(emTheta); 
02256           double emCorrFull_et = thePFSCEnergyCalibration_->SCCorrEtEtaBarrel(emBR_et, absEta); 
02257           Eene = emCorrFull_et/sin(emTheta);
02258         }
02259         else {
02260           //  double Etene = Eene*sin(emTheta); //not needed anymore for endcaps MM
02261           double emBR_e = thePFSCEnergyCalibration_->SCCorrFBremEndcap(Eene, absEta, brLinear); 
02262           double emBR_et = emBR_e*sin(emTheta); 
02263           double emCorrFull_et = thePFSCEnergyCalibration_->SCCorrEtEtaEndcap(emBR_et, absEta); 
02264           Eene = emCorrFull_et/sin(emTheta);
02265         }
02266         dene = sqrt(dene)*(Eene/unCorrEene);
02267         dene = dene*dene;
02268       }
02269 
02270       if( DebugIDCandidates ) 
02271         cout << " EneCorrected " << Eene << " Err " << dene  << endl;
02272 
02273       // charge determination with the majority method
02274       // if the kf track exists: 2 among 3 of supercluster barycenter position
02275       // gsf track and kf track
02276       if(has_kf && unCorrEene > 0.) {
02277         posX /=unCorrEene;
02278         posY /=unCorrEene;
02279         posZ /=unCorrEene;
02280         math::XYZPoint sc_pflow(posX,posY,posZ);
02281 
02282         std::multimap<double, unsigned int> bremElems;
02283         block.associatedElements( gsf_index,linkData,
02284                                   bremElems,
02285                                   reco::PFBlockElement::BREM,
02286                                   reco::PFBlock::LINKTEST_ALL );
02287 
02288         double phiTrack = RefGSF->phiMode();
02289         if(bremElems.size()>0) {
02290           unsigned int brem_index =  bremElems.begin()->second;
02291           const reco::PFBlockElementBrem * BremEl  =  
02292             dynamic_cast<const reco::PFBlockElementBrem*>((&elements[brem_index]));
02293           phiTrack = BremEl->positionAtECALEntrance().phi();
02294         }
02295 
02296         double dphi_normalsc = sc_pflow.Phi() - phiTrack;
02297         if ( dphi_normalsc < -M_PI ) 
02298           dphi_normalsc = dphi_normalsc + 2.*M_PI;
02299         else if ( dphi_normalsc > M_PI ) 
02300           dphi_normalsc = dphi_normalsc - 2.*M_PI;
02301         
02302         int chargeGsf = RefGSF->chargeMode();
02303         int chargeKf = RefKF->charge();
02304 
02305         int chargeSC = 0;
02306         if(dphi_normalsc < 0.) 
02307           chargeSC = 1;
02308         else 
02309           chargeSC = -1;
02310         
02311         if(chargeKf == chargeGsf) 
02312           charge = chargeGsf;
02313         else if(chargeGsf == chargeSC)
02314           charge = chargeGsf;
02315         else 
02316           charge = chargeKf;
02317 
02318         if( DebugIDCandidates ) 
02319           cout << "PFElectronAlgo:: charge determination " 
02320                << " charge GSF " << chargeGsf 
02321                << " charge KF " << chargeKf 
02322                << " charge SC " << chargeSC
02323                << " Final Charge " << charge << endl;
02324         
02325       }
02326        
02327       // Think about this... 
02328       if ((nhit_gsf<8) && (has_kf)){
02329         
02330         // Use Hene if some condition.... 
02331         
02332         momentum=momentum_kf;
02333         float Fe=Eene;
02334         float scale= Fe/momentum.E();
02335         
02336         // Daniele Changed
02337         if (Eene < 0.0001) {
02338           Fe = momentum.E();
02339           scale = 1.;
02340         }
02341 
02342 
02343         newmomentum.SetPxPyPzE(scale*momentum.Px(),
02344                                scale*momentum.Py(),
02345                                scale*momentum.Pz(),Fe);
02346         if( DebugIDCandidates ) 
02347           cout << "SetCandidates:: (nhit_gsf<8) && (has_kf):: pt " << newmomentum.pt() << " Ene " <<  Fe <<endl;
02348 
02349         
02350       } 
02351       if ((nhit_gsf>7) || (has_kf==false)){
02352         if(Eene > 0.0001) {
02353           de_gs=1-momentum_gsf.E()/Eene;
02354           de_me=1-momentum_mean.E()/Eene;
02355           de_kf=1-momentum_kf.E()/Eene;
02356         }
02357 
02358         momentum=momentum_gsf;
02359         dpt=1/(dpt_gsf*dpt_gsf);
02360         
02361         if(dene > 0.)
02362           dene= 1./dene;
02363         
02364         float Fe = 0.;
02365         if(Eene > 0.0001) {
02366           Fe =((dene*Eene) +(dpt*momentum.E()))/(dene+dpt);
02367         }
02368         else {
02369           Fe=momentum.E();
02370         }
02371         
02372         if ((de_gs>0.05)&&(de_kf>0.05)){
02373           Fe=Eene;
02374         }
02375         if ((de_gs<-0.1)&&(de_me<-0.1) &&(de_kf<0.) && 
02376             (momentum.E()/dpt_gsf) > 5. && momentum_gsf.pt() < 30.){
02377           Fe=momentum.E();
02378         }
02379         float scale= Fe/momentum.E();
02380         
02381         newmomentum.SetPxPyPzE(scale*momentum.Px(),
02382                                scale*momentum.Py(),
02383                                scale*momentum.Pz(),Fe);
02384         if( DebugIDCandidates ) 
02385           cout << "SetCandidates::(nhit_gsf>7) || (has_kf==false)  " << newmomentum.pt() << " Ene " <<  Fe <<endl;
02386         
02387         
02388       }
02389       if (newmomentum.pt()>0.5){
02390         
02391         // the pf candidate are created: we need to set something more? 
02392         // IMPORTANT -> We need the gsftrackRef, not only the TrackRef??
02393 
02394         if( DebugIDCandidates )
02395           cout << "SetCandidates:: I am before doing candidate " <<endl;
02396         
02397         //vector with the cluster energies (for the extra)
02398         std::vector<float> clusterEnergyVec;
02399         clusterEnergyVec.push_back(RawEene);
02400         clusterEnergyVec.insert(clusterEnergyVec.end(),bremEnergyVec.begin(),bremEnergyVec.end());
02401 
02402         // add the information in the extra
02403         std::vector<reco::PFCandidateElectronExtra>::iterator itextra;
02404         PFElectronExtraEqual myExtraEqual(RefGSF);
02405         itextra=find_if(electronExtra_.begin(),electronExtra_.end(),myExtraEqual);
02406         if(itextra!=electronExtra_.end()) {
02407           itextra->setClusterEnergies(clusterEnergyVec);
02408         }
02409         else {
02410           if(RawEene>0.) 
02411             std::cout << " There is a big problem with the electron extra, PFElectronAlgo should crash soon " << RawEene << std::endl;
02412         }
02413 
02414         reco::PFCandidate::ParticleType particleType 
02415           = reco::PFCandidate::e;
02416         reco::PFCandidate temp_Candidate;
02417         temp_Candidate = PFCandidate(charge,newmomentum,particleType);
02418         temp_Candidate.set_mva_e_pi(BDToutput_[cgsf]);
02419         temp_Candidate.setEcalEnergy(RawEene,Eene);
02420         // Note the Hcal energy is set but the element is never locked 
02421         temp_Candidate.setHcalEnergy(Hene,Hene);  
02422         temp_Candidate.setPs1Energy(ps1TotEne);
02423         temp_Candidate.setPs2Energy(ps2TotEne);
02424         temp_Candidate.setTrackRef(RefKF);   
02425         // This reference could be NULL it is needed a protection? 
02426         temp_Candidate.setGsfTrackRef(RefGSF);
02427         temp_Candidate.setPositionAtECALEntrance(posGsfEcalEntrance);
02428         // Add Vertex
02429         temp_Candidate.setVertexSource(PFCandidate::kGSFVertex);
02430         
02431         // save the superclusterRef when available
02432         if(RefGSF->extra().isAvailable() && RefGSF->extra()->seedRef().isAvailable()) {
02433           reco::ElectronSeedRef seedRef=  RefGSF->extra()->seedRef().castTo<reco::ElectronSeedRef>();
02434           if(seedRef.isAvailable() && seedRef->isEcalDriven()) {
02435             reco::SuperClusterRef scRef = seedRef->caloCluster().castTo<reco::SuperClusterRef>();
02436             if(scRef.isNonnull())  
02437               temp_Candidate.setSuperClusterRef(scRef);
02438           }
02439         }
02440 
02441         if( DebugIDCandidates ) 
02442           cout << "SetCandidates:: I am after doing candidate " <<endl;
02443         
02444         for (unsigned int elad=0; elad<elementsToAdd.size();elad++){
02445           temp_Candidate.addElementInBlock(blockRef,elementsToAdd[elad]);
02446         }
02447 
02448         // now add the photons to this candidate
02449         std::map<unsigned int, std::vector<reco::PFCandidate> >::const_iterator itcluster=
02450           electronConstituents_.find(cgsf);
02451         if(itcluster!=electronConstituents_.end())
02452           {
02453             const std::vector<reco::PFCandidate> & theClusters=itcluster->second;
02454             unsigned nclus=theClusters.size();
02455             //      std::cout << " PFElectronAlgo " << nclus << " daugthers to add" << std::endl;
02456             for(unsigned iclus=0;iclus<nclus;++iclus)
02457               {
02458                 temp_Candidate.addDaughter(theClusters[iclus]);
02459               }
02460           }
02461 
02462         // By-pass the mva is the electron has been pre-selected 
02463         bool bypassmva=false;
02464         if(useEGElectrons_) {
02465           GsfElectronEqual myEqual(RefGSF);
02466           std::vector<reco::GsfElectron>::const_iterator itcheck=find_if(theGsfElectrons_->begin(),theGsfElectrons_->end(),myEqual);
02467           if(itcheck!=theGsfElectrons_->end()) {
02468             if(BDToutput_[cgsf] >= -1.)  {
02469               // bypass the mva only if the reconstruction went fine
02470               bypassmva=true;
02471 
02472               if( DebugIDCandidates ) {
02473                 if(BDToutput_[cgsf] < -0.1) {
02474                   float esceg = itcheck->caloEnergy();          
02475                   cout << " Attention By pass the mva " << BDToutput_[cgsf] 
02476                        << " SuperClusterEnergy " << esceg
02477                        << " PF Energy " << Eene << endl;
02478                   
02479                   cout << " hoe " << itcheck->hcalOverEcal()
02480                        << " tkiso04 " << itcheck->dr04TkSumPt()
02481                        << " ecaliso04 " << itcheck->dr04EcalRecHitSumEt()
02482                        << " hcaliso04 " << itcheck->dr04HcalTowerSumEt()
02483                        << " tkiso03 " << itcheck->dr03TkSumPt()
02484                        << " ecaliso03 " << itcheck->dr03EcalRecHitSumEt()
02485                        << " hcaliso03 " << itcheck->dr03HcalTowerSumEt() << endl;
02486                 }
02487               } // end DebugIDCandidates
02488             }
02489           }
02490         }
02491         
02492         bool mvaSelected = (BDToutput_[cgsf] >=  mvaEleCut_);
02493         if( mvaSelected || bypassmva )    {
02494             elCandidate_.push_back(temp_Candidate);
02495             if(itextra!=electronExtra_.end()) 
02496               itextra->setStatus(PFCandidateElectronExtra::Selected,true);
02497           }
02498         else      {
02499           if(itextra!=electronExtra_.end()) 
02500             itextra->setStatus(PFCandidateElectronExtra::Rejected,true);
02501         }
02502         allElCandidate_.push_back(temp_Candidate);
02503         
02504         // save the status information
02505         if(itextra!=electronExtra_.end()) {
02506           itextra->setStatus(PFCandidateElectronExtra::ECALDrivenPreselected,bypassmva);
02507           itextra->setStatus(PFCandidateElectronExtra::MVASelected,mvaSelected);
02508         }
02509         
02510 
02511       }
02512       else {
02513         BDToutput_[cgsf] = -1.;   // if the momentum is < 0.5 ID = false, but not sure
02514         // it could be misleading. 
02515         if( DebugIDCandidates ) 
02516           cout << "SetCandidates:: No Candidate Produced because of Pt cut: 0.5 " <<endl;
02517       }
02518     } 
02519     else {
02520       BDToutput_[cgsf] = -1.;  // if gsf ref does not exist
02521       if( DebugIDCandidates ) 
02522         cout << "SetCandidates:: No Candidate Produced because of No GSF Track Ref " <<endl;
02523     }
02524   } // End Loop On GSF tracks
02525   return;
02526 }
02527 // // This function get the associatedToGsf and associatedToBrems maps and for each pfelectron candidate 
02528 // // the element used are set active == false. 
02529 // // note: the HCAL cluster are not used for the moments and also are not locked. 
02530 void PFElectronAlgo::SetActive(const reco::PFBlockRef&  blockRef,
02531                                      AssMap& associatedToGsf_,
02532                                      AssMap& associatedToBrems_,
02533                                      AssMap& associatedToEcal_,
02534                                      std::vector<bool>& active){
02535   const reco::PFBlock& block = *blockRef;
02536   PFBlock::LinkData linkData =  block.linkData();  
02537    
02538   const edm::OwnVector< reco::PFBlockElement >&  elements = block.elements();
02539   
02540   unsigned int cgsf=0;
02541   for (map<unsigned int,vector<unsigned int> >::iterator igsf = associatedToGsf_.begin();
02542        igsf != associatedToGsf_.end(); igsf++,cgsf++) {
02543 
02544     unsigned int gsf_index =  igsf->first;
02545     const reco::PFBlockElementGsfTrack * GsfEl  =  
02546       dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[gsf_index]));
02547     reco::GsfTrackRef RefGSF = GsfEl->GsftrackRef();
02548 
02549     // lock only the elements that pass the BDT cut
02550     bool bypassmva=false;
02551     if(useEGElectrons_) {
02552       GsfElectronEqual myEqual(RefGSF);
02553       std::vector<reco::GsfElectron>::const_iterator itcheck=find_if(theGsfElectrons_->begin(),theGsfElectrons_->end(),myEqual);
02554       if(itcheck!=theGsfElectrons_->end()) {
02555         if(BDToutput_[cgsf] >= -1.) 
02556           bypassmva=true;
02557       }
02558     }
02559 
02560     if(BDToutput_[cgsf] < mvaEleCut_ && bypassmva == false) continue;
02561 
02562     
02563     active[gsf_index] = false;  // lock the gsf
02564     vector<unsigned int> assogsf_index = igsf->second;
02565     for  (unsigned int ielegsf=0;ielegsf<assogsf_index.size();ielegsf++) {
02566       PFBlockElement::Type assoele_type = elements[(assogsf_index[ielegsf])].type();
02567       // lock the elements associated to the gsf: ECAL, Brems
02568       active[(assogsf_index[ielegsf])] = false;  
02569       if (assoele_type == reco::PFBlockElement::ECAL) {
02570         unsigned int keyecalgsf = assogsf_index[ielegsf];
02571 
02572         // added protection against fifth step
02573         if(fifthStepKfTrack_.size() > 0) {
02574           for(unsigned int itr = 0; itr < fifthStepKfTrack_.size(); itr++) {
02575             if(fifthStepKfTrack_[itr].first == keyecalgsf) {
02576               active[(fifthStepKfTrack_[itr].second)] = false;
02577             }
02578           }
02579         }
02580 
02581         // added locking for conv gsf tracks and kf tracks
02582         if(convGsfTrack_.size() > 0) {
02583           for(unsigned int iconv = 0; iconv < convGsfTrack_.size(); iconv++) {
02584             if(convGsfTrack_[iconv].first == keyecalgsf) {
02585               // lock the GSF track
02586               active[(convGsfTrack_[iconv].second)] = false;
02587               // lock also the KF track associated
02588               std::multimap<double, unsigned> convKf;
02589               block.associatedElements( convGsfTrack_[iconv].second,
02590                                         linkData,
02591                                         convKf,
02592                                         reco::PFBlockElement::TRACK,
02593                                         reco::PFBlock::LINKTEST_ALL );
02594               if(convKf.size() > 0) {
02595                 active[convKf.begin()->second] = false;
02596               }
02597             }
02598           }
02599         }
02600 
02601 
02602         vector<unsigned int> assoecalgsf_index = associatedToEcal_.find(keyecalgsf)->second;
02603         for(unsigned int ips =0; ips<assoecalgsf_index.size();ips++) {
02604           // lock the elements associated to ECAL: PS1,PS2, for the moment not HCAL
02605           if  (elements[(assoecalgsf_index[ips])].type() == reco::PFBlockElement::PS1) 
02606             active[(assoecalgsf_index[ips])] = false;
02607           if  (elements[(assoecalgsf_index[ips])].type() == reco::PFBlockElement::PS2) 
02608             active[(assoecalgsf_index[ips])] = false;
02609           if  (elements[(assoecalgsf_index[ips])].type() == reco::PFBlockElement::TRACK) {
02610             if(lockExtraKf_[cgsf] == true) {          
02611               active[(assoecalgsf_index[ips])] = false;
02612             }
02613           }
02614         }
02615       } // End if ECAL
02616       if (assoele_type == reco::PFBlockElement::BREM) {
02617         unsigned int brem_index = assogsf_index[ielegsf];
02618         vector<unsigned int> assobrem_index = associatedToBrems_.find(brem_index)->second;
02619         for (unsigned int ibrem = 0; ibrem < assobrem_index.size(); ibrem++){
02620           if (elements[(assobrem_index[ibrem])].type() == reco::PFBlockElement::ECAL) {
02621             unsigned int keyecalbrem = assobrem_index[ibrem];
02622             // lock the ecal cluster associated to the brem
02623             active[(assobrem_index[ibrem])] = false;
02624 
02625             // add protection against fifth step
02626             if(fifthStepKfTrack_.size() > 0) {
02627               for(unsigned int itr = 0; itr < fifthStepKfTrack_.size(); itr++) {
02628                 if(fifthStepKfTrack_[itr].first == keyecalbrem) {
02629                   active[(fifthStepKfTrack_[itr].second)] = false;
02630                 }
02631               }
02632             }
02633 
02634             vector<unsigned int> assoelebrem_index = associatedToEcal_.find(keyecalbrem)->second;
02635             // lock the elements associated to ECAL: PS1,PS2, for the moment not HCAL
02636             for (unsigned int ielebrem=0; ielebrem<assoelebrem_index.size();ielebrem++) {
02637               if (elements[(assoelebrem_index[ielebrem])].type() == reco::PFBlockElement::PS1) 
02638                 active[(assoelebrem_index[ielebrem])] = false;
02639               if (elements[(assoelebrem_index[ielebrem])].type() == reco::PFBlockElement::PS2) 
02640                 active[(assoelebrem_index[ielebrem])] = false;
02641             }
02642           }
02643         }
02644       } // End if BREM    
02645     } // End loop on elements from gsf track
02646   }  // End loop on gsf track  
02647   return;
02648 }
02649 void PFElectronAlgo::setEGElectronCollection(const reco::GsfElectronCollection & egelectrons) {
02650   theGsfElectrons_ = & egelectrons;
02651 }
02652 unsigned int PFElectronAlgo::whichTrackAlgo(const reco::TrackRef& trackRef) {
02653   unsigned int Algo = 0; 
02654   switch (trackRef->algo()) {
02655   case TrackBase::ctf:
02656   case TrackBase::iter0:
02657   case TrackBase::iter1:
02658   case TrackBase::iter2:
02659     Algo = 0;
02660     break;
02661   case TrackBase::iter3:
02662     Algo = 1;
02663     break;
02664   case TrackBase::iter4:
02665     Algo = 2;
02666     break;
02667   case TrackBase::iter5:
02668     Algo = 3;
02669     break;
02670   case TrackBase::iter6:
02671     Algo = 4;
02672     break;
02673   default:
02674     Algo = 5;
02675     break;
02676   }
02677   return Algo;
02678 }
02679 bool PFElectronAlgo::isPrimaryTrack(const reco::PFBlockElementTrack& KfEl,
02680                                     const reco::PFBlockElementGsfTrack& GsfEl) {
02681   bool isPrimary = false;
02682   
02683   GsfPFRecTrackRef gsfPfRef = GsfEl.GsftrackRefPF();
02684   
02685   if(gsfPfRef.isNonnull()) {
02686     PFRecTrackRef  kfPfRef = KfEl.trackRefPF();
02687     PFRecTrackRef  kfPfRef_fromGsf = (*gsfPfRef).kfPFRecTrackRef();
02688     if(kfPfRef.isNonnull() && kfPfRef_fromGsf.isNonnull()) {
02689       reco::TrackRef kfref= (*kfPfRef).trackRef();
02690       reco::TrackRef kfref_fromGsf = (*kfPfRef_fromGsf).trackRef();
02691       if(kfref.isNonnull() && kfref_fromGsf.isNonnull()) {
02692         if(kfref ==  kfref_fromGsf)
02693           isPrimary = true;
02694       }
02695     }
02696   }
02697 
02698   return isPrimary;
02699 }