CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/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 
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   isvalid_(false), 
00028   verbosityLevel_(Silent), 
00029   MVACUT(mvaConvCut),
00030   thePFEnergyCalibration_(thePFEnergyCalibration)
00031 {  
00032     primaryVertex_=primary;  
00033     //Book MVA  
00034     tmvaReader_ = new TMVA::Reader("!Color:Silent");  
00035     tmvaReader_->AddVariable("del_phi",&del_phi);  
00036     tmvaReader_->AddVariable("nlayers", &nlayers);  
00037     tmvaReader_->AddVariable("chi2",&chi2);  
00038     tmvaReader_->AddVariable("EoverPt",&EoverPt);  
00039     tmvaReader_->AddVariable("HoverPt",&HoverPt);  
00040     tmvaReader_->AddVariable("track_pt", &track_pt);  
00041     tmvaReader_->AddVariable("STIP",&STIP);  
00042     tmvaReader_->AddVariable("nlost", &nlost);  
00043     tmvaReader_->BookMVA("BDT",mvaweightfile.c_str());  
00044   }
00045 
00046 void PFPhotonAlgo::RunPFPhoton(const reco::PFBlockRef&  blockRef,
00047                                std::vector<bool>& active,
00048                                std::auto_ptr<PFCandidateCollection> &pfCandidates){
00049   
00050   //std::cout<<" calling RunPFPhoton "<<std::endl;
00051   
00052   /*      For now we construct the PhotonCandidate simply from 
00053           a) adding the CORRECTED energies of each participating ECAL cluster
00054           b) build the energy-weighted direction for the Photon
00055   */
00056 
00057 
00058   // define how much is printed out for debugging.
00059   // ... will be setable via CFG file parameter
00060   verbosityLevel_ = Chatty;          // Chatty mode.
00061   
00062 
00063   // loop over all elements in the Block
00064   const edm::OwnVector< reco::PFBlockElement >&          elements         = blockRef->elements();
00065   edm::OwnVector< reco::PFBlockElement >::const_iterator ele              = elements.begin();
00066   std::vector<bool>::const_iterator                      actIter          = active.begin();
00067   PFBlock::LinkData                                      linkData         = blockRef->linkData();
00068   bool                                                   isActive         = true;
00069 
00070   if(elements.size() != active.size()) {
00071     // throw excpetion...
00072     //std::cout<<" WARNING: Size of collection and active-vectro don't agree!"<<std::endl;
00073     return;
00074   }
00075   
00076   // local vecotr to keep track of the indices of the 'elements' for the Photon candidate
00077   // once we decide to keep the candidate, the 'active' entriesd for them must be set to false
00078   std::vector<unsigned int> elemsToLock;
00079   elemsToLock.resize(0);
00080   
00081   for( ; ele != elements.end(); ++ele, ++actIter ) {
00082 
00083     // if it's not a SuperCluster, go to the next element
00084     if( !( ele->type() == reco::PFBlockElement::SC ) ) continue;
00085     
00086     // Photon kienmatics, will be updated for each identified participating element
00087     float photonEnergy_        =   0.;
00088     float photonX_             =   0.;
00089     float photonY_             =   0.;
00090     float photonZ_             =   0.;
00091     float RawEcalEne           =   0.;
00092 
00093     // Total pre-shower energy
00094     float ps1TotEne      = 0.;
00095     float ps2TotEne      = 0.;
00096     
00097     bool hasConvTrack=false;  
00098     bool hasSingleleg=false;  
00099     std::vector<unsigned int> AddClusters(0);  
00100     std::vector<unsigned int> IsoTracks(0);  
00101     std::multimap<unsigned int, unsigned int>ClusterAddPS1;  
00102     std::multimap<unsigned int, unsigned int>ClusterAddPS2;
00103 
00104     isActive = *(actIter);
00105     //cout << " Found a SuperCluster.  Energy " ;
00106     const reco::PFBlockElementSuperCluster *sc = dynamic_cast<const reco::PFBlockElementSuperCluster*>(&(*ele));
00107     //std::cout << sc->superClusterRef()->energy () << " Track/Ecal/Hcal Iso " << sc->trackIso()<< " " << sc->ecalIso() ;
00108     //std::cout << " " << sc->hcalIso() <<std::endl;
00109     if (!(sc->fromPhoton()))continue;
00110 
00111     // check the status of the SC Element... 
00112     // ..... I understand it should *always* be active, since PFElectronAlgo does not touch this (yet?) RISHI: YES
00113     if( !isActive ) {
00114       //std::cout<<" SuperCluster is NOT active.... "<<std::endl;
00115       continue;
00116     }
00117     elemsToLock.push_back(ele-elements.begin()); //add SC to elements to lock
00118     // loop over its constituent ECAL cluster
00119     std::multimap<double, unsigned int> ecalAssoPFClusters;
00120     blockRef->associatedElements( ele-elements.begin(), 
00121                                   linkData,
00122                                   ecalAssoPFClusters,
00123                                   reco::PFBlockElement::ECAL,
00124                                   reco::PFBlock::LINKTEST_ALL );
00125     
00126     // loop over the ECAL clusters linked to the iEle 
00127     if( ! ecalAssoPFClusters.size() ) {
00128       // This SC element has NO ECAL elements asigned... *SHOULD NOT HAPPEN*
00129       //std::cout<<" Found SC element with no ECAL assigned "<<std::endl;
00130       continue;
00131     }
00132     
00133     // This is basically CASE 2
00134     // .... we loop over all ECAL cluster linked to each other by this SC
00135     for(std::multimap<double, unsigned int>::iterator itecal = ecalAssoPFClusters.begin(); 
00136         itecal != ecalAssoPFClusters.end(); ++itecal) { 
00137       
00138       // to get the reference to the PF clusters, this is needed.
00139       reco::PFClusterRef clusterRef = elements[itecal->second].clusterRef();    
00140       
00141       // from the clusterRef get the energy, direction, etc
00142       //      float ClustRawEnergy = clusterRef->energy();
00143       //      float ClustEta = clusterRef->position().eta();
00144       //      float ClustPhi = clusterRef->position().phi();
00145 
00146       // initialize the vectors for the PS energies
00147       vector<double> ps1Ene(0);
00148       vector<double> ps2Ene(0);
00149       double ps1=0;  
00150       double ps2=0;  
00151       hasSingleleg=false;  
00152       hasConvTrack=false;
00153 
00154       /*
00155       cout << " My cluster index " << itecal->second 
00156            << " energy " <<  ClustRawEnergy
00157            << " eta " << ClustEta
00158            << " phi " << ClustPhi << endl;
00159       */
00160       // check if this ECAL element is still active (could have been eaten by PFElectronAlgo)
00161       // ......for now we give the PFElectron Algo *ALWAYS* Shot-Gun on the ECAL elements to the PFElectronAlgo
00162       
00163       if( !( active[itecal->second] ) ) {
00164         //std::cout<< "  .... this ECAL element is NOT active anymore. Is skipped. "<<std::endl;
00165         continue;
00166       }
00167       
00168       // ------------------------------------------------------------------------------------------
00169       // TODO: do some tests on the ECAL cluster itself, deciding to use it or not for the Photons
00170       // ..... ??? Do we need this?
00171       if ( false ) {
00172         // Check if there are a large number tracks that do not pass pre-ID around this ECAL cluster
00173         bool useIt = true;
00174         int mva_reject=0;  
00175         bool isClosest=false;  
00176         std::multimap<double, unsigned int> Trackscheck;  
00177         blockRef->associatedElements( itecal->second,  
00178                                       linkData,  
00179                                       Trackscheck,  
00180                                       reco::PFBlockElement::TRACK,  
00181                                       reco::PFBlock::LINKTEST_ALL);  
00182         for(std::multimap<double, unsigned int>::iterator track = Trackscheck.begin();  
00183             track != Trackscheck.end(); ++track) {  
00184            
00185           // first check if is it's still active  
00186           if( ! (active[track->second]) ) continue;  
00187           hasSingleleg=EvaluateSingleLegMVA(blockRef,  primaryVertex_, track->second);  
00188           //check if it is the closest linked track  
00189           std::multimap<double, unsigned int> closecheck;  
00190           blockRef->associatedElements(track->second,  
00191                                        linkData,  
00192                                        closecheck,  
00193                                        reco::PFBlockElement::ECAL,  
00194                                        reco::PFBlock::LINKTEST_ALL);  
00195           if(closecheck.begin()->second ==itecal->second)isClosest=true;  
00196           if(!hasSingleleg)mva_reject++;  
00197         }  
00198          
00199         if(mva_reject>0 &&  isClosest)useIt=false;  
00200         //if(mva_reject==1 && isClosest)useIt=false;
00201         if( !useIt ) continue;    // Go to next ECAL cluster within SC
00202       }
00203       // ------------------------------------------------------------------------------------------
00204       
00205       // We decided to keep the ECAL cluster for this Photon Candidate ...
00206       elemsToLock.push_back(itecal->second);
00207       
00208       // look for PS in this Block linked to this ECAL cluster      
00209       std::multimap<double, unsigned int> PS1Elems;
00210       std::multimap<double, unsigned int> PS2Elems;
00211       //PS Layer 1 linked to ECAL cluster
00212       blockRef->associatedElements( itecal->second,
00213                                     linkData,
00214                                     PS1Elems,
00215                                     reco::PFBlockElement::PS1,
00216                                     reco::PFBlock::LINKTEST_ALL );
00217       //PS Layer 2 linked to the ECAL cluster
00218       blockRef->associatedElements( itecal->second,
00219                                     linkData,
00220                                     PS2Elems,
00221                                     reco::PFBlockElement::PS2,
00222                                     reco::PFBlock::LINKTEST_ALL );
00223       
00224       // loop over all PS1 and compute energy
00225       for(std::multimap<double, unsigned int>::iterator iteps = PS1Elems.begin();
00226           iteps != PS1Elems.end(); ++iteps) {
00227 
00228         // first chekc if it's still active
00229         if( !(active[iteps->second]) ) continue;
00230         
00231         //Check if this PS1 is not closer to another ECAL cluster in this Block          
00232         std::multimap<double, unsigned int> ECALPS1check;  
00233         blockRef->associatedElements( iteps->second,  
00234                                       linkData,  
00235                                       ECALPS1check,  
00236                                       reco::PFBlockElement::ECAL,  
00237                                       reco::PFBlock::LINKTEST_ALL );  
00238         if(itecal->second==ECALPS1check.begin()->second)//then it is closest linked  
00239           {
00240             reco::PFClusterRef ps1ClusterRef = elements[iteps->second].clusterRef();
00241             ps1Ene.push_back( ps1ClusterRef->energy() );
00242             ps1=ps1+ps1ClusterRef->energy(); //add to total PS1
00243             // incativate this PS1 Element
00244             elemsToLock.push_back(iteps->second);
00245           }
00246       }
00247       for(std::multimap<double, unsigned int>::iterator iteps = PS2Elems.begin();
00248           iteps != PS2Elems.end(); ++iteps) {
00249 
00250         // first chekc if it's still active
00251         if( !(active[iteps->second]) ) continue;
00252         
00253         // Check if this PS2 is not closer to another ECAL cluster in this Block:
00254         std::multimap<double, unsigned int> ECALPS2check;  
00255         blockRef->associatedElements( iteps->second,  
00256                                       linkData,  
00257                                       ECALPS2check,  
00258                                       reco::PFBlockElement::ECAL,  
00259                                       reco::PFBlock::LINKTEST_ALL );  
00260         if(itecal->second==ECALPS2check.begin()->second)//is closest linked  
00261           {
00262             reco::PFClusterRef ps2ClusterRef = elements[iteps->second].clusterRef();
00263             ps2Ene.push_back( ps2ClusterRef->energy() );
00264             ps2=ps2ClusterRef->energy()+ps2; //add to total PS2
00265             // incativate this PS2 Element
00266             elemsToLock.push_back(iteps->second);
00267           }
00268       }
00269             
00270       // loop over the HCAL Clusters linked to the ECAL cluster (CASE 6)
00271       std::multimap<double, unsigned int> hcalElems;
00272       blockRef->associatedElements( itecal->second,linkData,
00273                                     hcalElems,
00274                                     reco::PFBlockElement::HCAL,
00275                                     reco::PFBlock::LINKTEST_ALL );
00276 
00277       for(std::multimap<double, unsigned int>::iterator ithcal = hcalElems.begin();
00278           ithcal != hcalElems.end(); ++ithcal) {
00279 
00280         if ( ! (active[ithcal->second] ) ) continue; // HCAL Cluster already used....
00281         
00282         // TODO: Decide if this HCAL cluster is to be used
00283         // .... based on some Physics
00284         // .... To we need to check if it's closer to any other ECAL/TRACK?
00285 
00286         bool useHcal = false;
00287         if ( !useHcal ) continue;
00288         //not locked
00289         //elemsToLock.push_back(ithcal->second);
00290       }
00291 
00292       // This is entry point for CASE 3.
00293       // .... we loop over all Tracks linked to this ECAL and check if it's labeled as conversion
00294       // This is the part for looping over all 'Conversion' Tracks
00295       std::multimap<double, unsigned int> convTracks;
00296       blockRef->associatedElements( itecal->second,
00297                                     linkData,
00298                                     convTracks,
00299                                     reco::PFBlockElement::TRACK,
00300                                     reco::PFBlock::LINKTEST_ALL);
00301       for(std::multimap<double, unsigned int>::iterator track = convTracks.begin();
00302           track != convTracks.end(); ++track) {
00303 
00304         // first check if is it's still active
00305         if( ! (active[track->second]) ) continue;
00306         
00307         // check if it's a CONV track
00308         const reco::PFBlockElementTrack * trackRef = dynamic_cast<const reco::PFBlockElementTrack*>((&elements[track->second]));        
00309         
00310         //Check if track is a Single leg from a Conversion  
00311         mvaValue=-999;  
00312         hasSingleleg=EvaluateSingleLegMVA(blockRef,  primaryVertex_, track->second);  
00313         //If it is not then it will be used to check Track Isolation at the end  
00314         if(!hasSingleleg)  
00315           {  
00316             bool included=false;  
00317             //check if this track is already included in the vector so it is linked to an ECAL cluster that is already examined  
00318             for(unsigned int i=0; i<IsoTracks.size(); i++)  
00319               {if(IsoTracks[i]==track->second)included=true;}  
00320             if(!included)IsoTracks.push_back(track->second);  
00321           }  
00322         //For now only Pre-ID tracks that are not already identified as Conversions  
00323         if(hasSingleleg &&!(trackRef->trackType(reco::PFBlockElement::T_FROM_GAMMACONV)))  
00324           {  
00325             elemsToLock.push_back(track->second);  
00326             //find all the clusters linked to this track  
00327             std::multimap<double, unsigned int> moreClusters;  
00328             blockRef->associatedElements( track->second,  
00329                                           linkData,  
00330                                           moreClusters,  
00331                                           reco::PFBlockElement::ECAL,  
00332                                           reco::PFBlock::LINKTEST_ALL);  
00333              
00334             float p_in=sqrt(elements[track->second].trackRef()->innerMomentum().x() * elements[track->second].trackRef()->innerMomentum().x() +  
00335                             elements[track->second].trackRef()->innerMomentum().y()*elements[track->second].trackRef()->innerMomentum().y()+  
00336                             elements[track->second].trackRef()->innerMomentum().z()*elements[track->second].trackRef()->innerMomentum().z());  
00337             float linked_E=0;  
00338             for(std::multimap<double, unsigned int>::iterator clust = moreClusters.begin();  
00339                 clust != moreClusters.end(); ++clust)  
00340               {  
00341                 if(!active[clust->second])continue;  
00342                 //running sum of linked energy  
00343                 linked_E=linked_E+elements[clust->second].clusterRef()->energy();  
00344                 //prevent too much energy from being added  
00345                 if(linked_E/p_in>1.5)break;  
00346                 bool included=false;  
00347                 //check if these ecal clusters are already included with the supercluster  
00348                 for(std::multimap<double, unsigned int>::iterator cluscheck = ecalAssoPFClusters.begin();  
00349                     cluscheck != ecalAssoPFClusters.end(); ++cluscheck)  
00350                   {  
00351                     if(cluscheck->second==clust->second)included=true;  
00352                   }  
00353                 if(!included)AddClusters.push_back(clust->second);//Add to a container of clusters to be Added to the Photon candidate  
00354               }  
00355           }
00356 
00357         // Possibly need to be more smart about them (CASE 5)
00358         // .... for now we simply skip non id'ed tracks
00359         if( ! (trackRef->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) ) ) continue;  
00360         hasConvTrack=true;  
00361         elemsToLock.push_back(track->second);  
00362         //again look at the clusters linked to this track  
00363         std::multimap<double, unsigned int> moreClusters;  
00364         blockRef->associatedElements( track->second,  
00365                                       linkData,  
00366                                       moreClusters,  
00367                                       reco::PFBlockElement::ECAL,  
00368                                       reco::PFBlock::LINKTEST_ALL);
00369         
00370         float p_in=sqrt(elements[track->second].trackRef()->innerMomentum().x() * elements[track->second].trackRef()->innerMomentum().x() +  
00371                         elements[track->second].trackRef()->innerMomentum().y()*elements[track->second].trackRef()->innerMomentum().y()+  
00372                         elements[track->second].trackRef()->innerMomentum().z()*elements[track->second].trackRef()->innerMomentum().z());  
00373         float linked_E=0;  
00374         for(std::multimap<double, unsigned int>::iterator clust = moreClusters.begin();  
00375             clust != moreClusters.end(); ++clust)  
00376           {  
00377             if(!active[clust->second])continue;  
00378             linked_E=linked_E+elements[clust->second].clusterRef()->energy();  
00379             if(linked_E/p_in>1.5)break;  
00380             bool included=false;  
00381             for(std::multimap<double, unsigned int>::iterator cluscheck = ecalAssoPFClusters.begin();  
00382                 cluscheck != ecalAssoPFClusters.end(); ++cluscheck)  
00383               {  
00384                 if(cluscheck->second==clust->second)included=true;  
00385               }  
00386             if(!included)AddClusters.push_back(clust->second);//again only add if it is not already included with the supercluster  
00387           }
00388 
00389         // we need to check for other TRACKS linked to this conversion track, that point possibly no an ECAL cluster not included in the SC
00390         // .... This is basically CASE 4.
00391 
00392         std::multimap<double, unsigned int> moreTracks;
00393         blockRef->associatedElements( track->second,
00394                                       linkData,
00395                                       moreTracks,
00396                                       reco::PFBlockElement::TRACK,
00397                                       reco::PFBlock::LINKTEST_ALL);
00398 
00399         for(std::multimap<double, unsigned int>::iterator track2 = moreTracks.begin();
00400             track2 != moreTracks.end(); ++track2) {
00401           
00402           // first check if is it's still active
00403           if( ! (active[track2->second]) ) continue;
00404           //skip over the 1st leg already found above  
00405           if(track->second==track2->second)continue;
00406           // check if it's a CONV track
00407           const reco::PFBlockElementTrack * track2Ref = dynamic_cast<const reco::PFBlockElementTrack*>((&elements[track2->second]));    
00408           if( ! (track2Ref->trackType(reco::PFBlockElement::T_FROM_GAMMACONV) ) ) continue;  // Possibly need to be more smart about them (CASE 5)
00409           elemsToLock.push_back(track2->second);
00410           // so it's another active conversion track, that is in the Block and linked to the conversion track we already found
00411           // find the ECAL cluster linked to it...
00412           std::multimap<double, unsigned int> convEcal;
00413           blockRef->associatedElements( track2->second,
00414                                         linkData,
00415                                         convEcal,
00416                                         reco::PFBlockElement::ECAL,
00417                                         reco::PFBlock::LINKTEST_ALL);
00418           float p_in=sqrt(elements[track->second].trackRef()->innerMomentum().x()*elements[track->second].trackRef()->innerMomentum().x()+
00419                           elements[track->second].trackRef()->innerMomentum().y()*elements[track->second].trackRef()->innerMomentum().y()+  
00420                           elements[track->second].trackRef()->innerMomentum().z()*elements[track->second].trackRef()->innerMomentum().z());  
00421 
00422 
00423           float linked_E=0;
00424           for(std::multimap<double, unsigned int>::iterator itConvEcal = convEcal.begin();
00425               itConvEcal != convEcal.end(); ++itConvEcal) {
00426             
00427             if( ! (active[itConvEcal->second]) ) continue;
00428             bool included=false;  
00429             for(std::multimap<double, unsigned int>::iterator cluscheck = ecalAssoPFClusters.begin();  
00430                 cluscheck != ecalAssoPFClusters.end(); ++cluscheck)  
00431               {  
00432                 if(cluscheck->second==itConvEcal->second)included=true;  
00433               }
00434             linked_E=linked_E+elements[itConvEcal->second].clusterRef()->energy();
00435             if(linked_E/p_in>1.5)break;
00436             if(!included){AddClusters.push_back(itConvEcal->second);
00437             }
00438             
00439             // it's still active, so we have to add it.
00440             // CAUTION: we don't care here if it's part of the SC or not, we include it anyways
00441             
00442             // loop over the HCAL Clusters linked to the ECAL cluster (CASE 6)
00443             std::multimap<double, unsigned int> hcalElems_conv;
00444             blockRef->associatedElements( itecal->second,linkData,
00445                                           hcalElems_conv,
00446                                           reco::PFBlockElement::HCAL,
00447                                           reco::PFBlock::LINKTEST_ALL );
00448             
00449             for(std::multimap<double, unsigned int>::iterator ithcal2 = hcalElems_conv.begin();
00450                 ithcal2 != hcalElems_conv.end(); ++ithcal2) {
00451               
00452               if ( ! (active[ithcal2->second] ) ) continue; // HCAL Cluster already used....
00453               
00454               // TODO: Decide if this HCAL cluster is to be used
00455               // .... based on some Physics
00456               // .... To we need to check if it's closer to any other ECAL/TRACK?
00457               
00458               bool useHcal = true;
00459               if ( !useHcal ) continue;
00460               
00461               //elemsToLock.push_back(ithcal2->second);
00462 
00463             } // end of loop over HCAL clusters linked to the ECAL cluster from second CONVERSION leg
00464             
00465           } // end of loop over ECALs linked to second T_FROM_GAMMACONV
00466           
00467         } // end of loop over SECOND conversion leg
00468 
00469         // TODO: Do we need to check separatly if there are HCAL cluster linked to the track?
00470         
00471       } // end of loop over tracks
00472       
00473             
00474       // Calibrate the Added ECAL energy
00475       float addedCalibEne=0;
00476       float addedRawEne=0;
00477       std::vector<double>AddedPS1(0);
00478       std::vector<double>AddedPS2(0);  
00479       double addedps1=0;  
00480       double addedps2=0;  
00481       for(unsigned int i=0; i<AddClusters.size(); i++)  
00482         {  
00483           std::multimap<double, unsigned int> PS1Elems_conv;  
00484           std::multimap<double, unsigned int> PS2Elems_conv;  
00485           blockRef->associatedElements(AddClusters[i],  
00486                                        linkData,  
00487                                        PS1Elems_conv,  
00488                                        reco::PFBlockElement::PS1,  
00489                                        reco::PFBlock::LINKTEST_ALL );  
00490           blockRef->associatedElements( AddClusters[i],  
00491                                         linkData,  
00492                                         PS2Elems_conv,  
00493                                         reco::PFBlockElement::PS2,  
00494                                         reco::PFBlock::LINKTEST_ALL );  
00495            
00496           for(std::multimap<double, unsigned int>::iterator iteps = PS1Elems_conv.begin();  
00497               iteps != PS1Elems_conv.end(); ++iteps)  
00498             {  
00499               if(!active[iteps->second])continue;  
00500               std::multimap<double, unsigned int> PS1Elems_check;  
00501               blockRef->associatedElements(iteps->second,  
00502                                            linkData,  
00503                                            PS1Elems_check,  
00504                                            reco::PFBlockElement::ECAL,  
00505                                            reco::PFBlock::LINKTEST_ALL );  
00506               if(PS1Elems_check.begin()->second==AddClusters[i])  
00507                 {  
00508                    
00509                   reco::PFClusterRef ps1ClusterRef = elements[iteps->second].clusterRef();  
00510                   AddedPS1.push_back(ps1ClusterRef->energy());  
00511                   addedps1=addedps1+ps1ClusterRef->energy();  
00512                   elemsToLock.push_back(iteps->second);  
00513                 }  
00514             }  
00515            
00516           for(std::multimap<double, unsigned int>::iterator iteps = PS2Elems_conv.begin();  
00517               iteps != PS2Elems_conv.end(); ++iteps) {  
00518             if(!active[iteps->second])continue;  
00519             std::multimap<double, unsigned int> PS2Elems_check;  
00520             blockRef->associatedElements(iteps->second,  
00521                                          linkData,  
00522                                          PS2Elems_check,  
00523                                          reco::PFBlockElement::ECAL,  
00524                                          reco::PFBlock::LINKTEST_ALL );  
00525              
00526             if(PS2Elems_check.begin()->second==AddClusters[i])  
00527               {  
00528                 reco::PFClusterRef ps2ClusterRef = elements[iteps->second].clusterRef();  
00529                 AddedPS2.push_back(ps2ClusterRef->energy());  
00530                 addedps2=addedps2+ps2ClusterRef->energy();  
00531                 elemsToLock.push_back(iteps->second);  
00532               }  
00533           }  
00534           reco::PFClusterRef AddclusterRef = elements[AddClusters[i]].clusterRef();  
00535           addedRawEne = AddclusterRef->energy()+addedRawEne;  
00536           addedCalibEne = thePFEnergyCalibration_->energyEm(*AddclusterRef,AddedPS1,AddedPS2,false)+addedCalibEne;  
00537           AddedPS2.clear(); 
00538           AddedPS1.clear();  
00539           elemsToLock.push_back(AddClusters[i]);  
00540         }  
00541       AddClusters.clear();
00542       float EE = thePFEnergyCalibration_->energyEm(*clusterRef,ps1Ene,ps2Ene,false)+addedCalibEne;  
00543       //cout<<"Original Energy "<<EE<<"Added Energy "<<addedCalibEne<<endl;
00544       
00545       photonEnergy_ +=  EE;
00546       RawEcalEne    +=  clusterRef->energy()+addedRawEne;
00547       photonX_      +=  EE * clusterRef->position().X();
00548       photonY_      +=  EE * clusterRef->position().Y();
00549       photonZ_      +=  EE * clusterRef->position().Z();                
00550       ps1TotEne     +=  ps1+addedps1;
00551       ps2TotEne     +=  ps2+addedps2;
00552     } // end of loop over all ECAL cluster within this SC
00553     
00554     // we've looped over all ECAL clusters, ready to generate PhotonCandidate
00555     if( ! (photonEnergy_ > 0.) ) continue;    // This SC is not a Photon Candidate
00556     float sum_track_pt=0;
00557     //Now check if there are tracks failing isolation outside of the Jurassic isolation region  
00558     for(unsigned int i=0; i<IsoTracks.size(); i++)sum_track_pt=sum_track_pt+elements[IsoTracks[i]].trackRef()->pt();  
00559     
00560 
00561 
00562     math::XYZVector photonPosition(photonX_,
00563                                    photonY_,
00564                                    photonZ_);
00565 
00566     math::XYZVector photonDirection=photonPosition.Unit();
00567     
00568     math::XYZTLorentzVector photonMomentum(photonEnergy_* photonDirection.X(),
00569                                            photonEnergy_* photonDirection.Y(),
00570                                            photonEnergy_* photonDirection.Z(),
00571                                            photonEnergy_           );
00572 
00573     if(sum_track_pt>(2+ 0.001* photonMomentum.pt()))
00574       continue;//THIS SC is not a Photon it fails track Isolation
00575 
00576     /*
00577     std::cout<<" Created Photon with energy = "<<photonEnergy_<<std::endl;
00578     std::cout<<"                         pT = "<<photonMomentum.pt()<<std::endl;
00579     std::cout<<"                     RawEne = "<<RawEcalEne<<std::endl;
00580     std::cout<<"                          E = "<<photonMomentum.e()<<std::endl;
00581     std::cout<<"                        eta = "<<photonMomentum.eta()<<std::endl;
00582     std::cout<<"             TrackIsolation = "<< sum_track_pt <<std::endl;
00583     */
00584 
00585     reco::PFCandidate photonCand(0,photonMomentum, reco::PFCandidate::gamma);
00586     
00587     photonCand.setPs1Energy(ps1TotEne);
00588     photonCand.setPs2Energy(ps2TotEne);
00589     photonCand.setEcalEnergy(RawEcalEne,photonEnergy_);
00590     photonCand.setHcalEnergy(0.,0.);
00591     photonCand.set_mva_nothing_gamma(1.);  
00592     photonCand.setSuperClusterRef(sc->superClusterRef());
00593     if(hasConvTrack || hasSingleleg)photonCand.setFlag( reco::PFCandidate::GAMMA_TO_GAMMACONV, true);
00594 
00595     //photonCand.setPositionAtECALEntrance(math::XYZPointF(photonMom_.position()));
00596 
00597     
00598     // set isvalid_ to TRUE since we've found at least one photon candidate
00599     isvalid_ = true;
00600     // push back the candidate into the collection ...
00601 
00602     // ... and lock all elemts used
00603     for(std::vector<unsigned int>::const_iterator it = elemsToLock.begin();
00604         it != elemsToLock.end(); ++it)
00605       {
00606         if(active[*it])photonCand.addElementInBlock(blockRef,*it);
00607         active[*it] = false;
00608       }
00609     pfCandidates->push_back(photonCand);
00610     // ... and reset the vector
00611     elemsToLock.resize(0);
00612     hasConvTrack=false;
00613     hasSingleleg=false;
00614   } // end of loops over all elements in block
00615   
00616   return;
00617 
00618 }
00619 
00620 bool PFPhotonAlgo::EvaluateSingleLegMVA(const reco::PFBlockRef& blockref, const reco::Vertex& primaryvtx, unsigned int track_index)  
00621 {  
00622   bool convtkfound=false;  
00623   const reco::PFBlock& block = *blockref;  
00624   const edm::OwnVector< reco::PFBlockElement >& elements = block.elements();  
00625   //use this to store linkdata in the associatedElements function below  
00626   PFBlock::LinkData linkData =  block.linkData();  
00627   //calculate MVA Variables  
00628   chi2=elements[track_index].trackRef()->chi2()/elements[track_index].trackRef()->ndof();  
00629   nlost=elements[track_index].trackRef()->trackerExpectedHitsInner().numberOfLostHits();  
00630   nlayers=elements[track_index].trackRef()->hitPattern().trackerLayersWithMeasurement();  
00631   track_pt=elements[track_index].trackRef()->pt();  
00632   STIP=elements[track_index].trackRefPF()->STIP();  
00633    
00634   float linked_e=0;  
00635   float linked_h=0;  
00636   std::multimap<double, unsigned int> ecalAssoTrack;  
00637   block.associatedElements( track_index,linkData,  
00638                             ecalAssoTrack,  
00639                             reco::PFBlockElement::ECAL,  
00640                             reco::PFBlock::LINKTEST_ALL );  
00641   std::multimap<double, unsigned int> hcalAssoTrack;  
00642   block.associatedElements( track_index,linkData,  
00643                             hcalAssoTrack,  
00644                             reco::PFBlockElement::HCAL,  
00645                             reco::PFBlock::LINKTEST_ALL );  
00646   if(ecalAssoTrack.size() > 0) {  
00647     for(std::multimap<double, unsigned int>::iterator itecal = ecalAssoTrack.begin();  
00648         itecal != ecalAssoTrack.end(); ++itecal) {  
00649       linked_e=linked_e+elements[itecal->second].clusterRef()->energy();  
00650     }  
00651   }  
00652   if(hcalAssoTrack.size() > 0) {  
00653     for(std::multimap<double, unsigned int>::iterator ithcal = hcalAssoTrack.begin();  
00654         ithcal != hcalAssoTrack.end(); ++ithcal) {  
00655       linked_h=linked_h+elements[ithcal->second].clusterRef()->energy();  
00656     }  
00657   }  
00658   EoverPt=linked_e/elements[track_index].trackRef()->pt();  
00659   HoverPt=linked_h/elements[track_index].trackRef()->pt();  
00660   GlobalVector rvtx(elements[track_index].trackRef()->innerPosition().X()-primaryvtx.x(),  
00661                     elements[track_index].trackRef()->innerPosition().Y()-primaryvtx.y(),  
00662                     elements[track_index].trackRef()->innerPosition().Z()-primaryvtx.z());  
00663   double vtx_phi=rvtx.phi();  
00664   //delta Phi between conversion vertex and track  
00665   del_phi=fabs(deltaPhi(vtx_phi, elements[track_index].trackRef()->innerMomentum().Phi()));  
00666   mvaValue = tmvaReader_->EvaluateMVA("BDT");  
00667   if(mvaValue > MVACUT)convtkfound=true;  
00668   return convtkfound;  
00669 }