CMS 3D CMS Logo

DeepTauId.cc
Go to the documentation of this file.
1 /*
2  * \class DeepTauId
3  *
4  * Tau identification using Deep NN.
5  *
6  * \author Konstantin Androsov, INFN Pisa
7  */
8 
10 
11 namespace {
12 
13 struct dnn_inputs_2017v1 {
14  enum vars {
17  dxy, dxy_sig, dz, ip3d, ip3d_sig,
18  hasSecondaryVertex, flightLength_r, flightLength_dEta, flightLength_dPhi,
19  flightLength_sig, leadChargedHadrCand_pt, leadChargedHadrCand_dEta,
20  leadChargedHadrCand_dPhi, leadChargedHadrCand_mass, pt_weighted_deta_strip,
21  pt_weighted_dphi_strip, pt_weighted_dr_signal, pt_weighted_dr_iso,
22  leadingTrackNormChi2, e_ratio, gj_angle_diff, n_photons, emFraction,
23  has_gsf_track, inside_ecal_crack,
24  gsf_ele_matched, gsf_ele_pt, gsf_ele_dEta, gsf_ele_dPhi, gsf_ele_mass, gsf_ele_Ee,
25  gsf_ele_Egamma, gsf_ele_Pin, gsf_ele_Pout, gsf_ele_EtotOverPin, gsf_ele_Eecal,
26  gsf_ele_dEta_SeedClusterTrackAtCalo, gsf_ele_dPhi_SeedClusterTrackAtCalo, gsf_ele_mvaIn_sigmaEtaEta,
27  gsf_ele_mvaIn_hadEnergy,
28  gsf_ele_mvaIn_deltaEta, gsf_ele_Chi2NormGSF, gsf_ele_GSFNumHits, gsf_ele_GSFTrackResol,
29  gsf_ele_GSFTracklnPt, gsf_ele_Chi2NormKF, gsf_ele_KFNumHits,
30  leadChargedCand_etaAtEcalEntrance, leadChargedCand_pt, leadChargedHadrCand_HoP,
31  leadChargedHadrCand_EoP, tau_visMass_innerSigCone,
32  n_matched_muons, muon_pt, muon_dEta, muon_dPhi,
33  muon_n_matches_DT_1, muon_n_matches_DT_2, muon_n_matches_DT_3, muon_n_matches_DT_4,
34  muon_n_matches_CSC_1, muon_n_matches_CSC_2, muon_n_matches_CSC_3, muon_n_matches_CSC_4,
35  muon_n_hits_DT_2, muon_n_hits_DT_3, muon_n_hits_DT_4,
36  muon_n_hits_CSC_2, muon_n_hits_CSC_3, muon_n_hits_CSC_4,
37  muon_n_hits_RPC_2, muon_n_hits_RPC_3, muon_n_hits_RPC_4,
38  muon_n_stations_with_matches_03, muon_n_stations_with_hits_23,
39  signalChargedHadrCands_sum_innerSigCone_pt, signalChargedHadrCands_sum_innerSigCone_dEta,
40  signalChargedHadrCands_sum_innerSigCone_dPhi, signalChargedHadrCands_sum_innerSigCone_mass,
41  signalChargedHadrCands_sum_outerSigCone_pt, signalChargedHadrCands_sum_outerSigCone_dEta,
42  signalChargedHadrCands_sum_outerSigCone_dPhi, signalChargedHadrCands_sum_outerSigCone_mass,
43  signalChargedHadrCands_nTotal_innerSigCone, signalChargedHadrCands_nTotal_outerSigCone,
44  signalNeutrHadrCands_sum_innerSigCone_pt, signalNeutrHadrCands_sum_innerSigCone_dEta,
45  signalNeutrHadrCands_sum_innerSigCone_dPhi, signalNeutrHadrCands_sum_innerSigCone_mass,
46  signalNeutrHadrCands_sum_outerSigCone_pt, signalNeutrHadrCands_sum_outerSigCone_dEta,
47  signalNeutrHadrCands_sum_outerSigCone_dPhi, signalNeutrHadrCands_sum_outerSigCone_mass,
48  signalNeutrHadrCands_nTotal_innerSigCone, signalNeutrHadrCands_nTotal_outerSigCone,
49  signalGammaCands_sum_innerSigCone_pt, signalGammaCands_sum_innerSigCone_dEta,
50  signalGammaCands_sum_innerSigCone_dPhi, signalGammaCands_sum_innerSigCone_mass,
51  signalGammaCands_sum_outerSigCone_pt, signalGammaCands_sum_outerSigCone_dEta,
52  signalGammaCands_sum_outerSigCone_dPhi, signalGammaCands_sum_outerSigCone_mass,
53  signalGammaCands_nTotal_innerSigCone, signalGammaCands_nTotal_outerSigCone,
54  isolationChargedHadrCands_sum_pt, isolationChargedHadrCands_sum_dEta,
55  isolationChargedHadrCands_sum_dPhi, isolationChargedHadrCands_sum_mass,
56  isolationChargedHadrCands_nTotal,
57  isolationNeutrHadrCands_sum_pt, isolationNeutrHadrCands_sum_dEta,
58  isolationNeutrHadrCands_sum_dPhi, isolationNeutrHadrCands_sum_mass,
59  isolationNeutrHadrCands_nTotal,
60  isolationGammaCands_sum_pt, isolationGammaCands_sum_dEta,
61  isolationGammaCands_sum_dPhi, isolationGammaCands_sum_mass,
62  isolationGammaCands_nTotal,
63  NumberOfInputs
64  };
65 
66  static constexpr int NumberOfOutputs = 4;
67 };
68 
69 template<typename LVector1, typename LVector2>
70 float dEta(const LVector1& p4, const LVector2& tau_p4)
71 {
72  return static_cast<float>(p4.eta() - tau_p4.eta());
73 }
74 
75 template<typename LVector1, typename LVector2>
76 float dPhi(const LVector1& p4, const LVector2& tau_p4)
77 {
78  return static_cast<float>(ROOT::Math::VectorUtil::DeltaPhi(p4, tau_p4));
79 }
80 
81 namespace MuonSubdetId {
82  enum { DT = 1, CSC = 2, RPC = 3, GEM = 4, ME0 = 5 };
83 }
84 
85 struct MuonHitMatch {
86  static constexpr int n_muon_stations = 4;
87 
88  std::map<int, std::vector<UInt_t>> n_matches, n_hits;
89  unsigned n_muons{0};
90  const pat::Muon* best_matched_muon{nullptr};
91  double deltaR2_best_match{-1};
92 
93  MuonHitMatch()
94  {
95  n_matches[MuonSubdetId::DT].assign(n_muon_stations, 0);
96  n_matches[MuonSubdetId::CSC].assign(n_muon_stations, 0);
97  n_matches[MuonSubdetId::RPC].assign(n_muon_stations, 0);
98  n_hits[MuonSubdetId::DT].assign(n_muon_stations, 0);
99  n_hits[MuonSubdetId::CSC].assign(n_muon_stations, 0);
100  n_hits[MuonSubdetId::RPC].assign(n_muon_stations, 0);
101  }
102 
103  void addMatchedMuon(const pat::Muon& muon, const pat::Tau& tau)
104  {
105  static constexpr int n_stations = 4;
106 
107  ++n_muons;
108  const double dR2 = reco::deltaR2(tau.p4(), muon.p4());
109  if(!best_matched_muon || dR2 < deltaR2_best_match) {
110  best_matched_muon = &muon;
111  deltaR2_best_match = dR2;
112  }
113 
114  for(const auto& segment : muon.matches()) {
115  if(segment.segmentMatches.empty()) continue;
116  if(n_matches.count(segment.detector()))
117  ++n_matches.at(segment.detector()).at(segment.station() - 1);
118  }
119 
120  if(muon.outerTrack().isNonnull()) {
121  const auto& hit_pattern = muon.outerTrack()->hitPattern();
122  for(int hit_index = 0; hit_index < hit_pattern.numberOfAllHits(reco::HitPattern::TRACK_HITS); ++hit_index) {
123  auto hit_id = hit_pattern.getHitPattern(reco::HitPattern::TRACK_HITS, hit_index);
124  if(hit_id == 0) break;
125  if(hit_pattern.muonHitFilter(hit_id) && (hit_pattern.getHitType(hit_id) == TrackingRecHit::valid
126  || hit_pattern.getHitType(hit_id == TrackingRecHit::bad))) {
127  const int station = hit_pattern.getMuonStation(hit_id) - 1;
128  if(station > 0 && station < n_stations) {
129  std::vector<UInt_t>* muon_n_hits = nullptr;
130  if(hit_pattern.muonDTHitFilter(hit_id))
131  muon_n_hits = &n_hits.at(MuonSubdetId::DT);
132  else if(hit_pattern.muonCSCHitFilter(hit_id))
133  muon_n_hits = &n_hits.at(MuonSubdetId::CSC);
134  else if(hit_pattern.muonRPCHitFilter(hit_id))
135  muon_n_hits = &n_hits.at(MuonSubdetId::RPC);
136 
137  if(muon_n_hits)
138  ++muon_n_hits->at(station);
139  }
140  }
141  }
142  }
143  }
144 
145  static std::vector<const pat::Muon*> findMatchedMuons(const pat::Tau& tau, const pat::MuonCollection& muons,
146  double deltaR, double minPt)
147  {
148  const reco::Muon* hadr_cand_muon = nullptr;
149  if(tau.leadPFChargedHadrCand().isNonnull() && tau.leadPFChargedHadrCand()->muonRef().isNonnull())
150  hadr_cand_muon = tau.leadPFChargedHadrCand()->muonRef().get();
151  std::vector<const pat::Muon*> matched_muons;
152  const double dR2 = deltaR*deltaR;
153  for(const pat::Muon& muon : muons) {
154  const reco::Muon* reco_muon = &muon;
155  if(muon.pt() <= minPt) continue;
156  if(reco_muon == hadr_cand_muon) continue;
157  if(reco::deltaR2(tau.p4(), muon.p4()) >= dR2) continue;
158  matched_muons.push_back(&muon);
159  }
160  return matched_muons;
161  }
162 
163  template<typename dnn, typename TensorElemGet>
164  void fillTensor(const TensorElemGet& get, const pat::Tau& tau, float default_value) const
165  {
166  get(dnn::n_matched_muons) = n_muons;
167  get(dnn::muon_pt) = best_matched_muon != nullptr ? best_matched_muon->p4().pt() : default_value;
168  get(dnn::muon_dEta) = best_matched_muon != nullptr
169  ? dEta(best_matched_muon->p4(), tau.p4()) : default_value;
170  get(dnn::muon_dPhi) = best_matched_muon != nullptr
171  ? dPhi(best_matched_muon->p4(), tau.p4()) : default_value;
172  get(dnn::muon_n_matches_DT_1) = n_matches.at(MuonSubdetId::DT).at(0);
173  get(dnn::muon_n_matches_DT_2) = n_matches.at(MuonSubdetId::DT).at(1);
174  get(dnn::muon_n_matches_DT_3) = n_matches.at(MuonSubdetId::DT).at(2);
175  get(dnn::muon_n_matches_DT_4) = n_matches.at(MuonSubdetId::DT).at(3);
176  get(dnn::muon_n_matches_CSC_1) = n_matches.at(MuonSubdetId::CSC).at(0);
177  get(dnn::muon_n_matches_CSC_2) = n_matches.at(MuonSubdetId::CSC).at(1);
178  get(dnn::muon_n_matches_CSC_3) = n_matches.at(MuonSubdetId::CSC).at(2);
179  get(dnn::muon_n_matches_CSC_4) = n_matches.at(MuonSubdetId::CSC).at(3);
180  get(dnn::muon_n_hits_DT_2) = n_hits.at(MuonSubdetId::DT).at(1);
181  get(dnn::muon_n_hits_DT_3) = n_hits.at(MuonSubdetId::DT).at(2);
182  get(dnn::muon_n_hits_DT_4) = n_hits.at(MuonSubdetId::DT).at(3);
183  get(dnn::muon_n_hits_CSC_2) = n_hits.at(MuonSubdetId::CSC).at(1);
184  get(dnn::muon_n_hits_CSC_3) = n_hits.at(MuonSubdetId::CSC).at(2);
185  get(dnn::muon_n_hits_CSC_4) = n_hits.at(MuonSubdetId::CSC).at(3);
186  get(dnn::muon_n_hits_RPC_2) = n_hits.at(MuonSubdetId::RPC).at(1);
187  get(dnn::muon_n_hits_RPC_3) = n_hits.at(MuonSubdetId::RPC).at(2);
188  get(dnn::muon_n_hits_RPC_4) = n_hits.at(MuonSubdetId::RPC).at(3);
189  get(dnn::muon_n_stations_with_matches_03) = countMuonStationsWithMatches(0, 3);
190  get(dnn::muon_n_stations_with_hits_23) = countMuonStationsWithHits(2, 3);
191  }
192 
193 private:
194  unsigned countMuonStationsWithMatches(size_t first_station, size_t last_station) const
195  {
196  static const std::map<int, std::vector<bool>> masks = {
197  { MuonSubdetId::DT, { false, false, false, false } },
198  { MuonSubdetId::CSC, { true, false, false, false } },
199  { MuonSubdetId::RPC, { false, false, false, false } },
200  };
201  unsigned cnt = 0;
202  for(unsigned n = first_station; n <= last_station; ++n) {
203  for(const auto& match : n_matches) {
204  if(!masks.at(match.first).at(n) && match.second.at(n) > 0) ++cnt;
205  }
206  }
207  return cnt;
208  }
209 
210  unsigned countMuonStationsWithHits(size_t first_station, size_t last_station) const
211  {
212  static const std::map<int, std::vector<bool>> masks = {
213  { MuonSubdetId::DT, { false, false, false, false } },
214  { MuonSubdetId::CSC, { false, false, false, false } },
215  { MuonSubdetId::RPC, { false, false, false, false } },
216  };
217 
218  unsigned cnt = 0;
219  for(unsigned n = first_station; n <= last_station; ++n) {
220  for(const auto& hit : n_hits) {
221  if(!masks.at(hit.first).at(n) && hit.second.at(n) > 0) ++cnt;
222  }
223  }
224  return cnt;
225  }
226 };
227 
228 } // anonymous namespace
229 
231 public:
232 
233  static constexpr float default_value = -999.;
234 
235  static const OutputCollection& GetOutputs()
236  {
237  static constexpr size_t e_index = 0, mu_index = 1, tau_index = 2, jet_index = 3;
238  static const OutputCollection outputs_ = {
239  { "VSe", Output({tau_index}, {e_index, tau_index}) },
240  { "VSmu", Output({tau_index}, {mu_index, tau_index}) },
241  { "VSjet", Output({tau_index}, {jet_index, tau_index}) },
242  };
243  return outputs_;
244  }
245 
247  {
249  desc.add<edm::InputTag>("electrons", edm::InputTag("slimmedElectrons"));
250  desc.add<edm::InputTag>("muons", edm::InputTag("slimmedMuons"));
251  desc.add<edm::InputTag>("taus", edm::InputTag("slimmedTaus"));
252  desc.add<std::string>("graph_file", "RecoTauTag/TrainingFiles/data/DeepTauId/deepTau_2017v1_20L1024N_quantized.pb");
253  desc.add<bool>("mem_mapped", false);
254 
256  descWP.add<std::string>("VVVLoose", "0");
257  descWP.add<std::string>("VVLoose", "0");
258  descWP.add<std::string>("VLoose", "0");
259  descWP.add<std::string>("Loose", "0");
260  descWP.add<std::string>("Medium", "0");
261  descWP.add<std::string>("Tight", "0");
262  descWP.add<std::string>("VTight", "0");
263  descWP.add<std::string>("VVTight", "0");
264  descWP.add<std::string>("VVVTight", "0");
265  desc.add<edm::ParameterSetDescription>("VSeWP", descWP);
266  desc.add<edm::ParameterSetDescription>("VSmuWP", descWP);
267  desc.add<edm::ParameterSetDescription>("VSjetWP", descWP);
268  descriptions.add("DeepTau2017v1", desc);
269  }
270 
271 public:
273  DeepTauBase(cfg, GetOutputs(), cache),
274  electrons_token(consumes<ElectronCollection>(cfg.getParameter<edm::InputTag>("electrons"))),
275  muons_token(consumes<MuonCollection>(cfg.getParameter<edm::InputTag>("muons"))),
276  input_layer(cache_->getGraph().node(0).name()),
277  output_layer(cache_->getGraph().node(cache_->getGraph().node_size() - 1).name())
278  {
279  const auto& shape = cache_->getGraph().node(0).attr().at("shape").shape();
280  if(shape.dim(1).size() != dnn_inputs_2017v1::NumberOfInputs)
281  throw cms::Exception("DeepTauId") << "number of inputs does not match the expected inputs for the given version";
282 
283  }
284 
285  static std::unique_ptr<deep_tau::DeepTauCache> initializeGlobalCache(const edm::ParameterSet& cfg)
286  {
287  return DeepTauBase::initializeGlobalCache(cfg);
288  }
289 
290  static void globalEndJob(const deep_tau::DeepTauCache* cache_)
291  {
292  return DeepTauBase::globalEndJob(cache_);
293  }
294 
295 private:
296  tensorflow::Tensor getPredictions(edm::Event& event, const edm::EventSetup& es,
298  {
300  event.getByToken(electrons_token, electrons);
301 
303  event.getByToken(muons_token, muons);
304 
305  tensorflow::Tensor predictions(tensorflow::DT_FLOAT, { static_cast<int>(taus->size()),
306  dnn_inputs_2017v1::NumberOfOutputs});
307  for(size_t tau_index = 0; tau_index < taus->size(); ++tau_index) {
308  const tensorflow::Tensor& inputs = createInputs<dnn_inputs_2017v1>(taus->at(tau_index), *electrons, *muons);
309  std::vector<tensorflow::Tensor> pred_vector;
310  tensorflow::run(&(cache_->getSession()), { { input_layer, inputs } }, { output_layer }, &pred_vector);
311  for(int k = 0; k < dnn_inputs_2017v1::NumberOfOutputs; ++k)
312  predictions.matrix<float>()(tau_index, k) = pred_vector[0].flat<float>()(k);
313  }
314  return predictions;
315  }
316 
317  template<typename dnn>
318  tensorflow::Tensor createInputs(const TauType& tau, const ElectronCollection& electrons,
319  const MuonCollection& muons) const
320  {
321  static constexpr bool check_all_set = false;
322  static constexpr float default_value_for_set_check = -42;
323  static const TauIdMVAAuxiliaries clusterVariables;
324 
325  tensorflow::Tensor inputs(tensorflow::DT_FLOAT, { 1, dnn_inputs_2017v1::NumberOfInputs});
326  const auto& get = [&](int var_index) -> float& { return inputs.matrix<float>()(0, var_index); };
327  auto leadChargedHadrCand = dynamic_cast<const pat::PackedCandidate*>(tau.leadChargedHadrCand().get());
328 
329  if(check_all_set) {
330  for(int var_index = 0; var_index < dnn::NumberOfInputs; ++var_index) {
331  get(var_index) = default_value_for_set_check;
332  }
333  }
334 
335  get(dnn::pt) = tau.p4().pt();
336  get(dnn::eta) = tau.p4().eta();
337  get(dnn::mass) = tau.p4().mass();
338  get(dnn::decayMode) = tau.decayMode();
339  get(dnn::chargedIsoPtSum) = tau.tauID("chargedIsoPtSum");
340  get(dnn::neutralIsoPtSum) = tau.tauID("neutralIsoPtSum");
341  get(dnn::neutralIsoPtSumWeight) = tau.tauID("neutralIsoPtSumWeight");
342  get(dnn::photonPtSumOutsideSignalCone) = tau.tauID("photonPtSumOutsideSignalCone");
343  get(dnn::puCorrPtSum) = tau.tauID("puCorrPtSum");
344  get(dnn::dxy) = tau.dxy();
345  get(dnn::dxy_sig) = tau.dxy_Sig();
346  get(dnn::dz) = leadChargedHadrCand ? leadChargedHadrCand->dz() : default_value;
347  get(dnn::ip3d) = tau.ip3d();
348  get(dnn::ip3d_sig) = tau.ip3d_Sig();
349  get(dnn::hasSecondaryVertex) = tau.hasSecondaryVertex();
350  get(dnn::flightLength_r) = tau.flightLength().R();
351  get(dnn::flightLength_dEta) = dEta(tau.flightLength(), tau.p4());
352  get(dnn::flightLength_dPhi) = dPhi(tau.flightLength(), tau.p4());
353  get(dnn::flightLength_sig) = tau.flightLengthSig();
354  get(dnn::leadChargedHadrCand_pt) = leadChargedHadrCand ? leadChargedHadrCand->p4().Pt() : default_value;
355  get(dnn::leadChargedHadrCand_dEta) = leadChargedHadrCand
356  ? dEta(leadChargedHadrCand->p4(), tau.p4()) : default_value;
357  get(dnn::leadChargedHadrCand_dPhi) = leadChargedHadrCand
358  ? dPhi(leadChargedHadrCand->p4(), tau.p4()) : default_value;
359  get(dnn::leadChargedHadrCand_mass) = leadChargedHadrCand
360  ? leadChargedHadrCand->p4().mass() : default_value;
361  get(dnn::pt_weighted_deta_strip) = clusterVariables.tau_pt_weighted_deta_strip(tau, tau.decayMode());
362  get(dnn::pt_weighted_dphi_strip) = clusterVariables.tau_pt_weighted_dphi_strip(tau, tau.decayMode());
363  get(dnn::pt_weighted_dr_signal) = clusterVariables.tau_pt_weighted_dr_signal(tau, tau.decayMode());
364  get(dnn::pt_weighted_dr_iso) = clusterVariables.tau_pt_weighted_dr_iso(tau, tau.decayMode());
365  get(dnn::leadingTrackNormChi2) = tau.leadingTrackNormChi2();
366  get(dnn::e_ratio) = clusterVariables.tau_Eratio(tau);
367  get(dnn::gj_angle_diff) = calculateGottfriedJacksonAngleDifference(tau);
368  get(dnn::n_photons) = clusterVariables.tau_n_photons_total(tau);
369  get(dnn::emFraction) = tau.emFraction_MVA();
370  get(dnn::has_gsf_track) = leadChargedHadrCand && std::abs(leadChargedHadrCand->pdgId()) == 11;
371  get(dnn::inside_ecal_crack) = isInEcalCrack(tau.p4().Eta());
372  auto gsf_ele = findMatchedElectron(tau, electrons, 0.3);
373  get(dnn::gsf_ele_matched) = gsf_ele != nullptr;
374  get(dnn::gsf_ele_pt) = gsf_ele != nullptr ? gsf_ele->p4().Pt() : default_value;
375  get(dnn::gsf_ele_dEta) = gsf_ele != nullptr ? dEta(gsf_ele->p4(), tau.p4()) : default_value;
376  get(dnn::gsf_ele_dPhi) = gsf_ele != nullptr ? dPhi(gsf_ele->p4(), tau.p4()) : default_value;
377  get(dnn::gsf_ele_mass) = gsf_ele != nullptr ? gsf_ele->p4().mass() : default_value;
378  calculateElectronClusterVars(gsf_ele, get(dnn::gsf_ele_Ee), get(dnn::gsf_ele_Egamma));
379  get(dnn::gsf_ele_Pin) = gsf_ele != nullptr ? gsf_ele->trackMomentumAtVtx().R() : default_value;
380  get(dnn::gsf_ele_Pout) = gsf_ele != nullptr ? gsf_ele->trackMomentumOut().R() : default_value;
381  get(dnn::gsf_ele_EtotOverPin) = get(dnn::gsf_ele_Pin) > 0
382  ? (get(dnn::gsf_ele_Ee) + get(dnn::gsf_ele_Egamma)) / get(dnn::gsf_ele_Pin)
383  : default_value;
384  get(dnn::gsf_ele_Eecal) = gsf_ele != nullptr ? gsf_ele->ecalEnergy() : default_value;
385  get(dnn::gsf_ele_dEta_SeedClusterTrackAtCalo) = gsf_ele != nullptr
386  ? gsf_ele->deltaEtaSeedClusterTrackAtCalo() : default_value;
387  get(dnn::gsf_ele_dPhi_SeedClusterTrackAtCalo) = gsf_ele != nullptr
388  ? gsf_ele->deltaPhiSeedClusterTrackAtCalo() : default_value;
389  get(dnn::gsf_ele_mvaIn_sigmaEtaEta) = gsf_ele != nullptr
390  ? gsf_ele->mvaInput().sigmaEtaEta : default_value;
391  get(dnn::gsf_ele_mvaIn_hadEnergy) = gsf_ele != nullptr ? gsf_ele->mvaInput().hadEnergy : default_value;
392  get(dnn::gsf_ele_mvaIn_deltaEta) = gsf_ele != nullptr ? gsf_ele->mvaInput().deltaEta : default_value;
393 
394  get(dnn::gsf_ele_Chi2NormGSF) = default_value;
395  get(dnn::gsf_ele_GSFNumHits) = default_value;
396  get(dnn::gsf_ele_GSFTrackResol) = default_value;
397  get(dnn::gsf_ele_GSFTracklnPt) = default_value;
398  if(gsf_ele != nullptr && gsf_ele->gsfTrack().isNonnull()) {
399  get(dnn::gsf_ele_Chi2NormGSF) = gsf_ele->gsfTrack()->normalizedChi2();
400  get(dnn::gsf_ele_GSFNumHits) = gsf_ele->gsfTrack()->numberOfValidHits();
401  if(gsf_ele->gsfTrack()->pt() > 0) {
402  get(dnn::gsf_ele_GSFTrackResol) = gsf_ele->gsfTrack()->ptError() / gsf_ele->gsfTrack()->pt();
403  get(dnn::gsf_ele_GSFTracklnPt) = std::log10(gsf_ele->gsfTrack()->pt());
404  }
405  }
406 
407  get(dnn::gsf_ele_Chi2NormKF) = default_value;
408  get(dnn::gsf_ele_KFNumHits) = default_value;
409  if(gsf_ele != nullptr && gsf_ele->closestCtfTrackRef().isNonnull()) {
410  get(dnn::gsf_ele_Chi2NormKF) = gsf_ele->closestCtfTrackRef()->normalizedChi2();
411  get(dnn::gsf_ele_KFNumHits) = gsf_ele->closestCtfTrackRef()->numberOfValidHits();
412  }
413  get(dnn::leadChargedCand_etaAtEcalEntrance) = tau.etaAtEcalEntranceLeadChargedCand();
414  get(dnn::leadChargedCand_pt) = tau.ptLeadChargedCand();
415 
416  get(dnn::leadChargedHadrCand_HoP) = default_value;
417  get(dnn::leadChargedHadrCand_EoP) = default_value;
418  if(tau.leadChargedHadrCand()->pt() > 0) {
419  get(dnn::leadChargedHadrCand_HoP) = tau.hcalEnergyLeadChargedHadrCand()
420  / tau.leadChargedHadrCand()->pt();
421  get(dnn::leadChargedHadrCand_EoP) = tau.ecalEnergyLeadChargedHadrCand()
422  / tau.leadChargedHadrCand()->pt();
423  }
424 
425  MuonHitMatch muon_hit_match;
426  if(tau.leadPFChargedHadrCand().isNonnull() && tau.leadPFChargedHadrCand()->muonRef().isNonnull())
427  muon_hit_match.addMatchedMuon(*tau.leadPFChargedHadrCand()->muonRef(), tau);
428 
429  auto matched_muons = muon_hit_match.findMatchedMuons(tau, muons, 0.3, 5);
430  for(auto muon : matched_muons)
431  muon_hit_match.addMatchedMuon(*muon, tau);
432  muon_hit_match.fillTensor<dnn>(get, tau, default_value);
433 
434  LorentzVectorXYZ signalChargedHadrCands_sumIn, signalChargedHadrCands_sumOut;
435  processSignalPFComponents(tau, tau.signalChargedHadrCands(),
436  signalChargedHadrCands_sumIn, signalChargedHadrCands_sumOut,
437  get(dnn::signalChargedHadrCands_sum_innerSigCone_pt),
438  get(dnn::signalChargedHadrCands_sum_innerSigCone_dEta),
439  get(dnn::signalChargedHadrCands_sum_innerSigCone_dPhi),
440  get(dnn::signalChargedHadrCands_sum_innerSigCone_mass),
441  get(dnn::signalChargedHadrCands_sum_outerSigCone_pt),
442  get(dnn::signalChargedHadrCands_sum_outerSigCone_dEta),
443  get(dnn::signalChargedHadrCands_sum_outerSigCone_dPhi),
444  get(dnn::signalChargedHadrCands_sum_outerSigCone_mass),
445  get(dnn::signalChargedHadrCands_nTotal_innerSigCone),
446  get(dnn::signalChargedHadrCands_nTotal_outerSigCone));
447 
448  LorentzVectorXYZ signalNeutrHadrCands_sumIn, signalNeutrHadrCands_sumOut;
449  processSignalPFComponents(tau, tau.signalNeutrHadrCands(),
450  signalNeutrHadrCands_sumIn, signalNeutrHadrCands_sumOut,
451  get(dnn::signalNeutrHadrCands_sum_innerSigCone_pt),
452  get(dnn::signalNeutrHadrCands_sum_innerSigCone_dEta),
453  get(dnn::signalNeutrHadrCands_sum_innerSigCone_dPhi),
454  get(dnn::signalNeutrHadrCands_sum_innerSigCone_mass),
455  get(dnn::signalNeutrHadrCands_sum_outerSigCone_pt),
456  get(dnn::signalNeutrHadrCands_sum_outerSigCone_dEta),
457  get(dnn::signalNeutrHadrCands_sum_outerSigCone_dPhi),
458  get(dnn::signalNeutrHadrCands_sum_outerSigCone_mass),
459  get(dnn::signalNeutrHadrCands_nTotal_innerSigCone),
460  get(dnn::signalNeutrHadrCands_nTotal_outerSigCone));
461 
462 
463  LorentzVectorXYZ signalGammaCands_sumIn, signalGammaCands_sumOut;
464  processSignalPFComponents(tau, tau.signalGammaCands(),
465  signalGammaCands_sumIn, signalGammaCands_sumOut,
466  get(dnn::signalGammaCands_sum_innerSigCone_pt),
467  get(dnn::signalGammaCands_sum_innerSigCone_dEta),
468  get(dnn::signalGammaCands_sum_innerSigCone_dPhi),
469  get(dnn::signalGammaCands_sum_innerSigCone_mass),
470  get(dnn::signalGammaCands_sum_outerSigCone_pt),
471  get(dnn::signalGammaCands_sum_outerSigCone_dEta),
472  get(dnn::signalGammaCands_sum_outerSigCone_dPhi),
473  get(dnn::signalGammaCands_sum_outerSigCone_mass),
474  get(dnn::signalGammaCands_nTotal_innerSigCone),
475  get(dnn::signalGammaCands_nTotal_outerSigCone));
476 
477  LorentzVectorXYZ isolationChargedHadrCands_sum;
478  processIsolationPFComponents(tau, tau.isolationChargedHadrCands(), isolationChargedHadrCands_sum,
479  get(dnn::isolationChargedHadrCands_sum_pt),
480  get(dnn::isolationChargedHadrCands_sum_dEta),
481  get(dnn::isolationChargedHadrCands_sum_dPhi),
482  get(dnn::isolationChargedHadrCands_sum_mass),
483  get(dnn::isolationChargedHadrCands_nTotal));
484 
485  LorentzVectorXYZ isolationNeutrHadrCands_sum;
486  processIsolationPFComponents(tau, tau.isolationNeutrHadrCands(), isolationNeutrHadrCands_sum,
487  get(dnn::isolationNeutrHadrCands_sum_pt),
488  get(dnn::isolationNeutrHadrCands_sum_dEta),
489  get(dnn::isolationNeutrHadrCands_sum_dPhi),
490  get(dnn::isolationNeutrHadrCands_sum_mass),
491  get(dnn::isolationNeutrHadrCands_nTotal));
492 
493  LorentzVectorXYZ isolationGammaCands_sum;
494  processIsolationPFComponents(tau, tau.isolationGammaCands(), isolationGammaCands_sum,
495  get(dnn::isolationGammaCands_sum_pt),
496  get(dnn::isolationGammaCands_sum_dEta),
497  get(dnn::isolationGammaCands_sum_dPhi),
498  get(dnn::isolationGammaCands_sum_mass),
499  get(dnn::isolationGammaCands_nTotal));
500 
501  get(dnn::tau_visMass_innerSigCone) = (signalGammaCands_sumIn + signalChargedHadrCands_sumIn).mass();
502 
503  if(check_all_set) {
504  for(int var_index = 0; var_index < dnn::NumberOfInputs; ++var_index) {
505  if(get(var_index) == default_value_for_set_check)
506  throw cms::Exception("DeepTauId: variable with index = ") << var_index << " is not set.";
507  }
508  }
509 
510  return inputs;
511  }
512 
513  static void calculateElectronClusterVars(const pat::Electron* ele, float& elecEe, float& elecEgamma)
514  {
515  if(ele) {
516  elecEe = elecEgamma = 0;
517  auto superCluster = ele->superCluster();
518  if(superCluster.isNonnull() && superCluster.isAvailable() && superCluster->clusters().isNonnull()
519  && superCluster->clusters().isAvailable()) {
520  for(auto iter = superCluster->clustersBegin(); iter != superCluster->clustersEnd(); ++iter) {
521  const double energy = (*iter)->energy();
522  if(iter == superCluster->clustersBegin()) elecEe += energy;
523  else elecEgamma += energy;
524  }
525  }
526  } else {
527  elecEe = elecEgamma = default_value;
528  }
529  }
530 
531  template<typename CandidateCollection>
533  LorentzVectorXYZ& p4_inner, LorentzVectorXYZ& p4_outer,
534  float& pt_inner, float& dEta_inner, float& dPhi_inner, float& m_inner,
535  float& pt_outer, float& dEta_outer, float& dPhi_outer, float& m_outer,
536  float& n_inner, float& n_outer)
537  {
538  p4_inner = LorentzVectorXYZ(0, 0, 0, 0);
539  p4_outer = LorentzVectorXYZ(0, 0, 0, 0);
540  n_inner = 0;
541  n_outer = 0;
542 
543  const double innerSigCone_radius = getInnerSignalConeRadius(tau.pt());
544  for(const auto& cand : candidates) {
545  const double dR = reco::deltaR(cand->p4(), tau.leadChargedHadrCand()->p4());
546  const bool isInside_innerSigCone = dR < innerSigCone_radius;
547  if(isInside_innerSigCone) {
548  p4_inner += cand->p4();
549  ++n_inner;
550  } else {
551  p4_outer += cand->p4();
552  ++n_outer;
553  }
554  }
555 
556  pt_inner = n_inner != 0 ? p4_inner.Pt() : default_value;
557  dEta_inner = n_inner != 0 ? dEta(p4_inner, tau.p4()) : default_value;
558  dPhi_inner = n_inner != 0 ? dPhi(p4_inner, tau.p4()) : default_value;
559  m_inner = n_inner != 0 ? p4_inner.mass() : default_value;
560 
561  pt_outer = n_outer != 0 ? p4_outer.Pt() : default_value;
562  dEta_outer = n_outer != 0 ? dEta(p4_outer, tau.p4()) : default_value;
563  dPhi_outer = n_outer != 0 ? dPhi(p4_outer, tau.p4()) : default_value;
564  m_outer = n_outer != 0 ? p4_outer.mass() : default_value;
565  }
566 
567  template<typename CandidateCollection>
569  LorentzVectorXYZ& p4, float& pt, float& d_eta, float& d_phi, float& m,
570  float& n)
571  {
572  p4 = LorentzVectorXYZ(0, 0, 0, 0);
573  n = 0;
574 
575  for(const auto& cand : candidates) {
576  p4 += cand->p4();
577  ++n;
578  }
579 
580  pt = n != 0 ? p4.Pt() : default_value;
581  d_eta = n != 0 ? dEta(p4, tau.p4()) : default_value;
582  d_phi = n != 0 ? dPhi(p4, tau.p4()) : default_value;
583  m = n != 0 ? p4.mass() : default_value;
584  }
585 
586  static double getInnerSignalConeRadius(double pt)
587  {
588  static constexpr double min_pt = 30., min_radius = 0.05, cone_opening_coef = 3.;
589  // This is equivalent of the original formula (std::max(std::min(0.1, 3.0/pt), 0.05)
590  return std::max(cone_opening_coef / std::max(pt, min_pt), min_radius);
591  }
592 
593  // Copied from https://github.com/cms-sw/cmssw/blob/CMSSW_9_4_X/RecoTauTag/RecoTau/plugins/PATTauDiscriminationByMVAIsolationRun2.cc#L218
595  {
596  if(tau.decayMode() == 10) {
597  static constexpr double mTau = 1.77682;
598  const double mAOne = tau.p4().M();
599  const double pAOneMag = tau.p();
600  const double argumentThetaGJmax = (std::pow(mTau,2) - std::pow(mAOne,2) ) / ( 2 * mTau * pAOneMag );
601  const double argumentThetaGJmeasured = tau.p4().Vect().Dot(tau.flightLength())
602  / ( pAOneMag * tau.flightLength().R() );
603  if ( std::abs(argumentThetaGJmax) <= 1. && std::abs(argumentThetaGJmeasured) <= 1. ) {
604  double thetaGJmax = std::asin( argumentThetaGJmax );
605  double thetaGJmeasured = std::acos( argumentThetaGJmeasured );
606  return thetaGJmeasured - thetaGJmax;
607  }
608  }
609  return default_value;
610  }
611 
612  static bool isInEcalCrack(double eta)
613  {
614  const double abs_eta = std::abs(eta);
615  return abs_eta > 1.46 && abs_eta < 1.558;
616  }
617 
619  double deltaR)
620  {
621  const double dR2 = deltaR*deltaR;
622  const pat::Electron* matched_ele = nullptr;
623  for(const auto& ele : electrons) {
624  if(reco::deltaR2(tau.p4(), ele.p4()) < dR2 && (!matched_ele || matched_ele->pt() < ele.pt())) {
625  matched_ele = &ele;
626  }
627  }
628  return matched_ele;
629  }
630 
631 private:
634  std::string input_layer, output_layer;
635 };
636 
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
Definition: DeepTauId.cc:246
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:253
float tau_Eratio(const reco::PFTau &tau) const
return ratio of energy in ECAL over sum of energy in ECAL and HCAL
static std::unique_ptr< deep_tau::DeepTauCache > initializeGlobalCache(const edm::ParameterSet &cfg)
Definition: DeepTauId.cc:285
float hcalEnergyLeadChargedHadrCand() const
return hcal energy from LeadChargedHadrCand
Definition: Tau.h:345
float dxy() const
Definition: Tau.h:314
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:17
T const * get() const
Returns C++ pointer to the item.
Definition: Ptr.h:159
static double getInnerSignalConeRadius(double pt)
Definition: DeepTauId.cc:586
edm::EDGetTokenT< ElectronCollection > electrons_token
Definition: DeepTauId.cc:632
const reco::PFCandidatePtr leadPFChargedHadrCand() const
static bool isInEcalCrack(double eta)
Definition: DeepTauId.cc:612
double pt() const final
transverse momentum
static void processIsolationPFComponents(const pat::Tau &tau, const CandidateCollection &candidates, LorentzVectorXYZ &p4, float &pt, float &d_eta, float &d_phi, float &m, float &n)
Definition: DeepTauId.cc:568
float ip3d_Sig() const
float tauID(const std::string &name) const
std::map< std::string, Output > OutputCollection
Definition: DeepTauBase.h:82
#define constexpr
static const OutputCollection & GetOutputs()
Definition: DeepTauId.cc:235
DeepTauId(const edm::ParameterSet &cfg, const deep_tau::DeepTauCache *cache)
Definition: DeepTauId.cc:272
static const int CSC
Definition: MuonSubdetId.h:13
std::vector< Electron > ElectronCollection
Definition: Electron.h:37
reco::TrackRef outerTrack() const override
reference to Track reconstructed in the muon detector only (reimplemented from reco::Muon) ...
Definition: Muon.h:77
static float calculateGottfriedJacksonAngleDifference(const pat::Tau &tau)
Definition: DeepTauId.cc:594
float ip3d() const
Definition: Tau.h:327
double p4[4]
Definition: TauolaWrapper.h:92
const pat::tau::TauPFEssential::Vector & flightLength() const
Definition: Tau.h:321
float tau_pt_weighted_dphi_strip(const reco::PFTau &tau, int dm) const
float ecalEnergyLeadChargedHadrCand() const
Definition: Tau.h:343
pat::ElectronCollection ElectronCollection
Definition: DeepTauBase.h:65
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
auto deltaR(const T1 &t1, const T2 &t2) -> decltype(t1.eta())
Definition: deltaR.h:28
const LorentzVector & p4() const final
four-momentum Lorentz vector
Definition: LeafCandidate.h:99
static void globalEndJob(const deep_tau::DeepTauCache *cache_)
Definition: DeepTauId.cc:290
bool hasSecondaryVertex() const
Definition: Tau.h:320
const reco::CandidatePtr leadChargedHadrCand() const
ParameterDescriptionBase * add(U const &iLabel, T const &value)
float tau_pt_weighted_dr_signal(const reco::PFTau &tau, int dm) const
Analysis-level tau class.
Definition: Tau.h:55
float tau_pt_weighted_dr_iso(const reco::PFTau &tau, int dm) const
def cache(function)
bool isNonnull() const
Checks for non-null.
Definition: Ptr.h:168
int k[5][pyjets_maxn]
double deltaR(double eta1, double eta2, double phi1, double phi2)
Definition: TreeUtility.cc:17
float ptLeadChargedCand() const
return pt from LeadChargedCand
Definition: Tau.h:353
tensorflow::Tensor getPredictions(edm::Event &event, const edm::EventSetup &es, edm::Handle< TauCollection > taus) override
Definition: DeepTauId.cc:296
double p() const final
magnitude of momentum vector
pat::MuonCollection MuonCollection
Definition: DeepTauBase.h:66
int decayMode() const
reconstructed tau decay mode (specific to PFTau)
Definition: Tau.h:365
float tau_pt_weighted_deta_strip(const reco::PFTau &tau, int dm) const
Analysis-level electron class.
Definition: Electron.h:52
std::vector< MuonChamberMatch > & matches()
get muon matching information
Definition: Muon.h:144
void add(std::string const &label, ParameterSetDescription const &psetDescription)
T1 deltaR2(T1 eta1, T2 phi1, T3 eta2, T4 phi2)
Definition: deltaR.h:36
std::vector< Muon > MuonCollection
Definition: Muon.h:34
static void processSignalPFComponents(const pat::Tau &tau, const CandidateCollection &candidates, LorentzVectorXYZ &p4_inner, LorentzVectorXYZ &p4_outer, float &pt_inner, float &dEta_inner, float &dPhi_inner, float &m_inner, float &pt_outer, float &dEta_outer, float &dPhi_outer, float &m_outer, float &n_inner, float &n_outer)
Definition: DeepTauId.cc:532
float emFraction_MVA() const
return emFraction_MVA
Definition: Tau.h:355
float flightLengthSig() const
Definition: Tau.h:322
float dxy_Sig() const
HLT enums.
constexpr uint32_t masks[]
Definition: CaloRecHit.cc:12
static const int RPC
Definition: MuonSubdetId.h:14
#define Output(cl)
Definition: vmac.h:192
float leadingTrackNormChi2() const
return normalized chi2 of leading track
Definition: Tau.h:338
static const pat::Electron * findMatchedElectron(const pat::Tau &tau, const pat::ElectronCollection &electrons, double deltaR)
Definition: DeepTauId.cc:618
void run(Session *session, const NamedTensorList &inputs, const std::vector< std::string > &outputNames, const std::vector< std::string > &targetNodes, std::vector< Tensor > *outputs)
Definition: TensorFlow.cc:210
static const int DT
Definition: MuonSubdetId.h:12
std::pair< typename Association::data_type::first_type, double > match(Reference key, Association association, bool bestMatchByMaxValue)
Generic matching function.
Definition: Utils.h:10
float etaAtEcalEntranceLeadChargedCand() const
return etaAtEcalEntrance from LeadChargedCand
Definition: Tau.h:351
edm::OwnVector< Candidate > CandidateCollection
collection of Candidate objects
Definition: CandidateFwd.h:21
static void calculateElectronClusterVars(const pat::Electron *ele, float &elecEe, float &elecEgamma)
Definition: DeepTauId.cc:513
tensorflow::Tensor createInputs(const TauType &tau, const ElectronCollection &electrons, const MuonCollection &muons) const
Definition: DeepTauId.cc:318
edm::EDGetTokenT< MuonCollection > muons_token
Definition: DeepTauId.cc:633
Analysis-level muon class.
Definition: Muon.h:50
ROOT::Math::LorentzVector< ROOT::Math::PxPyPzE4D< double >> LorentzVectorXYZ
Definition: DeepTauBase.h:67
reco::SuperClusterRef superCluster() const override
override the reco::GsfElectron::superCluster method, to access the internal storage of the superclust...
std::string output_layer
Definition: DeepTauId.cc:634
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
Definition: event.py:1
unsigned int tau_n_photons_total(const reco::PFTau &tau) const
return total number of pf photon candidates with pT>500 MeV, which are associated to signal ...