CMS 3D CMS Logo

CMSSW_4_4_3_patch1/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
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/PFBlockElementSuperCluster.h"
00011 #include "DataFormats/EgammaReco/interface/ElectronSeed.h"
00012 #include "RecoParticleFlow/PFClusterTools/interface/PFEnergyCalibration.h"
00013 #include "DataFormats/Math/interface/deltaPhi.h"
00014 #include "DataFormats/Math/interface/deltaR.h"
00015 
00016 #include <iomanip>
00017 #include <algorithm>
00018 
00019 using namespace std;
00020 using namespace reco;
00021 
00022 
00023 PFPhotonAlgo::PFPhotonAlgo(std::string mvaweightfile,  
00024                            double mvaConvCut, 
00025                            const reco::Vertex& primary,
00026                            const boost::shared_ptr<PFEnergyCalibration>& thePFEnergyCalibration,
00027                            double sumPtTrackIsoForPhoton,
00028                            double sumPtTrackIsoSlopeForPhoton
00029                            ) : 
00030   isvalid_(false), 
00031   verbosityLevel_(Silent), 
00032   MVACUT(mvaConvCut),
00033   thePFEnergyCalibration_(thePFEnergyCalibration),
00034   sumPtTrackIsoForPhoton_(sumPtTrackIsoForPhoton),
00035   sumPtTrackIsoSlopeForPhoton_(sumPtTrackIsoSlopeForPhoton)
00036 {  
00037     primaryVertex_=primary;  
00038     //Book MVA  
00039     tmvaReader_ = new TMVA::Reader("!Color:Silent");  
00040     tmvaReader_->AddVariable("del_phi",&del_phi);  
00041     tmvaReader_->AddVariable("nlayers", &nlayers);  
00042     tmvaReader_->AddVariable("chi2",&chi2);  
00043     tmvaReader_->AddVariable("EoverPt",&EoverPt);  
00044     tmvaReader_->AddVariable("HoverPt",&HoverPt);  
00045     tmvaReader_->AddVariable("track_pt", &track_pt);  
00046     tmvaReader_->AddVariable("STIP",&STIP);  
00047     tmvaReader_->AddVariable("nlost", &nlost);  
00048     tmvaReader_->BookMVA("BDT",mvaweightfile.c_str());  
00049   }
00050 
00051 void PFPhotonAlgo::RunPFPhoton(const reco::PFBlockRef&  blockRef,
00052                                std::vector<bool>& active,
00053                                std::auto_ptr<PFCandidateCollection> &pfCandidates,
00054                                std::vector<reco::PFCandidatePhotonExtra>& pfPhotonExtraCandidates,
00055                                std::vector<reco::PFCandidate> 
00056                                &tempElectronCandidates
00057 ){
00058   
00059   //std::cout<<" calling RunPFPhoton "<<std::endl;
00060   
00061   /*      For now we construct the PhotonCandidate simply from 
00062           a) adding the CORRECTED energies of each participating ECAL cluster
00063           b) build the energy-weighted direction for the Photon
00064   */
00065 
00066 
00067   // define how much is printed out for debugging.
00068   // ... will be setable via CFG file parameter
00069   verbosityLevel_ = Chatty;          // Chatty mode.
00070   
00071 
00072   // loop over all elements in the Block
00073   const edm::OwnVector< reco::PFBlockElement >&          elements         = blockRef->elements();
00074   edm::OwnVector< reco::PFBlockElement >::const_iterator ele              = elements.begin();
00075   std::vector<bool>::const_iterator                      actIter          = active.begin();
00076   PFBlock::LinkData                                      linkData         = blockRef->linkData();
00077   bool                                                   isActive         = true;
00078 
00079 
00080   if(elements.size() != active.size()) {
00081     // throw excpetion...
00082     //std::cout<<" WARNING: Size of collection and active-vectro don't agree!"<<std::endl;
00083     return;
00084   }
00085   
00086   // local vecotr to keep track of the indices of the 'elements' for the Photon candidate
00087   // once we decide to keep the candidate, the 'active' entriesd for them must be set to false
00088   std::vector<unsigned int> elemsToLock;
00089   elemsToLock.resize(0);
00090   
00091   for( ; ele != elements.end(); ++ele, ++actIter ) {
00092 
00093     // if it's not a SuperCluster, go to the next element
00094     if( !( ele->type() == reco::PFBlockElement::SC ) ) continue;
00095     
00096     // Photon kienmatics, will be updated for each identified participating element
00097     float photonEnergy_        =   0.;
00098     float photonX_             =   0.;
00099     float photonY_             =   0.;
00100     float photonZ_             =   0.;
00101     float RawEcalEne           =   0.;
00102 
00103     // Total pre-shower energy
00104     float ps1TotEne      = 0.;
00105     float ps2TotEne      = 0.;
00106     
00107     bool hasConvTrack=false;  
00108     bool hasSingleleg=false;  
00109     std::vector<unsigned int> AddClusters(0);  
00110     std::vector<unsigned int> IsoTracks(0);  
00111     std::multimap<unsigned int, unsigned int>ClusterAddPS1;  
00112     std::multimap<unsigned int, unsigned int>ClusterAddPS2;
00113     std::vector<reco::TrackRef>singleLegRef;
00114     std::vector<float>MVA_values(0);
00115     reco::ConversionRefVector ConversionsRef_;
00116     isActive = *(actIter);
00117     //cout << " Found a SuperCluster.  Energy " ;
00118     const reco::PFBlockElementSuperCluster *sc = dynamic_cast<const reco::PFBlockElementSuperCluster*>(&(*ele));
00119     //std::cout << sc->superClusterRef()->energy () << " Track/Ecal/Hcal Iso " << sc->trackIso()<< " " << sc->ecalIso() ;
00120     //std::cout << " " << sc->hcalIso() <<std::endl;
00121     if (!(sc->fromPhoton()))continue;
00122 
00123     // check the status of the SC Element... 
00124     // ..... I understand it should *always* be active, since PFElectronAlgo does not touch this (yet?) RISHI: YES
00125     if( !isActive ) {
00126       //std::cout<<" SuperCluster is NOT active.... "<<std::endl;
00127       continue;
00128     }
00129     elemsToLock.push_back(ele-elements.begin()); //add SC to elements to lock
00130     // loop over its constituent ECAL cluster
00131     std::multimap<double, unsigned int> ecalAssoPFClusters;
00132     blockRef->associatedElements( ele-elements.begin(), 
00133                                   linkData,
00134                                   ecalAssoPFClusters,
00135                                   reco::PFBlockElement::ECAL,
00136                                   reco::PFBlock::LINKTEST_ALL );
00137     
00138     // loop over the ECAL clusters linked to the iEle 
00139     if( ! ecalAssoPFClusters.size() ) {
00140       // This SC element has NO ECAL elements asigned... *SHOULD NOT HAPPEN*
00141       //std::cout<<" Found SC element with no ECAL assigned "<<std::endl;
00142       continue;
00143     }
00144     
00145     // This is basically CASE 2
00146     // .... we loop over all ECAL cluster linked to each other by this SC
00147     for(std::multimap<double, unsigned int>::iterator itecal = ecalAssoPFClusters.begin(); 
00148         itecal != ecalAssoPFClusters.end(); ++itecal) { 
00149       
00150       // to get the reference to the PF clusters, this is needed.
00151       reco::PFClusterRef clusterRef = elements[itecal->second].clusterRef();    
00152       
00153       // from the clusterRef get the energy, direction, etc
00154       //      float ClustRawEnergy = clusterRef->energy();
00155       //      float ClustEta = clusterRef->position().eta();
00156       //      float ClustPhi = clusterRef->position().phi();
00157 
00158       // initialize the vectors for the PS energies
00159       vector<double> ps1Ene(0);
00160       vector<double> ps2Ene(0);
00161       double ps1=0;  
00162       double ps2=0;  
00163       hasSingleleg=false;  
00164       hasConvTrack=false;
00165 
00166       /*
00167       cout << " My cluster index " << itecal->second 
00168            << " energy " <<  ClustRawEnergy
00169            << " eta " << ClustEta
00170            << " phi " << ClustPhi << endl;
00171       */
00172       // check if this ECAL element is still active (could have been eaten by PFElectronAlgo)
00173       // ......for now we give the PFElectron Algo *ALWAYS* Shot-Gun on the ECAL elements to the PFElectronAlgo
00174       
00175       if( !( active[itecal->second] ) ) {
00176         //std::cout<< "  .... this ECAL element is NOT active anymore. Is skipped. "<<std::endl;
00177         continue;
00178       }
00179       
00180       // ------------------------------------------------------------------------------------------
00181       // TODO: do some tests on the ECAL cluster itself, deciding to use it or not for the Photons
00182       // ..... ??? Do we need this?
00183       if ( false ) {
00184         // Check if there are a large number tracks that do not pass pre-ID around this ECAL cluster
00185         bool useIt = true;
00186         int mva_reject=0;  
00187         bool isClosest=false;  
00188         std::multimap<double, unsigned int> Trackscheck;  
00189         blockRef->associatedElements( itecal->second,  
00190                                       linkData,  
00191                                       Trackscheck,  
00192                                       reco::PFBlockElement::TRACK,  
00193                                       reco::PFBlock::LINKTEST_ALL);  
00194         for(std::multimap<double, unsigned int>::iterator track = Trackscheck.begin();  
00195             track != Trackscheck.end(); ++track) {  
00196            
00197           // first check if is it's still active  
00198           if( ! (active[track->second]) ) continue;  
00199           hasSingleleg=EvaluateSingleLegMVA(blockRef,  primaryVertex_, track->second);  
00200           //check if it is the closest linked track  
00201           std::multimap<double, unsigned int> closecheck;  
00202           blockRef->associatedElements(track->second,  
00203                                        linkData,  
00204                                        closecheck,  
00205                                        reco::PFBlockElement::ECAL,  
00206                                        reco::PFBlock::LINKTEST_ALL);  
00207           if(closecheck.begin()->second ==itecal->second)isClosest=true;  
00208           if(!hasSingleleg)mva_reject++;  
00209         }  
00210          
00211         if(mva_reject>0 &&  isClosest)useIt=false;  
00212         //if(mva_reject==1 && isClosest)useIt=false;
00213         if( !useIt ) continue;    // Go to next ECAL cluster within SC
00214       }
00215       // ------------------------------------------------------------------------------------------
00216       
00217       // We decided to keep the ECAL cluster for this Photon Candidate ...
00218       elemsToLock.push_back(itecal->second);
00219       
00220       // look for PS in this Block linked to this ECAL cluster      
00221       std::multimap<double, unsigned int> PS1Elems;
00222       std::multimap<double, unsigned int> PS2Elems;
00223       //PS Layer 1 linked to ECAL cluster
00224       blockRef->associatedElements( itecal->second,
00225                                     linkData,
00226                                     PS1Elems,
00227                                     reco::PFBlockElement::PS1,
00228                                     reco::PFBlock::LINKTEST_ALL );
00229       //PS Layer 2 linked to the ECAL cluster
00230       blockRef->associatedElements( itecal->second,
00231                                     linkData,
00232                                     PS2Elems,
00233                                     reco::PFBlockElement::PS2,
00234                                     reco::PFBlock::LINKTEST_ALL );
00235       
00236       // loop over all PS1 and compute energy
00237       for(std::multimap<double, unsigned int>::iterator iteps = PS1Elems.begin();
00238           iteps != PS1Elems.end(); ++iteps) {
00239 
00240         // first chekc if it's still active
00241         if( !(active[iteps->second]) ) continue;
00242         
00243         //Check if this PS1 is not closer to another ECAL cluster in this Block          
00244         std::multimap<double, unsigned int> ECALPS1check;  
00245         blockRef->associatedElements( iteps->second,  
00246                                       linkData,  
00247                                       ECALPS1check,  
00248                                       reco::PFBlockElement::ECAL,  
00249                                       reco::PFBlock::LINKTEST_ALL );  
00250         if(itecal->second==ECALPS1check.begin()->second)//then it is closest linked  
00251           {
00252             reco::PFClusterRef ps1ClusterRef = elements[iteps->second].clusterRef();
00253             ps1Ene.push_back( ps1ClusterRef->energy() );
00254             ps1=ps1+ps1ClusterRef->energy(); //add to total PS1
00255             // incativate this PS1 Element
00256             elemsToLock.push_back(iteps->second);
00257           }
00258       }
00259       for(std::multimap<double, unsigned int>::iterator iteps = PS2Elems.begin();
00260           iteps != PS2Elems.end(); ++iteps) {
00261 
00262         // first chekc if it's still active
00263         if( !(active[iteps->second]) ) continue;
00264         
00265         // Check if this PS2 is not closer to another ECAL cluster in this Block:
00266         std::multimap<double, unsigned int> ECALPS2check;  
00267         blockRef->associatedElements( iteps->second,  
00268                                       linkData,  
00269                                       ECALPS2check,  
00270                                       reco::PFBlockElement::ECAL,  
00271                                       reco::PFBlock::LINKTEST_ALL );  
00272         if(itecal->second==ECALPS2check.begin()->second)//is closest linked  
00273           {
00274             reco::PFClusterRef ps2ClusterRef = elements[iteps->second].clusterRef();
00275             ps2Ene.push_back( ps2ClusterRef->energy() );
00276             ps2=ps2ClusterRef->energy()+ps2; //add to total PS2
00277             // incativate this PS2 Element
00278             elemsToLock.push_back(iteps->second);
00279           }
00280       }
00281             
00282       // loop over the HCAL Clusters linked to the ECAL cluster (CASE 6)
00283       std::multimap<double, unsigned int> hcalElems;
00284       blockRef->associatedElements( itecal->second,linkData,
00285                                     hcalElems,
00286                                     reco::PFBlockElement::HCAL,
00287                                     reco::PFBlock::LINKTEST_ALL );
00288 
00289       for(std::multimap<double, unsigned int>::iterator ithcal = hcalElems.begin();
00290           ithcal != hcalElems.end(); ++ithcal) {
00291 
00292         if ( ! (active[ithcal->second] ) ) continue; // HCAL Cluster already used....
00293         
00294         // TODO: Decide if this HCAL cluster is to be used
00295         // .... based on some Physics
00296         // .... To we need to check if it's closer to any other ECAL/TRACK?
00297 
00298         bool useHcal = false;
00299         if ( !useHcal ) continue;
00300         //not locked
00301         //elemsToLock.push_back(ithcal->second);
00302       }
00303 
00304       // This is entry point for CASE 3.
00305       // .... we loop over all Tracks linked to this ECAL and check if it's labeled as conversion
00306       // This is the part for looping over all 'Conversion' Tracks
00307       std::multimap<double, unsigned int> convTracks;
00308       blockRef->associatedElements( itecal->second,
00309                                     linkData,
00310                                     convTracks,
00311                                     reco::PFBlockElement::TRACK,
00312                                     reco::PFBlock::LINKTEST_ALL);
00313       for(std::multimap<double, unsigned int>::iterator track = convTracks.begin();
00314           track != convTracks.end(); ++track) {
00315 
00316         // first check if is it's still active
00317         if( ! (active[track->second]) ) continue;
00318         
00319         // check if it's a CONV track
00320         const reco::PFBlockElementTrack * trackRef = dynamic_cast<const reco::PFBlockElementTrack*>((&elements[track->second]));        
00321         
00322         //Check if track is a Single leg from a Conversion  
00323         mvaValue=-999;  
00324         hasSingleleg=EvaluateSingleLegMVA(blockRef,  primaryVertex_, track->second);  
00325 
00326         // Daniele; example for mvaValues, do the same for single leg trackRef and convRef
00327         //          
00328         //      if(hasSingleleg)
00329         //        mvaValues.push_back(mvaValue);
00330 
00331         //If it is not then it will be used to check Track Isolation at the end  
00332         if(!hasSingleleg)  
00333           {  
00334             bool included=false;  
00335             //check if this track is already included in the vector so it is linked to an ECAL cluster that is already examined  
00336             for(unsigned int i=0; i<IsoTracks.size(); i++)  
00337               {if(IsoTracks[i]==track->second)included=true;}  
00338             if(!included)IsoTracks.push_back(track->second);  
00339           }  
00340         //For now only Pre-ID tracks that are not already identified as Conversions  
00341         if(hasSingleleg &&!(trackRef->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)))  
00342           {  
00343             elemsToLock.push_back(track->second);
00344             
00345             reco::TrackRef t_ref=elements[track->second].trackRef();
00346             bool matched=false;
00347             for(unsigned int ic=0; ic<singleLegRef.size(); ic++)
00348               if(singleLegRef[ic]==t_ref)matched=true;
00349             
00350             if(!matched){
00351               singleLegRef.push_back(t_ref);
00352               MVA_values.push_back(mvaValue);
00353             }
00354             //find all the clusters linked to this track  
00355             std::multimap<double, unsigned int> moreClusters;  
00356             blockRef->associatedElements( track->second,  
00357                                           linkData,  
00358                                           moreClusters,  
00359                                           reco::PFBlockElement::ECAL,  
00360                                           reco::PFBlock::LINKTEST_ALL);  
00361              
00362             float p_in=sqrt(elements[track->second].trackRef()->innerMomentum().x() * elements[track->second].trackRef()->innerMomentum().x() +  
00363                             elements[track->second].trackRef()->innerMomentum().y()*elements[track->second].trackRef()->innerMomentum().y()+  
00364                             elements[track->second].trackRef()->innerMomentum().z()*elements[track->second].trackRef()->innerMomentum().z());  
00365             float linked_E=0;  
00366             for(std::multimap<double, unsigned int>::iterator clust = moreClusters.begin();  
00367                 clust != moreClusters.end(); ++clust)  
00368               {  
00369                 if(!active[clust->second])continue;  
00370                 //running sum of linked energy  
00371                 linked_E=linked_E+elements[clust->second].clusterRef()->energy();  
00372                 //prevent too much energy from being added  
00373                 if(linked_E/p_in>1.5)break;  
00374                 bool included=false;  
00375                 //check if these ecal clusters are already included with the supercluster  
00376                 for(std::multimap<double, unsigned int>::iterator cluscheck = ecalAssoPFClusters.begin();  
00377                     cluscheck != ecalAssoPFClusters.end(); ++cluscheck)  
00378                   {  
00379                     if(cluscheck->second==clust->second)included=true;  
00380                   }  
00381                 if(!included)AddClusters.push_back(clust->second);//Add to a container of clusters to be Added to the Photon candidate  
00382               }  
00383           }
00384 
00385         // Possibly need to be more smart about them (CASE 5)
00386         // .... for now we simply skip non id'ed tracks
00387         if( ! (trackRef->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) ) ) continue;  
00388         hasConvTrack=true;  
00389         elemsToLock.push_back(track->second);
00390         //again look at the clusters linked to this track  
00391         //if(elements[track->second].convRef().isNonnull())
00392         //{         
00393         //  ConversionsRef_.push_back(elements[track->second].convRef());
00394         //}
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             linked_E=linked_E+elements[clust->second].clusterRef()->energy();  
00411             if(linked_E/p_in>1.5)break;  
00412             bool included=false;  
00413             for(std::multimap<double, unsigned int>::iterator cluscheck = ecalAssoPFClusters.begin();  
00414                 cluscheck != ecalAssoPFClusters.end(); ++cluscheck)  
00415               {  
00416                 if(cluscheck->second==clust->second)included=true;  
00417               }  
00418             if(!included)AddClusters.push_back(clust->second);//again only add if it is not already included with the supercluster  
00419           }
00420         
00421         // we need to check for other TRACKS linked to this conversion track, that point possibly no an ECAL cluster not included in the SC
00422         // .... This is basically CASE 4.
00423         
00424         std::multimap<double, unsigned int> moreTracks;
00425         blockRef->associatedElements( track->second,
00426                                       linkData,
00427                                       moreTracks,
00428                                       reco::PFBlockElement::TRACK,
00429                                       reco::PFBlock::LINKTEST_ALL);
00430         
00431         for(std::multimap<double, unsigned int>::iterator track2 = moreTracks.begin();
00432             track2 != moreTracks.end(); ++track2) {
00433           
00434           // first check if is it's still active
00435           if( ! (active[track2->second]) ) continue;
00436           //skip over the 1st leg already found above  
00437           if(track->second==track2->second)continue;      
00438           // check if it's a CONV track
00439           const reco::PFBlockElementTrack * track2Ref = dynamic_cast<const reco::PFBlockElementTrack*>((&elements[track2->second]));    
00440           if( ! (track2Ref->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) ) ) continue;  // Possibly need to be more smart about them (CASE 5)
00441           elemsToLock.push_back(track2->second);
00442           // so it's another active conversion track, that is in the Block and linked to the conversion track we already found
00443           // find the ECAL cluster linked to it...
00444           std::multimap<double, unsigned int> convEcal;
00445           blockRef->associatedElements( track2->second,
00446                                         linkData,
00447                                         convEcal,
00448                                         reco::PFBlockElement::ECAL,
00449                                         reco::PFBlock::LINKTEST_ALL);
00450           float p_in=sqrt(elements[track->second].trackRef()->innerMomentum().x()*elements[track->second].trackRef()->innerMomentum().x()+
00451                           elements[track->second].trackRef()->innerMomentum().y()*elements[track->second].trackRef()->innerMomentum().y()+  
00452                           elements[track->second].trackRef()->innerMomentum().z()*elements[track->second].trackRef()->innerMomentum().z());  
00453           
00454           
00455           float linked_E=0;
00456           for(std::multimap<double, unsigned int>::iterator itConvEcal = convEcal.begin();
00457               itConvEcal != convEcal.end(); ++itConvEcal) {
00458             
00459             if( ! (active[itConvEcal->second]) ) continue;
00460             bool included=false;  
00461             for(std::multimap<double, unsigned int>::iterator cluscheck = ecalAssoPFClusters.begin();  
00462                 cluscheck != ecalAssoPFClusters.end(); ++cluscheck)  
00463               {  
00464                 if(cluscheck->second==itConvEcal->second)included=true;  
00465               }
00466             linked_E=linked_E+elements[itConvEcal->second].clusterRef()->energy();
00467             if(linked_E/p_in>1.5)break;
00468             if(!included){AddClusters.push_back(itConvEcal->second);
00469             }
00470             
00471             // it's still active, so we have to add it.
00472             // CAUTION: we don't care here if it's part of the SC or not, we include it anyways
00473             
00474             // loop over the HCAL Clusters linked to the ECAL cluster (CASE 6)
00475             std::multimap<double, unsigned int> hcalElems_conv;
00476             blockRef->associatedElements( itecal->second,linkData,
00477                                           hcalElems_conv,
00478                                           reco::PFBlockElement::HCAL,
00479                                           reco::PFBlock::LINKTEST_ALL );
00480             
00481             for(std::multimap<double, unsigned int>::iterator ithcal2 = hcalElems_conv.begin();
00482                 ithcal2 != hcalElems_conv.end(); ++ithcal2) {
00483               
00484               if ( ! (active[ithcal2->second] ) ) continue; // HCAL Cluster already used....
00485               
00486               // TODO: Decide if this HCAL cluster is to be used
00487               // .... based on some Physics
00488               // .... To we need to check if it's closer to any other ECAL/TRACK?
00489               
00490               bool useHcal = true;
00491               if ( !useHcal ) continue;
00492               
00493               //elemsToLock.push_back(ithcal2->second);
00494 
00495             } // end of loop over HCAL clusters linked to the ECAL cluster from second CONVERSION leg
00496             
00497           } // end of loop over ECALs linked to second T_FROM_GAMMACONV
00498           
00499         } // end of loop over SECOND conversion leg
00500 
00501         // TODO: Do we need to check separatly if there are HCAL cluster linked to the track?
00502         
00503       } // end of loop over tracks
00504       
00505             
00506       // Calibrate the Added ECAL energy
00507       float addedCalibEne=0;
00508       float addedRawEne=0;
00509       std::vector<double>AddedPS1(0);
00510       std::vector<double>AddedPS2(0);  
00511       double addedps1=0;  
00512       double addedps2=0;  
00513       for(unsigned int i=0; i<AddClusters.size(); i++)  
00514         {  
00515           std::multimap<double, unsigned int> PS1Elems_conv;  
00516           std::multimap<double, unsigned int> PS2Elems_conv;  
00517           blockRef->associatedElements(AddClusters[i],  
00518                                        linkData,  
00519                                        PS1Elems_conv,  
00520                                        reco::PFBlockElement::PS1,  
00521                                        reco::PFBlock::LINKTEST_ALL );  
00522           blockRef->associatedElements( AddClusters[i],  
00523                                         linkData,  
00524                                         PS2Elems_conv,  
00525                                         reco::PFBlockElement::PS2,  
00526                                         reco::PFBlock::LINKTEST_ALL );  
00527            
00528           for(std::multimap<double, unsigned int>::iterator iteps = PS1Elems_conv.begin();  
00529               iteps != PS1Elems_conv.end(); ++iteps)  
00530             {  
00531               if(!active[iteps->second])continue;  
00532               std::multimap<double, unsigned int> PS1Elems_check;  
00533               blockRef->associatedElements(iteps->second,  
00534                                            linkData,  
00535                                            PS1Elems_check,  
00536                                            reco::PFBlockElement::ECAL,  
00537                                            reco::PFBlock::LINKTEST_ALL );  
00538               if(PS1Elems_check.begin()->second==AddClusters[i])  
00539                 {  
00540                    
00541                   reco::PFClusterRef ps1ClusterRef = elements[iteps->second].clusterRef();  
00542                   AddedPS1.push_back(ps1ClusterRef->energy());  
00543                   addedps1=addedps1+ps1ClusterRef->energy();  
00544                   elemsToLock.push_back(iteps->second);  
00545                 }  
00546             }  
00547            
00548           for(std::multimap<double, unsigned int>::iterator iteps = PS2Elems_conv.begin();  
00549               iteps != PS2Elems_conv.end(); ++iteps) {  
00550             if(!active[iteps->second])continue;  
00551             std::multimap<double, unsigned int> PS2Elems_check;  
00552             blockRef->associatedElements(iteps->second,  
00553                                          linkData,  
00554                                          PS2Elems_check,  
00555                                          reco::PFBlockElement::ECAL,  
00556                                          reco::PFBlock::LINKTEST_ALL );  
00557              
00558             if(PS2Elems_check.begin()->second==AddClusters[i])  
00559               {  
00560                 reco::PFClusterRef ps2ClusterRef = elements[iteps->second].clusterRef();  
00561                 AddedPS2.push_back(ps2ClusterRef->energy());  
00562                 addedps2=addedps2+ps2ClusterRef->energy();  
00563                 elemsToLock.push_back(iteps->second);  
00564               }  
00565           }  
00566           reco::PFClusterRef AddclusterRef = elements[AddClusters[i]].clusterRef();  
00567           addedRawEne = AddclusterRef->energy()+addedRawEne;  
00568           addedCalibEne = thePFEnergyCalibration_->energyEm(*AddclusterRef,AddedPS1,AddedPS2,false)+addedCalibEne;  
00569           AddedPS2.clear(); 
00570           AddedPS1.clear();  
00571           elemsToLock.push_back(AddClusters[i]);  
00572         }  
00573       AddClusters.clear();
00574       float EE = thePFEnergyCalibration_->energyEm(*clusterRef,ps1Ene,ps2Ene,false)+addedCalibEne;  
00575       //cout<<"Original Energy "<<EE<<"Added Energy "<<addedCalibEne<<endl;
00576       
00577       photonEnergy_ +=  EE;
00578       RawEcalEne    +=  clusterRef->energy()+addedRawEne;
00579       photonX_      +=  EE * clusterRef->position().X();
00580       photonY_      +=  EE * clusterRef->position().Y();
00581       photonZ_      +=  EE * clusterRef->position().Z();                
00582       ps1TotEne     +=  ps1+addedps1;
00583       ps2TotEne     +=  ps2+addedps2;
00584     } // end of loop over all ECAL cluster within this SC
00585     AddFromElectron_.clear();
00586     float Elec_energy=0;
00587     float Elec_rawEcal=0;
00588     float Elec_totPs1=0;
00589     float Elec_totPs2=0;
00590     float ElectronX=0;
00591     float ElectronY=0;
00592     float ElectronZ=0;  
00593     std::vector<double>AddedPS1(0);
00594     std::vector<double>AddedPS2(0);
00595     
00596     EarlyConversion(    
00597             tempElectronCandidates,
00598             sc
00599             );   
00600     
00601     if(AddFromElectron_.size()>0)
00602       { 
00603         //collect elements from early Conversions that are reconstructed as Electrons
00604         
00605         for(std::vector<unsigned int>::const_iterator it = 
00606               AddFromElectron_.begin();
00607             it != AddFromElectron_.end(); ++it)
00608           {
00609             
00610             if(elements[*it].type()== reco::PFBlockElement::ECAL)
00611               {
00612                 //cout<<"Cluster ind "<<*it<<endl;
00613                 AddedPS1.clear();
00614                 AddedPS2.clear();
00615                 unsigned int index=*it;
00616                 reco::PFClusterRef clusterRef = 
00617                 elements[index].clusterRef();
00618                 //match to PS1 and PS2 to this cluster for calibration
00619                 Elec_rawEcal=Elec_rawEcal+
00620                   elements[index].clusterRef()->energy();
00621                 std::multimap<double, unsigned int> PS1Elems;  
00622                 std::multimap<double, unsigned int> PS2Elems;  
00623                 
00624                 blockRef->associatedElements(index,  
00625                                              linkData,  
00626                                              PS1Elems,                                               reco::PFBlockElement::PS1,  
00627                                              reco::PFBlock::LINKTEST_ALL );  
00628                 blockRef->associatedElements( index,  
00629                                               linkData,  
00630                                               PS2Elems,  
00631                                               reco::PFBlockElement::PS2,  
00632                                               reco::PFBlock::LINKTEST_ALL );
00633                 
00634                 
00635                 for(std::multimap<double, unsigned int>::iterator iteps = 
00636                       PS1Elems.begin();  
00637                     iteps != PS1Elems.end(); ++iteps) 
00638                   {  
00639                     std::multimap<double, unsigned int> Clustcheck;                         blockRef->associatedElements( iteps->second,                                                                   linkData,  
00640                                                                                                                           Clustcheck,  
00641                                                                                                                           reco::PFBlockElement::ECAL,  
00642                                                                                                                           reco::PFBlock::LINKTEST_ALL );
00643                     if(Clustcheck.begin()->second==index)
00644                       {
00645                         AddedPS1.push_back(elements[iteps->second].clusterRef()->energy());
00646                         Elec_totPs1=Elec_totPs1+elements[iteps->second].clusterRef()->energy();
00647                       }
00648                   }
00649                 
00650                 for(std::multimap<double, unsigned int>::iterator iteps = 
00651                       PS2Elems.begin();  
00652                     iteps != PS2Elems.end(); ++iteps) 
00653                   {  
00654                     std::multimap<double, unsigned int> Clustcheck;                         blockRef->associatedElements( iteps->second,                                                                   linkData,  
00655                                                                                                                           Clustcheck,  
00656                                                                                                                           reco::PFBlockElement::ECAL,  
00657                                                                                                                           reco::PFBlock::LINKTEST_ALL );
00658                     if(Clustcheck.begin()->second==index)
00659                       {
00660                         AddedPS2.push_back(elements[iteps->second].clusterRef()->energy());
00661                         Elec_totPs2=Elec_totPs2+elements[iteps->second].clusterRef()->energy();
00662                       }
00663                   }
00664                 
00665               //energy calibration 
00666                 float EE=thePFEnergyCalibration_->
00667                   energyEm(*clusterRef,AddedPS1,AddedPS2,false);
00668                 Elec_energy    += EE;
00669                 ElectronX      +=  EE * clusterRef->position().X();
00670                 ElectronY      +=  EE * clusterRef->position().Y();
00671                 ElectronZ      +=  EE * clusterRef->position().Z();
00672               
00673               }
00674           }
00675         
00676       }
00677  
00678     //std::cout<<"Added Energy to Photon "<<Elec_energy<<" to "<<photonEnergy_<<std::endl;   
00679       photonEnergy_ +=  Elec_energy;
00680       RawEcalEne    +=  Elec_rawEcal;
00681       photonX_      +=  ElectronX;
00682       photonY_      +=  ElectronY;
00683       photonZ_      +=  ElectronZ;              
00684       ps1TotEne     +=  Elec_totPs1;
00685       ps2TotEne     +=  Elec_totPs2;
00686     
00687     // we've looped over all ECAL clusters, ready to generate PhotonCandidate
00688     if( ! (photonEnergy_ > 0.) ) continue;    // This SC is not a Photon Candidate
00689     float sum_track_pt=0;
00690     //Now check if there are tracks failing isolation outside of the Jurassic isolation region  
00691     for(unsigned int i=0; i<IsoTracks.size(); i++)sum_track_pt=sum_track_pt+elements[IsoTracks[i]].trackRef()->pt();  
00692     
00693 
00694 
00695     math::XYZVector photonPosition(photonX_,
00696                                    photonY_,
00697                                    photonZ_);
00698 
00699     math::XYZVector photonDirection=photonPosition.Unit();
00700     
00701     math::XYZTLorentzVector photonMomentum(photonEnergy_* photonDirection.X(),
00702                                            photonEnergy_* photonDirection.Y(),
00703                                            photonEnergy_* photonDirection.Z(),
00704                                            photonEnergy_           );
00705 
00706     if(sum_track_pt>(sumPtTrackIsoForPhoton_ + sumPtTrackIsoSlopeForPhoton_ * photonMomentum.pt()))
00707       {
00708         //cout<<"Hit Continue "<<endl;
00709         match_ind.clear(); //release the matched Electron candidates
00710         continue;
00711       }
00712 
00713         //THIS SC is not a Photon it fails track Isolation
00714     //if(sum_track_pt>(2+ 0.001* photonMomentum.pt()))
00715     //continue;//THIS SC is not a Photon it fails track Isolation
00716 
00717     /*
00718     std::cout<<" Created Photon with energy = "<<photonEnergy_<<std::endl;
00719     std::cout<<"                         pT = "<<photonMomentum.pt()<<std::endl;
00720     std::cout<<"                     RawEne = "<<RawEcalEne<<std::endl;
00721     std::cout<<"                          E = "<<photonMomentum.e()<<std::endl;
00722     std::cout<<"                        eta = "<<photonMomentum.eta()<<std::endl;
00723     std::cout<<"             TrackIsolation = "<< sum_track_pt <<std::endl;
00724     */
00725 
00726     reco::PFCandidate photonCand(0,photonMomentum, reco::PFCandidate::gamma);
00727     
00728     photonCand.setPs1Energy(ps1TotEne);
00729     photonCand.setPs2Energy(ps2TotEne);
00730     photonCand.setEcalEnergy(RawEcalEne,photonEnergy_);
00731     photonCand.setHcalEnergy(0.,0.);
00732     photonCand.set_mva_nothing_gamma(1.);  
00733     photonCand.setSuperClusterRef(sc->superClusterRef());
00734     math::XYZPoint v(primaryVertex_.x(), primaryVertex_.y(), primaryVertex_.z());
00735     photonCand.setVertex( v  );
00736     if(hasConvTrack || hasSingleleg)photonCand.setFlag( reco::PFCandidate::GAMMA_TO_GAMMACONV, true);
00737     int matches=match_ind.size();
00738     int count=0;
00739     for ( std::vector<reco::PFCandidate>::const_iterator ec=tempElectronCandidates.begin();   ec != tempElectronCandidates.end(); ++ec ){
00740       for(int i=0; i<matches; i++)
00741         {
00742           if(count==match_ind[i])photonCand.addDaughter(*ec);
00743           count++;
00744         }
00745     }
00746     //photonCand.setPositionAtECALEntrance(math::XYZPointF(photonMom_.position()));
00747     // set isvalid_ to TRUE since we've found at least one photon candidate
00748     isvalid_ = true;
00749     // push back the candidate into the collection ...
00750     //Add Elements from Electron
00751         for(std::vector<unsigned int>::const_iterator it = 
00752               AddFromElectron_.begin();
00753             it != AddFromElectron_.end(); ++it)photonCand.addElementInBlock(blockRef,*it);
00754 
00755 
00756     // ... and lock all elemts used
00757     for(std::vector<unsigned int>::const_iterator it = elemsToLock.begin();
00758         it != elemsToLock.end(); ++it)
00759       {
00760         if(active[*it])
00761           {
00762             photonCand.addElementInBlock(blockRef,*it);
00763             if( elements[*it].type() == reco::PFBlockElement::TRACK  )
00764               {
00765                 if(elements[*it].convRef().isNonnull())
00766                   {
00767                     //make sure it is not stored already as the partner track
00768                     bool matched=false;
00769                     for(unsigned int ic = 0; ic < ConversionsRef_.size(); ic++)
00770                       {
00771                         if(ConversionsRef_[ic]==elements[*it].convRef())matched=true;
00772                       }
00773                     if(!matched)ConversionsRef_.push_back(elements[*it].convRef());
00774                   }
00775               }
00776           }
00777         active[*it] = false;    
00778       }
00779     
00780     // here add the extra information
00781     PFCandidatePhotonExtra myExtra(sc->superClusterRef());
00782 
00783     //    Daniele example for mvaValues
00784     //    do the same for single leg trackRef and convRef
00785     for(unsigned int ic = 0; ic < MVA_values.size(); ic++)
00786       {
00787         myExtra.addSingleLegConvMva(MVA_values[ic]);
00788         myExtra.addSingleLegConvTrackRef(singleLegRef[ic]);
00789         //cout<<"Single Leg Tracks "<<singleLegRef[ic]->pt()<<" MVA "<<MVA_values[ic]<<endl;
00790       }
00791     for(unsigned int ic = 0; ic < ConversionsRef_.size(); ic++)
00792       {
00793         myExtra.addConversionRef(ConversionsRef_[ic]);
00794         //cout<<"Conversion Pairs "<<ConversionsRef_[ic]->pairMomentum()<<endl;
00795       }
00796     pfPhotonExtraCandidates.push_back(myExtra);
00797     pfCandidates->push_back(photonCand);
00798     // ... and reset the vector
00799     elemsToLock.resize(0);
00800     hasConvTrack=false;
00801     hasSingleleg=false;
00802   } // end of loops over all elements in block
00803   
00804   return;
00805 
00806 }
00807 bool PFPhotonAlgo::EvaluateSingleLegMVA(const reco::PFBlockRef& blockref, const reco::Vertex& primaryvtx, unsigned int track_index)  
00808 {  
00809   bool convtkfound=false;  
00810   const reco::PFBlock& block = *blockref;  
00811   const edm::OwnVector< reco::PFBlockElement >& elements = block.elements();  
00812   //use this to store linkdata in the associatedElements function below  
00813   PFBlock::LinkData linkData =  block.linkData();  
00814   //calculate MVA Variables  
00815   chi2=elements[track_index].trackRef()->chi2()/elements[track_index].trackRef()->ndof();  
00816   nlost=elements[track_index].trackRef()->trackerExpectedHitsInner().numberOfLostHits();  
00817   nlayers=elements[track_index].trackRef()->hitPattern().trackerLayersWithMeasurement();  
00818   track_pt=elements[track_index].trackRef()->pt();  
00819   STIP=elements[track_index].trackRefPF()->STIP();  
00820    
00821   float linked_e=0;  
00822   float linked_h=0;  
00823   std::multimap<double, unsigned int> ecalAssoTrack;  
00824   block.associatedElements( track_index,linkData,  
00825                             ecalAssoTrack,  
00826                             reco::PFBlockElement::ECAL,  
00827                             reco::PFBlock::LINKTEST_ALL );  
00828   std::multimap<double, unsigned int> hcalAssoTrack;  
00829   block.associatedElements( track_index,linkData,  
00830                             hcalAssoTrack,  
00831                             reco::PFBlockElement::HCAL,  
00832                             reco::PFBlock::LINKTEST_ALL );  
00833   if(ecalAssoTrack.size() > 0) {  
00834     for(std::multimap<double, unsigned int>::iterator itecal = ecalAssoTrack.begin();  
00835         itecal != ecalAssoTrack.end(); ++itecal) {  
00836       linked_e=linked_e+elements[itecal->second].clusterRef()->energy();  
00837     }  
00838   }  
00839   if(hcalAssoTrack.size() > 0) {  
00840     for(std::multimap<double, unsigned int>::iterator ithcal = hcalAssoTrack.begin();  
00841         ithcal != hcalAssoTrack.end(); ++ithcal) {  
00842       linked_h=linked_h+elements[ithcal->second].clusterRef()->energy();  
00843     }  
00844   }  
00845   EoverPt=linked_e/elements[track_index].trackRef()->pt();  
00846   HoverPt=linked_h/elements[track_index].trackRef()->pt();  
00847   GlobalVector rvtx(elements[track_index].trackRef()->innerPosition().X()-primaryvtx.x(),  
00848                     elements[track_index].trackRef()->innerPosition().Y()-primaryvtx.y(),  
00849                     elements[track_index].trackRef()->innerPosition().Z()-primaryvtx.z());  
00850   double vtx_phi=rvtx.phi();  
00851   //delta Phi between conversion vertex and track  
00852   del_phi=fabs(deltaPhi(vtx_phi, elements[track_index].trackRef()->innerMomentum().Phi()));  
00853   mvaValue = tmvaReader_->EvaluateMVA("BDT");  
00854   if(mvaValue > MVACUT)convtkfound=true;  
00855   return convtkfound;  
00856 }
00857 
00858 //Recover Early Conversions reconstructed as PFelectrons
00859 void PFPhotonAlgo::EarlyConversion(    
00860                                    //std::auto_ptr< reco::PFCandidateCollection > 
00861                                    //&pfElectronCandidates_,
00862                                    std::vector<reco::PFCandidate>& 
00863                                    tempElectronCandidates,
00864                                    const reco::PFBlockElementSuperCluster* sc
00865                                    ){
00866   //step 1 check temp electrons for clusters that match Photon Supercluster:
00867   // permElectronCandidates->clear();
00868   int count=0;
00869   for ( std::vector<reco::PFCandidate>::const_iterator ec=tempElectronCandidates.begin();   ec != tempElectronCandidates.end(); ++ec ) 
00870     {
00871       bool matched=false;
00872       int mh=ec->gsfTrackRef()->trackerExpectedHitsInner().numberOfLostHits();
00873       if(mh==0)continue;//Case where missing hits greater than zero
00874       
00875       reco::GsfTrackRef gsf=ec->gsfTrackRef();
00876       //some hoopla to get Electron SC ref
00877       
00878       if(gsf->extra().isAvailable() && gsf->extra()->seedRef().isAvailable()) 
00879         {
00880           reco::ElectronSeedRef seedRef=  gsf->extra()->seedRef().castTo<reco::ElectronSeedRef>();
00881           if(seedRef.isAvailable() && seedRef->isEcalDriven()) 
00882             {
00883               reco::SuperClusterRef ElecscRef = seedRef->caloCluster().castTo<reco::SuperClusterRef>();
00884               
00885               if(ElecscRef.isNonnull()){
00886                 //finally see if it matches:
00887                 reco::SuperClusterRef PhotscRef=sc->superClusterRef();
00888                 
00889                 if(PhotscRef==ElecscRef)
00890                   {
00891                     match_ind.push_back(count);
00892                     matched=true; 
00893                     //cout<<"Matched Electron with Index "<<count<<" This is the electron "<<*ec<<endl;
00894                     //find that they have the same SC footprint start to collect Clusters and tracks and these will be passed to PFPhoton
00895                     reco::PFCandidate::ElementsInBlocks eleInBlocks = ec->elementsInBlocks();
00896                     for(unsigned i=0; i<eleInBlocks.size(); i++) 
00897                       {
00898                         reco::PFBlockRef blockRef = eleInBlocks[i].first;
00899                         unsigned indexInBlock = eleInBlocks[i].second;   
00900                         //const edm::OwnVector< reco::PFBlockElement >&  elements=eleInBlocks[i].first->elements();
00901                         //const reco::PFBlockElement& element = elements[indexInBlock];                 
00902                         
00903                         AddFromElectron_.push_back(indexInBlock);               
00904                       }             
00905                   }             
00906               }
00907             }     
00908         }           
00909       count++;
00910     }
00911 }