CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_6/src/RecoTauTag/RecoTau/plugins/RecoTauBuilderCombinatoricPlugin.cc

Go to the documentation of this file.
00001 #include <vector>
00002 
00003 #include "RecoTauTag/RecoTau/interface/RecoTauBuilderPlugins.h"
00004 #include "RecoTauTag/RecoTau/interface/RecoTauCommonUtilities.h"
00005 
00006 #include "RecoTauTag/RecoTau/interface/CombinatoricGenerator.h"
00007 #include "RecoTauTag/RecoTau/interface/RecoTauCrossCleaning.h"
00008 #include "RecoTauTag/RecoTau/interface/ConeTools.h"
00009 
00010 #include "DataFormats/TauReco/interface/PFTau.h"
00011 #include "DataFormats/TauReco/interface/RecoTauPiZero.h"
00012 #include "DataFormats/VertexReco/interface/Vertex.h"
00013 #include "RecoTauTag/RecoTau/interface/RecoTauConstructor.h"
00014 #include "RecoTauTag/RecoTau/interface/RecoTauQualityCuts.h"
00015 
00016 namespace reco { namespace tau {
00017 
00018 class RecoTauBuilderCombinatoricPlugin : public RecoTauBuilderPlugin {
00019   public:
00020     explicit RecoTauBuilderCombinatoricPlugin(const edm::ParameterSet& pset);
00021     virtual ~RecoTauBuilderCombinatoricPlugin() {}
00022     virtual return_type operator() (const reco::PFJetRef& jet,
00023          const std::vector<RecoTauPiZero>& piZeros,
00024          const std::vector<PFCandidatePtr>& regionalExtras) const;
00025   private:
00026     RecoTauQualityCuts qcuts_;
00027     bool usePFLeptonsAsChargedHadrons_;
00028     double isolationConeSize_;
00029     struct decayModeInfo {
00030       uint32_t maxPiZeros_;
00031       uint32_t maxPFCHs_;
00032       uint32_t nCharged_;
00033       uint32_t nPiZeros_;
00034     };
00035     std::vector<decayModeInfo> decayModesToBuild_;
00036 };
00037 
00038 RecoTauBuilderCombinatoricPlugin::RecoTauBuilderCombinatoricPlugin(
00039     const edm::ParameterSet& pset): RecoTauBuilderPlugin(pset),
00040   qcuts_(pset.getParameterSet(
00041         "qualityCuts").getParameterSet("signalQualityCuts")),
00042   usePFLeptonsAsChargedHadrons_(pset.getParameter<bool>("usePFLeptons")),
00043   isolationConeSize_(pset.getParameter<double>("isolationConeSize")) {
00044   typedef std::vector<edm::ParameterSet> VPSet;
00045   const VPSet& decayModes = pset.getParameter<VPSet>("decayModes");
00046   for (VPSet::const_iterator dm = decayModes.begin();
00047       dm != decayModes.end(); ++dm) {
00048     decayModeInfo info;
00049     info.nCharged_ = dm->getParameter<uint32_t>("nCharged");
00050     info.nPiZeros_ = dm->getParameter<uint32_t>("nPiZeros");
00051     info.maxPFCHs_ = dm->getParameter<uint32_t>("maxTracks");
00052     info.maxPiZeros_ = dm->getParameter<uint32_t>("maxPiZeros");
00053     decayModesToBuild_.push_back(info);
00054   }
00055 }
00056 
00057 RecoTauBuilderCombinatoricPlugin::return_type
00058 RecoTauBuilderCombinatoricPlugin::operator()(
00059     const reco::PFJetRef& jet,
00060     const std::vector<RecoTauPiZero>& piZeros,
00061     const std::vector<PFCandidatePtr>& regionalExtras) const {
00062 
00063   typedef std::vector<PFCandidatePtr> PFCandPtrs;
00064   typedef std::vector<RecoTauPiZero> PiZeroList;
00065 
00066   output_type output;
00067 
00068   // Update the primary vertex used by the quality cuts.  The PV is supplied by
00069   // the base class.
00070   qcuts_.setPV(primaryVertex(jet));
00071 
00072   // Get PFCHs from this jet.  They are already sorted by descending Pt
00073   PFCandPtrs pfchs;
00074   if (!usePFLeptonsAsChargedHadrons_) {
00075     pfchs = qcuts_.filterRefs(pfCandidates(*jet, reco::PFCandidate::h));
00076   } else {
00077     // Check if we want to include electrons in muons in "charged hadron"
00078     // collection.  This is the preferred behavior, as the PF lepton selections
00079     // are very loose.
00080     pfchs = qcuts_.filterRefs(pfChargedCands(*jet));
00081   }
00082 
00083   PFCandPtrs pfnhs = qcuts_.filterRefs(
00084       pfCandidates(*jet, reco::PFCandidate::h0));
00085 
00088   PFCandPtrs regionalJunk = qcuts_.filterRefs(regionalExtras);
00089 
00090   // Loop over the decay modes we want to build
00091   for (std::vector<decayModeInfo>::const_iterator
00092        decayMode = decayModesToBuild_.begin();
00093        decayMode != decayModesToBuild_.end(); ++decayMode) {
00094     // Find how many piZeros are in this decay mode
00095     size_t piZerosToBuild = decayMode->nPiZeros_;
00096     // Find how many tracks are in this decay mode
00097     size_t tracksToBuild = decayMode->nCharged_;
00098 
00099     // Skip decay mode if jet doesn't have the multiplicity to support it
00100     if (pfchs.size() < tracksToBuild)
00101       continue;
00102 
00103     // Find the start and end of potential signal tracks
00104     PFCandPtrs::iterator pfch_begin = pfchs.begin();
00105     PFCandPtrs::iterator pfch_end =  pfchs.end();
00106     pfch_end = takeNElements(pfch_begin, pfch_end, decayMode->maxPFCHs_);
00107 
00108     // Build our track combo generator
00109     typedef tau::CombinatoricGenerator<PFCandPtrs> PFCombo;
00110     PFCombo trackCombos(pfch_begin, pfch_end, tracksToBuild);
00111 
00112     /*
00113      * Begin combinatoric loop for this decay mode
00114      */
00115 
00116     // Loop over the different combinations of tracks
00117     for (PFCombo::iterator trackCombo = trackCombos.begin();
00118          trackCombo != trackCombos.end(); ++trackCombo) {
00119 
00120       xclean::CrossCleanPiZeros<PFCombo::combo_iterator>
00121         xCleaner(trackCombo->combo_begin(), trackCombo->combo_end());
00122 
00123       PiZeroList cleanPiZeros = xCleaner(piZeros);
00124 
00125       // Skip decay mode if we don't have enough remaining clean pizeros to
00126       // build it.
00127       if (cleanPiZeros.size() < piZerosToBuild)
00128         continue;
00129 
00130       // Find the start and end of potential signal tracks
00131       PiZeroList::iterator piZero_begin = cleanPiZeros.begin();
00132       PiZeroList::iterator piZero_end = cleanPiZeros.end();
00133 
00134       piZero_end = takeNElements(piZero_begin, piZero_end,
00135                                  decayMode->maxPiZeros_);
00136 
00137       // Build our piZero combo generator
00138       typedef tau::CombinatoricGenerator<PiZeroList> PiZeroCombo;
00139       PiZeroCombo piZeroCombos(piZero_begin, piZero_end, piZerosToBuild);
00140 
00141       // Loop over the different combinations of PiZeros
00142       for (PiZeroCombo::iterator piZeroCombo = piZeroCombos.begin();
00143            piZeroCombo != piZeroCombos.end(); ++piZeroCombo) {
00144 
00145         // Output tau
00146         RecoTauConstructor tau(jet, getPFCands(), true);
00147         // Reserve space in our collections
00148         tau.reserve(RecoTauConstructor::kSignal,
00149                     RecoTauConstructor::kChargedHadron, tracksToBuild);
00150         tau.reserve(
00151             RecoTauConstructor::kSignal,
00152             RecoTauConstructor::kGamma, 2*piZerosToBuild);  // k-factor = 2
00153         tau.reservePiZero(RecoTauConstructor::kSignal, piZerosToBuild);
00154 
00155         // FIXME - are all these reserves okay?  will they get propagated to the
00156         // dataformat size if they are wrong?
00157         tau.reserve(
00158             RecoTauConstructor::kIsolation,
00159             RecoTauConstructor::kChargedHadron, pfchs.size() - tracksToBuild);
00160         tau.reserve(RecoTauConstructor::kIsolation,
00161                     RecoTauConstructor::kGamma,
00162                     (cleanPiZeros.size() - piZerosToBuild)*2);
00163         tau.reservePiZero(RecoTauConstructor::kIsolation,
00164                           (cleanPiZeros.size() - piZerosToBuild));
00165 
00166         // Set signal and isolation components for charged hadrons, after
00167         // converting them to a PFCandidateRefVector
00168         tau.addPFCands(
00169             RecoTauConstructor::kSignal, RecoTauConstructor::kChargedHadron,
00170             trackCombo->combo_begin(), trackCombo->combo_end()
00171             );
00172 
00173         // Get signal PiZero constituents and add them to the tau.
00174         // The sub-gammas are automatically added.
00175         tau.addPiZeros(
00176             RecoTauConstructor::kSignal,
00177             piZeroCombo->combo_begin(), piZeroCombo->combo_end()
00178             );
00179 
00180         // Now build isolation collections
00181         // Load our isolation tools
00182         using namespace reco::tau::cone;
00183         PFCandPtrDRFilter isolationConeFilter(tau.p4(), 0, isolationConeSize_);
00184 
00185         // Cross cleaning predicate.  Remove any PFCandidatePtrs that are
00186         // contained within existing PiZeros.  This predicate will return false
00187         // for any object that overlaps with cleanPiZeros.
00188         xclean::CrossCleanPtrs pfCandXCleaner(cleanPiZeros);
00189         // And this cleaning filter predicate with our Iso cone filter
00190         xclean::PredicateAND<PFCandPtrDRFilter, xclean::CrossCleanPtrs>
00191           pfCandFilter(isolationConeFilter, pfCandXCleaner);
00192 
00193         PiZeroDRFilter isolationConeFilterPiZero(
00194             tau.p4(), 0, isolationConeSize_);
00195 
00196         // Additionally make predicates to select the different PF object types
00197         // of the regional junk objects to add
00198         typedef xclean::PredicateAND<xclean::FilterPFCandByParticleId,
00199                 PFCandPtrDRFilter> RegionalJunkConeAndIdFilter;
00200 
00201         xclean::FilterPFCandByParticleId
00202           pfchCandSelector(reco::PFCandidate::h);
00203         xclean::FilterPFCandByParticleId
00204           pfgammaCandSelector(reco::PFCandidate::gamma);
00205         xclean::FilterPFCandByParticleId
00206           pfnhCandSelector(reco::PFCandidate::h0);
00207 
00208         RegionalJunkConeAndIdFilter pfChargedJunk(
00209             pfchCandSelector, // select charged stuff from junk
00210             isolationConeFilter // only take those in iso cone
00211             );
00212 
00213         RegionalJunkConeAndIdFilter pfGammaJunk(
00214             pfgammaCandSelector, // select gammas from junk
00215             isolationConeFilter // only take those in iso cone
00216             );
00217 
00218         RegionalJunkConeAndIdFilter pfNeutralJunk(
00219             pfnhCandSelector, // select neutral stuff from junk
00220             isolationConeFilter // select stuff in iso cone
00221             );
00222 
00223         // Filter the isolation candidates in a DR cone
00224         tau.addPFCands(
00225             RecoTauConstructor::kIsolation, RecoTauConstructor::kChargedHadron,
00226             boost::make_filter_iterator(
00227                 pfCandFilter,
00228                 trackCombo->remainder_begin(), trackCombo->remainder_end()),
00229             boost::make_filter_iterator(
00230                 pfCandFilter,
00231                 trackCombo->remainder_end(), trackCombo->remainder_end())
00232             );
00233 
00234         // Add all the candidates that weren't included in the combinatoric
00235         // generation
00236         tau.addPFCands(
00237             RecoTauConstructor::kIsolation, RecoTauConstructor::kChargedHadron,
00238             boost::make_filter_iterator(
00239                 pfCandFilter,
00240                 pfch_end, pfchs.end()),
00241             boost::make_filter_iterator(
00242                 pfCandFilter,
00243                 pfchs.end(), pfchs.end())
00244             );
00245         // Add all charged candidates that are in the iso cone but weren't in the
00246         // original PFJet
00247         tau.addPFCands(
00248             RecoTauConstructor::kIsolation, RecoTauConstructor::kChargedHadron,
00249             boost::make_filter_iterator(
00250                 pfChargedJunk, regionalJunk.begin(), regionalJunk.end()),
00251             boost::make_filter_iterator(
00252                 pfChargedJunk, regionalJunk.end(), regionalJunk.end())
00253             );
00254 
00255         // Add all gammas that are in the iso cone but weren't in the
00256         // orginal PFJet
00257         tau.addPFCands(
00258             RecoTauConstructor::kIsolation, RecoTauConstructor::kGamma,
00259             boost::make_filter_iterator(
00260                 pfGammaJunk, regionalJunk.begin(), regionalJunk.end()),
00261             boost::make_filter_iterator(
00262                 pfGammaJunk, regionalJunk.end(), regionalJunk.end())
00263             );
00264 
00265         // Add all the netural hadron candidates to the isolation collection
00266         tau.addPFCands(
00267             RecoTauConstructor::kIsolation, RecoTauConstructor::kNeutralHadron,
00268             boost::make_filter_iterator(
00269                 pfCandFilter,
00270                 pfnhs.begin(), pfnhs.end()),
00271             boost::make_filter_iterator(
00272                 pfCandFilter,
00273                 pfnhs.end(), pfnhs.end())
00274             );
00275         // Add all the netural hadrons from the region collection that are in
00276         // the iso cone to the tau
00277         tau.addPFCands(
00278             RecoTauConstructor::kIsolation,  RecoTauConstructor::kNeutralHadron,
00279             boost::make_filter_iterator(
00280               pfNeutralJunk, regionalJunk.begin(), regionalJunk.end()),
00281             boost::make_filter_iterator(
00282               pfNeutralJunk, regionalJunk.end(), regionalJunk.end())
00283             );
00284 
00285         tau.addPiZeros(
00286             RecoTauConstructor::kIsolation,
00287             boost::make_filter_iterator(
00288                 isolationConeFilterPiZero,
00289                 piZeroCombo->remainder_begin(), piZeroCombo->remainder_end()),
00290             boost::make_filter_iterator(
00291                 isolationConeFilterPiZero,
00292                 piZeroCombo->remainder_end(), piZeroCombo->remainder_end())
00293             );
00294 
00295         tau.addPiZeros(
00296             RecoTauConstructor::kIsolation,
00297             boost::make_filter_iterator(
00298                 isolationConeFilterPiZero,
00299                 piZero_end, cleanPiZeros.end()),
00300             boost::make_filter_iterator(
00301                 isolationConeFilterPiZero,
00302                 cleanPiZeros.end(), cleanPiZeros.end())
00303             );
00304 
00305         std::auto_ptr<reco::PFTau> tauPtr = tau.get(true);
00306 
00307         // Set event vertex position for tau
00308         reco::VertexRef primaryVertexRef = primaryVertex(jet);
00309         if ( primaryVertexRef.isNonnull() )
00310           tauPtr->setVertex(primaryVertexRef->position());
00311 
00312         output.push_back(tauPtr);
00313       }
00314     }
00315   }
00316   return output.release();
00317 }
00318 }}  // end namespace reco::tau
00319 
00320 #include "FWCore/Framework/interface/MakerMacros.h"
00321 DEFINE_EDM_PLUGIN(RecoTauBuilderPluginFactory,
00322                   reco::tau::RecoTauBuilderCombinatoricPlugin,
00323                   "RecoTauBuilderCombinatoricPlugin");