CMS 3D CMS Logo

RecoTauQualityCuts.cc
Go to the documentation of this file.
6 
7 namespace reco::tau {
8 
9 namespace {
10  // Get the KF track if it exists. Otherwise, see if PFCandidate has a GSF track.
11  const reco::TrackBaseRef getTrackRef(const PFCandidate& cand)
12  {
13  if ( cand.trackRef().isNonnull() ) return reco::TrackBaseRef(cand.trackRef());
14  else if ( cand.gsfTrackRef().isNonnull() ) return reco::TrackBaseRef(cand.gsfTrackRef());
15  else return reco::TrackBaseRef();
16  }
17 
18  // Translate GsfTrackRef to TrackBaseRef
19  template <typename T>
20  reco::TrackBaseRef convertRef(const T& ref) {
21  return reco::TrackBaseRef(ref);
22  }
23 }
24 
25 // Quality cut implementations
26 namespace qcuts {
27 
28 bool ptMin(const TrackBaseRef& track, double cut)
29 {
30  LogDebug("TauQCuts") << "<ptMin>: Pt = " << track->pt() << ", cut = " << cut ;
31  return (track->pt() > cut);
32 }
33 
34 bool ptMin_cand(const PFCandidate& cand, double cut)
35 {
36  LogDebug("TauQCuts") << "<ptMin_cand>: Pt = " << cand.pt() << ", cut = " << cut ;
37  return (cand.pt() > cut);
38 }
39 
40 bool etMin_cand(const PFCandidate& cand, double cut)
41 {
42  LogDebug("TauQCuts") << "<etMin_cand>: Et = " << cand.et() << ", cut = " << cut ;
43  return (cand.et() > cut);
44 }
45 
46 bool trkPixelHits(const TrackBaseRef& track, int cut)
47 {
48  // For some reason, the number of hits is signed
49  LogDebug("TauQCuts") << "<trkPixelHits>: #Pxl hits = " << track->hitPattern().numberOfValidPixelHits() << ", cut = " << cut ;
50  return (track->hitPattern().numberOfValidPixelHits() >= cut);
51 }
52 
53 bool trkPixelHits_cand(const PFCandidate& cand, int cut)
54 {
55  // For some reason, the number of hits is signed
56  auto track = getTrackRef(cand);
57  if ( track.isNonnull() ) {
58  LogDebug("TauQCuts") << "<trkPixelHits_cand>: #Pxl hits = " << trkPixelHits(track, cut) << ", cut = " << cut ;
59  return trkPixelHits(track, cut);
60  } else {
61  LogDebug("TauQCuts") << "<trkPixelHits_cand>: #Pxl hits = N/A, cut = " << cut ;
62  return false;
63  }
64 }
65 
67 {
68  LogDebug("TauQCuts") << "<trkTrackerHits>: #Trk hits = " << track->hitPattern().numberOfValidHits() << ", cut = " << cut ;
69  return (track->hitPattern().numberOfValidHits() >= cut);
70 }
71 
72 bool trkTrackerHits_cand(const PFCandidate& cand, int cut)
73 {
74  auto track = getTrackRef(cand);
75  if ( track.isNonnull() ) {
76  LogDebug("TauQCuts") << "<trkTrackerHits>: #Trk hits = " << track->hitPattern().numberOfValidHits() << ", cut = " << cut ;
77  return trkTrackerHits(track, cut);
78  } else {
79  LogDebug("TauQCuts") << "<trkTrackerHits>: #Trk hits = N/A, cut = " << cut ;
80  return false;
81  }
82 }
83 
85 {
86  if ( pv->isNull() ) {
87  edm::LogError("QCutsNoPrimaryVertex") << "Primary vertex Ref in " <<
88  "RecoTauQualityCuts is invalid. - trkTransverseImpactParameter";
89  return false;
90  }
91  LogDebug("TauQCuts") << " track: Pt = " << track->pt() << ", eta = " << track->eta() << ", phi = " << track->phi() ;
92  LogDebug("TauQCuts") << " vertex: x = " << (*pv)->position().x() << ", y = " << (*pv)->position().y() << ", z = " << (*pv)->position().z() ;
93  LogDebug("TauQCuts") << "--> dxy = " << std::fabs(track->dxy((*pv)->position())) << " (cut = " << cut << ")" ;
94  return (std::fabs(track->dxy((*pv)->position())) <= cut);
95 }
96 
98 {
99  auto track = getTrackRef(cand);
100  if ( track.isNonnull() ) {
101  return trkTransverseImpactParameter(track, pv, cut);
102  } else {
103  LogDebug("TauQCuts") << "<trkTransverseImpactParameter_cand>: dXY = N/A, cut = " << cut ;
104  return false;
105  }
106 }
107 
109 {
110  if ( pv->isNull() ) {
111  edm::LogError("QCutsNoPrimaryVertex") << "Primary vertex Ref in " <<
112  "RecoTauQualityCuts is invalid. - trkLongitudinalImpactParameter";
113  return false;
114  }
115  LogDebug("TauQCuts") << " track: Pt = " << track->pt() << ", eta = " << track->eta() << ", phi = " << track->phi() ;
116  LogDebug("TauQCuts") << " vertex: x = " << (*pv)->position().x() << ", y = " << (*pv)->position().y() << ", z = " << (*pv)->position().z() ;
117  LogDebug("TauQCuts") << "--> dz = " << std::fabs(track->dz((*pv)->position())) << " (cut = " << cut << ")" ;
118  return (std::fabs(track->dz((*pv)->position())) <= cut);
119 }
120 
122 {
123  auto track = getTrackRef(cand);
124  if ( track.isNonnull() ) {
125  return trkLongitudinalImpactParameter(track, pv, cut);
126  } else {
127  LogDebug("TauQCuts") << "<trkLongitudinalImpactParameter_cand>: dZ = N/A, cut = " << cut ;
128  return false;
129  }
130 }
131 
134 {
135  if ( leadTrack->isNull()) {
136  edm::LogError("QCutsNoValidLeadTrack") << "Lead track Ref in " <<
137  "RecoTauQualityCuts is invalid. - trkLongitudinalImpactParameterWrtTrack";
138  return false;
139  }
140  return (std::fabs(track->dz((*pv)->position()) - (*leadTrack)->dz((*pv)->position())) <= cut);
141 }
142 
144 {
145  auto track = getTrackRef(cand);
146  if ( track.isNonnull() ) return trkLongitudinalImpactParameterWrtTrack(track, leadTrack, pv, cut);
147  else return false;
148 }
149 
151 {
152  if ( pv->isNull() ) {
153  edm::LogError("QCutsNoPrimaryVertex") << "Primary vertex Ref in " <<
154  "RecoTauQualityCuts is invalid. - minTrackVertexWeight";
155  return false;
156  }
157  LogDebug("TauQCuts") << " track: Pt = " << track->pt() << ", eta = " << track->eta() << ", phi = " << track->phi() ;
158  LogDebug("TauQCuts") << " vertex: x = " << (*pv)->position().x() << ", y = " << (*pv)->position().y() << ", z = " << (*pv)->position().z() ;
159  LogDebug("TauQCuts") << "--> trackWeight = " << (*pv)->trackWeight(track) << " (cut = " << cut << ")" ;
160  return ((*pv)->trackWeight(track) >= cut);
161 }
162 
163 bool minTrackVertexWeight_cand(const PFCandidate& cand, const reco::VertexRef* pv, double cut)
164 {
165  auto track = getTrackRef(cand);
166  if ( track.isNonnull() ) {
167  return minTrackVertexWeight(track, pv, cut);
168  } else {
169  LogDebug("TauQCuts") << "<minTrackVertexWeight_cand>: weight = N/A, cut = " << cut ;
170  return false;
171  }
172 }
173 
174 bool trkChi2(const TrackBaseRef& track, double cut)
175 {
176  LogDebug("TauQCuts") << "<trkChi2>: chi^2 = " << track->normalizedChi2() << ", cut = " << cut ;
177  return (track->normalizedChi2() <= cut);
178 }
179 
180 bool trkChi2_cand(const PFCandidate& cand, double cut)
181 {
182  auto track = getTrackRef(cand);
183  if ( track.isNonnull() ) {
184  LogDebug("TauQCuts") << "<trkChi2_cand>: chi^2 = " << track->normalizedChi2() << ", cut = " << cut ;
185  return trkChi2(track, cut);
186  } else {
187  LogDebug("TauQCuts") << "<trkChi2_cand>: chi^2 = N/A, cut = " << cut ;
188  return false;
189  }
190 }
191 
192 // And a set of qcuts
194 {
195  for(auto const& func : cuts ) {
196  if ( !func(track) ) return false;
197  }
198  return true;
199 }
200 
202 {
203  for(auto const& func : cuts ) {
204  if ( !func(cand) ) return false;
205  }
206  return true;
207 }
208 
209 // Get the set of Q cuts for a given type (i.e. gamma)
211 {
212  // Find the cuts that for this particle type
213  RecoTauQualityCuts::CandQCutFuncMap::const_iterator cuts = funcMap.find(cand.particleId());
214  // Return false if we dont' know how to deal with this particle type
215  if ( cuts == funcMap.end() ) return false;
216  return AND_cand(cand, cuts->second); // Otherwise AND all the cuts
217 }
218 
219 } // end qcuts implementation namespace
220 
222 {
223  // Setup all of our predicates
224  CandQCutFuncCollection chargedHadronCuts;
225  CandQCutFuncCollection gammaCuts;
226  CandQCutFuncCollection neutralHadronCuts;
227 
228  // Make sure there are no extra passed options
229  std::set<std::string> passedOptionSet;
230  std::vector<std::string> passedOptions = qcuts.getParameterNames();
231 
232  for(auto const& option : passedOptions) {
233  passedOptionSet.insert(option);
234  }
235 
236  unsigned int nCuts = 0;
237  auto getDouble = [&qcuts, &passedOptionSet, &nCuts](const std::string& name) {
238  if(qcuts.exists(name)) {
239  ++nCuts;
240  passedOptionSet.erase(name);
241  return qcuts.getParameter<double>(name);
242  }
243  return -1.0;
244  };
245  auto getUint = [&qcuts, &passedOptionSet, &nCuts](const std::string& name) -> unsigned int {
246  if(qcuts.exists(name)) {
247  ++nCuts;
248  passedOptionSet.erase(name);
249  return qcuts.getParameter<unsigned int>(name);
250  }
251  return 0;
252  };
253 
254  // Build all the QCuts for tracks
255  minTrackPt_ = getDouble("minTrackPt");
256  maxTrackChi2_ = getDouble("maxTrackChi2");
257  minTrackPixelHits_ = getUint("minTrackPixelHits");
258  minTrackHits_ = getUint("minTrackHits");
259  maxTransverseImpactParameter_ = getDouble("maxTransverseImpactParameter");
260  maxDeltaZ_ = getDouble("maxDeltaZ");
261  maxDeltaZToLeadTrack_ = getDouble("maxDeltaZToLeadTrack");
262  // Require tracks to contribute a minimum weight to the associated vertex.
263  minTrackVertexWeight_ = getDouble("minTrackVertexWeight");
264 
265  // Use bit-wise & to avoid conditional code
266  checkHitPattern_ = (minTrackHits_ > 0) || (minTrackPixelHits_ > 0);
267  checkPV_ = (maxTransverseImpactParameter_ >= 0) ||
268  (maxDeltaZ_ >= 0) ||
269  (maxDeltaZToLeadTrack_ >= 0) ||
270  (minTrackVertexWeight_ >= 0);
271 
272  // Build the QCuts for gammas
273  minGammaEt_ = getDouble("minGammaEt");
274 
275  // Build QCuts for netural hadrons
276  minNeutralHadronEt_ = getDouble("minNeutralHadronEt");
277 
278  // Check if there are any remaining unparsed QCuts
279  if ( !passedOptionSet.empty() ) {
280  std::string unParsedOptions;
281  bool thereIsABadParameter = false;
282  for(auto const& option : passedOptionSet ) {
283  // Workaround for HLT - TODO FIXME
284  if ( option == "useTracksInsteadOfPFHadrons" ) {
285  // Crash if true - no one should have this option enabled.
286  if ( qcuts.getParameter<bool>("useTracksInsteadOfPFHadrons") ) {
287  throw cms::Exception("DontUseTracksInQcuts")
288  << "The obsolete exception useTracksInsteadOfPFHadrons "
289  << "is set to true in the quality cut config." << std::endl;
290  }
291  continue;
292  }
293 
294  // If we get to this point, there is a real unknown parameter
295  thereIsABadParameter = true;
296 
297  unParsedOptions += option;
298  unParsedOptions += "\n";
299  }
300  if ( thereIsABadParameter ) {
301  throw cms::Exception("BadQualityCutConfig")
302  << " The PSet passed to the RecoTauQualityCuts class had"
303  << " the following unrecognized options: " << std::endl
304  << unParsedOptions;
305  }
306  }
307 
308  // Make sure there are at least some quality cuts
309  if ( !nCuts ) {
310  throw cms::Exception("BadQualityCutConfig")
311  << " No options were passed to the quality cut class!" << std::endl;
312  }
313 }
314 
315 std::pair<edm::ParameterSet, edm::ParameterSet> factorizePUQCuts(const edm::ParameterSet& input)
316 {
317  edm::ParameterSet puCuts;
318  edm::ParameterSet nonPUCuts;
319 
320  std::vector<std::string> inputNames = input.getParameterNames();
321  for(auto const& cut : inputNames ) {
322  if ( cut == "minTrackVertexWeight" ||
323  cut == "maxDeltaZ" ||
324  cut == "maxDeltaZToLeadTrack" ) {
325  puCuts.copyFrom(input, cut);
326  } else {
327  nonPUCuts.copyFrom(input, cut);
328  }
329  }
330  return std::make_pair(puCuts, nonPUCuts);
331 }
332 
334 {
335  return filterTrack_(track);
336 }
337 
339 {
340  return filterTrack_(track);
341 }
342 
343 template <typename T>
344 bool RecoTauQualityCuts::filterTrack_(const T& trackRef) const
345 {
346  const Track *track = trackRef.get();
347  if(minTrackPt_ >= 0 && !(track->pt() > minTrackPt_)) return false;
348  if(maxTrackChi2_ >= 0 && !(track->normalizedChi2() <= maxTrackChi2_)) return false;
349  if(checkHitPattern_) {
350  const reco::HitPattern &hitPattern = track->hitPattern();
351  if(minTrackPixelHits_ > 0 && !(hitPattern.numberOfValidPixelHits() >= minTrackPixelHits_)) return false;
352  if(minTrackHits_ > 0 && !(hitPattern.numberOfValidHits() >= minTrackHits_)) return false;
353  }
354  if(checkPV_ && pv_.isNull()) {
355  edm::LogError("QCutsNoPrimaryVertex") << "Primary vertex Ref in " <<
356  "RecoTauQualityCuts is invalid. - filterTrack";
357  return false;
358  }
359 
360  if(maxTransverseImpactParameter_ >= 0 &&
361  !(std::fabs(track->dxy(pv_->position())) <= maxTransverseImpactParameter_))
362  return false;
363  if(maxDeltaZ_ >= 0 && !(std::fabs(track->dz(pv_->position())) <= maxDeltaZ_)) return false;
364  if(maxDeltaZToLeadTrack_ >= 0) {
365  if ( leadTrack_.isNull()) {
366  edm::LogError("QCutsNoValidLeadTrack") << "Lead track Ref in " <<
367  "RecoTauQualityCuts is invalid. - filterTrack";
368  return false;
369  }
370 
371  if(!(std::fabs(track->dz(pv_->position()) - leadTrack_->dz(pv_->position())) <= maxDeltaZToLeadTrack_))
372  return false;
373  }
374  if(minTrackVertexWeight_ > -1.0 && !(pv_->trackWeight(convertRef(trackRef)) >= minTrackVertexWeight_)) return false;
375 
376  return true;
377 }
378 
380  if(minGammaEt_ >= 0 && !(cand.et() > minGammaEt_)) return false;
381  return true;
382 }
383 
385  if(minNeutralHadronEt_ >= 0 && !(cand.et() > minNeutralHadronEt_)) return false;
386  return true;
387 }
388 
390  switch(cand.particleId()) {
391  case PFCandidate::gamma:
392  return filterGammaCand(cand);
393  case PFCandidate::h0:
394  return filterNeutralHadronCand(cand);
395  // We use the same qcuts for muons/electrons and charged hadrons.
396  case PFCandidate::h:
397  case PFCandidate::e:
398  case PFCandidate::mu:
399  // no cuts ATM (track cuts applied in filterCand)
400  return true;
401  // Return false if we dont' know how to deal with this particle type
402  default:
403  return false;
404  };
405  return false;
406 }
407 
409 {
410  auto trackRef = cand.trackRef();
411  bool result = true;
412  if(trackRef.isNonnull()) {
413  result = filterTrack_(trackRef);
414  }
415  else {
416  auto gsfTrackRef = cand.gsfTrackRef();
417  if(gsfTrackRef.isNonnull()) {
418  result = filterTrack_(gsfTrackRef);
419  }
420  }
421  if(result)
422  result = filterCandByType(cand);
423  return result;
424 }
425 
427 {
428  leadTrack_ = reco::TrackBaseRef(leadTrack);
429 }
430 
432 {
433  leadTrack_ = getTrackRef(leadCand);
434 }
435 
437 {
438  if ( leadCand.isNonnull() ) {
439  leadTrack_ = getTrackRef(*leadCand);
440  } else {
441  // Set null
442  leadTrack_ = reco::TrackBaseRef();
443  }
444 }
445 
446 } // end namespace reco::tau
#define LogDebug(id)
T getParameter(std::string const &) const
bool filterCandByType(const reco::PFCandidate &cand) const
bool trkLongitudinalImpactParameter_cand(const PFCandidate &cand, const reco::VertexRef *pv, double cut)
bool minTrackVertexWeight(const TrackBaseRef &track, const reco::VertexRef *pv, double cut)
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:253
bool trkTransverseImpactParameter_cand(const PFCandidate &cand, const reco::VertexRef *pv, double cut)
RecoTauQualityCuts(const edm::ParameterSet &qcuts)
double normalizedChi2() const
chi-squared divided by n.d.o.f. (or chi-squared * 1e6 if n.d.o.f. is zero)
Definition: TrackBase.h:594
bool minTrackVertexWeight_cand(const PFCandidate &cand, const reco::VertexRef *pv, double cut)
int numberOfValidHits() const
Definition: HitPattern.h:888
bool exists(std::string const &parameterName) const
checks if a parameter exists
bool etMin_cand(const PFCandidate &cand, double cut)
double phi() const
azimuthal angle of momentum vector
Definition: TrackBase.h:678
double pt() const final
transverse momentum
bool trkPixelHits(const TrackBaseRef &track, int cut)
bool filterTrack_(const T &trackRef) const
bool filterNeutralHadronCand(const reco::PFCandidate &cand) const
bool trkTransverseImpactParameter(const TrackBaseRef &track, const reco::VertexRef *pv, double cut)
static std::string const input
Definition: EdmProvDump.cc:45
std::vector< CandQCutFunc > CandQCutFuncCollection
reco::TrackRef trackRef() const
Definition: PFCandidate.cc:442
bool filterGammaCand(const reco::PFCandidate &cand) const
void copyFrom(ParameterSet const &from, std::string const &name)
double eta() const
pseudorapidity of momentum vector
Definition: TrackBase.h:684
bool trkLongitudinalImpactParameterWrtTrack_cand(const PFCandidate &cand, const reco::TrackBaseRef *leadTrack, const reco::VertexRef *pv, double cut)
edm::RefToBase< reco::Track > TrackBaseRef
persistent reference to a Track, using views
Definition: TrackFwd.h:32
double et() const final
transverse energy
std::map< PFCandidate::ParticleType, CandQCutFuncCollection > CandQCutFuncMap
double pt() const
track transverse momentum
Definition: TrackBase.h:654
def pv(vc)
Definition: MetAnalyzer.py:7
std::pair< edm::ParameterSet, edm::ParameterSet > factorizePUQCuts(const edm::ParameterSet &inputSet)
std::vector< TrackQCutFunc > TrackQCutFuncCollection
std::vector< std::string > getParameterNames() const
bool ptMin(const TrackBaseRef &track, double cut)
bool isNull() const
Checks for null.
Definition: Ref.h:250
bool trkTrackerHits(const TrackBaseRef &track, int cut)
double dz() const
dz parameter (= dsz/cos(lambda)). This is the track z0 w.r.t (0,0,0) only if the refPoint is close to...
Definition: TrackBase.h:642
bool trkTrackerHits_cand(const PFCandidate &cand, int cut)
bool mapAndCutByType(const PFCandidate &cand, const RecoTauQualityCuts::CandQCutFuncMap &funcMap)
const HitPattern & hitPattern() const
Access the hit pattern, indicating in which Tracker layers the track has hits.
Definition: TrackBase.h:479
bool ptMin_cand(const PFCandidate &cand, double cut)
bool trkChi2_cand(const PFCandidate &cand, double cut)
bool trkChi2(const TrackBaseRef &track, double cut)
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:40
bool AND(const TrackBaseRef &track, const RecoTauQualityCuts::TrackQCutFuncCollection &cuts)
bool trkLongitudinalImpactParameter(const TrackBaseRef &track, const reco::VertexRef *pv, double cut)
reco::GsfTrackRef gsfTrackRef() const
Definition: PFCandidate.cc:480
bool trkPixelHits_cand(const PFCandidate &cand, int cut)
int numberOfValidPixelHits() const
Definition: HitPattern.h:908
void setLeadTrack(const reco::TrackRef &leadTrack) const
Update the leading track.
bool trkLongitudinalImpactParameterWrtTrack(const TrackBaseRef &track, const reco::TrackBaseRef *leadTrack, const reco::VertexRef *pv, double cut)
DZ cut, with respect to the current lead rack.
bool filterCand(const reco::PFCandidate &cand) const
Filter a single PFCandidate.
virtual ParticleType particleId() const
Definition: PFCandidate.h:374
double dxy() const
dxy parameter. (This is the transverse impact parameter w.r.t. to (0,0,0) ONLY if refPoint is close t...
Definition: TrackBase.h:624
long double T
bool AND_cand(const PFCandidate &cand, const RecoTauQualityCuts::CandQCutFuncCollection &cuts)
bool filterTrack(const reco::TrackBaseRef &track) const
Filter a single Track.