CMS 3D CMS Logo

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