CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/RecoParticleFlow/PFProducer/src/PFEGammaAlgo.cc

Go to the documentation of this file.
00001 //
00002 // Original Authors: Fabian Stoeckli: fabian.stoeckli@cern.ch
00003 //                   Nicholas Wardle: nckw@cern.ch
00004 //                   Rishi Patel rpatel@cern.ch(ongoing developer and maintainer)
00005 //
00006 
00007 #include "RecoParticleFlow/PFProducer/interface/PFEGammaAlgo.h"
00008 #include "RecoParticleFlow/PFProducer/interface/PFMuonAlgo.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/PFBlockElementCluster.h"
00013 #include "DataFormats/ParticleFlowReco/interface/PFCluster.h"
00014 #include "DataFormats/ParticleFlowReco/interface/PFClusterFwd.h"
00015 #include "DataFormats/ParticleFlowReco/interface/PFBlockElementSuperCluster.h"
00016 #include "DataFormats/EgammaReco/interface/ElectronSeed.h"
00017 #include "DataFormats/ParticleFlowReco/interface/PFRecHit.h"
00018 #include "DataFormats/EcalDetId/interface/EBDetId.h"
00019 #include "DataFormats/EcalDetId/interface/EEDetId.h"
00020 #include "DataFormats/EgammaCandidates/interface/Photon.h"
00021 #include "RecoParticleFlow/PFClusterTools/interface/PFEnergyCalibration.h"
00022 #include "RecoParticleFlow/PFClusterTools/interface/PFPhotonClusters.h"
00023 #include "RecoParticleFlow/PFClusterTools/interface/PFEnergyCalibration.h"
00024 #include "RecoParticleFlow/PFClusterTools/interface/PFSCEnergyCalibration.h"
00025 #include "RecoParticleFlow/PFClusterTools/interface/PFEnergyResolution.h"
00026 #include "RecoParticleFlow/PFClusterTools/interface/PFClusterWidthAlgo.h"
00027 #include "RecoParticleFlow/PFProducer/interface/PFElectronExtraEqual.h"
00028 #include "RecoEcal/EgammaCoreTools/interface/Mustache.h"
00029 #include "DataFormats/Math/interface/deltaPhi.h"
00030 #include "DataFormats/Math/interface/deltaR.h"
00031 #include <TFile.h>
00032 #include <iomanip>
00033 #include <algorithm>
00034 #include <TMath.h>
00035 using namespace std;
00036 using namespace reco;
00037 
00038 
00039 PFEGammaAlgo::PFEGammaAlgo(const double mvaEleCut,
00040                            std::string  mvaWeightFileEleID,
00041                            const boost::shared_ptr<PFSCEnergyCalibration>& thePFSCEnergyCalibration,
00042                            const boost::shared_ptr<PFEnergyCalibration>& thePFEnergyCalibration,
00043                            bool applyCrackCorrections,
00044                            bool usePFSCEleCalib,
00045                            bool useEGElectrons,
00046                            bool useEGammaSupercluster,
00047                            double sumEtEcalIsoForEgammaSC_barrel,
00048                            double sumEtEcalIsoForEgammaSC_endcap,
00049                            double coneEcalIsoForEgammaSC,
00050                            double sumPtTrackIsoForEgammaSC_barrel,
00051                            double sumPtTrackIsoForEgammaSC_endcap,
00052                            unsigned int nTrackIsoForEgammaSC,
00053                            double coneTrackIsoForEgammaSC,
00054                            std::string mvaweightfile,  
00055                            double mvaConvCut, 
00056                            bool useReg, 
00057                            std::string X0_Map,
00058                            const reco::Vertex& primary,
00059                            double sumPtTrackIsoForPhoton,
00060                            double sumPtTrackIsoSlopeForPhoton
00061                            ) : 
00062   mvaEleCut_(mvaEleCut),
00063   thePFSCEnergyCalibration_(thePFSCEnergyCalibration),
00064   thePFEnergyCalibration_(thePFEnergyCalibration),
00065   applyCrackCorrections_(applyCrackCorrections),
00066   usePFSCEleCalib_(usePFSCEleCalib),
00067   useEGElectrons_(useEGElectrons),
00068   useEGammaSupercluster_(useEGammaSupercluster),
00069   sumEtEcalIsoForEgammaSC_barrel_(sumEtEcalIsoForEgammaSC_barrel),
00070   sumEtEcalIsoForEgammaSC_endcap_(sumEtEcalIsoForEgammaSC_endcap),
00071   coneEcalIsoForEgammaSC_(coneEcalIsoForEgammaSC),
00072   sumPtTrackIsoForEgammaSC_barrel_(sumPtTrackIsoForEgammaSC_barrel),
00073   sumPtTrackIsoForEgammaSC_endcap_(sumPtTrackIsoForEgammaSC_endcap),
00074   nTrackIsoForEgammaSC_(nTrackIsoForEgammaSC),
00075   coneTrackIsoForEgammaSC_(coneTrackIsoForEgammaSC),  
00076   isvalid_(false), 
00077   verbosityLevel_(Silent), 
00078   MVACUT(mvaConvCut),
00079   useReg_(useReg),
00080   sumPtTrackIsoForPhoton_(sumPtTrackIsoForPhoton),
00081   sumPtTrackIsoSlopeForPhoton_(sumPtTrackIsoSlopeForPhoton),
00082   nlost(0.0), nlayers(0.0),
00083   chi2(0.0), STIP(0.0), del_phi(0.0),HoverPt(0.0), EoverPt(0.0), track_pt(0.0),
00084   mvaValue(0.0),
00085   CrysPhi_(0.0), CrysEta_(0.0),  VtxZ_(0.0), ClusPhi_(0.0), ClusEta_(0.0),
00086   ClusR9_(0.0), Clus5x5ratio_(0.0),  PFCrysEtaCrack_(0.0), logPFClusE_(0.0), e3x3_(0.0),
00087   CrysIPhi_(0), CrysIEta_(0),
00088   CrysX_(0.0), CrysY_(0.0),
00089   EB(0.0),
00090   eSeed_(0.0), e1x3_(0.0),e3x1_(0.0), e1x5_(0.0), e2x5Top_(0.0),  e2x5Bottom_(0.0), e2x5Left_(0.0),  e2x5Right_(0.0),
00091   etop_(0.0), ebottom_(0.0), eleft_(0.0), eright_(0.0),
00092   e2x5Max_(0.0),
00093   PFPhoEta_(0.0), PFPhoPhi_(0.0), PFPhoR9_(0.0), PFPhoR9Corr_(0.0), SCPhiWidth_(0.0), SCEtaWidth_(0.0), 
00094   PFPhoEt_(0.0), RConv_(0.0), PFPhoEtCorr_(0.0), PFPhoE_(0.0), PFPhoECorr_(0.0), MustE_(0.0), E3x3_(0.0),
00095   dEta_(0.0), dPhi_(0.0), LowClusE_(0.0), RMSAll_(0.0), RMSMust_(0.0), nPFClus_(0.0),
00096   TotPS1_(0.0), TotPS2_(0.0),
00097   nVtx_(0.0),
00098   x0inner_(0.0), x0middle_(0.0), x0outer_(0.0),
00099   excluded_(0.0), Mustache_EtRatio_(0.0), Mustache_Et_out_(0.0)
00100 {  
00101 
00102   
00103   // Set the tmva reader for electrons
00104   tmvaReaderEle_ = new TMVA::Reader("!Color:Silent");
00105   tmvaReaderEle_->AddVariable("lnPt_gsf",&lnPt_gsf);
00106   tmvaReaderEle_->AddVariable("Eta_gsf",&Eta_gsf);
00107   tmvaReaderEle_->AddVariable("dPtOverPt_gsf",&dPtOverPt_gsf);
00108   tmvaReaderEle_->AddVariable("DPtOverPt_gsf",&DPtOverPt_gsf);
00109   //tmvaReaderEle_->AddVariable("nhit_gsf",&nhit_gsf);
00110   tmvaReaderEle_->AddVariable("chi2_gsf",&chi2_gsf);
00111   //tmvaReaderEle_->AddVariable("DPtOverPt_kf",&DPtOverPt_kf);
00112   tmvaReaderEle_->AddVariable("nhit_kf",&nhit_kf);
00113   tmvaReaderEle_->AddVariable("chi2_kf",&chi2_kf);
00114   tmvaReaderEle_->AddVariable("EtotPinMode",&EtotPinMode);
00115   tmvaReaderEle_->AddVariable("EGsfPoutMode",&EGsfPoutMode);
00116   tmvaReaderEle_->AddVariable("EtotBremPinPoutMode",&EtotBremPinPoutMode);
00117   tmvaReaderEle_->AddVariable("DEtaGsfEcalClust",&DEtaGsfEcalClust);
00118   tmvaReaderEle_->AddVariable("SigmaEtaEta",&SigmaEtaEta);
00119   tmvaReaderEle_->AddVariable("HOverHE",&HOverHE);
00120 //   tmvaReaderEle_->AddVariable("HOverPin",&HOverPin);
00121   tmvaReaderEle_->AddVariable("lateBrem",&lateBrem);
00122   tmvaReaderEle_->AddVariable("firstBrem",&firstBrem);
00123   tmvaReaderEle_->BookMVA("BDT",mvaWeightFileEleID.c_str());
00124   
00125   
00126     //Book MVA  
00127     tmvaReader_ = new TMVA::Reader("!Color:Silent");  
00128     tmvaReader_->AddVariable("del_phi",&del_phi);  
00129     tmvaReader_->AddVariable("nlayers", &nlayers);  
00130     tmvaReader_->AddVariable("chi2",&chi2);  
00131     tmvaReader_->AddVariable("EoverPt",&EoverPt);  
00132     tmvaReader_->AddVariable("HoverPt",&HoverPt);  
00133     tmvaReader_->AddVariable("track_pt", &track_pt);  
00134     tmvaReader_->AddVariable("STIP",&STIP);  
00135     tmvaReader_->AddVariable("nlost", &nlost);  
00136     tmvaReader_->BookMVA("BDT",mvaweightfile.c_str());  
00137 
00138     //Material Map
00139     TFile *XO_File = new TFile(X0_Map.c_str(),"READ");
00140     X0_sum=(TH2D*)XO_File->Get("TrackerSum");
00141     X0_inner = (TH2D*)XO_File->Get("Inner");
00142     X0_middle = (TH2D*)XO_File->Get("Middle");
00143     X0_outer = (TH2D*)XO_File->Get("Outer");
00144     
00145 }
00146 
00147 void PFEGammaAlgo::RunPFEG(const reco::PFBlockRef&  blockRef,
00148                                std::vector<bool>& active
00149 ){
00150   
00151   // should be cleaned as often as often as possible
00152 //   elCandidate_.clear();
00153 //   electronExtra_.clear();
00154 //   allElCandidate_.clear();
00155   //electronConstituents_.clear();
00156   fifthStepKfTrack_.clear();
00157   convGsfTrack_.clear();
00158   
00159   egCandidate_.clear();
00160   egExtra_.clear();
00161   
00162   //std::cout<<" calling RunPFPhoton "<<std::endl;
00163   
00164   /*      For now we construct the PhotonCandidate simply from 
00165           a) adding the CORRECTED energies of each participating ECAL cluster
00166           b) build the energy-weighted direction for the Photon
00167   */
00168 
00169 
00170   // define how much is printed out for debugging.
00171   // ... will be setable via CFG file parameter
00172   verbosityLevel_ = Chatty;          // Chatty mode.
00173   
00174 
00175   // loop over all elements in the Block
00176   const edm::OwnVector< reco::PFBlockElement >&          elements         = blockRef->elements();
00177   edm::OwnVector< reco::PFBlockElement >::const_iterator ele              = elements.begin();
00178   std::vector<bool>::const_iterator                      actIter          = active.begin();
00179   PFBlock::LinkData                                      linkData         = blockRef->linkData();
00180   bool                                                   isActive         = true;
00181 
00182 
00183   if(elements.size() != active.size()) {
00184     // throw excpetion...
00185     //std::cout<<" WARNING: Size of collection and active-vectro don't agree!"<<std::endl;
00186     return;
00187   }
00188   
00189   //build large set of association maps between gsf/kf tracks, PFClusters and SuperClusters
00190   //this function originally came from the PFElectronAlgo
00191   // the maps are initialized 
00192   AssMap associatedToGsf;
00193   AssMap associatedToBrems;
00194   AssMap associatedToEcal;  
00195   
00196   //bool blockHasGSF =  
00197   SetLinks(blockRef,associatedToGsf,
00198                             associatedToBrems,associatedToEcal,
00199                             active, *primaryVertex_);
00200   
00201   //printf("blockHasGsf = %i\n",int(blockHasGSF));
00202   
00203   
00204   // local vecotr to keep track of the indices of the 'elements' for the Photon candidate
00205   // once we decide to keep the candidate, the 'active' entriesd for them must be set to false
00206   std::vector<unsigned int> elemsToLock;
00207   elemsToLock.resize(0);
00208   
00209   for( ; ele != elements.end(); ++ele, ++actIter ) {
00210 
00211     // if it's not a SuperCluster, go to the next element
00212     if( !( ele->type() == reco::PFBlockElement::SC ) ) continue;
00213     
00214     //printf("supercluster\n");
00215     
00216     // Photon kienmatics, will be updated for each identified participating element
00217     float photonEnergy_        =   0.;
00218     float photonX_             =   0.;
00219     float photonY_             =   0.;
00220     float photonZ_             =   0.;
00221     float RawEcalEne           =   0.;
00222 
00223     // Total pre-shower energy
00224     float ps1TotEne      = 0.;
00225     float ps2TotEne      = 0.;
00226     
00227     bool hasConvTrack=false;  
00228     bool hasSingleleg=false;  
00229     std::vector<unsigned int> AddClusters(0);  
00230     std::vector<unsigned int> IsoTracks(0);  
00231     std::multimap<unsigned int, unsigned int>ClusterAddPS1;  
00232     std::multimap<unsigned int, unsigned int>ClusterAddPS2;
00233     std::vector<reco::TrackRef>singleLegRef;
00234     std::vector<float>MVA_values(0);
00235     std::vector<float>MVALCorr;
00236     std::vector<CaloCluster>PFClusters;
00237     reco::ConversionRefVector ConversionsRef_;
00238     isActive = *(actIter);
00239     //cout << " Found a SuperCluster.  Energy " ;
00240     const reco::PFBlockElementSuperCluster *sc = dynamic_cast<const reco::PFBlockElementSuperCluster*>(&(*ele));
00241     //std::cout << sc->superClusterRef()->energy () << " Track/Ecal/Hcal Iso " << sc->trackIso()<< " " << sc->ecalIso() ;
00242     //std::cout << " " << sc->hcalIso() <<std::endl;
00243     //if (!(sc->fromPhoton()))continue;
00244     
00245     // check the status of the SC Element... 
00246     // ..... I understand it should *always* be active, since PFElectronAlgo does not touch this (yet?) RISHI: YES
00247     if( !isActive ) {
00248       //std::cout<<" SuperCluster is NOT active.... "<<std::endl;
00249       continue;
00250     }
00251     elemsToLock.push_back(ele-elements.begin()); //add SC to elements to lock
00252     // loop over its constituent ECAL cluster
00253     std::multimap<double, unsigned int> ecalAssoPFClusters;
00254     blockRef->associatedElements( ele-elements.begin(), 
00255                                   linkData,
00256                                   ecalAssoPFClusters,
00257                                   reco::PFBlockElement::ECAL,
00258                                   reco::PFBlock::LINKTEST_ALL );
00259     //R9 of SuperCluster and RawE
00260     //PFPhoR9_=sc->photonRef()->r9();
00261     PFPhoR9_=1.0;
00262     E3x3_=PFPhoR9_*(sc->superClusterRef()->rawEnergy());
00263     // loop over the ECAL clusters linked to the iEle 
00264     if( ! ecalAssoPFClusters.size() ) {
00265       // This SC element has NO ECAL elements asigned... *SHOULD NOT HAPPEN*
00266       //std::cout<<" Found SC element with no ECAL assigned "<<std::endl;
00267       continue;
00268     }
00269     
00270     //list of matched gsf tracks associated to this supercluster through
00271     //a shared PFCluster
00272     //std::set<unsigned int> matchedGsf;
00273     std::vector<unsigned int> matchedGsf;
00274     for (map<unsigned int,vector<unsigned int> >::iterator igsf = associatedToGsf.begin();
00275        igsf != associatedToGsf.end(); igsf++) {    
00276       
00277       bool matched = false;
00278       if( !( active[igsf->first] ) ) continue;
00279     
00280       vector<unsigned int> assogsf_index = igsf->second;
00281       for  (unsigned int ielegsf=0;ielegsf<assogsf_index.size();ielegsf++) {
00282         unsigned int associdx = assogsf_index[ielegsf];
00283         
00284         if( !( active[associdx] ) ) continue;
00285         
00286         PFBlockElement::Type assoele_type = elements[associdx].type();
00287         
00288         if(assoele_type == reco::PFBlockElement::ECAL) {
00289           for(std::multimap<double, unsigned int>::iterator itecal = ecalAssoPFClusters.begin(); 
00290             itecal != ecalAssoPFClusters.end(); ++itecal) {
00291             
00292             if (itecal->second==associdx) {
00293               matchedGsf.push_back(igsf->first);
00294               matched = true;
00295               break;
00296             }
00297           }
00298         }
00299           
00300         if (matched) break;
00301       }
00302       
00303     }
00304     
00305    //printf("matchedGsf size = %i\n",int(matchedGsf.size()));
00306 
00307       
00308     // This is basically CASE 2
00309     // .... we loop over all ECAL cluster linked to each other by this SC
00310     for(std::multimap<double, unsigned int>::iterator itecal = ecalAssoPFClusters.begin(); 
00311         itecal != ecalAssoPFClusters.end(); ++itecal) { 
00312       
00313       //printf("ecal cluster\n");
00314       
00315       //loop over associated elements to check for gsf
00316       
00317 //       std::map<unsigned int, std::vector<unsigned int> >::const_iterator assoc_ecal_it = associatedToEcal.find(itecal->second);
00318 //       if (assoc_ecal_it!=associatedToEcal.end()) {
00319 //      const std::vector<unsigned int> &assoecal_index = assoc_ecal_it->second;
00320 //      for  (unsigned int iecalassoc=0;iecalassoc<assoecal_index.size();iecalassoc++) {
00321 //        int associdx = assoecal_index[iecalassoc];
00322 //        PFBlockElement::Type assoele_type = elements[associdx].type();
00323 //        // lock the elements associated to the gsf: ECAL, Brems
00324 //        //active[(assogsf_index[ielegsf])] = false;  
00325 //        printf("matched element to ecal cluster, type = %i\n",int(assoele_type));
00326 //        
00327 //        if (assoele_type == reco::PFBlockElement::GSF) {      
00328 //          printf("matched gsf\n");
00329 //          if (!matchedGsf.count(associdx)) {
00330 //            matchedGsf.insert(associdx);
00331 //          }
00332 //        }
00333 //      }
00334 //       }
00335       
00336 
00337       
00338       // to get the reference to the PF clusters, this is needed.
00339       reco::PFClusterRef clusterRef = elements[itecal->second].clusterRef();    
00340       
00341     
00342     
00343     
00344       // from the clusterRef get the energy, direction, etc
00345       //      float ClustRawEnergy = clusterRef->energy();
00346       //      float ClustEta = clusterRef->position().eta();
00347       //      float ClustPhi = clusterRef->position().phi();
00348       
00349       // initialize the vectors for the PS energies
00350       vector<double> ps1Ene(0);
00351       vector<double> ps2Ene(0);
00352       double ps1=0;  
00353       double ps2=0;  
00354       hasSingleleg=false;  
00355       hasConvTrack=false;
00356       
00357       /*
00358         cout << " My cluster index " << itecal->second 
00359         << " energy " <<  ClustRawEnergy
00360            << " eta " << ClustEta
00361            << " phi " << ClustPhi << endl;
00362       */
00363       // check if this ECAL element is still active (could have been eaten by PFElectronAlgo)
00364       // ......for now we give the PFElectron Algo *ALWAYS* Shot-Gun on the ECAL elements to the PFElectronAlgo
00365       
00366       if( !( active[itecal->second] ) ) {
00367         //std::cout<< "  .... this ECAL element is NOT active anymore. Is skipped. "<<std::endl;
00368         continue;
00369       }
00370       
00371       // ------------------------------------------------------------------------------------------
00372       // TODO: do some tests on the ECAL cluster itself, deciding to use it or not for the Photons
00373       // ..... ??? Do we need this?
00374       if ( false ) {
00375         // Check if there are a large number tracks that do not pass pre-ID around this ECAL cluster
00376         bool useIt = true;
00377         int mva_reject=0;  
00378         bool isClosest=false;  
00379         std::multimap<double, unsigned int> Trackscheck;  
00380         blockRef->associatedElements( itecal->second,  
00381                                       linkData,  
00382                                       Trackscheck,  
00383                                       reco::PFBlockElement::TRACK,  
00384                                       reco::PFBlock::LINKTEST_ALL);  
00385         for(std::multimap<double, unsigned int>::iterator track = Trackscheck.begin();  
00386             track != Trackscheck.end(); ++track) {  
00387            
00388           // first check if is it's still active  
00389           if( ! (active[track->second]) ) continue;  
00390           hasSingleleg=EvaluateSingleLegMVA(blockRef,  *primaryVertex_, track->second);  
00391           //check if it is the closest linked track  
00392           std::multimap<double, unsigned int> closecheck;  
00393           blockRef->associatedElements(track->second,  
00394                                        linkData,  
00395                                        closecheck,  
00396                                        reco::PFBlockElement::ECAL,  
00397                                        reco::PFBlock::LINKTEST_ALL);  
00398           if(closecheck.begin()->second ==itecal->second)isClosest=true;  
00399           if(!hasSingleleg)mva_reject++;  
00400         }  
00401         
00402         if(mva_reject>0 &&  isClosest)useIt=false;  
00403         //if(mva_reject==1 && isClosest)useIt=false;
00404         if( !useIt ) continue;    // Go to next ECAL cluster within SC
00405       }
00406       // ------------------------------------------------------------------------------------------
00407       
00408       // We decided to keep the ECAL cluster for this Photon Candidate ...
00409       elemsToLock.push_back(itecal->second);
00410       
00411       // look for PS in this Block linked to this ECAL cluster      
00412       std::multimap<double, unsigned int> PS1Elems;
00413       std::multimap<double, unsigned int> PS2Elems;
00414       //PS Layer 1 linked to ECAL cluster
00415       blockRef->associatedElements( itecal->second,
00416                                     linkData,
00417                                     PS1Elems,
00418                                     reco::PFBlockElement::PS1,
00419                                     reco::PFBlock::LINKTEST_ALL );
00420       //PS Layer 2 linked to the ECAL cluster
00421       blockRef->associatedElements( itecal->second,
00422                                     linkData,
00423                                     PS2Elems,
00424                                     reco::PFBlockElement::PS2,
00425                                     reco::PFBlock::LINKTEST_ALL );
00426       
00427       // loop over all PS1 and compute energy
00428       for(std::multimap<double, unsigned int>::iterator iteps = PS1Elems.begin();
00429           iteps != PS1Elems.end(); ++iteps) {
00430 
00431         // first chekc if it's still active
00432         if( !(active[iteps->second]) ) continue;
00433         
00434         //Check if this PS1 is not closer to another ECAL cluster in this Block          
00435         std::multimap<double, unsigned int> ECALPS1check;  
00436         blockRef->associatedElements( iteps->second,  
00437                                       linkData,  
00438                                       ECALPS1check,  
00439                                       reco::PFBlockElement::ECAL,  
00440                                       reco::PFBlock::LINKTEST_ALL );  
00441         if(itecal->second==ECALPS1check.begin()->second)//then it is closest linked  
00442           {
00443             reco::PFClusterRef ps1ClusterRef = elements[iteps->second].clusterRef();
00444             ps1Ene.push_back( ps1ClusterRef->energy() );
00445             ps1=ps1+ps1ClusterRef->energy(); //add to total PS1
00446             // incativate this PS1 Element
00447             elemsToLock.push_back(iteps->second);
00448           }
00449       }
00450       for(std::multimap<double, unsigned int>::iterator iteps = PS2Elems.begin();
00451           iteps != PS2Elems.end(); ++iteps) {
00452 
00453         // first chekc if it's still active
00454         if( !(active[iteps->second]) ) continue;
00455         
00456         // Check if this PS2 is not closer to another ECAL cluster in this Block:
00457         std::multimap<double, unsigned int> ECALPS2check;  
00458         blockRef->associatedElements( iteps->second,  
00459                                       linkData,  
00460                                       ECALPS2check,  
00461                                       reco::PFBlockElement::ECAL,  
00462                                       reco::PFBlock::LINKTEST_ALL );  
00463         if(itecal->second==ECALPS2check.begin()->second)//is closest linked  
00464           {
00465             reco::PFClusterRef ps2ClusterRef = elements[iteps->second].clusterRef();
00466             ps2Ene.push_back( ps2ClusterRef->energy() );
00467             ps2=ps2ClusterRef->energy()+ps2; //add to total PS2
00468             // incativate this PS2 Element
00469             elemsToLock.push_back(iteps->second);
00470           }
00471       }
00472             
00473       // loop over the HCAL Clusters linked to the ECAL cluster (CASE 6)
00474       std::multimap<double, unsigned int> hcalElems;
00475       blockRef->associatedElements( itecal->second,linkData,
00476                                     hcalElems,
00477                                     reco::PFBlockElement::HCAL,
00478                                     reco::PFBlock::LINKTEST_ALL );
00479 
00480       for(std::multimap<double, unsigned int>::iterator ithcal = hcalElems.begin();
00481           ithcal != hcalElems.end(); ++ithcal) {
00482 
00483         if ( ! (active[ithcal->second] ) ) continue; // HCAL Cluster already used....
00484         
00485         // TODO: Decide if this HCAL cluster is to be used
00486         // .... based on some Physics
00487         // .... To we need to check if it's closer to any other ECAL/TRACK?
00488 
00489         bool useHcal = false;
00490         if ( !useHcal ) continue;
00491         //not locked
00492         //elemsToLock.push_back(ithcal->second);
00493       }
00494 
00495       // This is entry point for CASE 3.
00496       // .... we loop over all Tracks linked to this ECAL and check if it's labeled as conversion
00497       // This is the part for looping over all 'Conversion' Tracks
00498       std::multimap<double, unsigned int> convTracks;
00499       blockRef->associatedElements( itecal->second,
00500                                     linkData,
00501                                     convTracks,
00502                                     reco::PFBlockElement::TRACK,
00503                                     reco::PFBlock::LINKTEST_ALL);
00504       for(std::multimap<double, unsigned int>::iterator track = convTracks.begin();
00505           track != convTracks.end(); ++track) {
00506 
00507         // first check if is it's still active
00508         if( ! (active[track->second]) ) continue;
00509         
00510         // check if it's a CONV track
00511         const reco::PFBlockElementTrack * trackRef = dynamic_cast<const reco::PFBlockElementTrack*>((&elements[track->second]));        
00512         
00513         //Check if track is a Single leg from a Conversion  
00514         mvaValue=-999;  
00515         hasSingleleg=EvaluateSingleLegMVA(blockRef,  *primaryVertex_, track->second);
00516 
00517         // Daniele; example for mvaValues, do the same for single leg trackRef and convRef
00518         //          
00519         //      if(hasSingleleg)
00520         //        mvaValues.push_back(mvaValue);
00521 
00522         //If it is not then it will be used to check Track Isolation at the end  
00523         if(!hasSingleleg)  
00524           {  
00525             bool included=false;  
00526             //check if this track is already included in the vector so it is linked to an ECAL cluster that is already examined  
00527             for(unsigned int i=0; i<IsoTracks.size(); i++)  
00528               {if(IsoTracks[i]==track->second)included=true;}  
00529             if(!included)IsoTracks.push_back(track->second);  
00530           }  
00531         //For now only Pre-ID tracks that are not already identified as Conversions  
00532         if(hasSingleleg &&!(trackRef->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)))  
00533           {  
00534             elemsToLock.push_back(track->second);
00535             
00536             reco::TrackRef t_ref=elements[track->second].trackRef();
00537             bool matched=false;
00538             for(unsigned int ic=0; ic<singleLegRef.size(); ic++)
00539               if(singleLegRef[ic]==t_ref)matched=true;
00540             
00541             if(!matched){
00542               singleLegRef.push_back(t_ref);
00543               MVA_values.push_back(mvaValue);
00544             }
00545             //find all the clusters linked to this track  
00546             std::multimap<double, unsigned int> moreClusters;  
00547             blockRef->associatedElements( track->second,  
00548                                           linkData,  
00549                                           moreClusters,  
00550                                           reco::PFBlockElement::ECAL,  
00551                                           reco::PFBlock::LINKTEST_ALL);  
00552              
00553             float p_in=sqrt(elements[track->second].trackRef()->innerMomentum().x() * elements[track->second].trackRef()->innerMomentum().x() +  
00554                             elements[track->second].trackRef()->innerMomentum().y()*elements[track->second].trackRef()->innerMomentum().y()+  
00555                             elements[track->second].trackRef()->innerMomentum().z()*elements[track->second].trackRef()->innerMomentum().z());  
00556             float linked_E=0;  
00557             for(std::multimap<double, unsigned int>::iterator clust = moreClusters.begin();  
00558                 clust != moreClusters.end(); ++clust)  
00559               {  
00560                 if(!active[clust->second])continue;  
00561                 //running sum of linked energy  
00562                 linked_E=linked_E+elements[clust->second].clusterRef()->energy();  
00563                 //prevent too much energy from being added  
00564                 if(linked_E/p_in>1.5)break;  
00565                 bool included=false;  
00566                 //check if these ecal clusters are already included with the supercluster  
00567                 for(std::multimap<double, unsigned int>::iterator cluscheck = ecalAssoPFClusters.begin();  
00568                     cluscheck != ecalAssoPFClusters.end(); ++cluscheck)  
00569                   {  
00570                     if(cluscheck->second==clust->second)included=true;  
00571                   }  
00572                 if(!included)AddClusters.push_back(clust->second);//Add to a container of clusters to be Added to the Photon candidate  
00573               }  
00574           }
00575 
00576         // Possibly need to be more smart about them (CASE 5)
00577         // .... for now we simply skip non id'ed tracks
00578         if( ! (trackRef->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) ) ) continue;  
00579         hasConvTrack=true;  
00580         elemsToLock.push_back(track->second);
00581         //again look at the clusters linked to this track  
00582         //if(elements[track->second].convRef().isNonnull())
00583         //{         
00584         //  ConversionsRef_.push_back(elements[track->second].convRef());
00585         //}
00586         std::multimap<double, unsigned int> moreClusters;  
00587         blockRef->associatedElements( track->second,  
00588                                       linkData,  
00589                                       moreClusters,  
00590                                       reco::PFBlockElement::ECAL,  
00591                                       reco::PFBlock::LINKTEST_ALL);
00592         
00593         float p_in=sqrt(elements[track->second].trackRef()->innerMomentum().x() * elements[track->second].trackRef()->innerMomentum().x() +  
00594                         elements[track->second].trackRef()->innerMomentum().y()*elements[track->second].trackRef()->innerMomentum().y()+  
00595                         elements[track->second].trackRef()->innerMomentum().z()*elements[track->second].trackRef()->innerMomentum().z());  
00596         float linked_E=0;  
00597         for(std::multimap<double, unsigned int>::iterator clust = moreClusters.begin();  
00598             clust != moreClusters.end(); ++clust)  
00599           {  
00600             if(!active[clust->second])continue;  
00601             linked_E=linked_E+elements[clust->second].clusterRef()->energy();  
00602             if(linked_E/p_in>1.5)break;  
00603             bool included=false;  
00604             for(std::multimap<double, unsigned int>::iterator cluscheck = ecalAssoPFClusters.begin();  
00605                 cluscheck != ecalAssoPFClusters.end(); ++cluscheck)  
00606               {  
00607                 if(cluscheck->second==clust->second)included=true;  
00608               }  
00609             if(!included)AddClusters.push_back(clust->second);//again only add if it is not already included with the supercluster  
00610           }
00611         
00612         // we need to check for other TRACKS linked to this conversion track, that point possibly no an ECAL cluster not included in the SC
00613         // .... This is basically CASE 4.
00614         
00615         std::multimap<double, unsigned int> moreTracks;
00616         blockRef->associatedElements( track->second,
00617                                       linkData,
00618                                       moreTracks,
00619                                       reco::PFBlockElement::TRACK,
00620                                       reco::PFBlock::LINKTEST_ALL);
00621         
00622         for(std::multimap<double, unsigned int>::iterator track2 = moreTracks.begin();
00623             track2 != moreTracks.end(); ++track2) {
00624           
00625           // first check if is it's still active
00626           if( ! (active[track2->second]) ) continue;
00627           //skip over the 1st leg already found above  
00628           if(track->second==track2->second)continue;      
00629           // check if it's a CONV track
00630           const reco::PFBlockElementTrack * track2Ref = dynamic_cast<const reco::PFBlockElementTrack*>((&elements[track2->second]));    
00631           if( ! (track2Ref->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) ) ) continue;  // Possibly need to be more smart about them (CASE 5)
00632           elemsToLock.push_back(track2->second);
00633           // so it's another active conversion track, that is in the Block and linked to the conversion track we already found
00634           // find the ECAL cluster linked to it...
00635           std::multimap<double, unsigned int> convEcalAll;
00636           blockRef->associatedElements( track2->second,
00637                                         linkData,
00638                                         convEcalAll,
00639                                         reco::PFBlockElement::ECAL,
00640                                         reco::PFBlock::LINKTEST_ALL);
00641           
00642           //create cleaned collection of associated ecal clusters restricted to subdetector of the seeding supercluster
00643           //This cleaning is needed since poorly reconstructed conversions can occasionally have the second track pointing
00644           //to the wrong subdetector
00645           std::multimap<double, unsigned int> convEcal;
00646           for(std::multimap<double, unsigned int>::iterator itecal = convEcalAll.begin(); 
00647               itecal != convEcalAll.end(); ++itecal) { 
00648                   
00649                   // to get the reference to the PF clusters, this is needed.
00650             reco::PFClusterRef clusterRef = elements[itecal->second].clusterRef();
00651             
00652             if (clusterRef->hitsAndFractions().at(0).first.subdetId()==sc->superClusterRef()->seed()->hitsAndFractions().at(0).first.subdetId()) {
00653               convEcal.insert(*itecal);
00654             }
00655           }
00656           
00657           float p_in=sqrt(elements[track->second].trackRef()->innerMomentum().x()*elements[track->second].trackRef()->innerMomentum().x()+
00658                           elements[track->second].trackRef()->innerMomentum().y()*elements[track->second].trackRef()->innerMomentum().y()+  
00659                           elements[track->second].trackRef()->innerMomentum().z()*elements[track->second].trackRef()->innerMomentum().z());  
00660           
00661           
00662           float linked_E=0;
00663           for(std::multimap<double, unsigned int>::iterator itConvEcal = convEcal.begin();
00664               itConvEcal != convEcal.end(); ++itConvEcal) {
00665             
00666             if( ! (active[itConvEcal->second]) ) continue;
00667             bool included=false;  
00668             for(std::multimap<double, unsigned int>::iterator cluscheck = ecalAssoPFClusters.begin();  
00669                 cluscheck != ecalAssoPFClusters.end(); ++cluscheck)  
00670               {  
00671                 if(cluscheck->second==itConvEcal->second)included=true;  
00672               }
00673             linked_E=linked_E+elements[itConvEcal->second].clusterRef()->energy();
00674             if(linked_E/p_in>1.5)break;
00675             if(!included){AddClusters.push_back(itConvEcal->second);
00676             }
00677             
00678             // it's still active, so we have to add it.
00679             // CAUTION: we don't care here if it's part of the SC or not, we include it anyways
00680             
00681             // loop over the HCAL Clusters linked to the ECAL cluster (CASE 6)
00682             std::multimap<double, unsigned int> hcalElems_conv;
00683             blockRef->associatedElements( itecal->second,linkData,
00684                                           hcalElems_conv,
00685                                           reco::PFBlockElement::HCAL,
00686                                           reco::PFBlock::LINKTEST_ALL );
00687             
00688             for(std::multimap<double, unsigned int>::iterator ithcal2 = hcalElems_conv.begin();
00689                 ithcal2 != hcalElems_conv.end(); ++ithcal2) {
00690               
00691               if ( ! (active[ithcal2->second] ) ) continue; // HCAL Cluster already used....
00692               
00693               // TODO: Decide if this HCAL cluster is to be used
00694               // .... based on some Physics
00695               // .... To we need to check if it's closer to any other ECAL/TRACK?
00696               
00697               bool useHcal = true;
00698               if ( !useHcal ) continue;
00699               
00700               //elemsToLock.push_back(ithcal2->second);
00701 
00702             } // end of loop over HCAL clusters linked to the ECAL cluster from second CONVERSION leg
00703             
00704           } // end of loop over ECALs linked to second T_FROM_GAMMACONV
00705           
00706         } // end of loop over SECOND conversion leg
00707 
00708         // TODO: Do we need to check separatly if there are HCAL cluster linked to the track?
00709         
00710       } // end of loop over tracks
00711       
00712             
00713       // Calibrate the Added ECAL energy
00714       float addedCalibEne=0;
00715       float addedRawEne=0;
00716       std::vector<double>AddedPS1(0);
00717       std::vector<double>AddedPS2(0);  
00718       double addedps1=0;  
00719       double addedps2=0;  
00720       for(unsigned int i=0; i<AddClusters.size(); i++)  
00721         {  
00722           std::multimap<double, unsigned int> PS1Elems_conv;  
00723           std::multimap<double, unsigned int> PS2Elems_conv;  
00724           blockRef->associatedElements(AddClusters[i],  
00725                                        linkData,  
00726                                        PS1Elems_conv,  
00727                                        reco::PFBlockElement::PS1,  
00728                                        reco::PFBlock::LINKTEST_ALL );  
00729           blockRef->associatedElements( AddClusters[i],  
00730                                         linkData,  
00731                                         PS2Elems_conv,  
00732                                         reco::PFBlockElement::PS2,  
00733                                         reco::PFBlock::LINKTEST_ALL );  
00734            
00735           for(std::multimap<double, unsigned int>::iterator iteps = PS1Elems_conv.begin();  
00736               iteps != PS1Elems_conv.end(); ++iteps)  
00737             {  
00738               if(!active[iteps->second])continue;  
00739               std::multimap<double, unsigned int> PS1Elems_check;  
00740               blockRef->associatedElements(iteps->second,  
00741                                            linkData,  
00742                                            PS1Elems_check,  
00743                                            reco::PFBlockElement::ECAL,  
00744                                            reco::PFBlock::LINKTEST_ALL );  
00745               if(PS1Elems_check.begin()->second==AddClusters[i])  
00746                 {  
00747                    
00748                   reco::PFClusterRef ps1ClusterRef = elements[iteps->second].clusterRef();  
00749                   AddedPS1.push_back(ps1ClusterRef->energy());  
00750                   addedps1=addedps1+ps1ClusterRef->energy();  
00751                   elemsToLock.push_back(iteps->second);  
00752                 }  
00753             }  
00754            
00755           for(std::multimap<double, unsigned int>::iterator iteps = PS2Elems_conv.begin();  
00756               iteps != PS2Elems_conv.end(); ++iteps) {  
00757             if(!active[iteps->second])continue;  
00758             std::multimap<double, unsigned int> PS2Elems_check;  
00759             blockRef->associatedElements(iteps->second,  
00760                                          linkData,  
00761                                          PS2Elems_check,  
00762                                          reco::PFBlockElement::ECAL,  
00763                                          reco::PFBlock::LINKTEST_ALL );  
00764              
00765             if(PS2Elems_check.begin()->second==AddClusters[i])  
00766               {  
00767                 reco::PFClusterRef ps2ClusterRef = elements[iteps->second].clusterRef();  
00768                 AddedPS2.push_back(ps2ClusterRef->energy());  
00769                 addedps2=addedps2+ps2ClusterRef->energy();  
00770                 elemsToLock.push_back(iteps->second);  
00771               }  
00772           }  
00773           reco::PFClusterRef AddclusterRef = elements[AddClusters[i]].clusterRef();  
00774           addedRawEne = AddclusterRef->energy()+addedRawEne;  
00775           addedCalibEne = thePFEnergyCalibration_->energyEm(*AddclusterRef,AddedPS1,AddedPS2,false)+addedCalibEne;  
00776           AddedPS2.clear(); 
00777           AddedPS1.clear();  
00778           elemsToLock.push_back(AddClusters[i]);  
00779         }  
00780       AddClusters.clear();
00781       float EE=thePFEnergyCalibration_->energyEm(*clusterRef,ps1Ene,ps2Ene,false)+addedCalibEne;
00782       PFClusters.push_back(*clusterRef);
00783       if(useReg_){
00784         float LocCorr=EvaluateLCorrMVA(clusterRef);
00785         EE=LocCorr*clusterRef->energy()+addedCalibEne;
00786       }
00787       else{
00788         float LocCorr=EvaluateLCorrMVA(clusterRef);
00789         MVALCorr.push_back(LocCorr*clusterRef->energy());
00790       }
00791       
00792       //cout<<"Original Energy "<<EE<<"Added Energy "<<addedCalibEne<<endl;
00793       
00794       photonEnergy_ +=  EE;
00795       RawEcalEne    +=  clusterRef->energy()+addedRawEne;
00796       photonX_      +=  EE * clusterRef->position().X();
00797       photonY_      +=  EE * clusterRef->position().Y();
00798       photonZ_      +=  EE * clusterRef->position().Z();                
00799       ps1TotEne     +=  ps1+addedps1;
00800       ps2TotEne     +=  ps2+addedps2;
00801     } // end of loop over all ECAL cluster within this SC
00802 
00803     
00804     //add elements from electron candidates
00805     bool goodelectron = false;
00806     if (matchedGsf.size()>0) {
00807       //printf("making electron, candsize = %i\n",int(egCandidate_.size()));
00808       int eleidx = matchedGsf.front();
00809       AddElectronElements(eleidx, elemsToLock, blockRef, associatedToGsf, associatedToBrems, associatedToEcal);
00810       goodelectron = AddElectronCandidate(eleidx, sc->superClusterRef(), elemsToLock, blockRef, associatedToGsf, associatedToBrems, associatedToEcal, active);
00811       //printf("goodelectron = %i, candsize = %i\n",int(goodelectron),int(egCandidate_.size()));
00812     }    
00813     
00814     if (goodelectron) continue;
00815     
00816     //printf("making photon\n");
00817     
00818     // we've looped over all ECAL clusters, ready to generate PhotonCandidate
00819     if( ! (photonEnergy_ > 0.) ) continue;    // This SC is not a Photon Candidate
00820     float sum_track_pt=0;
00821     //Now check if there are tracks failing isolation outside of the Jurassic isolation region  
00822     for(unsigned int i=0; i<IsoTracks.size(); i++)sum_track_pt=sum_track_pt+elements[IsoTracks[i]].trackRef()->pt();  
00823     
00824 
00825 
00826     math::XYZVector photonPosition(photonX_,
00827                                    photonY_,
00828                                    photonZ_);
00829     math::XYZVector photonPositionwrtVtx(
00830                                          photonX_- primaryVertex_->x(),
00831                                          photonY_-primaryVertex_->y(),
00832                                          photonZ_-primaryVertex_->z()
00833                                          );
00834     math::XYZVector photonDirection=photonPositionwrtVtx.Unit();
00835     
00836     math::XYZTLorentzVector photonMomentum(photonEnergy_* photonDirection.X(),
00837                                            photonEnergy_* photonDirection.Y(),
00838                                            photonEnergy_* photonDirection.Z(),
00839                                            photonEnergy_           );
00840 
00841 //     if(sum_track_pt>(sumPtTrackIsoForPhoton_ + sumPtTrackIsoSlopeForPhoton_ * photonMomentum.pt()) && AddFromElectron_.size()==0)
00842 //       {
00843 //      elemsToLock.resize(0);
00844 //      continue;
00845 //      
00846 //       }
00847 
00848         //THIS SC is not a Photon it fails track Isolation
00849     //if(sum_track_pt>(2+ 0.001* photonMomentum.pt()))
00850     //continue;//THIS SC is not a Photon it fails track Isolation
00851 
00852     /*
00853     std::cout<<" Created Photon with energy = "<<photonEnergy_<<std::endl;
00854     std::cout<<"                         pT = "<<photonMomentum.pt()<<std::endl;
00855     std::cout<<"                     RawEne = "<<RawEcalEne<<std::endl;
00856     std::cout<<"                          E = "<<photonMomentum.e()<<std::endl;
00857     std::cout<<"                        eta = "<<photonMomentum.eta()<<std::endl;
00858     std::cout<<"             TrackIsolation = "<< sum_track_pt <<std::endl;
00859     */
00860 
00861     reco::PFCandidate photonCand(0,photonMomentum, reco::PFCandidate::gamma);
00862     photonCand.setPs1Energy(ps1TotEne);
00863     photonCand.setPs2Energy(ps2TotEne);
00864     photonCand.setEcalEnergy(RawEcalEne,photonEnergy_);
00865     photonCand.setHcalEnergy(0.,0.);
00866     photonCand.set_mva_nothing_gamma(1.);  
00867     photonCand.setSuperClusterRef(sc->superClusterRef());
00868     math::XYZPoint v(primaryVertex_->x(), primaryVertex_->y(), primaryVertex_->z());
00869     photonCand.setVertex( v  );
00870     if(hasConvTrack || hasSingleleg)photonCand.setFlag( reco::PFCandidate::GAMMA_TO_GAMMACONV, true);
00871 //     int matches=match_ind.size();
00872 //     int count=0;
00873 //     for ( std::vector<reco::PFCandidate>::const_iterator ec=tempElectronCandidates.begin();   ec != tempElectronCandidates.end(); ++ec ){
00874 //       for(int i=0; i<matches; i++)
00875 //      {
00876 //        if(count==match_ind[i])photonCand.addDaughter(*ec);
00877 //        count++;
00878 //      }
00879 //     }
00880     // set isvalid_ to TRUE since we've found at least one photon candidate
00881     isvalid_ = true;
00882     // push back the candidate into the collection ...
00883     //Add Elements from Electron
00884     for(std::vector<unsigned int>::const_iterator it = 
00885           AddFromElectron_.begin();
00886         it != AddFromElectron_.end(); ++it)photonCand.addElementInBlock(blockRef,*it);
00887     
00888     // ... and lock all elemts used
00889     for(std::vector<unsigned int>::const_iterator it = elemsToLock.begin();
00890         it != elemsToLock.end(); ++it)
00891       {
00892         if(active[*it])
00893           {
00894             photonCand.addElementInBlock(blockRef,*it);
00895             if( elements[*it].type() == reco::PFBlockElement::TRACK  )
00896               {
00897                 if(elements[*it].convRef().isNonnull())
00898                   {
00899                     //make sure it is not stored already as the partner track
00900                     bool matched=false;
00901                     for(unsigned int ic = 0; ic < ConversionsRef_.size(); ic++)
00902                       {
00903                         if(ConversionsRef_[ic]==elements[*it].convRef())matched=true;
00904                       }
00905                     if(!matched)ConversionsRef_.push_back(elements[*it].convRef());
00906                   }
00907               }
00908           }
00909         active[*it] = false;    
00910       }
00911     PFPhoECorr_=0;
00912     // here add the extra information
00913     //PFCandidateEGammaExtra myExtra(sc->superClusterRef());
00914     PFCandidateEGammaExtra myExtra;
00915     //myExtra.setSuperClusterRef(sc->superClusterRef());
00916     myExtra.setSuperClusterBoxRef(sc->superClusterRef());
00917     //myExtra.setClusterEnergies(MVALCorr);
00918     //Store Locally Contained PF Cluster regressed energy
00919     for(unsigned int l=0; l<MVALCorr.size(); ++l)
00920       {
00921         //myExtra.addLCorrClusEnergy(MVALCorr[l]);
00922         PFPhoECorr_=PFPhoECorr_+MVALCorr[l];//total Locally corrected energy
00923       }
00924     TotPS1_=ps1TotEne;
00925     TotPS2_=ps2TotEne;
00926     //Do Global Corrections here:
00927     float GCorr=EvaluateGCorrMVA(photonCand, PFClusters);
00928     if(useReg_){
00929       math::XYZTLorentzVector photonCorrMomentum(GCorr*PFPhoECorr_* photonDirection.X(),
00930                                                  GCorr*PFPhoECorr_* photonDirection.Y(),
00931                                                  GCorr*PFPhoECorr_* photonDirection.Z(),
00932                                                  GCorr * photonEnergy_           );
00933       photonCand.setP4(photonCorrMomentum);
00934     }
00935     
00936     std::multimap<float, unsigned int>OrderedClust;
00937     for(unsigned int i=0; i<PFClusters.size(); ++i){  
00938       float et=PFClusters[i].energy()*sin(PFClusters[i].position().theta());
00939       OrderedClust.insert(make_pair(et, i));
00940     }
00941     std::multimap<float, unsigned int>::reverse_iterator rit;
00942     rit=OrderedClust.rbegin();
00943     unsigned int highEindex=(*rit).second;
00944     //store Position at ECAL Entrance as Position of Max Et PFCluster
00945     photonCand.setPositionAtECALEntrance(math::XYZPointF(PFClusters[highEindex].position()));
00946     
00947     //Mustache ID variables
00948 //     Mustache Must;
00949 //     Must.FillMustacheVar(PFClusters);
00950 //     int excluded= Must.OutsideMust();
00951 //     float MustacheEt=Must.MustacheEtOut();
00952     //myExtra.setMustache_Et(MustacheEt);
00953     //myExtra.setExcludedClust(excluded);
00954 //     if(fabs(photonCand.eta()<1.4446))
00955 //       myExtra.setMVAGlobalCorrE(GCorr * PFPhoECorr_);
00956 //     else if(PFPhoR9_>0.94)
00957 //       myExtra.setMVAGlobalCorrE(GCorr * PFPhoECorr_);
00958 //     else myExtra.setMVAGlobalCorrE(GCorr * photonEnergy_);
00959 //     float Res=EvaluateResMVA(photonCand, PFClusters);
00960 //     myExtra.SetPFPhotonRes(Res);
00961     
00962     //    Daniele example for mvaValues
00963     //    do the same for single leg trackRef and convRef
00964     for(unsigned int ic = 0; ic < MVA_values.size(); ic++)
00965       {
00966         myExtra.addSingleLegConvMva(MVA_values[ic]);
00967         myExtra.addSingleLegConvTrackRef(singleLegRef[ic]);
00968         //cout<<"Single Leg Tracks "<<singleLegRef[ic]->pt()<<" MVA "<<MVA_values[ic]<<endl;
00969       }
00970     for(unsigned int ic = 0; ic < ConversionsRef_.size(); ic++)
00971       {
00972         myExtra.addConversionRef(ConversionsRef_[ic]);
00973         //cout<<"Conversion Pairs "<<ConversionsRef_[ic]->pairMomentum()<<endl;
00974       }
00975     egExtra_.push_back(myExtra);
00976     egCandidate_.push_back(photonCand);
00977     // ... and reset the vector
00978     elemsToLock.resize(0);
00979     hasConvTrack=false;
00980     hasSingleleg=false;
00981   } // end of loops over all elements in block
00982   
00983   return;
00984 }
00985 
00986 float PFEGammaAlgo::EvaluateResMVA(reco::PFCandidate photon, std::vector<reco::CaloCluster>PFClusters){
00987   float BDTG=1;
00988   PFPhoEta_=photon.eta();
00989   PFPhoPhi_=photon.phi();
00990   PFPhoE_=photon.energy();
00991   //fill Material Map:
00992   int ix = X0_sum->GetXaxis()->FindBin(PFPhoEta_);
00993   int iy = X0_sum->GetYaxis()->FindBin(PFPhoPhi_);
00994   x0inner_= X0_inner->GetBinContent(ix,iy);
00995   x0middle_=X0_middle->GetBinContent(ix,iy);
00996   x0outer_=X0_outer->GetBinContent(ix,iy);
00997   SCPhiWidth_=photon.superClusterRef()->phiWidth();
00998   SCEtaWidth_=photon.superClusterRef()->etaWidth();
00999   Mustache Must;
01000   std::vector<unsigned int>insideMust;
01001   std::vector<unsigned int>outsideMust;
01002   std::multimap<float, unsigned int>OrderedClust;
01003   Must.FillMustacheVar(PFClusters);
01004   MustE_=Must.MustacheE();
01005   LowClusE_=Must.LowestMustClust();
01006   PFPhoR9Corr_=E3x3_/MustE_;
01007   Must.MustacheClust(PFClusters,insideMust, outsideMust );
01008   for(unsigned int i=0; i<insideMust.size(); ++i){
01009     int index=insideMust[i];
01010     OrderedClust.insert(make_pair(PFClusters[index].energy(),index));
01011   }
01012   std::multimap<float, unsigned int>::iterator it;
01013   it=OrderedClust.begin();
01014   unsigned int lowEindex=(*it).second;
01015   std::multimap<float, unsigned int>::reverse_iterator rit;
01016   rit=OrderedClust.rbegin();
01017   unsigned int highEindex=(*rit).second;
01018   if(insideMust.size()>1){
01019     dEta_=fabs(PFClusters[highEindex].eta()-PFClusters[lowEindex].eta());
01020     dPhi_=asin(PFClusters[highEindex].phi()-PFClusters[lowEindex].phi());
01021   }
01022   else{
01023     dEta_=0;
01024     dPhi_=0;
01025     LowClusE_=0;
01026   }
01027   //calculate RMS for All clusters and up until the Next to Lowest inside the Mustache
01028   RMSAll_=ClustersPhiRMS(PFClusters, PFPhoPhi_);
01029   std::vector<reco::CaloCluster>PFMustClusters;
01030   if(insideMust.size()>2){
01031     for(unsigned int i=0; i<insideMust.size(); ++i){
01032       unsigned int index=insideMust[i];
01033       if(index==lowEindex)continue;
01034       PFMustClusters.push_back(PFClusters[index]);
01035     }
01036   }
01037   else{
01038     for(unsigned int i=0; i<insideMust.size(); ++i){
01039       unsigned int index=insideMust[i];
01040       PFMustClusters.push_back(PFClusters[index]);
01041     }    
01042   }
01043   RMSMust_=ClustersPhiRMS(PFMustClusters, PFPhoPhi_);
01044   //then use cluster Width for just one PFCluster
01045   RConv_=310;
01046   PFCandidate::ElementsInBlocks eleInBlocks = photon.elementsInBlocks();
01047   for(unsigned i=0; i<eleInBlocks.size(); i++)
01048     {
01049       PFBlockRef blockRef = eleInBlocks[i].first;
01050       unsigned indexInBlock = eleInBlocks[i].second;
01051       const edm::OwnVector< reco::PFBlockElement >&  elements=eleInBlocks[i].first->elements();
01052       const reco::PFBlockElement& element = elements[indexInBlock];
01053       if(element.type()==reco::PFBlockElement::TRACK){
01054         float R=sqrt(element.trackRef()->innerPosition().X()*element.trackRef()->innerPosition().X()+element.trackRef()->innerPosition().Y()*element.trackRef()->innerPosition().Y());
01055         if(RConv_>R)RConv_=R;
01056       }
01057       else continue;
01058     }
01059   float GC_Var[17];
01060   GC_Var[0]=PFPhoEta_;
01061   GC_Var[1]=PFPhoEt_;
01062   GC_Var[2]=PFPhoR9Corr_;
01063   GC_Var[3]=PFPhoPhi_;
01064   GC_Var[4]=SCEtaWidth_;
01065   GC_Var[5]=SCPhiWidth_;
01066   GC_Var[6]=x0inner_;  
01067   GC_Var[7]=x0middle_;
01068   GC_Var[8]=x0outer_;
01069   GC_Var[9]=RConv_;
01070   GC_Var[10]=LowClusE_;
01071   GC_Var[11]=RMSMust_;
01072   GC_Var[12]=RMSAll_;
01073   GC_Var[13]=dEta_;
01074   GC_Var[14]=dPhi_;
01075   GC_Var[15]=nVtx_;
01076   GC_Var[16]=MustE_;
01077   
01078   BDTG=ReaderRes_->GetResponse(GC_Var);
01079   //  cout<<"Res "<<BDTG<<endl;
01080   
01081   //  cout<<"BDTG Parameters X0"<<x0inner_<<", "<<x0middle_<<", "<<x0outer_<<endl;
01082   //  cout<<"Et, Eta, Phi "<<PFPhoEt_<<", "<<PFPhoEta_<<", "<<PFPhoPhi_<<endl;
01083   // cout<<"PFPhoR9 "<<PFPhoR9_<<endl;
01084   // cout<<"R "<<RConv_<<endl;
01085   
01086   return BDTG;
01087    
01088 }
01089 
01090 float PFEGammaAlgo::EvaluateGCorrMVA(reco::PFCandidate photon, std::vector<CaloCluster>PFClusters){
01091   float BDTG=1;
01092   PFPhoEta_=photon.eta();
01093   PFPhoPhi_=photon.phi();
01094   PFPhoE_=photon.energy();
01095     //fill Material Map:
01096   int ix = X0_sum->GetXaxis()->FindBin(PFPhoEta_);
01097   int iy = X0_sum->GetYaxis()->FindBin(PFPhoPhi_);
01098   x0inner_= X0_inner->GetBinContent(ix,iy);
01099   x0middle_=X0_middle->GetBinContent(ix,iy);
01100   x0outer_=X0_outer->GetBinContent(ix,iy);
01101   SCPhiWidth_=photon.superClusterRef()->phiWidth();
01102   SCEtaWidth_=photon.superClusterRef()->etaWidth();
01103   Mustache Must;
01104   std::vector<unsigned int>insideMust;
01105   std::vector<unsigned int>outsideMust;
01106   std::multimap<float, unsigned int>OrderedClust;
01107   Must.FillMustacheVar(PFClusters);
01108   MustE_=Must.MustacheE();
01109   LowClusE_=Must.LowestMustClust();
01110   PFPhoR9Corr_=E3x3_/MustE_;
01111   Must.MustacheClust(PFClusters,insideMust, outsideMust );
01112   for(unsigned int i=0; i<insideMust.size(); ++i){
01113     int index=insideMust[i];
01114     OrderedClust.insert(make_pair(PFClusters[index].energy(),index));
01115   }
01116   std::multimap<float, unsigned int>::iterator it;
01117   it=OrderedClust.begin();
01118   unsigned int lowEindex=(*it).second;
01119   std::multimap<float, unsigned int>::reverse_iterator rit;
01120   rit=OrderedClust.rbegin();
01121   unsigned int highEindex=(*rit).second;
01122   if(insideMust.size()>1){
01123     dEta_=fabs(PFClusters[highEindex].eta()-PFClusters[lowEindex].eta());
01124     dPhi_=asin(PFClusters[highEindex].phi()-PFClusters[lowEindex].phi());
01125   }
01126   else{
01127     dEta_=0;
01128     dPhi_=0;
01129     LowClusE_=0;
01130   }
01131   //calculate RMS for All clusters and up until the Next to Lowest inside the Mustache
01132   RMSAll_=ClustersPhiRMS(PFClusters, PFPhoPhi_);
01133   std::vector<reco::CaloCluster>PFMustClusters;
01134   if(insideMust.size()>2){
01135     for(unsigned int i=0; i<insideMust.size(); ++i){
01136       unsigned int index=insideMust[i];
01137       if(index==lowEindex)continue;
01138       PFMustClusters.push_back(PFClusters[index]);
01139     }
01140   }
01141   else{
01142     for(unsigned int i=0; i<insideMust.size(); ++i){
01143       unsigned int index=insideMust[i];
01144       PFMustClusters.push_back(PFClusters[index]);
01145     }    
01146   }
01147   RMSMust_=ClustersPhiRMS(PFMustClusters, PFPhoPhi_);
01148   //then use cluster Width for just one PFCluster
01149   RConv_=310;
01150   PFCandidate::ElementsInBlocks eleInBlocks = photon.elementsInBlocks();
01151   for(unsigned i=0; i<eleInBlocks.size(); i++)
01152     {
01153       PFBlockRef blockRef = eleInBlocks[i].first;
01154       unsigned indexInBlock = eleInBlocks[i].second;
01155       const edm::OwnVector< reco::PFBlockElement >&  elements=eleInBlocks[i].first->elements();
01156       const reco::PFBlockElement& element = elements[indexInBlock];
01157       if(element.type()==reco::PFBlockElement::TRACK){
01158         float R=sqrt(element.trackRef()->innerPosition().X()*element.trackRef()->innerPosition().X()+element.trackRef()->innerPosition().Y()*element.trackRef()->innerPosition().Y());
01159         if(RConv_>R)RConv_=R;
01160       }
01161       else continue;
01162     }
01163   //cout<<"Nvtx "<<nVtx_<<endl;
01164   if(fabs(PFPhoEta_)<1.4446){
01165     float GC_Var[17];
01166     GC_Var[0]=PFPhoEta_;
01167     GC_Var[1]=PFPhoECorr_;
01168     GC_Var[2]=PFPhoR9Corr_;
01169     GC_Var[3]=SCEtaWidth_;
01170     GC_Var[4]=SCPhiWidth_;
01171     GC_Var[5]=PFPhoPhi_;
01172     GC_Var[6]=x0inner_;
01173     GC_Var[7]=x0middle_;
01174     GC_Var[8]=x0outer_;
01175     GC_Var[9]=RConv_;
01176     GC_Var[10]=LowClusE_;
01177     GC_Var[11]=RMSMust_;
01178     GC_Var[12]=RMSAll_;
01179     GC_Var[13]=dEta_;
01180     GC_Var[14]=dPhi_;
01181     GC_Var[15]=nVtx_;
01182     GC_Var[16]=MustE_;
01183     BDTG=ReaderGCEB_->GetResponse(GC_Var);
01184   }
01185   else if(PFPhoR9_>0.94){
01186     float GC_Var[19];
01187     GC_Var[0]=PFPhoEta_;
01188     GC_Var[1]=PFPhoECorr_;
01189     GC_Var[2]=PFPhoR9Corr_;
01190     GC_Var[3]=SCEtaWidth_;
01191     GC_Var[4]=SCPhiWidth_;
01192     GC_Var[5]=PFPhoPhi_;
01193     GC_Var[6]=x0inner_;
01194     GC_Var[7]=x0middle_;
01195     GC_Var[8]=x0outer_;
01196     GC_Var[9]=RConv_;
01197     GC_Var[10]=LowClusE_;
01198     GC_Var[11]=RMSMust_;
01199     GC_Var[12]=RMSAll_;
01200     GC_Var[13]=dEta_;
01201     GC_Var[14]=dPhi_;
01202     GC_Var[15]=nVtx_;
01203     GC_Var[16]=TotPS1_;
01204     GC_Var[17]=TotPS2_;
01205     GC_Var[18]=MustE_;
01206     BDTG=ReaderGCEEhR9_->GetResponse(GC_Var);
01207   }
01208   
01209   else{
01210     float GC_Var[19];
01211     GC_Var[0]=PFPhoEta_;
01212     GC_Var[1]=PFPhoE_;
01213     GC_Var[2]=PFPhoR9Corr_;
01214     GC_Var[3]=SCEtaWidth_;
01215     GC_Var[4]=SCPhiWidth_;
01216     GC_Var[5]=PFPhoPhi_;
01217     GC_Var[6]=x0inner_;
01218     GC_Var[7]=x0middle_;
01219     GC_Var[8]=x0outer_;
01220     GC_Var[9]=RConv_;
01221     GC_Var[10]=LowClusE_;
01222     GC_Var[11]=RMSMust_;
01223     GC_Var[12]=RMSAll_;
01224     GC_Var[13]=dEta_;
01225     GC_Var[14]=dPhi_;
01226     GC_Var[15]=nVtx_;
01227     GC_Var[16]=TotPS1_;
01228     GC_Var[17]=TotPS2_;
01229     GC_Var[18]=MustE_;
01230     BDTG=ReaderGCEElR9_->GetResponse(GC_Var);
01231   }
01232   //cout<<"GC "<<BDTG<<endl;
01233 
01234   return BDTG;
01235   
01236 }
01237 
01238 double PFEGammaAlgo::ClustersPhiRMS(std::vector<reco::CaloCluster>PFClusters, float PFPhoPhi){
01239   double PFClustPhiRMS=0;
01240   double delPhi2=0;
01241   double delPhiSum=0;
01242   double ClusSum=0;
01243   for(unsigned int c=0; c<PFClusters.size(); ++c){
01244     delPhi2=(acos(cos(PFPhoPhi-PFClusters[c].phi()))* acos(cos(PFPhoPhi-PFClusters[c].phi())) )+delPhi2;
01245     delPhiSum=delPhiSum+ acos(cos(PFPhoPhi-PFClusters[c].phi()))*PFClusters[c].energy();
01246     ClusSum=ClusSum+PFClusters[c].energy();
01247   }
01248   double meandPhi=delPhiSum/ClusSum;
01249   PFClustPhiRMS=sqrt(fabs(delPhi2/ClusSum - (meandPhi*meandPhi)));
01250   
01251   return PFClustPhiRMS;
01252 }
01253 
01254 float PFEGammaAlgo::EvaluateLCorrMVA(reco::PFClusterRef clusterRef ){
01255   float BDTG=1;
01256   PFPhotonClusters ClusterVar(clusterRef);
01257   std::pair<double, double>ClusCoor=ClusterVar.GetCrysCoor();
01258   std::pair<int, int>ClusIndex=ClusterVar.GetCrysIndex();
01259   //Local Coordinates:
01260   if(clusterRef->layer()==PFLayer:: ECAL_BARREL ){//is Barrel
01261     PFCrysEtaCrack_=ClusterVar.EtaCrack();
01262     CrysEta_=ClusCoor.first;
01263     CrysPhi_=ClusCoor.second;
01264     CrysIEta_=ClusIndex.first;
01265     CrysIPhi_=ClusIndex.second;
01266   }
01267   else{
01268     CrysX_=ClusCoor.first;
01269     CrysY_=ClusCoor.second;
01270   }
01271   //Shower Shape Variables:
01272   eSeed_= ClusterVar.E5x5Element(0, 0)/clusterRef->energy();
01273   etop_=ClusterVar.E5x5Element(0,1)/clusterRef->energy();
01274   ebottom_=ClusterVar.E5x5Element(0,-1)/clusterRef->energy();
01275   eleft_=ClusterVar.E5x5Element(-1,0)/clusterRef->energy();
01276   eright_=ClusterVar.E5x5Element(1,0)/clusterRef->energy();
01277   e1x3_=(ClusterVar.E5x5Element(0,0)+ClusterVar.E5x5Element(0,1)+ClusterVar.E5x5Element(0,-1))/clusterRef->energy();
01278   e3x1_=(ClusterVar.E5x5Element(0,0)+ClusterVar.E5x5Element(-1,0)+ClusterVar.E5x5Element(1,0))/clusterRef->energy();
01279   e1x5_=ClusterVar.E5x5Element(0,0)+ClusterVar.E5x5Element(0,-2)+ClusterVar.E5x5Element(0,-1)+ClusterVar.E5x5Element(0,1)+ClusterVar.E5x5Element(0,2);
01280   
01281   e2x5Top_=(ClusterVar.E5x5Element(-2,2)+ClusterVar.E5x5Element(-1, 2)+ClusterVar.E5x5Element(0, 2)
01282             +ClusterVar.E5x5Element(1, 2)+ClusterVar.E5x5Element(2, 2)
01283             +ClusterVar.E5x5Element(-2,1)+ClusterVar.E5x5Element(-1,1)+ClusterVar.E5x5Element(0,1)
01284             +ClusterVar.E5x5Element(1,1)+ClusterVar.E5x5Element(2,1))/clusterRef->energy();
01285   e2x5Bottom_=(ClusterVar.E5x5Element(-2,-2)+ClusterVar.E5x5Element(-1,-2)+ClusterVar.E5x5Element(0,-2)
01286                +ClusterVar.E5x5Element(1,-2)+ClusterVar.E5x5Element(2,-2)
01287                +ClusterVar.E5x5Element(-2,1)+ClusterVar.E5x5Element(-1,1)
01288                +ClusterVar.E5x5Element(0,1)+ClusterVar.E5x5Element(1,1)+ClusterVar.E5x5Element(2,1))/clusterRef->energy();
01289   e2x5Left_= (ClusterVar.E5x5Element(-2,-2)+ClusterVar.E5x5Element(-2,-1)
01290               +ClusterVar.E5x5Element(-2,0)
01291                +ClusterVar.E5x5Element(-2,1)+ClusterVar.E5x5Element(-2,2)
01292               +ClusterVar.E5x5Element(-1,-2)+ClusterVar.E5x5Element(-1,-1)+ClusterVar.E5x5Element(-1,0)
01293               +ClusterVar.E5x5Element(-1,1)+ClusterVar.E5x5Element(-1,2))/clusterRef->energy();
01294   
01295   e2x5Right_ =(ClusterVar.E5x5Element(2,-2)+ClusterVar.E5x5Element(2,-1)
01296                +ClusterVar.E5x5Element(2,0)+ClusterVar.E5x5Element(2,1)+ClusterVar.E5x5Element(2,2)
01297                +ClusterVar.E5x5Element(1,-2)+ClusterVar.E5x5Element(1,-1)+ClusterVar.E5x5Element(1,0)
01298                +ClusterVar.E5x5Element(1,1)+ClusterVar.E5x5Element(1,2))/clusterRef->energy();
01299   float centerstrip=ClusterVar.E5x5Element(0,0)+ClusterVar.E5x5Element(0, -2)
01300     +ClusterVar.E5x5Element(0,-1)+ClusterVar.E5x5Element(0,1)+ClusterVar.E5x5Element(0,2);
01301   float rightstrip=ClusterVar.E5x5Element(1, 0)+ClusterVar.E5x5Element(1,1)
01302     +ClusterVar.E5x5Element(1,2)+ClusterVar.E5x5Element(1,-1)+ClusterVar.E5x5Element(1,-2);
01303   float leftstrip=ClusterVar.E5x5Element(-1,0)+ClusterVar.E5x5Element(-1,-1)+ClusterVar.E5x5Element(-1,2)
01304     +ClusterVar.E5x5Element(-1,1)+ClusterVar.E5x5Element(-1,2);
01305   
01306   if(rightstrip>leftstrip)e2x5Max_=rightstrip+centerstrip;
01307   else e2x5Max_=leftstrip+centerstrip;
01308   e2x5Max_=e2x5Max_/clusterRef->energy();
01309   //GetCrysCoordinates(clusterRef);
01310   //fill5x5Map(clusterRef);
01311   VtxZ_=primaryVertex_->z();
01312   ClusPhi_=clusterRef->position().phi(); 
01313   ClusEta_=fabs(clusterRef->position().eta());
01314   EB=fabs(clusterRef->position().eta())/clusterRef->position().eta();
01315   logPFClusE_=log(clusterRef->energy());
01316   if(ClusEta_<1.4446){
01317     float LC_Var[26];
01318     LC_Var[0]=VtxZ_;
01319     LC_Var[1]=EB;
01320     LC_Var[2]=ClusEta_;
01321     LC_Var[3]=ClusPhi_;
01322     LC_Var[4]=logPFClusE_;
01323     LC_Var[5]=eSeed_;
01324     //top bottom left right
01325     LC_Var[6]=etop_;
01326     LC_Var[7]=ebottom_;
01327     LC_Var[8]=eleft_;
01328     LC_Var[9]=eright_;
01329     LC_Var[10]=ClusR9_;
01330     LC_Var[11]=e1x3_;
01331     LC_Var[12]=e3x1_;
01332     LC_Var[13]=Clus5x5ratio_;
01333     LC_Var[14]=e1x5_;
01334     LC_Var[15]=e2x5Max_;
01335     LC_Var[16]=e2x5Top_;
01336     LC_Var[17]=e2x5Bottom_;
01337     LC_Var[18]=e2x5Left_;
01338     LC_Var[19]=e2x5Right_;
01339     LC_Var[20]=CrysEta_;
01340     LC_Var[21]=CrysPhi_;
01341     float CrysIphiMod2=CrysIPhi_%2;
01342     float CrysIetaMod5=CrysIEta_%5;
01343     float CrysIphiMod20=CrysIPhi_%20;
01344     LC_Var[22]=CrysIphiMod2;
01345     LC_Var[23]=CrysIetaMod5;
01346     LC_Var[24]=CrysIphiMod20;   
01347     LC_Var[25]=PFCrysEtaCrack_;
01348     BDTG=ReaderLCEB_->GetResponse(LC_Var);   
01349     //cout<<"LC "<<BDTG<<endl;  
01350   }
01351   else{
01352     float LC_Var[22];
01353     LC_Var[0]=VtxZ_;
01354     LC_Var[1]=EB;
01355     LC_Var[2]=ClusEta_;
01356     LC_Var[3]=ClusPhi_;
01357     LC_Var[4]=logPFClusE_;
01358     LC_Var[5]=eSeed_;
01359     //top bottom left right
01360     LC_Var[6]=etop_;
01361     LC_Var[7]=ebottom_;
01362     LC_Var[8]=eleft_;
01363     LC_Var[9]=eright_;
01364     LC_Var[10]=ClusR9_;
01365     LC_Var[11]=e1x3_;
01366     LC_Var[12]=e3x1_;
01367     LC_Var[13]=Clus5x5ratio_;
01368     LC_Var[14]=e1x5_;
01369     LC_Var[15]=e2x5Max_;
01370     LC_Var[16]=e2x5Top_;
01371     LC_Var[17]=e2x5Bottom_;
01372     LC_Var[18]=e2x5Left_;
01373     LC_Var[19]=e2x5Right_;
01374     LC_Var[20]=CrysX_;
01375     LC_Var[21]=CrysY_;
01376     BDTG=ReaderLCEE_->GetResponse(LC_Var);   
01377     //cout<<"LC "<<BDTG<<endl;  
01378   }
01379    return BDTG;
01380   
01381 }
01382 
01383 bool PFEGammaAlgo::EvaluateSingleLegMVA(const reco::PFBlockRef& blockref, const reco::Vertex& primaryvtx, unsigned int track_index)  
01384 {  
01385   bool convtkfound=false;  
01386   const reco::PFBlock& block = *blockref;  
01387   const edm::OwnVector< reco::PFBlockElement >& elements = block.elements();  
01388   //use this to store linkdata in the associatedElements function below  
01389   PFBlock::LinkData linkData =  block.linkData();  
01390   //calculate MVA Variables  
01391   chi2=elements[track_index].trackRef()->chi2()/elements[track_index].trackRef()->ndof();  
01392   nlost=elements[track_index].trackRef()->trackerExpectedHitsInner().numberOfLostHits();  
01393   nlayers=elements[track_index].trackRef()->hitPattern().trackerLayersWithMeasurement();  
01394   track_pt=elements[track_index].trackRef()->pt();  
01395   STIP=elements[track_index].trackRefPF()->STIP();  
01396    
01397   float linked_e=0;  
01398   float linked_h=0;  
01399   std::multimap<double, unsigned int> ecalAssoTrack;  
01400   block.associatedElements( track_index,linkData,  
01401                             ecalAssoTrack,  
01402                             reco::PFBlockElement::ECAL,  
01403                             reco::PFBlock::LINKTEST_ALL );  
01404   std::multimap<double, unsigned int> hcalAssoTrack;  
01405   block.associatedElements( track_index,linkData,  
01406                             hcalAssoTrack,  
01407                             reco::PFBlockElement::HCAL,  
01408                             reco::PFBlock::LINKTEST_ALL );  
01409   if(ecalAssoTrack.size() > 0) {  
01410     for(std::multimap<double, unsigned int>::iterator itecal = ecalAssoTrack.begin();  
01411         itecal != ecalAssoTrack.end(); ++itecal) {  
01412       linked_e=linked_e+elements[itecal->second].clusterRef()->energy();  
01413     }  
01414   }  
01415   if(hcalAssoTrack.size() > 0) {  
01416     for(std::multimap<double, unsigned int>::iterator ithcal = hcalAssoTrack.begin();  
01417         ithcal != hcalAssoTrack.end(); ++ithcal) {  
01418       linked_h=linked_h+elements[ithcal->second].clusterRef()->energy();  
01419     }  
01420   }  
01421   EoverPt=linked_e/elements[track_index].trackRef()->pt();  
01422   HoverPt=linked_h/elements[track_index].trackRef()->pt();  
01423   GlobalVector rvtx(elements[track_index].trackRef()->innerPosition().X()-primaryvtx.x(),  
01424                     elements[track_index].trackRef()->innerPosition().Y()-primaryvtx.y(),  
01425                     elements[track_index].trackRef()->innerPosition().Z()-primaryvtx.z());  
01426   double vtx_phi=rvtx.phi();  
01427   //delta Phi between conversion vertex and track  
01428   del_phi=fabs(deltaPhi(vtx_phi, elements[track_index].trackRef()->innerMomentum().Phi()));  
01429   mvaValue = tmvaReader_->EvaluateMVA("BDT");  
01430   if(mvaValue > MVACUT)convtkfound=true;  
01431   return convtkfound;  
01432 }
01433 
01434 //Recover Early Conversions reconstructed as PFelectrons
01435 void PFEGammaAlgo::EarlyConversion(    
01436                                    //std::auto_ptr< reco::PFCandidateCollection > 
01437                                    //&pfElectronCandidates_,
01438                                    std::vector<reco::PFCandidate>& 
01439                                    tempElectronCandidates,
01440                                    const reco::PFBlockElementSuperCluster* sc
01441                                    ){
01442   //step 1 check temp electrons for clusters that match Photon Supercluster:
01443   // permElectronCandidates->clear();
01444   int count=0;
01445   for ( std::vector<reco::PFCandidate>::const_iterator ec=tempElectronCandidates.begin();   ec != tempElectronCandidates.end(); ++ec ) 
01446     {
01447       //      bool matched=false;
01448       int mh=ec->gsfTrackRef()->trackerExpectedHitsInner().numberOfLostHits();
01449       //if(mh==0)continue;//Case where missing hits greater than zero
01450       
01451       reco::GsfTrackRef gsf=ec->gsfTrackRef();
01452       //some hoopla to get Electron SC ref
01453       
01454       if(gsf->extra().isAvailable() && gsf->extra()->seedRef().isAvailable() && mh>0) 
01455         {
01456           reco::ElectronSeedRef seedRef=  gsf->extra()->seedRef().castTo<reco::ElectronSeedRef>();
01457           if(seedRef.isAvailable() && seedRef->isEcalDriven()) 
01458             {
01459               reco::SuperClusterRef ElecscRef = seedRef->caloCluster().castTo<reco::SuperClusterRef>();
01460               
01461               if(ElecscRef.isNonnull()){
01462                 //finally see if it matches:
01463                 reco::SuperClusterRef PhotscRef=sc->superClusterRef();
01464                 if(PhotscRef==ElecscRef)
01465                   {
01466                     match_ind.push_back(count);
01467                     //  matched=true; 
01468                     //cout<<"Matched Electron with Index "<<count<<" This is the electron "<<*ec<<endl;
01469                     //find that they have the same SC footprint start to collect Clusters and tracks and these will be passed to PFPhoton
01470                     reco::PFCandidate::ElementsInBlocks eleInBlocks = ec->elementsInBlocks();
01471                     for(unsigned i=0; i<eleInBlocks.size(); i++) 
01472                       {
01473                         reco::PFBlockRef blockRef = eleInBlocks[i].first;
01474                         unsigned indexInBlock = eleInBlocks[i].second;   
01475                         //const edm::OwnVector< reco::PFBlockElement >&  elements=eleInBlocks[i].first->elements();
01476                         //const reco::PFBlockElement& element = elements[indexInBlock];                 
01477                         
01478                         AddFromElectron_.push_back(indexInBlock);               
01479                       }             
01480                   }             
01481               }
01482             }     
01483         }           
01484       count++;
01485     }
01486 }
01487 
01488 bool PFEGammaAlgo::SetLinks(const reco::PFBlockRef&  blockRef,
01489                               AssMap& associatedToGsf_,
01490                               AssMap& associatedToBrems_,
01491                               AssMap& associatedToEcal_,     
01492                               std::vector<bool>& active,
01493                                   const reco::Vertex & primaryVertex) {
01494   unsigned int CutIndex = 100000;
01495   double CutGSFECAL = 10000. ;  
01496   // no other cut are not used anymore. We use the default of PFBlockAlgo
01497   //PFEnergyCalibration pfcalib_;  
01498   bool DebugSetLinksSummary = false;
01499   bool DebugSetLinksDetailed = false;
01500 
01501   const reco::PFBlock& block = *blockRef;
01502   const edm::OwnVector< reco::PFBlockElement >&  elements = block.elements();
01503   PFBlock::LinkData linkData =  block.linkData();  
01504   
01505   bool IsThereAGSFTrack = false;
01506   bool IsThereAGoodGSFTrack = false;
01507 
01508   vector<unsigned int> trackIs(0);
01509   vector<unsigned int> gsfIs(0);
01510   vector<unsigned int> ecalIs(0);
01511 
01512   std::vector<bool> localactive(elements.size(),true);
01513  
01514 
01515   // Save the elements in shorter vectors like in PFAlgo.
01516   std::multimap<double, unsigned int> kfElems;
01517   for(unsigned int iEle=0; iEle<elements.size(); iEle++) {
01518     localactive[iEle] = active[iEle];
01519     bool thisIsAMuon = false;
01520     PFBlockElement::Type type = elements[iEle].type();
01521     switch( type ) {
01522     case PFBlockElement::TRACK:
01523       // Check if the track is already identified as a muon
01524       thisIsAMuon =  PFMuonAlgo::isMuon(elements[iEle]);
01525       // Otherwise store index
01526       if ( !thisIsAMuon && active[iEle] ) { 
01527         trackIs.push_back( iEle );
01528         if (DebugSetLinksDetailed) 
01529           cout<<"TRACK, stored index, continue "<< iEle << endl;
01530       }
01531       continue;
01532     case PFBlockElement::GSF:
01533       // Check if the track has a KF partner identified as a muon
01534       block.associatedElements( iEle,linkData,
01535                                 kfElems,
01536                                 reco::PFBlockElement::TRACK,
01537                                 reco::PFBlock::LINKTEST_ALL );
01538       thisIsAMuon = kfElems.size() ? 
01539       PFMuonAlgo::isMuon(elements[kfElems.begin()->second]) : false;
01540       // Otherwise store index
01541       if ( !thisIsAMuon && active[iEle] ) { 
01542         IsThereAGSFTrack = true;    
01543         gsfIs.push_back( iEle );
01544         if (DebugSetLinksDetailed) 
01545           cout<<"GSF, stored index, continue "<< iEle << endl;
01546       }
01547       continue;
01548     case PFBlockElement::ECAL: 
01549       if ( active[iEle]  ) { 
01550         ecalIs.push_back( iEle );
01551         if (DebugSetLinksDetailed) 
01552           cout<<"ECAL, stored index, continue "<< iEle << endl;
01553       }
01554       continue;
01555     default:
01556       continue;
01557     }
01558   }
01559   // ******************* Start Link *****************************
01560   // Do something only if a gsf track is found in the block
01561   if(IsThereAGSFTrack) {
01562     
01563 
01564     // LocalLock the Elements associated to a Kf tracks and not to a Gsf
01565     // The clusters associated both to a kf track and to a brem tangend 
01566     // are then assigned only to the kf track
01567     // Could be improved doing this after. 
01568 
01569     // 19 Mar 2010 adding the KF track from Gamma Conv. 
01570     // They are linked to the GSF tracks they are not considered
01571     // anymore in the following ecal cluster locking 
01572     if (DebugSetLinksDetailed) {
01573       cout<<"#########################################################"<<endl;
01574       cout<<"#####           Process Block:                      #####"<<endl;
01575       cout<<"#########################################################"<<endl;
01576       cout<<block<<endl;
01577     }      
01578 
01579     
01580     for(unsigned int iEle=0; iEle<trackIs.size(); iEle++) {
01581       std::multimap<double, unsigned int> gsfElems;
01582       block.associatedElements( trackIs[iEle],  linkData,
01583                                 gsfElems ,
01584                                 reco::PFBlockElement::GSF,
01585                                 reco::PFBlock::LINKTEST_ALL );
01586       if(gsfElems.size() == 0){
01587         // This means that the considered kf is *not* associated
01588         // to any gsf track
01589         std::multimap<double, unsigned int> ecalKfElems;
01590         block.associatedElements( trackIs[iEle],linkData,
01591                                   ecalKfElems,
01592                                   reco::PFBlockElement::ECAL,
01593                                   reco::PFBlock::LINKTEST_ALL );
01594         if(ecalKfElems.size() > 0) { 
01595           unsigned int ecalKf_index = ecalKfElems.begin()->second;
01596           if(localactive[ecalKf_index]==true) {
01597             // Check if this clusters is however well linked to a primary gsf track
01598             // if this the case the cluster is not locked.
01599             
01600             bool isGsfLinked = false;
01601             for(unsigned int iGsf=0; iGsf<gsfIs.size(); iGsf++) {  
01602               // if the ecal cluster is associated contemporary to a KF track
01603               // and to a GSF track from conv, it is assigned to the KF track 
01604               // In this way we can loose some cluster but it is safer for double counting. 
01605               const reco::PFBlockElementGsfTrack * GsfEl  =  
01606                 dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[gsfIs[iGsf]]));
01607               if(GsfEl->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)) continue;
01608               
01609               std::multimap<double, unsigned int> ecalGsfElems;
01610               block.associatedElements( gsfIs[iGsf],linkData,
01611                                         ecalGsfElems,
01612                                         reco::PFBlockElement::ECAL,
01613                                         reco::PFBlock::LINKTEST_ALL );
01614               if(ecalGsfElems.size() > 0) {
01615                 if (ecalGsfElems.begin()->second == ecalKf_index) {
01616                   isGsfLinked = true;
01617                 }
01618               }
01619             }
01620             if(isGsfLinked == false) {
01621               // add protection against energy loss because
01622               // of the tracking fifth step
01623               const reco::PFBlockElementTrack * kfEle =  
01624                 dynamic_cast<const reco::PFBlockElementTrack*>((&elements[(trackIs[iEle])]));   
01625               reco::TrackRef refKf = kfEle->trackRef();
01626               
01627               int nexhits = refKf->trackerExpectedHitsInner().numberOfLostHits();  
01628               
01629               unsigned int Algo = 0;
01630               if (refKf.isNonnull()) 
01631                 Algo = refKf->algo(); 
01632               
01633               bool trackIsFromPrimaryVertex = false;
01634               for (Vertex::trackRef_iterator trackIt = primaryVertex.tracks_begin(); trackIt != primaryVertex.tracks_end(); ++trackIt) {
01635                 if ( (*trackIt).castTo<TrackRef>() == refKf ) {
01636                   trackIsFromPrimaryVertex = true;
01637                   break;
01638                 }
01639               }
01640               
01641               if(Algo < 9 && nexhits == 0 && trackIsFromPrimaryVertex) {
01642                 localactive[ecalKf_index] = false;
01643               } else {
01644                 fifthStepKfTrack_.push_back(make_pair(ecalKf_index,trackIs[iEle]));
01645               }
01646             }
01647           }
01648         }
01649       } // gsfElems.size()
01650     } // loop on kf tracks
01651     
01652 
01653     // start loop on gsf tracks
01654     for(unsigned int iEle=0; iEle<gsfIs.size(); iEle++) {  
01655 
01656       if (!localactive[(gsfIs[iEle])]) continue;  
01657 
01658       localactive[gsfIs[iEle]] = false;
01659       bool ClosestEcalWithKf = false;
01660 
01661       if (DebugSetLinksDetailed) cout << " Gsf Index " << gsfIs[iEle] << endl;
01662 
01663       const reco::PFBlockElementGsfTrack * GsfEl  =  
01664         dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[(gsfIs[iEle])]));
01665 
01666       // if GsfTrack fron converted bremsstralung continue
01667       if(GsfEl->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)) continue;
01668       IsThereAGoodGSFTrack = true;
01669       float eta_gsf = GsfEl->positionAtECALEntrance().eta();
01670       float etaOut_gsf = GsfEl->Pout().eta();
01671       float diffOutEcalEta =  fabs(eta_gsf-etaOut_gsf);
01672       reco::GsfTrackRef RefGSF = GsfEl->GsftrackRef();
01673       float Pin_gsf   = 0.01;
01674       if (RefGSF.isNonnull() ) 
01675         Pin_gsf = RefGSF->pMode();
01676       
01677 
01678       // Find Associated Kf Track elements and Ecal to KF elements
01679       unsigned int KfGsf_index = CutIndex;
01680       unsigned int KfGsf_secondIndex = CutIndex; 
01681       std::multimap<double, unsigned int> kfElems;
01682       block.associatedElements( gsfIs[iEle],linkData,
01683                                 kfElems,
01684                                 reco::PFBlockElement::TRACK,
01685                                 reco::PFBlock::LINKTEST_ALL );
01686       std::multimap<double, unsigned int> ecalKfElems;
01687       if (kfElems.size() > 0) {
01688         // 19 Mar 2010 now a loop is needed because > 1 KF track could
01689         // be associated to the same GSF track
01690 
01691         for(std::multimap<double, unsigned int>::iterator itkf = kfElems.begin();
01692             itkf != kfElems.end(); ++itkf) {
01693           const reco::PFBlockElementTrack * TrkEl  =  
01694             dynamic_cast<const reco::PFBlockElementTrack*>((&elements[itkf->second]));
01695           
01696           bool isPrim = isPrimaryTrack(*TrkEl,*GsfEl);
01697           if(!isPrim) 
01698             continue;
01699           
01700           if(localactive[itkf->second] == true) {
01701 
01702             KfGsf_index = itkf->second;
01703             localactive[KfGsf_index] = false;
01704             // Find clusters associated to kftrack using linkbyrechit
01705             block.associatedElements( KfGsf_index,  linkData,
01706                                       ecalKfElems ,
01707                                       reco::PFBlockElement::ECAL,
01708                                       reco::PFBlock::LINKTEST_ALL );  
01709           }
01710           else {          
01711             KfGsf_secondIndex = itkf->second;
01712           }
01713         }
01714       }
01715       
01716       // Find the closest Ecal clusters associated to this Gsf
01717       std::multimap<double, unsigned int> ecalGsfElems;
01718       block.associatedElements( gsfIs[iEle],linkData,
01719                                 ecalGsfElems,
01720                                 reco::PFBlockElement::ECAL,
01721                                 reco::PFBlock::LINKTEST_ALL );    
01722       double ecalGsf_dist = CutGSFECAL;
01723       unsigned int ClosestEcalGsf_index = CutIndex;
01724       if (ecalGsfElems.size() > 0) {    
01725         if(localactive[(ecalGsfElems.begin()->second)] == true) {
01726           // check energy compatibility for outer eta != ecal entrance, looping tracks
01727           bool compatibleEPout = true;
01728           if(diffOutEcalEta > 0.3) {
01729             reco::PFClusterRef clusterRef = elements[(ecalGsfElems.begin()->second)].clusterRef();      
01730             float EoPout = (clusterRef->energy())/(GsfEl->Pout().t());
01731             if(EoPout > 5) 
01732               compatibleEPout = false;
01733           }
01734           if(compatibleEPout) {
01735             ClosestEcalGsf_index = ecalGsfElems.begin()->second;
01736             ecalGsf_dist = block.dist(gsfIs[iEle],ClosestEcalGsf_index,
01737                                       linkData,reco::PFBlock::LINKTEST_ALL);
01738             
01739             // Check that this cluster is not closer to another primary Gsf track
01740             
01741             std::multimap<double, unsigned int> ecalOtherGsfElems;
01742             block.associatedElements( ClosestEcalGsf_index,linkData,
01743                                       ecalOtherGsfElems,
01744                                       reco::PFBlockElement::GSF,
01745                                       reco::PFBlock::LINKTEST_ALL);
01746             
01747             if(ecalOtherGsfElems.size()>0) {
01748               // get if it is closed to a conv brem gsf tracks
01749               const reco::PFBlockElementGsfTrack * gsfCheck  =  
01750                 dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[ecalOtherGsfElems.begin()->second]));
01751               
01752               if(ecalOtherGsfElems.begin()->second != gsfIs[iEle]&&
01753                  gsfCheck->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) == false) {             
01754                 ecalGsf_dist = CutGSFECAL;
01755                 ClosestEcalGsf_index = CutIndex;
01756               }
01757             }
01758           }
01759           // do not lock at the moment we need this for the late brem
01760         }
01761       }
01762       // if any cluster is found with the gsf-ecal link, try with kf-ecal
01763       else if(ecalKfElems.size() > 0) {
01764         if(localactive[(ecalKfElems.begin()->second)] == true) {
01765           ClosestEcalGsf_index = ecalKfElems.begin()->second;     
01766           ecalGsf_dist = block.dist(gsfIs[iEle],ClosestEcalGsf_index,
01767                                     linkData,reco::PFBlock::LINKTEST_ALL);
01768           ClosestEcalWithKf = true;
01769           
01770           // Check if this cluster is not closer to another Gsf track
01771           std::multimap<double, unsigned int> ecalOtherGsfElems;
01772           block.associatedElements( ClosestEcalGsf_index,linkData,
01773                                     ecalOtherGsfElems,
01774                                     reco::PFBlockElement::GSF,
01775                                     reco::PFBlock::LINKTEST_ALL);
01776           if(ecalOtherGsfElems.size() > 0) {
01777             const reco::PFBlockElementGsfTrack * gsfCheck  =  
01778               dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[ecalOtherGsfElems.begin()->second]));
01779 
01780             if(ecalOtherGsfElems.begin()->second != gsfIs[iEle] &&
01781                gsfCheck->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) == false) {
01782               ecalGsf_dist = CutGSFECAL;
01783               ClosestEcalGsf_index = CutIndex;
01784               ClosestEcalWithKf = false;
01785             }
01786           }
01787         }
01788       }
01789 
01790       if (DebugSetLinksDetailed) 
01791         cout << " Closest Ecal to the Gsf/Kf: index " << ClosestEcalGsf_index 
01792              << " dist " << ecalGsf_dist << endl;
01793       
01794       
01795       
01796       //  Find the brems associated to this Gsf
01797       std::multimap<double, unsigned int> bremElems;
01798       block.associatedElements( gsfIs[iEle],linkData,
01799                                 bremElems,
01800                                 reco::PFBlockElement::BREM,
01801                                 reco::PFBlock::LINKTEST_ALL );
01802       
01803       
01804       multimap<unsigned int,unsigned int> cleanedEcalBremElems;
01805       vector<unsigned int> keyBremIndex(0);
01806       unsigned int latestBrem_trajP = 0;     
01807       unsigned int latestBrem_index = CutIndex;
01808       for(std::multimap<double, unsigned int>::iterator ieb = bremElems.begin(); 
01809           ieb != bremElems.end(); ++ieb ) {
01810         unsigned int brem_index = ieb->second;
01811         if(localactive[brem_index] == false) continue;
01812 
01813 
01814         // Find the ecal clusters associated to the brems
01815         std::multimap<double, unsigned int> ecalBremsElems;
01816 
01817         block.associatedElements( brem_index,  linkData,
01818                                   ecalBremsElems,
01819                                   reco::PFBlockElement::ECAL,
01820                                   reco::PFBlock::LINKTEST_ALL );
01821 
01822         for (std::multimap<double, unsigned int>::iterator ie = ecalBremsElems.begin();
01823              ie != ecalBremsElems.end();ie++) {
01824           unsigned int ecalBrem_index = ie->second;
01825           if(localactive[ecalBrem_index] == false) continue;
01826 
01827           //to be changed, using the distance
01828           float ecalBrem_dist = block.dist(brem_index,ecalBrem_index,
01829                                            linkData,reco::PFBlock::LINKTEST_ALL); 
01830           
01831           
01832           if (ecalBrem_index == ClosestEcalGsf_index && (ecalBrem_dist + 0.0012) > ecalGsf_dist) continue;
01833 
01834           // Find the closest brem
01835           std::multimap<double, unsigned int> sortedBremElems;
01836           block.associatedElements( ecalBrem_index,linkData,
01837                                     sortedBremElems,
01838                                     reco::PFBlockElement::BREM,
01839                                     reco::PFBlock::LINKTEST_ALL);
01840           // check that this brem is that one coming from the same *primary* gsf
01841           bool isGoodBrem = false;
01842           unsigned int sortedBrem_index =  CutIndex;
01843           for (std::multimap<double, unsigned int>::iterator ibs = sortedBremElems.begin();
01844                ibs != sortedBremElems.end();ibs++) {
01845             unsigned int temp_sortedBrem_index = ibs->second;
01846             std::multimap<double, unsigned int> sortedGsfElems;
01847             block.associatedElements( temp_sortedBrem_index,linkData,
01848                                       sortedGsfElems,
01849                                       reco::PFBlockElement::GSF,
01850                                       reco::PFBlock::LINKTEST_ALL);
01851             bool enteredInPrimaryGsf = false;
01852             for (std::multimap<double, unsigned int>::iterator igs = sortedGsfElems.begin();
01853                  igs != sortedGsfElems.end();igs++) {
01854               const reco::PFBlockElementGsfTrack * gsfCheck  =  
01855                 dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[igs->second]));
01856 
01857               if(gsfCheck->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) == false) {
01858                 if(igs->second ==  gsfIs[iEle]) {
01859                   isGoodBrem = true;
01860                   sortedBrem_index = temp_sortedBrem_index;
01861                 }
01862                 enteredInPrimaryGsf = true;
01863                 break;
01864               }
01865             }
01866             if(enteredInPrimaryGsf)
01867               break;
01868           }
01869 
01870           if(isGoodBrem) { 
01871 
01872             //  Check that this cluster is not closer to another Gsf Track
01873             // The check is not performed on KF track because the ecal clusters are aready locked.
01874             std::multimap<double, unsigned int> ecalOtherGsfElems;
01875             block.associatedElements( ecalBrem_index,linkData,
01876                                       ecalOtherGsfElems,
01877                                       reco::PFBlockElement::GSF,
01878                                       reco::PFBlock::LINKTEST_ALL);
01879             if (ecalOtherGsfElems.size() > 0) {
01880               const reco::PFBlockElementGsfTrack * gsfCheck  =  
01881                 dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[ecalOtherGsfElems.begin()->second]));
01882               if(ecalOtherGsfElems.begin()->second != gsfIs[iEle] &&
01883                  gsfCheck->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) == false) {
01884                 continue;
01885               }
01886             }
01887 
01888             const reco::PFBlockElementBrem * BremEl  =  
01889               dynamic_cast<const reco::PFBlockElementBrem*>((&elements[sortedBrem_index]));
01890 
01891             reco::PFClusterRef clusterRef = 
01892               elements[ecalBrem_index].clusterRef();
01893             
01894 
01895             float sortedBremEcal_deta = fabs(clusterRef->position().eta() - BremEl->positionAtECALEntrance().eta());
01896             // Triangular cut on plan chi2:deta -> OLD
01897             //if((0.0075*sortedBremEcal_chi2 + 100.*sortedBremEcal_deta -1.5) < 0.) {
01898             if(sortedBremEcal_deta < 0.015) {
01899             
01900               cleanedEcalBremElems.insert(pair<unsigned int,unsigned int>(sortedBrem_index,ecalBrem_index));
01901               
01902               unsigned int BremTrajP = BremEl->indTrajPoint();
01903               if (BremTrajP > latestBrem_trajP) {
01904                 latestBrem_trajP = BremTrajP;
01905                 latestBrem_index = sortedBrem_index;
01906               }
01907               if (DebugSetLinksDetailed)
01908                 cout << " brem Index " <<  sortedBrem_index 
01909                      << " associated cluster " << ecalBrem_index << " BremTrajP " << BremTrajP <<endl;
01910               
01911               // > 1 ecal clusters could be associated to the same brem twice: allowed N-1 link. 
01912               // But the brem need to be stored once. 
01913               // locallock the brem and the ecal clusters
01914               localactive[ecalBrem_index] = false;  // the cluster
01915               bool  alreadyfound = false;
01916               for(unsigned int ii=0;ii<keyBremIndex.size();ii++) {
01917                 if (sortedBrem_index == keyBremIndex[ii]) alreadyfound = true;
01918               }
01919               if (alreadyfound == false) {
01920                 keyBremIndex.push_back(sortedBrem_index);
01921                 localactive[sortedBrem_index] = false;   // the brem
01922               }
01923             }
01924           }
01925         }
01926       }
01927 
01928       
01929       // Find Possible Extra Cluster associated to the gsf/kf
01930       vector<unsigned int> GsfElemIndex(0);
01931       vector<unsigned int> EcalIndex(0);
01932 
01933       // locallock the ecal cluster associated to the gsf
01934       if (ClosestEcalGsf_index < CutIndex) {
01935         GsfElemIndex.push_back(ClosestEcalGsf_index);
01936         localactive[ClosestEcalGsf_index] = false;
01937         for (std::multimap<double, unsigned int>::iterator ii = ecalGsfElems.begin();
01938              ii != ecalGsfElems.end();ii++) {   
01939           if(localactive[ii->second]) {
01940             // Check that this cluster is not closer to another Gsf Track
01941             std::multimap<double, unsigned int> ecalOtherGsfElems;
01942             block.associatedElements( ii->second,linkData,
01943                                       ecalOtherGsfElems,
01944                                       reco::PFBlockElement::GSF,
01945                                       reco::PFBlock::LINKTEST_ALL);
01946             if(ecalOtherGsfElems.size()) {
01947               if(ecalOtherGsfElems.begin()->second != gsfIs[iEle]) continue;
01948             } 
01949             
01950             // get the cluster only if the deta (ecal-gsf) < 0.05
01951             reco::PFClusterRef clusterRef = elements[(ii->second)].clusterRef();
01952             float etacl =  clusterRef->eta();
01953             if( fabs(eta_gsf-etacl) < 0.05) {       
01954               GsfElemIndex.push_back(ii->second);
01955               localactive[ii->second] = false;
01956               if (DebugSetLinksDetailed)
01957                 cout << " ExtraCluster From Gsf " << ii->second << endl;
01958             }
01959           }
01960         }
01961       }
01962 
01963       //Add the possibility to link other ecal clusters from kf. 
01964      
01965 //       for (std::multimap<double, unsigned int>::iterator ii = ecalKfElems.begin();
01966 //         ii != ecalKfElems.end();ii++) {
01967 //      if(localactive[ii->second]) {
01968 //         // Check that this cluster is not closer to another Gsf Track    
01969 //        std::multimap<double, unsigned int> ecalOtherGsfElems;
01970 //        block.associatedElements( ii->second,linkData,
01971 //                                  ecalOtherGsfElems,
01972 //                                  reco::PFBlockElement::GSF,
01973 //                                  reco::PFBlock::LINKTEST_CHI2);
01974 //        if(ecalOtherGsfElems.size()) {
01975 //          if(ecalOtherGsfElems.begin()->second != gsfIs[iEle]) continue;
01976 //        } 
01977 //        GsfElemIndex.push_back(ii->second);
01978 //        reco::PFClusterRef clusterRef = elements[(ii->second)].clusterRef();
01979 //        float etacl =  clusterRef->eta();
01980 //        if( fabs(eta_gsf-etacl) < 0.05) {         
01981 //          localactive[ii->second] = false;
01982 //          if (DebugSetLinksDetailed)
01983 //            cout << " ExtraCluster From KF " << ii->second << endl;
01984 //        }
01985 //      }
01986 //       }
01987       
01988       //****************** Fill Maps *************************
01989 
01990       // The GsfMap    
01991 
01992       // if any clusters have been associated to the gsf track    
01993       // use the Ecal clusters associated to the latest brem and associate it to the gsf
01994        if(GsfElemIndex.size() == 0){
01995         if(latestBrem_index < CutIndex) {
01996           unsigned int ckey = cleanedEcalBremElems.count(latestBrem_index);
01997           if(ckey == 1) {
01998             unsigned int temp_cal = 
01999               cleanedEcalBremElems.find(latestBrem_index)->second;
02000             GsfElemIndex.push_back(temp_cal);
02001             if (DebugSetLinksDetailed)
02002               cout << "******************** Gsf Cluster From Brem " << temp_cal 
02003                    << " Latest Brem index " << latestBrem_index 
02004                    << " ************************* " << endl;
02005           }
02006           else{
02007             pair<multimap<unsigned int,unsigned int>::iterator,multimap<unsigned int,unsigned int>::iterator> ret;
02008             ret = cleanedEcalBremElems.equal_range(latestBrem_index);
02009             multimap<unsigned int,unsigned int>::iterator it;
02010             for(it=ret.first; it!=ret.second; ++it) {
02011               GsfElemIndex.push_back((*it).second);
02012               if (DebugSetLinksDetailed)
02013                 cout << "******************** Gsf Cluster From Brem " << (*it).second 
02014                      << " Latest Brem index " << latestBrem_index 
02015                      << " ************************* " << endl;
02016             }
02017           }
02018           // erase the brem. 
02019           unsigned int elToErase = 0;
02020           for(unsigned int i = 0; i<keyBremIndex.size();i++) {
02021             if(latestBrem_index == keyBremIndex[i]) {
02022               elToErase = i;
02023             }
02024           }
02025           keyBremIndex.erase(keyBremIndex.begin()+elToErase);
02026         }       
02027       }
02028 
02029       // Get Extra Clusters from converted brem gsf tracks. The locallock method
02030       // tells me if the ecal cluster has been already assigned to the primary
02031       // gsf track or to a brem
02032 
02033       for(unsigned int iConv=0; iConv<gsfIs.size(); iConv++) {  
02034         if(iConv != iEle) {
02035 
02036           const reco::PFBlockElementGsfTrack * gsfConv  =  
02037             dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[(gsfIs[iConv])]));
02038           
02039           // look at only to secondary gsf tracks
02040           if(gsfConv->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)){
02041             if (DebugSetLinksDetailed)
02042               cout << "  PFElectronAlgo:: I'm running on convGsfBrem " << endl;
02043             // check if they are linked to the primary
02044             float conv_dist = block.dist(gsfIs[iConv],gsfIs[iEle],
02045                                          linkData,reco::PFBlock::LINKTEST_ALL);
02046             if(conv_dist > 0.) {
02047               // find the closest ecal cluster associated to conversions
02048 
02049               std::multimap<double, unsigned int> ecalConvElems;
02050               block.associatedElements( gsfIs[iConv],linkData,
02051                                         ecalConvElems,
02052                                         reco::PFBlockElement::ECAL,
02053                                         reco::PFBlock::LINKTEST_ALL );    
02054               if(ecalConvElems.size() > 0) {
02055                 // the ecal cluster is still active?
02056                 if(localactive[(ecalConvElems.begin()->second)] == true) {
02057                   if (DebugSetLinksDetailed)
02058                     cout << "  PFElectronAlgo:: convGsfBrem has a ECAL cluster linked and free" << endl;
02059                   // Check that this cluster is not closer to another primary Gsf track
02060                   std::multimap<double, unsigned int> ecalOtherGsfPrimElems;
02061                   block.associatedElements( ecalConvElems.begin()->second,linkData,
02062                                             ecalOtherGsfPrimElems,
02063                                             reco::PFBlockElement::GSF,
02064                                             reco::PFBlock::LINKTEST_ALL);
02065                   if(ecalOtherGsfPrimElems.size()>0) {
02066                     unsigned int gsfprimcheck_index = ecalOtherGsfPrimElems.begin()->second;
02067                     const reco::PFBlockElementGsfTrack * gsfCheck  =  
02068                       dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[gsfprimcheck_index]));
02069                     if(gsfCheck->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) == false) continue;
02070                     
02071                     reco::PFClusterRef clusterRef = elements[ecalConvElems.begin()->second].clusterRef();
02072                     if (DebugSetLinksDetailed)
02073                       cout << " PFElectronAlgo: !!!!!!! convGsfBrem ECAL cluster has been stored !!!!!!! "
02074                            << " Energy " << clusterRef->energy() << " eta,phi "  << clusterRef->position().eta()
02075                            <<", " <<  clusterRef->position().phi() << endl;
02076                  
02077                     GsfElemIndex.push_back(ecalConvElems.begin()->second);
02078                     convGsfTrack_.push_back(make_pair(ecalConvElems.begin()->second,gsfIs[iConv]));
02079                     localactive[ecalConvElems.begin()->second] = false;
02080                     
02081                   }
02082                 }
02083               }
02084             }
02085           }
02086         }
02087       }
02088 
02089 
02090       
02091       EcalIndex.insert(EcalIndex.end(),GsfElemIndex.begin(),GsfElemIndex.end());
02092       
02093       
02094 
02095       // The BremMap
02096       for(unsigned int i =0;i<keyBremIndex.size();i++) {
02097         unsigned int ikey = keyBremIndex[i];
02098         unsigned int ckey = cleanedEcalBremElems.count(ikey);
02099         vector<unsigned int> BremElemIndex(0);
02100         if(ckey == 1) {
02101           unsigned int temp_cal = 
02102             cleanedEcalBremElems.find(ikey)->second;
02103           BremElemIndex.push_back(temp_cal);
02104         }
02105         else{
02106           pair<multimap<unsigned int,unsigned int>::iterator,multimap<unsigned int,unsigned int>::iterator> ret;
02107           ret = cleanedEcalBremElems.equal_range(ikey);
02108           multimap<unsigned int,unsigned int>::iterator it;
02109           for(it=ret.first; it!=ret.second; ++it) {
02110             BremElemIndex.push_back((*it).second);
02111           }
02112         }
02113         EcalIndex.insert(EcalIndex.end(),BremElemIndex.begin(),BremElemIndex.end());
02114         associatedToBrems_.insert(pair<unsigned int,vector<unsigned int> >(ikey,BremElemIndex));
02115       }
02116 
02117       
02118       // 19 Mar 2010: add KF and ECAL elements from converted brem photons
02119       vector<unsigned int> convBremKFTrack;
02120       convBremKFTrack.clear();
02121       if (kfElems.size() > 0) {
02122         for(std::multimap<double, unsigned int>::iterator itkf = kfElems.begin();
02123             itkf != kfElems.end(); ++itkf) {
02124           const reco::PFBlockElementTrack * TrkEl  =  
02125             dynamic_cast<const reco::PFBlockElementTrack*>((&elements[itkf->second]));
02126           bool isPrim = isPrimaryTrack(*TrkEl,*GsfEl);
02127 
02128           if(!isPrim) {
02129 
02130             // search for linked ECAL clusters
02131             std::multimap<double, unsigned int> ecalConvElems;
02132             block.associatedElements( itkf->second,linkData,
02133                                       ecalConvElems,
02134                                       reco::PFBlockElement::ECAL,
02135                                       reco::PFBlock::LINKTEST_ALL );
02136             if(ecalConvElems.size() > 0) {
02137               // Further Cleaning: DANIELE This could be improved!
02138               TrackRef trkRef =   TrkEl->trackRef();
02139               // iter0, iter1, iter2, iter3 = Algo < 3
02140               unsigned int Algo = whichTrackAlgo(trkRef);
02141 
02142               float secpin = trkRef->p();       
02143               
02144               const reco::PFBlockElementCluster * clust =  
02145                 dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(ecalConvElems.begin()->second)])); 
02146               float eneclust  =clust->clusterRef()->energy();
02147 
02148               //1)  ******* Reject secondary KF tracks linked to also an HCAL cluster with H/(E+H) > 0.1
02149               //            This is applied also to KF linked to locked ECAL cluster
02150               //            NOTE: trusting the H/(E+H) and not the conv brem selection increse the number
02151               //                  of charged hadrons around the electron. DANIELE? re-think about this. 
02152               std::multimap<double, unsigned int> hcalConvElems;
02153               block.associatedElements( itkf->second,linkData,
02154                                         hcalConvElems,
02155                                         reco::PFBlockElement::HCAL,
02156                                         reco::PFBlock::LINKTEST_ALL );
02157 
02158               bool isHoHE = false;
02159               bool isHoE = false;
02160               bool isPoHE = false;
02161 
02162               float enehcalclust = -1;
02163               if(hcalConvElems.size() > 0) {
02164                 const reco::PFBlockElementCluster * clusthcal =  
02165                   dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(hcalConvElems.begin()->second)])); 
02166                 enehcalclust  =clusthcal->clusterRef()->energy();
02167                 // NOTE: DANIELE? Are you sure you want to use the Algo type here? 
02168                 if( (enehcalclust / (enehcalclust+eneclust) ) > 0.1 && Algo < 3) {
02169                   isHoHE = true;
02170                   if(enehcalclust > eneclust) 
02171                     isHoE = true;
02172                   if(secpin > (enehcalclust+eneclust) )
02173                     isPoHE = true;
02174                 }
02175               }
02176               
02177 
02178               if(localactive[(ecalConvElems.begin()->second)] == false) {
02179                 
02180                 if(isHoE || isPoHE) {
02181                   if (DebugSetLinksDetailed)
02182                     cout << "PFElectronAlgo:: LOCKED ECAL REJECTED TRACK FOR H/E or P/(H+E) "
02183                          << " H/H+E " << enehcalclust/(enehcalclust+eneclust)                 
02184                          << " H/E " <<  enehcalclust/eneclust
02185                          << " P/(H+E) " << secpin/(enehcalclust+eneclust) 
02186                          << " HCAL ENE " << enehcalclust 
02187                          << " ECAL ENE " << eneclust 
02188                          << " secPIN " << secpin 
02189                          << " Algo Track " << Algo << endl;
02190                   continue;
02191                 }
02192 
02193                 // check if this track has been alread assigned to an ECAL cluster
02194                 for(unsigned int iecal =0; iecal < EcalIndex.size(); iecal++) {
02195                   // in case this track is already assigned to a locked ECAL cluster
02196                   // the secondary kf track is also saved for further lock
02197                   if(EcalIndex[iecal] == ecalConvElems.begin()->second) {
02198                     if (DebugSetLinksDetailed)
02199                       cout << " PFElectronAlgo:: Conv Brem Recovery locked cluster and I will lock also the KF track " << endl; 
02200                     convBremKFTrack.push_back(itkf->second);
02201                   }
02202                 }
02203               }       
02204               else{
02205                 // ECAL cluster free
02206                 
02207                 // 
02208                 if(isHoHE){
02209                   if (DebugSetLinksDetailed)
02210                     cout << "PFElectronAlgo:: FREE ECAL REJECTED TRACK FOR H/H+E " 
02211                          << " H/H+E " <<  (enehcalclust / (enehcalclust+eneclust) ) 
02212                          << " H/E " <<  enehcalclust/eneclust
02213                          << " P/(H+E) " << secpin/(enehcalclust+eneclust) 
02214                          << " HCAL ENE " << enehcalclust 
02215                          << " ECAL ENE " << eneclust 
02216                          << " secPIN " << secpin 
02217                          << " Algo Track " << Algo << endl;
02218                   continue;
02219                 }
02220 
02221                 // check that this cluster is not cluser to another KF track (primary)
02222                 std::multimap<double, unsigned int> ecalOtherKFPrimElems;
02223                 block.associatedElements( ecalConvElems.begin()->second,linkData,
02224                                           ecalOtherKFPrimElems,
02225                                           reco::PFBlockElement::TRACK,
02226                                           reco::PFBlock::LINKTEST_ALL);
02227                 if(ecalOtherKFPrimElems.size() > 0) {
02228                   
02229                   // check that this ECAL clusters is the best associated to at least one of the  KF tracks
02230                   // linked to the considered GSF track
02231                   bool isFromGSF = false;
02232                   for(std::multimap<double, unsigned int>::iterator itclos = kfElems.begin();
02233                       itclos != kfElems.end(); ++itclos) {
02234                     if(ecalOtherKFPrimElems.begin()->second == itclos->second) {
02235                       isFromGSF = true;
02236                       break;
02237                     }
02238                   }
02239                   if(isFromGSF){
02240 
02241                     // Further Cleaning: DANIELE This could be improved!                                    
02242                   
02243                                           
02244                     float Epin = eneclust/secpin;
02245                     
02246                     // compute the pfsupercluster energy till now
02247                     float totenergy = 0.;
02248                     for(unsigned int ikeyecal = 0; 
02249                         ikeyecal<EcalIndex.size(); ikeyecal++){
02250                       // EcalIndex can have the same cluster save twice (because of the late brem cluster).
02251                       bool foundcluster = false;
02252                       if(ikeyecal > 0) {
02253                         for(unsigned int i2 = 0; i2<ikeyecal-1; i2++) {
02254                           if(EcalIndex[ikeyecal] == EcalIndex[i2]) 
02255                             foundcluster = true;
02256                         }
02257                       }
02258                       if(foundcluster) continue;
02259                       const reco::PFBlockElementCluster * clusasso =  
02260                         dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(EcalIndex[ikeyecal])])); 
02261                       totenergy += clusasso->clusterRef()->energy();
02262                     }
02263                     
02264                     // Further Cleaning: DANIELE This could be improved! 
02265                     //2) *****  Do not consider secondary tracks if the GSF and brems have failed in finding ECAL clusters
02266                     if(totenergy == 0.) {
02267                       if (DebugSetLinksDetailed)
02268                         cout << "PFElectronAlgo:: REJECTED_NULLTOT totenergy " << totenergy << endl;
02269                       continue;
02270                     }
02271                     
02272                     //3) ****** Reject secondary KF tracks that have an high E/secPin and that make worse the Etot/pin 
02273                     if(Epin > 3) {
02274                       double res_before = fabs((totenergy-Pin_gsf)/Pin_gsf);
02275                       double res_after = fabs(((totenergy+eneclust)-Pin_gsf)/Pin_gsf);
02276                       
02277                       if(res_before < res_after) {
02278                         if (DebugSetLinksDetailed)
02279                           cout << "PFElectronAlgo::REJECTED_RES totenergy " << totenergy << " Pin_gsf " << Pin_gsf << " cluster to secondary " <<  eneclust 
02280                                << " Res before " <<  res_before << " res_after " << res_after << endl;
02281                         continue;
02282                       }
02283                     }
02284                     
02285                     if (DebugSetLinksDetailed)
02286                       cout << "PFElectronAlgo:: conv brem found asso to ECAL linked to a secondary KF " << endl;
02287                     convBremKFTrack.push_back(itkf->second);
02288                     GsfElemIndex.push_back(ecalConvElems.begin()->second);
02289                     EcalIndex.push_back(ecalConvElems.begin()->second);
02290                     localactive[(ecalConvElems.begin()->second)] = false;
02291                     localactive[(itkf->second)] = false;
02292                   }
02293                 }
02294               }
02295             }
02296           }
02297         }
02298       }
02299  
02300       // 4May import EG supercluster
02301       if(EcalIndex.size() > 0 && useEGammaSupercluster_) {
02302         double sumEtEcalInTheCone  = 0.;
02303         
02304         // Position of the first cluster
02305         const reco::PFBlockElementCluster * clust =  
02306           dynamic_cast<const reco::PFBlockElementCluster*>((&elements[EcalIndex[0]])); 
02307         double PhiFC  = clust->clusterRef()->position().Phi();
02308         double EtaFC =  clust->clusterRef()->position().Eta();
02309 
02310         // Compute ECAL isolation ->
02311         for(unsigned int iEcal=0; iEcal<ecalIs.size(); iEcal++) {
02312           bool foundcluster = false;
02313           for(unsigned int ikeyecal = 0; 
02314               ikeyecal<EcalIndex.size(); ikeyecal++){
02315             if(ecalIs[iEcal] == EcalIndex[ikeyecal])
02316               foundcluster = true;
02317           }
02318           
02319           // -> only for clusters not already in the PFSCCluster
02320           if(foundcluster == false) {
02321             const reco::PFBlockElementCluster * clustExt =  
02322               dynamic_cast<const reco::PFBlockElementCluster*>((&elements[ecalIs[iEcal]])); 
02323             double eta_clust =  clustExt->clusterRef()->position().Eta();
02324             double phi_clust =  clustExt->clusterRef()->position().Phi();
02325             double theta_clust =  clustExt->clusterRef()->position().Theta();
02326             double deta_clust = eta_clust - EtaFC;
02327             double dphi_clust = phi_clust - PhiFC;
02328             if ( dphi_clust < -M_PI ) 
02329               dphi_clust = dphi_clust + 2.*M_PI;
02330             else if ( dphi_clust > M_PI ) 
02331               dphi_clust = dphi_clust - 2.*M_PI;
02332             double  DR = sqrt(deta_clust*deta_clust+
02333                               dphi_clust*dphi_clust);             
02334             
02335             //Jurassic veto in deta
02336             if(fabs(deta_clust) > 0.05 && DR < coneEcalIsoForEgammaSC_) {
02337               vector<double> ps1Ene(0);
02338               vector<double> ps2Ene(0);
02339               double ps1,ps2;
02340               ps1=ps2=0.;
02341               double EE_calib = thePFEnergyCalibration_->energyEm(*(clustExt->clusterRef()),ps1Ene,ps2Ene,ps1,ps2,applyCrackCorrections_);
02342               double ET_calib = EE_calib*sin(theta_clust);
02343               sumEtEcalInTheCone += ET_calib;
02344             }
02345           }
02346         } //EndLoop Additional ECAL clusters in the block
02347         
02348         // Compute track isolation: number of tracks && sumPt
02349         unsigned int sumNTracksInTheCone = 0;
02350         double sumPtTracksInTheCone = 0.;
02351         for(unsigned int iTrack=0; iTrack<trackIs.size(); iTrack++) {
02352           // the track from the electron are already locked at this stage
02353           if(localactive[(trackIs[iTrack])]==true) {
02354             const reco::PFBlockElementTrack * kfEle =  
02355               dynamic_cast<const reco::PFBlockElementTrack*>((&elements[(trackIs[iTrack])]));   
02356             reco::TrackRef trkref = kfEle->trackRef();
02357             if (trkref.isNonnull()) {
02358               double deta_trk =  trkref->eta() - RefGSF->etaMode();
02359               double dphi_trk =  trkref->phi() - RefGSF->phiMode();
02360               if ( dphi_trk < -M_PI ) 
02361                 dphi_trk = dphi_trk + 2.*M_PI;
02362               else if ( dphi_trk > M_PI ) 
02363                 dphi_trk = dphi_trk - 2.*M_PI;
02364               double  DR = sqrt(deta_trk*deta_trk+
02365                                 dphi_trk*dphi_trk);
02366               
02367               reco::HitPattern kfHitPattern = trkref->hitPattern();
02368               int NValPixelHit = kfHitPattern.numberOfValidPixelHits();
02369               
02370               if(DR < coneTrackIsoForEgammaSC_ && NValPixelHit >=3) {
02371                 sumNTracksInTheCone++;
02372                 sumPtTracksInTheCone+=trkref->pt();
02373               }
02374             }
02375           }
02376         }
02377 
02378         
02379         bool isBarrelIsolated = false;
02380         if( fabs(EtaFC < 1.478) && 
02381             (sumEtEcalInTheCone < sumEtEcalIsoForEgammaSC_barrel_ && 
02382              (sumNTracksInTheCone < nTrackIsoForEgammaSC_  || sumPtTracksInTheCone < sumPtTrackIsoForEgammaSC_barrel_)))
02383           isBarrelIsolated = true;
02384         
02385         
02386         bool isEndcapIsolated = false;
02387         if( fabs(EtaFC >= 1.478) && 
02388             (sumEtEcalInTheCone < sumEtEcalIsoForEgammaSC_endcap_ &&  
02389              (sumNTracksInTheCone < nTrackIsoForEgammaSC_  || sumPtTracksInTheCone < sumPtTrackIsoForEgammaSC_endcap_)))
02390           isEndcapIsolated = true;
02391         
02392 
02393         // only print out
02394         if(DebugSetLinksDetailed) {
02395           if(fabs(EtaFC < 1.478) && isBarrelIsolated == false) {
02396             cout << "**** PFElectronAlgo:: SUPERCLUSTER FOUND BUT FAILS ISOLATION:BARREL *** " 
02397                  << " sumEtEcalInTheCone " <<sumEtEcalInTheCone 
02398                  << " sumNTracksInTheCone " << sumNTracksInTheCone 
02399                  << " sumPtTracksInTheCone " << sumPtTracksInTheCone << endl;
02400           }
02401           if(fabs(EtaFC >= 1.478) && isEndcapIsolated == false) {
02402             cout << "**** PFElectronAlgo:: SUPERCLUSTER FOUND BUT FAILS ISOLATION:ENDCAP *** " 
02403                  << " sumEtEcalInTheCone " <<sumEtEcalInTheCone 
02404                  << " sumNTracksInTheCone " << sumNTracksInTheCone 
02405                  << " sumPtTracksInTheCone " << sumPtTracksInTheCone << endl;
02406           }
02407         }
02408 
02409 
02410 
02411         
02412         if(isBarrelIsolated || isEndcapIsolated ) {
02413           
02414           
02415           // Compute TotEnergy
02416           double totenergy = 0.;
02417           for(unsigned int ikeyecal = 0; 
02418               ikeyecal<EcalIndex.size(); ikeyecal++){
02419             // EcalIndex can have the same cluster save twice (because of the late brem cluster).
02420             bool foundcluster = false;
02421             if(ikeyecal > 0) {
02422               for(unsigned int i2 = 0; i2<ikeyecal-1; i2++) {
02423                 if(EcalIndex[ikeyecal] == EcalIndex[i2]) 
02424                   foundcluster = true;;
02425               }
02426             }
02427             if(foundcluster) continue;
02428             const reco::PFBlockElementCluster * clusasso =  
02429               dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(EcalIndex[ikeyecal])])); 
02430             totenergy += clusasso->clusterRef()->energy();
02431           }
02432           // End copute TotEnergy
02433 
02434 
02435           // Find extra cluster from e/g importing
02436           for(unsigned int ikeyecal = 0; 
02437               ikeyecal<EcalIndex.size(); ikeyecal++){
02438             // EcalIndex can have the same cluster save twice (because of the late brem cluster).
02439             bool foundcluster = false;
02440             if(ikeyecal > 0) {
02441               for(unsigned int i2 = 0; i2<ikeyecal-1; i2++) {
02442                 if(EcalIndex[ikeyecal] == EcalIndex[i2]) 
02443                   foundcluster = true;
02444               }
02445             }     
02446             if(foundcluster) continue;
02447             
02448             
02449             std::multimap<double, unsigned int> ecalFromSuperClusterElems;
02450             block.associatedElements( EcalIndex[ikeyecal],linkData,
02451                                       ecalFromSuperClusterElems,
02452                                       reco::PFBlockElement::ECAL,
02453                                       reco::PFBlock::LINKTEST_ALL);
02454             if(ecalFromSuperClusterElems.size() > 0) {
02455               for(std::multimap<double, unsigned int>::iterator itsc = ecalFromSuperClusterElems.begin();
02456                   itsc != ecalFromSuperClusterElems.end(); ++itsc) {
02457                 if(localactive[itsc->second] == false) {
02458                   continue;
02459                 }
02460                 
02461                 std::multimap<double, unsigned int> ecalOtherKFPrimElems;
02462                 block.associatedElements( itsc->second,linkData,
02463                                           ecalOtherKFPrimElems,
02464                                           reco::PFBlockElement::TRACK,
02465                                           reco::PFBlock::LINKTEST_ALL);
02466                 if(ecalOtherKFPrimElems.size() > 0) {
02467                   if(localactive[ecalOtherKFPrimElems.begin()->second] == true) {
02468                     if (DebugSetLinksDetailed)
02469                       cout << "**** PFElectronAlgo:: SUPERCLUSTER FOUND BUT FAILS KF VETO *** " << endl;
02470                     continue;
02471                   }
02472                 }
02473                 bool isInTheEtaRange = false;
02474                 const reco::PFBlockElementCluster * clustToAdd =  
02475                   dynamic_cast<const reco::PFBlockElementCluster*>((&elements[itsc->second])); 
02476                 double deta_clustToAdd = clustToAdd->clusterRef()->position().Eta() - EtaFC;
02477                 double ene_clustToAdd = clustToAdd->clusterRef()->energy();
02478                 
02479                 if(fabs(deta_clustToAdd) < 0.05)
02480                   isInTheEtaRange = true;
02481                 
02482                 // check for both KF and GSF
02483                 bool isBetterEpin = false;
02484                 if(isInTheEtaRange == false ) {
02485                   if (DebugSetLinksDetailed)
02486                     cout << "**** PFElectronAlgo:: SUPERCLUSTER FOUND BUT FAILS GAMMA DETA RANGE  *** " 
02487                          << fabs(deta_clustToAdd) << endl;
02488                   
02489                   if(KfGsf_index < CutIndex) {              
02490                     //GSF
02491                     double res_before_gsf = fabs((totenergy-Pin_gsf)/Pin_gsf);
02492                     double res_after_gsf = fabs(((totenergy+ene_clustToAdd)-Pin_gsf)/Pin_gsf);
02493 
02494                     //KF
02495                     const reco::PFBlockElementTrack * trackEl =  
02496                       dynamic_cast<const reco::PFBlockElementTrack*>((&elements[KfGsf_index])); 
02497                     double Pin_kf = trackEl->trackRef()->p();
02498                     double res_before_kf = fabs((totenergy-Pin_kf)/Pin_kf);
02499                     double res_after_kf = fabs(((totenergy+ene_clustToAdd)-Pin_kf)/Pin_kf);                           
02500                     
02501                     // The new cluster improve both the E/pin?
02502                     if(res_after_gsf < res_before_gsf && res_after_kf < res_before_kf ) {
02503                       isBetterEpin = true;
02504                     }
02505                     else {
02506                       if (DebugSetLinksDetailed)
02507                         cout << "**** PFElectronAlgo:: SUPERCLUSTER FOUND AND FAILS ALSO RES_EPIN" 
02508                              << " tot energy " << totenergy 
02509                              << " Pin_gsf " << Pin_gsf 
02510                              << " Pin_kf " << Pin_kf 
02511                              << " cluster from SC to ADD " <<  ene_clustToAdd 
02512                              << " Res before GSF " <<  res_before_gsf << " res_after_gsf " << res_after_gsf 
02513                              << " Res before KF " <<  res_before_kf << " res_after_kf " << res_after_kf  << endl;
02514                     }
02515                   }
02516                 }
02517                 
02518                 if(isInTheEtaRange || isBetterEpin) {           
02519                   if (DebugSetLinksDetailed)
02520                     cout << "!!!! PFElectronAlgo:: ECAL from SUPERCLUSTER FOUND !!!!! " << endl;
02521                   GsfElemIndex.push_back(itsc->second);
02522                   EcalIndex.push_back(itsc->second);
02523                   localactive[(itsc->second)] = false;
02524                 }
02525               }
02526             }
02527           }
02528         } // END ISOLATION IF
02529       }
02530 
02531 
02532       if(KfGsf_index < CutIndex) 
02533         GsfElemIndex.push_back(KfGsf_index);
02534       else if(KfGsf_secondIndex < CutIndex) 
02535         GsfElemIndex.push_back(KfGsf_secondIndex);
02536       
02537       // insert the secondary KF tracks
02538       GsfElemIndex.insert(GsfElemIndex.end(),convBremKFTrack.begin(),convBremKFTrack.end());
02539       GsfElemIndex.insert(GsfElemIndex.end(),keyBremIndex.begin(),keyBremIndex.end());
02540       associatedToGsf_.insert(pair<unsigned int, vector<unsigned int> >(gsfIs[iEle],GsfElemIndex));
02541 
02542       // The EcalMap
02543       for(unsigned int ikeyecal = 0; 
02544           ikeyecal<EcalIndex.size(); ikeyecal++){
02545         
02546 
02547         vector<unsigned int> EcalElemsIndex(0);
02548 
02549         std::multimap<double, unsigned int> PS1Elems;
02550         block.associatedElements( EcalIndex[ikeyecal],linkData,
02551                                   PS1Elems,
02552                                   reco::PFBlockElement::PS1,
02553                                   reco::PFBlock::LINKTEST_ALL );
02554         for( std::multimap<double, unsigned int>::iterator it = PS1Elems.begin();
02555              it != PS1Elems.end();it++) {
02556           unsigned int index = it->second;
02557           if(localactive[index] == true) {
02558             
02559             // Check that this cluster is not closer to another ECAL cluster
02560             std::multimap<double, unsigned> sortedECAL;
02561             block.associatedElements( index,  linkData,
02562                                       sortedECAL,
02563                                       reco::PFBlockElement::ECAL,
02564                                       reco::PFBlock::LINKTEST_ALL );
02565             unsigned jEcal = sortedECAL.begin()->second;
02566             if ( jEcal != EcalIndex[ikeyecal]) continue; 
02567 
02568 
02569             EcalElemsIndex.push_back(index);
02570             localactive[index] = false;
02571           }
02572         }
02573         
02574         std::multimap<double, unsigned int> PS2Elems;
02575         block.associatedElements( EcalIndex[ikeyecal],linkData,
02576                                   PS2Elems,
02577                                   reco::PFBlockElement::PS2,
02578                                   reco::PFBlock::LINKTEST_ALL );
02579         for( std::multimap<double, unsigned int>::iterator it = PS2Elems.begin();
02580              it != PS2Elems.end();it++) {
02581           unsigned int index = it->second;
02582           if(localactive[index] == true) {
02583             // Check that this cluster is not closer to another ECAL cluster
02584             std::multimap<double, unsigned> sortedECAL;
02585             block.associatedElements( index,  linkData,
02586                                       sortedECAL,
02587                                       reco::PFBlockElement::ECAL,
02588                                       reco::PFBlock::LINKTEST_ALL );
02589             unsigned jEcal = sortedECAL.begin()->second;
02590             if ( jEcal != EcalIndex[ikeyecal]) continue; 
02591             
02592             EcalElemsIndex.push_back(index);
02593             localactive[index] = false;
02594           }
02595         }
02596         if(ikeyecal == 0) {
02597           // The first cluster is that one coming from the Gsf. 
02598           // Only for this one is found the HCAL cluster using the Track-HCAL link
02599           // and not the Ecal-Hcal not well tested yet.
02600           std::multimap<double, unsigned int> hcalGsfElems;
02601           block.associatedElements( gsfIs[iEle],linkData,
02602                                     hcalGsfElems,
02603                                     reco::PFBlockElement::HCAL,
02604                                     reco::PFBlock::LINKTEST_ALL );      
02605           for( std::multimap<double, unsigned int>::iterator it = hcalGsfElems.begin();
02606                it != hcalGsfElems.end();it++) {
02607             unsigned int index = it->second;
02608             //  if(localactive[index] == true) {
02609 
02610               // Check that this cluster is not closer to another GSF
02611               // remove in high energetic jets this is dangerous. 
02612 //            std::multimap<double, unsigned> sortedGsf;
02613 //            block.associatedElements( index,  linkData,
02614 //                                      sortedGsf,
02615 //                                      reco::PFBlockElement::GSF,
02616 //                                      reco::PFBlock::LINKTEST_ALL );
02617 //            unsigned jGsf = sortedGsf.begin()->second;
02618 //            if ( jGsf != gsfIs[iEle]) continue; 
02619 
02620               EcalElemsIndex.push_back(index);
02621               localactive[index] = false;
02622               
02623               // }
02624           }
02625           // if the closest ecal cluster has been link with the KF, check KF - HCAL link
02626           if(hcalGsfElems.size() == 0 && ClosestEcalWithKf == true) {
02627             std::multimap<double, unsigned int> hcalKfElems;
02628             block.associatedElements( KfGsf_index,linkData,
02629                                       hcalKfElems,
02630                                       reco::PFBlockElement::HCAL,
02631                                       reco::PFBlock::LINKTEST_ALL );    
02632             for( std::multimap<double, unsigned int>::iterator it = hcalKfElems.begin();
02633                  it != hcalKfElems.end();it++) {
02634               unsigned int index = it->second;
02635               if(localactive[index] == true) {
02636                 
02637                 // Check that this cluster is not closer to another KF
02638                 std::multimap<double, unsigned> sortedKf;
02639                 block.associatedElements( index,  linkData,
02640                                           sortedKf,
02641                                           reco::PFBlockElement::TRACK,
02642                                           reco::PFBlock::LINKTEST_ALL );
02643                 unsigned jKf = sortedKf.begin()->second;
02644                 if ( jKf != KfGsf_index) continue; 
02645                 EcalElemsIndex.push_back(index);
02646                 localactive[index] = false;
02647               }
02648             }
02649           }
02650           // Find Other Primary Tracks Associated to the same Gsf Clusters
02651           std::multimap<double, unsigned int> kfEtraElems;
02652           block.associatedElements( EcalIndex[ikeyecal],linkData,
02653                                     kfEtraElems,
02654                                     reco::PFBlockElement::TRACK,
02655                                     reco::PFBlock::LINKTEST_ALL );
02656           if(kfEtraElems.size() > 0) {
02657             for( std::multimap<double, unsigned int>::iterator it = kfEtraElems.begin();
02658                  it != kfEtraElems.end();it++) {
02659               unsigned int index = it->second;
02660 
02661               // 19 Mar 2010 do not consider here tracks from gamma conv
02662              //  const reco::PFBlockElementTrack * kfTk =  
02663              //  dynamic_cast<const reco::PFBlockElementTrack*>((&elements[index]));         
02664               // DANIELE ?  It is not need because of the local locking 
02665               //   if(kfTk->isLinkedToDisplacedVertex()) continue;
02666 
02667               bool thisIsAMuon = false;
02668               thisIsAMuon =  PFMuonAlgo::isMuon(elements[index]);
02669               if (DebugSetLinksDetailed && thisIsAMuon)
02670                 cout << " This is a Muon: index " << index << endl;
02671               if(localactive[index] == true && !thisIsAMuon) {
02672                 if(index != KfGsf_index) {
02673                   // Check that this track is not closer to another ECAL cluster
02674                   // Not Sure here I need this step
02675                   std::multimap<double, unsigned> sortedECAL;
02676                   block.associatedElements( index,  linkData,
02677                                             sortedECAL,
02678                                             reco::PFBlockElement::ECAL,
02679                                             reco::PFBlock::LINKTEST_ALL );
02680                   unsigned jEcal = sortedECAL.begin()->second;
02681                   if ( jEcal != EcalIndex[ikeyecal]) continue; 
02682                   EcalElemsIndex.push_back(index);
02683                   localactive[index] = false;
02684                 }
02685               }
02686             }
02687           }       
02688 
02689         }
02690         associatedToEcal_.insert(pair<unsigned int,vector<unsigned int> >(EcalIndex[ikeyecal],EcalElemsIndex));
02691       }
02692     }// end type GSF
02693   } // endis there a gsf track
02694   
02695   // ******************* End Link *****************************
02696 
02697   // 
02698   // Below is only for debugging printout 
02699   if (DebugSetLinksSummary) {
02700     if(IsThereAGoodGSFTrack) {
02701       if (DebugSetLinksSummary) cout << " -- The Link Summary --" << endl;
02702       for(map<unsigned int,vector<unsigned int> >::iterator it = associatedToGsf_.begin();
02703           it != associatedToGsf_.end(); it++) {
02704         
02705         if (DebugSetLinksSummary) cout << " AssoGsf " << it->first << endl;
02706         vector<unsigned int> eleasso = it->second;
02707         for(unsigned int i=0;i<eleasso.size();i++) {
02708           PFBlockElement::Type type = elements[eleasso[i]].type();
02709           if(type == reco::PFBlockElement::BREM) {
02710             if (DebugSetLinksSummary) 
02711               cout << " AssoGsfElements BREM " <<  eleasso[i] <<  endl;
02712           }
02713           else if(type == reco::PFBlockElement::ECAL) {
02714             if (DebugSetLinksSummary) 
02715               cout << " AssoGsfElements ECAL " <<  eleasso[i] <<  endl;
02716           }
02717           else if(type == reco::PFBlockElement::TRACK) {
02718             if (DebugSetLinksSummary) 
02719               cout << " AssoGsfElements KF " <<  eleasso[i] <<  endl;
02720           }
02721           else {
02722             if (DebugSetLinksSummary) 
02723               cout << " AssoGsfElements ????? " <<  eleasso[i] <<  endl;
02724           }
02725         }
02726       }
02727       
02728       for(map<unsigned int,vector<unsigned int> >::iterator it = associatedToBrems_.begin();
02729           it != associatedToBrems_.end(); it++) {
02730         if (DebugSetLinksSummary) cout << " AssoBrem " << it->first << endl;
02731         vector<unsigned int> eleasso = it->second;
02732         for(unsigned int i=0;i<eleasso.size();i++) {
02733           PFBlockElement::Type type = elements[eleasso[i]].type();
02734           if(type == reco::PFBlockElement::ECAL) {
02735             if (DebugSetLinksSummary) 
02736               cout << " AssoBremElements ECAL " <<  eleasso[i] <<  endl;
02737           }
02738           else {
02739             if (DebugSetLinksSummary) 
02740               cout << " AssoBremElements ????? " <<  eleasso[i] <<  endl;
02741           }
02742         }
02743       }
02744       
02745       for(map<unsigned int,vector<unsigned int> >::iterator it = associatedToEcal_.begin();
02746           it != associatedToEcal_.end(); it++) {
02747         if (DebugSetLinksSummary) cout << " AssoECAL " << it->first << endl;
02748         vector<unsigned int> eleasso = it->second;
02749         for(unsigned int i=0;i<eleasso.size();i++) {
02750           PFBlockElement::Type type = elements[eleasso[i]].type();
02751           if(type == reco::PFBlockElement::PS1) {
02752             if (DebugSetLinksSummary) 
02753               cout << " AssoECALElements PS1  " <<  eleasso[i] <<  endl;
02754           }
02755           else if(type == reco::PFBlockElement::PS2) {
02756             if (DebugSetLinksSummary) 
02757               cout << " AssoECALElements PS2  " <<  eleasso[i] <<  endl;
02758           }
02759           else if(type == reco::PFBlockElement::HCAL) {
02760             if (DebugSetLinksSummary) 
02761               cout << " AssoECALElements HCAL  " <<  eleasso[i] <<  endl;
02762           }
02763           else {
02764             if (DebugSetLinksSummary) 
02765               cout << " AssoHCALElements ????? " <<  eleasso[i] <<  endl;
02766           }
02767         }
02768       }
02769       if (DebugSetLinksSummary) 
02770         cout << "-- End Summary --" <<  endl;
02771     }
02772     
02773   }
02774   // EndPrintOut
02775   return IsThereAGoodGSFTrack;
02776 }
02777 
02778 unsigned int PFEGammaAlgo::whichTrackAlgo(const reco::TrackRef& trackRef) {
02779   unsigned int Algo = 0; 
02780   switch (trackRef->algo()) {
02781   case TrackBase::ctf:
02782   case TrackBase::iter0:
02783   case TrackBase::iter1:
02784   case TrackBase::iter2:
02785     Algo = 0;
02786     break;
02787   case TrackBase::iter3:
02788     Algo = 1;
02789     break;
02790   case TrackBase::iter4:
02791     Algo = 2;
02792     break;
02793   case TrackBase::iter5:
02794     Algo = 3;
02795     break;
02796   case TrackBase::iter6:
02797     Algo = 4;
02798     break;
02799   default:
02800     Algo = 5;
02801     break;
02802   }
02803   return Algo;
02804 }
02805 bool PFEGammaAlgo::isPrimaryTrack(const reco::PFBlockElementTrack& KfEl,
02806                                     const reco::PFBlockElementGsfTrack& GsfEl) {
02807   bool isPrimary = false;
02808   
02809   GsfPFRecTrackRef gsfPfRef = GsfEl.GsftrackRefPF();
02810   
02811   if(gsfPfRef.isNonnull()) {
02812     PFRecTrackRef  kfPfRef = KfEl.trackRefPF();
02813     PFRecTrackRef  kfPfRef_fromGsf = (*gsfPfRef).kfPFRecTrackRef();
02814     if(kfPfRef.isNonnull() && kfPfRef_fromGsf.isNonnull()) {
02815       reco::TrackRef kfref= (*kfPfRef).trackRef();
02816       reco::TrackRef kfref_fromGsf = (*kfPfRef_fromGsf).trackRef();
02817       if(kfref.isNonnull() && kfref_fromGsf.isNonnull()) {
02818         if(kfref ==  kfref_fromGsf)
02819           isPrimary = true;
02820       }
02821     }
02822   }
02823 
02824   return isPrimary;
02825 }
02826 
02827 void PFEGammaAlgo::AddElectronElements(unsigned int gsf_index,
02828                                      std::vector<unsigned int> &elemsToLock,
02829                                      const reco::PFBlockRef&  blockRef,
02830                                      AssMap& associatedToGsf_,
02831                                      AssMap& associatedToBrems_,
02832                                      AssMap& associatedToEcal_){
02833   const reco::PFBlock& block = *blockRef;
02834   PFBlock::LinkData linkData =  block.linkData();  
02835    
02836   const edm::OwnVector< reco::PFBlockElement >&  elements = block.elements();
02837   
02838   const reco::PFBlockElementGsfTrack * GsfEl  =  
02839     dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[gsf_index]));
02840   reco::GsfTrackRef RefGSF = GsfEl->GsftrackRef();
02841 
02842   // lock only the elements that pass the BDT cut
02843 //   bool bypassmva=false;
02844 //   if(useEGElectrons_) {
02845 //     GsfElectronEqual myEqual(RefGSF);
02846 //     std::vector<reco::GsfElectron>::const_iterator itcheck=find_if(theGsfElectrons_->begin(),theGsfElectrons_->end(),myEqual);
02847 //     if(itcheck!=theGsfElectrons_->end()) {
02848 //       if(BDToutput_[cgsf] >= -1.) 
02849 //      bypassmva=true;
02850 //     }
02851 //   }
02852 
02853   //if(BDToutput_[cgsf] < mvaEleCut_ && bypassmva == false) continue;
02854 
02855   
02856   elemsToLock.push_back(gsf_index);
02857   vector<unsigned int> &assogsf_index = associatedToGsf_[gsf_index];
02858   for  (unsigned int ielegsf=0;ielegsf<assogsf_index.size();ielegsf++) {
02859     PFBlockElement::Type assoele_type = elements[(assogsf_index[ielegsf])].type();
02860     // lock the elements associated to the gsf: ECAL, Brems
02861     elemsToLock.push_back((assogsf_index[ielegsf]));
02862     if (assoele_type == reco::PFBlockElement::ECAL) {
02863       unsigned int keyecalgsf = assogsf_index[ielegsf];
02864 
02865       // added protection against fifth step
02866       if(fifthStepKfTrack_.size() > 0) {
02867         for(unsigned int itr = 0; itr < fifthStepKfTrack_.size(); itr++) {
02868           if(fifthStepKfTrack_[itr].first == keyecalgsf) {
02869             elemsToLock.push_back((fifthStepKfTrack_[itr].second));
02870           }
02871         }
02872       }
02873 
02874       // added locking for conv gsf tracks and kf tracks
02875       if(convGsfTrack_.size() > 0) {
02876         for(unsigned int iconv = 0; iconv < convGsfTrack_.size(); iconv++) {
02877           if(convGsfTrack_[iconv].first == keyecalgsf) {
02878             // lock the GSF track
02879             elemsToLock.push_back(convGsfTrack_[iconv].second);
02880             // lock also the KF track associated
02881             std::multimap<double, unsigned> convKf;
02882             block.associatedElements( convGsfTrack_[iconv].second,
02883                                       linkData,
02884                                       convKf,
02885                                       reco::PFBlockElement::TRACK,
02886                                       reco::PFBlock::LINKTEST_ALL );
02887             if(convKf.size() > 0) {
02888               elemsToLock.push_back(convKf.begin()->second);
02889             }
02890           }
02891         }
02892       }
02893 
02894 
02895       vector<unsigned int> assoecalgsf_index = associatedToEcal_.find(keyecalgsf)->second;
02896       for(unsigned int ips =0; ips<assoecalgsf_index.size();ips++) {
02897         // lock the elements associated to ECAL: PS1,PS2, for the moment not HCAL
02898         if  (elements[(assoecalgsf_index[ips])].type() == reco::PFBlockElement::PS1) 
02899           elemsToLock.push_back((assoecalgsf_index[ips]));
02900         if  (elements[(assoecalgsf_index[ips])].type() == reco::PFBlockElement::PS2) 
02901           elemsToLock.push_back(assoecalgsf_index[ips]);
02902         if  (elements[(assoecalgsf_index[ips])].type() == reco::PFBlockElement::TRACK) {
02903           //FIXME: some extra input needed here which is not available yet
02904 //        if(lockExtraKf_[cgsf] == true) {            
02905 //          elemsToLock.push_back(assoecalgsf_index[ips])
02906 //        }
02907         }
02908       }
02909     } // End if ECAL
02910     if (assoele_type == reco::PFBlockElement::BREM) {
02911       unsigned int brem_index = assogsf_index[ielegsf];
02912       vector<unsigned int> assobrem_index = associatedToBrems_.find(brem_index)->second;
02913       for (unsigned int ibrem = 0; ibrem < assobrem_index.size(); ibrem++){
02914         if (elements[(assobrem_index[ibrem])].type() == reco::PFBlockElement::ECAL) {
02915           unsigned int keyecalbrem = assobrem_index[ibrem];
02916           // lock the ecal cluster associated to the brem
02917           elemsToLock.push_back(assobrem_index[ibrem]);
02918 
02919           // add protection against fifth step
02920           if(fifthStepKfTrack_.size() > 0) {
02921             for(unsigned int itr = 0; itr < fifthStepKfTrack_.size(); itr++) {
02922               if(fifthStepKfTrack_[itr].first == keyecalbrem) {
02923                 elemsToLock.push_back(fifthStepKfTrack_[itr].second);
02924               }
02925             }
02926           }
02927 
02928           vector<unsigned int> assoelebrem_index = associatedToEcal_.find(keyecalbrem)->second;
02929           // lock the elements associated to ECAL: PS1,PS2, for the moment not HCAL
02930           for (unsigned int ielebrem=0; ielebrem<assoelebrem_index.size();ielebrem++) {
02931             if (elements[(assoelebrem_index[ielebrem])].type() == reco::PFBlockElement::PS1) 
02932               elemsToLock.push_back(assoelebrem_index[ielebrem]);
02933             if (elements[(assoelebrem_index[ielebrem])].type() == reco::PFBlockElement::PS2) 
02934               elemsToLock.push_back(assoelebrem_index[ielebrem]);
02935           }
02936         }
02937       }
02938     } // End if BREM      
02939   } // End loop on elements from gsf track
02940   return;
02941 }
02942 
02943 // This function get the associatedToGsf and associatedToBrems maps and  
02944 // compute the electron 4-mom and set the pf candidate, for
02945 // the gsf track with a BDTcut > mvaEleCut_
02946 bool PFEGammaAlgo::AddElectronCandidate(unsigned int gsf_index,
02947                                         reco::SuperClusterRef scref,
02948                                          std::vector<unsigned int> &elemsToLock,
02949                                          const reco::PFBlockRef&  blockRef,
02950                                          AssMap& associatedToGsf_,
02951                                          AssMap& associatedToBrems_,
02952                                          AssMap& associatedToEcal_,
02953                                          std::vector<bool>& active) {
02954   
02955   const reco::PFBlock& block = *blockRef;
02956   PFBlock::LinkData linkData =  block.linkData();     
02957   const edm::OwnVector< reco::PFBlockElement >&  elements = block.elements();
02958   PFEnergyResolution pfresol_;
02959   //PFEnergyCalibration pfcalib_;
02960 
02961   bool DebugIDCandidates = false;
02962 //   vector<reco::PFCluster> pfClust_vec(0);
02963 //   pfClust_vec.clear();
02964 
02965           
02966   // They should be reset for each gsf track
02967   int eecal=0;
02968   int hcal=0;
02969   int charge =0; 
02970   // bool goodphi=true;
02971   math::XYZTLorentzVector momentum_kf,momentum_gsf,momentum,momentum_mean;
02972   float dpt=0; float dpt_gsf=0;
02973   float Eene=0; float dene=0; float Hene=0.;
02974   float RawEene = 0.;
02975   double posX=0.;
02976   double posY=0.;
02977   double posZ=0.;
02978   std::vector<float> bremEnergyVec;
02979 
02980   std::vector<const PFCluster*> pfSC_Clust_vec; 
02981 
02982   float de_gs = 0., de_me = 0., de_kf = 0.; 
02983   float m_el=0.00051;
02984   int nhit_kf=0; int nhit_gsf=0;
02985   bool has_gsf=false;
02986   bool has_kf=false;
02987   math::XYZTLorentzVector newmomentum;
02988   float ps1TotEne = 0;
02989   float ps2TotEne = 0;
02990   vector<unsigned int> elementsToAdd(0);
02991   reco::TrackRef RefKF;  
02992 
02993 
02994 
02995   elementsToAdd.push_back(gsf_index);
02996   const reco::PFBlockElementGsfTrack * GsfEl  =  
02997     dynamic_cast<const reco::PFBlockElementGsfTrack*>((&elements[gsf_index]));
02998   const math::XYZPointF& posGsfEcalEntrance = GsfEl->positionAtECALEntrance();
02999   reco::GsfTrackRef RefGSF = GsfEl->GsftrackRef();
03000   if (RefGSF.isNonnull()) {
03001     
03002     has_gsf=true;
03003     
03004     charge= RefGSF->chargeMode();
03005     nhit_gsf= RefGSF->hitPattern().trackerLayersWithMeasurement();
03006     
03007     momentum_gsf.SetPx(RefGSF->pxMode());
03008     momentum_gsf.SetPy(RefGSF->pyMode());
03009     momentum_gsf.SetPz(RefGSF->pzMode());
03010     float ENE=sqrt(RefGSF->pMode()*
03011                     RefGSF->pMode()+m_el*m_el);
03012     
03013     if( DebugIDCandidates ) 
03014       cout << "SetCandidates:: GsfTrackRef: Ene " << ENE 
03015             << " charge " << charge << " nhits " << nhit_gsf <<endl;
03016     
03017     momentum_gsf.SetE(ENE);       
03018     dpt_gsf=RefGSF->ptModeError()*
03019       (RefGSF->pMode()/RefGSF->ptMode());
03020     
03021     momentum_mean.SetPx(RefGSF->px());
03022     momentum_mean.SetPy(RefGSF->py());
03023     momentum_mean.SetPz(RefGSF->pz());
03024     float ENEm=sqrt(RefGSF->p()*
03025                     RefGSF->p()+m_el*m_el);
03026     momentum_mean.SetE(ENEm);       
03027     //       dpt_mean=RefGSF->ptError()*
03028     //  (RefGSF->p()/RefGSF->pt());  
03029   }
03030   else {
03031     if( DebugIDCandidates ) 
03032       cout <<  "SetCandidates:: !!!!  NULL GSF Track Ref " << endl;     
03033   } 
03034 
03035   //    vector<unsigned int> assogsf_index =  associatedToGsf_[igsf].second;
03036   vector<unsigned int> &assogsf_index = associatedToGsf_[gsf_index];
03037   unsigned int ecalGsf_index = 100000;
03038   bool FirstEcalGsf = true;
03039   for  (unsigned int ielegsf=0;ielegsf<assogsf_index.size();ielegsf++) {
03040     PFBlockElement::Type assoele_type = elements[(assogsf_index[ielegsf])].type();
03041     if  (assoele_type == reco::PFBlockElement::TRACK) {
03042       elementsToAdd.push_back((assogsf_index[ielegsf])); // Daniele
03043       const reco::PFBlockElementTrack * KfTk =  
03044         dynamic_cast<const reco::PFBlockElementTrack*>((&elements[(assogsf_index[ielegsf])]));
03045       // 19 Mar 2010 do not consider here track from gamam conv
03046       bool isPrim = isPrimaryTrack(*KfTk,*GsfEl);
03047       if(!isPrim) continue;
03048       
03049       RefKF = KfTk->trackRef();
03050       if (RefKF.isNonnull()) {
03051         has_kf = true;
03052         // dpt_kf=(RefKF->ptError()*RefKF->ptError());
03053         nhit_kf=RefKF->hitPattern().trackerLayersWithMeasurement();
03054         momentum_kf.SetPx(RefKF->px());
03055         momentum_kf.SetPy(RefKF->py());
03056         momentum_kf.SetPz(RefKF->pz());
03057         float ENE=sqrt(RefKF->p()*RefKF->p()+m_el*m_el);
03058         if( DebugIDCandidates ) 
03059           cout << "SetCandidates:: KFTrackRef: Ene " << ENE << " nhits " << nhit_kf << endl;
03060         
03061         momentum_kf.SetE(ENE);
03062       }
03063       else {
03064         if( DebugIDCandidates ) 
03065           cout <<  "SetCandidates:: !!!! NULL KF Track Ref " << endl;
03066       }
03067     } 
03068 
03069     if  (assoele_type == reco::PFBlockElement::ECAL) {
03070       unsigned int keyecalgsf = assogsf_index[ielegsf];
03071       vector<unsigned int> assoecalgsf_index = associatedToEcal_.find(keyecalgsf)->second;
03072       vector<double> ps1Ene(0);
03073       vector<double> ps2Ene(0);
03074       // Important is the PS clusters are not saved before the ecal one, these
03075       // energy are not correctly assigned 
03076       // For the moment I get only the closest PS clusters: this has to be changed
03077       for(unsigned int ips =0; ips<assoecalgsf_index.size();ips++) {
03078         PFBlockElement::Type typeassoecal = elements[(assoecalgsf_index[ips])].type();
03079         if  (typeassoecal == reco::PFBlockElement::PS1) {  
03080           PFClusterRef  psref = elements[(assoecalgsf_index[ips])].clusterRef();
03081           ps1Ene.push_back(psref->energy());
03082           elementsToAdd.push_back((assoecalgsf_index[ips]));
03083         }
03084         if  (typeassoecal == reco::PFBlockElement::PS2) {  
03085           PFClusterRef  psref = elements[(assoecalgsf_index[ips])].clusterRef();
03086           ps2Ene.push_back(psref->energy());
03087           elementsToAdd.push_back((assoecalgsf_index[ips]));
03088         }
03089         if  (typeassoecal == reco::PFBlockElement::HCAL) {
03090           const reco::PFBlockElementCluster * clust =  
03091             dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(assoecalgsf_index[ips])])); 
03092           elementsToAdd.push_back((assoecalgsf_index[ips])); 
03093           Hene+=clust->clusterRef()->energy();
03094           hcal++;
03095         }
03096       }
03097       elementsToAdd.push_back((assogsf_index[ielegsf]));
03098 
03099 
03100       const reco::PFBlockElementCluster * clust =  
03101         dynamic_cast<const reco::PFBlockElementCluster*>((&elements[(assogsf_index[ielegsf])]));
03102       
03103       eecal++;
03104       
03105       const reco::PFCluster& cl(*clust->clusterRef());
03106       //pfClust_vec.push_back((*clust->clusterRef()));
03107 
03108       // The electron RAW energy is the energy of the corrected GSF cluster     
03109       double ps1,ps2;
03110       ps1=ps2=0.;
03111       //        float EE=pfcalib_.energyEm(cl,ps1Ene,ps2Ene);
03112       float EE = thePFEnergyCalibration_->energyEm(cl,ps1Ene,ps2Ene,ps1,ps2,applyCrackCorrections_);      
03113       //        float RawEE = cl.energy();
03114 
03115       float ceta=cl.position().eta();
03116       float cphi=cl.position().phi();
03117       
03118       /*
03119         float mphi=-2.97025;
03120         if (ceta<0) mphi+=0.00638;
03121         
03122         for (int ip=1; ip<19; ip++){
03123         float df= cphi - (mphi+(ip*6.283185/18));
03124         if (fabs(df)<0.01) goodphi=false;
03125         }
03126       */
03127 
03128       float dE=pfresol_.getEnergyResolutionEm(EE,cl.position().eta());
03129       if( DebugIDCandidates ) 
03130         cout << "SetCandidates:: EcalCluster: EneNoCalib " << clust->clusterRef()->energy()  
03131               << " eta,phi " << ceta << "," << cphi << " Calib " <<  EE << " dE " <<  dE <<endl;
03132 
03133       bool elecCluster=false;
03134       if (FirstEcalGsf) {
03135         FirstEcalGsf = false;
03136         elecCluster=true;
03137         ecalGsf_index = assogsf_index[ielegsf];
03138         //        std::cout << " PFElectronAlgo / Seed " << EE << std::endl;
03139         RawEene += EE;
03140       }
03141       
03142       // create a photon/electron candidate
03143       math::XYZTLorentzVector clusterMomentum;
03144       math::XYZPoint direction=cl.position()/cl.position().R();
03145       clusterMomentum.SetPxPyPzE(EE*direction.x(),
03146                                   EE*direction.y(),
03147                                   EE*direction.z(),
03148                                   EE);
03149       reco::PFCandidate cluster_Candidate((elecCluster)?charge:0,
03150                                           clusterMomentum, 
03151                                           (elecCluster)? reco::PFCandidate::e : reco::PFCandidate::gamma);
03152       
03153       cluster_Candidate.setPs1Energy(ps1);
03154       cluster_Candidate.setPs2Energy(ps2);
03155       // The Raw Ecal energy will be the energy of the basic cluster. 
03156       // It will be the corrected energy without the preshower
03157       cluster_Candidate.setEcalEnergy(EE-ps1-ps2,EE);
03158       //              std::cout << " PFElectronAlgo, adding Brem (1) " << EE << std::endl;
03159       cluster_Candidate.setPositionAtECALEntrance(math::XYZPointF(cl.position()));
03160       cluster_Candidate.addElementInBlock(blockRef,assogsf_index[ielegsf]);
03161       // store the photon candidate
03162 //       std::map<unsigned int,std::vector<reco::PFCandidate> >::iterator itcheck=
03163 //      electronConstituents_.find(cgsf);
03164 //       if(itcheck==electronConstituents_.end())
03165 //      {                 
03166 //        // beurk
03167 //        std::vector<reco::PFCandidate> tmpVec;
03168 //        tmpVec.push_back(cluster_Candidate);
03169 //        electronConstituents_.insert(std::pair<unsigned int, std::vector<reco::PFCandidate> >
03170 //                                      (cgsf,tmpVec));
03171 //      }
03172 //       else
03173 //      {
03174 //        itcheck->second.push_back(cluster_Candidate);
03175 //      }
03176       
03177       Eene+=EE;
03178       posX +=  EE * cl.position().X();
03179       posY +=  EE * cl.position().Y();
03180       posZ +=  EE * cl.position().Z();    
03181       ps1TotEne+=ps1;
03182       ps2TotEne+=ps2;
03183       dene+=dE*dE;
03184       
03185       //MM Add cluster to the vector pfSC_Clust_vec needed for brem corrections
03186       pfSC_Clust_vec.push_back( &cl );
03187 
03188     }
03189     
03190 
03191 
03192     // Important: Add energy from the brems
03193     if  (assoele_type == reco::PFBlockElement::BREM) {
03194       unsigned int brem_index = assogsf_index[ielegsf];
03195       vector<unsigned int> assobrem_index = associatedToBrems_.find(brem_index)->second;
03196       elementsToAdd.push_back(brem_index);
03197       for (unsigned int ibrem = 0; ibrem < assobrem_index.size(); ibrem++){
03198         if (elements[(assobrem_index[ibrem])].type() == reco::PFBlockElement::ECAL) {
03199           // brem emission is from the considered gsf track
03200           if( assobrem_index[ibrem] !=  ecalGsf_index) {
03201             unsigned int keyecalbrem = assobrem_index[ibrem];
03202             const vector<unsigned int>& assoelebrem_index = associatedToEcal_.find(keyecalbrem)->second;
03203             vector<double> ps1EneFromBrem(0);
03204             vector<double> ps2EneFromBrem(0);
03205             for (unsigned int ielebrem=0; ielebrem<assoelebrem_index.size();ielebrem++) {
03206               if (elements[(assoelebrem_index[ielebrem])].type() == reco::PFBlockElement::PS1) {
03207                 PFClusterRef  psref = elements[(assoelebrem_index[ielebrem])].clusterRef();
03208                 ps1EneFromBrem.push_back(psref->energy());
03209                 elementsToAdd.push_back(assoelebrem_index[ielebrem]);
03210               }
03211               if (elements[(assoelebrem_index[ielebrem])].type() == reco::PFBlockElement::PS2) {
03212                 PFClusterRef  psref = elements[(assoelebrem_index[ielebrem])].clusterRef();
03213                 ps2EneFromBrem.push_back(psref->energy());
03214                 elementsToAdd.push_back(assoelebrem_index[ielebrem]);
03215               }   
03216             }
03217             elementsToAdd.push_back(assobrem_index[ibrem]);
03218             reco::PFClusterRef clusterRef = elements[(assobrem_index[ibrem])].clusterRef();
03219             //pfClust_vec.push_back(*clusterRef);
03220             // to get a calibrated PS energy 
03221             double ps1=0;
03222             double ps2=0;
03223             float EE = thePFEnergyCalibration_->energyEm(*clusterRef,ps1EneFromBrem,ps2EneFromBrem,ps1,ps2,applyCrackCorrections_);
03224             bremEnergyVec.push_back(EE);
03225             // float RawEE  = clusterRef->energy();
03226             float ceta = clusterRef->position().eta();
03227             // float cphi = clusterRef->position().phi();
03228             float dE=pfresol_.getEnergyResolutionEm(EE,ceta);
03229             if( DebugIDCandidates ) 
03230               cout << "SetCandidates:: BremCluster: Ene " << EE << " dE " <<  dE <<endl;          
03231 
03232             Eene+=EE;
03233             posX +=  EE * clusterRef->position().X();
03234             posY +=  EE * clusterRef->position().Y();
03235             posZ +=  EE * clusterRef->position().Z();     
03236             ps1TotEne+=ps1;
03237             ps2TotEne+=ps2;
03238             // Removed 4 March 2009. Florian. The Raw energy is the (corrected) one of the GSF cluster only
03239             //        RawEene += RawEE;
03240             dene+=dE*dE;
03241 
03242             //MM Add cluster to the vector pfSC_Clust_vec needed for brem corrections
03243             pfSC_Clust_vec.push_back( clusterRef.get() );
03244 
03245             // create a PFCandidate out of it. Watch out, it is for the e/gamma and tau only
03246             // not to be used by the PFAlgo
03247             math::XYZTLorentzVector photonMomentum;
03248             math::XYZPoint direction=clusterRef->position()/clusterRef->position().R();
03249             
03250             photonMomentum.SetPxPyPzE(EE*direction.x(),
03251                                       EE*direction.y(),
03252                                       EE*direction.z(),
03253                                       EE);
03254             reco::PFCandidate photon_Candidate(0,photonMomentum, reco::PFCandidate::gamma);
03255             
03256             photon_Candidate.setPs1Energy(ps1);
03257             photon_Candidate.setPs2Energy(ps2);
03258             // yes, EE, we want the raw ecal energy of the daugther to have the same definition
03259             // as the GSF cluster
03260             photon_Candidate.setEcalEnergy(EE-ps1-ps2,EE);
03261             //        std::cout << " PFElectronAlgo, adding Brem " << EE << std::endl;
03262             photon_Candidate.setPositionAtECALEntrance(math::XYZPointF(clusterRef->position()));
03263             photon_Candidate.addElementInBlock(blockRef,assobrem_index[ibrem]);
03264 
03265             // store the photon candidate
03266             //FIXME: constituents needed?
03267 //          std::map<unsigned int,std::vector<reco::PFCandidate> >::iterator itcheck=
03268 //            electronConstituents_.find(cgsf);
03269 //          if(itcheck==electronConstituents_.end())
03270 //            {           
03271 //              // beurk
03272 //              std::vector<reco::PFCandidate> tmpVec;
03273 //              tmpVec.push_back(photon_Candidate);
03274 //              electronConstituents_.insert(std::pair<unsigned int, std::vector<reco::PFCandidate> >
03275 //                                        (cgsf,tmpVec));
03276 //            }
03277 //          else
03278 //            {
03279 //              itcheck->second.push_back(photon_Candidate);
03280 //            }
03281           }
03282         } 
03283       }
03284     }
03285   } // End Loop On element associated to the GSF tracks
03286   if (has_gsf) {
03287     
03288     // SuperCluster energy corrections
03289     double unCorrEene = Eene;
03290     double absEta = fabs(momentum_gsf.Eta());
03291     double emTheta = momentum_gsf.Theta();
03292     PFClusterWidthAlgo pfSCwidth(pfSC_Clust_vec); 
03293     double brLinear = pfSCwidth.pflowPhiWidth()/pfSCwidth.pflowEtaWidth(); 
03294     pfSC_Clust_vec.clear();
03295     
03296     if( DebugIDCandidates ) 
03297       cout << "PFEelectronAlgo:: absEta " << absEta  << " theta " << emTheta 
03298             << " EneRaw " << Eene << " Err " << dene;
03299     
03300     // The calibrations are provided till ET = 200 GeV //No longer a such cut MM
03301     // Protection on at least 1 GeV energy...avoid possible divergencies at very low energy.
03302     if(usePFSCEleCalib_ && unCorrEene > 0.) { 
03303       if( absEta < 1.5) {
03304         double Etene = Eene*sin(emTheta);
03305         double emBR_e = thePFSCEnergyCalibration_->SCCorrFBremBarrel(Eene, Etene, brLinear); 
03306         double emBR_et = emBR_e*sin(emTheta); 
03307         double emCorrFull_et = thePFSCEnergyCalibration_->SCCorrEtEtaBarrel(emBR_et, absEta); 
03308         Eene = emCorrFull_et/sin(emTheta);
03309       }
03310       else {
03311         //  double Etene = Eene*sin(emTheta); //not needed anymore for endcaps MM
03312         double emBR_e = thePFSCEnergyCalibration_->SCCorrFBremEndcap(Eene, absEta, brLinear); 
03313         double emBR_et = emBR_e*sin(emTheta); 
03314         double emCorrFull_et = thePFSCEnergyCalibration_->SCCorrEtEtaEndcap(emBR_et, absEta); 
03315         Eene = emCorrFull_et/sin(emTheta);
03316       }
03317       dene = sqrt(dene)*(Eene/unCorrEene);
03318       dene = dene*dene;
03319     }
03320 
03321     if( DebugIDCandidates ) 
03322       cout << " EneCorrected " << Eene << " Err " << dene  << endl;
03323 
03324     // charge determination with the majority method
03325     // if the kf track exists: 2 among 3 of supercluster barycenter position
03326     // gsf track and kf track
03327     if(has_kf && unCorrEene > 0.) {
03328       posX /=unCorrEene;
03329       posY /=unCorrEene;
03330       posZ /=unCorrEene;
03331       math::XYZPoint sc_pflow(posX,posY,posZ);
03332 
03333       std::multimap<double, unsigned int> bremElems;
03334       block.associatedElements( gsf_index,linkData,
03335                                 bremElems,
03336                                 reco::PFBlockElement::BREM,
03337                                 reco::PFBlock::LINKTEST_ALL );
03338 
03339       double phiTrack = RefGSF->phiMode();
03340       if(bremElems.size()>0) {
03341         unsigned int brem_index =  bremElems.begin()->second;
03342         const reco::PFBlockElementBrem * BremEl  =  
03343           dynamic_cast<const reco::PFBlockElementBrem*>((&elements[brem_index]));
03344         phiTrack = BremEl->positionAtECALEntrance().phi();
03345       }
03346 
03347       double dphi_normalsc = sc_pflow.Phi() - phiTrack;
03348       if ( dphi_normalsc < -M_PI ) 
03349         dphi_normalsc = dphi_normalsc + 2.*M_PI;
03350       else if ( dphi_normalsc > M_PI ) 
03351         dphi_normalsc = dphi_normalsc - 2.*M_PI;
03352       
03353       int chargeGsf = RefGSF->chargeMode();
03354       int chargeKf = RefKF->charge();
03355 
03356       int chargeSC = 0;
03357       if(dphi_normalsc < 0.) 
03358         chargeSC = 1;
03359       else 
03360         chargeSC = -1;
03361       
03362       if(chargeKf == chargeGsf) 
03363         charge = chargeGsf;
03364       else if(chargeGsf == chargeSC)
03365         charge = chargeGsf;
03366       else 
03367         charge = chargeKf;
03368 
03369       if( DebugIDCandidates ) 
03370         cout << "PFElectronAlgo:: charge determination " 
03371               << " charge GSF " << chargeGsf 
03372               << " charge KF " << chargeKf 
03373               << " charge SC " << chargeSC
03374               << " Final Charge " << charge << endl;
03375       
03376     }
03377       
03378     // Think about this... 
03379     if ((nhit_gsf<8) && (has_kf)){
03380       
03381       // Use Hene if some condition.... 
03382       
03383       momentum=momentum_kf;
03384       float Fe=Eene;
03385       float scale= Fe/momentum.E();
03386       
03387       // Daniele Changed
03388       if (Eene < 0.0001) {
03389         Fe = momentum.E();
03390         scale = 1.;
03391       }
03392 
03393 
03394       newmomentum.SetPxPyPzE(scale*momentum.Px(),
03395                               scale*momentum.Py(),
03396                               scale*momentum.Pz(),Fe);
03397       if( DebugIDCandidates ) 
03398         cout << "SetCandidates:: (nhit_gsf<8) && (has_kf):: pt " << newmomentum.pt() << " Ene " <<  Fe <<endl;
03399 
03400       
03401     } 
03402     if ((nhit_gsf>7) || (has_kf==false)){
03403       if(Eene > 0.0001) {
03404         de_gs=1-momentum_gsf.E()/Eene;
03405         de_me=1-momentum_mean.E()/Eene;
03406         de_kf=1-momentum_kf.E()/Eene;
03407       }
03408 
03409       momentum=momentum_gsf;
03410       dpt=1/(dpt_gsf*dpt_gsf);
03411       
03412       if(dene > 0.)
03413         dene= 1./dene;
03414       
03415       float Fe = 0.;
03416       if(Eene > 0.0001) {
03417         Fe =((dene*Eene) +(dpt*momentum.E()))/(dene+dpt);
03418       }
03419       else {
03420         Fe=momentum.E();
03421       }
03422       
03423       if ((de_gs>0.05)&&(de_kf>0.05)){
03424         Fe=Eene;
03425       }
03426       if ((de_gs<-0.1)&&(de_me<-0.1) &&(de_kf<0.) && 
03427           (momentum.E()/dpt_gsf) > 5. && momentum_gsf.pt() < 30.){
03428         Fe=momentum.E();
03429       }
03430       float scale= Fe/momentum.E();
03431       
03432       newmomentum.SetPxPyPzE(scale*momentum.Px(),
03433                               scale*momentum.Py(),
03434                               scale*momentum.Pz(),Fe);
03435       if( DebugIDCandidates ) 
03436         cout << "SetCandidates::(nhit_gsf>7) || (has_kf==false)  " << newmomentum.pt() << " Ene " <<  Fe <<endl;
03437       
03438       
03439     }
03440     if (newmomentum.pt()>0.5){
03441       
03442       // the pf candidate are created: we need to set something more? 
03443       // IMPORTANT -> We need the gsftrackRef, not only the TrackRef??
03444 
03445       if( DebugIDCandidates )
03446         cout << "SetCandidates:: I am before doing candidate " <<endl;
03447       
03448       //vector with the cluster energies (for the extra)
03449       std::vector<float> clusterEnergyVec;
03450       clusterEnergyVec.push_back(RawEene);
03451       clusterEnergyVec.insert(clusterEnergyVec.end(),bremEnergyVec.begin(),bremEnergyVec.end());
03452 
03453       // add the information in the extra
03454       //std::vector<reco::PFCandidateElectronExtra>::iterator itextra;
03455       //PFElectronExtraEqual myExtraEqual(RefGSF);
03456       PFCandidateEGammaExtra myExtraEqual(RefGSF);
03457       //myExtraEqual.setSuperClusterRef(scref);
03458       myExtraEqual.setSuperClusterBoxRef(scref);
03459       myExtraEqual.setClusterEnergies(clusterEnergyVec);
03460       //itextra=find_if(electronExtra_.begin(),electronExtra_.end(),myExtraEqual);
03461       //if(itextra!=electronExtra_.end()) {
03462         //itextra->setClusterEnergies(clusterEnergyVec);
03463 //       else {
03464 //      if(RawEene>0.) 
03465 //        std::cout << " There is a big problem with the electron extra, PFElectronAlgo should crash soon " << RawEene << std::endl;
03466 //       }
03467 
03468       reco::PFCandidate::ParticleType particleType 
03469         = reco::PFCandidate::e;
03470       //reco::PFCandidate temp_Candidate;
03471       reco::PFCandidate temp_Candidate(charge,newmomentum,particleType);
03472       //FIXME: need bdt output
03473       //temp_Candidate.set_mva_e_pi(BDToutput_[cgsf]);
03474       temp_Candidate.setEcalEnergy(RawEene,Eene);
03475       // Note the Hcal energy is set but the element is never locked 
03476       temp_Candidate.setHcalEnergy(Hene,Hene);  
03477       temp_Candidate.setPs1Energy(ps1TotEne);
03478       temp_Candidate.setPs2Energy(ps2TotEne);
03479       temp_Candidate.setTrackRef(RefKF);   
03480       // This reference could be NULL it is needed a protection? 
03481       temp_Candidate.setGsfTrackRef(RefGSF);
03482       temp_Candidate.setPositionAtECALEntrance(posGsfEcalEntrance);
03483       // Add Vertex
03484       temp_Candidate.setVertexSource(PFCandidate::kGSFVertex);
03485       
03486       //supercluster ref is always available now and points to ecal-drive box/mustache supercluster
03487       temp_Candidate.setSuperClusterRef(scref);
03488       
03489       // save the superclusterRef when available
03490       //FIXME: Point back to ecal-driven supercluster ref, which is now always available
03491 //       if(RefGSF->extra().isAvailable() && RefGSF->extra()->seedRef().isAvailable()) {
03492 //      reco::ElectronSeedRef seedRef=  RefGSF->extra()->seedRef().castTo<reco::ElectronSeedRef>();
03493 //      if(seedRef.isAvailable() && seedRef->isEcalDriven()) {
03494 //        reco::SuperClusterRef scRef = seedRef->caloCluster().castTo<reco::SuperClusterRef>();
03495 //        if(scRef.isNonnull())  
03496 //          temp_Candidate.setSuperClusterRef(scRef);
03497 //      }
03498 //       }
03499 
03500       if( DebugIDCandidates ) 
03501         cout << "SetCandidates:: I am after doing candidate " <<endl;
03502       
03503 //       for (unsigned int elad=0; elad<elementsToAdd.size();elad++){
03504 //      temp_Candidate.addElementInBlock(blockRef,elementsToAdd[elad]);
03505 //       }
03506 // 
03507 //       // now add the photons to this candidate
03508 //       std::map<unsigned int, std::vector<reco::PFCandidate> >::const_iterator itcluster=
03509 //      electronConstituents_.find(cgsf);
03510 //       if(itcluster!=electronConstituents_.end())
03511 //      {
03512 //        const std::vector<reco::PFCandidate> & theClusters=itcluster->second;
03513 //        unsigned nclus=theClusters.size();
03514 //        //        std::cout << " PFElectronAlgo " << nclus << " daugthers to add" << std::endl;
03515 //        for(unsigned iclus=0;iclus<nclus;++iclus)
03516 //          {
03517 //            temp_Candidate.addDaughter(theClusters[iclus]);
03518 //          }
03519 //      }
03520 
03521       // By-pass the mva is the electron has been pre-selected 
03522 //       bool bypassmva=false;
03523 //       if(useEGElectrons_) {
03524 //      GsfElectronEqual myEqual(RefGSF);
03525 //      std::vector<reco::GsfElectron>::const_iterator itcheck=find_if(theGsfElectrons_->begin(),theGsfElectrons_->end(),myEqual);
03526 //      if(itcheck!=theGsfElectrons_->end()) {
03527 //        if(BDToutput_[cgsf] >= -1.)  {
03528 //          // bypass the mva only if the reconstruction went fine
03529 //          bypassmva=true;
03530 // 
03531 //          if( DebugIDCandidates ) {
03532 //            if(BDToutput_[cgsf] < -0.1) {
03533 //              float esceg = itcheck->caloEnergy();            
03534 //              cout << " Attention By pass the mva " << BDToutput_[cgsf] 
03535 //                    << " SuperClusterEnergy " << esceg
03536 //                    << " PF Energy " << Eene << endl;
03537 //              
03538 //              cout << " hoe " << itcheck->hcalOverEcal()
03539 //                    << " tkiso04 " << itcheck->dr04TkSumPt()
03540 //                    << " ecaliso04 " << itcheck->dr04EcalRecHitSumEt()
03541 //                    << " hcaliso04 " << itcheck->dr04HcalTowerSumEt()
03542 //                    << " tkiso03 " << itcheck->dr03TkSumPt()
03543 //                    << " ecaliso03 " << itcheck->dr03EcalRecHitSumEt()
03544 //                    << " hcaliso03 " << itcheck->dr03HcalTowerSumEt() << endl;
03545 //            }
03546 //          } // end DebugIDCandidates
03547 //        }
03548 //      }
03549 //       }
03550       
03551       myExtraEqual.setStatus(PFCandidateEGammaExtra::Selected,true);
03552       
03553       // ... and lock all elemts used
03554       for(std::vector<unsigned int>::const_iterator it = elemsToLock.begin();
03555           it != elemsToLock.end(); ++it)
03556         {
03557           if(active[*it])
03558             {
03559               temp_Candidate.addElementInBlock(blockRef,*it);
03560             }
03561           active[*it] = false;  
03562         }      
03563       
03564       egCandidate_.push_back(temp_Candidate);
03565       egExtra_.push_back(myExtraEqual);
03566       
03567       return true;
03568       
03569 //       bool mvaSelected = (BDToutput_[cgsf] >=  mvaEleCut_);
03570 //       if( mvaSelected || bypassmva )           {
03571 //        elCandidate_.push_back(temp_Candidate);
03572 //        if(itextra!=electronExtra_.end()) 
03573 //          itextra->setStatus(PFCandidateElectronExtra::Selected,true);
03574 //      }
03575 //       else     {
03576 //      if(itextra!=electronExtra_.end()) 
03577 //        itextra->setStatus(PFCandidateElectronExtra::Rejected,true);
03578 //       }
03579 //       allElCandidate_.push_back(temp_Candidate);
03580 //       
03581 //       // save the status information
03582 //       if(itextra!=electronExtra_.end()) {
03583 //      itextra->setStatus(PFCandidateElectronExtra::ECALDrivenPreselected,bypassmva);
03584 //      itextra->setStatus(PFCandidateElectronExtra::MVASelected,mvaSelected);
03585 //       }
03586       
03587 
03588     }
03589     else {
03590       //BDToutput_[cgsf] = -1.;   // if the momentum is < 0.5 ID = false, but not sure
03591       // it could be misleading. 
03592       if( DebugIDCandidates ) 
03593         cout << "SetCandidates:: No Candidate Produced because of Pt cut: 0.5 " <<endl;
03594       return false;
03595     }
03596   } 
03597   else {
03598     //BDToutput_[cgsf] = -1.;  // if gsf ref does not exist
03599     if( DebugIDCandidates ) 
03600       cout << "SetCandidates:: No Candidate Produced because of No GSF Track Ref " <<endl;
03601     return false;
03602   }
03603   return false;
03604 }