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