CMS 3D CMS Logo

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