CMS 3D CMS Logo

RecoTauCleaner.cc
Go to the documentation of this file.
1 /*
2  * RecoTauCleaner
3  *
4  * Author: Evan K. Friis, UC Davis
5  *
6  * Given a input collection of PFTaus, produces an output collection of PFTaus
7  * such that no two PFTaus come from the same PFJet. If multiple taus in the
8  * collection come from the same PFJet, (dirty) they are ordered according to a
9  * list of cleaners. Each cleaner is a RecoTauCleanerPlugin, and returns a
10  * double corresponding to the 'quality' for a given tau - an example would be
11  * the level of isolation. The set of dirty taus is then ranked
12  * lexicographically by these cleaners, and the best one is placed in the
13  * output collection.
14  *
15  */
16 
17 #include <boost/ptr_container/ptr_vector.hpp>
18 #include <algorithm>
19 #include <memory>
20 
26 
29 
33 
40 
42 
43 template<typename Prod>
45 {
48  {
49  std::shared_ptr<Cleaner> plugin_;
50  float tolerance_;
51  };
52  typedef std::vector<std::unique_ptr<CleanerEntryType> > CleanerList;
53  // Define our output type - i.e. reco::PFTau OR reco::PFTauRef
54  typedef typename Prod::value_type output_type;
55 
56  // Predicate that determines if two taus 'overlap' i.e. share a base PFJet
58  {
59  public:
60  bool operator()(const reco::PFTauRef& a, const reco::PFTauRef& b) const { return (a->jetRef() == b->jetRef()); }
61  };
62 
63  public:
64  explicit RecoTauCleanerImpl(const edm::ParameterSet& pset);
65  ~RecoTauCleanerImpl() override;
66  void produce(edm::Event& evt, const edm::EventSetup& es) override;
67 
68  static void fillDescriptions(edm::ConfigurationDescriptions & descriptions);
69 
70  private:
72  CleanerList cleaners_;
73  // Optional selection on the output of the taus
74  std::unique_ptr<const StringCutObjectSelector<reco::PFTau> > outputSelector_;
77 };
78 
79 template<typename Prod>
81 {
82  tauSrc_ = pset.getParameter<edm::InputTag>("src");
83  tau_token=consumes<reco::PFTauCollection>(tauSrc_);
84  // Build our list of quality plugins
85  typedef std::vector<edm::ParameterSet> VPSet;
86  // Get each of our tau builders
87  const VPSet& cleaners = pset.getParameter<VPSet>("cleaners");
88  for ( VPSet::const_iterator cleanerPSet = cleaners.begin();
89  cleanerPSet != cleaners.end(); ++cleanerPSet ) {
90  auto cleanerEntry = std::make_unique<CleanerEntryType>();
91  // Get plugin name
92  const std::string& pluginType = cleanerPSet->getParameter<std::string>("plugin");
93  // Build the plugin
94  cleanerEntry->plugin_ = std::unique_ptr<Cleaner>{RecoTauCleanerPluginFactory::get()->create(pluginType, *cleanerPSet, consumesCollector())};
95  cleanerEntry->tolerance_ = cleanerPSet->getParameter<double>("tolerance");
96  cleaners_.emplace_back(std::move(cleanerEntry));
97  }
98 
99  // Check if we want to apply a final output selection
100  std::string selection = pset.getParameter<std::string>("outputSelection");
101  if ( !selection.empty() ) {
102  outputSelector_ = std::make_unique<StringCutObjectSelector<reco::PFTau>>(selection);
103  }
104 
105  // Enable/disable debug output
106  verbosity_ = pset.getParameter<int>("verbosity");
107 
108  // Build the predicate that ranks our taus.
109  produces<Prod>();
110 }
111 
112 template<typename Prod>
114 {
115 }
116 
117 namespace {
118 // Template to convert a ref to desired output type
119 template<typename T> const T convert(const reco::PFTauRef &tau);
120 
121  //template<> const edm::RefToBase<reco::PFTau>
122  //convert<edm::RefToBase<reco::PFTau> >(const reco::PFTauRef &tau) {
123  // return edm::RefToBase<reco::PFTau>(tau);
124  //}
125 
126 template<> const reco::PFTauRef
127 convert<reco::PFTauRef>(const reco::PFTauRef &tau) { return tau; }
128 
129 template<> const reco::PFTau
130 convert<reco::PFTau>(const reco::PFTauRef &tau) { return *tau; }
131 }
132 
133 namespace
134 {
135  template <typename T>
136  std::string format_vT(const std::vector<T>& vT)
137  {
138  std::ostringstream os;
139  os << "{ ";
140  unsigned numEntries = vT.size();
141  for ( unsigned iEntry = 0; iEntry < numEntries; ++iEntry ) {
142  os << vT[iEntry];
143  if ( iEntry < (numEntries - 1) ) os << ", ";
144  }
145  os << " }";
146  return os.str();
147  }
148 
149  struct PFTauRankType
150  {
151  PFTauRankType(const reco::PFTauRef& tauRef)
152  : idx_(tauRef.key()),
153  tauRef_(tauRef)
154  {}
155  ~PFTauRankType() {}
156  void print(const std::string& label) const
157  {
158  std::cout << label << " (" << tauRef_.id() << ":" << tauRef_.key() << ", idx = " << idx_ << "):";
159  assert(tauRef_.key() == idx_);
160  std::cout << " Pt = " << tauRef_->pt() << ", eta = " << tauRef_->eta() << ", phi = " << tauRef_->phi() << ", mass = " << tauRef_->mass() << " (decayMode = " << tauRef_->decayMode() << ")";
161  std::cout << std::endl;
162  std::cout << "associated jet:";
163  if ( tauRef_->jetRef().isNonnull() ) {
164  std::cout << " Pt = " << tauRef_->jetRef()->pt() << ", eta = " << tauRef_->jetRef()->eta() << ", phi = " << tauRef_->jetRef()->phi()
165  << ", mass = " << tauRef_->jetRef()->mass() << ", area = " << tauRef_->jetRef()->jetArea();
166  }
167  else std::cout << " N/A";
168  std::cout << std::endl;
169  const std::vector<reco::PFRecoTauChargedHadron>& signalTauChargedHadronCandidates = tauRef_->signalTauChargedHadronCandidates();
170  size_t numChargedHadrons = signalTauChargedHadronCandidates.size();
171  for ( size_t iChargedHadron = 0; iChargedHadron < numChargedHadrons; ++iChargedHadron ) {
172  const reco::PFRecoTauChargedHadron& chargedHadron = signalTauChargedHadronCandidates.at(iChargedHadron);
173  std::cout << " chargedHadron #" << iChargedHadron << ":" << std::endl;
174  chargedHadron.print(std::cout);
175  }
176  const std::vector<reco::RecoTauPiZero>& signalPiZeroCandidates = tauRef_->signalPiZeroCandidates();
177  size_t numPiZeros = signalPiZeroCandidates.size();
178  std::cout << "signalPiZeroCandidates = " << numPiZeros << std::endl;
179  for ( size_t iPiZero = 0; iPiZero < numPiZeros; ++iPiZero ) {
180  const reco::RecoTauPiZero& piZero = signalPiZeroCandidates.at(iPiZero);
181  std::cout << " piZero #" << iPiZero << ": Pt = " << piZero.pt() << ", eta = " << piZero.eta() << ", phi = " << piZero.phi() << ", mass = " << piZero.mass() << std::endl;
182  }
183  const auto& isolationCands = tauRef_->isolationCands();
184  size_t numCands = isolationCands.size();
185  std::cout << "isolationCands = " << numCands << std::endl;
186  for ( size_t iCand = 0; iCand < numCands; ++iCand ) {
187  const auto& cand = isolationCands.at(iCand);
188  std::cout << " pfCand #" << iCand << " (" << cand.id() << ":" << cand.key() << "):"
189  << " Pt = " << cand->pt() << ", eta = " << cand->eta() << ", phi = " << cand->phi() << std::endl;
190  }
191  std::cout << " ranks = " << format_vT(ranks_) << std::endl;
192  std::cout << " tolerances = " << format_vT(tolerances_) << std::endl;
193  }
194  size_t idx_;
195  reco::PFTauRef tauRef_;
196  size_t N_;
197  std::vector<float> ranks_;
198  std::vector<float> tolerances_;
199  };
200 
201  bool isHigherRank(const PFTauRankType* tau1, const PFTauRankType* tau2)
202  {
203  //std::cout << "<isHigherRank>:" << std::endl;
204  //std::cout << "tau1 @ " << tau1;
205  //tau1->print("");
206  //std::cout << "tau2 @ " << tau2;
207  //tau2->print("");
208  assert(tau1->N_ == tau1->ranks_.size());
209  assert(tau1->N_ == tau2->ranks_.size());
210  assert(tau1->N_ == tau1->tolerances_.size());
211  for ( size_t i = 0; i < tau1->N_; ++i ) {
212  const float& val1 = tau1->ranks_[i];
213  const float& val2 = tau2->ranks_[i];
214  double av = 0.5*(val1 + val2);
215  double thresh = av*tau1->tolerances_[i];
216  if ( val1 < (val2 - thresh) ) return true;
217  else if ( val2 < (val1 - thresh) ) return false;
218  }
219  return true;
220  }
221 }
222 
223 template<typename Prod>
225 {
226  if ( verbosity_ ) {
227  std::cout << "<RecoTauCleanerImpl::produce>:" << std::endl;
228  }
229 
230  // Update all our cleaners with the event info if they need it
231  for ( typename CleanerList::iterator cleaner = cleaners_.begin();
232  cleaner != cleaners_.end(); ++cleaner ) {
233  (*cleaner)->plugin_->setup(evt, es);
234  }
235 
236  // Get the input collection of all taus. Some are from the same PFJet. We must clean them.
238  evt.getByToken(tau_token, inputTaus);
239 
240  // Sort the input tau refs according to our predicate
241  std::list<PFTauRankType*> rankedTaus;
242  size_t N = inputTaus->size();
243  for ( size_t idx = 0; idx < N; ++idx ) {
244  reco::PFTauRef inputRef(inputTaus, idx);
245  PFTauRankType* rankedTau = new PFTauRankType(inputRef);
246  rankedTau->N_ = cleaners_.size();
247  rankedTau->ranks_.reserve(rankedTau->N_);
248  rankedTau->tolerances_.reserve(rankedTau->N_);
249  for ( typename CleanerList::const_iterator cleaner = cleaners_.begin();
250  cleaner != cleaners_.end(); ++cleaner ) {
251  rankedTau->ranks_.push_back((*(*cleaner)->plugin_)(inputRef));
252  rankedTau->tolerances_.push_back((*cleaner)->tolerance_);
253  }
254  if ( verbosity_ ) {
255  std::ostringstream os;
256  os << "rankedTau #" << idx;
257  rankedTau->print(os.str());
258  }
259  rankedTaus.push_back(rankedTau);
260  }
261  rankedTaus.sort(isHigherRank);
262 
263  // Make an STL algorithm friendly vector of refs
264  typedef std::vector<reco::PFTauRef> PFTauRefs;
265  PFTauRefs dirty(inputTaus->size());
266  size_t idx_sorted = 0;
267  for ( std::list<PFTauRankType*>::const_iterator rankedTau = rankedTaus.begin();
268  rankedTau != rankedTaus.end(); ++rankedTau ) {
269  dirty[idx_sorted] = (*rankedTau)->tauRef_;
270  if ( verbosity_ ) {
271  std::cout << "dirty[" << idx_sorted << "] = " << dirty[idx_sorted].id() << ":" << dirty[idx_sorted].key() << std::endl;
272  }
273  delete (*rankedTau);
274  ++idx_sorted;
275  }
276 
277  // Clean the taus, ensuring that only one tau per jet is produced
278  PFTauRefs cleanTaus = reco::tau::cleanOverlaps<PFTauRefs, RemoveDuplicateJets>(dirty);
279 
280  // create output collection
281  auto output = std::make_unique<Prod>();
282  //output->reserve(cleanTaus.size());
283 
284  // Copy clean refs into output
285  for ( PFTauRefs::const_iterator tau = cleanTaus.begin();
286  tau != cleanTaus.end(); ++tau ) {
287  // If we are applying an output selection, check if it passes
288  bool selected = true;
289  if ( outputSelector_.get() && !(*outputSelector_)(**tau) ) {
290  selected = false;
291  }
292  if ( selected ) {
293  output->push_back(convert<output_type>(*tau));
294  }
295  }
296  evt.put(std::move(output));
297 }
298 
301 
302 template <>
303 void
305  // RecoTauCleaner
307  desc.add<std::string>("outputSelection", "");
308  {
309  // this description is the validator for all PSets in the cleaners VPSet passed to the plugin from the python configuration
310  edm::ParameterSetDescription vps_description_for_cleaners;
311  // the common parameters for all cleaners
312  // no default value is provided -- the user has to provide the values for these parameters
313  vps_description_for_cleaners.add<std::string>("plugin");
314  vps_description_for_cleaners.add<double>("tolerance", 0);
315  vps_description_for_cleaners.add<std::string>("name");
316 
317  // the following parameters are not common for all cleaners, they are needed for few PSets, therefore they are added as optional
318  // these optional parameters are used in the default cleaners vector
319  vps_description_for_cleaners.addOptional<int>("passForCharge");
320  vps_description_for_cleaners.addOptional<double>("selectionFailValue");
321  vps_description_for_cleaners.addOptional<std::vector<unsigned int>>("nprongs");
322  vps_description_for_cleaners.addOptional<edm::InputTag>("src");
323  vps_description_for_cleaners.addOptional<double>("minTrackPt");
324  vps_description_for_cleaners.addOptional<std::string>("selection");
325  vps_description_for_cleaners.addOptional<std::string>("selectionPassFunction");
326  // more PSets for cleaners can be found in
327  // RecoTauTag/RecoTau/python/RecoTauCleanerPlugins.py
328  // however, at this moment (2018-11-09) they do not have any new optional parameters
329 
330  // the cleaner defaults, as in RecoTauTag/RecoTau/python/RecoTauCleaner_cfi.py
331  std::vector<edm::ParameterSet> default_cleaners;
332  default_cleaners.reserve(7);
333  {
334  edm::ParameterSet cleaner_Charge;
335  cleaner_Charge.addParameter<std::string>("name", "Charge");
336  cleaner_Charge.addParameter<std::string>("plugin", "RecoTauChargeCleanerPlugin");
337  cleaner_Charge.addParameter<int>("passForCharge", 1);
338  cleaner_Charge.addParameter<double>("selectionFailValue", 0);
339  cleaner_Charge.addParameter<std::vector<unsigned int>>("nprongs", {1, 3,});
340  cleaner_Charge.addParameter<double>("tolerance", 0);
341  default_cleaners.push_back(cleaner_Charge);
342  }
343  {
344  edm::ParameterSet temp2;
345  temp2.addParameter<std::string>("name", "HPS_Select");
346  temp2.addParameter<std::string>("plugin", "RecoTauDiscriminantCleanerPlugin");
347  temp2.addParameter<edm::InputTag>("src", edm::InputTag("hpsSelectionDiscriminator"));
348  temp2.addParameter<double>("tolerance", 0);
349  default_cleaners.push_back(temp2);
350  }
351  {
352  edm::ParameterSet temp2;
353  temp2.addParameter<std::string>("name", "killSoftTwoProngTaus");
354  temp2.addParameter<std::string>("plugin", "RecoTauSoftTwoProngTausCleanerPlugin");
355  temp2.addParameter<double>("minTrackPt", 5.0);
356  temp2.addParameter<double>("tolerance", 0);
357  default_cleaners.push_back(temp2);
358  }
359  {
360  edm::ParameterSet temp2;
361  temp2.addParameter<std::string>("name", "ChargedHadronMultiplicity");
362  temp2.addParameter<std::string>("plugin", "RecoTauChargedHadronMultiplicityCleanerPlugin");
363  temp2.addParameter<double>("tolerance", 0);
364  default_cleaners.push_back(temp2);
365  }
366  {
367  edm::ParameterSet temp2;
368  temp2.addParameter<std::string>("name", "Pt");
369  temp2.addParameter<std::string>("plugin", "RecoTauStringCleanerPlugin");
370  temp2.addParameter<std::string>("selectionPassFunction", "-pt()");
371  temp2.addParameter<std::string>("selection", "leadPFCand().isNonnull()");
372  temp2.addParameter<double>("selectionFailValue", 1000.0);
373  temp2.addParameter<double>("tolerance", 0.01);
374  default_cleaners.push_back(temp2);
375  }
376  {
377  edm::ParameterSet temp2;
378  temp2.addParameter<std::string>("name", "StripMultiplicity");
379  temp2.addParameter<std::string>("plugin", "RecoTauStringCleanerPlugin");
380  temp2.addParameter<std::string>("selectionPassFunction", "-signalPiZeroCandidates().size()");
381  temp2.addParameter<std::string>("selection", "leadPFCand().isNonnull()");
382  temp2.addParameter<double>("selectionFailValue", 1000.0);
383  temp2.addParameter<double>("tolerance", 0);
384  default_cleaners.push_back(temp2);
385  }
386  {
387  edm::ParameterSet temp2;
388  temp2.addParameter<std::string>("name", "CombinedIsolation");
389  temp2.addParameter<std::string>("plugin", "RecoTauStringCleanerPlugin");
390  temp2.addParameter<std::string>("selectionPassFunction", "isolationPFChargedHadrCandsPtSum() + isolationPFGammaCandsEtSum()");
391  temp2.addParameter<std::string>("selection", "leadPFCand().isNonnull()");
392  temp2.addParameter<double>("selectionFailValue", 1000.0);
393  temp2.addParameter<double>("tolerance", 0);
394  default_cleaners.push_back(temp2);
395  }
396 
397  desc.addVPSet("cleaners", vps_description_for_cleaners, default_cleaners);
398  }
399 
400  desc.add<int>("verbosity", 0);
401  desc.add<edm::InputTag>("src", edm::InputTag("combinatoricRecoTaus"));
402  descriptions.add("RecoTauCleaner", desc);
403 }
404 
405 template <>
406 void
408 // there was no cfi file for this plugin
409 }
410 
412 
415 
T getParameter(std::string const &) const
RecoTauCleanerImpl< reco::PFTauRefVector > RecoTauRefCleaner
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:125
ParameterDescriptionBase * addOptional(U const &iLabel, T const &value)
double eta() const final
momentum pseudorapidity
ParameterDescriptionBase * addVPSet(U const &iLabel, ParameterSetDescription const &validator, std::vector< ParameterSet > const &defaults)
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:517
bool operator()(const reco::PFTauRef &a, const reco::PFTauRef &b) const
edm::InputTag tauSrc_
std::vector< std::unique_ptr< CleanerEntryType > > CleanerList
selection
main part
Definition: corrVsCorr.py:100
double pt() const final
transverse momentum
key_type key() const
Accessor for product key.
Definition: Ref.h:263
RecoTauCleanerImpl< reco::PFTauCollection > RecoTauCleaner
S & print(S &os, JobReport::InputFile const &f)
Definition: JobReport.cc:66
edm::EDGetTokenT< reco::PFTauCollection > tau_token
void print(std::ostream &stream=std::cout) const
char const * label
CleanerList cleaners_
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
Long64_t numEntries(TFile *hdl, std::string const &trname)
Definition: CollUtil.cc:50
void addParameter(std::string const &name, T const &value)
Definition: ParameterSet.h:125
ParameterDescriptionBase * add(U const &iLabel, T const &value)
def convert(infile, ofile)
#define N
Definition: blowfish.cc:9
double b
Definition: hdecay.h:120
void add(std::string const &label, ParameterSetDescription const &psetDescription)
reco::tau::RecoTauCleanerPlugin Cleaner
double a
Definition: hdecay.h:121
std::unique_ptr< const StringCutObjectSelector< reco::PFTau > > outputSelector_
void produce(edm::Event &evt, const edm::EventSetup &es) override
long double T
double phi() const final
momentum azimuthal angle
Prod::value_type output_type
~RecoTauCleanerImpl() override
def move(src, dest)
Definition: eostools.py:511
T get(const Candidate &c)
Definition: component.h:55
RecoTauCleanerImpl(const edm::ParameterSet &pset)
double mass() const final
mass
std::shared_ptr< Cleaner > plugin_