CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/PhysicsTools/SelectorUtils/interface/PFJetIDSelectionFunctor.h

Go to the documentation of this file.
00001 #ifndef PhysicsTools_SelectorUtils_interface_PFJetIDSelectionFunctor_h
00002 #define PhysicsTools_SelectorUtils_interface_PFJetIDSelectionFunctor_h
00003 
00015 #include "DataFormats/PatCandidates/interface/Jet.h"
00016 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00017 
00018 #include "PhysicsTools/SelectorUtils/interface/Selector.h"
00019 
00020 #include <TMath.h>
00021 class PFJetIDSelectionFunctor : public Selector<pat::Jet>  {
00022 
00023  public: // interface
00024 
00025   enum Version_t { FIRSTDATA, N_VERSIONS };
00026   enum Quality_t { LOOSE, TIGHT, N_QUALITY};
00027 
00028   PFJetIDSelectionFunctor() {}
00029   
00030  PFJetIDSelectionFunctor( edm::ParameterSet const & params ) 
00031  {
00032    std::string versionStr = params.getParameter<std::string>("version");
00033    std::string qualityStr = params.getParameter<std::string>("quality");
00034 
00035    if ( versionStr == "FIRSTDATA" ) 
00036      version_ = FIRSTDATA;
00037    else
00038      version_ = FIRSTDATA;  
00039 
00040    if      ( qualityStr == "LOOSE") quality_ = LOOSE;
00041    else if ( qualityStr == "TIGHT") quality_ = TIGHT;
00042    else quality_ = LOOSE;
00043 
00044     push_back("CHF" );
00045     push_back("NHF" );
00046     push_back("CEF" );
00047     push_back("NEF" );
00048     push_back("NCH" );
00049     push_back("nConstituents");
00050 
00051 
00052     // Set some default cuts for LOOSE, TIGHT
00053     if ( quality_ == LOOSE ) {
00054       set("CHF", 0.0);
00055       set("NHF", 0.99);
00056       set("CEF", 0.99);
00057       set("NEF", 0.99);
00058       set("NCH", 0);
00059       set("nConstituents", 1);
00060     } else if ( quality_ == TIGHT ) {
00061       set("CHF", 0.0);
00062       set("NHF", 0.9);
00063       set("CEF", 0.99);
00064       set("NEF", 0.9);
00065       set("NCH", 0);
00066       set("nConstituents", 1);      
00067     }
00068 
00069 
00070     // Now check the configuration to see if the user changed anything
00071     if ( params.exists("CHF") ) set("CHF", params.getParameter<double>("CHF") );
00072     if ( params.exists("NHF") ) set("NHF", params.getParameter<double>("NHF") );
00073     if ( params.exists("CEF") ) set("CEF", params.getParameter<double>("CEF") );
00074     if ( params.exists("NEF") ) set("NEF", params.getParameter<double>("NEF") );
00075     if ( params.exists("NCH") ) set("NCH", params.getParameter<int>   ("NCH") );
00076     if ( params.exists("nConstuents") ) set("nConstituents", params.getParameter<int> ("nConstituents") );
00077 
00078     if ( params.exists("cutsToIgnore") )
00079       setIgnoredCuts( params.getParameter<std::vector<std::string> >("cutsToIgnore") );
00080 
00081 
00082     indexNConstituents_ = index_type (&bits_, "nConstituents");
00083     indexNEF_ = index_type (&bits_, "NEF");
00084     indexNHF_ = index_type (&bits_, "NHF");
00085     indexCEF_ = index_type (&bits_, "CEF");
00086     indexCHF_ = index_type (&bits_, "CHF");
00087     indexNCH_ = index_type (&bits_, "NCH");
00088 
00089     retInternal_ = getBitTemplate();
00090     
00091   }
00092 
00093 
00094  PFJetIDSelectionFunctor( Version_t version,
00095                           Quality_t quality ) :
00096   version_(version), quality_(quality)
00097  {
00098 
00099     push_back("CHF" );
00100     push_back("NHF" );
00101     push_back("CEF" );
00102     push_back("NEF" );
00103     push_back("NCH" );
00104     push_back("nConstituents");
00105 
00106 
00107     // Set some default cuts for LOOSE, TIGHT
00108     if ( quality_ == LOOSE ) {
00109       set("CHF", 0.0);
00110       set("NHF", 0.99);
00111       set("CEF", 0.99);
00112       set("NEF", 0.99);
00113       set("NCH", 0);
00114       set("nConstituents", 1);
00115     } else if ( quality_ == TIGHT ) {
00116       set("CHF", 0.0);
00117       set("NHF", 0.9);
00118       set("CEF", 0.99);
00119       set("NEF", 0.9);
00120       set("NCH", 0);
00121       set("nConstituents", 1);      
00122     }
00123 
00124 
00125     indexNConstituents_ = index_type (&bits_, "nConstituents");
00126     indexNEF_ = index_type (&bits_, "NEF");
00127     indexNHF_ = index_type (&bits_, "NHF");
00128     indexCEF_ = index_type (&bits_, "CEF");
00129     indexCHF_ = index_type (&bits_, "CHF");
00130     indexNCH_ = index_type (&bits_, "NCH");
00131 
00132     retInternal_ = getBitTemplate();   
00133  }
00134                            
00135 
00136   // 
00137   // Accessor from PAT jets
00138   // 
00139   bool operator()( const pat::Jet & jet, pat::strbitset & ret )  
00140   {
00141     if ( version_ == FIRSTDATA ) {
00142       if ( jet.currentJECLevel() == "Uncorrected" || !jet.jecSetsAvailable() ) 
00143         return firstDataCuts( jet, ret );
00144       else 
00145         return firstDataCuts( jet.correctedJet("Uncorrected"), ret );
00146     }
00147     else {
00148       return false;
00149     }
00150   }
00151   using Selector<pat::Jet>::operator();
00152 
00153   // 
00154   // Accessor from *CORRECTED* 4-vector, EMF, and Jet ID. 
00155   // This can be used with reco quantities. 
00156   // 
00157   bool operator()( const reco::PFJet & jet, pat::strbitset & ret )  
00158   {
00159     if ( version_ == FIRSTDATA ) return firstDataCuts( jet, ret );
00160     else {
00161       return false;
00162     }
00163   }
00164 
00165   bool operator()( const reco::PFJet & jet )
00166   {
00167     retInternal_.set(false);
00168     operator()(jet, retInternal_);
00169     setIgnored(retInternal_);
00170     return (bool)retInternal_;
00171   }
00172   
00173   // 
00174   // cuts based on craft 08 analysis. 
00175   // 
00176   bool firstDataCuts( reco::Jet const & jet,
00177                       pat::strbitset & ret) 
00178   {    
00179     ret.set(false);
00180 
00181     // cache some variables
00182     double chf = 0.0;
00183     double nhf = 0.0;
00184     double cef = 0.0;
00185     double nef = 0.0;
00186     int    nch = 0;
00187     int    nconstituents = 0;
00188 
00189     // Have to do this because pat::Jet inherits from reco::Jet but not reco::PFJet
00190     reco::PFJet const * pfJet = dynamic_cast<reco::PFJet const *>(&jet);
00191     pat::Jet const * patJet = dynamic_cast<pat::Jet const *>(&jet);
00192     reco::BasicJet const * basicJet = dynamic_cast<reco::BasicJet const *>(&jet);
00193 
00194     if ( patJet != 0 ) {
00195       if ( patJet->isPFJet() ) {
00196         chf = patJet->chargedHadronEnergyFraction();
00197         nhf = ( patJet->neutralHadronEnergy() + patJet->HFHadronEnergy() ) / patJet->energy();
00198         cef = patJet->chargedEmEnergyFraction();
00199         nef = patJet->neutralEmEnergyFraction();
00200         nch = patJet->chargedMultiplicity();
00201         nconstituents = patJet->numberOfDaughters();
00202       } 
00203       // Handle the special case where this is a composed jet for
00204       // subjet analyses
00205       else if ( patJet->isBasicJet() ) {
00206         double e_chf = 0.0;
00207         double e_nhf = 0.0;
00208         double e_cef = 0.0;
00209         double e_nef = 0.0;
00210         nch = 0;
00211         nconstituents = 0;
00212 
00213         for ( reco::Jet::const_iterator ibegin = patJet->begin(),
00214                 iend = patJet->end(), isub = ibegin;
00215               isub != iend; ++isub ) {
00216           reco::PFJet const * pfsub = dynamic_cast<reco::PFJet const *>( &*isub );
00217           e_chf += pfsub->chargedHadronEnergy();
00218           e_nhf += (pfsub->neutralHadronEnergy() + pfsub->HFHadronEnergy());
00219           e_cef += pfsub->chargedEmEnergy();
00220           e_nef += pfsub->neutralEmEnergy();
00221           nch += pfsub->chargedMultiplicity();
00222           nconstituents += pfsub->numberOfDaughters();
00223         }
00224         double e = patJet->energy();
00225         if ( e > 0.000001 ) {
00226           chf = e_chf / e;
00227           nhf = e_nhf / e;
00228           cef = e_cef / e;
00229           nef = e_nef / e;
00230         } else {
00231           chf = nhf = cef = nef = 0.0;
00232         }
00233       }
00234     } // end if pat jet
00235     else if ( pfJet != 0 ) {
00236       // CV: need to compute energy fractions in a way that works for corrected as well as for uncorrected PFJets
00237       double jetEnergyUncorrected = 
00238         pfJet->chargedHadronEnergy() 
00239        + pfJet->neutralHadronEnergy()
00240        + pfJet->photonEnergy()
00241        + pfJet->electronEnergy()
00242        + pfJet->muonEnergy()
00243        + pfJet->HFHadronEnergy()
00244        + pfJet->HFEMEnergy();
00245       if ( jetEnergyUncorrected > 0. ) {
00246         chf = pfJet->chargedHadronEnergy() / jetEnergyUncorrected;
00247         nhf = ( pfJet->neutralHadronEnergy() + pfJet->HFHadronEnergy() ) / jetEnergyUncorrected;
00248         cef = pfJet->chargedEmEnergy() / jetEnergyUncorrected;
00249         nef = pfJet->neutralEmEnergy() / jetEnergyUncorrected;
00250       }
00251       nch = pfJet->chargedMultiplicity();
00252       nconstituents = pfJet->numberOfDaughters();
00253     } // end if PF jet
00254     // Handle the special case where this is a composed jet for
00255     // subjet analyses
00256     else if ( basicJet != 0 ) {
00257       double e_chf = 0.0;
00258       double e_nhf = 0.0;
00259       double e_cef = 0.0;
00260       double e_nef = 0.0;
00261       nch = 0;
00262       nconstituents = 0;
00263       
00264       for ( reco::Jet::const_iterator ibegin = basicJet->begin(),
00265               iend = patJet->end(), isub = ibegin;
00266             isub != iend; ++isub ) {
00267         reco::PFJet const * pfsub = dynamic_cast<reco::PFJet const *>( &*isub );
00268         e_chf += pfsub->chargedHadronEnergy();
00269         e_nhf += (pfsub->neutralHadronEnergy() + pfsub->HFHadronEnergy());
00270         e_cef += pfsub->chargedEmEnergy();
00271         e_nef += pfsub->neutralEmEnergy();
00272         nch += pfsub->chargedMultiplicity();
00273         nconstituents += pfsub->numberOfDaughters();
00274       }
00275       double e = basicJet->energy();
00276       if ( e > 0.000001 ) {
00277         chf = e_chf / e;
00278         nhf = e_nhf / e;
00279         cef = e_cef / e;
00280         nef = e_nef / e;
00281       }
00282     } // end if basic jet
00283 
00284 
00285     // Cuts for all |eta|:
00286     if ( ignoreCut(indexNConstituents_) || nconstituents > cut(indexNConstituents_, int() ) ) passCut( ret, indexNConstituents_);
00287     if ( ignoreCut(indexNEF_)           || ( nef < cut(indexNEF_, double()) ) ) passCut( ret, indexNEF_);
00288     if ( ignoreCut(indexNHF_)           || ( nhf < cut(indexNHF_, double()) ) ) passCut( ret, indexNHF_);    
00289     // Cuts for |eta| < 2.4:
00290     if ( ignoreCut(indexCEF_)           || ( cef < cut(indexCEF_, double()) || std::abs(jet.eta()) > 2.4 ) ) passCut( ret, indexCEF_);
00291     if ( ignoreCut(indexCHF_)           || ( chf > cut(indexCHF_, double()) || std::abs(jet.eta()) > 2.4 ) ) passCut( ret, indexCHF_);
00292     if ( ignoreCut(indexNCH_)           || ( nch > cut(indexNCH_, int())    || std::abs(jet.eta()) > 2.4 ) ) passCut( ret, indexNCH_);    
00293 
00294     //std::cout << "<PFJetIDSelectionFunctor::firstDataCuts>:" << std::endl;
00295     //std::cout << " jet: Pt = " << jet.pt() << ", eta = " << jet.eta() << ", phi = " << jet.phi() << std::endl;
00296     //ret.print(std::cout);
00297 
00298     setIgnored( ret );
00299     return (bool)ret;
00300   }
00301   
00302  private: // member variables
00303   
00304   Version_t version_;
00305   Quality_t quality_;
00306 
00307   index_type indexNConstituents_;
00308   index_type indexNEF_;
00309   index_type indexNHF_;
00310   index_type indexCEF_;
00311   index_type indexCHF_;
00312   index_type indexNCH_;
00313   
00314 };
00315 
00316 #endif