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 
49  storeRawOccupancy_ = pset.exists("storeRawOccupancy") ?
50  pset.getParameter<bool>("storeRawOccupancy") : false;
51  storeRawSumPt_ = pset.exists("storeRawSumPt") ?
52  pset.getParameter<bool>("storeRawSumPt") : false;
53  storeRawPUsumPt_ = pset.exists("storeRawPUsumPt") ?
54  pset.getParameter<bool>("storeRawPUsumPt") : false;
55 
56  // Sanity check on requested options. We can't apply cuts and store the
57  // raw output at the same time
58  if ( applySumPtCut_ || applyOccupancyCut_ || applyRelativeSumPtCut_ ) {
59  if ( storeRawSumPt_ || storeRawOccupancy_ || storeRawPUsumPt_ ) {
60  throw cms::Exception("BadIsoConfig")
61  << "A 'store raw' and a 'apply cut' option have been set to true "
62  << "simultaneously. These options are mutually exclusive.";
63  }
64  }
65 
66  // Can only store one type
67  int numStoreOptions = 0;
68  if ( storeRawSumPt_ ) ++numStoreOptions;
69  if ( storeRawOccupancy_ ) ++numStoreOptions;
70  if ( storeRawPUsumPt_ ) ++numStoreOptions;
71  if ( numStoreOptions > 1 ) {
72  throw cms::Exception("BadIsoConfig")
73  << "Both 'store sum pt' and 'store occupancy' options are set."
74  << " These options are mutually exclusive.";
75  }
76 
77  if ( pset.exists("customOuterCone") ) {
78  customIsoCone_ = pset.getParameter<double>("customOuterCone");
79  } else {
80  customIsoCone_ = -1;
81  }
82 
83  // Get the quality cuts specific to the isolation region
84  edm::ParameterSet isolationQCuts = qualityCutsPSet_.getParameterSet(
85  "isolationQualityCuts");
86 
87  qcuts_.reset(new tau::RecoTauQualityCuts(isolationQCuts));
88 
89  vertexAssociator_.reset(
90  new tau::RecoTauVertexAssociator(qualityCutsPSet_,consumesCollector()));
91 
92  applyDeltaBeta_ = pset.exists("applyDeltaBetaCorrection") ?
93  pset.getParameter<bool>("applyDeltaBetaCorrection") : false;
94 
95  if ( applyDeltaBeta_ ) {
96  // Factorize the isolation QCuts into those that are used to
97  // select PU and those that are not.
98  std::pair<edm::ParameterSet, edm::ParameterSet> puFactorizedIsoQCuts =
99  reco::tau::factorizePUQCuts(isolationQCuts);
100 
101  // Determine the pt threshold for the PU tracks
102  // First check if the user specifies explicitly the cut.
103  if ( pset.exists("deltaBetaPUTrackPtCutOverride") ) {
104  puFactorizedIsoQCuts.second.addParameter<double>(
105  "minTrackPt",
106  pset.getParameter<double>("deltaBetaPUTrackPtCutOverride"));
107  } else {
108  // Secondly take it from the minGammaEt
109  puFactorizedIsoQCuts.second.addParameter<double>(
110  "minTrackPt",
111  isolationQCuts.getParameter<double>("minGammaEt"));
112  }
113 
114  pileupQcutsPUTrackSelection_.reset(new tau::RecoTauQualityCuts(
115  puFactorizedIsoQCuts.first));
116 
117  pileupQcutsGeneralQCuts_.reset(new tau::RecoTauQualityCuts(
118  puFactorizedIsoQCuts.second));
119 
120  pfCandSrc_ = pset.getParameter<edm::InputTag>("particleFlowSrc");
121  pfCand_token=consumes<reco::PFCandidateCollection>(pfCandSrc_);
122  vertexSrc_ = pset.getParameter<edm::InputTag>("vertexSrc");
123  vertex_token=consumes<reco::VertexCollection>(vertexSrc_);
124  deltaBetaCollectionCone_ = pset.getParameter<double>(
125  "isoConeSizeForDeltaBeta");
126  std::string deltaBetaFactorFormula =
127  pset.getParameter<string>("deltaBetaFactor");
128  deltaBetaFormula_.reset(
129  new TFormula("DB_corr", deltaBetaFactorFormula.c_str()));
130  }
131 
132  applyRhoCorrection_ = pset.exists("applyRhoCorrection") ?
133  pset.getParameter<bool>("applyRhoCorrection") : false;
134  if ( applyRhoCorrection_ ) {
135  rhoProducer_ = pset.getParameter<edm::InputTag>("rhoProducer");
136  rho_token=consumes<double>(rhoProducer_);
137  rhoConeSize_ = pset.getParameter<double>("rhoConeSize");
138  rhoUEOffsetCorrection_ =
139  pset.getParameter<double>("rhoUEOffsetCorrection");
140  }
141 
142  verbosity_ = ( pset.exists("verbosity") ) ?
143  pset.getParameter<int>("verbosity") : 0;
144  }
145 
147 
148  void beginEvent(const edm::Event& evt, const edm::EventSetup& evtSetup) override;
149  double discriminate(const PFTauRef& pfTau) override;
150 
151  private:
153 
155  std::auto_ptr<tau::RecoTauQualityCuts> qcuts_;
156 
157  // Inverted QCut which selects tracks with bad DZ/trackWeight
158  std::auto_ptr<tau::RecoTauQualityCuts> pileupQcutsPUTrackSelection_;
159  std::auto_ptr<tau::RecoTauQualityCuts> pileupQcutsGeneralQCuts_;
160 
161  std::auto_ptr<tau::RecoTauVertexAssociator> vertexAssociator_;
162 
172 
173  // Options to store the raw value in the discriminator instead of boolean pass/fail flag
177 
178  /* **********************************************************************
179  **** Pileup Subtraction Parameters ***********************************
180  **********************************************************************/
181 
182  // Delta Beta correction
186  // Keep track of how many vertices are in the event
189  std::vector<reco::PFCandidatePtr> chargedPFCandidatesInEvent_;
190  std::vector<PFCandidatePtr> isoCharged_;
191  std::vector<PFCandidatePtr> isoNeutral_;
192  std::vector<PFCandidatePtr> isoPU_;
193  // Size of cone used to collect PU tracks
195  std::auto_ptr<TFormula> deltaBetaFormula_;
197 
198  // Rho correction
202  double rhoConeSize_;
206 
207  // Flag to enable/disable debug output
209 };
210 
212 {
213  // NB: The use of the PV in this context is necessitated by its use in
214  // applying quality cuts to the different objects in the isolation cone
215  // The vertex associator contains the logic to select the appropriate vertex
216  // We need to pass it the event so it can load the vertices.
217  vertexAssociator_->setEvent(event);
218 
219  // If we are applying the delta beta correction, we need to get the PF
220  // candidates from the event so we can find the PU tracks.
221  if ( applyDeltaBeta_ ) {
222  // Collect all the PF pile up tracks
224  event.getByToken(pfCand_token, pfCandidates);
225  chargedPFCandidatesInEvent_.clear();
226  chargedPFCandidatesInEvent_.reserve(pfCandidates->size());
227  size_t numPFCandidates = pfCandidates->size();
228  for ( size_t i = 0; i < numPFCandidates; ++i ) {
229  reco::PFCandidatePtr pfCandidate(pfCandidates, i);
230  if ( pfCandidate->charge() != 0 ) {
231  chargedPFCandidatesInEvent_.push_back(pfCandidate);
232  }
233  }
234  // Count all the vertices in the event, to parameterize the DB
235  // correction factor
237  event.getByToken(vertex_token, vertices);
238  size_t nVtxThisEvent = vertices->size();
239  deltaBetaFactorThisEvent_ = deltaBetaFormula_->Eval(nVtxThisEvent);
240  }
241 
242  if ( applyRhoCorrection_ ) {
243  edm::Handle<double> rhoHandle_;
244  event.getByToken(rho_token, rhoHandle_);
245  rhoThisEvent_ = (*rhoHandle_ - rhoUEOffsetCorrection_)*
246  (3.14159)*rhoConeSize_*rhoConeSize_;
247  }
248 }
249 
250 double
252 {
253  if ( verbosity_ ) {
254  std::cout << "<PFRecoTauDiscriminationByIsolation::discriminate (moduleLabel = " << moduleLabel_ <<")>:" << std::endl;
255  std::cout << " tau: Pt = " << pfTau->pt() << ", eta = " << pfTau->eta() << ", phi = " << pfTau->phi() << std::endl;
256  }
257 
258  // collect the objects we are working with (ie tracks, tracks+gammas, etc)
259  isoCharged_.clear();
260  isoCharged_.reserve(pfTau->isolationPFChargedHadrCands().size());
261  isoNeutral_.clear();
262  isoNeutral_.reserve(pfTau->isolationPFGammaCands().size());
263  isoPU_.clear();
264  isoPU_.reserve(chargedPFCandidatesInEvent_.size());
265 
266  // Get the primary vertex associated to this tau
267  reco::VertexRef pv = vertexAssociator_->associatedVertex(*pfTau);
268  // Let the quality cuts know which the vertex to use when applying selections
269  // on dz, etc.
270  if ( verbosity_ ) {
271  if ( pv.isNonnull() ) {
272  std::cout << "pv: x = " << pv->position().x() << ", y = " << pv->position().y() << ", z = " << pv->position().z() << std::endl;
273  } else {
274  std::cout << "pv: N/A" << std::endl;
275  }
276  if ( pfTau->leadPFChargedHadrCand().isNonnull() ) {
277  std::cout << "leadPFChargedHadron:"
278  << " Pt = " << pfTau->leadPFChargedHadrCand()->pt() << ","
279  << " eta = " << pfTau->leadPFChargedHadrCand()->eta() << ","
280  << " phi = " << pfTau->leadPFChargedHadrCand()->phi() << std::endl;
281  } else {
282  std::cout << "leadPFChargedHadron: N/A" << std::endl;
283  }
284  }
285 
286  // CV: isolation is not well defined in case primary vertex or leading charged hadron do not exist
287  if ( !(pv.isNonnull() && pfTau->leadPFChargedHadrCand().isNonnull()) ) return 0.;
288 
289  qcuts_->setPV(pv);
290  qcuts_->setLeadTrack(pfTau->leadPFChargedHadrCand());
291 
292  if ( applyDeltaBeta_ ) {
293  pileupQcutsGeneralQCuts_->setPV(pv);
294  pileupQcutsGeneralQCuts_->setLeadTrack(pfTau->leadPFChargedHadrCand());
295  pileupQcutsPUTrackSelection_->setPV(pv);
296  pileupQcutsPUTrackSelection_->setLeadTrack(pfTau->leadPFChargedHadrCand());
297  }
298 
299  // Load the tracks if they are being used.
300  if ( includeTracks_ ) {
301  BOOST_FOREACH( const reco::PFCandidatePtr& cand, pfTau->isolationPFChargedHadrCands() ) {
302  if ( qcuts_->filterCandRef(cand) ) {
303  isoCharged_.push_back(cand);
304  }
305  }
306  }
307  if ( includeGammas_ ) {
308  BOOST_FOREACH( const reco::PFCandidatePtr& cand, pfTau->isolationPFGammaCands() ) {
309  if ( qcuts_->filterCandRef(cand) ) {
310  isoNeutral_.push_back(cand);
311  }
312  }
313  }
314 
316 
317  // If desired, get PU tracks.
318  if ( applyDeltaBeta_ ) {
319  // First select by inverted the DZ/track weight cuts. True = invert
320  //if ( verbosity_ ) {
321  // std::cout << "Initial PFCands: " << chargedPFCandidatesInEvent_.size() << std::endl;
322  //}
323 
324  std::vector<PFCandidatePtr> allPU =
325  pileupQcutsPUTrackSelection_->filterCandRefs(
326  chargedPFCandidatesInEvent_, true);
327  //if ( verbosity_ ) {
328  // std::cout << "After track cuts: " << allPU.size() << std::endl;
329  //}
330 
331  // Now apply the rest of the cuts, like pt, and TIP, tracker hits, etc
332  std::vector<PFCandidatePtr> cleanPU =
333  pileupQcutsGeneralQCuts_->filterCandRefs(allPU);
334  //if ( verbosity_ ) {
335  // std::cout << "After cleaning cuts: " << cleanPU.size() << std::endl;
336  //}
337 
338  // Only select PU tracks inside the isolation cone.
339  DRFilter deltaBetaFilter(pfTau->p4(), 0, deltaBetaCollectionCone_);
340  BOOST_FOREACH(const reco::PFCandidatePtr& cand, cleanPU) {
341  if ( deltaBetaFilter(cand) ) {
342  isoPU_.push_back(cand);
343  }
344  }
345  //if ( verbosity_ ) {
346  // std::cout << "After cone cuts: " << isoPU.size() << std::endl;
347  //}
348  }
349 
350  // Check if we want a custom iso cone
351  if ( customIsoCone_ >= 0. ) {
352  //std::cout << "<PFRecoTauDiscriminationByIsolation::discriminate (moduleLabel = " << moduleLabel_ <<")>:" << std::endl;
353  //std::cout << " customIsoCone = " << customIsoCone_ << std::endl;
354  DRFilter filter(pfTau->p4(), 0, customIsoCone_);
355  std::vector<PFCandidatePtr> isoCharged_filter;
356  std::vector<PFCandidatePtr> isoNeutral_filter;
357  // Remove all the objects not in our iso cone
358  BOOST_FOREACH( const PFCandidatePtr& isoObject, isoCharged_ ) {
359  if ( filter(isoObject) ) isoCharged_filter.push_back(isoObject);
360  }
361  BOOST_FOREACH( const PFCandidatePtr& isoObject, isoNeutral_ ) {
362  if ( filter(isoObject) ) isoNeutral_filter.push_back(isoObject);
363  }
364  isoCharged_ = isoCharged_filter;
365  isoNeutral_ = isoNeutral_filter;
366  }
367 
368  bool failsOccupancyCut = false;
369  bool failsSumPtCut = false;
370  bool failsRelativeSumPtCut = false;
371 
372 //--- nObjects requirement
373  int neutrals = isoNeutral_.size();
374 
375  if ( applyDeltaBeta_ ) {
376  neutrals -= TMath::Nint(deltaBetaFactorThisEvent_*isoPU_.size());
377  }
378  if ( neutrals < 0 ) {
379  neutrals = 0;
380  }
381 
382  size_t nOccupants = isoCharged_.size() + neutrals;
383 
384  failsOccupancyCut = ( nOccupants > maximumOccupancy_ );
385 
386  double totalPt = 0.0;
387  double puPt = 0.0;
388 //--- Sum PT requirement
389  if ( applySumPtCut_ || applyRelativeSumPtCut_ || storeRawSumPt_ || storeRawPUsumPt_ ) {
390  double chargedPt = 0.0;
391  double neutralPt = 0.0;
392  BOOST_FOREACH ( const PFCandidatePtr& isoObject, isoCharged_ ) {
393  chargedPt += isoObject->pt();
394  }
395  BOOST_FOREACH ( const PFCandidatePtr& isoObject, isoNeutral_ ) {
396  neutralPt += isoObject->pt();
397  }
398  BOOST_FOREACH ( const PFCandidatePtr& isoObject, isoPU_ ) {
399  puPt += isoObject->pt();
400  }
401  if ( verbosity_ ) {
402  std::cout << "chargedPt = " << chargedPt << std::endl;
403  std::cout << "neutralPt = " << neutralPt << std::endl;
404  std::cout << "puPt = " << puPt << " (delta-beta corr. = " << (deltaBetaFactorThisEvent_*puPt) << ")" << std::endl;
405  }
406 
407  if ( applyDeltaBeta_ ) {
408  neutralPt -= deltaBetaFactorThisEvent_*puPt;
409  }
410 
411  if ( applyRhoCorrection_ ) {
412  neutralPt -= rhoThisEvent_;
413  }
414 
415  if ( neutralPt < 0.0 ) {
416  neutralPt = 0.0;
417  }
418 
419  totalPt = chargedPt + neutralPt;
420  if ( verbosity_ ) {
421  std::cout << "totalPt = " << totalPt << " (cut = " << maximumSumPt_ << ")" << std::endl;
422  }
423 
424  failsSumPtCut = (totalPt > maximumSumPt_);
425 
426 //--- Relative Sum PT requirement
427  failsRelativeSumPtCut = (totalPt > (pfTau->pt()*maximumRelativeSumPt_));
428  }
429 
430  bool fails = (applyOccupancyCut_ && failsOccupancyCut) ||
431  (applySumPtCut_ && failsSumPtCut) ||
432  (applyRelativeSumPtCut_ && failsRelativeSumPtCut);
433 
434  // We did error checking in the constructor, so this is safe.
435  if ( storeRawSumPt_ ) {
436  return totalPt;
437  } else if ( storeRawPUsumPt_ ) {
438  if ( applyDeltaBeta_ ) return puPt;
439  else if ( applyRhoCorrection_ ) return rhoThisEvent_;
440  else return 0.;
441  } else if ( storeRawOccupancy_ ) {
442  return nOccupants;
443  } else {
444  return (fails ? 0. : 1.);
445  }
446 }
447 
PFRecoTauDiscriminationByIsolation(const edm::ParameterSet &pset)
T getParameter(std::string const &) const
int i
Definition: DBlmapReader.cc:9
std::auto_ptr< tau::RecoTauQualityCuts > pileupQcutsGeneralQCuts_
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_
DEFINE_FWK_MODULE(CosmicTrackingParticleSelector)
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