CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
PFRecoTauDiscriminationByIsolation.cc
Go to the documentation of this file.
1 #include <functional>
2 #include <boost/foreach.hpp>
9 
10 #include "TMath.h"
11 #include "TFormula.h"
12 
13 /* class PFRecoTauDiscriminationByIsolation
14  * created : Jul 23 2007,
15  * revised : Thu Aug 13 14:44:40 PDT 2009
16  * contributors : Ludovic Houchu (IPHC, Strasbourg),
17  * Christian Veelken (UC Davis),
18  * Evan K. Friis (UC Davis)
19  * Michalis Bachtis (UW Madison)
20  */
21 
22 using namespace reco;
23 using namespace std;
24 
26 {
27  public:
30  moduleLabel_(pset.getParameter<std::string>("@module_label")),
31  qualityCutsPSet_(pset.getParameter<edm::ParameterSet>("qualityCuts"))
32  {
33  includeTracks_ = pset.getParameter<bool>(
34  "ApplyDiscriminationByTrackerIsolation");
35  includeGammas_ = pset.getParameter<bool>(
36  "ApplyDiscriminationByECALIsolation");
37 
38  applyOccupancyCut_ = pset.getParameter<bool>("applyOccupancyCut");
39  maximumOccupancy_ = pset.getParameter<uint32_t>("maximumOccupancy");
40 
41  applySumPtCut_ = pset.getParameter<bool>("applySumPtCut");
42  maximumSumPt_ = pset.getParameter<double>("maximumSumPtCut");
43 
44  applyRelativeSumPtCut_ = pset.getParameter<bool>(
45  "applyRelativeSumPtCut");
46  maximumRelativeSumPt_ = pset.getParameter<double>(
47  "relativeSumPtCut");
48  offsetRelativeSumPt_ = pset.exists("relativeSumPtOffset") ?
49  pset.getParameter<double>("relativeSumPtOffset") : 0.0;
50 
51  storeRawOccupancy_ = pset.exists("storeRawOccupancy") ?
52  pset.getParameter<bool>("storeRawOccupancy") : false;
53  storeRawSumPt_ = pset.exists("storeRawSumPt") ?
54  pset.getParameter<bool>("storeRawSumPt") : false;
55  storeRawPUsumPt_ = pset.exists("storeRawPUsumPt") ?
56  pset.getParameter<bool>("storeRawPUsumPt") : false;
57 
58  // Sanity check on requested options. We can't apply cuts and store the
59  // raw output at the same time
60  if ( applySumPtCut_ || applyOccupancyCut_ || applyRelativeSumPtCut_ ) {
61  if ( storeRawSumPt_ || storeRawOccupancy_ || storeRawPUsumPt_ ) {
62  throw cms::Exception("BadIsoConfig")
63  << "A 'store raw' and a 'apply cut' option have been set to true "
64  << "simultaneously. These options are mutually exclusive.";
65  }
66  }
67 
68  // Can only store one type
69  int numStoreOptions = 0;
70  if ( storeRawSumPt_ ) ++numStoreOptions;
71  if ( storeRawOccupancy_ ) ++numStoreOptions;
72  if ( storeRawPUsumPt_ ) ++numStoreOptions;
73  if ( numStoreOptions > 1 ) {
74  throw cms::Exception("BadIsoConfig")
75  << "Both 'store sum pt' and 'store occupancy' options are set."
76  << " These options are mutually exclusive.";
77  }
78 
79  if ( pset.exists("customOuterCone") ) {
80  customIsoCone_ = pset.getParameter<double>("customOuterCone");
81  } else {
82  customIsoCone_ = -1;
83  }
84 
85  // Get the quality cuts specific to the isolation region
86  edm::ParameterSet isolationQCuts = qualityCutsPSet_.getParameterSet(
87  "isolationQualityCuts");
88 
89  qcuts_.reset(new tau::RecoTauQualityCuts(isolationQCuts));
90 
91  vertexAssociator_.reset(
92  new tau::RecoTauVertexAssociator(qualityCutsPSet_,consumesCollector()));
93 
94  applyDeltaBeta_ = pset.exists("applyDeltaBetaCorrection") ?
95  pset.getParameter<bool>("applyDeltaBetaCorrection") : false;
96 
97  if ( applyDeltaBeta_ ) {
98  // Factorize the isolation QCuts into those that are used to
99  // select PU and those that are not.
100  std::pair<edm::ParameterSet, edm::ParameterSet> puFactorizedIsoQCuts =
101  reco::tau::factorizePUQCuts(isolationQCuts);
102 
103  // Determine the pt threshold for the PU tracks
104  // First check if the user specifies explicitly the cut.
105  if ( pset.exists("deltaBetaPUTrackPtCutOverride") ) {
106  puFactorizedIsoQCuts.second.addParameter<double>(
107  "minTrackPt",
108  pset.getParameter<double>("deltaBetaPUTrackPtCutOverride"));
109  } else {
110  // Secondly take it from the minGammaEt
111  puFactorizedIsoQCuts.second.addParameter<double>(
112  "minTrackPt",
113  isolationQCuts.getParameter<double>("minGammaEt"));
114  }
115 
116  pileupQcutsPUTrackSelection_.reset(new tau::RecoTauQualityCuts(
117  puFactorizedIsoQCuts.first));
118 
119  pileupQcutsGeneralQCuts_.reset(new tau::RecoTauQualityCuts(
120  puFactorizedIsoQCuts.second));
121 
122  pfCandSrc_ = pset.getParameter<edm::InputTag>("particleFlowSrc");
123  pfCand_token=consumes<reco::PFCandidateCollection>(pfCandSrc_);
124  vertexSrc_ = pset.getParameter<edm::InputTag>("vertexSrc");
125  vertex_token=consumes<reco::VertexCollection>(vertexSrc_);
126  deltaBetaCollectionCone_ = pset.getParameter<double>(
127  "isoConeSizeForDeltaBeta");
128  std::string deltaBetaFactorFormula =
129  pset.getParameter<string>("deltaBetaFactor");
130  deltaBetaFormula_.reset(
131  new TFormula("DB_corr", deltaBetaFactorFormula.c_str()));
132  }
133 
134  applyRhoCorrection_ = pset.exists("applyRhoCorrection") ?
135  pset.getParameter<bool>("applyRhoCorrection") : false;
136  if ( applyRhoCorrection_ ) {
137  rhoProducer_ = pset.getParameter<edm::InputTag>("rhoProducer");
138  rho_token=consumes<double>(rhoProducer_);
139  rhoConeSize_ = pset.getParameter<double>("rhoConeSize");
140  rhoUEOffsetCorrection_ =
141  pset.getParameter<double>("rhoUEOffsetCorrection");
142  }
143 
144  verbosity_ = ( pset.exists("verbosity") ) ?
145  pset.getParameter<int>("verbosity") : 0;
146  }
147 
149 
150  void beginEvent(const edm::Event& evt, const edm::EventSetup& evtSetup) override;
151  double discriminate(const PFTauRef& pfTau) override;
152 
153  private:
155 
157  std::auto_ptr<tau::RecoTauQualityCuts> qcuts_;
158 
159  // Inverted QCut which selects tracks with bad DZ/trackWeight
160  std::auto_ptr<tau::RecoTauQualityCuts> pileupQcutsPUTrackSelection_;
161  std::auto_ptr<tau::RecoTauQualityCuts> pileupQcutsGeneralQCuts_;
162 
163  std::auto_ptr<tau::RecoTauVertexAssociator> vertexAssociator_;
164 
175 
176  // Options to store the raw value in the discriminator instead of boolean pass/fail flag
180 
181  /* **********************************************************************
182  **** Pileup Subtraction Parameters ***********************************
183  **********************************************************************/
184 
185  // Delta Beta correction
189  // Keep track of how many vertices are in the event
192  std::vector<reco::PFCandidatePtr> chargedPFCandidatesInEvent_;
193  std::vector<PFCandidatePtr> isoCharged_;
194  std::vector<PFCandidatePtr> isoNeutral_;
195  std::vector<PFCandidatePtr> isoPU_;
196  // Size of cone used to collect PU tracks
198  std::auto_ptr<TFormula> deltaBetaFormula_;
200 
201  // Rho correction
205  double rhoConeSize_;
209 
210  // Flag to enable/disable debug output
212 };
213 
215 {
216  // NB: The use of the PV in this context is necessitated by its use in
217  // applying quality cuts to the different objects in the isolation cone
218  // The vertex associator contains the logic to select the appropriate vertex
219  // We need to pass it the event so it can load the vertices.
220  vertexAssociator_->setEvent(event);
221 
222  // If we are applying the delta beta correction, we need to get the PF
223  // candidates from the event so we can find the PU tracks.
224  if ( applyDeltaBeta_ ) {
225  // Collect all the PF pile up tracks
227  event.getByToken(pfCand_token, pfCandidates);
228  chargedPFCandidatesInEvent_.clear();
229  chargedPFCandidatesInEvent_.reserve(pfCandidates->size());
230  size_t numPFCandidates = pfCandidates->size();
231  for ( size_t i = 0; i < numPFCandidates; ++i ) {
232  reco::PFCandidatePtr pfCandidate(pfCandidates, i);
233  if ( pfCandidate->charge() != 0 ) {
234  chargedPFCandidatesInEvent_.push_back(pfCandidate);
235  }
236  }
237  // Count all the vertices in the event, to parameterize the DB
238  // correction factor
240  event.getByToken(vertex_token, vertices);
241  size_t nVtxThisEvent = vertices->size();
242  deltaBetaFactorThisEvent_ = deltaBetaFormula_->Eval(nVtxThisEvent);
243  }
244 
245  if ( applyRhoCorrection_ ) {
246  edm::Handle<double> rhoHandle_;
247  event.getByToken(rho_token, rhoHandle_);
248  rhoThisEvent_ = (*rhoHandle_ - rhoUEOffsetCorrection_)*
249  (3.14159)*rhoConeSize_*rhoConeSize_;
250  }
251 }
252 
253 double
255 {
256  if ( verbosity_ ) {
257  std::cout << "<PFRecoTauDiscriminationByIsolation::discriminate (moduleLabel = " << moduleLabel_ <<")>:" << std::endl;
258  std::cout << " tau: Pt = " << pfTau->pt() << ", eta = " << pfTau->eta() << ", phi = " << pfTau->phi() << std::endl;
259  }
260 
261  // collect the objects we are working with (ie tracks, tracks+gammas, etc)
262  isoCharged_.clear();
263  isoCharged_.reserve(pfTau->isolationPFChargedHadrCands().size());
264  isoNeutral_.clear();
265  isoNeutral_.reserve(pfTau->isolationPFGammaCands().size());
266  isoPU_.clear();
267  isoPU_.reserve(chargedPFCandidatesInEvent_.size());
268 
269  // Get the primary vertex associated to this tau
270  reco::VertexRef pv = vertexAssociator_->associatedVertex(*pfTau);
271  // Let the quality cuts know which the vertex to use when applying selections
272  // on dz, etc.
273  if ( verbosity_ ) {
274  if ( pv.isNonnull() ) {
275  std::cout << "pv: x = " << pv->position().x() << ", y = " << pv->position().y() << ", z = " << pv->position().z() << std::endl;
276  } else {
277  std::cout << "pv: N/A" << std::endl;
278  }
279  if ( pfTau->leadPFChargedHadrCand().isNonnull() ) {
280  std::cout << "leadPFChargedHadron:"
281  << " Pt = " << pfTau->leadPFChargedHadrCand()->pt() << ","
282  << " eta = " << pfTau->leadPFChargedHadrCand()->eta() << ","
283  << " phi = " << pfTau->leadPFChargedHadrCand()->phi() << std::endl;
284  } else {
285  std::cout << "leadPFChargedHadron: N/A" << std::endl;
286  }
287  }
288 
289  // CV: isolation is not well defined in case primary vertex or leading charged hadron do not exist
290  if ( !(pv.isNonnull() && pfTau->leadPFChargedHadrCand().isNonnull()) ) return 0.;
291 
292  qcuts_->setPV(pv);
293  qcuts_->setLeadTrack(pfTau->leadPFChargedHadrCand());
294 
295  if ( applyDeltaBeta_ ) {
296  pileupQcutsGeneralQCuts_->setPV(pv);
297  pileupQcutsGeneralQCuts_->setLeadTrack(pfTau->leadPFChargedHadrCand());
298  pileupQcutsPUTrackSelection_->setPV(pv);
299  pileupQcutsPUTrackSelection_->setLeadTrack(pfTau->leadPFChargedHadrCand());
300  }
301 
302  // Load the tracks if they are being used.
303  if ( includeTracks_ ) {
304  BOOST_FOREACH( const reco::PFCandidatePtr& cand, pfTau->isolationPFChargedHadrCands() ) {
305  if ( qcuts_->filterCandRef(cand) ) {
306  isoCharged_.push_back(cand);
307  }
308  }
309  }
310  if ( includeGammas_ ) {
311  BOOST_FOREACH( const reco::PFCandidatePtr& cand, pfTau->isolationPFGammaCands() ) {
312  if ( qcuts_->filterCandRef(cand) ) {
313  isoNeutral_.push_back(cand);
314  }
315  }
316  }
317 
319 
320  // If desired, get PU tracks.
321  if ( applyDeltaBeta_ ) {
322  // First select by inverted the DZ/track weight cuts. True = invert
323  //if ( verbosity_ ) {
324  // std::cout << "Initial PFCands: " << chargedPFCandidatesInEvent_.size() << std::endl;
325  //}
326 
327  std::vector<PFCandidatePtr> allPU =
328  pileupQcutsPUTrackSelection_->filterCandRefs(
329  chargedPFCandidatesInEvent_, true);
330  //if ( verbosity_ ) {
331  // std::cout << "After track cuts: " << allPU.size() << std::endl;
332  //}
333 
334  // Now apply the rest of the cuts, like pt, and TIP, tracker hits, etc
335  std::vector<PFCandidatePtr> cleanPU =
336  pileupQcutsGeneralQCuts_->filterCandRefs(allPU);
337  //if ( verbosity_ ) {
338  // std::cout << "After cleaning cuts: " << cleanPU.size() << std::endl;
339  //}
340 
341  // Only select PU tracks inside the isolation cone.
342  DRFilter deltaBetaFilter(pfTau->p4(), 0, deltaBetaCollectionCone_);
343  BOOST_FOREACH(const reco::PFCandidatePtr& cand, cleanPU) {
344  if ( deltaBetaFilter(cand) ) {
345  isoPU_.push_back(cand);
346  }
347  }
348  //if ( verbosity_ ) {
349  // std::cout << "After cone cuts: " << isoPU.size() << std::endl;
350  //}
351  }
352 
353  // Check if we want a custom iso cone
354  if ( customIsoCone_ >= 0. ) {
355  //std::cout << "<PFRecoTauDiscriminationByIsolation::discriminate (moduleLabel = " << moduleLabel_ <<")>:" << std::endl;
356  //std::cout << " customIsoCone = " << customIsoCone_ << std::endl;
357  DRFilter filter(pfTau->p4(), 0, customIsoCone_);
358  std::vector<PFCandidatePtr> isoCharged_filter;
359  std::vector<PFCandidatePtr> isoNeutral_filter;
360  // Remove all the objects not in our iso cone
361  BOOST_FOREACH( const PFCandidatePtr& isoObject, isoCharged_ ) {
362  if ( filter(isoObject) ) isoCharged_filter.push_back(isoObject);
363  }
364  BOOST_FOREACH( const PFCandidatePtr& isoObject, isoNeutral_ ) {
365  if ( filter(isoObject) ) isoNeutral_filter.push_back(isoObject);
366  }
367  isoCharged_ = isoCharged_filter;
368  isoNeutral_ = isoNeutral_filter;
369  }
370 
371  bool failsOccupancyCut = false;
372  bool failsSumPtCut = false;
373  bool failsRelativeSumPtCut = false;
374 
375 //--- nObjects requirement
376  int neutrals = isoNeutral_.size();
377 
378  if ( applyDeltaBeta_ ) {
379  neutrals -= TMath::Nint(deltaBetaFactorThisEvent_*isoPU_.size());
380  }
381  if ( neutrals < 0 ) {
382  neutrals = 0;
383  }
384 
385  size_t nOccupants = isoCharged_.size() + neutrals;
386 
387  failsOccupancyCut = ( nOccupants > maximumOccupancy_ );
388 
389  double totalPt = 0.0;
390  double puPt = 0.0;
391 //--- Sum PT requirement
392  if ( applySumPtCut_ || applyRelativeSumPtCut_ || storeRawSumPt_ || storeRawPUsumPt_ ) {
393  double chargedPt = 0.0;
394  double neutralPt = 0.0;
395  BOOST_FOREACH ( const PFCandidatePtr& isoObject, isoCharged_ ) {
396  chargedPt += isoObject->pt();
397  }
398  BOOST_FOREACH ( const PFCandidatePtr& isoObject, isoNeutral_ ) {
399  neutralPt += isoObject->pt();
400  }
401  BOOST_FOREACH ( const PFCandidatePtr& isoObject, isoPU_ ) {
402  puPt += isoObject->pt();
403  }
404  if ( verbosity_ ) {
405  std::cout << "chargedPt = " << chargedPt << std::endl;
406  std::cout << "neutralPt = " << neutralPt << std::endl;
407  std::cout << "puPt = " << puPt << " (delta-beta corr. = " << (deltaBetaFactorThisEvent_*puPt) << ")" << std::endl;
408  }
409 
410  if ( applyDeltaBeta_ ) {
411  neutralPt -= deltaBetaFactorThisEvent_*puPt;
412  }
413 
414  if ( applyRhoCorrection_ ) {
415  neutralPt -= rhoThisEvent_;
416  }
417 
418  if ( neutralPt < 0.0 ) {
419  neutralPt = 0.0;
420  }
421 
422  totalPt = chargedPt + neutralPt;
423  if ( verbosity_ ) {
424  std::cout << "totalPt = " << totalPt << " (cut = " << maximumSumPt_ << ")" << std::endl;
425  }
426 
427  failsSumPtCut = (totalPt > maximumSumPt_);
428 
429 //--- Relative Sum PT requirement
430  failsRelativeSumPtCut = (totalPt > ((pfTau->pt() - offsetRelativeSumPt_)*maximumRelativeSumPt_));
431  }
432 
433  bool fails = (applyOccupancyCut_ && failsOccupancyCut) ||
434  (applySumPtCut_ && failsSumPtCut) ||
435  (applyRelativeSumPtCut_ && failsRelativeSumPtCut);
436 
437  // We did error checking in the constructor, so this is safe.
438  if ( storeRawSumPt_ ) {
439  return totalPt;
440  } else if ( storeRawPUsumPt_ ) {
441  if ( applyDeltaBeta_ ) return puPt;
442  else if ( applyRhoCorrection_ ) return rhoThisEvent_;
443  else return 0.;
444  } else if ( storeRawOccupancy_ ) {
445  return nOccupants;
446  } else {
447  return (fails ? 0. : 1.);
448  }
449 }
450 
PFRecoTauDiscriminationByIsolation(const edm::ParameterSet &pset)
T getParameter(std::string const &) const
int i
Definition: DBlmapReader.cc:9
std::auto_ptr< tau::RecoTauQualityCuts > pileupQcutsGeneralQCuts_
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
void beginEvent(const edm::Event &evt, const edm::EventSetup &evtSetup) override
bool exists(std::string const &parameterName) const
checks if a parameter exists
std::vector< PFCandidatePtr > pfCandidates(const PFJet &jet, int particleId, bool sort=true)
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:250
edm::EDGetTokenT< reco::PFCandidateCollection > pfCand_token
std::vector< reco::PFCandidatePtr > chargedPFCandidatesInEvent_
std::pair< edm::ParameterSet, edm::ParameterSet > factorizePUQCuts(const edm::ParameterSet &inputSet)
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger but the state exists so we define the behavior If all triggers are the negative crieriion will lead to accepting the event(this again matches the behavior of"!*"before the partial wildcard feature was incorporated).The per-event"cost"of each negative criterion with multiple relevant triggers is about the same as!*was in the past
double discriminate(const PFTauRef &pfTau) override
std::auto_ptr< tau::RecoTauQualityCuts > qcuts_
std::auto_ptr< tau::RecoTauQualityCuts > pileupQcutsPUTrackSelection_
ParameterSet const & getParameterSet(std::string const &) const
std::auto_ptr< tau::RecoTauVertexAssociator > vertexAssociator_
tuple cout
Definition: gather_cfg.py:121
moduleLabel_(iConfig.getParameter< string >("@module_label"))
edm::EDGetTokenT< reco::VertexCollection > vertex_token