CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_1/src/RecoTauTag/RecoTau/plugins/RecoTauBuilderConePlugin.cc

Go to the documentation of this file.
00001 /*
00002  * RecoTauBuilderConePlugin
00003  *
00004  * Build a PFTau using cones defined in DeltaR.
00005  *
00006  * Original Authors: Ludovic Houchu, Simone Gennai
00007  * Modifications: Evan K. Friis
00008  *
00009  * $Id $
00010  */
00011 
00012 #include <vector>
00013 #include <algorithm>
00014 
00015 #include "RecoTauTag/RecoTau/interface/RecoTauBuilderPlugins.h"
00016 #include "RecoTauTag/RecoTau/interface/RecoTauCommonUtilities.h"
00017 #include "RecoTauTag/RecoTau/interface/RecoTauConstructor.h"
00018 #include "RecoTauTag/RecoTau/interface/RecoTauQualityCuts.h"
00019 
00020 #include "RecoTauTag/RecoTau/interface/ConeTools.h"
00021 #include "RecoTauTag/RecoTau/interface/RecoTauCrossCleaning.h"
00022 
00023 #include "DataFormats/TauReco/interface/PFTau.h"
00024 #include "DataFormats/TauReco/interface/RecoTauPiZero.h"
00025 #include "DataFormats/VertexReco/interface/Vertex.h"
00026 #include "DataFormats/Math/interface/deltaR.h"
00027 
00028 #include "CommonTools/Utils/interface/StringObjectFunction.h"
00029 
00030 namespace reco { namespace tau {
00031 
00032 class RecoTauBuilderConePlugin : public RecoTauBuilderPlugin {
00033   public:
00034     explicit RecoTauBuilderConePlugin(const edm::ParameterSet& pset);
00035     ~RecoTauBuilderConePlugin() {}
00036     // Build a tau from a jet
00037     return_type operator()(const reco::PFJetRef& jet,
00038         const std::vector<RecoTauPiZero>& piZeros,
00039         const std::vector<PFCandidatePtr>& regionalExtras) const;
00040   private:
00041     RecoTauQualityCuts qcuts_;
00042     bool usePFLeptonsAsChargedHadrons_;
00043     double leadObjecPtThreshold_;
00044     /* String function to extract values from PFJets */
00045     typedef StringObjectFunction<reco::PFJet> JetFunc;
00046     // Cone defintions
00047     JetFunc matchingCone_;
00048     JetFunc signalConeChargedHadrons_;
00049     JetFunc isoConeChargedHadrons_;
00050     JetFunc signalConePiZeros_;
00051     JetFunc isoConePiZeros_;
00052     JetFunc signalConeNeutralHadrons_;
00053     JetFunc isoConeNeutralHadrons_;
00054 };
00055 
00056 // ctor - initialize all of our variables
00057 RecoTauBuilderConePlugin::RecoTauBuilderConePlugin(
00058     const edm::ParameterSet& pset):RecoTauBuilderPlugin(pset),
00059     qcuts_(pset.getParameterSet(
00060           "qualityCuts").getParameterSet("signalQualityCuts")),
00061     usePFLeptonsAsChargedHadrons_(pset.getParameter<bool>("usePFLeptons")),
00062     leadObjecPtThreshold_(pset.getParameter<double>("leadObjectPt")),
00063     matchingCone_(pset.getParameter<std::string>("matchingCone")),
00064     signalConeChargedHadrons_(pset.getParameter<std::string>(
00065             "signalConeChargedHadrons")),
00066     isoConeChargedHadrons_(
00067         pset.getParameter<std::string>("isoConeChargedHadrons")),
00068     signalConePiZeros_(
00069         pset.getParameter<std::string>("signalConePiZeros")),
00070     isoConePiZeros_(
00071         pset.getParameter<std::string>("isoConePiZeros")),
00072     signalConeNeutralHadrons_(
00073         pset.getParameter<std::string>("signalConeNeutralHadrons")),
00074     isoConeNeutralHadrons_(
00075         pset.getParameter<std::string>("isoConeNeutralHadrons")) {}
00076 
00077 RecoTauBuilderConePlugin::return_type RecoTauBuilderConePlugin::operator()(
00078     const reco::PFJetRef& jet,
00079     const std::vector<RecoTauPiZero>& piZeros,
00080     const std::vector<PFCandidatePtr>& regionalExtras) const {
00081   // Get access to our cone tools
00082   using namespace cone;
00083   // Define output.  We only produce one tau per jet for the cone algo.
00084   output_type output;
00085 
00086   // Our tau builder - the true indicates to automatically copy gamma candidates
00087   // from the pizeros.
00088   RecoTauConstructor tau(jet, getPFCands(), true);
00089   // Setup our quality cuts to use the current vertex (supplied by base class)
00090   qcuts_.setPV(primaryVertex(jet));
00091 
00092   typedef std::vector<PFCandidatePtr> PFCandPtrs;
00093 
00094   // Get the PF Charged hadrons + quality cuts
00095   PFCandPtrs pfchs;
00096   if (!usePFLeptonsAsChargedHadrons_) {
00097     pfchs = qcuts_.filterRefs(pfCandidates(*jet, reco::PFCandidate::h));
00098   } else {
00099     // Check if we want to include electrons in muons in "charged hadron"
00100     // collection.  This is the preferred behavior, as the PF lepton selections
00101     // are very loose.
00102     pfchs = qcuts_.filterRefs(pfChargedCands(*jet));
00103   }
00104 
00105   // Get the PF gammas
00106   PFCandPtrs pfGammas = qcuts_.filterRefs(
00107       pfCandidates(*jet, reco::PFCandidate::gamma));
00108   // Neutral hadrons
00109   PFCandPtrs pfnhs = qcuts_.filterRefs(
00110       pfCandidates(*jet, reco::PFCandidate::h0));
00111 
00112   // All the extra junk
00113   PFCandPtrs regionalJunk = qcuts_.filterRefs(regionalExtras);
00114 
00115   /***********************************************
00116    ******     Lead Candidate Finding    **********
00117    ***********************************************/
00118 
00119   // Define our matching cone and filters
00120   double matchingCone = matchingCone_(*jet);
00121   PFCandPtrDRFilter matchingConeFilter(jet->p4(), 0, matchingCone);
00122 
00123   // Find the maximum PFCharged hadron in the matching cone.  The call to
00124   // PFCandidates always a sorted list, so we can just take the first if it
00125   // if it exists.
00126   PFCandidatePtr leadPFCH;
00127   PFCandPtrs::iterator leadPFCH_iter =
00128       std::find_if(pfchs.begin(), pfchs.end(), matchingConeFilter);
00129 
00130   if (leadPFCH_iter != pfchs.end()) {
00131     leadPFCH = *leadPFCH_iter;
00132     // Set leading candidate
00133     tau.setleadPFChargedHadrCand(leadPFCH);
00134   } else {
00135     // If there is no leading charged candidate at all, return nothing - the
00136     // producer class that owns the plugin will build a null tau if desired.
00137     return output.release();
00138   }
00139 
00140   // Find the leading neutral candidate
00141   PFCandidatePtr leadPFGamma;
00142   PFCandPtrs::iterator leadPFGamma_iter =
00143       std::find_if(pfGammas.begin(), pfGammas.end(), matchingConeFilter);
00144 
00145   if (leadPFGamma_iter != pfGammas.end()) {
00146     leadPFGamma = *leadPFGamma_iter;
00147     // Set leading neutral candidate
00148     tau.setleadPFNeutralCand(leadPFGamma);
00149   }
00150 
00151   PFCandidatePtr leadPFCand;
00152   // Always use the leadPFCH if it is above our threshold
00153   if (leadPFCH.isNonnull() && leadPFCH->pt() > leadObjecPtThreshold_) {
00154     leadPFCand = leadPFCH;
00155   } else if (leadPFGamma.isNonnull() &&
00156              leadPFGamma->pt() > leadObjecPtThreshold_) {
00157     // Otherwise use the lead Gamma if it is above threshold
00158     leadPFCand = leadPFGamma;
00159   } else {
00160     // If both are too low PT, just take the charged one
00161     leadPFCand = leadPFCH;
00162   }
00163 
00164   tau.setleadPFCand(leadPFCand);
00165 
00166   // Our cone axis is defined about the lead charged hadron
00167   reco::Candidate::LorentzVector coneAxis = leadPFCH->p4();
00168 
00169   /***********************************************
00170    ******     Cone Construction         **********
00171    ***********************************************/
00172 
00173   // Define the signal and isolation cone sizes for this jet and build filters
00174   // to select elements in the given DeltaR regions
00175 
00176   PFCandPtrDRFilter signalConePFCHFilter(
00177       coneAxis, -0.1, signalConeChargedHadrons_(*jet));
00178   PFCandPtrDRFilter signalConePFNHFilter(
00179       coneAxis, -0.1, signalConeNeutralHadrons_(*jet));
00180   PiZeroDRFilter signalConePiZeroFilter(
00181       coneAxis, -0.1, signalConePiZeros_(*jet));
00182 
00183   PFCandPtrDRFilter isoConePFCHFilter(
00184       coneAxis, signalConeChargedHadrons_(*jet), isoConeChargedHadrons_(*jet));
00185   PFCandPtrDRFilter isoConePFGammaFilter(
00186       coneAxis, signalConePiZeros_(*jet), isoConePiZeros_(*jet));
00187   PFCandPtrDRFilter isoConePFNHFilter(
00188       coneAxis, signalConeNeutralHadrons_(*jet), isoConeNeutralHadrons_(*jet));
00189   PiZeroDRFilter isoConePiZeroFilter(
00190       coneAxis, signalConePiZeros_(*jet), isoConePiZeros_(*jet));
00191 
00192   // Additionally make predicates to select the different PF object types
00193   // of the regional junk objects to add to the iso cone.
00194   typedef xclean::PredicateAND<xclean::FilterPFCandByParticleId,
00195           PFCandPtrDRFilter> RegionalJunkConeAndIdFilter;
00196 
00197   xclean::FilterPFCandByParticleId
00198     pfchCandSelector(reco::PFCandidate::h);
00199   xclean::FilterPFCandByParticleId
00200     pfgammaCandSelector(reco::PFCandidate::gamma);
00201   xclean::FilterPFCandByParticleId
00202     pfnhCandSelector(reco::PFCandidate::h0);
00203 
00204   // Predicate to select the regional junk in the iso cone by PF id
00205   RegionalJunkConeAndIdFilter pfChargedJunk(
00206       pfchCandSelector, // select charged stuff from junk
00207       isoConePFCHFilter // only take those in iso cone
00208       );
00209 
00210   RegionalJunkConeAndIdFilter pfGammaJunk(
00211       pfgammaCandSelector, // select gammas from junk
00212       isoConePFGammaFilter // only take those in iso cone
00213       );
00214 
00215   RegionalJunkConeAndIdFilter pfNeutralJunk(
00216       pfnhCandSelector, // select neutral stuff from junk
00217       isoConePFNHFilter // select stuff in iso cone
00218       );
00219 
00220   // Build filter iterators select the signal charged stuff.
00221   PFCandPtrDRFilterIter signalPFCHs_begin(
00222       signalConePFCHFilter, pfchs.begin(), pfchs.end());
00223   PFCandPtrDRFilterIter signalPFCHs_end(
00224       signalConePFCHFilter, pfchs.end(), pfchs.end());
00225 
00226   // Cross clean pi zero content using signal cone charged hadron constituents.
00227   xclean::CrossCleanPiZeros<PFCandPtrDRFilterIter> xCleaner(
00228       signalPFCHs_begin, signalPFCHs_end);
00229   std::vector<reco::RecoTauPiZero> cleanPiZeros = xCleaner(piZeros);
00230 
00231   // For the rest of the constituents, we need to filter any constituents that
00232   // are already contained in the pizeros (i.e. electrons)
00233   xclean::CrossCleanPtrs pfCandXCleaner(cleanPiZeros);
00234 
00235   // Build signal charged hadrons
00236   tau.addPFCands(RecoTauConstructor::kSignal,
00237                  RecoTauConstructor::kChargedHadron,
00238                  signalPFCHs_begin, signalPFCHs_end);
00239 
00240   tau.addPFCands(RecoTauConstructor::kSignal,
00241                  RecoTauConstructor::kNeutralHadron,
00242                  boost::make_filter_iterator(
00243                    xclean::makePredicateAND(signalConePFNHFilter, pfCandXCleaner),
00244                    pfnhs.begin(), pfnhs.end()),
00245                  boost::make_filter_iterator(
00246                    xclean::makePredicateAND(signalConePFNHFilter, pfCandXCleaner),
00247                    pfnhs.end(), pfnhs.end()));
00248 
00249   // Build signal PiZeros
00250   tau.addPiZeros(RecoTauConstructor::kSignal,
00251                  PiZeroDRFilterIter(signalConePiZeroFilter,
00252                                     cleanPiZeros.begin(), cleanPiZeros.end()),
00253                  PiZeroDRFilterIter(signalConePiZeroFilter,
00254                                     cleanPiZeros.end(), cleanPiZeros.end()));
00255 
00256   // Build isolation charged hadrons
00257   tau.addPFCands(RecoTauConstructor::kIsolation,
00258                  RecoTauConstructor::kChargedHadron,
00259                  boost::make_filter_iterator(
00260                    xclean::makePredicateAND(isoConePFCHFilter, pfCandXCleaner),
00261                    pfchs.begin(), pfchs.end()),
00262                  boost::make_filter_iterator(
00263                    xclean::makePredicateAND(isoConePFCHFilter, pfCandXCleaner),
00264                    pfchs.end(), pfchs.end()));
00265 
00266   // Add all the stuff in the isolation cone that wasn't in the jet constituents
00267   tau.addPFCands(RecoTauConstructor::kIsolation,
00268                  RecoTauConstructor::kChargedHadron,
00269                  boost::make_filter_iterator(
00270                    pfChargedJunk, regionalJunk.begin(), regionalJunk.end()),
00271                  boost::make_filter_iterator(
00272                    pfChargedJunk, regionalJunk.end(), regionalJunk.end())
00273       );
00274 
00275   // Build isolation neutral hadrons
00276   tau.addPFCands(RecoTauConstructor::kIsolation,
00277                  RecoTauConstructor::kNeutralHadron,
00278                  boost::make_filter_iterator(
00279                    xclean::makePredicateAND(isoConePFNHFilter, pfCandXCleaner),
00280                    pfnhs.begin(), pfnhs.end()),
00281                  boost::make_filter_iterator(
00282                    xclean::makePredicateAND(isoConePFNHFilter, pfCandXCleaner),
00283                    pfnhs.end(), pfnhs.end()));
00284 
00285   // Add regional stuff not in jet
00286   tau.addPFCands(RecoTauConstructor::kIsolation,
00287                  RecoTauConstructor::kNeutralHadron,
00288                  boost::make_filter_iterator(
00289                    pfNeutralJunk, regionalJunk.begin(), regionalJunk.end()),
00290                  boost::make_filter_iterator(
00291                    pfNeutralJunk, regionalJunk.end(), regionalJunk.end())
00292       );
00293 
00294   // Build isolation PiZeros
00295   tau.addPiZeros(RecoTauConstructor::kIsolation,
00296                  PiZeroDRFilterIter(isoConePiZeroFilter, cleanPiZeros.begin(),
00297                                     cleanPiZeros.end()),
00298                  PiZeroDRFilterIter(isoConePiZeroFilter, cleanPiZeros.end(),
00299                                     cleanPiZeros.end()));
00300 
00301   // Add regional stuff not in jet
00302   tau.addPFCands(RecoTauConstructor::kIsolation,
00303                  RecoTauConstructor::kGamma,
00304                  boost::make_filter_iterator(
00305                    pfGammaJunk, regionalJunk.begin(), regionalJunk.end()),
00306                  boost::make_filter_iterator(
00307                    pfGammaJunk, regionalJunk.end(), regionalJunk.end())
00308       );
00309 
00310   // Put our built tau in the output - 'false' indicates don't build the
00311   // leading candidates, we already did that explicitly above.
00312 
00313   std::auto_ptr<reco::PFTau> tauPtr = tau.get(false);
00314 
00315   // Set event vertex position for tau
00316   reco::VertexRef primaryVertexRef = primaryVertex(jet);
00317   if ( primaryVertexRef.isNonnull() )
00318     tauPtr->setVertex(primaryVertexRef->position());
00319 
00320   output.push_back(tauPtr);
00321   return output.release();
00322 }
00323 }}  // end namespace reco::tauk
00324 
00325 #include "FWCore/Framework/interface/MakerMacros.h"
00326 DEFINE_EDM_PLUGIN(RecoTauBuilderPluginFactory,
00327                   reco::tau::RecoTauBuilderConePlugin,
00328                   "RecoTauBuilderConePlugin");