CMS 3D CMS Logo

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