CMS 3D CMS Logo

RecoTauQualityCuts.cc
Go to the documentation of this file.
2 
7 
8 namespace reco::tau {
9 
10  namespace {
11  const reco::Track* getTrack(const Candidate& cand) {
12  const PFCandidate* pfCandPtr = dynamic_cast<const PFCandidate*>(&cand);
13  if (pfCandPtr) {
14  // Get the KF track if it exists. Otherwise, see if PFCandidate has a GSF track.
15  if (pfCandPtr->trackRef().isNonnull())
16  return pfCandPtr->trackRef().get();
17  else if (pfCandPtr->gsfTrackRef().isNonnull())
18  return pfCandPtr->gsfTrackRef().get();
19  else
20  return nullptr;
21  }
22 
23  const pat::PackedCandidate* packedCand = dynamic_cast<const pat::PackedCandidate*>(&cand);
24  if (packedCand && packedCand->hasTrackDetails())
25  return &packedCand->pseudoTrack();
26 
27  return nullptr;
28  }
29 
30  const reco::TrackRef getTrackRef(const Candidate& cand) {
31  const PFCandidate* pfCandPtr = dynamic_cast<const PFCandidate*>(&cand);
32  if (pfCandPtr)
33  return pfCandPtr->trackRef();
34 
35  return reco::TrackRef();
36  }
37 
38  const reco::TrackBaseRef getGsfTrackRef(const Candidate& cand) {
39  const PFCandidate* pfCandPtr = dynamic_cast<const PFCandidate*>(&cand);
40  if (pfCandPtr) {
41  return reco::TrackBaseRef(pfCandPtr->gsfTrackRef());
42  }
43  return reco::TrackBaseRef();
44  }
45 
46  // Translate GsfTrackRef to TrackBaseRef
47  template <typename T>
48  reco::TrackBaseRef convertRef(const T& ref) {
49  return reco::TrackBaseRef(ref);
50  }
51  } // namespace
52 
53  // Quality cut implementations
54  namespace qcuts {
56  if (pv->isNull()) {
57  edm::LogError("QCutsNoPrimaryVertex") << "Primary vertex Ref in "
58  << "RecoTauQualityCuts is invalid. - minPackedCandVertexWeight";
59  return false;
60  }
61  //there is some low granular information on track weight in the vertex available with packed cands
62  double weight = -9.9;
63  if (pCand.vertexRef().isNonnull() && pCand.vertexRef().key() == pv->key()) {
64  int quality = pCand.pvAssociationQuality();
66  weight = 0.6; //0.6 as proxy for weight above 0.5
68  weight = 0.1; //0.6 as proxy for weight below 0.5
69  }
70  LogDebug("TauQCuts") << " packedCand: Pt = " << pCand.pt() << ", eta = " << pCand.eta()
71  << ", phi = " << pCand.phi();
72  LogDebug("TauQCuts") << " vertex: x = " << (*pv)->position().x() << ", y = " << (*pv)->position().y()
73  << ", z = " << (*pv)->position().z();
74  LogDebug("TauQCuts") << "--> trackWeight from packedCand = " << weight << " (cut = " << cut << ")";
75  return (weight >= cut);
76  }
77  } // namespace qcuts
78 
80  // Setup all of our predicates
81  CandQCutFuncCollection chargedHadronCuts;
82  CandQCutFuncCollection gammaCuts;
83  CandQCutFuncCollection neutralHadronCuts;
84 
85  // Make sure there are no extra passed options
86  std::set<std::string> passedOptionSet;
87  std::vector<std::string> passedOptions = qcuts.getParameterNames();
88 
89  for (auto const& option : passedOptions) {
90  passedOptionSet.insert(option);
91  }
92 
93  unsigned int nCuts = 0;
94  auto getDouble = [&qcuts, &passedOptionSet, &nCuts](const std::string& name) {
95  if (qcuts.exists(name)) {
96  ++nCuts;
97  passedOptionSet.erase(name);
98  return qcuts.getParameter<double>(name);
99  }
100  return -1.0;
101  };
102  auto getUint = [&qcuts, &passedOptionSet, &nCuts](const std::string& name) -> unsigned int {
103  if (qcuts.exists(name)) {
104  ++nCuts;
105  passedOptionSet.erase(name);
106  return qcuts.getParameter<unsigned int>(name);
107  }
108  return 0;
109  };
110 
111  // Build all the QCuts for tracks
112  minTrackPt_ = getDouble("minTrackPt");
113  maxTrackChi2_ = getDouble("maxTrackChi2");
114  minTrackPixelHits_ = getUint("minTrackPixelHits");
115  minTrackHits_ = getUint("minTrackHits");
116  maxTransverseImpactParameter_ = getDouble("maxTransverseImpactParameter");
117  maxDeltaZ_ = getDouble("maxDeltaZ");
118  maxDeltaZToLeadTrack_ = getDouble("maxDeltaZToLeadTrack");
119  // Require tracks to contribute a minimum weight to the associated vertex.
120  minTrackVertexWeight_ = getDouble("minTrackVertexWeight");
121 
122  // Use bit-wise & to avoid conditional code
125  (minTrackVertexWeight_ >= 0);
126 
127  // Build the QCuts for gammas
128  minGammaEt_ = getDouble("minGammaEt");
129 
130  // Build QCuts for netural hadrons
131  minNeutralHadronEt_ = getDouble("minNeutralHadronEt");
132 
133  // Check if there are any remaining unparsed QCuts
134  if (!passedOptionSet.empty()) {
135  std::string unParsedOptions;
136  bool thereIsABadParameter = false;
137  for (auto const& option : passedOptionSet) {
138  // Workaround for HLT - TODO FIXME
139  if (option == "useTracksInsteadOfPFHadrons") {
140  // Crash if true - no one should have this option enabled.
141  if (qcuts.getParameter<bool>("useTracksInsteadOfPFHadrons")) {
142  throw cms::Exception("DontUseTracksInQcuts") << "The obsolete exception useTracksInsteadOfPFHadrons "
143  << "is set to true in the quality cut config." << std::endl;
144  }
145  continue;
146  }
147 
148  // If we get to this point, there is a real unknown parameter
149  thereIsABadParameter = true;
150 
151  unParsedOptions += option;
152  unParsedOptions += "\n";
153  }
154  if (thereIsABadParameter) {
155  throw cms::Exception("BadQualityCutConfig") << " The PSet passed to the RecoTauQualityCuts class had"
156  << " the following unrecognized options: " << std::endl
157  << unParsedOptions;
158  }
159  }
160 
161  // Make sure there are at least some quality cuts
162  if (!nCuts) {
163  throw cms::Exception("BadQualityCutConfig") << " No options were passed to the quality cut class!" << std::endl;
164  }
165  }
166 
167  std::pair<edm::ParameterSet, edm::ParameterSet> factorizePUQCuts(const edm::ParameterSet& input) {
168  edm::ParameterSet puCuts;
169  edm::ParameterSet nonPUCuts;
170 
171  std::vector<std::string> inputNames = input.getParameterNames();
172  for (auto const& cut : inputNames) {
173  if (cut == "minTrackVertexWeight" || cut == "maxDeltaZ" || cut == "maxDeltaZToLeadTrack") {
174  puCuts.copyFrom(input, cut);
175  } else {
176  nonPUCuts.copyFrom(input, cut);
177  }
178  }
179  return std::make_pair(puCuts, nonPUCuts);
180  }
181 
183  if (!filterTrack_(track.get()))
184  return false;
185  if (minTrackVertexWeight_ >= 0. && !(pv_->trackWeight(convertRef(track)) >= minTrackVertexWeight_))
186  return false;
187  return true;
188  }
189 
191  if (!filterTrack_(track.get()))
192  return false;
193  if (minTrackVertexWeight_ >= 0. && !(pv_->trackWeight(convertRef(track)) >= minTrackVertexWeight_))
194  return false;
195  return true;
196  }
197 
199 
201  if (minTrackPt_ >= 0 && !(track->pt() > minTrackPt_))
202  return false;
203  if (maxTrackChi2_ >= 0 && !(track->normalizedChi2() <= maxTrackChi2_))
204  return false;
205  if (checkHitPattern_) {
206  const reco::HitPattern& hitPattern = track->hitPattern();
207  if (minTrackPixelHits_ > 0 && !(hitPattern.numberOfValidPixelHits() >= minTrackPixelHits_))
208  return false;
209  if (minTrackHits_ > 0 && !(hitPattern.numberOfValidHits() >= minTrackHits_))
210  return false;
211  }
212  if (checkPV_ && pv_.isNull()) {
213  edm::LogError("QCutsNoPrimaryVertex") << "Primary vertex Ref in "
214  << "RecoTauQualityCuts is invalid. - filterTrack";
215  return false;
216  }
217 
219  !(std::fabs(track->dxy(pv_->position())) <= maxTransverseImpactParameter_))
220  return false;
221  if (maxDeltaZ_ >= 0 && !(std::fabs(track->dz(pv_->position())) <= maxDeltaZ_))
222  return false;
223  if (maxDeltaZToLeadTrack_ >= 0) {
224  if (!leadTrack_) {
225  edm::LogError("QCutsNoValidLeadTrack") << "Lead track Ref in "
226  << "RecoTauQualityCuts is invalid. - filterTrack";
227  return false;
228  }
229 
230  if (!(std::fabs(track->dz(pv_->position()) - leadTrack_->dz(pv_->position())) <= maxDeltaZToLeadTrack_))
231  return false;
232  }
233 
234  return true;
235  }
236 
238  if (cand.charge() == 0)
239  return true;
240  const pat::PackedCandidate* pCand = dynamic_cast<const pat::PackedCandidate*>(&cand);
241  if (pCand == nullptr)
242  return true;
243 
244  //Get track, it should be present for cands with pT(charged)>0.5GeV
245  //and check track quality critera other than vertex weight
246  auto track = getTrack(cand);
247  if (track != nullptr) {
248  if (!filterTrack(*track))
249  return false;
250  } else { //Candidates without track (pT(charged)<0.5GeV): Can still check pT and calculate dxy and dz
251  if (minTrackPt_ >= 0 && !(pCand->pt() > minTrackPt_))
252  return false;
253  if (checkPV_ && pv_.isNull()) {
254  edm::LogError("QCutsNoPrimaryVertex") << "Primary vertex Ref in "
255  << "RecoTauQualityCuts is invalid. - filterChargedCand";
256  return false;
257  }
258 
260  !(std::fabs(pCand->dxy(pv_->position())) <= maxTransverseImpactParameter_))
261  return false;
262  if (maxDeltaZ_ >= 0 && !(std::fabs(pCand->dz(pv_->position())) <= maxDeltaZ_))
263  return false;
264  if (maxDeltaZToLeadTrack_ >= 0) {
265  if (leadTrack_ == nullptr) {
266  edm::LogError("QCutsNoValidLeadTrack") << "Lead track Ref in "
267  << "RecoTauQualityCuts is invalid. - filterChargedCand";
268  return false;
269  }
270 
271  if (!(std::fabs(pCand->dz(pv_->position()) - leadTrack_->dz(pv_->position())) <= maxDeltaZToLeadTrack_))
272  return false;
273  }
274  }
276  return false;
277 
278  return true;
279  }
280 
282  if (minGammaEt_ >= 0 && !(cand.et() > minGammaEt_))
283  return false;
284  return true;
285  }
286 
288  if (minNeutralHadronEt_ >= 0 && !(cand.et() > minNeutralHadronEt_))
289  return false;
290  return true;
291  }
292 
294  switch (std::abs(cand.pdgId())) {
295  case 22:
296  return filterGammaCand(cand);
297  case 130:
299  // We use the same qcuts for muons/electrons and charged hadrons.
300  case 211:
301  case 11:
302  case 13:
303  // no cuts ATM (track cuts applied in filterCand)
304  return true;
305  // Return false if we dont' know how to deal with this particle type
306  default:
307  return false;
308  };
309  return false;
310  }
311 
313  auto trackRef = getTrackRef(cand);
314  bool result = true;
315 
316  if (trackRef.isNonnull()) {
317  result = filterTrack(trackRef);
318  } else {
319  auto gsfTrackRef = getGsfTrackRef(cand);
320  if (gsfTrackRef.isNonnull())
321  result = filterTrack(gsfTrackRef);
322  else if (cand.charge() != 0) {
324  }
325  }
326 
327  if (result)
329 
330  return result;
331  }
332 
334 
336 
338  if (leadCand.isNonnull()) {
340  } else {
341  // Set null
342  leadTrack_ = nullptr;
343  }
344  }
345 
347  edm::ParameterSetDescription desc_signalQualityCuts;
348  desc_signalQualityCuts.add<double>("minTrackPt", 0.5);
349  desc_signalQualityCuts.add<double>("maxTrackChi2", 100.0);
350  desc_signalQualityCuts.add<double>("maxTransverseImpactParameter", 0.1);
351  desc_signalQualityCuts.add<double>("maxDeltaZ", 0.4);
352  desc_signalQualityCuts.add<double>("maxDeltaZToLeadTrack", -1.0); // by default disabled
353  desc_signalQualityCuts.add<double>("minTrackVertexWeight", -1.0); // by default disabled
354  desc_signalQualityCuts.add<unsigned int>("minTrackPixelHits", 0);
355  desc_signalQualityCuts.add<unsigned int>("minTrackHits", 3);
356  desc_signalQualityCuts.add<double>("minGammaEt", 1.0);
357  desc_signalQualityCuts.addOptional<bool>("useTracksInsteadOfPFHadrons");
358  desc_signalQualityCuts.add<double>("minNeutralHadronEt", 30.0);
359 
360  edm::ParameterSetDescription desc_isolationQualityCuts;
361  desc_isolationQualityCuts.add<double>("minTrackPt", 1.0);
362  desc_isolationQualityCuts.add<double>("maxTrackChi2", 100.0);
363  desc_isolationQualityCuts.add<double>("maxTransverseImpactParameter", 0.03);
364  desc_isolationQualityCuts.add<double>("maxDeltaZ", 0.2);
365  desc_isolationQualityCuts.add<double>("maxDeltaZToLeadTrack", -1.0); // by default disabled
366  desc_isolationQualityCuts.add<double>("minTrackVertexWeight", -1.0); // by default disabled
367  desc_isolationQualityCuts.add<unsigned int>("minTrackPixelHits", 0);
368  desc_isolationQualityCuts.add<unsigned int>("minTrackHits", 8);
369  desc_isolationQualityCuts.add<double>("minGammaEt", 1.5);
370  desc_isolationQualityCuts.addOptional<bool>("useTracksInsteadOfPFHadrons");
371 
372  edm::ParameterSetDescription desc_vxAssocQualityCuts;
373  desc_vxAssocQualityCuts.add<double>("minTrackPt", 0.5);
374  desc_vxAssocQualityCuts.add<double>("maxTrackChi2", 100.0);
375  desc_vxAssocQualityCuts.add<double>("maxTransverseImpactParameter", 0.1);
376  desc_vxAssocQualityCuts.add<double>("minTrackVertexWeight", -1.0);
377  desc_vxAssocQualityCuts.add<unsigned int>("minTrackPixelHits", 0);
378  desc_vxAssocQualityCuts.add<unsigned int>("minTrackHits", 3);
379  desc_vxAssocQualityCuts.add<double>("minGammaEt", 1.0);
380  desc_vxAssocQualityCuts.addOptional<bool>("useTracksInsteadOfPFHadrons");
381 
382  desc_qualityCuts.add<edm::ParameterSetDescription>("signalQualityCuts", desc_signalQualityCuts);
383  desc_qualityCuts.add<edm::ParameterSetDescription>("isolationQualityCuts", desc_isolationQualityCuts);
384  desc_qualityCuts.add<edm::ParameterSetDescription>("vxAssocQualityCuts", desc_vxAssocQualityCuts);
385  desc_qualityCuts.add<edm::InputTag>("primaryVertexSrc", edm::InputTag("offlinePrimaryVertices"));
386  desc_qualityCuts.add<std::string>("pvFindingAlgo", "closestInDeltaZ");
387  desc_qualityCuts.add<bool>("vertexTrackFiltering", false);
388  desc_qualityCuts.add<bool>("recoverLeadingTrk", false);
389  desc_qualityCuts.add<std::string>("leadingTrkOrPFCandOption", "leadPFCand");
390  }
391 
392 } // end namespace reco::tau
bool filterTrack_(const reco::Track *track) const
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
ParameterDescriptionBase * addOptional(U const &iLabel, T const &value)
RecoTauQualityCuts(const edm::ParameterSet &qcuts)
static void fillDescriptions(edm::ParameterSetDescription &descriptions)
Declare all parameters read from python config file.
bool filterCandByType(const reco::Candidate &cand) const
bool filterGammaCand(const reco::Candidate &cand) const
bool exists(std::string const &parameterName) const
checks if a parameter exists
bool filterNeutralHadronCand(const reco::Candidate &cand) const
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:238
Definition: weight.py:1
Log< level::Error, false > LogError
const reco::VertexRef vertexRef() const
bool filterTrack(const reco::TrackBaseRef &track) const
Filter a single Track.
InputIterator leadCand(InputIterator begin, InputIterator end)
key_type key() const
Accessor for product key.
Definition: Ref.h:250
static std::string const input
Definition: EdmProvDump.cc:50
std::vector< CandQCutFunc > CandQCutFuncCollection
const PVAssociationQuality pvAssociationQuality() const
string quality
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:622
void copyFrom(ParameterSet const &from, std::string const &name)
double eta() const override
momentum pseudorapidity
edm::RefToBase< reco::Track > TrackBaseRef
persistent reference to a Track, using views
Definition: TrackFwd.h:35
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
std::pair< edm::ParameterSet, edm::ParameterSet > factorizePUQCuts(const edm::ParameterSet &inputSet)
ParameterDescriptionBase * add(U const &iLabel, T const &value)
bool filterChargedCand(const reco::Candidate &cand) const
or a single charged candidate
bool isNull() const
Checks for null.
Definition: Ref.h:235
static const TrackGhostTrackState * getTrack(const BasicGhostTrackState *basic)
double pt() const override
transverse momentum
edm::Ref< TrackCollection > TrackRef
persistent reference to a Track
Definition: TrackFwd.h:20
bool filterCand(const reco::Candidate &cand) const
Filter a single Candidate.
virtual float dxy() const
dxy with respect to the PV ref
void setLeadTrack(const reco::Track &leadTrack)
Update the leading track.
virtual float dz(size_t ipv=0) const
dz with respect to the PV[ipv]
long double T
std::vector< std::string > getParameterNames() const
bool minPackedCandVertexWeight(const pat::PackedCandidate &pCand, const reco::VertexRef *pv, double cut)
double phi() const override
momentum azimuthal angle
virtual const reco::Track & pseudoTrack() const
#define LogDebug(id)
bool hasTrackDetails() const
Return true if a bestTrack can be extracted from this Candidate.