CMS 3D CMS Logo

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