CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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
67  else if (quality == pat::PackedCandidate::UsedInFitLoose)
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 
198  bool RecoTauQualityCuts::filterTrack(const reco::Track& track) const { return filterTrack_(&track); }
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:
298  return filterNeutralHadronCand(cand);
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) {
323  result = filterChargedCand(cand);
324  }
325  }
326 
327  if (result)
328  result = filterCandByType(cand);
329 
330  return result;
331  }
332 
334 
336 
338  if (leadCand.isNonnull()) {
339  leadTrack_ = getTrack(*leadCand);
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
virtual float dz(size_t ipv=0) const
dz with respect to the PV[ipv]
value_type const * get() const
Definition: RefToBase.h:209
ParameterDescriptionBase * addOptional(U const &iLabel, T const &value)
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:238
RecoTauQualityCuts(const edm::ParameterSet &qcuts)
static void fillDescriptions(edm::ParameterSetDescription &descriptions)
Declare all parameters read from python config file.
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:593
virtual double et() const =0
transverse energy
uint32_t const *__restrict__ Quality * quality
int numberOfValidHits() const
Definition: HitPattern.h:811
bool exists(std::string const &parameterName) const
checks if a parameter exists
key_type key() const
Accessor for product key.
Definition: Ref.h:250
bool filterCand(const reco::Candidate &cand) const
Filter a single Candidate.
Log< level::Error, false > LogError
const reco::VertexRef vertexRef() const
InputIterator leadCand(InputIterator begin, InputIterator end)
static std::string const input
Definition: EdmProvDump.cc:47
tuple result
Definition: mps_fire.py:311
std::vector< CandQCutFunc > CandQCutFuncCollection
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
const PVAssociationQuality pvAssociationQuality() const
bool filterCandByType(const reco::Candidate &cand) const
double pt() const
track transverse momentum
Definition: TrackBase.h:637
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
virtual const reco::Track & pseudoTrack() const
virtual int charge() const =0
electric charge
T const * get() const
Returns C++ pointer to the item.
Definition: Ref.h:232
std::pair< edm::ParameterSet, edm::ParameterSet > factorizePUQCuts(const edm::ParameterSet &inputSet)
std::vector< std::string > getParameterNames() const
ParameterDescriptionBase * add(U const &iLabel, T const &value)
bool isNull() const
Checks for null.
Definition: Ref.h:235
bool filterTrack_(const reco::Track *track) const
bool hasTrackDetails() const
Return true if a bestTrack can be extracted from this Candidate.
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
virtual int pdgId() const =0
PDG identifier.
static const TrackGhostTrackState * getTrack(const BasicGhostTrackState *basic)
double pt() const override
transverse momentum
bool filterChargedCand(const reco::Candidate &cand) const
or a single charged candidate
const HitPattern & hitPattern() const
Access the hit pattern, indicating in which Tracker layers the track has hits.
Definition: TrackBase.h:504
edm::Ref< TrackCollection > TrackRef
persistent reference to a Track
Definition: TrackFwd.h:20
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
bool filterNeutralHadronCand(const reco::Candidate &cand) const
int numberOfValidPixelHits() const
Definition: HitPattern.h:825
bool filterGammaCand(const reco::Candidate &cand) const
void setLeadTrack(const reco::Track &leadTrack)
Update the leading track.
int weight
Definition: histoStyle.py:51
virtual float dxy() const
dxy with respect to the PV ref
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:608
long double T
bool minPackedCandVertexWeight(const pat::PackedCandidate &pCand, const reco::VertexRef *pv, double cut)
bool filterTrack(const reco::TrackBaseRef &track) const
Filter a single Track.
double phi() const override
momentum azimuthal angle
#define LogDebug(id)