CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
PFRecoTauDiscriminationByHPSSelection.cc
Go to the documentation of this file.
3 
6 
9 
13 
14 namespace {
15  // Apply a hypothesis on the mass of the strips.
16  math::XYZTLorentzVector applyMassConstraint(const math::XYZTLorentzVector& vec, double mass) {
17  double factor = sqrt(vec.energy() * vec.energy() - mass * mass) / vec.P();
18  return math::XYZTLorentzVector(vec.px() * factor, vec.py() * factor, vec.pz() * factor, vec.energy());
19  }
20 } // namespace
21 
23 public:
26  double discriminate(const reco::PFTauRef&) const override;
27 
28  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
29 
30 private:
32 
33  struct DecayModeCuts {
34  DecayModeCuts() : maxMass_(nullptr) {}
35  ~DecayModeCuts() {} // CV: maxMass object gets deleted by PFRecoTauDiscriminationByHPSSelection destructor
36  unsigned nTracksMin_;
38  double minMass_;
43  double minPi0Mass_;
44  double maxPi0Mass_;
46  };
47 
48  typedef std::pair<unsigned int, unsigned int> IntPair;
49  typedef std::pair<double, double> DoublePair;
50  typedef std::map<IntPair, DecayModeCuts> DecayModeCutMap;
51 
53  double matchingCone_;
54  double minPt_;
55 
57 
59 
61 };
62 
65  // Get the matchign cut
66  matchingCone_ = pset.getParameter<double>("matchingCone");
67  minPt_ = pset.getParameter<double>("minTauPt");
68  // Get the mass cuts for each decay mode
69  typedef std::vector<edm::ParameterSet> VPSet;
70  const VPSet& decayModes = pset.getParameter<VPSet>("decayModes");
71  for (auto const& decayMode : decayModes) {
72  // The mass window(s)
74  cuts.nTracksMin_ = decayMode.getParameter<unsigned>("nTracksMin");
75  cuts.nChargedPFCandsMin_ = decayMode.getParameter<unsigned>("nChargedPFCandsMin");
76  cuts.minMass_ = decayMode.getParameter<double>("minMass");
77  cuts.maxMass_ = new TauFunc(decayMode.getParameter<std::string>("maxMass"));
78  edm::ParameterSet applyBendCorrection = decayMode.getParameter<edm::ParameterSet>("applyBendCorrection");
79  cuts.applyBendCorrection_eta_ = applyBendCorrection.getParameter<bool>("eta");
80  cuts.applyBendCorrection_phi_ = applyBendCorrection.getParameter<bool>("phi");
81  cuts.applyBendCorrection_mass_ = applyBendCorrection.getParameter<bool>("mass");
82  cuts.minPi0Mass_ = decayMode.getParameter<double>("minPi0Mass");
83  cuts.maxPi0Mass_ = decayMode.getParameter<double>("maxPi0Mass");
84  cuts.assumeStripMass_ = decayMode.getParameter<double>("assumeStripMass");
85  decayModeCuts_.insert(std::make_pair(
86  // The decay mode as a key
87  std::make_pair(decayMode.getParameter<uint32_t>("nCharged"), decayMode.getParameter<uint32_t>("nPiZeros")),
88  cuts));
89  }
90  requireTauChargedHadronsToBeChargedPFCands_ = pset.getParameter<bool>("requireTauChargedHadronsToBeChargedPFCands");
91  minPixelHits_ = pset.getParameter<int>("minPixelHits");
92  verbosity_ = pset.getParameter<int>("verbosity");
93 }
94 
96  for (DecayModeCutMap::iterator it = decayModeCuts_.begin(); it != decayModeCuts_.end(); ++it) {
97  delete it->second.maxMass_;
98  }
99 }
100 
101 namespace {
102  inline const reco::Track* getTrack(const reco::Candidate& cand) {
103  const reco::PFCandidate* pfCandPtr = dynamic_cast<const reco::PFCandidate*>(&cand);
104  if (pfCandPtr) {
105  if (pfCandPtr->trackRef().isNonnull())
106  return pfCandPtr->trackRef().get();
107  else if (pfCandPtr->gsfTrackRef().isNonnull())
108  return pfCandPtr->gsfTrackRef().get();
109  else
110  return nullptr;
111  }
112  const pat::PackedCandidate* packedCand = dynamic_cast<const pat::PackedCandidate*>(&cand);
113  if (packedCand && packedCand->hasTrackDetails())
114  return &packedCand->pseudoTrack();
115 
116  return nullptr;
117  }
118 } // namespace
119 
121  if (verbosity_) {
122  edm::LogPrint("PFTauByHPSSelect") << "<PFRecoTauDiscriminationByHPSSelection::discriminate>:";
123  edm::LogPrint("PFTauByHPSSelect") << " nCharged = " << tau->signalTauChargedHadronCandidates().size();
124  edm::LogPrint("PFTauByHPSSelect") << " nPiZeros = " << tau->signalPiZeroCandidates().size();
125  }
126 
127  // Check if we pass the min pt
128  if (tau->pt() < minPt_) {
129  if (verbosity_) {
130  edm::LogPrint("PFTauByHPSSelect") << " fails minPt cut.";
131  }
132  return 0.0;
133  }
134 
135  // See if we select this decay mode
136  DecayModeCutMap::const_iterator massWindowIter = decayModeCuts_.find(
137  std::make_pair(tau->signalTauChargedHadronCandidates().size(), tau->signalPiZeroCandidates().size()));
138  // Check if decay mode is supported
139  if (massWindowIter == decayModeCuts_.end()) {
140  if (verbosity_) {
141  edm::LogPrint("PFTauByHPSSelect") << " fails mass-window definition requirement.";
142  }
143  return 0.0;
144  }
145  const DecayModeCuts& massWindow = massWindowIter->second;
146 
147  if (massWindow.nTracksMin_ > 0) {
148  unsigned int nTracks = 0;
149  const std::vector<reco::PFRecoTauChargedHadron>& chargedHadrons = tau->signalTauChargedHadronCandidates();
150  for (std::vector<reco::PFRecoTauChargedHadron>::const_iterator chargedHadron = chargedHadrons.begin();
151  chargedHadron != chargedHadrons.end();
152  ++chargedHadron) {
153  if (chargedHadron->algoIs(reco::PFRecoTauChargedHadron::kChargedPFCandidate) ||
154  chargedHadron->algoIs(reco::PFRecoTauChargedHadron::kTrack)) {
155  ++nTracks;
156  }
157  }
158  if (verbosity_) {
159  edm::LogPrint("PFTauByHPSSelect") << "nTracks = " << nTracks << " (min = " << massWindow.nTracksMin_ << ")";
160  }
161  if (nTracks < massWindow.nTracksMin_) {
162  if (verbosity_) {
163  edm::LogPrint("PFTauByHPSSelect") << " fails nTracks requirement for mass-window.";
164  }
165  return 0.0;
166  }
167  }
168  if (massWindow.nChargedPFCandsMin_ > 0) {
169  unsigned int nChargedPFCands = 0;
170  const std::vector<reco::PFRecoTauChargedHadron>& chargedHadrons = tau->signalTauChargedHadronCandidates();
171  for (std::vector<reco::PFRecoTauChargedHadron>::const_iterator chargedHadron = chargedHadrons.begin();
172  chargedHadron != chargedHadrons.end();
173  ++chargedHadron) {
174  if (chargedHadron->algoIs(reco::PFRecoTauChargedHadron::kChargedPFCandidate)) {
175  ++nChargedPFCands;
176  }
177  }
178  if (verbosity_) {
179  edm::LogPrint("PFTauByHPSSelect") << "nChargedPFCands = " << nChargedPFCands
180  << " (min = " << massWindow.nChargedPFCandsMin_ << ")";
181  }
182  if (nChargedPFCands < massWindow.nChargedPFCandsMin_) {
183  if (verbosity_) {
184  edm::LogPrint("PFTauByHPSSelect") << " fails nChargedPFCands requirement for mass-window.";
185  }
186  return 0.0;
187  }
188  }
189 
190  math::XYZTLorentzVector tauP4 = tau->p4();
191  if (verbosity_) {
192  edm::LogPrint("PFTauByHPSSelect") << "tau: Pt = " << tauP4.pt() << ", eta = " << tauP4.eta()
193  << ", phi = " << tauP4.phi() << ", mass = " << tauP4.mass();
194  }
195  // Find the total pizero p4
197  for (auto const& cand : tau->signalPiZeroCandidates()) {
198  const math::XYZTLorentzVector& candP4 = cand.p4();
199  stripsP4 += candP4;
200  }
201 
202  // Apply strip mass assumption corrections
203  if (massWindow.assumeStripMass_ >= 0) {
204  for (auto const& cand : tau->signalPiZeroCandidates()) {
205  const math::XYZTLorentzVector& uncorrected = cand.p4();
206  math::XYZTLorentzVector corrected = applyMassConstraint(uncorrected, massWindow.assumeStripMass_);
208  tauP4 += correction;
209  stripsP4 += correction;
210  }
211  }
212  if (verbosity_) {
213  edm::LogPrint("PFTauByHPSSelect") << "strips: Pt = " << stripsP4.pt() << ", eta = " << stripsP4.eta()
214  << ", phi = " << stripsP4.phi() << ", mass = " << stripsP4.mass();
215  }
216 
217  // Check if tau fails mass cut
218  double maxMass_value = (*massWindow.maxMass_)(*tau);
219  double bendCorrection_mass = (massWindow.applyBendCorrection_mass_) ? tau->bendCorrMass() : 0.;
220  if (!((tauP4.M() - bendCorrection_mass) < maxMass_value && (tauP4.M() + bendCorrection_mass) > massWindow.minMass_)) {
221  if (verbosity_) {
222  edm::LogPrint("PFTauByHPSSelect") << " fails tau mass-window cut.";
223  }
224  return 0.0;
225  }
226  // CV: require that mass of charged tau decay products is always within specified mass window,
227  // irrespective of bendCorrection_mass
228  reco::Candidate::LorentzVector tauP4_charged;
229  const std::vector<reco::PFRecoTauChargedHadron>& signalChargedHadrons = tau->signalTauChargedHadronCandidates();
230  for (std::vector<reco::PFRecoTauChargedHadron>::const_iterator signalChargedHadron = signalChargedHadrons.begin();
231  signalChargedHadron != signalChargedHadrons.end();
232  ++signalChargedHadron) {
233  tauP4_charged += signalChargedHadron->p4();
234  }
235  if (!(tauP4_charged.mass() < maxMass_value)) {
236  if (verbosity_) {
237  edm::LogPrint("PFTauByHPSSelect") << " fails tau mass-window cut.";
238  }
239  return 0.0;
240  }
241 
242  // Check if it fails the pi0 IM cut
243  if (stripsP4.M() > massWindow.maxPi0Mass_ || stripsP4.M() < massWindow.minPi0Mass_) {
244  if (verbosity_) {
245  edm::LogPrint("PFTauByHPSSelect") << " fails strip mass-window cut.";
246  }
247  return 0.0;
248  }
249 
250  // Check if tau passes matching cone cut
251  //edm::LogPrint("PFTauByHPSSelect") << "dR(tau, jet) = " << deltaR(tauP4, tau->jetRef()->p4()) ;
252  if (deltaR(tauP4, tau->jetRef()->p4()) > matchingCone_) {
253  if (verbosity_) {
254  edm::LogPrint("PFTauByHPSSelect") << " fails matching-cone cut.";
255  }
256  return 0.0;
257  }
258 
259  // Check if tau passes cone cut
260  double cone_size = tau->signalConeSize();
261  // Check if any charged objects fail the signal cone cut
262  for (auto const& cand : tau->signalTauChargedHadronCandidates()) {
263  if (verbosity_) {
264  edm::LogPrint("PFTauByHPSSelect") << "dR(tau, signalPFChargedHadr) = " << deltaR(cand.p4(), tauP4);
265  }
266  if (deltaR(cand.p4(), tauP4) > cone_size) {
267  if (verbosity_) {
268  edm::LogPrint("PFTauByHPSSelect") << " fails signal-cone cut for charged hadron(s).";
269  }
270  return 0.0;
271  }
272  }
273  // Now check the pizeros
274  for (auto const& cand : tau->signalPiZeroCandidates()) {
275  double bendCorrection_eta = (massWindow.applyBendCorrection_eta_) ? cand.bendCorrEta() : 0.;
276  double dEta = std::max(0., fabs(cand.eta() - tauP4.eta()) - bendCorrection_eta);
277  double bendCorrection_phi = (massWindow.applyBendCorrection_phi_) ? cand.bendCorrPhi() : 0.;
278  double dPhi = std::max(0., std::abs(reco::deltaPhi(cand.phi(), tauP4.phi())) - bendCorrection_phi);
279  double dR2 = dEta * dEta + dPhi * dPhi;
280  if (verbosity_) {
281  edm::LogPrint("PFTauByHPSSelect") << "dR2(tau, signalPiZero) = " << dR2;
282  }
283  if (dR2 > cone_size * cone_size) {
284  if (verbosity_) {
285  edm::LogPrint("PFTauByHPSSelect") << " fails signal-cone cut for strip(s).";
286  }
287  return 0.0;
288  }
289  }
290 
292  for (auto const& cand : tau->signalTauChargedHadronCandidates()) {
293  if (verbosity_) {
294  std::string algo_string;
296  algo_string = "ChargedPFCandidate";
297  else if (cand.algo() == reco::PFRecoTauChargedHadron::kTrack)
298  algo_string = "Track";
299  else if (cand.algo() == reco::PFRecoTauChargedHadron::kPFNeutralHadron)
300  algo_string = "PFNeutralHadron";
301  else
302  algo_string = "Undefined";
303  edm::LogPrint("PFTauByHPSSelect") << "algo(signalPFChargedHadr) = " << algo_string;
304  }
306  if (verbosity_) {
307  edm::LogPrint("PFTauByHPSSelect") << " fails cut on PFRecoTauChargedHadron algo.";
308  }
309  return 0.0;
310  }
311  }
312  }
313 
314  if (minPixelHits_ > 0) {
315  int numPixelHits = 0;
316  for (const auto& chargedHadrCand : tau->signalChargedHadrCands()) {
317  const reco::Track* track = getTrack(*chargedHadrCand);
318  if (track != nullptr) {
319  numPixelHits += track->hitPattern().numberOfValidPixelHits();
320  }
321  }
322  if (!(numPixelHits >= minPixelHits_)) {
323  if (verbosity_) {
324  edm::LogPrint("PFTauByHPSSelect") << " fails cut on sum of pixel hits.";
325  }
326  return 0.0;
327  }
328  }
329 
330  // Otherwise, we pass!
331  if (verbosity_) {
332  edm::LogPrint("PFTauByHPSSelect") << " passes all cuts.";
333  }
334  return 1.0;
335 }
336 
338  // hpsSelectionDiscriminator
340  desc.add<edm::InputTag>("PFTauProducer", edm::InputTag("combinatoricRecoTaus"));
341  desc.add<int>("verbosity", 0);
342  desc.add<double>("minTauPt", 0.0);
343  {
345  psd0.add<std::string>("BooleanOperator", "and");
346  desc.add<edm::ParameterSetDescription>("Prediscriminants", psd0);
347  }
348 
349  {
350  edm::ParameterSetDescription vpset_decayModes;
351  vpset_decayModes.add<double>("minPi0Mass", -1.e3);
352  vpset_decayModes.add<std::string>("maxMass");
353  vpset_decayModes.add<double>("maxPi0Mass", 1.e9);
354  vpset_decayModes.add<unsigned int>("nPiZeros");
355  vpset_decayModes.add<double>("minMass");
356  vpset_decayModes.add<unsigned int>("nChargedPFCandsMin", 0);
357  vpset_decayModes.add<unsigned int>("nTracksMin", 0);
358  vpset_decayModes.add<unsigned int>("nCharged");
359  {
361  psd0.add<bool>("phi");
362  psd0.add<bool>("eta");
363  psd0.add<bool>("mass");
364  vpset_decayModes.add<edm::ParameterSetDescription>("applyBendCorrection", psd0);
365  }
366  vpset_decayModes.add<double>("assumeStripMass", -1.0);
367  std::vector<edm::ParameterSet> vpset_default;
368  {
370  pset.addParameter<double>("minPi0Mass", -1.e3);
371  pset.addParameter<double>("maxPi0Mass", 1.e9);
372  pset.addParameter<unsigned int>("nChargedPFCandsMin", 0);
373  pset.addParameter<unsigned int>("nTracksMin", 0);
374  pset.addParameter<double>("assumeStripMass", -1.0);
375  vpset_default.push_back(pset);
376  }
377  desc.addVPSet("decayModes", vpset_decayModes, vpset_default);
378  }
379 
380  desc.add<double>("matchingCone", 0.5);
381  desc.add<int>("minPixelHits", 1);
382  desc.add<bool>("requireTauChargedHadronsToBeChargedPFCands", false);
383  descriptions.add("hpsSelectionDiscriminator", desc);
384 }
385 
constexpr double deltaPhi(double phi1, double phi2)
Definition: deltaPhi.h:26
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:238
ParameterDescriptionBase * addVPSet(U const &iLabel, ParameterSetDescription const &validator, std::vector< ParameterSet > const &defaults)
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
reco::TrackRef trackRef() const
Definition: PFCandidate.cc:430
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
TkSoA const *__restrict__ CAHitNtupletGeneratorKernelsGPU::QualityCuts cuts
T sqrt(T t)
Definition: SSEVec.h:19
void addParameter(std::string const &name, T const &value)
Definition: ParameterSet.h:135
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
virtual const reco::Track & pseudoTrack() const
T const * get() const
Returns C++ pointer to the item.
Definition: Ref.h:232
ParameterDescriptionBase * add(U const &iLabel, T const &value)
Log< level::Warning, true > LogPrint
bool hasTrackDetails() const
Return true if a bestTrack can be extracted from this Candidate.
static const TrackGhostTrackState * getTrack(const BasicGhostTrackState *basic)
const HitPattern & hitPattern() const
Access the hit pattern, indicating in which Tracker layers the track has hits.
Definition: TrackBase.h:504
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
constexpr float correction(int sizeM1, int q_f, int q_l, uint16_t upper_edge_first_pix, uint16_t lower_edge_last_pix, float lorentz_shift, float theThickness, float cot_angle, float pitch, bool first_is_big, bool last_is_big)
void add(std::string const &label, ParameterSetDescription const &psetDescription)
math::XYZTLorentzVector LorentzVector
Lorentz vector.
Definition: Candidate.h:36
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:41
reco::GsfTrackRef gsfTrackRef() const
Definition: PFCandidate.cc:462
int numberOfValidPixelHits() const
Definition: HitPattern.h:825
double discriminate(const reco::PFTauRef &) const override
virtual double phi() const =0
momentum azimuthal angle
virtual double eta() const =0
momentum pseudorapidity
virtual const LorentzVector & p4() const =0
four-momentum Lorentz vector