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 it has a GSF track.
13  reco::Track const * getTrack(const PFCandidate& cand) {
14  reco::Track const * ret = cand.trackRef().get();
15  if (!ret) ret = cand.gsfTrackRef().get();
16  return ret;
17  }
18  // slow!
19  const reco::TrackBaseRef getTrackRef(const PFCandidate& cand) {
20  if (cand.trackRef().isNonnull())
21  return reco::TrackBaseRef(cand.trackRef());
22  else if (cand.gsfTrackRef().isNonnull()) {
23  return reco::TrackBaseRef(cand.gsfTrackRef());
24  }
25  return reco::TrackBaseRef();
26  }
27 }
28 
29 // Quality cut implementations
30 namespace qcuts {
31 
32 bool ptMin(const PFCandidate& cand, double cut) {
33  return cand.pt() > cut;
34 }
35 
36 bool etMin(const PFCandidate& cand, double cut) {
37  return cand.et() > cut;
38 }
39 
40 bool trkPixelHits(const PFCandidate& cand, int cut) {
41  // For some reason, the number of hits is signed
42  auto trk = getTrack(cand);
43  if (!trk) return false;
44  return trk->hitPattern().numberOfValidPixelHits() >= cut;
45 }
46 
47 bool trkTrackerHits(const PFCandidate& cand, int cut) {
48  auto trk = getTrack(cand);
49  if (!trk) return false;
50  return trk->hitPattern().numberOfValidHits() >= cut;
51 }
52 
54  const reco::VertexRef* pv,
55  double cut) {
56  if (pv->isNull()) {
57  edm::LogError("QCutsNoPrimaryVertex") << "Primary vertex Ref in " <<
58  "RecoTauQualityCuts is invalid. - trkTransverseImpactParameter";
59  return false;
60  }
61  auto trk = getTrack(cand);
62  if (!trk) return false;
63  return std::abs(trk->dxy((*pv)->position())) <= cut;
64 }
65 
67  const reco::VertexRef* pv,
68  double cut) {
69  if (pv->isNull()) {
70  edm::LogError("QCutsNoPrimaryVertex") << "Primary vertex Ref in " <<
71  "RecoTauQualityCuts is invalid. - trkLongitudinalImpactParameter";
72  return false;
73  }
74  auto trk = getTrack(cand);
75  if (!trk) return false;
76  double difference = std::abs(trk->dz((*pv)->position()));
77  //std::cout << "QCUTS LIP: track vz: " << trk->vz() <<
78  //" diff: " << difference << " cut: " << cut << std::endl;
79  return difference <= cut;
80 }
81 
84  const reco::TrackBaseRef* trk, double cut) {
85  if (trk->isNull()) {
86  edm::LogError("QCutsNoValidLeadTrack") << "Lead track Ref in " <<
87  "RecoTauQualityCuts is invalid. - trkLongitudinalImpactParameterWrtTrack";
88  return false;
89  }
90  auto candTrk = getTrack(cand);
91  if (!candTrk) return false;
92  double difference = std::abs((*trk)->vz() - candTrk->vz());
93  return difference <= cut;
94 }
95 
96 
97 bool minTrackVertexWeight(const PFCandidate& cand, const reco::VertexRef* pv,
98  double cut) {
99  if (pv->isNull()) {
100  edm::LogError("QCutsNoPrimaryVertex") << "Primary vertex Ref in " <<
101  "RecoTauQualityCuts is invalid. - minTrackVertexWeight";
102  return false;
103  }
104  auto trk = getTrackRef(cand);
105  if (!trk) return false;
106  double weight = (*pv)->trackWeight(trk);
107  return weight >= cut;
108 }
109 
110 bool trkChi2(const PFCandidate& cand, double cut) {
111  auto trk = getTrack(cand);
112  if (!trk) return false;
113  return trk->normalizedChi2() <= cut;
114 }
115 
116 // And a set of qcuts
117 bool AND(const PFCandidate& cand,
119  BOOST_FOREACH(const RecoTauQualityCuts::QCutFunc& func, cuts) {
120  if (!func(cand))
121  return false;
122  }
123  return true;
124 }
125 
126 // Get the set of Q cuts for a given type (i.e. gamma)
127 bool mapAndCutByType(const PFCandidate& cand,
128  const RecoTauQualityCuts::QCutFuncMap& funcMap) {
129  // Find the cuts that for this particle type
130  RecoTauQualityCuts::QCutFuncMap::const_iterator cuts =
131  funcMap.find(cand.particleId());
132  // Return false if we dont' know how to deal w/ this particle type
133  if (cuts == funcMap.end())
134  return false;
135  else
136  // Otherwise AND all the cuts
137  return AND(cand, cuts->second);
138 }
139 
140 } // end qcuts implementation namespace
141 
143  // Setup all of our predicates
144  QCutFuncCollection chargedHadronCuts;
145  QCutFuncCollection gammaCuts;
146  QCutFuncCollection neutralHadronCuts;
147 
148  // Make sure there are no extra passed options
149  std::set<std::string> passedOptionSet;
150  std::vector<std::string> passedOptions = qcuts.getParameterNames();
151 
152  BOOST_FOREACH(const std::string& option, passedOptions) {
153  passedOptionSet.insert(option);
154  }
155 
156  // Build all the QCuts for tracks
157  if (qcuts.exists("minTrackPt")) {
158  chargedHadronCuts.push_back(
159  boost::bind(qcuts::ptMin, _1,
160  qcuts.getParameter<double>("minTrackPt")));
161  passedOptionSet.erase("minTrackPt");
162  }
163 
164  if (qcuts.exists("maxTrackChi2")) {
165  chargedHadronCuts.push_back(
166  boost::bind(qcuts::trkChi2, _1,
167  qcuts.getParameter<double>("maxTrackChi2")));
168  passedOptionSet.erase("maxTrackChi2");
169  }
170 
171  if (qcuts.exists("minTrackPixelHits")) {
172  chargedHadronCuts.push_back(boost::bind(
174  qcuts.getParameter<uint32_t>("minTrackPixelHits")));
175  passedOptionSet.erase("minTrackPixelHits");
176  }
177 
178  if (qcuts.exists("minTrackHits")) {
179  chargedHadronCuts.push_back(boost::bind(
181  qcuts.getParameter<uint32_t>("minTrackHits")));
182  passedOptionSet.erase("minTrackHits");
183  }
184 
185  // The impact parameter functions are bound to our member PV, since they
186  // need it to compute the discriminant value.
187  if (qcuts.exists("maxTransverseImpactParameter")) {
188  chargedHadronCuts.push_back(boost::bind(
190  qcuts.getParameter<double>("maxTransverseImpactParameter")));
191  passedOptionSet.erase("maxTransverseImpactParameter");
192  }
193 
194  if (qcuts.exists("maxDeltaZ")) {
195  chargedHadronCuts.push_back(boost::bind(
197  qcuts.getParameter<double>("maxDeltaZ")));
198  passedOptionSet.erase("maxDeltaZ");
199  }
200 
201  if (qcuts.exists("maxDeltaZToLeadTrack")) {
202  chargedHadronCuts.push_back(boost::bind(
204  qcuts.getParameter<double>("maxDeltaZToLeadTrack")));
205  passedOptionSet.erase("maxDeltaZToLeadTrack");
206  }
207 
208  // Require tracks to contribute a minimum weight to the associated vertex.
209  if (qcuts.exists("minTrackVertexWeight")) {
210  chargedHadronCuts.push_back(boost::bind(
212  qcuts.getParameter<double>("minTrackVertexWeight")));
213  passedOptionSet.erase("minTrackVertexWeight");
214  }
215 
216  // Build the QCuts for gammas
217  if (qcuts.exists("minGammaEt")) {
218  gammaCuts.push_back(boost::bind(
219  qcuts::etMin, _1, qcuts.getParameter<double>("minGammaEt")));
220  passedOptionSet.erase("minGammaEt");
221  }
222 
223  // Build QCuts for netural hadrons
224  if (qcuts.exists("minNeutralHadronEt")) {
225  neutralHadronCuts.push_back(boost::bind(
226  qcuts::etMin, _1,
227  qcuts.getParameter<double>("minNeutralHadronEt")));
228  passedOptionSet.erase("minNeutralHadronEt");
229  }
230 
231  // Check if there are any remaining unparsed QCuts
232  if (passedOptionSet.size()) {
233  std::string unParsedOptions;
234  bool thereIsABadParameter = false;
235  BOOST_FOREACH(const std::string& option, passedOptionSet) {
236  // Workaround for HLT - TODO FIXME
237  if (option == "useTracksInsteadOfPFHadrons") {
238  // Crash if true - no one should have this option enabled.
239  if (qcuts.getParameter<bool>("useTracksInsteadOfPFHadrons")) {
240  throw cms::Exception("DontUseTracksInQcuts")
241  << "The obsolete exception useTracksInsteadOfPFHadrons "
242  << "is set to true in the quality cut config." << std::endl;
243  }
244  continue;
245  }
246 
247  // If we get to this point, there is a real unknown parameter
248  thereIsABadParameter = true;
249 
250  unParsedOptions += option;
251  unParsedOptions += "\n";
252  }
253  if (thereIsABadParameter) {
254  throw cms::Exception("BadQualityCutConfig")
255  << " The PSet passed to the RecoTauQualityCuts class had"
256  << " the following unrecognized options: " << std::endl
257  << unParsedOptions;
258  }
259  }
260 
261  // Make sure there are at least some quality cuts
262  size_t nCuts = chargedHadronCuts.size() + gammaCuts.size()
263  + neutralHadronCuts.size();
264  if (!nCuts) {
265  throw cms::Exception("BadQualityCutConfig")
266  << " No options were passed to the quality cut class!" << std::endl;
267  }
268 
269  // Map our QCut collections to the particle Ids they are associated to.
270  qcuts_[PFCandidate::h] = chargedHadronCuts;
271  qcuts_[PFCandidate::gamma] = gammaCuts;
272  qcuts_[PFCandidate::h0] = neutralHadronCuts;
273  // We use the same qcuts for muons/electrons and charged hadrons.
274  qcuts_[PFCandidate::e] = chargedHadronCuts;
275  qcuts_[PFCandidate::mu] = chargedHadronCuts;
276 
277  // Build a final level predicate that works on any PFCand
278  predicate_ = boost::bind(qcuts::mapAndCutByType, _1, boost::cref(qcuts_));
279 }
280 
281 std::pair<edm::ParameterSet, edm::ParameterSet> factorizePUQCuts(
282  const edm::ParameterSet& input) {
283 
284  edm::ParameterSet puCuts;
285  edm::ParameterSet nonPUCuts;
286 
287  std::vector<std::string> inputNames = input.getParameterNames();
288  BOOST_FOREACH(const std::string& cut, inputNames) {
289  if (cut == "minTrackVertexWeight" || cut == "maxDeltaZ"
290  || cut == "maxDeltaZToLeadTrack") {
291  puCuts.copyFrom(input, cut);
292  } else {
293  nonPUCuts.copyFrom(input, cut);
294  }
295  }
296  return std::make_pair(puCuts, nonPUCuts);
297 }
298 
299 
301  const reco::PFCandidate& leadCand) const {
302  leadTrack_ = getTrackRef(leadCand);
303 }
304 
306  const reco::PFCandidateRef& leadCand) const {
307  if (leadCand.isNonnull()) {
308  leadTrack_ = getTrackRef(*leadCand);
309  } else {
310  // Set null
312  }
313 }
314 
315 
316 }} // end namespace reco::tau
bool ptMin(const PFCandidate &cand, double cut)
T getParameter(std::string const &) const
virtual double et() const GCC11_FINAL
transverse energy
bool AND(const PFCandidate &cand, const RecoTauQualityCuts::QCutFuncCollection &cuts)
bool trkChi2(const PFCandidate &cand, double cut)
RecoTauQualityCuts(const edm::ParameterSet &qcuts)
boost::function< bool(const PFCandidate &)> QCutFunc
bool minTrackVertexWeight(const PFCandidate &cand, const reco::VertexRef *pv, double cut)
bool exists(std::string const &parameterName) const
checks if a parameter exists
#define abs(x)
Definition: mlp_lapack.h:159
void setLeadTrack(const reco::PFCandidate &leadCand) const
Update the leading track.
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:250
void copyFrom(ParameterSet const &from, std::string const &name)
bool isNull() const
Checks for null.
Definition: Ref.h:247
edm::RefToBase< reco::Track > TrackBaseRef
persistent reference to a Track, using views
Definition: TrackFwd.h:22
bool trkPixelHits(const PFCandidate &cand, int cut)
std::map< PFCandidate::ParticleType, QCutFuncCollection > QCutFuncMap
std::pair< edm::ParameterSet, edm::ParameterSet > factorizePUQCuts(const edm::ParameterSet &inputSet)
bool mapAndCutByType(const PFCandidate &cand, const RecoTauQualityCuts::QCutFuncMap &funcMap)
std::vector< std::string > getParameterNames() const
bool trkLongitudinalImpactParameter(const PFCandidate &cand, const reco::VertexRef *pv, double cut)
bool etMin(const PFCandidate &cand, double cut)
bool trkTransverseImpactParameter(const PFCandidate &cand, const reco::VertexRef *pv, double cut)
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:35
const reco::TrackBaseRef getTrack(const reco::PFCandidate &cand)
bool trkTrackerHits(const PFCandidate &cand, int cut)
bool trkLongitudinalImpactParameterWrtTrack(const PFCandidate &cand, const reco::TrackBaseRef *trk, double cut)
DZ cut, with respect to the current lead rack.
int weight
Definition: histoStyle.py:50
virtual ParticleType particleId() const
Definition: PFCandidate.h:347
virtual float pt() const GCC11_FINAL
transverse momentum
std::vector< QCutFunc > QCutFuncCollection