CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/RecoParticleFlow/PFProducer/src/PFPhotonAlgo.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/PFPhotonAlgo.h"
00008 #include "DataFormats/ParticleFlowReco/interface/PFBlockElementCluster.h"
00009 #include "DataFormats/ParticleFlowReco/interface/PFCluster.h"
00010 #include "DataFormats/ParticleFlowReco/interface/PFClusterFwd.h"
00011 #include "DataFormats/ParticleFlowReco/interface/PFBlockElementSuperCluster.h"
00012 #include "DataFormats/EgammaReco/interface/ElectronSeed.h"
00013 #include "DataFormats/ParticleFlowReco/interface/PFRecHit.h"
00014 #include "DataFormats/EcalDetId/interface/EBDetId.h"
00015 #include "DataFormats/EcalDetId/interface/EEDetId.h"
00016 #include "DataFormats/EgammaCandidates/interface/Photon.h"
00017 #include "RecoParticleFlow/PFClusterTools/interface/PFEnergyCalibration.h"
00018 #include "RecoParticleFlow/PFClusterTools/interface/PFPhotonClusters.h"
00019 #include "RecoEcal/EgammaCoreTools/interface/Mustache.h"
00020 #include "DataFormats/Math/interface/deltaPhi.h"
00021 #include "DataFormats/Math/interface/deltaR.h"
00022 #include <TFile.h>
00023 #include <iomanip>
00024 #include <algorithm>
00025 #include <TMath.h>
00026 using namespace std;
00027 using namespace reco;
00028 
00029 
00030 PFPhotonAlgo::PFPhotonAlgo(std::string mvaweightfile,  
00031                            double mvaConvCut, 
00032                            bool useReg,
00033                            std::string X0_Map,
00034                            const reco::Vertex& primary,
00035                            const boost::shared_ptr<PFEnergyCalibration>& thePFEnergyCalibration,
00036                            double sumPtTrackIsoForPhoton,
00037                            double sumPtTrackIsoSlopeForPhoton
00038                            ) : 
00039   isvalid_(false), 
00040   verbosityLevel_(Silent), 
00041   MVACUT(mvaConvCut),
00042   useReg_(useReg),
00043   thePFEnergyCalibration_(thePFEnergyCalibration),
00044   sumPtTrackIsoForPhoton_(sumPtTrackIsoForPhoton),
00045   sumPtTrackIsoSlopeForPhoton_(sumPtTrackIsoSlopeForPhoton),
00046   nlost(0.0), nlayers(0.0),
00047   chi2(0.0), STIP(0.0), del_phi(0.0),HoverPt(0.0), EoverPt(0.0), track_pt(0.0),
00048   mvaValue(0.0),
00049   CrysPhi_(0.0), CrysEta_(0.0),  VtxZ_(0.0), ClusPhi_(0.0), ClusEta_(0.0),
00050   ClusR9_(0.0), Clus5x5ratio_(0.0),  PFCrysEtaCrack_(0.0), logPFClusE_(0.0), e3x3_(0.0),
00051   CrysIPhi_(0), CrysIEta_(0),
00052   CrysX_(0.0), CrysY_(0.0),
00053   EB(0.0),
00054   eSeed_(0.0), e1x3_(0.0),e3x1_(0.0), e1x5_(0.0), e2x5Top_(0.0),  e2x5Bottom_(0.0), e2x5Left_(0.0),  e2x5Right_(0.0),
00055   etop_(0.0), ebottom_(0.0), eleft_(0.0), eright_(0.0),
00056   e2x5Max_(0.0),
00057   PFPhoEta_(0.0), PFPhoPhi_(0.0), PFPhoR9_(0.0), PFPhoR9Corr_(0.0), SCPhiWidth_(0.0), SCEtaWidth_(0.0), 
00058   PFPhoEt_(0.0), RConv_(0.0), PFPhoEtCorr_(0.0), PFPhoE_(0.0), PFPhoECorr_(0.0), MustE_(0.0), E3x3_(0.0),
00059   dEta_(0.0), dPhi_(0.0), LowClusE_(0.0), RMSAll_(0.0), RMSMust_(0.0), nPFClus_(0.0),
00060   TotPS1_(0.0), TotPS2_(0.0),
00061   nVtx_(0.0),
00062   x0inner_(0.0), x0middle_(0.0), x0outer_(0.0),
00063   excluded_(0.0), Mustache_EtRatio_(0.0), Mustache_Et_out_(0.0)
00064 {  
00065 
00066     //Book MVA  
00067     tmvaReader_ = new TMVA::Reader("!Color:Silent");  
00068     tmvaReader_->AddVariable("del_phi",&del_phi);  
00069     tmvaReader_->AddVariable("nlayers", &nlayers);  
00070     tmvaReader_->AddVariable("chi2",&chi2);  
00071     tmvaReader_->AddVariable("EoverPt",&EoverPt);  
00072     tmvaReader_->AddVariable("HoverPt",&HoverPt);  
00073     tmvaReader_->AddVariable("track_pt", &track_pt);  
00074     tmvaReader_->AddVariable("STIP",&STIP);  
00075     tmvaReader_->AddVariable("nlost", &nlost);  
00076     tmvaReader_->BookMVA("BDT",mvaweightfile.c_str());  
00077 
00078     //Material Map
00079     TFile *XO_File = new TFile(X0_Map.c_str(),"READ");
00080     X0_sum=(TH2D*)XO_File->Get("TrackerSum");
00081     X0_inner = (TH2D*)XO_File->Get("Inner");
00082     X0_middle = (TH2D*)XO_File->Get("Middle");
00083     X0_outer = (TH2D*)XO_File->Get("Outer");
00084     
00085 }
00086 
00087 void PFPhotonAlgo::RunPFPhoton(const reco::PFBlockRef&  blockRef,
00088                                std::vector<bool>& active,
00089                                std::auto_ptr<PFCandidateCollection> &pfCandidates,
00090                                std::vector<reco::PFCandidatePhotonExtra>& pfPhotonExtraCandidates,
00091                                std::vector<reco::PFCandidate> 
00092                                &tempElectronCandidates
00093 ){
00094   
00095   //std::cout<<" calling RunPFPhoton "<<std::endl;
00096   
00097   /*      For now we construct the PhotonCandidate simply from 
00098           a) adding the CORRECTED energies of each participating ECAL cluster
00099           b) build the energy-weighted direction for the Photon
00100   */
00101 
00102 
00103   // define how much is printed out for debugging.
00104   // ... will be setable via CFG file parameter
00105   verbosityLevel_ = Chatty;          // Chatty mode.
00106   
00107 
00108   // loop over all elements in the Block
00109   const edm::OwnVector< reco::PFBlockElement >&          elements         = blockRef->elements();
00110   edm::OwnVector< reco::PFBlockElement >::const_iterator ele              = elements.begin();
00111   std::vector<bool>::const_iterator                      actIter          = active.begin();
00112   PFBlock::LinkData                                      linkData         = blockRef->linkData();
00113   bool                                                   isActive         = true;
00114 
00115 
00116   if(elements.size() != active.size()) {
00117     // throw excpetion...
00118     //std::cout<<" WARNING: Size of collection and active-vectro don't agree!"<<std::endl;
00119     return;
00120   }
00121   
00122   // local vecotr to keep track of the indices of the 'elements' for the Photon candidate
00123   // once we decide to keep the candidate, the 'active' entriesd for them must be set to false
00124   std::vector<unsigned int> elemsToLock;
00125   elemsToLock.resize(0);
00126   
00127   for( ; ele != elements.end(); ++ele, ++actIter ) {
00128 
00129     // if it's not a SuperCluster, go to the next element
00130     if( !( ele->type() == reco::PFBlockElement::SC ) ) continue;
00131     
00132     // Photon kienmatics, will be updated for each identified participating element
00133     float photonEnergy_        =   0.;
00134     float photonX_             =   0.;
00135     float photonY_             =   0.;
00136     float photonZ_             =   0.;
00137     float RawEcalEne           =   0.;
00138 
00139     // Total pre-shower energy
00140     float ps1TotEne      = 0.;
00141     float ps2TotEne      = 0.;
00142     
00143     bool hasConvTrack=false;  
00144     bool hasSingleleg=false;  
00145     std::vector<unsigned int> AddClusters(0);  
00146     std::vector<unsigned int> IsoTracks(0);  
00147     std::multimap<unsigned int, unsigned int>ClusterAddPS1;  
00148     std::multimap<unsigned int, unsigned int>ClusterAddPS2;
00149     std::vector<reco::TrackRef>singleLegRef;
00150     std::vector<float>MVA_values(0);
00151     std::vector<float>MVALCorr;
00152     std::vector<CaloCluster>PFClusters;
00153     reco::ConversionRefVector ConversionsRef_;
00154     isActive = *(actIter);
00155     //cout << " Found a SuperCluster.  Energy " ;
00156     const reco::PFBlockElementSuperCluster *sc = dynamic_cast<const reco::PFBlockElementSuperCluster*>(&(*ele));
00157     //std::cout << sc->superClusterRef()->energy () << " Track/Ecal/Hcal Iso " << sc->trackIso()<< " " << sc->ecalIso() ;
00158     //std::cout << " " << sc->hcalIso() <<std::endl;
00159     if (!(sc->fromPhoton()))continue;
00160     
00161     // check the status of the SC Element... 
00162     // ..... I understand it should *always* be active, since PFElectronAlgo does not touch this (yet?) RISHI: YES
00163     if( !isActive ) {
00164       //std::cout<<" SuperCluster is NOT active.... "<<std::endl;
00165       continue;
00166     }
00167     elemsToLock.push_back(ele-elements.begin()); //add SC to elements to lock
00168     // loop over its constituent ECAL cluster
00169     std::multimap<double, unsigned int> ecalAssoPFClusters;
00170     blockRef->associatedElements( ele-elements.begin(), 
00171                                   linkData,
00172                                   ecalAssoPFClusters,
00173                                   reco::PFBlockElement::ECAL,
00174                                   reco::PFBlock::LINKTEST_ALL );
00175     //R9 of SuperCluster and RawE
00176     PFPhoR9_=sc->photonRef()->r9();
00177     E3x3_=PFPhoR9_*(sc->superClusterRef()->rawEnergy());
00178     // loop over the ECAL clusters linked to the iEle 
00179     if( ! ecalAssoPFClusters.size() ) {
00180       // This SC element has NO ECAL elements asigned... *SHOULD NOT HAPPEN*
00181       //std::cout<<" Found SC element with no ECAL assigned "<<std::endl;
00182       continue;
00183     }
00184     
00185     // This is basically CASE 2
00186     // .... we loop over all ECAL cluster linked to each other by this SC
00187     for(std::multimap<double, unsigned int>::iterator itecal = ecalAssoPFClusters.begin(); 
00188         itecal != ecalAssoPFClusters.end(); ++itecal) { 
00189       
00190       // to get the reference to the PF clusters, this is needed.
00191       reco::PFClusterRef clusterRef = elements[itecal->second].clusterRef();    
00192       
00193       // from the clusterRef get the energy, direction, etc
00194       //      float ClustRawEnergy = clusterRef->energy();
00195       //      float ClustEta = clusterRef->position().eta();
00196       //      float ClustPhi = clusterRef->position().phi();
00197       
00198       // initialize the vectors for the PS energies
00199       vector<double> ps1Ene(0);
00200       vector<double> ps2Ene(0);
00201       double ps1=0;  
00202       double ps2=0;  
00203       hasSingleleg=false;  
00204       hasConvTrack=false;
00205       
00206       /*
00207         cout << " My cluster index " << itecal->second 
00208         << " energy " <<  ClustRawEnergy
00209            << " eta " << ClustEta
00210            << " phi " << ClustPhi << endl;
00211       */
00212       // check if this ECAL element is still active (could have been eaten by PFElectronAlgo)
00213       // ......for now we give the PFElectron Algo *ALWAYS* Shot-Gun on the ECAL elements to the PFElectronAlgo
00214       
00215       if( !( active[itecal->second] ) ) {
00216         //std::cout<< "  .... this ECAL element is NOT active anymore. Is skipped. "<<std::endl;
00217         continue;
00218       }
00219       
00220       // ------------------------------------------------------------------------------------------
00221       // TODO: do some tests on the ECAL cluster itself, deciding to use it or not for the Photons
00222       // ..... ??? Do we need this?
00223       if ( false ) {
00224         // Check if there are a large number tracks that do not pass pre-ID around this ECAL cluster
00225         bool useIt = true;
00226         int mva_reject=0;  
00227         bool isClosest=false;  
00228         std::multimap<double, unsigned int> Trackscheck;  
00229         blockRef->associatedElements( itecal->second,  
00230                                       linkData,  
00231                                       Trackscheck,  
00232                                       reco::PFBlockElement::TRACK,  
00233                                       reco::PFBlock::LINKTEST_ALL);  
00234         for(std::multimap<double, unsigned int>::iterator track = Trackscheck.begin();  
00235             track != Trackscheck.end(); ++track) {  
00236            
00237           // first check if is it's still active  
00238           if( ! (active[track->second]) ) continue;  
00239           hasSingleleg=EvaluateSingleLegMVA(blockRef,  *primaryVertex_, track->second);  
00240           //check if it is the closest linked track  
00241           std::multimap<double, unsigned int> closecheck;  
00242           blockRef->associatedElements(track->second,  
00243                                        linkData,  
00244                                        closecheck,  
00245                                        reco::PFBlockElement::ECAL,  
00246                                        reco::PFBlock::LINKTEST_ALL);  
00247           if(closecheck.begin()->second ==itecal->second)isClosest=true;  
00248           if(!hasSingleleg)mva_reject++;  
00249         }  
00250         
00251         if(mva_reject>0 &&  isClosest)useIt=false;  
00252         //if(mva_reject==1 && isClosest)useIt=false;
00253         if( !useIt ) continue;    // Go to next ECAL cluster within SC
00254       }
00255       // ------------------------------------------------------------------------------------------
00256       
00257       // We decided to keep the ECAL cluster for this Photon Candidate ...
00258       elemsToLock.push_back(itecal->second);
00259       
00260       // look for PS in this Block linked to this ECAL cluster      
00261       std::multimap<double, unsigned int> PS1Elems;
00262       std::multimap<double, unsigned int> PS2Elems;
00263       //PS Layer 1 linked to ECAL cluster
00264       blockRef->associatedElements( itecal->second,
00265                                     linkData,
00266                                     PS1Elems,
00267                                     reco::PFBlockElement::PS1,
00268                                     reco::PFBlock::LINKTEST_ALL );
00269       //PS Layer 2 linked to the ECAL cluster
00270       blockRef->associatedElements( itecal->second,
00271                                     linkData,
00272                                     PS2Elems,
00273                                     reco::PFBlockElement::PS2,
00274                                     reco::PFBlock::LINKTEST_ALL );
00275       
00276       // loop over all PS1 and compute energy
00277       for(std::multimap<double, unsigned int>::iterator iteps = PS1Elems.begin();
00278           iteps != PS1Elems.end(); ++iteps) {
00279 
00280         // first chekc if it's still active
00281         if( !(active[iteps->second]) ) continue;
00282         
00283         //Check if this PS1 is not closer to another ECAL cluster in this Block          
00284         std::multimap<double, unsigned int> ECALPS1check;  
00285         blockRef->associatedElements( iteps->second,  
00286                                       linkData,  
00287                                       ECALPS1check,  
00288                                       reco::PFBlockElement::ECAL,  
00289                                       reco::PFBlock::LINKTEST_ALL );  
00290         if(itecal->second==ECALPS1check.begin()->second)//then it is closest linked  
00291           {
00292             reco::PFClusterRef ps1ClusterRef = elements[iteps->second].clusterRef();
00293             ps1Ene.push_back( ps1ClusterRef->energy() );
00294             ps1=ps1+ps1ClusterRef->energy(); //add to total PS1
00295             // incativate this PS1 Element
00296             elemsToLock.push_back(iteps->second);
00297           }
00298       }
00299       for(std::multimap<double, unsigned int>::iterator iteps = PS2Elems.begin();
00300           iteps != PS2Elems.end(); ++iteps) {
00301 
00302         // first chekc if it's still active
00303         if( !(active[iteps->second]) ) continue;
00304         
00305         // Check if this PS2 is not closer to another ECAL cluster in this Block:
00306         std::multimap<double, unsigned int> ECALPS2check;  
00307         blockRef->associatedElements( iteps->second,  
00308                                       linkData,  
00309                                       ECALPS2check,  
00310                                       reco::PFBlockElement::ECAL,  
00311                                       reco::PFBlock::LINKTEST_ALL );  
00312         if(itecal->second==ECALPS2check.begin()->second)//is closest linked  
00313           {
00314             reco::PFClusterRef ps2ClusterRef = elements[iteps->second].clusterRef();
00315             ps2Ene.push_back( ps2ClusterRef->energy() );
00316             ps2=ps2ClusterRef->energy()+ps2; //add to total PS2
00317             // incativate this PS2 Element
00318             elemsToLock.push_back(iteps->second);
00319           }
00320       }
00321             
00322       // loop over the HCAL Clusters linked to the ECAL cluster (CASE 6)
00323       std::multimap<double, unsigned int> hcalElems;
00324       blockRef->associatedElements( itecal->second,linkData,
00325                                     hcalElems,
00326                                     reco::PFBlockElement::HCAL,
00327                                     reco::PFBlock::LINKTEST_ALL );
00328 
00329       for(std::multimap<double, unsigned int>::iterator ithcal = hcalElems.begin();
00330           ithcal != hcalElems.end(); ++ithcal) {
00331 
00332         if ( ! (active[ithcal->second] ) ) continue; // HCAL Cluster already used....
00333         
00334         // TODO: Decide if this HCAL cluster is to be used
00335         // .... based on some Physics
00336         // .... To we need to check if it's closer to any other ECAL/TRACK?
00337 
00338         bool useHcal = false;
00339         if ( !useHcal ) continue;
00340         //not locked
00341         //elemsToLock.push_back(ithcal->second);
00342       }
00343 
00344       // This is entry point for CASE 3.
00345       // .... we loop over all Tracks linked to this ECAL and check if it's labeled as conversion
00346       // This is the part for looping over all 'Conversion' Tracks
00347       std::multimap<double, unsigned int> convTracks;
00348       blockRef->associatedElements( itecal->second,
00349                                     linkData,
00350                                     convTracks,
00351                                     reco::PFBlockElement::TRACK,
00352                                     reco::PFBlock::LINKTEST_ALL);
00353       for(std::multimap<double, unsigned int>::iterator track = convTracks.begin();
00354           track != convTracks.end(); ++track) {
00355 
00356         // first check if is it's still active
00357         if( ! (active[track->second]) ) continue;
00358         
00359         // check if it's a CONV track
00360         const reco::PFBlockElementTrack * trackRef = dynamic_cast<const reco::PFBlockElementTrack*>((&elements[track->second]));        
00361         
00362         //Check if track is a Single leg from a Conversion  
00363         mvaValue=-999;  
00364         hasSingleleg=EvaluateSingleLegMVA(blockRef,  *primaryVertex_, track->second);  
00365 
00366         // Daniele; example for mvaValues, do the same for single leg trackRef and convRef
00367         //          
00368         //      if(hasSingleleg)
00369         //        mvaValues.push_back(mvaValue);
00370 
00371         //If it is not then it will be used to check Track Isolation at the end  
00372         if(!hasSingleleg)  
00373           {  
00374             bool included=false;  
00375             //check if this track is already included in the vector so it is linked to an ECAL cluster that is already examined  
00376             for(unsigned int i=0; i<IsoTracks.size(); i++)  
00377               {if(IsoTracks[i]==track->second)included=true;}  
00378             if(!included)IsoTracks.push_back(track->second);  
00379           }  
00380         //For now only Pre-ID tracks that are not already identified as Conversions  
00381         if(hasSingleleg &&!(trackRef->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)))  
00382           {  
00383             elemsToLock.push_back(track->second);
00384             
00385             reco::TrackRef t_ref=elements[track->second].trackRef();
00386             bool matched=false;
00387             for(unsigned int ic=0; ic<singleLegRef.size(); ic++)
00388               if(singleLegRef[ic]==t_ref)matched=true;
00389             
00390             if(!matched){
00391               singleLegRef.push_back(t_ref);
00392               MVA_values.push_back(mvaValue);
00393             }
00394             //find all the clusters linked to this track  
00395             std::multimap<double, unsigned int> moreClusters;  
00396             blockRef->associatedElements( track->second,  
00397                                           linkData,  
00398                                           moreClusters,  
00399                                           reco::PFBlockElement::ECAL,  
00400                                           reco::PFBlock::LINKTEST_ALL);  
00401              
00402             float p_in=sqrt(elements[track->second].trackRef()->innerMomentum().x() * elements[track->second].trackRef()->innerMomentum().x() +  
00403                             elements[track->second].trackRef()->innerMomentum().y()*elements[track->second].trackRef()->innerMomentum().y()+  
00404                             elements[track->second].trackRef()->innerMomentum().z()*elements[track->second].trackRef()->innerMomentum().z());  
00405             float linked_E=0;  
00406             for(std::multimap<double, unsigned int>::iterator clust = moreClusters.begin();  
00407                 clust != moreClusters.end(); ++clust)  
00408               {  
00409                 if(!active[clust->second])continue;  
00410                 //running sum of linked energy  
00411                 linked_E=linked_E+elements[clust->second].clusterRef()->energy();  
00412                 //prevent too much energy from being added  
00413                 if(linked_E/p_in>1.5)break;  
00414                 bool included=false;  
00415                 //check if these ecal clusters are already included with the supercluster  
00416                 for(std::multimap<double, unsigned int>::iterator cluscheck = ecalAssoPFClusters.begin();  
00417                     cluscheck != ecalAssoPFClusters.end(); ++cluscheck)  
00418                   {  
00419                     if(cluscheck->second==clust->second)included=true;  
00420                   }  
00421                 if(!included)AddClusters.push_back(clust->second);//Add to a container of clusters to be Added to the Photon candidate  
00422               }  
00423           }
00424 
00425         // Possibly need to be more smart about them (CASE 5)
00426         // .... for now we simply skip non id'ed tracks
00427         if( ! (trackRef->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) ) ) continue;  
00428         hasConvTrack=true;  
00429         elemsToLock.push_back(track->second);
00430         //again look at the clusters linked to this track  
00431         //if(elements[track->second].convRef().isNonnull())
00432         //{         
00433         //  ConversionsRef_.push_back(elements[track->second].convRef());
00434         //}
00435         std::multimap<double, unsigned int> moreClusters;  
00436         blockRef->associatedElements( track->second,  
00437                                       linkData,  
00438                                       moreClusters,  
00439                                       reco::PFBlockElement::ECAL,  
00440                                       reco::PFBlock::LINKTEST_ALL);
00441         
00442         float p_in=sqrt(elements[track->second].trackRef()->innerMomentum().x() * elements[track->second].trackRef()->innerMomentum().x() +  
00443                         elements[track->second].trackRef()->innerMomentum().y()*elements[track->second].trackRef()->innerMomentum().y()+  
00444                         elements[track->second].trackRef()->innerMomentum().z()*elements[track->second].trackRef()->innerMomentum().z());  
00445         float linked_E=0;  
00446         for(std::multimap<double, unsigned int>::iterator clust = moreClusters.begin();  
00447             clust != moreClusters.end(); ++clust)  
00448           {  
00449             if(!active[clust->second])continue;  
00450             linked_E=linked_E+elements[clust->second].clusterRef()->energy();  
00451             if(linked_E/p_in>1.5)break;  
00452             bool included=false;  
00453             for(std::multimap<double, unsigned int>::iterator cluscheck = ecalAssoPFClusters.begin();  
00454                 cluscheck != ecalAssoPFClusters.end(); ++cluscheck)  
00455               {  
00456                 if(cluscheck->second==clust->second)included=true;  
00457               }  
00458             if(!included)AddClusters.push_back(clust->second);//again only add if it is not already included with the supercluster  
00459           }
00460         
00461         // we need to check for other TRACKS linked to this conversion track, that point possibly no an ECAL cluster not included in the SC
00462         // .... This is basically CASE 4.
00463         
00464         std::multimap<double, unsigned int> moreTracks;
00465         blockRef->associatedElements( track->second,
00466                                       linkData,
00467                                       moreTracks,
00468                                       reco::PFBlockElement::TRACK,
00469                                       reco::PFBlock::LINKTEST_ALL);
00470         
00471         for(std::multimap<double, unsigned int>::iterator track2 = moreTracks.begin();
00472             track2 != moreTracks.end(); ++track2) {
00473           
00474           // first check if is it's still active
00475           if( ! (active[track2->second]) ) continue;
00476           //skip over the 1st leg already found above  
00477           if(track->second==track2->second)continue;      
00478           // check if it's a CONV track
00479           const reco::PFBlockElementTrack * track2Ref = dynamic_cast<const reco::PFBlockElementTrack*>((&elements[track2->second]));    
00480           if( ! (track2Ref->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) ) ) continue;  // Possibly need to be more smart about them (CASE 5)
00481           elemsToLock.push_back(track2->second);
00482           // so it's another active conversion track, that is in the Block and linked to the conversion track we already found
00483           // find the ECAL cluster linked to it...
00484           std::multimap<double, unsigned int> convEcal;
00485           blockRef->associatedElements( track2->second,
00486                                         linkData,
00487                                         convEcal,
00488                                         reco::PFBlockElement::ECAL,
00489                                         reco::PFBlock::LINKTEST_ALL);
00490           float p_in=sqrt(elements[track->second].trackRef()->innerMomentum().x()*elements[track->second].trackRef()->innerMomentum().x()+
00491                           elements[track->second].trackRef()->innerMomentum().y()*elements[track->second].trackRef()->innerMomentum().y()+  
00492                           elements[track->second].trackRef()->innerMomentum().z()*elements[track->second].trackRef()->innerMomentum().z());  
00493           
00494           
00495           float linked_E=0;
00496           for(std::multimap<double, unsigned int>::iterator itConvEcal = convEcal.begin();
00497               itConvEcal != convEcal.end(); ++itConvEcal) {
00498             
00499             if( ! (active[itConvEcal->second]) ) continue;
00500             bool included=false;  
00501             for(std::multimap<double, unsigned int>::iterator cluscheck = ecalAssoPFClusters.begin();  
00502                 cluscheck != ecalAssoPFClusters.end(); ++cluscheck)  
00503               {  
00504                 if(cluscheck->second==itConvEcal->second)included=true;  
00505               }
00506             linked_E=linked_E+elements[itConvEcal->second].clusterRef()->energy();
00507             if(linked_E/p_in>1.5)break;
00508             if(!included){AddClusters.push_back(itConvEcal->second);
00509             }
00510             
00511             // it's still active, so we have to add it.
00512             // CAUTION: we don't care here if it's part of the SC or not, we include it anyways
00513             
00514             // loop over the HCAL Clusters linked to the ECAL cluster (CASE 6)
00515             std::multimap<double, unsigned int> hcalElems_conv;
00516             blockRef->associatedElements( itecal->second,linkData,
00517                                           hcalElems_conv,
00518                                           reco::PFBlockElement::HCAL,
00519                                           reco::PFBlock::LINKTEST_ALL );
00520             
00521             for(std::multimap<double, unsigned int>::iterator ithcal2 = hcalElems_conv.begin();
00522                 ithcal2 != hcalElems_conv.end(); ++ithcal2) {
00523               
00524               if ( ! (active[ithcal2->second] ) ) continue; // HCAL Cluster already used....
00525               
00526               // TODO: Decide if this HCAL cluster is to be used
00527               // .... based on some Physics
00528               // .... To we need to check if it's closer to any other ECAL/TRACK?
00529               
00530               bool useHcal = true;
00531               if ( !useHcal ) continue;
00532               
00533               //elemsToLock.push_back(ithcal2->second);
00534 
00535             } // end of loop over HCAL clusters linked to the ECAL cluster from second CONVERSION leg
00536             
00537           } // end of loop over ECALs linked to second T_FROM_GAMMACONV
00538           
00539         } // end of loop over SECOND conversion leg
00540 
00541         // TODO: Do we need to check separatly if there are HCAL cluster linked to the track?
00542         
00543       } // end of loop over tracks
00544       
00545             
00546       // Calibrate the Added ECAL energy
00547       float addedCalibEne=0;
00548       float addedRawEne=0;
00549       std::vector<double>AddedPS1(0);
00550       std::vector<double>AddedPS2(0);  
00551       double addedps1=0;  
00552       double addedps2=0;  
00553       for(unsigned int i=0; i<AddClusters.size(); i++)  
00554         {  
00555           std::multimap<double, unsigned int> PS1Elems_conv;  
00556           std::multimap<double, unsigned int> PS2Elems_conv;  
00557           blockRef->associatedElements(AddClusters[i],  
00558                                        linkData,  
00559                                        PS1Elems_conv,  
00560                                        reco::PFBlockElement::PS1,  
00561                                        reco::PFBlock::LINKTEST_ALL );  
00562           blockRef->associatedElements( AddClusters[i],  
00563                                         linkData,  
00564                                         PS2Elems_conv,  
00565                                         reco::PFBlockElement::PS2,  
00566                                         reco::PFBlock::LINKTEST_ALL );  
00567            
00568           for(std::multimap<double, unsigned int>::iterator iteps = PS1Elems_conv.begin();  
00569               iteps != PS1Elems_conv.end(); ++iteps)  
00570             {  
00571               if(!active[iteps->second])continue;  
00572               std::multimap<double, unsigned int> PS1Elems_check;  
00573               blockRef->associatedElements(iteps->second,  
00574                                            linkData,  
00575                                            PS1Elems_check,  
00576                                            reco::PFBlockElement::ECAL,  
00577                                            reco::PFBlock::LINKTEST_ALL );  
00578               if(PS1Elems_check.begin()->second==AddClusters[i])  
00579                 {  
00580                    
00581                   reco::PFClusterRef ps1ClusterRef = elements[iteps->second].clusterRef();  
00582                   AddedPS1.push_back(ps1ClusterRef->energy());  
00583                   addedps1=addedps1+ps1ClusterRef->energy();  
00584                   elemsToLock.push_back(iteps->second);  
00585                 }  
00586             }  
00587            
00588           for(std::multimap<double, unsigned int>::iterator iteps = PS2Elems_conv.begin();  
00589               iteps != PS2Elems_conv.end(); ++iteps) {  
00590             if(!active[iteps->second])continue;  
00591             std::multimap<double, unsigned int> PS2Elems_check;  
00592             blockRef->associatedElements(iteps->second,  
00593                                          linkData,  
00594                                          PS2Elems_check,  
00595                                          reco::PFBlockElement::ECAL,  
00596                                          reco::PFBlock::LINKTEST_ALL );  
00597              
00598             if(PS2Elems_check.begin()->second==AddClusters[i])  
00599               {  
00600                 reco::PFClusterRef ps2ClusterRef = elements[iteps->second].clusterRef();  
00601                 AddedPS2.push_back(ps2ClusterRef->energy());  
00602                 addedps2=addedps2+ps2ClusterRef->energy();  
00603                 elemsToLock.push_back(iteps->second);  
00604               }  
00605           }  
00606           reco::PFClusterRef AddclusterRef = elements[AddClusters[i]].clusterRef();  
00607           addedRawEne = AddclusterRef->energy()+addedRawEne;  
00608           addedCalibEne = thePFEnergyCalibration_->energyEm(*AddclusterRef,AddedPS1,AddedPS2,false)+addedCalibEne;  
00609           AddedPS2.clear(); 
00610           AddedPS1.clear();  
00611           elemsToLock.push_back(AddClusters[i]);  
00612         }  
00613       AddClusters.clear();
00614       float EE=thePFEnergyCalibration_->energyEm(*clusterRef,ps1Ene,ps2Ene,false)+addedCalibEne;
00615       PFClusters.push_back(*clusterRef);
00616       if(useReg_){
00617         float LocCorr=EvaluateLCorrMVA(clusterRef);
00618         EE=LocCorr*clusterRef->energy()+addedCalibEne;
00619       }
00620       else{
00621         float LocCorr=EvaluateLCorrMVA(clusterRef);
00622         MVALCorr.push_back(LocCorr*clusterRef->energy());
00623       }
00624       
00625       //cout<<"Original Energy "<<EE<<"Added Energy "<<addedCalibEne<<endl;
00626       
00627       photonEnergy_ +=  EE;
00628       RawEcalEne    +=  clusterRef->energy()+addedRawEne;
00629       photonX_      +=  EE * clusterRef->position().X();
00630       photonY_      +=  EE * clusterRef->position().Y();
00631       photonZ_      +=  EE * clusterRef->position().Z();                
00632       ps1TotEne     +=  ps1+addedps1;
00633       ps2TotEne     +=  ps2+addedps2;
00634     } // end of loop over all ECAL cluster within this SC
00635     AddFromElectron_.clear();
00636     float Elec_energy=0;
00637     float Elec_rawEcal=0;
00638     float Elec_totPs1=0;
00639     float Elec_totPs2=0;
00640     float ElectronX=0;
00641     float ElectronY=0;
00642     float ElectronZ=0;  
00643     std::vector<double>AddedPS1(0);
00644     std::vector<double>AddedPS2(0);
00645     
00646     EarlyConversion(    
00647                     tempElectronCandidates,
00648                     sc
00649                     );   
00650     
00651     if(AddFromElectron_.size()>0)
00652       { 
00653         //collect elements from early Conversions that are reconstructed as Electrons
00654         
00655         for(std::vector<unsigned int>::const_iterator it = 
00656               AddFromElectron_.begin();
00657             it != AddFromElectron_.end(); ++it)
00658           {
00659             
00660             if(elements[*it].type()== reco::PFBlockElement::ECAL)
00661               {
00662                 //cout<<"Cluster ind "<<*it<<endl;
00663                 AddedPS1.clear();
00664                 AddedPS2.clear();
00665                 unsigned int index=*it;
00666                 reco::PFClusterRef clusterRef = 
00667                 elements[index].clusterRef();
00668                 //match to PS1 and PS2 to this cluster for calibration
00669                 Elec_rawEcal=Elec_rawEcal+
00670                   elements[index].clusterRef()->energy();
00671                 std::multimap<double, unsigned int> PS1Elems;  
00672                 std::multimap<double, unsigned int> PS2Elems;  
00673                 
00674                 blockRef->associatedElements(index,  
00675                                              linkData,  
00676                                              PS1Elems,                                               reco::PFBlockElement::PS1,  
00677                                              reco::PFBlock::LINKTEST_ALL );  
00678                 blockRef->associatedElements( index,  
00679                                               linkData,  
00680                                               PS2Elems,  
00681                                               reco::PFBlockElement::PS2,  
00682                                               reco::PFBlock::LINKTEST_ALL );
00683                 
00684                 
00685                 for(std::multimap<double, unsigned int>::iterator iteps = 
00686                       PS1Elems.begin();  
00687                     iteps != PS1Elems.end(); ++iteps) 
00688                   {  
00689                     std::multimap<double, unsigned int> Clustcheck;                         blockRef->associatedElements( iteps->second,                                                                   linkData,  
00690                                                                                                                           Clustcheck,  
00691                                                                                                                           reco::PFBlockElement::ECAL,  
00692                                                                                                                           reco::PFBlock::LINKTEST_ALL );
00693                     if(Clustcheck.begin()->second==index)
00694                       {
00695                         AddedPS1.push_back(elements[iteps->second].clusterRef()->energy());
00696                         Elec_totPs1=Elec_totPs1+elements[iteps->second].clusterRef()->energy();
00697                       }
00698                   }
00699                 
00700                 for(std::multimap<double, unsigned int>::iterator iteps = 
00701                       PS2Elems.begin();  
00702                     iteps != PS2Elems.end(); ++iteps) 
00703                   {  
00704                     std::multimap<double, unsigned int> Clustcheck;                         blockRef->associatedElements( iteps->second,                                                                   linkData,  
00705                                                                                                                           Clustcheck,  
00706                                                                                                                           reco::PFBlockElement::ECAL,  
00707                                                                                                                           reco::PFBlock::LINKTEST_ALL );
00708                     if(Clustcheck.begin()->second==index)
00709                       {
00710                         AddedPS2.push_back(elements[iteps->second].clusterRef()->energy());
00711                         Elec_totPs2=Elec_totPs2+elements[iteps->second].clusterRef()->energy();
00712                       }
00713                   }
00714                 
00715                 //energy calibration 
00716                 float EE=thePFEnergyCalibration_->
00717                   energyEm(*clusterRef,AddedPS1,AddedPS2,false);
00718                 PFClusters.push_back(*clusterRef);
00719                 if(useReg_){
00720                   float LocCorr=EvaluateLCorrMVA(clusterRef);
00721                   EE=LocCorr*clusterRef->energy();        
00722                   MVALCorr.push_back(LocCorr*clusterRef->energy());
00723                   
00724                 }
00725                 else{
00726                   float LocCorr=EvaluateLCorrMVA(clusterRef);
00727                   MVALCorr.push_back(LocCorr*clusterRef->energy());
00728                 }
00729                 
00730                 Elec_energy    += EE;
00731                 ElectronX      +=  EE * clusterRef->position().X();
00732                 ElectronY      +=  EE * clusterRef->position().Y();
00733                 ElectronZ      +=  EE * clusterRef->position().Z();
00734                 
00735               }
00736             if(elements[*it].type()==reco::PFBlockElement::TRACK){
00737               reco::TrackRef t_ref=elements[*it].trackRef();
00738               singleLegRef.push_back(t_ref);
00739               EvaluateSingleLegMVA(blockRef,  *primaryVertex_, *it);  
00740               MVA_values.push_back(mvaValue);         
00741             }
00742           }
00743         
00744       }
00745     
00746     //std::cout<<"Added Energy to Photon "<<Elec_energy<<" to "<<photonEnergy_<<std::endl;   
00747     photonEnergy_ +=  Elec_energy;
00748     RawEcalEne    +=  Elec_rawEcal;
00749     photonX_      +=  ElectronX;
00750     photonY_      +=  ElectronY;
00751     photonZ_      +=  ElectronZ;                
00752     ps1TotEne     +=  Elec_totPs1;
00753     ps2TotEne     +=  Elec_totPs2;
00754     
00755     // we've looped over all ECAL clusters, ready to generate PhotonCandidate
00756     if( ! (photonEnergy_ > 0.) ) continue;    // This SC is not a Photon Candidate
00757     float sum_track_pt=0;
00758     //Now check if there are tracks failing isolation outside of the Jurassic isolation region  
00759     for(unsigned int i=0; i<IsoTracks.size(); i++)sum_track_pt=sum_track_pt+elements[IsoTracks[i]].trackRef()->pt();  
00760     
00761 
00762 
00763     math::XYZVector photonPosition(photonX_,
00764                                    photonY_,
00765                                    photonZ_);
00766     math::XYZVector photonPositionwrtVtx(
00767                                          photonX_- primaryVertex_->x(),
00768                                          photonY_-primaryVertex_->y(),
00769                                          photonZ_-primaryVertex_->z()
00770                                          );
00771     math::XYZVector photonDirection=photonPositionwrtVtx.Unit();
00772     
00773     math::XYZTLorentzVector photonMomentum(photonEnergy_* photonDirection.X(),
00774                                            photonEnergy_* photonDirection.Y(),
00775                                            photonEnergy_* photonDirection.Z(),
00776                                            photonEnergy_           );
00777 
00778     if(sum_track_pt>(sumPtTrackIsoForPhoton_ + sumPtTrackIsoSlopeForPhoton_ * photonMomentum.pt()) && AddFromElectron_.size()==0)
00779       {
00780         elemsToLock.resize(0);
00781         continue;
00782         
00783       }
00784 
00785         //THIS SC is not a Photon it fails track Isolation
00786     //if(sum_track_pt>(2+ 0.001* photonMomentum.pt()))
00787     //continue;//THIS SC is not a Photon it fails track Isolation
00788 
00789     /*
00790     std::cout<<" Created Photon with energy = "<<photonEnergy_<<std::endl;
00791     std::cout<<"                         pT = "<<photonMomentum.pt()<<std::endl;
00792     std::cout<<"                     RawEne = "<<RawEcalEne<<std::endl;
00793     std::cout<<"                          E = "<<photonMomentum.e()<<std::endl;
00794     std::cout<<"                        eta = "<<photonMomentum.eta()<<std::endl;
00795     std::cout<<"             TrackIsolation = "<< sum_track_pt <<std::endl;
00796     */
00797 
00798     reco::PFCandidate photonCand(0,photonMomentum, reco::PFCandidate::gamma);
00799     photonCand.setPs1Energy(ps1TotEne);
00800     photonCand.setPs2Energy(ps2TotEne);
00801     photonCand.setEcalEnergy(RawEcalEne,photonEnergy_);
00802     photonCand.setHcalEnergy(0.,0.);
00803     photonCand.set_mva_nothing_gamma(1.);  
00804     photonCand.setSuperClusterRef(sc->superClusterRef());
00805     math::XYZPoint v(primaryVertex_->x(), primaryVertex_->y(), primaryVertex_->z());
00806     photonCand.setVertex( v  );
00807     if(hasConvTrack || hasSingleleg)photonCand.setFlag( reco::PFCandidate::GAMMA_TO_GAMMACONV, true);
00808     int matches=match_ind.size();
00809     int count=0;
00810     for ( std::vector<reco::PFCandidate>::const_iterator ec=tempElectronCandidates.begin();   ec != tempElectronCandidates.end(); ++ec ){
00811       for(int i=0; i<matches; i++)
00812         {
00813           if(count==match_ind[i])photonCand.addDaughter(*ec);
00814           count++;
00815         }
00816     }
00817     // set isvalid_ to TRUE since we've found at least one photon candidate
00818     isvalid_ = true;
00819     // push back the candidate into the collection ...
00820     //Add Elements from Electron
00821     for(std::vector<unsigned int>::const_iterator it = 
00822           AddFromElectron_.begin();
00823         it != AddFromElectron_.end(); ++it)photonCand.addElementInBlock(blockRef,*it);
00824     
00825     // ... and lock all elemts used
00826     for(std::vector<unsigned int>::const_iterator it = elemsToLock.begin();
00827         it != elemsToLock.end(); ++it)
00828       {
00829         if(active[*it])
00830           {
00831             photonCand.addElementInBlock(blockRef,*it);
00832             if( elements[*it].type() == reco::PFBlockElement::TRACK  )
00833               {
00834                 if(elements[*it].convRef().isNonnull())
00835                   {
00836                     //make sure it is not stored already as the partner track
00837                     bool matched=false;
00838                     for(unsigned int ic = 0; ic < ConversionsRef_.size(); ic++)
00839                       {
00840                         if(ConversionsRef_[ic]==elements[*it].convRef())matched=true;
00841                       }
00842                     if(!matched)ConversionsRef_.push_back(elements[*it].convRef());
00843                   }
00844               }
00845           }
00846         active[*it] = false;    
00847       }
00848     PFPhoECorr_=0;
00849     // here add the extra information
00850     PFCandidatePhotonExtra myExtra(sc->superClusterRef());
00851     //Store Locally Contained PF Cluster regressed energy
00852     for(unsigned int l=0; l<MVALCorr.size(); ++l)
00853       {
00854         myExtra.addLCorrClusEnergy(MVALCorr[l]);
00855         PFPhoECorr_=PFPhoECorr_+MVALCorr[l];//total Locally corrected energy
00856       }
00857     TotPS1_=ps1TotEne;
00858     TotPS2_=ps2TotEne;
00859     //Do Global Corrections here:
00860     float GCorr=EvaluateGCorrMVA(photonCand, PFClusters);
00861     if(useReg_){
00862       math::XYZTLorentzVector photonCorrMomentum(GCorr*PFPhoECorr_* photonDirection.X(),
00863                                                  GCorr*PFPhoECorr_* photonDirection.Y(),
00864                                                  GCorr*PFPhoECorr_* photonDirection.Z(),
00865                                                  GCorr * photonEnergy_           );
00866       photonCand.setP4(photonCorrMomentum);
00867     }
00868     
00869     std::multimap<float, unsigned int>OrderedClust;
00870     for(unsigned int i=0; i<PFClusters.size(); ++i){  
00871       float et=PFClusters[i].energy()*sin(PFClusters[i].position().theta());
00872       OrderedClust.insert(make_pair(et, i));
00873     }
00874     std::multimap<float, unsigned int>::reverse_iterator rit;
00875     rit=OrderedClust.rbegin();
00876     unsigned int highEindex=(*rit).second;
00877     //store Position at ECAL Entrance as Position of Max Et PFCluster
00878     photonCand.setPositionAtECALEntrance(math::XYZPointF(PFClusters[highEindex].position()));
00879     
00880     //Mustache ID variables
00881     Mustache Must;
00882     Must.FillMustacheVar(PFClusters);
00883     int excluded= Must.OutsideMust();
00884     float MustacheEt=Must.MustacheEtOut();
00885     myExtra.setMustache_Et(MustacheEt);
00886     myExtra.setExcludedClust(excluded);
00887     if(fabs(photonCand.eta()<1.4446))
00888       myExtra.setMVAGlobalCorrE(GCorr * PFPhoECorr_);
00889     else if(PFPhoR9_>0.94)
00890       myExtra.setMVAGlobalCorrE(GCorr * PFPhoECorr_);
00891     else myExtra.setMVAGlobalCorrE(GCorr * photonEnergy_);
00892     float Res=EvaluateResMVA(photonCand, PFClusters);
00893     myExtra.SetPFPhotonRes(Res);
00894     
00895     //    Daniele example for mvaValues
00896     //    do the same for single leg trackRef and convRef
00897     for(unsigned int ic = 0; ic < MVA_values.size(); ic++)
00898       {
00899         myExtra.addSingleLegConvMva(MVA_values[ic]);
00900         myExtra.addSingleLegConvTrackRef(singleLegRef[ic]);
00901         //cout<<"Single Leg Tracks "<<singleLegRef[ic]->pt()<<" MVA "<<MVA_values[ic]<<endl;
00902       }
00903     for(unsigned int ic = 0; ic < ConversionsRef_.size(); ic++)
00904       {
00905         myExtra.addConversionRef(ConversionsRef_[ic]);
00906         //cout<<"Conversion Pairs "<<ConversionsRef_[ic]->pairMomentum()<<endl;
00907       }
00908     pfPhotonExtraCandidates.push_back(myExtra);
00909     pfCandidates->push_back(photonCand);
00910     // ... and reset the vector
00911     elemsToLock.resize(0);
00912     hasConvTrack=false;
00913     hasSingleleg=false;
00914   } // end of loops over all elements in block
00915   
00916   return;
00917 }
00918 
00919 float PFPhotonAlgo::EvaluateResMVA(reco::PFCandidate photon, std::vector<reco::CaloCluster>PFClusters){
00920   float BDTG=1;
00921   PFPhoEta_=photon.eta();
00922   PFPhoPhi_=photon.phi();
00923   PFPhoE_=photon.energy();
00924   //fill Material Map:
00925   int ix = X0_sum->GetXaxis()->FindBin(PFPhoEta_);
00926   int iy = X0_sum->GetYaxis()->FindBin(PFPhoPhi_);
00927   x0inner_= X0_inner->GetBinContent(ix,iy);
00928   x0middle_=X0_middle->GetBinContent(ix,iy);
00929   x0outer_=X0_outer->GetBinContent(ix,iy);
00930   SCPhiWidth_=photon.superClusterRef()->phiWidth();
00931   SCEtaWidth_=photon.superClusterRef()->etaWidth();
00932   Mustache Must;
00933   std::vector<unsigned int>insideMust;
00934   std::vector<unsigned int>outsideMust;
00935   std::multimap<float, unsigned int>OrderedClust;
00936   Must.FillMustacheVar(PFClusters);
00937   MustE_=Must.MustacheE();
00938   LowClusE_=Must.LowestMustClust();
00939   PFPhoR9Corr_=E3x3_/MustE_;
00940   Must.MustacheClust(PFClusters,insideMust, outsideMust );
00941   for(unsigned int i=0; i<insideMust.size(); ++i){
00942     int index=insideMust[i];
00943     OrderedClust.insert(make_pair(PFClusters[index].energy(),index));
00944   }
00945   std::multimap<float, unsigned int>::iterator it;
00946   it=OrderedClust.begin();
00947   unsigned int lowEindex=(*it).second;
00948   std::multimap<float, unsigned int>::reverse_iterator rit;
00949   rit=OrderedClust.rbegin();
00950   unsigned int highEindex=(*rit).second;
00951   if(insideMust.size()>1){
00952     dEta_=fabs(PFClusters[highEindex].eta()-PFClusters[lowEindex].eta());
00953     dPhi_=asin(PFClusters[highEindex].phi()-PFClusters[lowEindex].phi());
00954   }
00955   else{
00956     dEta_=0;
00957     dPhi_=0;
00958     LowClusE_=0;
00959   }
00960   //calculate RMS for All clusters and up until the Next to Lowest inside the Mustache
00961   RMSAll_=ClustersPhiRMS(PFClusters, PFPhoPhi_);
00962   std::vector<reco::CaloCluster>PFMustClusters;
00963   if(insideMust.size()>2){
00964     for(unsigned int i=0; i<insideMust.size(); ++i){
00965       unsigned int index=insideMust[i];
00966       if(index==lowEindex)continue;
00967       PFMustClusters.push_back(PFClusters[index]);
00968     }
00969   }
00970   else{
00971     for(unsigned int i=0; i<insideMust.size(); ++i){
00972       unsigned int index=insideMust[i];
00973       PFMustClusters.push_back(PFClusters[index]);
00974     }    
00975   }
00976   RMSMust_=ClustersPhiRMS(PFMustClusters, PFPhoPhi_);
00977   //then use cluster Width for just one PFCluster
00978   RConv_=310;
00979   PFCandidate::ElementsInBlocks eleInBlocks = photon.elementsInBlocks();
00980   for(unsigned i=0; i<eleInBlocks.size(); i++)
00981     {
00982       PFBlockRef blockRef = eleInBlocks[i].first;
00983       unsigned indexInBlock = eleInBlocks[i].second;
00984       const edm::OwnVector< reco::PFBlockElement >&  elements=eleInBlocks[i].first->elements();
00985       const reco::PFBlockElement& element = elements[indexInBlock];
00986       if(element.type()==reco::PFBlockElement::TRACK){
00987         float R=sqrt(element.trackRef()->innerPosition().X()*element.trackRef()->innerPosition().X()+element.trackRef()->innerPosition().Y()*element.trackRef()->innerPosition().Y());
00988         if(RConv_>R)RConv_=R;
00989       }
00990       else continue;
00991     }
00992   float GC_Var[17];
00993   GC_Var[0]=PFPhoEta_;
00994   GC_Var[1]=PFPhoEt_;
00995   GC_Var[2]=PFPhoR9Corr_;
00996   GC_Var[3]=PFPhoPhi_;
00997   GC_Var[4]=SCEtaWidth_;
00998   GC_Var[5]=SCPhiWidth_;
00999   GC_Var[6]=x0inner_;  
01000   GC_Var[7]=x0middle_;
01001   GC_Var[8]=x0outer_;
01002   GC_Var[9]=RConv_;
01003   GC_Var[10]=LowClusE_;
01004   GC_Var[11]=RMSMust_;
01005   GC_Var[12]=RMSAll_;
01006   GC_Var[13]=dEta_;
01007   GC_Var[14]=dPhi_;
01008   GC_Var[15]=nVtx_;
01009   GC_Var[16]=MustE_;
01010   
01011   BDTG=ReaderRes_->GetResponse(GC_Var);
01012   //  cout<<"Res "<<BDTG<<endl;
01013   
01014   //  cout<<"BDTG Parameters X0"<<x0inner_<<", "<<x0middle_<<", "<<x0outer_<<endl;
01015   //  cout<<"Et, Eta, Phi "<<PFPhoEt_<<", "<<PFPhoEta_<<", "<<PFPhoPhi_<<endl;
01016   // cout<<"PFPhoR9 "<<PFPhoR9_<<endl;
01017   // cout<<"R "<<RConv_<<endl;
01018   
01019   return BDTG;
01020    
01021 }
01022 
01023 float PFPhotonAlgo::EvaluateGCorrMVA(reco::PFCandidate photon, std::vector<CaloCluster>PFClusters){
01024   float BDTG=1;
01025   PFPhoEta_=photon.eta();
01026   PFPhoPhi_=photon.phi();
01027   PFPhoE_=photon.energy();
01028     //fill Material Map:
01029   int ix = X0_sum->GetXaxis()->FindBin(PFPhoEta_);
01030   int iy = X0_sum->GetYaxis()->FindBin(PFPhoPhi_);
01031   x0inner_= X0_inner->GetBinContent(ix,iy);
01032   x0middle_=X0_middle->GetBinContent(ix,iy);
01033   x0outer_=X0_outer->GetBinContent(ix,iy);
01034   SCPhiWidth_=photon.superClusterRef()->phiWidth();
01035   SCEtaWidth_=photon.superClusterRef()->etaWidth();
01036   Mustache Must;
01037   std::vector<unsigned int>insideMust;
01038   std::vector<unsigned int>outsideMust;
01039   std::multimap<float, unsigned int>OrderedClust;
01040   Must.FillMustacheVar(PFClusters);
01041   MustE_=Must.MustacheE();
01042   LowClusE_=Must.LowestMustClust();
01043   PFPhoR9Corr_=E3x3_/MustE_;
01044   Must.MustacheClust(PFClusters,insideMust, outsideMust );
01045   for(unsigned int i=0; i<insideMust.size(); ++i){
01046     int index=insideMust[i];
01047     OrderedClust.insert(make_pair(PFClusters[index].energy(),index));
01048   }
01049   std::multimap<float, unsigned int>::iterator it;
01050   it=OrderedClust.begin();
01051   unsigned int lowEindex=(*it).second;
01052   std::multimap<float, unsigned int>::reverse_iterator rit;
01053   rit=OrderedClust.rbegin();
01054   unsigned int highEindex=(*rit).second;
01055   if(insideMust.size()>1){
01056     dEta_=fabs(PFClusters[highEindex].eta()-PFClusters[lowEindex].eta());
01057     dPhi_=asin(PFClusters[highEindex].phi()-PFClusters[lowEindex].phi());
01058   }
01059   else{
01060     dEta_=0;
01061     dPhi_=0;
01062     LowClusE_=0;
01063   }
01064   //calculate RMS for All clusters and up until the Next to Lowest inside the Mustache
01065   RMSAll_=ClustersPhiRMS(PFClusters, PFPhoPhi_);
01066   std::vector<reco::CaloCluster>PFMustClusters;
01067   if(insideMust.size()>2){
01068     for(unsigned int i=0; i<insideMust.size(); ++i){
01069       unsigned int index=insideMust[i];
01070       if(index==lowEindex)continue;
01071       PFMustClusters.push_back(PFClusters[index]);
01072     }
01073   }
01074   else{
01075     for(unsigned int i=0; i<insideMust.size(); ++i){
01076       unsigned int index=insideMust[i];
01077       PFMustClusters.push_back(PFClusters[index]);
01078     }    
01079   }
01080   RMSMust_=ClustersPhiRMS(PFMustClusters, PFPhoPhi_);
01081   //then use cluster Width for just one PFCluster
01082   RConv_=310;
01083   PFCandidate::ElementsInBlocks eleInBlocks = photon.elementsInBlocks();
01084   for(unsigned i=0; i<eleInBlocks.size(); i++)
01085     {
01086       PFBlockRef blockRef = eleInBlocks[i].first;
01087       unsigned indexInBlock = eleInBlocks[i].second;
01088       const edm::OwnVector< reco::PFBlockElement >&  elements=eleInBlocks[i].first->elements();
01089       const reco::PFBlockElement& element = elements[indexInBlock];
01090       if(element.type()==reco::PFBlockElement::TRACK){
01091         float R=sqrt(element.trackRef()->innerPosition().X()*element.trackRef()->innerPosition().X()+element.trackRef()->innerPosition().Y()*element.trackRef()->innerPosition().Y());
01092         if(RConv_>R)RConv_=R;
01093       }
01094       else continue;
01095     }
01096   //cout<<"Nvtx "<<nVtx_<<endl;
01097   if(fabs(PFPhoEta_)<1.4446){
01098     float GC_Var[17];
01099     GC_Var[0]=PFPhoEta_;
01100     GC_Var[1]=PFPhoECorr_;
01101     GC_Var[2]=PFPhoR9Corr_;
01102     GC_Var[3]=SCEtaWidth_;
01103     GC_Var[4]=SCPhiWidth_;
01104     GC_Var[5]=PFPhoPhi_;
01105     GC_Var[6]=x0inner_;
01106     GC_Var[7]=x0middle_;
01107     GC_Var[8]=x0outer_;
01108     GC_Var[9]=RConv_;
01109     GC_Var[10]=LowClusE_;
01110     GC_Var[11]=RMSMust_;
01111     GC_Var[12]=RMSAll_;
01112     GC_Var[13]=dEta_;
01113     GC_Var[14]=dPhi_;
01114     GC_Var[15]=nVtx_;
01115     GC_Var[16]=MustE_;
01116     BDTG=ReaderGCEB_->GetResponse(GC_Var);
01117   }
01118   else if(PFPhoR9_>0.94){
01119     float GC_Var[19];
01120     GC_Var[0]=PFPhoEta_;
01121     GC_Var[1]=PFPhoECorr_;
01122     GC_Var[2]=PFPhoR9Corr_;
01123     GC_Var[3]=SCEtaWidth_;
01124     GC_Var[4]=SCPhiWidth_;
01125     GC_Var[5]=PFPhoPhi_;
01126     GC_Var[6]=x0inner_;
01127     GC_Var[7]=x0middle_;
01128     GC_Var[8]=x0outer_;
01129     GC_Var[9]=RConv_;
01130     GC_Var[10]=LowClusE_;
01131     GC_Var[11]=RMSMust_;
01132     GC_Var[12]=RMSAll_;
01133     GC_Var[13]=dEta_;
01134     GC_Var[14]=dPhi_;
01135     GC_Var[15]=nVtx_;
01136     GC_Var[16]=TotPS1_;
01137     GC_Var[17]=TotPS2_;
01138     GC_Var[18]=MustE_;
01139     BDTG=ReaderGCEEhR9_->GetResponse(GC_Var);
01140   }
01141   
01142   else{
01143     float GC_Var[19];
01144     GC_Var[0]=PFPhoEta_;
01145     GC_Var[1]=PFPhoE_;
01146     GC_Var[2]=PFPhoR9Corr_;
01147     GC_Var[3]=SCEtaWidth_;
01148     GC_Var[4]=SCPhiWidth_;
01149     GC_Var[5]=PFPhoPhi_;
01150     GC_Var[6]=x0inner_;
01151     GC_Var[7]=x0middle_;
01152     GC_Var[8]=x0outer_;
01153     GC_Var[9]=RConv_;
01154     GC_Var[10]=LowClusE_;
01155     GC_Var[11]=RMSMust_;
01156     GC_Var[12]=RMSAll_;
01157     GC_Var[13]=dEta_;
01158     GC_Var[14]=dPhi_;
01159     GC_Var[15]=nVtx_;
01160     GC_Var[16]=TotPS1_;
01161     GC_Var[17]=TotPS2_;
01162     GC_Var[18]=MustE_;
01163     BDTG=ReaderGCEElR9_->GetResponse(GC_Var);
01164   }
01165   //cout<<"GC "<<BDTG<<endl;
01166 
01167   return BDTG;
01168   
01169 }
01170 
01171 double PFPhotonAlgo::ClustersPhiRMS(std::vector<reco::CaloCluster>PFClusters, float PFPhoPhi){
01172   double PFClustPhiRMS=0;
01173   double delPhi2=0;
01174   double delPhiSum=0;
01175   double ClusSum=0;
01176   for(unsigned int c=0; c<PFClusters.size(); ++c){
01177     delPhi2=(acos(cos(PFPhoPhi-PFClusters[c].phi()))* acos(cos(PFPhoPhi-PFClusters[c].phi())) )+delPhi2;
01178     delPhiSum=delPhiSum+ acos(cos(PFPhoPhi-PFClusters[c].phi()))*PFClusters[c].energy();
01179     ClusSum=ClusSum+PFClusters[c].energy();
01180   }
01181   double meandPhi=delPhiSum/ClusSum;
01182   PFClustPhiRMS=sqrt(fabs(delPhi2/ClusSum - (meandPhi*meandPhi)));
01183   
01184   return PFClustPhiRMS;
01185 }
01186 
01187 float PFPhotonAlgo::EvaluateLCorrMVA(reco::PFClusterRef clusterRef ){
01188   float BDTG=1;
01189   PFPhotonClusters ClusterVar(clusterRef);
01190   std::pair<double, double>ClusCoor=ClusterVar.GetCrysCoor();
01191   std::pair<int, int>ClusIndex=ClusterVar.GetCrysIndex();
01192   //Local Coordinates:
01193   if(clusterRef->layer()==PFLayer:: ECAL_BARREL ){//is Barrel
01194     PFCrysEtaCrack_=ClusterVar.EtaCrack();
01195     CrysEta_=ClusCoor.first;
01196     CrysPhi_=ClusCoor.second;
01197     CrysIEta_=ClusIndex.first;
01198     CrysIPhi_=ClusIndex.second;
01199   }
01200   else{
01201     CrysX_=ClusCoor.first;
01202     CrysY_=ClusCoor.second;
01203   }
01204   //Shower Shape Variables:
01205   eSeed_= ClusterVar.E5x5Element(0, 0)/clusterRef->energy();
01206   etop_=ClusterVar.E5x5Element(0,1)/clusterRef->energy();
01207   ebottom_=ClusterVar.E5x5Element(0,-1)/clusterRef->energy();
01208   eleft_=ClusterVar.E5x5Element(-1,0)/clusterRef->energy();
01209   eright_=ClusterVar.E5x5Element(1,0)/clusterRef->energy();
01210   e1x3_=(ClusterVar.E5x5Element(0,0)+ClusterVar.E5x5Element(0,1)+ClusterVar.E5x5Element(0,-1))/clusterRef->energy();
01211   e3x1_=(ClusterVar.E5x5Element(0,0)+ClusterVar.E5x5Element(-1,0)+ClusterVar.E5x5Element(1,0))/clusterRef->energy();
01212   e1x5_=ClusterVar.E5x5Element(0,0)+ClusterVar.E5x5Element(0,-2)+ClusterVar.E5x5Element(0,-1)+ClusterVar.E5x5Element(0,1)+ClusterVar.E5x5Element(0,2);
01213   
01214   e2x5Top_=(ClusterVar.E5x5Element(-2,2)+ClusterVar.E5x5Element(-1, 2)+ClusterVar.E5x5Element(0, 2)
01215             +ClusterVar.E5x5Element(1, 2)+ClusterVar.E5x5Element(2, 2)
01216             +ClusterVar.E5x5Element(-2,1)+ClusterVar.E5x5Element(-1,1)+ClusterVar.E5x5Element(0,1)
01217             +ClusterVar.E5x5Element(1,1)+ClusterVar.E5x5Element(2,1))/clusterRef->energy();
01218   e2x5Bottom_=(ClusterVar.E5x5Element(-2,-2)+ClusterVar.E5x5Element(-1,-2)+ClusterVar.E5x5Element(0,-2)
01219                +ClusterVar.E5x5Element(1,-2)+ClusterVar.E5x5Element(2,-2)
01220                +ClusterVar.E5x5Element(-2,1)+ClusterVar.E5x5Element(-1,1)
01221                +ClusterVar.E5x5Element(0,1)+ClusterVar.E5x5Element(1,1)+ClusterVar.E5x5Element(2,1))/clusterRef->energy();
01222   e2x5Left_= (ClusterVar.E5x5Element(-2,-2)+ClusterVar.E5x5Element(-2,-1)
01223               +ClusterVar.E5x5Element(-2,0)
01224                +ClusterVar.E5x5Element(-2,1)+ClusterVar.E5x5Element(-2,2)
01225               +ClusterVar.E5x5Element(-1,-2)+ClusterVar.E5x5Element(-1,-1)+ClusterVar.E5x5Element(-1,0)
01226               +ClusterVar.E5x5Element(-1,1)+ClusterVar.E5x5Element(-1,2))/clusterRef->energy();
01227   
01228   e2x5Right_ =(ClusterVar.E5x5Element(2,-2)+ClusterVar.E5x5Element(2,-1)
01229                +ClusterVar.E5x5Element(2,0)+ClusterVar.E5x5Element(2,1)+ClusterVar.E5x5Element(2,2)
01230                +ClusterVar.E5x5Element(1,-2)+ClusterVar.E5x5Element(1,-1)+ClusterVar.E5x5Element(1,0)
01231                +ClusterVar.E5x5Element(1,1)+ClusterVar.E5x5Element(1,2))/clusterRef->energy();
01232   float centerstrip=ClusterVar.E5x5Element(0,0)+ClusterVar.E5x5Element(0, -2)
01233     +ClusterVar.E5x5Element(0,-1)+ClusterVar.E5x5Element(0,1)+ClusterVar.E5x5Element(0,2);
01234   float rightstrip=ClusterVar.E5x5Element(1, 0)+ClusterVar.E5x5Element(1,1)
01235     +ClusterVar.E5x5Element(1,2)+ClusterVar.E5x5Element(1,-1)+ClusterVar.E5x5Element(1,-2);
01236   float leftstrip=ClusterVar.E5x5Element(-1,0)+ClusterVar.E5x5Element(-1,-1)+ClusterVar.E5x5Element(-1,2)
01237     +ClusterVar.E5x5Element(-1,1)+ClusterVar.E5x5Element(-1,2);
01238   
01239   if(rightstrip>leftstrip)e2x5Max_=rightstrip+centerstrip;
01240   else e2x5Max_=leftstrip+centerstrip;
01241   e2x5Max_=e2x5Max_/clusterRef->energy();
01242   //GetCrysCoordinates(clusterRef);
01243   //fill5x5Map(clusterRef);
01244   VtxZ_=primaryVertex_->z();
01245   ClusPhi_=clusterRef->position().phi(); 
01246   ClusEta_=fabs(clusterRef->position().eta());
01247   EB=fabs(clusterRef->position().eta())/clusterRef->position().eta();
01248   logPFClusE_=log(clusterRef->energy());
01249   if(ClusEta_<1.4446){
01250     float LC_Var[26];
01251     LC_Var[0]=VtxZ_;
01252     LC_Var[1]=EB;
01253     LC_Var[2]=ClusEta_;
01254     LC_Var[3]=ClusPhi_;
01255     LC_Var[4]=logPFClusE_;
01256     LC_Var[5]=eSeed_;
01257     //top bottom left right
01258     LC_Var[6]=etop_;
01259     LC_Var[7]=ebottom_;
01260     LC_Var[8]=eleft_;
01261     LC_Var[9]=eright_;
01262     LC_Var[10]=ClusR9_;
01263     LC_Var[11]=e1x3_;
01264     LC_Var[12]=e3x1_;
01265     LC_Var[13]=Clus5x5ratio_;
01266     LC_Var[14]=e1x5_;
01267     LC_Var[15]=e2x5Max_;
01268     LC_Var[16]=e2x5Top_;
01269     LC_Var[17]=e2x5Bottom_;
01270     LC_Var[18]=e2x5Left_;
01271     LC_Var[19]=e2x5Right_;
01272     LC_Var[20]=CrysEta_;
01273     LC_Var[21]=CrysPhi_;
01274     float CrysIphiMod2=CrysIPhi_%2;
01275     float CrysIetaMod5=CrysIEta_%5;
01276     float CrysIphiMod20=CrysIPhi_%20;
01277     LC_Var[22]=CrysIphiMod2;
01278     LC_Var[23]=CrysIetaMod5;
01279     LC_Var[24]=CrysIphiMod20;   
01280     LC_Var[25]=PFCrysEtaCrack_;
01281     BDTG=ReaderLCEB_->GetResponse(LC_Var);   
01282     //cout<<"LC "<<BDTG<<endl;  
01283   }
01284   else{
01285     float LC_Var[22];
01286     LC_Var[0]=VtxZ_;
01287     LC_Var[1]=EB;
01288     LC_Var[2]=ClusEta_;
01289     LC_Var[3]=ClusPhi_;
01290     LC_Var[4]=logPFClusE_;
01291     LC_Var[5]=eSeed_;
01292     //top bottom left right
01293     LC_Var[6]=etop_;
01294     LC_Var[7]=ebottom_;
01295     LC_Var[8]=eleft_;
01296     LC_Var[9]=eright_;
01297     LC_Var[10]=ClusR9_;
01298     LC_Var[11]=e1x3_;
01299     LC_Var[12]=e3x1_;
01300     LC_Var[13]=Clus5x5ratio_;
01301     LC_Var[14]=e1x5_;
01302     LC_Var[15]=e2x5Max_;
01303     LC_Var[16]=e2x5Top_;
01304     LC_Var[17]=e2x5Bottom_;
01305     LC_Var[18]=e2x5Left_;
01306     LC_Var[19]=e2x5Right_;
01307     LC_Var[20]=CrysX_;
01308     LC_Var[21]=CrysY_;
01309     BDTG=ReaderLCEE_->GetResponse(LC_Var);   
01310     //cout<<"LC "<<BDTG<<endl;  
01311   }
01312    return BDTG;
01313   
01314 }
01315 
01316 bool PFPhotonAlgo::EvaluateSingleLegMVA(const reco::PFBlockRef& blockref, const reco::Vertex& primaryvtx, unsigned int track_index)  
01317 {  
01318   bool convtkfound=false;  
01319   const reco::PFBlock& block = *blockref;  
01320   const edm::OwnVector< reco::PFBlockElement >& elements = block.elements();  
01321   //use this to store linkdata in the associatedElements function below  
01322   PFBlock::LinkData linkData =  block.linkData();  
01323   //calculate MVA Variables  
01324   chi2=elements[track_index].trackRef()->chi2()/elements[track_index].trackRef()->ndof();  
01325   nlost=elements[track_index].trackRef()->trackerExpectedHitsInner().numberOfLostHits();  
01326   nlayers=elements[track_index].trackRef()->hitPattern().trackerLayersWithMeasurement();  
01327   track_pt=elements[track_index].trackRef()->pt();  
01328   STIP=elements[track_index].trackRefPF()->STIP();  
01329    
01330   float linked_e=0;  
01331   float linked_h=0;  
01332   std::multimap<double, unsigned int> ecalAssoTrack;  
01333   block.associatedElements( track_index,linkData,  
01334                             ecalAssoTrack,  
01335                             reco::PFBlockElement::ECAL,  
01336                             reco::PFBlock::LINKTEST_ALL );  
01337   std::multimap<double, unsigned int> hcalAssoTrack;  
01338   block.associatedElements( track_index,linkData,  
01339                             hcalAssoTrack,  
01340                             reco::PFBlockElement::HCAL,  
01341                             reco::PFBlock::LINKTEST_ALL );  
01342   if(ecalAssoTrack.size() > 0) {  
01343     for(std::multimap<double, unsigned int>::iterator itecal = ecalAssoTrack.begin();  
01344         itecal != ecalAssoTrack.end(); ++itecal) {  
01345       linked_e=linked_e+elements[itecal->second].clusterRef()->energy();  
01346     }  
01347   }  
01348   if(hcalAssoTrack.size() > 0) {  
01349     for(std::multimap<double, unsigned int>::iterator ithcal = hcalAssoTrack.begin();  
01350         ithcal != hcalAssoTrack.end(); ++ithcal) {  
01351       linked_h=linked_h+elements[ithcal->second].clusterRef()->energy();  
01352     }  
01353   }  
01354   EoverPt=linked_e/elements[track_index].trackRef()->pt();  
01355   HoverPt=linked_h/elements[track_index].trackRef()->pt();  
01356   GlobalVector rvtx(elements[track_index].trackRef()->innerPosition().X()-primaryvtx.x(),  
01357                     elements[track_index].trackRef()->innerPosition().Y()-primaryvtx.y(),  
01358                     elements[track_index].trackRef()->innerPosition().Z()-primaryvtx.z());  
01359   double vtx_phi=rvtx.phi();  
01360   //delta Phi between conversion vertex and track  
01361   del_phi=fabs(deltaPhi(vtx_phi, elements[track_index].trackRef()->innerMomentum().Phi()));  
01362   mvaValue = tmvaReader_->EvaluateMVA("BDT");  
01363   if(mvaValue > MVACUT)convtkfound=true;  
01364   return convtkfound;  
01365 }
01366 
01367 //Recover Early Conversions reconstructed as PFelectrons
01368 void PFPhotonAlgo::EarlyConversion(    
01369                                    //std::auto_ptr< reco::PFCandidateCollection > 
01370                                    //&pfElectronCandidates_,
01371                                    std::vector<reco::PFCandidate>& 
01372                                    tempElectronCandidates,
01373                                    const reco::PFBlockElementSuperCluster* sc
01374                                    ){
01375   //step 1 check temp electrons for clusters that match Photon Supercluster:
01376   // permElectronCandidates->clear();
01377   int count=0;
01378   for ( std::vector<reco::PFCandidate>::const_iterator ec=tempElectronCandidates.begin();   ec != tempElectronCandidates.end(); ++ec ) 
01379     {
01380       //      bool matched=false;
01381       int mh=ec->gsfTrackRef()->trackerExpectedHitsInner().numberOfLostHits();
01382       //if(mh==0)continue;//Case where missing hits greater than zero
01383       
01384       reco::GsfTrackRef gsf=ec->gsfTrackRef();
01385       //some hoopla to get Electron SC ref
01386       
01387       if(gsf->extra().isAvailable() && gsf->extra()->seedRef().isAvailable() && mh>0) 
01388         {
01389           reco::ElectronSeedRef seedRef=  gsf->extra()->seedRef().castTo<reco::ElectronSeedRef>();
01390           if(seedRef.isAvailable() && seedRef->isEcalDriven()) 
01391             {
01392               reco::SuperClusterRef ElecscRef = seedRef->caloCluster().castTo<reco::SuperClusterRef>();
01393               
01394               if(ElecscRef.isNonnull()){
01395                 //finally see if it matches:
01396                 reco::SuperClusterRef PhotscRef=sc->superClusterRef();
01397                 if(PhotscRef==ElecscRef)
01398                   {
01399                     match_ind.push_back(count);
01400                     //  matched=true; 
01401                     //cout<<"Matched Electron with Index "<<count<<" This is the electron "<<*ec<<endl;
01402                     //find that they have the same SC footprint start to collect Clusters and tracks and these will be passed to PFPhoton
01403                     reco::PFCandidate::ElementsInBlocks eleInBlocks = ec->elementsInBlocks();
01404                     for(unsigned i=0; i<eleInBlocks.size(); i++) 
01405                       {
01406                         reco::PFBlockRef blockRef = eleInBlocks[i].first;
01407                         unsigned indexInBlock = eleInBlocks[i].second;   
01408                         //const edm::OwnVector< reco::PFBlockElement >&  elements=eleInBlocks[i].first->elements();
01409                         //const reco::PFBlockElement& element = elements[indexInBlock];                 
01410                         
01411                         AddFromElectron_.push_back(indexInBlock);               
01412                       }             
01413                   }             
01414               }
01415             }     
01416         }           
01417       count++;
01418     }
01419 }