CMS 3D CMS Logo

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

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