CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_1/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     primaryVertex_=primary;  
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 
00767     math::XYZVector photonDirection=photonPosition.Unit();
00768     
00769     math::XYZTLorentzVector photonMomentum(photonEnergy_* photonDirection.X(),
00770                                            photonEnergy_* photonDirection.Y(),
00771                                            photonEnergy_* photonDirection.Z(),
00772                                            photonEnergy_           );
00773 
00774     if(sum_track_pt>(sumPtTrackIsoForPhoton_ + sumPtTrackIsoSlopeForPhoton_ * photonMomentum.pt()))
00775       {
00776         //cout<<"Hit Continue "<<endl;
00777         match_ind.clear(); //release the matched Electron candidates
00778         continue;
00779       }
00780 
00781         //THIS SC is not a Photon it fails track Isolation
00782     //if(sum_track_pt>(2+ 0.001* photonMomentum.pt()))
00783     //continue;//THIS SC is not a Photon it fails track Isolation
00784 
00785     /*
00786     std::cout<<" Created Photon with energy = "<<photonEnergy_<<std::endl;
00787     std::cout<<"                         pT = "<<photonMomentum.pt()<<std::endl;
00788     std::cout<<"                     RawEne = "<<RawEcalEne<<std::endl;
00789     std::cout<<"                          E = "<<photonMomentum.e()<<std::endl;
00790     std::cout<<"                        eta = "<<photonMomentum.eta()<<std::endl;
00791     std::cout<<"             TrackIsolation = "<< sum_track_pt <<std::endl;
00792     */
00793 
00794     reco::PFCandidate photonCand(0,photonMomentum, reco::PFCandidate::gamma);
00795     
00796     photonCand.setPs1Energy(ps1TotEne);
00797     photonCand.setPs2Energy(ps2TotEne);
00798     photonCand.setEcalEnergy(RawEcalEne,photonEnergy_);
00799     photonCand.setHcalEnergy(0.,0.);
00800     photonCand.set_mva_nothing_gamma(1.);  
00801     photonCand.setSuperClusterRef(sc->superClusterRef());
00802     math::XYZPoint v(primaryVertex_.x(), primaryVertex_.y(), primaryVertex_.z());
00803     photonCand.setVertex( v  );
00804     if(hasConvTrack || hasSingleleg)photonCand.setFlag( reco::PFCandidate::GAMMA_TO_GAMMACONV, true);
00805     int matches=match_ind.size();
00806     int count=0;
00807     for ( std::vector<reco::PFCandidate>::const_iterator ec=tempElectronCandidates.begin();   ec != tempElectronCandidates.end(); ++ec ){
00808       for(int i=0; i<matches; i++)
00809         {
00810           if(count==match_ind[i])photonCand.addDaughter(*ec);
00811           count++;
00812         }
00813     }
00814     //photonCand.setPositionAtECALEntrance(math::XYZPointF(photonMom_.position()));
00815     // set isvalid_ to TRUE since we've found at least one photon candidate
00816     isvalid_ = true;
00817     // push back the candidate into the collection ...
00818     //Add Elements from Electron
00819     for(std::vector<unsigned int>::const_iterator it = 
00820           AddFromElectron_.begin();
00821         it != AddFromElectron_.end(); ++it)photonCand.addElementInBlock(blockRef,*it);
00822     
00823     
00824     // ... and lock all elemts used
00825     for(std::vector<unsigned int>::const_iterator it = elemsToLock.begin();
00826         it != elemsToLock.end(); ++it)
00827       {
00828         if(active[*it])
00829           {
00830             photonCand.addElementInBlock(blockRef,*it);
00831             if( elements[*it].type() == reco::PFBlockElement::TRACK  )
00832               {
00833                 if(elements[*it].convRef().isNonnull())
00834                   {
00835                     //make sure it is not stored already as the partner track
00836                     bool matched=false;
00837                     for(unsigned int ic = 0; ic < ConversionsRef_.size(); ic++)
00838                       {
00839                         if(ConversionsRef_[ic]==elements[*it].convRef())matched=true;
00840                       }
00841                     if(!matched)ConversionsRef_.push_back(elements[*it].convRef());
00842                   }
00843               }
00844           }
00845         active[*it] = false;    
00846       }
00847     PFPhoECorr_=0;
00848     // here add the extra information
00849     PFCandidatePhotonExtra myExtra(sc->superClusterRef());
00850     //Store Locally Contained PF Cluster regressed energy
00851     for(unsigned int l=0; l<MVALCorr.size(); ++l)
00852       {
00853         myExtra.addLCorrClusEnergy(MVALCorr[l]);
00854         PFPhoECorr_=PFPhoECorr_+MVALCorr[l];//total Locally corrected energy
00855       }
00856     TotPS1_=ps1TotEne;
00857     TotPS2_=ps2TotEne;
00858     //Do Global Corrections here:
00859     float GCorr=EvaluateGCorrMVA(photonCand, PFClusters);
00860     if(useReg_){
00861       math::XYZTLorentzVector photonCorrMomentum(GCorr*PFPhoECorr_* photonDirection.X(),
00862                                                  GCorr*PFPhoECorr_* photonDirection.Y(),
00863                                                  GCorr*PFPhoECorr_* photonDirection.Z(),
00864                                                  GCorr * photonEnergy_           );
00865       photonCand.setP4(photonCorrMomentum);
00866     }
00867     //Mustache ID variables
00868     Mustache Must;
00869     Must.FillMustacheVar(PFClusters);
00870     int excluded= Must.OutsideMust();
00871     float MustacheEt=Must.MustacheEtOut();
00872     myExtra.setMustache_Et(MustacheEt);
00873     myExtra.setExcludedClust(excluded);
00874     if(fabs(photonCand.eta()<1.4446))
00875       myExtra.setMVAGlobalCorrE(GCorr * PFPhoECorr_);
00876     else if(PFPhoR9_>0.94)
00877       myExtra.setMVAGlobalCorrE(GCorr * PFPhoECorr_);
00878     else myExtra.setMVAGlobalCorrE(GCorr * photonEnergy_);
00879     float Res=EvaluateResMVA(photonCand, PFClusters);
00880     myExtra.SetPFPhotonRes(Res);
00881     
00882     //    Daniele example for mvaValues
00883     //    do the same for single leg trackRef and convRef
00884     for(unsigned int ic = 0; ic < MVA_values.size(); ic++)
00885       {
00886         myExtra.addSingleLegConvMva(MVA_values[ic]);
00887         myExtra.addSingleLegConvTrackRef(singleLegRef[ic]);
00888         //cout<<"Single Leg Tracks "<<singleLegRef[ic]->pt()<<" MVA "<<MVA_values[ic]<<endl;
00889       }
00890     for(unsigned int ic = 0; ic < ConversionsRef_.size(); ic++)
00891       {
00892         myExtra.addConversionRef(ConversionsRef_[ic]);
00893         //cout<<"Conversion Pairs "<<ConversionsRef_[ic]->pairMomentum()<<endl;
00894       }
00895     pfPhotonExtraCandidates.push_back(myExtra);
00896     pfCandidates->push_back(photonCand);
00897     // ... and reset the vector
00898     elemsToLock.resize(0);
00899     hasConvTrack=false;
00900     hasSingleleg=false;
00901   } // end of loops over all elements in block
00902   
00903   return;
00904 }
00905 
00906 float PFPhotonAlgo::EvaluateResMVA(reco::PFCandidate photon, std::vector<reco::CaloCluster>PFClusters){
00907   float BDTG=1;
00908   PFPhoEta_=photon.eta();
00909   PFPhoPhi_=photon.phi();
00910   PFPhoE_=photon.energy();
00911   //fill Material Map:
00912   int ix = X0_sum->GetXaxis()->FindBin(PFPhoEta_);
00913   int iy = X0_sum->GetYaxis()->FindBin(PFPhoPhi_);
00914   x0inner_= X0_inner->GetBinContent(ix,iy);
00915   x0middle_=X0_middle->GetBinContent(ix,iy);
00916   x0outer_=X0_outer->GetBinContent(ix,iy);
00917   SCPhiWidth_=photon.superClusterRef()->phiWidth();
00918   SCEtaWidth_=photon.superClusterRef()->etaWidth();
00919   Mustache Must;
00920   std::vector<unsigned int>insideMust;
00921   std::vector<unsigned int>outsideMust;
00922   std::multimap<float, unsigned int>OrderedClust;
00923   Must.FillMustacheVar(PFClusters);
00924   MustE_=Must.MustacheE();
00925   LowClusE_=Must.LowestMustClust();
00926   PFPhoR9Corr_=E3x3_/MustE_;
00927   Must.MustacheClust(PFClusters,insideMust, outsideMust );
00928   for(unsigned int i=0; i<insideMust.size(); ++i){
00929     int index=insideMust[i];
00930     OrderedClust.insert(make_pair(PFClusters[index].energy(),index));
00931   }
00932   std::multimap<float, unsigned int>::iterator it;
00933   it=OrderedClust.begin();
00934   unsigned int lowEindex=(*it).second;
00935   std::multimap<float, unsigned int>::reverse_iterator rit;
00936   rit=OrderedClust.rbegin();
00937   unsigned int highEindex=(*rit).second;
00938   if(insideMust.size()>1){
00939     dEta_=fabs(PFClusters[highEindex].eta()-PFClusters[lowEindex].eta());
00940     dPhi_=asin(PFClusters[highEindex].phi()-PFClusters[lowEindex].phi());
00941   }
00942   else{
00943     dEta_=0;
00944     dPhi_=0;
00945     LowClusE_=0;
00946   }
00947   //calculate RMS for All clusters and up until the Next to Lowest inside the Mustache
00948   RMSAll_=ClustersPhiRMS(PFClusters, PFPhoPhi_);
00949   std::vector<reco::CaloCluster>PFMustClusters;
00950   if(insideMust.size()>2){
00951     for(unsigned int i=0; i<insideMust.size(); ++i){
00952       unsigned int index=insideMust[i];
00953       if(index==lowEindex)continue;
00954       PFMustClusters.push_back(PFClusters[index]);
00955     }
00956   }
00957   else{
00958     for(unsigned int i=0; i<insideMust.size(); ++i){
00959       unsigned int index=insideMust[i];
00960       PFMustClusters.push_back(PFClusters[index]);
00961     }    
00962   }
00963   RMSMust_=ClustersPhiRMS(PFMustClusters, PFPhoPhi_);
00964   //then use cluster Width for just one PFCluster
00965   RConv_=310;
00966   PFCandidate::ElementsInBlocks eleInBlocks = photon.elementsInBlocks();
00967   for(unsigned i=0; i<eleInBlocks.size(); i++)
00968     {
00969       PFBlockRef blockRef = eleInBlocks[i].first;
00970       unsigned indexInBlock = eleInBlocks[i].second;
00971       const edm::OwnVector< reco::PFBlockElement >&  elements=eleInBlocks[i].first->elements();
00972       const reco::PFBlockElement& element = elements[indexInBlock];
00973       if(element.type()==reco::PFBlockElement::TRACK){
00974         float R=sqrt(element.trackRef()->innerPosition().X()*element.trackRef()->innerPosition().X()+element.trackRef()->innerPosition().Y()*element.trackRef()->innerPosition().Y());
00975         if(RConv_>R)RConv_=R;
00976       }
00977       else continue;
00978     }
00979   float GC_Var[17];
00980   GC_Var[0]=PFPhoEta_;
00981   GC_Var[1]=PFPhoEt_;
00982   GC_Var[2]=PFPhoR9Corr_;
00983   GC_Var[3]=PFPhoPhi_;
00984   GC_Var[4]=SCEtaWidth_;
00985   GC_Var[5]=SCPhiWidth_;
00986   GC_Var[6]=x0inner_;  
00987   GC_Var[7]=x0middle_;
00988   GC_Var[8]=x0outer_;
00989   GC_Var[9]=RConv_;
00990   GC_Var[10]=LowClusE_;
00991   GC_Var[11]=RMSMust_;
00992   GC_Var[12]=RMSAll_;
00993   GC_Var[13]=dEta_;
00994   GC_Var[14]=dPhi_;
00995   GC_Var[15]=nVtx_;
00996   GC_Var[16]=MustE_;
00997   
00998   BDTG=ReaderRes_->GetResponse(GC_Var);
00999   //  cout<<"Res "<<BDTG<<endl;
01000   
01001   //  cout<<"BDTG Parameters X0"<<x0inner_<<", "<<x0middle_<<", "<<x0outer_<<endl;
01002   //  cout<<"Et, Eta, Phi "<<PFPhoEt_<<", "<<PFPhoEta_<<", "<<PFPhoPhi_<<endl;
01003   // cout<<"PFPhoR9 "<<PFPhoR9_<<endl;
01004   // cout<<"R "<<RConv_<<endl;
01005   
01006   return BDTG;
01007    
01008 }
01009 
01010 float PFPhotonAlgo::EvaluateGCorrMVA(reco::PFCandidate photon, std::vector<CaloCluster>PFClusters){
01011   float BDTG=1;
01012   PFPhoEta_=photon.eta();
01013   PFPhoPhi_=photon.phi();
01014   PFPhoE_=photon.energy();
01015     //fill Material Map:
01016   int ix = X0_sum->GetXaxis()->FindBin(PFPhoEta_);
01017   int iy = X0_sum->GetYaxis()->FindBin(PFPhoPhi_);
01018   x0inner_= X0_inner->GetBinContent(ix,iy);
01019   x0middle_=X0_middle->GetBinContent(ix,iy);
01020   x0outer_=X0_outer->GetBinContent(ix,iy);
01021   SCPhiWidth_=photon.superClusterRef()->phiWidth();
01022   SCEtaWidth_=photon.superClusterRef()->etaWidth();
01023   Mustache Must;
01024   std::vector<unsigned int>insideMust;
01025   std::vector<unsigned int>outsideMust;
01026   std::multimap<float, unsigned int>OrderedClust;
01027   Must.FillMustacheVar(PFClusters);
01028   MustE_=Must.MustacheE();
01029   LowClusE_=Must.LowestMustClust();
01030   PFPhoR9Corr_=E3x3_/MustE_;
01031   Must.MustacheClust(PFClusters,insideMust, outsideMust );
01032   for(unsigned int i=0; i<insideMust.size(); ++i){
01033     int index=insideMust[i];
01034     OrderedClust.insert(make_pair(PFClusters[index].energy(),index));
01035   }
01036   std::multimap<float, unsigned int>::iterator it;
01037   it=OrderedClust.begin();
01038   unsigned int lowEindex=(*it).second;
01039   std::multimap<float, unsigned int>::reverse_iterator rit;
01040   rit=OrderedClust.rbegin();
01041   unsigned int highEindex=(*rit).second;
01042   if(insideMust.size()>1){
01043     dEta_=fabs(PFClusters[highEindex].eta()-PFClusters[lowEindex].eta());
01044     dPhi_=asin(PFClusters[highEindex].phi()-PFClusters[lowEindex].phi());
01045   }
01046   else{
01047     dEta_=0;
01048     dPhi_=0;
01049     LowClusE_=0;
01050   }
01051   //calculate RMS for All clusters and up until the Next to Lowest inside the Mustache
01052   RMSAll_=ClustersPhiRMS(PFClusters, PFPhoPhi_);
01053   std::vector<reco::CaloCluster>PFMustClusters;
01054   if(insideMust.size()>2){
01055     for(unsigned int i=0; i<insideMust.size(); ++i){
01056       unsigned int index=insideMust[i];
01057       if(index==lowEindex)continue;
01058       PFMustClusters.push_back(PFClusters[index]);
01059     }
01060   }
01061   else{
01062     for(unsigned int i=0; i<insideMust.size(); ++i){
01063       unsigned int index=insideMust[i];
01064       PFMustClusters.push_back(PFClusters[index]);
01065     }    
01066   }
01067   RMSMust_=ClustersPhiRMS(PFMustClusters, PFPhoPhi_);
01068   //then use cluster Width for just one PFCluster
01069   RConv_=310;
01070   PFCandidate::ElementsInBlocks eleInBlocks = photon.elementsInBlocks();
01071   for(unsigned i=0; i<eleInBlocks.size(); i++)
01072     {
01073       PFBlockRef blockRef = eleInBlocks[i].first;
01074       unsigned indexInBlock = eleInBlocks[i].second;
01075       const edm::OwnVector< reco::PFBlockElement >&  elements=eleInBlocks[i].first->elements();
01076       const reco::PFBlockElement& element = elements[indexInBlock];
01077       if(element.type()==reco::PFBlockElement::TRACK){
01078         float R=sqrt(element.trackRef()->innerPosition().X()*element.trackRef()->innerPosition().X()+element.trackRef()->innerPosition().Y()*element.trackRef()->innerPosition().Y());
01079         if(RConv_>R)RConv_=R;
01080       }
01081       else continue;
01082     }
01083   //cout<<"Nvtx "<<nVtx_<<endl;
01084   if(fabs(PFPhoEta_)<1.4446){
01085     float GC_Var[17];
01086     GC_Var[0]=PFPhoEta_;
01087     GC_Var[1]=PFPhoECorr_;
01088     GC_Var[2]=PFPhoR9Corr_;
01089     GC_Var[3]=SCEtaWidth_;
01090     GC_Var[4]=SCPhiWidth_;
01091     GC_Var[5]=PFPhoPhi_;
01092     GC_Var[6]=x0inner_;
01093     GC_Var[7]=x0middle_;
01094     GC_Var[8]=x0outer_;
01095     GC_Var[9]=RConv_;
01096     GC_Var[10]=LowClusE_;
01097     GC_Var[11]=RMSMust_;
01098     GC_Var[12]=RMSAll_;
01099     GC_Var[13]=dEta_;
01100     GC_Var[14]=dPhi_;
01101     GC_Var[15]=nVtx_;
01102     GC_Var[16]=MustE_;
01103     BDTG=ReaderGCEB_->GetResponse(GC_Var);
01104   }
01105   else if(PFPhoR9_>0.94){
01106     float GC_Var[19];
01107     GC_Var[0]=PFPhoEta_;
01108     GC_Var[1]=PFPhoECorr_;
01109     GC_Var[2]=PFPhoR9Corr_;
01110     GC_Var[3]=SCEtaWidth_;
01111     GC_Var[4]=SCPhiWidth_;
01112     GC_Var[5]=PFPhoPhi_;
01113     GC_Var[6]=x0inner_;
01114     GC_Var[7]=x0middle_;
01115     GC_Var[8]=x0outer_;
01116     GC_Var[9]=RConv_;
01117     GC_Var[10]=LowClusE_;
01118     GC_Var[11]=RMSMust_;
01119     GC_Var[12]=RMSAll_;
01120     GC_Var[13]=dEta_;
01121     GC_Var[14]=dPhi_;
01122     GC_Var[15]=nVtx_;
01123     GC_Var[16]=TotPS1_;
01124     GC_Var[17]=TotPS2_;
01125     GC_Var[18]=MustE_;
01126     BDTG=ReaderGCEEhR9_->GetResponse(GC_Var);
01127   }
01128   
01129   else{
01130     float GC_Var[19];
01131     GC_Var[0]=PFPhoEta_;
01132     GC_Var[1]=PFPhoE_;
01133     GC_Var[2]=PFPhoR9Corr_;
01134     GC_Var[3]=SCEtaWidth_;
01135     GC_Var[4]=SCPhiWidth_;
01136     GC_Var[5]=PFPhoPhi_;
01137     GC_Var[6]=x0inner_;
01138     GC_Var[7]=x0middle_;
01139     GC_Var[8]=x0outer_;
01140     GC_Var[9]=RConv_;
01141     GC_Var[10]=LowClusE_;
01142     GC_Var[11]=RMSMust_;
01143     GC_Var[12]=RMSAll_;
01144     GC_Var[13]=dEta_;
01145     GC_Var[14]=dPhi_;
01146     GC_Var[15]=nVtx_;
01147     GC_Var[16]=TotPS1_;
01148     GC_Var[17]=TotPS2_;
01149     GC_Var[18]=MustE_;
01150     BDTG=ReaderGCEElR9_->GetResponse(GC_Var);
01151   }
01152   //cout<<"GC "<<BDTG<<endl;
01153 
01154   return BDTG;
01155   
01156 }
01157 
01158 double PFPhotonAlgo::ClustersPhiRMS(std::vector<reco::CaloCluster>PFClusters, float PFPhoPhi){
01159   double PFClustPhiRMS=0;
01160   double delPhi2=0;
01161   double delPhiSum=0;
01162   double ClusSum=0;
01163   for(unsigned int c=0; c<PFClusters.size(); ++c){
01164     delPhi2=(acos(cos(PFPhoPhi-PFClusters[c].phi()))* acos(cos(PFPhoPhi-PFClusters[c].phi())) )+delPhi2;
01165     delPhiSum=delPhiSum+ acos(cos(PFPhoPhi-PFClusters[c].phi()))*PFClusters[c].energy();
01166     ClusSum=ClusSum+PFClusters[c].energy();
01167   }
01168   double meandPhi=delPhiSum/ClusSum;
01169   PFClustPhiRMS=sqrt(fabs(delPhi2/ClusSum - (meandPhi*meandPhi)));
01170   
01171   return PFClustPhiRMS;
01172 }
01173 
01174 float PFPhotonAlgo::EvaluateLCorrMVA(reco::PFClusterRef clusterRef ){
01175   float BDTG=1;
01176   PFPhotonClusters ClusterVar(clusterRef);
01177   std::pair<double, double>ClusCoor=ClusterVar.GetCrysCoor();
01178   std::pair<int, int>ClusIndex=ClusterVar.GetCrysIndex();
01179   //Local Coordinates:
01180   if(clusterRef->layer()==PFLayer:: ECAL_BARREL ){//is Barrel
01181     PFCrysEtaCrack_=ClusterVar.EtaCrack();
01182     CrysEta_=ClusCoor.first;
01183     CrysPhi_=ClusCoor.second;
01184     CrysIEta_=ClusIndex.first;
01185     CrysIPhi_=ClusIndex.second;
01186   }
01187   else{
01188     CrysX_=ClusCoor.first;
01189     CrysY_=ClusCoor.second;
01190   }
01191   //Shower Shape Variables:
01192   eSeed_= ClusterVar.E5x5Element(0, 0)/clusterRef->energy();
01193   etop_=ClusterVar.E5x5Element(0,1)/clusterRef->energy();
01194   ebottom_=ClusterVar.E5x5Element(0,-1)/clusterRef->energy();
01195   eleft_=ClusterVar.E5x5Element(-1,0)/clusterRef->energy();
01196   eright_=ClusterVar.E5x5Element(1,0)/clusterRef->energy();
01197   e1x3_=(ClusterVar.E5x5Element(0,0)+ClusterVar.E5x5Element(0,1)+ClusterVar.E5x5Element(0,-1))/clusterRef->energy();
01198   e3x1_=(ClusterVar.E5x5Element(0,0)+ClusterVar.E5x5Element(-1,0)+ClusterVar.E5x5Element(1,0))/clusterRef->energy();
01199   e1x5_=ClusterVar.E5x5Element(0,0)+ClusterVar.E5x5Element(0,-2)+ClusterVar.E5x5Element(0,-1)+ClusterVar.E5x5Element(0,1)+ClusterVar.E5x5Element(0,2);
01200   
01201   e2x5Top_=(ClusterVar.E5x5Element(-2,2)+ClusterVar.E5x5Element(-1, 2)+ClusterVar.E5x5Element(0, 2)
01202             +ClusterVar.E5x5Element(1, 2)+ClusterVar.E5x5Element(2, 2)
01203             +ClusterVar.E5x5Element(-2,1)+ClusterVar.E5x5Element(-1,1)+ClusterVar.E5x5Element(0,1)
01204             +ClusterVar.E5x5Element(1,1)+ClusterVar.E5x5Element(2,1))/clusterRef->energy();
01205   e2x5Bottom_=(ClusterVar.E5x5Element(-2,-2)+ClusterVar.E5x5Element(-1,-2)+ClusterVar.E5x5Element(0,-2)
01206                +ClusterVar.E5x5Element(1,-2)+ClusterVar.E5x5Element(2,-2)
01207                +ClusterVar.E5x5Element(-2,1)+ClusterVar.E5x5Element(-1,1)
01208                +ClusterVar.E5x5Element(0,1)+ClusterVar.E5x5Element(1,1)+ClusterVar.E5x5Element(2,1))/clusterRef->energy();
01209   e2x5Left_= (ClusterVar.E5x5Element(-2,-2)+ClusterVar.E5x5Element(-2,-1)
01210               +ClusterVar.E5x5Element(-2,0)
01211                +ClusterVar.E5x5Element(-2,1)+ClusterVar.E5x5Element(-2,2)
01212               +ClusterVar.E5x5Element(-1,-2)+ClusterVar.E5x5Element(-1,-1)+ClusterVar.E5x5Element(-1,0)
01213               +ClusterVar.E5x5Element(-1,1)+ClusterVar.E5x5Element(-1,2))/clusterRef->energy();
01214   
01215   e2x5Right_ =(ClusterVar.E5x5Element(2,-2)+ClusterVar.E5x5Element(2,-1)
01216                +ClusterVar.E5x5Element(2,0)+ClusterVar.E5x5Element(2,1)+ClusterVar.E5x5Element(2,2)
01217                +ClusterVar.E5x5Element(1,-2)+ClusterVar.E5x5Element(1,-1)+ClusterVar.E5x5Element(1,0)
01218                +ClusterVar.E5x5Element(1,1)+ClusterVar.E5x5Element(1,2))/clusterRef->energy();
01219   float centerstrip=ClusterVar.E5x5Element(0,0)+ClusterVar.E5x5Element(0, -2)
01220     +ClusterVar.E5x5Element(0,-1)+ClusterVar.E5x5Element(0,1)+ClusterVar.E5x5Element(0,2);
01221   float rightstrip=ClusterVar.E5x5Element(1, 0)+ClusterVar.E5x5Element(1,1)
01222     +ClusterVar.E5x5Element(1,2)+ClusterVar.E5x5Element(1,-1)+ClusterVar.E5x5Element(1,-2);
01223   float leftstrip=ClusterVar.E5x5Element(-1,0)+ClusterVar.E5x5Element(-1,-1)+ClusterVar.E5x5Element(-1,2)
01224     +ClusterVar.E5x5Element(-1,1)+ClusterVar.E5x5Element(-1,2);
01225   
01226   if(rightstrip>leftstrip)e2x5Max_=rightstrip+centerstrip;
01227   else e2x5Max_=leftstrip+centerstrip;
01228   e2x5Max_=e2x5Max_/clusterRef->energy();
01229   //GetCrysCoordinates(clusterRef);
01230   //fill5x5Map(clusterRef);
01231   VtxZ_=primaryVertex_.z();
01232   ClusPhi_=clusterRef->position().phi(); 
01233   ClusEta_=fabs(clusterRef->position().eta());
01234   EB=fabs(clusterRef->position().eta())/clusterRef->position().eta();
01235   logPFClusE_=log(clusterRef->energy());
01236   if(ClusEta_<1.4446){
01237     float LC_Var[26];
01238     LC_Var[0]=VtxZ_;
01239     LC_Var[1]=EB;
01240     LC_Var[2]=ClusEta_;
01241     LC_Var[3]=ClusPhi_;
01242     LC_Var[4]=logPFClusE_;
01243     LC_Var[5]=eSeed_;
01244     //top bottom left right
01245     LC_Var[6]=etop_;
01246     LC_Var[7]=ebottom_;
01247     LC_Var[8]=eleft_;
01248     LC_Var[9]=eright_;
01249     LC_Var[10]=ClusR9_;
01250     LC_Var[11]=e1x3_;
01251     LC_Var[12]=e3x1_;
01252     LC_Var[13]=Clus5x5ratio_;
01253     LC_Var[14]=e1x5_;
01254     LC_Var[15]=e2x5Max_;
01255     LC_Var[16]=e2x5Top_;
01256     LC_Var[17]=e2x5Bottom_;
01257     LC_Var[18]=e2x5Left_;
01258     LC_Var[19]=e2x5Right_;
01259     LC_Var[20]=CrysEta_;
01260     LC_Var[21]=CrysPhi_;
01261     float CrysIphiMod2=CrysIPhi_%2;
01262     float CrysIetaMod5=CrysIEta_%5;
01263     float CrysIphiMod20=CrysIPhi_%20;
01264     LC_Var[22]=CrysIphiMod2;
01265     LC_Var[23]=CrysIetaMod5;
01266     LC_Var[24]=CrysIphiMod20;   
01267     LC_Var[25]=PFCrysEtaCrack_;
01268     BDTG=ReaderLCEB_->GetResponse(LC_Var);   
01269     //cout<<"LC "<<BDTG<<endl;  
01270   }
01271   else{
01272     float LC_Var[22];
01273     LC_Var[0]=VtxZ_;
01274     LC_Var[1]=EB;
01275     LC_Var[2]=ClusEta_;
01276     LC_Var[3]=ClusPhi_;
01277     LC_Var[4]=logPFClusE_;
01278     LC_Var[5]=eSeed_;
01279     //top bottom left right
01280     LC_Var[6]=etop_;
01281     LC_Var[7]=ebottom_;
01282     LC_Var[8]=eleft_;
01283     LC_Var[9]=eright_;
01284     LC_Var[10]=ClusR9_;
01285     LC_Var[11]=e1x3_;
01286     LC_Var[12]=e3x1_;
01287     LC_Var[13]=Clus5x5ratio_;
01288     LC_Var[14]=e1x5_;
01289     LC_Var[15]=e2x5Max_;
01290     LC_Var[16]=e2x5Top_;
01291     LC_Var[17]=e2x5Bottom_;
01292     LC_Var[18]=e2x5Left_;
01293     LC_Var[19]=e2x5Right_;
01294     LC_Var[20]=CrysX_;
01295     LC_Var[21]=CrysY_;
01296     BDTG=ReaderLCEE_->GetResponse(LC_Var);   
01297     //cout<<"LC "<<BDTG<<endl;  
01298   }
01299    return BDTG;
01300   
01301 }
01302 
01303 bool PFPhotonAlgo::EvaluateSingleLegMVA(const reco::PFBlockRef& blockref, const reco::Vertex& primaryvtx, unsigned int track_index)  
01304 {  
01305   bool convtkfound=false;  
01306   const reco::PFBlock& block = *blockref;  
01307   const edm::OwnVector< reco::PFBlockElement >& elements = block.elements();  
01308   //use this to store linkdata in the associatedElements function below  
01309   PFBlock::LinkData linkData =  block.linkData();  
01310   //calculate MVA Variables  
01311   chi2=elements[track_index].trackRef()->chi2()/elements[track_index].trackRef()->ndof();  
01312   nlost=elements[track_index].trackRef()->trackerExpectedHitsInner().numberOfLostHits();  
01313   nlayers=elements[track_index].trackRef()->hitPattern().trackerLayersWithMeasurement();  
01314   track_pt=elements[track_index].trackRef()->pt();  
01315   STIP=elements[track_index].trackRefPF()->STIP();  
01316    
01317   float linked_e=0;  
01318   float linked_h=0;  
01319   std::multimap<double, unsigned int> ecalAssoTrack;  
01320   block.associatedElements( track_index,linkData,  
01321                             ecalAssoTrack,  
01322                             reco::PFBlockElement::ECAL,  
01323                             reco::PFBlock::LINKTEST_ALL );  
01324   std::multimap<double, unsigned int> hcalAssoTrack;  
01325   block.associatedElements( track_index,linkData,  
01326                             hcalAssoTrack,  
01327                             reco::PFBlockElement::HCAL,  
01328                             reco::PFBlock::LINKTEST_ALL );  
01329   if(ecalAssoTrack.size() > 0) {  
01330     for(std::multimap<double, unsigned int>::iterator itecal = ecalAssoTrack.begin();  
01331         itecal != ecalAssoTrack.end(); ++itecal) {  
01332       linked_e=linked_e+elements[itecal->second].clusterRef()->energy();  
01333     }  
01334   }  
01335   if(hcalAssoTrack.size() > 0) {  
01336     for(std::multimap<double, unsigned int>::iterator ithcal = hcalAssoTrack.begin();  
01337         ithcal != hcalAssoTrack.end(); ++ithcal) {  
01338       linked_h=linked_h+elements[ithcal->second].clusterRef()->energy();  
01339     }  
01340   }  
01341   EoverPt=linked_e/elements[track_index].trackRef()->pt();  
01342   HoverPt=linked_h/elements[track_index].trackRef()->pt();  
01343   GlobalVector rvtx(elements[track_index].trackRef()->innerPosition().X()-primaryvtx.x(),  
01344                     elements[track_index].trackRef()->innerPosition().Y()-primaryvtx.y(),  
01345                     elements[track_index].trackRef()->innerPosition().Z()-primaryvtx.z());  
01346   double vtx_phi=rvtx.phi();  
01347   //delta Phi between conversion vertex and track  
01348   del_phi=fabs(deltaPhi(vtx_phi, elements[track_index].trackRef()->innerMomentum().Phi()));  
01349   mvaValue = tmvaReader_->EvaluateMVA("BDT");  
01350   if(mvaValue > MVACUT)convtkfound=true;  
01351   return convtkfound;  
01352 }
01353 
01354 //Recover Early Conversions reconstructed as PFelectrons
01355 void PFPhotonAlgo::EarlyConversion(    
01356                                    //std::auto_ptr< reco::PFCandidateCollection > 
01357                                    //&pfElectronCandidates_,
01358                                    std::vector<reco::PFCandidate>& 
01359                                    tempElectronCandidates,
01360                                    const reco::PFBlockElementSuperCluster* sc
01361                                    ){
01362   //step 1 check temp electrons for clusters that match Photon Supercluster:
01363   // permElectronCandidates->clear();
01364   int count=0;
01365   for ( std::vector<reco::PFCandidate>::const_iterator ec=tempElectronCandidates.begin();   ec != tempElectronCandidates.end(); ++ec ) 
01366     {
01367       //      bool matched=false;
01368       int mh=ec->gsfTrackRef()->trackerExpectedHitsInner().numberOfLostHits();
01369       if(mh==0)continue;//Case where missing hits greater than zero
01370       
01371       reco::GsfTrackRef gsf=ec->gsfTrackRef();
01372       //some hoopla to get Electron SC ref
01373       
01374       if(gsf->extra().isAvailable() && gsf->extra()->seedRef().isAvailable()) 
01375         {
01376           reco::ElectronSeedRef seedRef=  gsf->extra()->seedRef().castTo<reco::ElectronSeedRef>();
01377           if(seedRef.isAvailable() && seedRef->isEcalDriven()) 
01378             {
01379               reco::SuperClusterRef ElecscRef = seedRef->caloCluster().castTo<reco::SuperClusterRef>();
01380               
01381               if(ElecscRef.isNonnull()){
01382                 //finally see if it matches:
01383                 reco::SuperClusterRef PhotscRef=sc->superClusterRef();
01384                 if(PhotscRef==ElecscRef)
01385                   {
01386                     match_ind.push_back(count);
01387                     //  matched=true; 
01388                     //cout<<"Matched Electron with Index "<<count<<" This is the electron "<<*ec<<endl;
01389                     //find that they have the same SC footprint start to collect Clusters and tracks and these will be passed to PFPhoton
01390                     reco::PFCandidate::ElementsInBlocks eleInBlocks = ec->elementsInBlocks();
01391                     for(unsigned i=0; i<eleInBlocks.size(); i++) 
01392                       {
01393                         reco::PFBlockRef blockRef = eleInBlocks[i].first;
01394                         unsigned indexInBlock = eleInBlocks[i].second;   
01395                         //const edm::OwnVector< reco::PFBlockElement >&  elements=eleInBlocks[i].first->elements();
01396                         //const reco::PFBlockElement& element = elements[indexInBlock];                 
01397                         
01398                         AddFromElectron_.push_back(indexInBlock);               
01399                       }             
01400                   }             
01401               }
01402             }     
01403         }           
01404       count++;
01405     }
01406 }