CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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  * Christian Veelken, Tallinn
8  */
9 
14 
15 #include <fstream>
16 #include "oneapi/tbb/concurrent_unordered_set.h"
17 
18 namespace deep_tau {
19  constexpr int NumberOfOutputs = 4;
20 }
21 
22 namespace {
23 
24  struct dnn_inputs_2017v1 {
25  enum vars {
26  pt = 0,
27  eta,
28  mass,
29  decayMode,
30  chargedIsoPtSum,
31  neutralIsoPtSum,
32  neutralIsoPtSumWeight,
33  photonPtSumOutsideSignalCone,
34  puCorrPtSum,
35  dxy,
36  dxy_sig,
37  dz,
38  ip3d,
39  ip3d_sig,
40  hasSecondaryVertex,
41  flightLength_r,
42  flightLength_dEta,
43  flightLength_dPhi,
44  flightLength_sig,
45  leadChargedHadrCand_pt,
46  leadChargedHadrCand_dEta,
47  leadChargedHadrCand_dPhi,
48  leadChargedHadrCand_mass,
53  leadingTrackNormChi2,
54  e_ratio,
55  gj_angle_diff,
56  n_photons,
57  emFraction,
58  has_gsf_track,
59  inside_ecal_crack,
60  gsf_ele_matched,
61  gsf_ele_pt,
62  gsf_ele_dEta,
63  gsf_ele_dPhi,
64  gsf_ele_mass,
65  gsf_ele_Ee,
66  gsf_ele_Egamma,
67  gsf_ele_Pin,
68  gsf_ele_Pout,
69  gsf_ele_EtotOverPin,
70  gsf_ele_Eecal,
71  gsf_ele_dEta_SeedClusterTrackAtCalo,
72  gsf_ele_dPhi_SeedClusterTrackAtCalo,
73  gsf_ele_mvaIn_sigmaEtaEta,
74  gsf_ele_mvaIn_hadEnergy,
75  gsf_ele_mvaIn_deltaEta,
76  gsf_ele_Chi2NormGSF,
77  gsf_ele_GSFNumHits,
78  gsf_ele_GSFTrackResol,
79  gsf_ele_GSFTracklnPt,
80  gsf_ele_Chi2NormKF,
81  gsf_ele_KFNumHits,
82  leadChargedCand_etaAtEcalEntrance,
83  leadChargedCand_pt,
84  leadChargedHadrCand_HoP,
85  leadChargedHadrCand_EoP,
86  tau_visMass_innerSigCone,
87  n_matched_muons,
88  muon_pt,
89  muon_dEta,
90  muon_dPhi,
91  muon_n_matches_DT_1,
92  muon_n_matches_DT_2,
93  muon_n_matches_DT_3,
94  muon_n_matches_DT_4,
95  muon_n_matches_CSC_1,
96  muon_n_matches_CSC_2,
97  muon_n_matches_CSC_3,
98  muon_n_matches_CSC_4,
99  muon_n_hits_DT_2,
100  muon_n_hits_DT_3,
101  muon_n_hits_DT_4,
102  muon_n_hits_CSC_2,
103  muon_n_hits_CSC_3,
104  muon_n_hits_CSC_4,
105  muon_n_hits_RPC_2,
106  muon_n_hits_RPC_3,
107  muon_n_hits_RPC_4,
108  muon_n_stations_with_matches_03,
109  muon_n_stations_with_hits_23,
110  signalChargedHadrCands_sum_innerSigCone_pt,
111  signalChargedHadrCands_sum_innerSigCone_dEta,
112  signalChargedHadrCands_sum_innerSigCone_dPhi,
113  signalChargedHadrCands_sum_innerSigCone_mass,
114  signalChargedHadrCands_sum_outerSigCone_pt,
115  signalChargedHadrCands_sum_outerSigCone_dEta,
116  signalChargedHadrCands_sum_outerSigCone_dPhi,
117  signalChargedHadrCands_sum_outerSigCone_mass,
118  signalChargedHadrCands_nTotal_innerSigCone,
119  signalChargedHadrCands_nTotal_outerSigCone,
120  signalNeutrHadrCands_sum_innerSigCone_pt,
121  signalNeutrHadrCands_sum_innerSigCone_dEta,
122  signalNeutrHadrCands_sum_innerSigCone_dPhi,
123  signalNeutrHadrCands_sum_innerSigCone_mass,
124  signalNeutrHadrCands_sum_outerSigCone_pt,
125  signalNeutrHadrCands_sum_outerSigCone_dEta,
126  signalNeutrHadrCands_sum_outerSigCone_dPhi,
127  signalNeutrHadrCands_sum_outerSigCone_mass,
128  signalNeutrHadrCands_nTotal_innerSigCone,
129  signalNeutrHadrCands_nTotal_outerSigCone,
130  signalGammaCands_sum_innerSigCone_pt,
131  signalGammaCands_sum_innerSigCone_dEta,
132  signalGammaCands_sum_innerSigCone_dPhi,
133  signalGammaCands_sum_innerSigCone_mass,
134  signalGammaCands_sum_outerSigCone_pt,
135  signalGammaCands_sum_outerSigCone_dEta,
136  signalGammaCands_sum_outerSigCone_dPhi,
137  signalGammaCands_sum_outerSigCone_mass,
138  signalGammaCands_nTotal_innerSigCone,
139  signalGammaCands_nTotal_outerSigCone,
140  isolationChargedHadrCands_sum_pt,
141  isolationChargedHadrCands_sum_dEta,
142  isolationChargedHadrCands_sum_dPhi,
143  isolationChargedHadrCands_sum_mass,
144  isolationChargedHadrCands_nTotal,
145  isolationNeutrHadrCands_sum_pt,
146  isolationNeutrHadrCands_sum_dEta,
147  isolationNeutrHadrCands_sum_dPhi,
148  isolationNeutrHadrCands_sum_mass,
149  isolationNeutrHadrCands_nTotal,
150  isolationGammaCands_sum_pt,
151  isolationGammaCands_sum_dEta,
152  isolationGammaCands_sum_dPhi,
153  isolationGammaCands_sum_mass,
154  isolationGammaCands_nTotal,
155  NumberOfInputs
156  };
157  };
158 
159  namespace dnn_inputs_2017_v2 {
160  constexpr int number_of_inner_cell = 11;
161  constexpr int number_of_outer_cell = 21;
162  constexpr int number_of_conv_features = 64;
163  namespace TauBlockInputs {
164  enum vars {
165  rho = 0,
166  tau_pt,
167  tau_eta,
168  tau_phi,
169  tau_mass,
170  tau_E_over_pt,
171  tau_charge,
172  tau_n_charged_prongs,
173  tau_n_neutral_prongs,
174  chargedIsoPtSum,
175  chargedIsoPtSumdR03_over_dR05,
176  footprintCorrection,
177  neutralIsoPtSum,
178  neutralIsoPtSumWeight_over_neutralIsoPtSum,
179  neutralIsoPtSumWeightdR03_over_neutralIsoPtSum,
180  neutralIsoPtSumdR03_over_dR05,
181  photonPtSumOutsideSignalCone,
182  puCorrPtSum,
183  tau_dxy_pca_x,
184  tau_dxy_pca_y,
185  tau_dxy_pca_z,
186  tau_dxy_valid,
187  tau_dxy,
188  tau_dxy_sig,
189  tau_ip3d_valid,
190  tau_ip3d,
191  tau_ip3d_sig,
192  tau_dz,
193  tau_dz_sig_valid,
194  tau_dz_sig,
195  tau_flightLength_x,
196  tau_flightLength_y,
197  tau_flightLength_z,
198  tau_flightLength_sig,
199  tau_pt_weighted_deta_strip,
200  tau_pt_weighted_dphi_strip,
201  tau_pt_weighted_dr_signal,
202  tau_pt_weighted_dr_iso,
203  tau_leadingTrackNormChi2,
204  tau_e_ratio_valid,
205  tau_e_ratio,
206  tau_gj_angle_diff_valid,
207  tau_gj_angle_diff,
208  tau_n_photons,
209  tau_emFraction,
210  tau_inside_ecal_crack,
211  leadChargedCand_etaAtEcalEntrance_minus_tau_eta,
212  NumberOfInputs
213  };
214  }
215 
216  namespace EgammaBlockInputs {
217  enum vars {
218  rho = 0,
219  tau_pt,
220  tau_eta,
221  tau_inside_ecal_crack,
222  pfCand_ele_valid,
223  pfCand_ele_rel_pt,
224  pfCand_ele_deta,
225  pfCand_ele_dphi,
226  pfCand_ele_pvAssociationQuality,
227  pfCand_ele_puppiWeight,
228  pfCand_ele_charge,
229  pfCand_ele_lostInnerHits,
230  pfCand_ele_numberOfPixelHits,
231  pfCand_ele_vertex_dx,
232  pfCand_ele_vertex_dy,
233  pfCand_ele_vertex_dz,
234  pfCand_ele_vertex_dx_tauFL,
235  pfCand_ele_vertex_dy_tauFL,
236  pfCand_ele_vertex_dz_tauFL,
237  pfCand_ele_hasTrackDetails,
238  pfCand_ele_dxy,
239  pfCand_ele_dxy_sig,
240  pfCand_ele_dz,
241  pfCand_ele_dz_sig,
242  pfCand_ele_track_chi2_ndof,
243  pfCand_ele_track_ndof,
244  ele_valid,
245  ele_rel_pt,
246  ele_deta,
247  ele_dphi,
248  ele_cc_valid,
249  ele_cc_ele_rel_energy,
250  ele_cc_gamma_rel_energy,
251  ele_cc_n_gamma,
252  ele_rel_trackMomentumAtVtx,
253  ele_rel_trackMomentumAtCalo,
254  ele_rel_trackMomentumOut,
255  ele_rel_trackMomentumAtEleClus,
256  ele_rel_trackMomentumAtVtxWithConstraint,
257  ele_rel_ecalEnergy,
258  ele_ecalEnergy_sig,
259  ele_eSuperClusterOverP,
260  ele_eSeedClusterOverP,
261  ele_eSeedClusterOverPout,
262  ele_eEleClusterOverPout,
263  ele_deltaEtaSuperClusterTrackAtVtx,
264  ele_deltaEtaSeedClusterTrackAtCalo,
265  ele_deltaEtaEleClusterTrackAtCalo,
266  ele_deltaPhiEleClusterTrackAtCalo,
267  ele_deltaPhiSuperClusterTrackAtVtx,
268  ele_deltaPhiSeedClusterTrackAtCalo,
269  ele_mvaInput_earlyBrem,
270  ele_mvaInput_lateBrem,
271  ele_mvaInput_sigmaEtaEta,
272  ele_mvaInput_hadEnergy,
273  ele_mvaInput_deltaEta,
274  ele_gsfTrack_normalizedChi2,
275  ele_gsfTrack_numberOfValidHits,
276  ele_rel_gsfTrack_pt,
277  ele_gsfTrack_pt_sig,
278  ele_has_closestCtfTrack,
279  ele_closestCtfTrack_normalizedChi2,
280  ele_closestCtfTrack_numberOfValidHits,
281  pfCand_gamma_valid,
282  pfCand_gamma_rel_pt,
283  pfCand_gamma_deta,
284  pfCand_gamma_dphi,
285  pfCand_gamma_pvAssociationQuality,
286  pfCand_gamma_fromPV,
287  pfCand_gamma_puppiWeight,
288  pfCand_gamma_puppiWeightNoLep,
289  pfCand_gamma_lostInnerHits,
290  pfCand_gamma_numberOfPixelHits,
291  pfCand_gamma_vertex_dx,
292  pfCand_gamma_vertex_dy,
293  pfCand_gamma_vertex_dz,
294  pfCand_gamma_vertex_dx_tauFL,
295  pfCand_gamma_vertex_dy_tauFL,
296  pfCand_gamma_vertex_dz_tauFL,
297  pfCand_gamma_hasTrackDetails,
298  pfCand_gamma_dxy,
299  pfCand_gamma_dxy_sig,
300  pfCand_gamma_dz,
301  pfCand_gamma_dz_sig,
302  pfCand_gamma_track_chi2_ndof,
303  pfCand_gamma_track_ndof,
304  NumberOfInputs
305  };
306  }
307 
308  namespace MuonBlockInputs {
309  enum vars {
310  rho = 0,
311  tau_pt,
312  tau_eta,
313  tau_inside_ecal_crack,
314  pfCand_muon_valid,
315  pfCand_muon_rel_pt,
316  pfCand_muon_deta,
317  pfCand_muon_dphi,
318  pfCand_muon_pvAssociationQuality,
319  pfCand_muon_fromPV,
320  pfCand_muon_puppiWeight,
321  pfCand_muon_charge,
322  pfCand_muon_lostInnerHits,
323  pfCand_muon_numberOfPixelHits,
324  pfCand_muon_vertex_dx,
325  pfCand_muon_vertex_dy,
326  pfCand_muon_vertex_dz,
327  pfCand_muon_vertex_dx_tauFL,
328  pfCand_muon_vertex_dy_tauFL,
329  pfCand_muon_vertex_dz_tauFL,
330  pfCand_muon_hasTrackDetails,
331  pfCand_muon_dxy,
332  pfCand_muon_dxy_sig,
333  pfCand_muon_dz,
334  pfCand_muon_dz_sig,
335  pfCand_muon_track_chi2_ndof,
336  pfCand_muon_track_ndof,
337  muon_valid,
338  muon_rel_pt,
339  muon_deta,
340  muon_dphi,
341  muon_dxy,
342  muon_dxy_sig,
343  muon_normalizedChi2_valid,
344  muon_normalizedChi2,
345  muon_numberOfValidHits,
346  muon_segmentCompatibility,
347  muon_caloCompatibility,
348  muon_pfEcalEnergy_valid,
349  muon_rel_pfEcalEnergy,
350  muon_n_matches_DT_1,
351  muon_n_matches_DT_2,
352  muon_n_matches_DT_3,
353  muon_n_matches_DT_4,
354  muon_n_matches_CSC_1,
355  muon_n_matches_CSC_2,
356  muon_n_matches_CSC_3,
357  muon_n_matches_CSC_4,
358  muon_n_matches_RPC_1,
359  muon_n_matches_RPC_2,
360  muon_n_matches_RPC_3,
361  muon_n_matches_RPC_4,
362  muon_n_hits_DT_1,
363  muon_n_hits_DT_2,
364  muon_n_hits_DT_3,
365  muon_n_hits_DT_4,
366  muon_n_hits_CSC_1,
367  muon_n_hits_CSC_2,
368  muon_n_hits_CSC_3,
369  muon_n_hits_CSC_4,
370  muon_n_hits_RPC_1,
371  muon_n_hits_RPC_2,
372  muon_n_hits_RPC_3,
373  muon_n_hits_RPC_4,
374  NumberOfInputs
375  };
376  }
377 
378  namespace HadronBlockInputs {
379  enum vars {
380  rho = 0,
381  tau_pt,
382  tau_eta,
383  tau_inside_ecal_crack,
384  pfCand_chHad_valid,
385  pfCand_chHad_rel_pt,
386  pfCand_chHad_deta,
387  pfCand_chHad_dphi,
388  pfCand_chHad_leadChargedHadrCand,
389  pfCand_chHad_pvAssociationQuality,
390  pfCand_chHad_fromPV,
391  pfCand_chHad_puppiWeight,
392  pfCand_chHad_puppiWeightNoLep,
393  pfCand_chHad_charge,
394  pfCand_chHad_lostInnerHits,
395  pfCand_chHad_numberOfPixelHits,
396  pfCand_chHad_vertex_dx,
397  pfCand_chHad_vertex_dy,
398  pfCand_chHad_vertex_dz,
399  pfCand_chHad_vertex_dx_tauFL,
400  pfCand_chHad_vertex_dy_tauFL,
401  pfCand_chHad_vertex_dz_tauFL,
402  pfCand_chHad_hasTrackDetails,
403  pfCand_chHad_dxy,
404  pfCand_chHad_dxy_sig,
405  pfCand_chHad_dz,
406  pfCand_chHad_dz_sig,
407  pfCand_chHad_track_chi2_ndof,
408  pfCand_chHad_track_ndof,
409  pfCand_chHad_hcalFraction,
410  pfCand_chHad_rawCaloFraction,
411  pfCand_nHad_valid,
412  pfCand_nHad_rel_pt,
413  pfCand_nHad_deta,
414  pfCand_nHad_dphi,
415  pfCand_nHad_puppiWeight,
416  pfCand_nHad_puppiWeightNoLep,
417  pfCand_nHad_hcalFraction,
418  NumberOfInputs
419  };
420  }
421  } // namespace dnn_inputs_2017_v2
422 
423  float getTauID(const pat::Tau& tau, const std::string& tauID, float default_value = -999., bool assert_input = true) {
424  static tbb::concurrent_unordered_set<std::string> isFirstWarning;
425  if (tau.isTauIDAvailable(tauID)) {
426  return tau.tauID(tauID);
427  } else {
428  if (assert_input) {
429  throw cms::Exception("DeepTauId")
430  << "Exception in <getTauID>: No tauID '" << tauID << "' available in pat::Tau given as function argument.";
431  }
432  if (isFirstWarning.insert(tauID).second) {
433  edm::LogWarning("DeepTauID") << "Warning in <getTauID>: No tauID '" << tauID
434  << "' available in pat::Tau given as function argument."
435  << " Using default_value = " << default_value << " instead." << std::endl;
436  }
437  return default_value;
438  }
439  }
440 
441  struct TauFunc {
442  const reco::TauDiscriminatorContainer* basicTauDiscriminatorCollection;
443  const reco::TauDiscriminatorContainer* basicTauDiscriminatordR03Collection;
446 
448  std::map<BasicDiscr, size_t> indexMap;
449  std::map<BasicDiscr, size_t> indexMapdR03;
450 
451  const float getChargedIsoPtSum(const reco::PFTau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
452  return (*basicTauDiscriminatorCollection)[tau_ref].rawValues.at(indexMap.at(BasicDiscr::ChargedIsoPtSum));
453  }
454  const float getChargedIsoPtSum(const pat::Tau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
455  return getTauID(tau, "chargedIsoPtSum");
456  }
457  const float getChargedIsoPtSumdR03(const reco::PFTau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
458  return (*basicTauDiscriminatordR03Collection)[tau_ref].rawValues.at(indexMapdR03.at(BasicDiscr::ChargedIsoPtSum));
459  }
460  const float getChargedIsoPtSumdR03(const pat::Tau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
461  return getTauID(tau, "chargedIsoPtSumdR03");
462  }
463  const float getFootprintCorrectiondR03(const reco::PFTau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
464  return (*basicTauDiscriminatordR03Collection)[tau_ref].rawValues.at(
465  indexMapdR03.at(BasicDiscr::FootprintCorrection));
466  }
467  const float getFootprintCorrectiondR03(const pat::Tau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
468  return getTauID(tau, "footprintCorrectiondR03");
469  }
470  const float getNeutralIsoPtSum(const reco::PFTau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
471  return (*basicTauDiscriminatorCollection)[tau_ref].rawValues.at(indexMap.at(BasicDiscr::NeutralIsoPtSum));
472  }
473  const float getNeutralIsoPtSum(const pat::Tau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
474  return getTauID(tau, "neutralIsoPtSum");
475  }
476  const float getNeutralIsoPtSumdR03(const reco::PFTau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
477  return (*basicTauDiscriminatordR03Collection)[tau_ref].rawValues.at(indexMapdR03.at(BasicDiscr::NeutralIsoPtSum));
478  }
479  const float getNeutralIsoPtSumdR03(const pat::Tau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
480  return getTauID(tau, "neutralIsoPtSumdR03");
481  }
482  const float getNeutralIsoPtSumWeight(const reco::PFTau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
483  return (*basicTauDiscriminatorCollection)[tau_ref].rawValues.at(indexMap.at(BasicDiscr::NeutralIsoPtSumWeight));
484  }
485  const float getNeutralIsoPtSumWeight(const pat::Tau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
486  return getTauID(tau, "neutralIsoPtSumWeight");
487  }
488  const float getNeutralIsoPtSumdR03Weight(const reco::PFTau& tau,
489  const edm::RefToBase<reco::BaseTau> tau_ref) const {
490  return (*basicTauDiscriminatordR03Collection)[tau_ref].rawValues.at(
491  indexMapdR03.at(BasicDiscr::NeutralIsoPtSumWeight));
492  }
493  const float getNeutralIsoPtSumdR03Weight(const pat::Tau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
494  return getTauID(tau, "neutralIsoPtSumWeightdR03");
495  }
496  const float getPhotonPtSumOutsideSignalCone(const reco::PFTau& tau,
497  const edm::RefToBase<reco::BaseTau> tau_ref) const {
498  return (*basicTauDiscriminatorCollection)[tau_ref].rawValues.at(
499  indexMap.at(BasicDiscr::PhotonPtSumOutsideSignalCone));
500  }
501  const float getPhotonPtSumOutsideSignalCone(const pat::Tau& tau,
502  const edm::RefToBase<reco::BaseTau> tau_ref) const {
503  return getTauID(tau, "photonPtSumOutsideSignalCone");
504  }
505  const float getPhotonPtSumOutsideSignalConedR03(const reco::PFTau& tau,
506  const edm::RefToBase<reco::BaseTau> tau_ref) const {
507  return (*basicTauDiscriminatordR03Collection)[tau_ref].rawValues.at(
508  indexMapdR03.at(BasicDiscr::PhotonPtSumOutsideSignalCone));
509  }
510  const float getPhotonPtSumOutsideSignalConedR03(const pat::Tau& tau,
511  const edm::RefToBase<reco::BaseTau> tau_ref) const {
512  return getTauID(tau, "photonPtSumOutsideSignalConedR03");
513  }
514  const float getPuCorrPtSum(const reco::PFTau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
515  return (*basicTauDiscriminatorCollection)[tau_ref].rawValues.at(indexMap.at(BasicDiscr::PUcorrPtSum));
516  }
517  const float getPuCorrPtSum(const pat::Tau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
518  return getTauID(tau, "puCorrPtSum");
519  }
520 
521  auto getdxyPCA(const reco::PFTau& tau, const size_t tau_index) const {
522  return pfTauTransverseImpactParameters->value(tau_index)->dxy_PCA();
523  }
524  auto getdxyPCA(const pat::Tau& tau, const size_t tau_index) const { return tau.dxy_PCA(); }
525  auto getdxy(const reco::PFTau& tau, const size_t tau_index) const {
526  return pfTauTransverseImpactParameters->value(tau_index)->dxy();
527  }
528  auto getdxy(const pat::Tau& tau, const size_t tau_index) const { return tau.dxy(); }
529  auto getdxyError(const reco::PFTau& tau, const size_t tau_index) const {
530  return pfTauTransverseImpactParameters->value(tau_index)->dxy_error();
531  }
532  auto getdxyError(const pat::Tau& tau, const size_t tau_index) const { return tau.dxy_error(); }
533  auto getdxySig(const reco::PFTau& tau, const size_t tau_index) const {
534  return pfTauTransverseImpactParameters->value(tau_index)->dxy_Sig();
535  }
536  auto getdxySig(const pat::Tau& tau, const size_t tau_index) const { return tau.dxy_Sig(); }
537  auto getip3d(const reco::PFTau& tau, const size_t tau_index) const {
538  return pfTauTransverseImpactParameters->value(tau_index)->ip3d();
539  }
540  auto getip3d(const pat::Tau& tau, const size_t tau_index) const { return tau.ip3d(); }
541  auto getip3dError(const reco::PFTau& tau, const size_t tau_index) const {
542  return pfTauTransverseImpactParameters->value(tau_index)->ip3d_error();
543  }
544  auto getip3dError(const pat::Tau& tau, const size_t tau_index) const { return tau.ip3d_error(); }
545  auto getip3dSig(const reco::PFTau& tau, const size_t tau_index) const {
546  return pfTauTransverseImpactParameters->value(tau_index)->ip3d_Sig();
547  }
548  auto getip3dSig(const pat::Tau& tau, const size_t tau_index) const { return tau.ip3d_Sig(); }
549  auto getHasSecondaryVertex(const reco::PFTau& tau, const size_t tau_index) const {
550  return pfTauTransverseImpactParameters->value(tau_index)->hasSecondaryVertex();
551  }
552  auto getHasSecondaryVertex(const pat::Tau& tau, const size_t tau_index) const { return tau.hasSecondaryVertex(); }
553  auto getFlightLength(const reco::PFTau& tau, const size_t tau_index) const {
554  return pfTauTransverseImpactParameters->value(tau_index)->flightLength();
555  }
556  auto getFlightLength(const pat::Tau& tau, const size_t tau_index) const { return tau.flightLength(); }
557  auto getFlightLengthSig(const reco::PFTau& tau, const size_t tau_index) const {
558  return pfTauTransverseImpactParameters->value(tau_index)->flightLengthSig();
559  }
560  auto getFlightLengthSig(const pat::Tau& tau, const size_t tau_index) const { return tau.flightLengthSig(); }
561 
562  auto getLeadingTrackNormChi2(const reco::PFTau& tau) { return reco::tau::lead_track_chi2(tau); }
563  auto getLeadingTrackNormChi2(const pat::Tau& tau) { return tau.leadingTrackNormChi2(); }
564  auto getEmFraction(const pat::Tau& tau) { return tau.emFraction_MVA(); }
565  auto getEmFraction(const reco::PFTau& tau) { return tau.emFraction(); }
566  auto getEtaAtEcalEntrance(const pat::Tau& tau) { return tau.etaAtEcalEntranceLeadChargedCand(); }
567  auto getEtaAtEcalEntrance(const reco::PFTau& tau) {
568  return tau.leadPFChargedHadrCand()->positionAtECALEntrance().eta();
569  }
570  auto getEcalEnergyLeadingChargedHadr(const reco::PFTau& tau) { return tau.leadPFChargedHadrCand()->ecalEnergy(); }
571  auto getEcalEnergyLeadingChargedHadr(const pat::Tau& tau) { return tau.ecalEnergyLeadChargedHadrCand(); }
572  auto getHcalEnergyLeadingChargedHadr(const reco::PFTau& tau) { return tau.leadPFChargedHadrCand()->hcalEnergy(); }
573  auto getHcalEnergyLeadingChargedHadr(const pat::Tau& tau) { return tau.hcalEnergyLeadChargedHadrCand(); }
574 
575  template <typename PreDiscrType>
576  bool passPrediscriminants(const PreDiscrType prediscriminants,
577  const size_t andPrediscriminants,
578  const edm::RefToBase<reco::BaseTau> tau_ref) {
579  bool passesPrediscriminants = (andPrediscriminants ? 1 : 0);
580  // check tau passes prediscriminants
581  size_t nPrediscriminants = prediscriminants.size();
582  for (size_t iDisc = 0; iDisc < nPrediscriminants; ++iDisc) {
583  // current discriminant result for this tau
584  double discResult = (*prediscriminants[iDisc].handle)[tau_ref];
585  uint8_t thisPasses = (discResult > prediscriminants[iDisc].cut) ? 1 : 0;
586 
587  // if we are using the AND option, as soon as one fails,
588  // the result is FAIL and we can quit looping.
589  // if we are using the OR option as soon as one passes,
590  // the result is pass and we can quit looping
591 
592  // truth table
593  // | result (thisPasses)
594  // | F | T
595  //-----------------------------------
596  // AND(T) | res=fails | continue
597  // | break |
598  //-----------------------------------
599  // OR (F) | continue | res=passes
600  // | | break
601 
602  if (thisPasses ^ andPrediscriminants) //XOR
603  {
604  passesPrediscriminants = (andPrediscriminants ? 0 : 1); //NOR
605  break;
606  }
607  }
608  return passesPrediscriminants;
609  }
610  };
611 
612  namespace candFunc {
613  auto getTauDz(const reco::PFCandidate& cand) { return cand.bestTrack()->dz(); }
614  auto getTauDz(const pat::PackedCandidate& cand) { return cand.dz(); }
615  auto getTauDZSigValid(const reco::PFCandidate& cand) {
616  return cand.bestTrack() != nullptr && std::isnormal(cand.bestTrack()->dz()) && std::isnormal(cand.dzError()) &&
617  cand.dzError() > 0;
618  }
619  auto getTauDZSigValid(const pat::PackedCandidate& cand) {
620  return cand.hasTrackDetails() && std::isnormal(cand.dz()) && std::isnormal(cand.dzError()) && cand.dzError() > 0;
621  }
622  auto getTauDxy(const reco::PFCandidate& cand) { return cand.bestTrack()->dxy(); }
623  auto getTauDxy(const pat::PackedCandidate& cand) { return cand.dxy(); }
624  auto getPvAssocationQuality(const reco::PFCandidate& cand) { return 0.7013f; }
625  auto getPvAssocationQuality(const pat::PackedCandidate& cand) { return cand.pvAssociationQuality(); }
626  auto getPuppiWeight(const reco::PFCandidate& cand, const float aod_value) { return aod_value; }
627  auto getPuppiWeight(const pat::PackedCandidate& cand, const float aod_value) { return cand.puppiWeight(); }
628  auto getPuppiWeightNoLep(const reco::PFCandidate& cand, const float aod_value) { return aod_value; }
629  auto getPuppiWeightNoLep(const pat::PackedCandidate& cand, const float aod_value) {
630  return cand.puppiWeightNoLep();
631  }
632  auto getLostInnerHits(const reco::PFCandidate& cand, float default_value) {
633  return cand.bestTrack() != nullptr
635  : default_value;
636  }
637  auto getLostInnerHits(const pat::PackedCandidate& cand, float default_value) { return cand.lostInnerHits(); }
638  auto getNumberOfPixelHits(const reco::PFCandidate& cand, float default_value) {
639  return cand.bestTrack() != nullptr
641  : default_value;
642  }
643  auto getNumberOfPixelHits(const pat::PackedCandidate& cand, float default_value) {
644  return cand.numberOfPixelHits();
645  }
646  auto getHasTrackDetails(const reco::PFCandidate& cand) { return cand.bestTrack() != nullptr; }
647  auto getHasTrackDetails(const pat::PackedCandidate& cand) { return cand.hasTrackDetails(); }
648  auto getPseudoTrack(const reco::PFCandidate& cand) { return *cand.bestTrack(); }
649  auto getPseudoTrack(const pat::PackedCandidate& cand) { return cand.pseudoTrack(); }
650  auto getFromPV(const reco::PFCandidate& cand) { return 0.9994f; }
651  auto getFromPV(const pat::PackedCandidate& cand) { return cand.fromPV(); }
652  auto getHCalFraction(const reco::PFCandidate& cand, bool disable_hcalFraction_workaround) {
653  return cand.rawHcalEnergy() / (cand.rawHcalEnergy() + cand.rawEcalEnergy());
654  }
655  auto getHCalFraction(const pat::PackedCandidate& cand, bool disable_hcalFraction_workaround) {
656  float hcal_fraction = 0.;
657  if (disable_hcalFraction_workaround) {
658  // CV: use consistent definition for pfCand_chHad_hcalFraction
659  // in DeepTauId.cc code and in TauMLTools/Production/plugins/TauTupleProducer.cc
660  hcal_fraction = cand.hcalFraction();
661  } else {
662  // CV: backwards compatibility with DeepTau training v2p1 used during Run 2
663  if (cand.pdgId() == 1 || cand.pdgId() == 130) {
664  hcal_fraction = cand.hcalFraction();
665  } else if (cand.isIsolatedChargedHadron()) {
666  hcal_fraction = cand.rawHcalFraction();
667  }
668  }
669  return hcal_fraction;
670  }
671  auto getRawCaloFraction(const reco::PFCandidate& cand) {
672  return (cand.rawEcalEnergy() + cand.rawHcalEnergy()) / cand.energy();
673  }
674  auto getRawCaloFraction(const pat::PackedCandidate& cand) { return cand.rawCaloFraction(); }
675  }; // namespace candFunc
676 
677  template <typename LVector1, typename LVector2>
678  float dEta(const LVector1& p4, const LVector2& tau_p4) {
679  return static_cast<float>(p4.eta() - tau_p4.eta());
680  }
681 
682  template <typename LVector1, typename LVector2>
683  float dPhi(const LVector1& p4_1, const LVector2& p4_2) {
684  return static_cast<float>(reco::deltaPhi(p4_2.phi(), p4_1.phi()));
685  }
686 
687  struct MuonHitMatchV1 {
688  static constexpr int n_muon_stations = 4;
689 
690  std::map<int, std::vector<UInt_t>> n_matches, n_hits;
691  unsigned n_muons{0};
692  const pat::Muon* best_matched_muon{nullptr};
693  double deltaR2_best_match{-1};
694 
695  MuonHitMatchV1() {
696  n_matches[MuonSubdetId::DT].assign(n_muon_stations, 0);
697  n_matches[MuonSubdetId::CSC].assign(n_muon_stations, 0);
698  n_matches[MuonSubdetId::RPC].assign(n_muon_stations, 0);
699  n_hits[MuonSubdetId::DT].assign(n_muon_stations, 0);
700  n_hits[MuonSubdetId::CSC].assign(n_muon_stations, 0);
701  n_hits[MuonSubdetId::RPC].assign(n_muon_stations, 0);
702  }
703 
704  void addMatchedMuon(const pat::Muon& muon, reco::BaseTau const& tau) {
705  static constexpr int n_stations = 4;
706 
707  ++n_muons;
708  const double dR2 = reco::deltaR2(tau.p4(), muon.p4());
709  if (!best_matched_muon || dR2 < deltaR2_best_match) {
710  best_matched_muon = &muon;
711  deltaR2_best_match = dR2;
712  }
713 
714  for (const auto& segment : muon.matches()) {
715  if (segment.segmentMatches.empty())
716  continue;
717  if (n_matches.count(segment.detector()))
718  ++n_matches.at(segment.detector()).at(segment.station() - 1);
719  }
720 
721  if (muon.outerTrack().isNonnull()) {
722  const auto& hit_pattern = muon.outerTrack()->hitPattern();
723  for (int hit_index = 0; hit_index < hit_pattern.numberOfAllHits(reco::HitPattern::TRACK_HITS); ++hit_index) {
724  auto hit_id = hit_pattern.getHitPattern(reco::HitPattern::TRACK_HITS, hit_index);
725  if (hit_id == 0)
726  break;
727  if (hit_pattern.muonHitFilter(hit_id) && (hit_pattern.getHitType(hit_id) == TrackingRecHit::valid ||
728  hit_pattern.getHitType(hit_id == TrackingRecHit::bad))) {
729  const int station = hit_pattern.getMuonStation(hit_id) - 1;
730  if (station > 0 && station < n_stations) {
731  std::vector<UInt_t>* muon_n_hits = nullptr;
732  if (hit_pattern.muonDTHitFilter(hit_id))
733  muon_n_hits = &n_hits.at(MuonSubdetId::DT);
734  else if (hit_pattern.muonCSCHitFilter(hit_id))
735  muon_n_hits = &n_hits.at(MuonSubdetId::CSC);
736  else if (hit_pattern.muonRPCHitFilter(hit_id))
737  muon_n_hits = &n_hits.at(MuonSubdetId::RPC);
738 
739  if (muon_n_hits)
740  ++muon_n_hits->at(station);
741  }
742  }
743  }
744  }
745  }
746 
747  template <typename TauCastType>
748  static std::vector<const pat::Muon*> findMatchedMuons(const TauCastType& tau,
749  const std::vector<pat::Muon>* muons,
750  double deltaR,
751  double minPt) {
752  const reco::Muon* hadr_cand_muon = nullptr;
753  if (tau.leadPFChargedHadrCand().isNonnull() && tau.leadPFChargedHadrCand()->muonRef().isNonnull())
754  hadr_cand_muon = tau.leadPFChargedHadrCand()->muonRef().get();
755  std::vector<const pat::Muon*> matched_muons;
756  const double dR2 = deltaR * deltaR;
757  for (const pat::Muon& muon : *muons) {
758  const reco::Muon* reco_muon = &muon;
759  if (muon.pt() <= minPt)
760  continue;
761  if (reco_muon == hadr_cand_muon)
762  continue;
763  if (reco::deltaR2(tau.p4(), muon.p4()) >= dR2)
764  continue;
765  matched_muons.push_back(&muon);
766  }
767  return matched_muons;
768  }
769 
770  template <typename dnn, typename TensorElemGet, typename TauCastType>
771  void fillTensor(const TensorElemGet& get, const TauCastType& tau, float default_value) const {
772  get(dnn::n_matched_muons) = n_muons;
773  get(dnn::muon_pt) = best_matched_muon != nullptr ? best_matched_muon->p4().pt() : default_value;
774  get(dnn::muon_dEta) = best_matched_muon != nullptr ? dEta(best_matched_muon->p4(), tau.p4()) : default_value;
775  get(dnn::muon_dPhi) = best_matched_muon != nullptr ? dPhi(best_matched_muon->p4(), tau.p4()) : default_value;
776  get(dnn::muon_n_matches_DT_1) = n_matches.at(MuonSubdetId::DT).at(0);
777  get(dnn::muon_n_matches_DT_2) = n_matches.at(MuonSubdetId::DT).at(1);
778  get(dnn::muon_n_matches_DT_3) = n_matches.at(MuonSubdetId::DT).at(2);
779  get(dnn::muon_n_matches_DT_4) = n_matches.at(MuonSubdetId::DT).at(3);
780  get(dnn::muon_n_matches_CSC_1) = n_matches.at(MuonSubdetId::CSC).at(0);
781  get(dnn::muon_n_matches_CSC_2) = n_matches.at(MuonSubdetId::CSC).at(1);
782  get(dnn::muon_n_matches_CSC_3) = n_matches.at(MuonSubdetId::CSC).at(2);
783  get(dnn::muon_n_matches_CSC_4) = n_matches.at(MuonSubdetId::CSC).at(3);
784  get(dnn::muon_n_hits_DT_2) = n_hits.at(MuonSubdetId::DT).at(1);
785  get(dnn::muon_n_hits_DT_3) = n_hits.at(MuonSubdetId::DT).at(2);
786  get(dnn::muon_n_hits_DT_4) = n_hits.at(MuonSubdetId::DT).at(3);
787  get(dnn::muon_n_hits_CSC_2) = n_hits.at(MuonSubdetId::CSC).at(1);
788  get(dnn::muon_n_hits_CSC_3) = n_hits.at(MuonSubdetId::CSC).at(2);
789  get(dnn::muon_n_hits_CSC_4) = n_hits.at(MuonSubdetId::CSC).at(3);
790  get(dnn::muon_n_hits_RPC_2) = n_hits.at(MuonSubdetId::RPC).at(1);
791  get(dnn::muon_n_hits_RPC_3) = n_hits.at(MuonSubdetId::RPC).at(2);
792  get(dnn::muon_n_hits_RPC_4) = n_hits.at(MuonSubdetId::RPC).at(3);
793  get(dnn::muon_n_stations_with_matches_03) = countMuonStationsWithMatches(0, 3);
794  get(dnn::muon_n_stations_with_hits_23) = countMuonStationsWithHits(2, 3);
795  }
796 
797  private:
798  unsigned countMuonStationsWithMatches(size_t first_station, size_t last_station) const {
799  static const std::map<int, std::vector<bool>> masks = {
800  {MuonSubdetId::DT, {false, false, false, false}},
801  {MuonSubdetId::CSC, {true, false, false, false}},
802  {MuonSubdetId::RPC, {false, false, false, false}},
803  };
804  unsigned cnt = 0;
805  for (unsigned n = first_station; n <= last_station; ++n) {
806  for (const auto& match : n_matches) {
807  if (!masks.at(match.first).at(n) && match.second.at(n) > 0)
808  ++cnt;
809  }
810  }
811  return cnt;
812  }
813 
814  unsigned countMuonStationsWithHits(size_t first_station, size_t last_station) const {
815  static const std::map<int, std::vector<bool>> masks = {
816  {MuonSubdetId::DT, {false, false, false, false}},
817  {MuonSubdetId::CSC, {false, false, false, false}},
818  {MuonSubdetId::RPC, {false, false, false, false}},
819  };
820 
821  unsigned cnt = 0;
822  for (unsigned n = first_station; n <= last_station; ++n) {
823  for (const auto& hit : n_hits) {
824  if (!masks.at(hit.first).at(n) && hit.second.at(n) > 0)
825  ++cnt;
826  }
827  }
828  return cnt;
829  }
830  };
831 
832  struct MuonHitMatchV2 {
833  static constexpr size_t n_muon_stations = 4;
834  static constexpr int first_station_id = 1;
835  static constexpr int last_station_id = first_station_id + n_muon_stations - 1;
836  using CountArray = std::array<unsigned, n_muon_stations>;
837  using CountMap = std::map<int, CountArray>;
838 
839  const std::vector<int>& consideredSubdets() {
840  static const std::vector<int> subdets = {MuonSubdetId::DT, MuonSubdetId::CSC, MuonSubdetId::RPC};
841  return subdets;
842  }
843 
844  const std::string& subdetName(int subdet) {
845  static const std::map<int, std::string> subdet_names = {
846  {MuonSubdetId::DT, "DT"}, {MuonSubdetId::CSC, "CSC"}, {MuonSubdetId::RPC, "RPC"}};
847  if (!subdet_names.count(subdet))
848  throw cms::Exception("MuonHitMatch") << "Subdet name for subdet id " << subdet << " not found.";
849  return subdet_names.at(subdet);
850  }
851 
852  size_t getStationIndex(int station, bool throw_exception) const {
853  if (station < first_station_id || station > last_station_id) {
854  if (throw_exception)
855  throw cms::Exception("MuonHitMatch") << "Station id is out of range";
857  }
858  return static_cast<size_t>(station - 1);
859  }
860 
861  MuonHitMatchV2(const pat::Muon& muon) {
862  for (int subdet : consideredSubdets()) {
863  n_matches[subdet].fill(0);
864  n_hits[subdet].fill(0);
865  }
866 
867  countMatches(muon, n_matches);
868  countHits(muon, n_hits);
869  }
870 
871  void countMatches(const pat::Muon& muon, CountMap& n_matches) {
872  for (const auto& segment : muon.matches()) {
873  if (segment.segmentMatches.empty() && segment.rpcMatches.empty())
874  continue;
875  if (n_matches.count(segment.detector())) {
876  const size_t station_index = getStationIndex(segment.station(), true);
877  ++n_matches.at(segment.detector()).at(station_index);
878  }
879  }
880  }
881 
882  void countHits(const pat::Muon& muon, CountMap& n_hits) {
883  if (muon.outerTrack().isNonnull()) {
884  const auto& hit_pattern = muon.outerTrack()->hitPattern();
885  for (int hit_index = 0; hit_index < hit_pattern.numberOfAllHits(reco::HitPattern::TRACK_HITS); ++hit_index) {
886  auto hit_id = hit_pattern.getHitPattern(reco::HitPattern::TRACK_HITS, hit_index);
887  if (hit_id == 0)
888  break;
889  if (hit_pattern.muonHitFilter(hit_id) && (hit_pattern.getHitType(hit_id) == TrackingRecHit::valid ||
890  hit_pattern.getHitType(hit_id) == TrackingRecHit::bad)) {
891  const size_t station_index = getStationIndex(hit_pattern.getMuonStation(hit_id), false);
892  if (station_index < n_muon_stations) {
893  CountArray* muon_n_hits = nullptr;
894  if (hit_pattern.muonDTHitFilter(hit_id))
895  muon_n_hits = &n_hits.at(MuonSubdetId::DT);
896  else if (hit_pattern.muonCSCHitFilter(hit_id))
897  muon_n_hits = &n_hits.at(MuonSubdetId::CSC);
898  else if (hit_pattern.muonRPCHitFilter(hit_id))
899  muon_n_hits = &n_hits.at(MuonSubdetId::RPC);
900 
901  if (muon_n_hits)
902  ++muon_n_hits->at(station_index);
903  }
904  }
905  }
906  }
907  }
908 
909  unsigned nMatches(int subdet, int station) const {
910  if (!n_matches.count(subdet))
911  throw cms::Exception("MuonHitMatch") << "Subdet " << subdet << " not found.";
912  const size_t station_index = getStationIndex(station, true);
913  return n_matches.at(subdet).at(station_index);
914  }
915 
916  unsigned nHits(int subdet, int station) const {
917  if (!n_hits.count(subdet))
918  throw cms::Exception("MuonHitMatch") << "Subdet " << subdet << " not found.";
919  const size_t station_index = getStationIndex(station, true);
920  return n_hits.at(subdet).at(station_index);
921  }
922 
923  unsigned countMuonStationsWithMatches(int first_station, int last_station) const {
924  static const std::map<int, std::vector<bool>> masks = {
925  {MuonSubdetId::DT, {false, false, false, false}},
926  {MuonSubdetId::CSC, {true, false, false, false}},
927  {MuonSubdetId::RPC, {false, false, false, false}},
928  };
929  const size_t first_station_index = getStationIndex(first_station, true);
930  const size_t last_station_index = getStationIndex(last_station, true);
931  unsigned cnt = 0;
932  for (size_t n = first_station_index; n <= last_station_index; ++n) {
933  for (const auto& match : n_matches) {
934  if (!masks.at(match.first).at(n) && match.second.at(n) > 0)
935  ++cnt;
936  }
937  }
938  return cnt;
939  }
940 
941  unsigned countMuonStationsWithHits(int first_station, int last_station) const {
942  static const std::map<int, std::vector<bool>> masks = {
943  {MuonSubdetId::DT, {false, false, false, false}},
944  {MuonSubdetId::CSC, {false, false, false, false}},
945  {MuonSubdetId::RPC, {false, false, false, false}},
946  };
947 
948  const size_t first_station_index = getStationIndex(first_station, true);
949  const size_t last_station_index = getStationIndex(last_station, true);
950  unsigned cnt = 0;
951  for (size_t n = first_station_index; n <= last_station_index; ++n) {
952  for (const auto& hit : n_hits) {
953  if (!masks.at(hit.first).at(n) && hit.second.at(n) > 0)
954  ++cnt;
955  }
956  }
957  return cnt;
958  }
959 
960  private:
961  CountMap n_matches, n_hits;
962  };
963 
964  enum class CellObjectType {
965  PfCand_electron,
966  PfCand_muon,
967  PfCand_chargedHadron,
968  PfCand_neutralHadron,
969  PfCand_gamma,
970  Electron,
971  Muon,
972  Other
973  };
974 
975  template <typename Object>
976  CellObjectType GetCellObjectType(const Object&);
977  template <>
978  CellObjectType GetCellObjectType(const pat::Electron&) {
980  }
981  template <>
982  CellObjectType GetCellObjectType(const pat::Muon&) {
983  return CellObjectType::Muon;
984  }
985 
986  template <>
987  CellObjectType GetCellObjectType(reco::Candidate const& cand) {
988  static const std::map<int, CellObjectType> obj_types = {{11, CellObjectType::PfCand_electron},
989  {13, CellObjectType::PfCand_muon},
990  {22, CellObjectType::PfCand_gamma},
991  {130, CellObjectType::PfCand_neutralHadron},
992  {211, CellObjectType::PfCand_chargedHadron}};
993 
994  auto iter = obj_types.find(std::abs(cand.pdgId()));
995  if (iter == obj_types.end())
996  return CellObjectType::Other;
997  return iter->second;
998  }
999 
1000  using Cell = std::map<CellObjectType, size_t>;
1001  struct CellIndex {
1002  int eta, phi;
1003 
1004  bool operator<(const CellIndex& other) const {
1005  if (eta != other.eta)
1006  return eta < other.eta;
1007  return phi < other.phi;
1008  }
1009  };
1010 
1011  class CellGrid {
1012  public:
1013  using Map = std::map<CellIndex, Cell>;
1014  using const_iterator = Map::const_iterator;
1015 
1016  CellGrid(unsigned n_cells_eta,
1017  unsigned n_cells_phi,
1018  double cell_size_eta,
1019  double cell_size_phi,
1021  : nCellsEta(n_cells_eta),
1022  nCellsPhi(n_cells_phi),
1023  nTotal(nCellsEta * nCellsPhi),
1024  cellSizeEta(cell_size_eta),
1025  cellSizePhi(cell_size_phi),
1026  disable_CellIndex_workaround_(disable_CellIndex_workaround) {
1027  if (nCellsEta % 2 != 1 || nCellsEta < 1)
1028  throw cms::Exception("DeepTauId") << "Invalid number of eta cells.";
1029  if (nCellsPhi % 2 != 1 || nCellsPhi < 1)
1030  throw cms::Exception("DeepTauId") << "Invalid number of phi cells.";
1031  if (cellSizeEta <= 0 || cellSizePhi <= 0)
1032  throw cms::Exception("DeepTauId") << "Invalid cell size.";
1033  }
1034 
1035  int maxEtaIndex() const { return static_cast<int>((nCellsEta - 1) / 2); }
1036  int maxPhiIndex() const { return static_cast<int>((nCellsPhi - 1) / 2); }
1037  double maxDeltaEta() const { return cellSizeEta * (0.5 + maxEtaIndex()); }
1038  double maxDeltaPhi() const { return cellSizePhi * (0.5 + maxPhiIndex()); }
1039  int getEtaTensorIndex(const CellIndex& cellIndex) const { return cellIndex.eta + maxEtaIndex(); }
1040  int getPhiTensorIndex(const CellIndex& cellIndex) const { return cellIndex.phi + maxPhiIndex(); }
1041 
1042  bool tryGetCellIndex(double deltaEta, double deltaPhi, CellIndex& cellIndex) const {
1043  const auto getCellIndex = [this](double x, double maxX, double size, int& index) {
1044  const double absX = std::abs(x);
1045  if (absX > maxX)
1046  return false;
1047  double absIndex;
1048  if (disable_CellIndex_workaround_) {
1049  // CV: use consistent definition for CellIndex
1050  // in DeepTauId.cc code and new DeepTau trainings
1051  absIndex = std::floor(absX / size + 0.5);
1052  } else {
1053  // CV: backwards compatibility with DeepTau training v2p1 used during Run 2
1054  absIndex = std::floor(std::abs(absX / size - 0.5));
1055  }
1056  index = static_cast<int>(std::copysign(absIndex, x));
1057  return true;
1058  };
1059 
1060  return getCellIndex(deltaEta, maxDeltaEta(), cellSizeEta, cellIndex.eta) &&
1061  getCellIndex(deltaPhi, maxDeltaPhi(), cellSizePhi, cellIndex.phi);
1062  }
1063 
1064  size_t num_valid_cells() const { return cells.size(); }
1065  Cell& operator[](const CellIndex& cellIndex) { return cells[cellIndex]; }
1066  const Cell& at(const CellIndex& cellIndex) const { return cells.at(cellIndex); }
1067  size_t count(const CellIndex& cellIndex) const { return cells.count(cellIndex); }
1068  const_iterator find(const CellIndex& cellIndex) const { return cells.find(cellIndex); }
1069  const_iterator begin() const { return cells.begin(); }
1070  const_iterator end() const { return cells.end(); }
1071 
1072  public:
1073  const unsigned nCellsEta, nCellsPhi, nTotal;
1074  const double cellSizeEta, cellSizePhi;
1075 
1076  private:
1077  std::map<CellIndex, Cell> cells;
1078  const bool disable_CellIndex_workaround_;
1079  };
1080 } // anonymous namespace
1081 
1083 const std::map<bd, std::string> deep_tau::DeepTauBase::stringFromDiscriminator_{
1084  {bd::ChargedIsoPtSum, "ChargedIsoPtSum"},
1085  {bd::NeutralIsoPtSum, "NeutralIsoPtSum"},
1086  {bd::NeutralIsoPtSumWeight, "NeutralIsoPtSumWeight"},
1087  {bd::FootprintCorrection, "TauFootprintCorrection"},
1088  {bd::PhotonPtSumOutsideSignalCone, "PhotonPtSumOutsideSignalCone"},
1089  {bd::PUcorrPtSum, "PUcorrPtSum"}};
1090 const std::vector<bd> deep_tau::DeepTauBase::requiredBasicDiscriminators_ = {bd::ChargedIsoPtSum,
1091  bd::NeutralIsoPtSum,
1092  bd::NeutralIsoPtSumWeight,
1093  bd::PhotonPtSumOutsideSignalCone,
1094  bd::PUcorrPtSum};
1095 const std::vector<bd> deep_tau::DeepTauBase::requiredBasicDiscriminatorsdR03_ = {bd::ChargedIsoPtSum,
1096  bd::NeutralIsoPtSum,
1097  bd::NeutralIsoPtSumWeight,
1098  bd::PhotonPtSumOutsideSignalCone,
1099  bd::FootprintCorrection};
1100 
1102 public:
1103  static constexpr float default_value = -999.;
1104 
1105  static const OutputCollection& GetOutputs() {
1106  static constexpr size_t e_index = 0, mu_index = 1, tau_index = 2, jet_index = 3;
1107  static const OutputCollection outputs_ = {
1108  {"VSe", Output({tau_index}, {e_index, tau_index})},
1109  {"VSmu", Output({tau_index}, {mu_index, tau_index})},
1110  {"VSjet", Output({tau_index}, {jet_index, tau_index})},
1111  };
1112  return outputs_;
1113  }
1114 
1115  const std::map<BasicDiscriminator, size_t> matchDiscriminatorIndices(
1116  edm::Event& event,
1117  edm::EDGetTokenT<reco::TauDiscriminatorContainer> discriminatorContainerToken,
1118  std::vector<BasicDiscriminator> requiredDiscr) {
1119  std::map<std::string, size_t> discrIndexMapStr;
1120  auto const aHandle = event.getHandle(discriminatorContainerToken);
1121  auto const aProv = aHandle.provenance();
1122  if (aProv == nullptr)
1123  aHandle.whyFailed()->raise();
1124  const auto& psetsFromProvenance = edm::parameterSet(aProv->stable(), event.processHistory());
1125  auto const idlist = psetsFromProvenance.getParameter<std::vector<edm::ParameterSet>>("IDdefinitions");
1126  for (size_t j = 0; j < idlist.size(); ++j) {
1127  std::string idname = idlist[j].getParameter<std::string>("IDname");
1128  if (discrIndexMapStr.count(idname)) {
1129  throw cms::Exception("DeepTauId")
1130  << "basic discriminator " << idname << " appears more than once in the input.";
1131  }
1132  discrIndexMapStr[idname] = j;
1133  }
1134 
1135  //translate to a map of <BasicDiscriminator, index> and check if all discriminators are present
1136  std::map<BasicDiscriminator, size_t> discrIndexMap;
1137  for (size_t i = 0; i < requiredDiscr.size(); i++) {
1138  if (discrIndexMapStr.find(stringFromDiscriminator_.at(requiredDiscr[i])) == discrIndexMapStr.end())
1139  throw cms::Exception("DeepTauId") << "Basic Discriminator " << stringFromDiscriminator_.at(requiredDiscr[i])
1140  << " was not provided in the config file.";
1141  else
1142  discrIndexMap[requiredDiscr[i]] = discrIndexMapStr[stringFromDiscriminator_.at(requiredDiscr[i])];
1143  }
1144  return discrIndexMap;
1145  }
1146 
1149  desc.add<edm::InputTag>("electrons", edm::InputTag("slimmedElectrons"));
1150  desc.add<edm::InputTag>("muons", edm::InputTag("slimmedMuons"));
1151  desc.add<edm::InputTag>("taus", edm::InputTag("slimmedTaus"));
1152  desc.add<edm::InputTag>("pfcands", edm::InputTag("packedPFCandidates"));
1153  desc.add<edm::InputTag>("vertices", edm::InputTag("offlineSlimmedPrimaryVertices"));
1154  desc.add<edm::InputTag>("rho", edm::InputTag("fixedGridRhoAll"));
1155  desc.add<std::vector<std::string>>("graph_file",
1156  {"RecoTauTag/TrainingFiles/data/DeepTauId/deepTau_2017v2p6_e6.pb"});
1157  desc.add<bool>("mem_mapped", false);
1158  desc.add<unsigned>("version", 2);
1159  desc.add<int>("debug_level", 0);
1160  desc.add<bool>("disable_dxy_pca", false);
1161  desc.add<bool>("disable_hcalFraction_workaround", false);
1162  desc.add<bool>("disable_CellIndex_workaround", false);
1163  desc.add<bool>("save_inputs", false);
1164  desc.add<bool>("is_online", false);
1165 
1166  desc.add<std::vector<std::string>>("VSeWP", {"-1."});
1167  desc.add<std::vector<std::string>>("VSmuWP", {"-1."});
1168  desc.add<std::vector<std::string>>("VSjetWP", {"-1."});
1169 
1170  desc.addUntracked<edm::InputTag>("basicTauDiscriminators", edm::InputTag("basicTauDiscriminators"));
1171  desc.addUntracked<edm::InputTag>("basicTauDiscriminatorsdR03", edm::InputTag("basicTauDiscriminatorsdR03"));
1172  desc.add<edm::InputTag>("pfTauTransverseImpactParameters", edm::InputTag("hpsPFTauTransverseImpactParameters"));
1173 
1174  {
1175  edm::ParameterSetDescription pset_Prediscriminants;
1176  pset_Prediscriminants.add<std::string>("BooleanOperator", "and");
1177  {
1179  psd1.add<double>("cut");
1180  psd1.add<edm::InputTag>("Producer");
1181  pset_Prediscriminants.addOptional<edm::ParameterSetDescription>("decayMode", psd1);
1182  }
1183  desc.add<edm::ParameterSetDescription>("Prediscriminants", pset_Prediscriminants);
1184  }
1185 
1186  descriptions.add("DeepTau", desc);
1187  }
1188 
1189 public:
1191  : DeepTauBase(cfg, GetOutputs(), cache),
1192  electrons_token_(consumes<std::vector<pat::Electron>>(cfg.getParameter<edm::InputTag>("electrons"))),
1193  muons_token_(consumes<std::vector<pat::Muon>>(cfg.getParameter<edm::InputTag>("muons"))),
1194  rho_token_(consumes<double>(cfg.getParameter<edm::InputTag>("rho"))),
1196  cfg.getUntrackedParameter<edm::InputTag>("basicTauDiscriminators"))),
1198  cfg.getUntrackedParameter<edm::InputTag>("basicTauDiscriminatorsdR03"))),
1200  consumes<edm::AssociationVector<reco::PFTauRefProd, std::vector<reco::PFTauTransverseImpactParameterRef>>>(
1201  cfg.getParameter<edm::InputTag>("pfTauTransverseImpactParameters"))),
1202  version_(cfg.getParameter<unsigned>("version")),
1203  debug_level(cfg.getParameter<int>("debug_level")),
1204  disable_dxy_pca_(cfg.getParameter<bool>("disable_dxy_pca")),
1205  disable_hcalFraction_workaround_(cfg.getParameter<bool>("disable_hcalFraction_workaround")),
1206  disable_CellIndex_workaround_(cfg.getParameter<bool>("disable_CellIndex_workaround")),
1207  save_inputs_(cfg.getParameter<bool>("save_inputs")),
1208  json_file_(nullptr),
1209  file_counter_(0) {
1210  if (version_ == 1) {
1211  input_layer_ = cache_->getGraph().node(0).name();
1212  output_layer_ = cache_->getGraph().node(cache_->getGraph().node_size() - 1).name();
1213  const auto& shape = cache_->getGraph().node(0).attr().at("shape").shape();
1214  if (shape.dim(1).size() != dnn_inputs_2017v1::NumberOfInputs)
1215  throw cms::Exception("DeepTauId")
1216  << "number of inputs does not match the expected inputs for the given version";
1217  } else if (version_ == 2) {
1218  tauBlockTensor_ = std::make_unique<tensorflow::Tensor>(
1219  tensorflow::DT_FLOAT, tensorflow::TensorShape{1, dnn_inputs_2017_v2::TauBlockInputs::NumberOfInputs});
1220  for (size_t n = 0; n < 2; ++n) {
1221  const bool is_inner = n == 0;
1222  const auto n_cells =
1223  is_inner ? dnn_inputs_2017_v2::number_of_inner_cell : dnn_inputs_2017_v2::number_of_outer_cell;
1224  eGammaTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
1225  tensorflow::DT_FLOAT,
1226  tensorflow::TensorShape{1, 1, 1, dnn_inputs_2017_v2::EgammaBlockInputs::NumberOfInputs});
1227  muonTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
1228  tensorflow::DT_FLOAT,
1229  tensorflow::TensorShape{1, 1, 1, dnn_inputs_2017_v2::MuonBlockInputs::NumberOfInputs});
1230  hadronsTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
1231  tensorflow::DT_FLOAT,
1232  tensorflow::TensorShape{1, 1, 1, dnn_inputs_2017_v2::HadronBlockInputs::NumberOfInputs});
1233  convTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
1234  tensorflow::DT_FLOAT,
1235  tensorflow::TensorShape{1, n_cells, n_cells, dnn_inputs_2017_v2::number_of_conv_features});
1236  zeroOutputTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
1237  tensorflow::DT_FLOAT, tensorflow::TensorShape{1, 1, 1, dnn_inputs_2017_v2::number_of_conv_features});
1238 
1239  eGammaTensor_[is_inner]->flat<float>().setZero();
1240  muonTensor_[is_inner]->flat<float>().setZero();
1241  hadronsTensor_[is_inner]->flat<float>().setZero();
1242 
1243  setCellConvFeatures(*zeroOutputTensor_[is_inner], getPartialPredictions(is_inner), 0, 0, 0);
1244  }
1245  } else {
1246  throw cms::Exception("DeepTauId") << "version " << version_ << " is not supported.";
1247  }
1248  }
1249 
1250  static std::unique_ptr<deep_tau::DeepTauCache> initializeGlobalCache(const edm::ParameterSet& cfg) {
1251  return DeepTauBase::initializeGlobalCache(cfg);
1252  }
1253 
1254  static void globalEndJob(const deep_tau::DeepTauCache* cache_) { return DeepTauBase::globalEndJob(cache_); }
1255 
1256 private:
1257  static constexpr float pi = M_PI;
1258 
1259  template <typename T>
1260  static float getValue(T value) {
1261  return std::isnormal(value) ? static_cast<float>(value) : 0.f;
1262  }
1263 
1264  template <typename T>
1265  static float getValueLinear(T value, float min_value, float max_value, bool positive) {
1266  const float fixed_value = getValue(value);
1267  const float clamped_value = std::clamp(fixed_value, min_value, max_value);
1268  float transformed_value = (clamped_value - min_value) / (max_value - min_value);
1269  if (!positive)
1270  transformed_value = transformed_value * 2 - 1;
1271  return transformed_value;
1272  }
1273 
1274  template <typename T>
1275  static float getValueNorm(T value, float mean, float sigma, float n_sigmas_max = 5) {
1276  const float fixed_value = getValue(value);
1277  const float norm_value = (fixed_value - mean) / sigma;
1278  return std::clamp(norm_value, -n_sigmas_max, n_sigmas_max);
1279  }
1280 
1281  static bool isAbove(double value, double min) { return std::isnormal(value) && value > min; }
1282 
1284  float& cc_ele_energy,
1285  float& cc_gamma_energy,
1286  int& cc_n_gamma) {
1287  cc_ele_energy = cc_gamma_energy = 0;
1288  cc_n_gamma = 0;
1289  const auto& superCluster = ele.superCluster();
1290  if (superCluster.isNonnull() && superCluster.isAvailable() && superCluster->clusters().isNonnull() &&
1291  superCluster->clusters().isAvailable()) {
1292  for (auto iter = superCluster->clustersBegin(); iter != superCluster->clustersEnd(); ++iter) {
1293  const float energy = static_cast<float>((*iter)->energy());
1294  if (iter == superCluster->clustersBegin())
1295  cc_ele_energy += energy;
1296  else {
1297  cc_gamma_energy += energy;
1298  ++cc_n_gamma;
1299  }
1300  }
1301  return true;
1302  } else
1303  return false;
1304  }
1305 
1306  inline void checkInputs(const tensorflow::Tensor& inputs,
1307  const std::string& block_name,
1308  int n_inputs,
1309  const CellGrid* grid = nullptr) const {
1310  if (debug_level >= 1) {
1311  std::cout << "<checkInputs>: block_name = " << block_name << std::endl;
1312  if (block_name == "input_tau") {
1313  for (int input_index = 0; input_index < n_inputs; ++input_index) {
1314  float input = inputs.matrix<float>()(0, input_index);
1315  if (edm::isNotFinite(input)) {
1316  throw cms::Exception("DeepTauId")
1317  << "in the " << block_name
1318  << ", input is not finite, i.e. infinite or NaN, for input_index = " << input_index;
1319  }
1320  if (debug_level >= 2) {
1321  std::cout << block_name << "[var = " << input_index << "] = " << std::setprecision(5) << std::fixed << input
1322  << std::endl;
1323  }
1324  }
1325  } else {
1326  assert(grid);
1327  int n_eta, n_phi;
1328  if (block_name.find("input_inner") != std::string::npos) {
1329  n_eta = 5;
1330  n_phi = 5;
1331  } else if (block_name.find("input_outer") != std::string::npos) {
1332  n_eta = 10;
1333  n_phi = 10;
1334  } else
1335  assert(0);
1336  int eta_phi_index = 0;
1337  for (int eta = -n_eta; eta <= n_eta; ++eta) {
1338  for (int phi = -n_phi; phi <= n_phi; ++phi) {
1339  const CellIndex cell_index{eta, phi};
1340  const auto cell_iter = grid->find(cell_index);
1341  if (cell_iter != grid->end()) {
1342  for (int input_index = 0; input_index < n_inputs; ++input_index) {
1343  float input = inputs.tensor<float, 4>()(eta_phi_index, 0, 0, input_index);
1344  if (edm::isNotFinite(input)) {
1345  throw cms::Exception("DeepTauId")
1346  << "in the " << block_name << ", input is not finite, i.e. infinite or NaN, for eta = " << eta
1347  << ", phi = " << phi << ", input_index = " << input_index;
1348  }
1349  if (debug_level >= 2) {
1350  std::cout << block_name << "[eta = " << eta << "][phi = " << phi << "][var = " << input_index
1351  << "] = " << std::setprecision(5) << std::fixed << input << std::endl;
1352  }
1353  }
1354  eta_phi_index += 1;
1355  }
1356  }
1357  }
1358  }
1359  }
1360  }
1361 
1362  inline void saveInputs(const tensorflow::Tensor& inputs,
1363  const std::string& block_name,
1364  int n_inputs,
1365  const CellGrid* grid = nullptr) {
1366  if (debug_level >= 1) {
1367  std::cout << "<saveInputs>: block_name = " << block_name << std::endl;
1368  }
1369  if (!is_first_block_)
1370  (*json_file_) << ", ";
1371  (*json_file_) << "\"" << block_name << "\": [";
1372  if (block_name == "input_tau") {
1373  for (int input_index = 0; input_index < n_inputs; ++input_index) {
1374  float input = inputs.matrix<float>()(0, input_index);
1375  if (input_index != 0)
1376  (*json_file_) << ", ";
1377  (*json_file_) << input;
1378  }
1379  } else {
1380  assert(grid);
1381  int n_eta, n_phi;
1382  if (block_name.find("input_inner") != std::string::npos) {
1383  n_eta = 5;
1384  n_phi = 5;
1385  } else if (block_name.find("input_outer") != std::string::npos) {
1386  n_eta = 10;
1387  n_phi = 10;
1388  } else
1389  assert(0);
1390  int eta_phi_index = 0;
1391  for (int eta = -n_eta; eta <= n_eta; ++eta) {
1392  if (eta != -n_eta)
1393  (*json_file_) << ", ";
1394  (*json_file_) << "[";
1395  for (int phi = -n_phi; phi <= n_phi; ++phi) {
1396  if (phi != -n_phi)
1397  (*json_file_) << ", ";
1398  (*json_file_) << "[";
1399  const CellIndex cell_index{eta, phi};
1400  const auto cell_iter = grid->find(cell_index);
1401  for (int input_index = 0; input_index < n_inputs; ++input_index) {
1402  float input = 0.;
1403  if (cell_iter != grid->end()) {
1404  input = inputs.tensor<float, 4>()(eta_phi_index, 0, 0, input_index);
1405  }
1406  if (input_index != 0)
1407  (*json_file_) << ", ";
1408  (*json_file_) << input;
1409  }
1410  if (cell_iter != grid->end()) {
1411  eta_phi_index += 1;
1412  }
1413  (*json_file_) << "]";
1414  }
1415  (*json_file_) << "]";
1416  }
1417  }
1418  (*json_file_) << "]";
1419  is_first_block_ = false;
1420  }
1421 
1422 private:
1424  // Empty dummy vectors
1425  const std::vector<pat::Electron> electron_collection_default;
1426  const std::vector<pat::Muon> muon_collection_default;
1427  const reco::TauDiscriminatorContainer basicTauDiscriminators_default;
1428  const reco::TauDiscriminatorContainer basicTauDiscriminatorsdR03_default;
1430  pfTauTransverseImpactParameters_default;
1431 
1432  const std::vector<pat::Electron>* electron_collection;
1433  const std::vector<pat::Muon>* muon_collection;
1438 
1439  if (!is_online_) {
1440  electron_collection = &event.get(electrons_token_);
1441  muon_collection = &event.get(muons_token_);
1442  pfTauTransverseImpactParameters = &pfTauTransverseImpactParameters_default;
1443  basicTauDiscriminators = &basicTauDiscriminators_default;
1444  basicTauDiscriminatorsdR03 = &basicTauDiscriminatorsdR03_default;
1445  } else {
1446  electron_collection = &electron_collection_default;
1447  muon_collection = &muon_collection_default;
1448  pfTauTransverseImpactParameters = &event.get(pfTauTransverseImpactParameters_token_);
1449  basicTauDiscriminators = &event.get(basicTauDiscriminators_inputToken_);
1450  basicTauDiscriminatorsdR03 = &event.get(basicTauDiscriminatorsdR03_inputToken_);
1451 
1452  // Get indices for discriminators
1453  if (!discrIndicesMapped_) {
1458  discrIndicesMapped_ = true;
1459  }
1460  }
1461 
1462  TauFunc tauIDs = {basicTauDiscriminators,
1467 
1469  event.getByToken(pfcandToken_, pfCands);
1470 
1472  event.getByToken(vtxToken_, vertices);
1473 
1475  event.getByToken(rho_token_, rho);
1476 
1477  tensorflow::Tensor predictions(tensorflow::DT_FLOAT, {static_cast<int>(taus->size()), deep_tau::NumberOfOutputs});
1478 
1479  for (size_t tau_index = 0; tau_index < taus->size(); ++tau_index) {
1480  const edm::RefToBase<reco::BaseTau> tauRef = taus->refAt(tau_index);
1481 
1482  std::vector<tensorflow::Tensor> pred_vector;
1483 
1484  bool passesPrediscriminants;
1485  if (is_online_) {
1486  passesPrediscriminants = tauIDs.passPrediscriminants<std::vector<TauDiscInfo<reco::PFTauDiscriminator>>>(
1488  } else {
1489  passesPrediscriminants = tauIDs.passPrediscriminants<std::vector<TauDiscInfo<pat::PATTauDiscriminator>>>(
1491  }
1492 
1493  if (passesPrediscriminants) {
1494  if (version_ == 1) {
1495  if (is_online_)
1496  getPredictionsV1<reco::PFCandidate, reco::PFTau>(
1497  taus->at(tau_index), tau_index, tauRef, electron_collection, muon_collection, pred_vector, tauIDs);
1498  else
1499  getPredictionsV1<pat::PackedCandidate, pat::Tau>(
1500  taus->at(tau_index), tau_index, tauRef, electron_collection, muon_collection, pred_vector, tauIDs);
1501  } else if (version_ == 2) {
1502  if (is_online_) {
1503  getPredictionsV2<reco::PFCandidate, reco::PFTau>(taus->at(tau_index),
1504  tau_index,
1505  tauRef,
1506  electron_collection,
1507  muon_collection,
1508  *pfCands,
1509  vertices->at(0),
1510  *rho,
1511  pred_vector,
1512  tauIDs);
1513  } else
1514  getPredictionsV2<pat::PackedCandidate, pat::Tau>(taus->at(tau_index),
1515  tau_index,
1516  tauRef,
1517  electron_collection,
1518  muon_collection,
1519  *pfCands,
1520  vertices->at(0),
1521  *rho,
1522  pred_vector,
1523  tauIDs);
1524  } else {
1525  throw cms::Exception("DeepTauId") << "version " << version_ << " is not supported.";
1526  }
1527 
1528  for (int k = 0; k < deep_tau::NumberOfOutputs; ++k) {
1529  const float pred = pred_vector[0].flat<float>()(k);
1530  if (!(pred >= 0 && pred <= 1))
1531  throw cms::Exception("DeepTauId")
1532  << "invalid prediction = " << pred << " for tau_index = " << tau_index << ", pred_index = " << k;
1533  predictions.matrix<float>()(tau_index, k) = pred;
1534  }
1535  } else {
1536  // This else statement was added as a part of the DeepTau@HLT development. It does not affect the current state
1537  // of offline DeepTauId code as there the preselection is not used (it was added in the DeepTau@HLT). It returns
1538  // default values for deepTau score if the preselection failed. Before this statement the values given for this tau
1539  // were random. k == 2 corresponds to the tau score and all other k values to e, mu and jets. By defining in this way
1540  // the final score is -1.
1541  for (int k = 0; k < deep_tau::NumberOfOutputs; ++k) {
1542  predictions.matrix<float>()(tau_index, k) = (k == 2) ? -1.f : 2.f;
1543  }
1544  }
1545  }
1546  return predictions;
1547  }
1548 
1549  template <typename CandidateCastType, typename TauCastType>
1551  const size_t tau_index,
1552  const edm::RefToBase<reco::BaseTau> tau_ref,
1553  const std::vector<pat::Electron>* electrons,
1554  const std::vector<pat::Muon>* muons,
1555  std::vector<tensorflow::Tensor>& pred_vector,
1556  TauFunc tau_funcs) {
1557  const tensorflow::Tensor& inputs = createInputsV1<dnn_inputs_2017v1, const CandidateCastType>(
1558  dynamic_cast<const TauCastType&>(tau), tau_index, tau_ref, electrons, muons, tau_funcs);
1559  tensorflow::run(&(cache_->getSession()), {{input_layer_, inputs}}, {output_layer_}, &pred_vector);
1560  }
1561 
1562  template <typename CandidateCastType, typename TauCastType>
1564  const size_t tau_index,
1565  const edm::RefToBase<reco::BaseTau> tau_ref,
1566  const std::vector<pat::Electron>* electrons,
1567  const std::vector<pat::Muon>* muons,
1568  const edm::View<reco::Candidate>& pfCands,
1569  const reco::Vertex& pv,
1570  double rho,
1571  std::vector<tensorflow::Tensor>& pred_vector,
1572  TauFunc tau_funcs) {
1573  if (debug_level >= 2) {
1574  std::cout << "<DeepTauId::getPredictionsV2 (moduleLabel = " << moduleDescription().moduleLabel()
1575  << ")>:" << std::endl;
1576  std::cout << " tau: pT = " << tau.pt() << ", eta = " << tau.eta() << ", phi = " << tau.phi() << std::endl;
1577  }
1578  CellGrid inner_grid(dnn_inputs_2017_v2::number_of_inner_cell,
1579  dnn_inputs_2017_v2::number_of_inner_cell,
1580  0.02,
1581  0.02,
1583  CellGrid outer_grid(dnn_inputs_2017_v2::number_of_outer_cell,
1584  dnn_inputs_2017_v2::number_of_outer_cell,
1585  0.05,
1586  0.05,
1588  fillGrids(dynamic_cast<const TauCastType&>(tau), *electrons, inner_grid, outer_grid);
1589  fillGrids(dynamic_cast<const TauCastType&>(tau), *muons, inner_grid, outer_grid);
1590  fillGrids(dynamic_cast<const TauCastType&>(tau), pfCands, inner_grid, outer_grid);
1591 
1592  createTauBlockInputs<CandidateCastType>(
1593  dynamic_cast<const TauCastType&>(tau), tau_index, tau_ref, pv, rho, tau_funcs);
1594  using namespace dnn_inputs_2017_v2;
1595  checkInputs(*tauBlockTensor_, "input_tau", TauBlockInputs::NumberOfInputs);
1596  createConvFeatures<CandidateCastType>(dynamic_cast<const TauCastType&>(tau),
1597  tau_index,
1598  tau_ref,
1599  pv,
1600  rho,
1601  electrons,
1602  muons,
1603  pfCands,
1604  inner_grid,
1605  tau_funcs,
1606  true);
1607  checkInputs(*eGammaTensor_[true], "input_inner_egamma", EgammaBlockInputs::NumberOfInputs, &inner_grid);
1608  checkInputs(*muonTensor_[true], "input_inner_muon", MuonBlockInputs::NumberOfInputs, &inner_grid);
1609  checkInputs(*hadronsTensor_[true], "input_inner_hadrons", HadronBlockInputs::NumberOfInputs, &inner_grid);
1610  createConvFeatures<CandidateCastType>(dynamic_cast<const TauCastType&>(tau),
1611  tau_index,
1612  tau_ref,
1613  pv,
1614  rho,
1615  electrons,
1616  muons,
1617  pfCands,
1618  outer_grid,
1619  tau_funcs,
1620  false);
1621  checkInputs(*eGammaTensor_[false], "input_outer_egamma", EgammaBlockInputs::NumberOfInputs, &outer_grid);
1622  checkInputs(*muonTensor_[false], "input_outer_muon", MuonBlockInputs::NumberOfInputs, &outer_grid);
1623  checkInputs(*hadronsTensor_[false], "input_outer_hadrons", HadronBlockInputs::NumberOfInputs, &outer_grid);
1624 
1625  if (save_inputs_) {
1626  std::string json_file_name = "DeepTauId_" + std::to_string(file_counter_) + ".json";
1627  json_file_ = new std::ofstream(json_file_name.data());
1628  is_first_block_ = true;
1629  (*json_file_) << "{";
1630  saveInputs(*tauBlockTensor_, "input_tau", dnn_inputs_2017_v2::TauBlockInputs::NumberOfInputs);
1631  saveInputs(*eGammaTensor_[true],
1632  "input_inner_egamma",
1633  dnn_inputs_2017_v2::EgammaBlockInputs::NumberOfInputs,
1634  &inner_grid);
1635  saveInputs(
1636  *muonTensor_[true], "input_inner_muon", dnn_inputs_2017_v2::MuonBlockInputs::NumberOfInputs, &inner_grid);
1637  saveInputs(*hadronsTensor_[true],
1638  "input_inner_hadrons",
1639  dnn_inputs_2017_v2::HadronBlockInputs::NumberOfInputs,
1640  &inner_grid);
1641  saveInputs(*eGammaTensor_[false],
1642  "input_outer_egamma",
1643  dnn_inputs_2017_v2::EgammaBlockInputs::NumberOfInputs,
1644  &outer_grid);
1645  saveInputs(
1646  *muonTensor_[false], "input_outer_muon", dnn_inputs_2017_v2::MuonBlockInputs::NumberOfInputs, &outer_grid);
1647  saveInputs(*hadronsTensor_[false],
1648  "input_outer_hadrons",
1649  dnn_inputs_2017_v2::HadronBlockInputs::NumberOfInputs,
1650  &outer_grid);
1651  (*json_file_) << "}";
1652  delete json_file_;
1653  ++file_counter_;
1654  }
1655 
1656  tensorflow::run(&(cache_->getSession("core")),
1657  {{"input_tau", *tauBlockTensor_},
1658  {"input_inner", *convTensor_.at(true)},
1659  {"input_outer", *convTensor_.at(false)}},
1660  {"main_output/Softmax"},
1661  &pred_vector);
1662  if (debug_level >= 1) {
1663  std::cout << "output = { ";
1664  for (int idx = 0; idx < deep_tau::NumberOfOutputs; ++idx) {
1665  if (idx > 0)
1666  std::cout << ", ";
1668  if (idx == 0)
1669  label = "e";
1670  else if (idx == 1)
1671  label = "mu";
1672  else if (idx == 2)
1673  label = "tau";
1674  else if (idx == 3)
1675  label = "jet";
1676  else
1677  assert(0);
1678  std::cout << label << " = " << pred_vector[0].flat<float>()(idx);
1679  }
1680  std::cout << " }" << std::endl;
1681  }
1682  }
1683 
1684  template <typename Collection, typename TauCastType>
1685  void fillGrids(const TauCastType& tau, const Collection& objects, CellGrid& inner_grid, CellGrid& outer_grid) {
1686  static constexpr double outer_dR2 = 0.25; //0.5^2
1687  const double inner_radius = getInnerSignalConeRadius(tau.polarP4().pt());
1688  const double inner_dR2 = std::pow(inner_radius, 2);
1689 
1690  const auto addObject = [&](size_t n, double deta, double dphi, CellGrid& grid) {
1691  const auto& obj = objects.at(n);
1692  const CellObjectType obj_type = GetCellObjectType(obj);
1693  if (obj_type == CellObjectType::Other)
1694  return;
1695  CellIndex cell_index;
1696  if (grid.tryGetCellIndex(deta, dphi, cell_index)) {
1697  Cell& cell = grid[cell_index];
1698  auto iter = cell.find(obj_type);
1699  if (iter != cell.end()) {
1700  const auto& prev_obj = objects.at(iter->second);
1701  if (obj.polarP4().pt() > prev_obj.polarP4().pt())
1702  iter->second = n;
1703  } else {
1704  cell[obj_type] = n;
1705  }
1706  }
1707  };
1708 
1709  for (size_t n = 0; n < objects.size(); ++n) {
1710  const auto& obj = objects.at(n);
1711  const double deta = obj.polarP4().eta() - tau.polarP4().eta();
1712  const double dphi = reco::deltaPhi(obj.polarP4().phi(), tau.polarP4().phi());
1713  const double dR2 = std::pow(deta, 2) + std::pow(dphi, 2);
1714  if (dR2 < inner_dR2)
1715  addObject(n, deta, dphi, inner_grid);
1716  if (dR2 < outer_dR2)
1717  addObject(n, deta, dphi, outer_grid);
1718  }
1719  }
1720 
1721  tensorflow::Tensor getPartialPredictions(bool is_inner) {
1722  std::vector<tensorflow::Tensor> pred_vector;
1723  if (is_inner) {
1724  tensorflow::run(&(cache_->getSession("inner")),
1725  {
1726  {"input_inner_egamma", *eGammaTensor_.at(is_inner)},
1727  {"input_inner_muon", *muonTensor_.at(is_inner)},
1728  {"input_inner_hadrons", *hadronsTensor_.at(is_inner)},
1729  },
1730  {"inner_all_dropout_4/Identity"},
1731  &pred_vector);
1732  } else {
1733  tensorflow::run(&(cache_->getSession("outer")),
1734  {
1735  {"input_outer_egamma", *eGammaTensor_.at(is_inner)},
1736  {"input_outer_muon", *muonTensor_.at(is_inner)},
1737  {"input_outer_hadrons", *hadronsTensor_.at(is_inner)},
1738  },
1739  {"outer_all_dropout_4/Identity"},
1740  &pred_vector);
1741  }
1742  return pred_vector.at(0);
1743  }
1744 
1745  template <typename CandidateCastType, typename TauCastType>
1746  void createConvFeatures(const TauCastType& tau,
1747  const size_t tau_index,
1748  const edm::RefToBase<reco::BaseTau> tau_ref,
1749  const reco::Vertex& pv,
1750  double rho,
1751  const std::vector<pat::Electron>* electrons,
1752  const std::vector<pat::Muon>* muons,
1753  const edm::View<reco::Candidate>& pfCands,
1754  const CellGrid& grid,
1755  TauFunc tau_funcs,
1756  bool is_inner) {
1757  if (debug_level >= 2) {
1758  std::cout << "<DeepTauId::createConvFeatures (is_inner = " << is_inner << ")>:" << std::endl;
1759  }
1760  tensorflow::Tensor& convTensor = *convTensor_.at(is_inner);
1761  eGammaTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
1762  tensorflow::DT_FLOAT,
1763  tensorflow::TensorShape{
1764  (long long int)grid.num_valid_cells(), 1, 1, dnn_inputs_2017_v2::EgammaBlockInputs::NumberOfInputs});
1765  muonTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
1766  tensorflow::DT_FLOAT,
1767  tensorflow::TensorShape{
1768  (long long int)grid.num_valid_cells(), 1, 1, dnn_inputs_2017_v2::MuonBlockInputs::NumberOfInputs});
1769  hadronsTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
1770  tensorflow::DT_FLOAT,
1771  tensorflow::TensorShape{
1772  (long long int)grid.num_valid_cells(), 1, 1, dnn_inputs_2017_v2::HadronBlockInputs::NumberOfInputs});
1773 
1774  eGammaTensor_[is_inner]->flat<float>().setZero();
1775  muonTensor_[is_inner]->flat<float>().setZero();
1776  hadronsTensor_[is_inner]->flat<float>().setZero();
1777 
1778  unsigned idx = 0;
1779  for (int eta = -grid.maxEtaIndex(); eta <= grid.maxEtaIndex(); ++eta) {
1780  for (int phi = -grid.maxPhiIndex(); phi <= grid.maxPhiIndex(); ++phi) {
1781  if (debug_level >= 2) {
1782  std::cout << "processing ( eta = " << eta << ", phi = " << phi << " )" << std::endl;
1783  }
1784  const CellIndex cell_index{eta, phi};
1785  const auto cell_iter = grid.find(cell_index);
1786  if (cell_iter != grid.end()) {
1787  if (debug_level >= 2) {
1788  std::cout << " creating inputs for ( eta = " << eta << ", phi = " << phi << " ): idx = " << idx
1789  << std::endl;
1790  }
1791  const Cell& cell = cell_iter->second;
1792  createEgammaBlockInputs<CandidateCastType>(
1793  idx, tau, tau_index, tau_ref, pv, rho, electrons, pfCands, cell, tau_funcs, is_inner);
1794  createMuonBlockInputs<CandidateCastType>(
1795  idx, tau, tau_index, tau_ref, pv, rho, muons, pfCands, cell, tau_funcs, is_inner);
1796  createHadronsBlockInputs<CandidateCastType>(
1797  idx, tau, tau_index, tau_ref, pv, rho, pfCands, cell, tau_funcs, is_inner);
1798  idx += 1;
1799  } else {
1800  if (debug_level >= 2) {
1801  std::cout << " skipping creation of inputs, because ( eta = " << eta << ", phi = " << phi
1802  << " ) is not in the grid !!" << std::endl;
1803  }
1804  }
1805  }
1806  }
1807 
1808  const auto predTensor = getPartialPredictions(is_inner);
1809  idx = 0;
1810  for (int eta = -grid.maxEtaIndex(); eta <= grid.maxEtaIndex(); ++eta) {
1811  for (int phi = -grid.maxPhiIndex(); phi <= grid.maxPhiIndex(); ++phi) {
1812  const CellIndex cell_index{eta, phi};
1813  const int eta_index = grid.getEtaTensorIndex(cell_index);
1814  const int phi_index = grid.getPhiTensorIndex(cell_index);
1815 
1816  const auto cell_iter = grid.find(cell_index);
1817  if (cell_iter != grid.end()) {
1818  setCellConvFeatures(convTensor, predTensor, idx, eta_index, phi_index);
1819  idx += 1;
1820  } else {
1821  setCellConvFeatures(convTensor, *zeroOutputTensor_[is_inner], 0, eta_index, phi_index);
1822  }
1823  }
1824  }
1825  }
1826 
1827  void setCellConvFeatures(tensorflow::Tensor& convTensor,
1828  const tensorflow::Tensor& features,
1829  unsigned batch_idx,
1830  int eta_index,
1831  int phi_index) {
1832  for (int n = 0; n < dnn_inputs_2017_v2::number_of_conv_features; ++n) {
1833  convTensor.tensor<float, 4>()(0, eta_index, phi_index, n) = features.tensor<float, 4>()(batch_idx, 0, 0, n);
1834  }
1835  }
1836 
1837  template <typename CandidateCastType, typename TauCastType>
1838  void createTauBlockInputs(const TauCastType& tau,
1839  const size_t& tau_index,
1840  const edm::RefToBase<reco::BaseTau> tau_ref,
1841  const reco::Vertex& pv,
1842  double rho,
1843  TauFunc tau_funcs) {
1844  namespace dnn = dnn_inputs_2017_v2::TauBlockInputs;
1845 
1846  tensorflow::Tensor& inputs = *tauBlockTensor_;
1847  inputs.flat<float>().setZero();
1848 
1849  const auto& get = [&](int var_index) -> float& { return inputs.matrix<float>()(0, var_index); };
1850 
1851  auto leadChargedHadrCand = dynamic_cast<const CandidateCastType*>(tau.leadChargedHadrCand().get());
1852 
1853  get(dnn::rho) = getValueNorm(rho, 21.49f, 9.713f);
1854  get(dnn::tau_pt) = getValueLinear(tau.polarP4().pt(), 20.f, 1000.f, true);
1855  get(dnn::tau_eta) = getValueLinear(tau.polarP4().eta(), -2.3f, 2.3f, false);
1856  get(dnn::tau_phi) = getValueLinear(tau.polarP4().phi(), -pi, pi, false);
1857  get(dnn::tau_mass) = getValueNorm(tau.polarP4().mass(), 0.6669f, 0.6553f);
1858  get(dnn::tau_E_over_pt) = getValueLinear(tau.p4().energy() / tau.p4().pt(), 1.f, 5.2f, true);
1859  get(dnn::tau_charge) = getValue(tau.charge());
1860  get(dnn::tau_n_charged_prongs) = getValueLinear(tau.decayMode() / 5 + 1, 1, 3, true);
1861  get(dnn::tau_n_neutral_prongs) = getValueLinear(tau.decayMode() % 5, 0, 2, true);
1862  get(dnn::chargedIsoPtSum) = getValueNorm(tau_funcs.getChargedIsoPtSum(tau, tau_ref), 47.78f, 123.5f);
1863  get(dnn::chargedIsoPtSumdR03_over_dR05) =
1864  getValue(tau_funcs.getChargedIsoPtSumdR03(tau, tau_ref) / tau_funcs.getChargedIsoPtSum(tau, tau_ref));
1865  get(dnn::footprintCorrection) = getValueNorm(tau_funcs.getFootprintCorrectiondR03(tau, tau_ref), 9.029f, 26.42f);
1866  get(dnn::neutralIsoPtSum) = getValueNorm(tau_funcs.getNeutralIsoPtSum(tau, tau_ref), 57.59f, 155.3f);
1867  get(dnn::neutralIsoPtSumWeight_over_neutralIsoPtSum) =
1868  getValue(tau_funcs.getNeutralIsoPtSumWeight(tau, tau_ref) / tau_funcs.getNeutralIsoPtSum(tau, tau_ref));
1869  get(dnn::neutralIsoPtSumWeightdR03_over_neutralIsoPtSum) =
1870  getValue(tau_funcs.getNeutralIsoPtSumdR03Weight(tau, tau_ref) / tau_funcs.getNeutralIsoPtSum(tau, tau_ref));
1871  get(dnn::neutralIsoPtSumdR03_over_dR05) =
1872  getValue(tau_funcs.getNeutralIsoPtSumdR03(tau, tau_ref) / tau_funcs.getNeutralIsoPtSum(tau, tau_ref));
1873  get(dnn::photonPtSumOutsideSignalCone) =
1874  getValueNorm(tau_funcs.getPhotonPtSumOutsideSignalCone(tau, tau_ref), 1.731f, 6.846f);
1875  get(dnn::puCorrPtSum) = getValueNorm(tau_funcs.getPuCorrPtSum(tau, tau_ref), 22.38f, 16.34f);
1876  // The global PCA coordinates were used as inputs during the NN training, but it was decided to disable
1877  // them for the inference, because modeling of dxy_PCA in MC poorly describes the data, and x and y coordinates
1878  // in data results outside of the expected 5 std. dev. input validity range. On the other hand,
1879  // these coordinates are strongly era-dependent. Kept as comment to document what NN expects.
1880  if (!disable_dxy_pca_) {
1881  auto const pca = tau_funcs.getdxyPCA(tau, tau_index);
1882  get(dnn::tau_dxy_pca_x) = getValueNorm(pca.x(), -0.0241f, 0.0074f);
1883  get(dnn::tau_dxy_pca_y) = getValueNorm(pca.y(), 0.0675f, 0.0128f);
1884  get(dnn::tau_dxy_pca_z) = getValueNorm(pca.z(), 0.7973f, 3.456f);
1885  } else {
1886  get(dnn::tau_dxy_pca_x) = 0;
1887  get(dnn::tau_dxy_pca_y) = 0;
1888  get(dnn::tau_dxy_pca_z) = 0;
1889  }
1890  const bool tau_dxy_valid =
1891  isAbove(tau_funcs.getdxy(tau, tau_index), -10) && isAbove(tau_funcs.getdxyError(tau, tau_index), 0);
1892  if (tau_dxy_valid) {
1893  get(dnn::tau_dxy_valid) = tau_dxy_valid;
1894  get(dnn::tau_dxy) = getValueNorm(tau_funcs.getdxy(tau, tau_index), 0.0018f, 0.0085f);
1895  get(dnn::tau_dxy_sig) = getValueNorm(
1896  std::abs(tau_funcs.getdxy(tau, tau_index)) / tau_funcs.getdxyError(tau, tau_index), 2.26f, 4.191f);
1897  }
1898  const bool tau_ip3d_valid =
1899  isAbove(tau_funcs.getip3d(tau, tau_index), -10) && isAbove(tau_funcs.getip3dError(tau, tau_index), 0);
1900  if (tau_ip3d_valid) {
1901  get(dnn::tau_ip3d_valid) = tau_ip3d_valid;
1902  get(dnn::tau_ip3d) = getValueNorm(tau_funcs.getip3d(tau, tau_index), 0.0026f, 0.0114f);
1903  get(dnn::tau_ip3d_sig) = getValueNorm(
1904  std::abs(tau_funcs.getip3d(tau, tau_index)) / tau_funcs.getip3dError(tau, tau_index), 2.928f, 4.466f);
1905  }
1906  if (leadChargedHadrCand) {
1907  const bool hasTrackDetails = candFunc::getHasTrackDetails(*leadChargedHadrCand);
1908  const float tau_dz = (is_online_ && !hasTrackDetails) ? 0 : candFunc::getTauDz(*leadChargedHadrCand);
1909  get(dnn::tau_dz) = getValueNorm(tau_dz, 0.f, 0.0190f);
1910  get(dnn::tau_dz_sig_valid) = candFunc::getTauDZSigValid(*leadChargedHadrCand);
1911  const double dzError = hasTrackDetails ? leadChargedHadrCand->dzError() : -999.;
1912  get(dnn::tau_dz_sig) = getValueNorm(std::abs(tau_dz) / dzError, 4.717f, 11.78f);
1913  }
1914  get(dnn::tau_flightLength_x) = getValueNorm(tau_funcs.getFlightLength(tau, tau_index).x(), -0.0003f, 0.7362f);
1915  get(dnn::tau_flightLength_y) = getValueNorm(tau_funcs.getFlightLength(tau, tau_index).y(), -0.0009f, 0.7354f);
1916  get(dnn::tau_flightLength_z) = getValueNorm(tau_funcs.getFlightLength(tau, tau_index).z(), -0.0022f, 1.993f);
1917  get(dnn::tau_flightLength_sig) = 0.55756444; //This value is set due to a bug in the training
1918  get(dnn::tau_pt_weighted_deta_strip) =
1919  getValueLinear(reco::tau::pt_weighted_deta_strip(tau, tau.decayMode()), 0, 1, true);
1920 
1921  get(dnn::tau_pt_weighted_dphi_strip) =
1922  getValueLinear(reco::tau::pt_weighted_dphi_strip(tau, tau.decayMode()), 0, 1, true);
1923  get(dnn::tau_pt_weighted_dr_signal) =
1924  getValueNorm(reco::tau::pt_weighted_dr_signal(tau, tau.decayMode()), 0.0052f, 0.01433f);
1925  get(dnn::tau_pt_weighted_dr_iso) = getValueLinear(reco::tau::pt_weighted_dr_iso(tau, tau.decayMode()), 0, 1, true);
1926  get(dnn::tau_leadingTrackNormChi2) = getValueNorm(tau_funcs.getLeadingTrackNormChi2(tau), 1.538f, 4.401f);
1927  const auto eratio = reco::tau::eratio(tau);
1928  const bool tau_e_ratio_valid = std::isnormal(eratio) && eratio > 0.f;
1929  get(dnn::tau_e_ratio_valid) = tau_e_ratio_valid;
1930  get(dnn::tau_e_ratio) = tau_e_ratio_valid ? getValueLinear(eratio, 0, 1, true) : 0.f;
1931  const double gj_angle_diff = calculateGottfriedJacksonAngleDifference(tau, tau_index, tau_funcs);
1932  const bool tau_gj_angle_diff_valid = (std::isnormal(gj_angle_diff) || gj_angle_diff == 0) && gj_angle_diff >= 0;
1933  get(dnn::tau_gj_angle_diff_valid) = tau_gj_angle_diff_valid;
1934  get(dnn::tau_gj_angle_diff) = tau_gj_angle_diff_valid ? getValueLinear(gj_angle_diff, 0, pi, true) : 0;
1935  get(dnn::tau_n_photons) = getValueNorm(reco::tau::n_photons_total(tau), 2.95f, 3.927f);
1936  get(dnn::tau_emFraction) = getValueLinear(tau_funcs.getEmFraction(tau), -1, 1, false);
1937 
1938  get(dnn::tau_inside_ecal_crack) = getValue(isInEcalCrack(tau.p4().eta()));
1939  get(dnn::leadChargedCand_etaAtEcalEntrance_minus_tau_eta) =
1940  getValueNorm(tau_funcs.getEtaAtEcalEntrance(tau) - tau.p4().eta(), 0.0042f, 0.0323f);
1941  }
1942 
1943  template <typename CandidateCastType, typename TauCastType>
1944  void createEgammaBlockInputs(unsigned idx,
1945  const TauCastType& tau,
1946  const size_t tau_index,
1947  const edm::RefToBase<reco::BaseTau> tau_ref,
1948  const reco::Vertex& pv,
1949  double rho,
1950  const std::vector<pat::Electron>* electrons,
1951  const edm::View<reco::Candidate>& pfCands,
1952  const Cell& cell_map,
1953  TauFunc tau_funcs,
1954  bool is_inner) {
1955  namespace dnn = dnn_inputs_2017_v2::EgammaBlockInputs;
1956 
1957  tensorflow::Tensor& inputs = *eGammaTensor_.at(is_inner);
1958 
1959  const auto& get = [&](int var_index) -> float& { return inputs.tensor<float, 4>()(idx, 0, 0, var_index); };
1960 
1961  const bool valid_index_pf_ele = cell_map.count(CellObjectType::PfCand_electron);
1962  const bool valid_index_pf_gamma = cell_map.count(CellObjectType::PfCand_gamma);
1963  const bool valid_index_ele = cell_map.count(CellObjectType::Electron);
1964 
1965  if (!cell_map.empty()) {
1966  get(dnn::rho) = getValueNorm(rho, 21.49f, 9.713f);
1967  get(dnn::tau_pt) = getValueLinear(tau.polarP4().pt(), 20.f, 1000.f, true);
1968  get(dnn::tau_eta) = getValueLinear(tau.polarP4().eta(), -2.3f, 2.3f, false);
1969  get(dnn::tau_inside_ecal_crack) = getValue(isInEcalCrack(tau.polarP4().eta()));
1970  }
1971  if (valid_index_pf_ele) {
1972  size_t index_pf_ele = cell_map.at(CellObjectType::PfCand_electron);
1973  const auto& ele_cand = dynamic_cast<const CandidateCastType&>(pfCands.at(index_pf_ele));
1974 
1975  get(dnn::pfCand_ele_valid) = valid_index_pf_ele;
1976  get(dnn::pfCand_ele_rel_pt) = getValueNorm(pfCands.at(index_pf_ele).polarP4().pt() / tau.polarP4().pt(),
1977  is_inner ? 0.9792f : 0.304f,
1978  is_inner ? 0.5383f : 1.845f);
1979  get(dnn::pfCand_ele_deta) = getValueLinear(pfCands.at(index_pf_ele).polarP4().eta() - tau.polarP4().eta(),
1980  is_inner ? -0.1f : -0.5f,
1981  is_inner ? 0.1f : 0.5f,
1982  false);
1983  get(dnn::pfCand_ele_dphi) = getValueLinear(dPhi(tau.polarP4(), pfCands.at(index_pf_ele).polarP4()),
1984  is_inner ? -0.1f : -0.5f,
1985  is_inner ? 0.1f : 0.5f,
1986  false);
1987  get(dnn::pfCand_ele_pvAssociationQuality) =
1988  getValueLinear<int>(candFunc::getPvAssocationQuality(ele_cand), 0, 7, true);
1989  get(dnn::pfCand_ele_puppiWeight) = is_inner ? getValue(candFunc::getPuppiWeight(ele_cand, 0.9906834f))
1990  : getValue(candFunc::getPuppiWeight(ele_cand, 0.9669586f));
1991  get(dnn::pfCand_ele_charge) = getValue(ele_cand.charge());
1992  get(dnn::pfCand_ele_lostInnerHits) = getValue<int>(candFunc::getLostInnerHits(ele_cand, 0));
1993  get(dnn::pfCand_ele_numberOfPixelHits) = getValueLinear(candFunc::getNumberOfPixelHits(ele_cand, 0), 0, 10, true);
1994  get(dnn::pfCand_ele_vertex_dx) =
1995  getValueNorm(pfCands.at(index_pf_ele).vertex().x() - pv.position().x(), 0.f, 0.1221f);
1996  get(dnn::pfCand_ele_vertex_dy) =
1997  getValueNorm(pfCands.at(index_pf_ele).vertex().y() - pv.position().y(), 0.f, 0.1226f);
1998  get(dnn::pfCand_ele_vertex_dz) =
1999  getValueNorm(pfCands.at(index_pf_ele).vertex().z() - pv.position().z(), 0.001f, 1.024f);
2000  get(dnn::pfCand_ele_vertex_dx_tauFL) = getValueNorm(
2001  pfCands.at(index_pf_ele).vertex().x() - pv.position().x() - tau_funcs.getFlightLength(tau, tau_index).x(),
2002  0.f,
2003  0.3411f);
2004  get(dnn::pfCand_ele_vertex_dy_tauFL) = getValueNorm(
2005  pfCands.at(index_pf_ele).vertex().y() - pv.position().y() - tau_funcs.getFlightLength(tau, tau_index).y(),
2006  0.0003f,
2007  0.3385f);
2008  get(dnn::pfCand_ele_vertex_dz_tauFL) = getValueNorm(
2009  pfCands.at(index_pf_ele).vertex().z() - pv.position().z() - tau_funcs.getFlightLength(tau, tau_index).z(),
2010  0.f,
2011  1.307f);
2012 
2013  const bool hasTrackDetails = candFunc::getHasTrackDetails(ele_cand);
2014  if (hasTrackDetails) {
2015  get(dnn::pfCand_ele_hasTrackDetails) = hasTrackDetails;
2016  get(dnn::pfCand_ele_dxy) = getValueNorm(candFunc::getTauDxy(ele_cand), 0.f, 0.171f);
2017  get(dnn::pfCand_ele_dxy_sig) =
2018  getValueNorm(std::abs(candFunc::getTauDxy(ele_cand)) / pfCands.at(index_pf_ele).dxyError(), 1.634f, 6.45f);
2019  get(dnn::pfCand_ele_dz) = getValueNorm(candFunc::getTauDz(ele_cand), 0.001f, 1.02f);
2020  get(dnn::pfCand_ele_dz_sig) =
2021  getValueNorm(std::abs(candFunc::getTauDz(ele_cand)) / ele_cand.dzError(), 24.56f, 210.4f);
2022  get(dnn::pfCand_ele_track_chi2_ndof) = getValueNorm(
2023  candFunc::getPseudoTrack(ele_cand).chi2() / candFunc::getPseudoTrack(ele_cand).ndof(), 2.272f, 8.439f);
2024  get(dnn::pfCand_ele_track_ndof) = getValueNorm(candFunc::getPseudoTrack(ele_cand).ndof(), 15.18f, 3.203f);
2025  }
2026  }
2027  if (valid_index_pf_gamma) {
2028  size_t index_pf_gamma = cell_map.at(CellObjectType::PfCand_gamma);
2029  const auto& gamma_cand = dynamic_cast<const CandidateCastType&>(pfCands.at(index_pf_gamma));
2030 
2031  get(dnn::pfCand_gamma_valid) = valid_index_pf_gamma;
2032  get(dnn::pfCand_gamma_rel_pt) = getValueNorm(pfCands.at(index_pf_gamma).polarP4().pt() / tau.polarP4().pt(),
2033  is_inner ? 0.6048f : 0.02576f,
2034  is_inner ? 1.669f : 0.3833f);
2035  get(dnn::pfCand_gamma_deta) = getValueLinear(pfCands.at(index_pf_gamma).polarP4().eta() - tau.polarP4().eta(),
2036  is_inner ? -0.1f : -0.5f,
2037  is_inner ? 0.1f : 0.5f,
2038  false);
2039  get(dnn::pfCand_gamma_dphi) = getValueLinear(dPhi(tau.polarP4(), pfCands.at(index_pf_gamma).polarP4()),
2040  is_inner ? -0.1f : -0.5f,
2041  is_inner ? 0.1f : 0.5f,
2042  false);
2043  get(dnn::pfCand_gamma_pvAssociationQuality) =
2044  getValueLinear<int>(candFunc::getPvAssocationQuality(gamma_cand), 0, 7, true);
2045  get(dnn::pfCand_gamma_fromPV) = getValueLinear<int>(candFunc::getFromPV(gamma_cand), 0, 3, true);
2046  get(dnn::pfCand_gamma_puppiWeight) = is_inner ? getValue(candFunc::getPuppiWeight(gamma_cand, 0.9084110f))
2047  : getValue(candFunc::getPuppiWeight(gamma_cand, 0.4211567f));
2048  get(dnn::pfCand_gamma_puppiWeightNoLep) = is_inner
2049  ? getValue(candFunc::getPuppiWeightNoLep(gamma_cand, 0.8857716f))
2050  : getValue(candFunc::getPuppiWeightNoLep(gamma_cand, 0.3822604f));
2051  get(dnn::pfCand_gamma_lostInnerHits) = getValue<int>(candFunc::getLostInnerHits(gamma_cand, 0));
2052  get(dnn::pfCand_gamma_numberOfPixelHits) =
2053  getValueLinear(candFunc::getNumberOfPixelHits(gamma_cand, 0), 0, 7, true);
2054  get(dnn::pfCand_gamma_vertex_dx) =
2055  getValueNorm(pfCands.at(index_pf_gamma).vertex().x() - pv.position().x(), 0.f, 0.0067f);
2056  get(dnn::pfCand_gamma_vertex_dy) =
2057  getValueNorm(pfCands.at(index_pf_gamma).vertex().y() - pv.position().y(), 0.f, 0.0069f);
2058  get(dnn::pfCand_gamma_vertex_dz) =
2059  getValueNorm(pfCands.at(index_pf_gamma).vertex().z() - pv.position().z(), 0.f, 0.0578f);
2060  get(dnn::pfCand_gamma_vertex_dx_tauFL) = getValueNorm(
2061  pfCands.at(index_pf_gamma).vertex().x() - pv.position().x() - tau_funcs.getFlightLength(tau, tau_index).x(),
2062  0.001f,
2063  0.9565f);
2064  get(dnn::pfCand_gamma_vertex_dy_tauFL) = getValueNorm(
2065  pfCands.at(index_pf_gamma).vertex().y() - pv.position().y() - tau_funcs.getFlightLength(tau, tau_index).y(),
2066  0.0008f,
2067  0.9592f);
2068  get(dnn::pfCand_gamma_vertex_dz_tauFL) = getValueNorm(
2069  pfCands.at(index_pf_gamma).vertex().z() - pv.position().z() - tau_funcs.getFlightLength(tau, tau_index).z(),
2070  0.0038f,
2071  2.154f);
2072  const bool hasTrackDetails = candFunc::getHasTrackDetails(gamma_cand);
2073  if (hasTrackDetails) {
2074  get(dnn::pfCand_gamma_hasTrackDetails) = hasTrackDetails;
2075  get(dnn::pfCand_gamma_dxy) = getValueNorm(candFunc::getTauDxy(gamma_cand), 0.0004f, 0.882f);
2076  get(dnn::pfCand_gamma_dxy_sig) =
2077  getValueNorm(std::abs(candFunc::getTauDxy(gamma_cand)) / gamma_cand.dxyError(), 4.271f, 63.78f);
2078  get(dnn::pfCand_gamma_dz) = getValueNorm(candFunc::getTauDz(gamma_cand), 0.0071f, 5.285f);
2079  get(dnn::pfCand_gamma_dz_sig) =
2080  getValueNorm(std::abs(candFunc::getTauDz(gamma_cand)) / gamma_cand.dzError(), 162.1f, 622.4f);
2081  get(dnn::pfCand_gamma_track_chi2_ndof) = candFunc::getPseudoTrack(gamma_cand).ndof() > 0
2082  ? getValueNorm(candFunc::getPseudoTrack(gamma_cand).chi2() /
2083  candFunc::getPseudoTrack(gamma_cand).ndof(),
2084  4.268f,
2085  15.47f)
2086  : 0;
2087  get(dnn::pfCand_gamma_track_ndof) =
2088  candFunc::getPseudoTrack(gamma_cand).ndof() > 0
2089  ? getValueNorm(candFunc::getPseudoTrack(gamma_cand).ndof(), 12.25f, 4.774f)
2090  : 0;
2091  }
2092  }
2093  if (valid_index_ele) {
2094  size_t index_ele = cell_map.at(CellObjectType::Electron);
2095 
2096  get(dnn::ele_valid) = valid_index_ele;
2097  get(dnn::ele_rel_pt) = getValueNorm(electrons->at(index_ele).polarP4().pt() / tau.polarP4().pt(),
2098  is_inner ? 1.067f : 0.5111f,
2099  is_inner ? 1.521f : 2.765f);
2100  get(dnn::ele_deta) = getValueLinear(electrons->at(index_ele).polarP4().eta() - tau.polarP4().eta(),
2101  is_inner ? -0.1f : -0.5f,
2102  is_inner ? 0.1f : 0.5f,
2103  false);
2104  get(dnn::ele_dphi) = getValueLinear(dPhi(tau.polarP4(), electrons->at(index_ele).polarP4()),
2105  is_inner ? -0.1f : -0.5f,
2106  is_inner ? 0.1f : 0.5f,
2107  false);
2108 
2109  float cc_ele_energy, cc_gamma_energy;
2110  int cc_n_gamma;
2111  const bool cc_valid =
2112  calculateElectronClusterVarsV2(electrons->at(index_ele), cc_ele_energy, cc_gamma_energy, cc_n_gamma);
2113  if (cc_valid) {
2114  get(dnn::ele_cc_valid) = cc_valid;
2115  get(dnn::ele_cc_ele_rel_energy) =
2116  getValueNorm(cc_ele_energy / electrons->at(index_ele).polarP4().pt(), 1.729f, 1.644f);
2117  get(dnn::ele_cc_gamma_rel_energy) = getValueNorm(cc_gamma_energy / cc_ele_energy, 0.1439f, 0.3284f);
2118  get(dnn::ele_cc_n_gamma) = getValueNorm(cc_n_gamma, 1.794f, 2.079f);
2119  }
2120  get(dnn::ele_rel_trackMomentumAtVtx) = getValueNorm(
2121  electrons->at(index_ele).trackMomentumAtVtx().R() / electrons->at(index_ele).polarP4().pt(), 1.531f, 1.424f);
2122  get(dnn::ele_rel_trackMomentumAtCalo) = getValueNorm(
2123  electrons->at(index_ele).trackMomentumAtCalo().R() / electrons->at(index_ele).polarP4().pt(), 1.531f, 1.424f);
2124  get(dnn::ele_rel_trackMomentumOut) = getValueNorm(
2125  electrons->at(index_ele).trackMomentumOut().R() / electrons->at(index_ele).polarP4().pt(), 0.7735f, 0.935f);
2126  get(dnn::ele_rel_trackMomentumAtEleClus) =
2127  getValueNorm(electrons->at(index_ele).trackMomentumAtEleClus().R() / electrons->at(index_ele).polarP4().pt(),
2128  0.7735f,
2129  0.935f);
2130  get(dnn::ele_rel_trackMomentumAtVtxWithConstraint) = getValueNorm(
2131  electrons->at(index_ele).trackMomentumAtVtxWithConstraint().R() / electrons->at(index_ele).polarP4().pt(),
2132  1.625f,
2133  1.581f);
2134  get(dnn::ele_rel_ecalEnergy) =
2135  getValueNorm(electrons->at(index_ele).ecalEnergy() / electrons->at(index_ele).polarP4().pt(), 1.993f, 1.308f);
2136  get(dnn::ele_ecalEnergy_sig) = getValueNorm(
2137  electrons->at(index_ele).ecalEnergy() / electrons->at(index_ele).ecalEnergyError(), 70.25f, 58.16f);
2138  get(dnn::ele_eSuperClusterOverP) = getValueNorm(electrons->at(index_ele).eSuperClusterOverP(), 2.432f, 15.13f);
2139  get(dnn::ele_eSeedClusterOverP) = getValueNorm(electrons->at(index_ele).eSeedClusterOverP(), 2.034f, 13.96f);
2140  get(dnn::ele_eSeedClusterOverPout) = getValueNorm(electrons->at(index_ele).eSeedClusterOverPout(), 6.64f, 36.8f);
2141  get(dnn::ele_eEleClusterOverPout) = getValueNorm(electrons->at(index_ele).eEleClusterOverPout(), 4.183f, 20.63f);
2142  get(dnn::ele_deltaEtaSuperClusterTrackAtVtx) =
2143  getValueNorm(electrons->at(index_ele).deltaEtaSuperClusterTrackAtVtx(), 0.f, 0.0363f);
2144  get(dnn::ele_deltaEtaSeedClusterTrackAtCalo) =
2145  getValueNorm(electrons->at(index_ele).deltaEtaSeedClusterTrackAtCalo(), -0.0001f, 0.0512f);
2146  get(dnn::ele_deltaEtaEleClusterTrackAtCalo) =
2147  getValueNorm(electrons->at(index_ele).deltaEtaEleClusterTrackAtCalo(), -0.0001f, 0.0541f);
2148  get(dnn::ele_deltaPhiEleClusterTrackAtCalo) =
2149  getValueNorm(electrons->at(index_ele).deltaPhiEleClusterTrackAtCalo(), 0.0002f, 0.0553f);
2150  get(dnn::ele_deltaPhiSuperClusterTrackAtVtx) =
2151  getValueNorm(electrons->at(index_ele).deltaPhiSuperClusterTrackAtVtx(), 0.0001f, 0.0523f);
2152  get(dnn::ele_deltaPhiSeedClusterTrackAtCalo) =
2153  getValueNorm(electrons->at(index_ele).deltaPhiSeedClusterTrackAtCalo(), 0.0004f, 0.0777f);
2154  get(dnn::ele_mvaInput_earlyBrem) = getValue(electrons->at(index_ele).mvaInput().earlyBrem);
2155  get(dnn::ele_mvaInput_lateBrem) = getValue(electrons->at(index_ele).mvaInput().lateBrem);
2156  get(dnn::ele_mvaInput_sigmaEtaEta) =
2157  getValueNorm(electrons->at(index_ele).mvaInput().sigmaEtaEta, 0.0008f, 0.0052f);
2158  get(dnn::ele_mvaInput_hadEnergy) = getValueNorm(electrons->at(index_ele).mvaInput().hadEnergy, 14.04f, 69.48f);
2159  get(dnn::ele_mvaInput_deltaEta) = getValueNorm(electrons->at(index_ele).mvaInput().deltaEta, 0.0099f, 0.0851f);
2160  const auto& gsfTrack = electrons->at(index_ele).gsfTrack();
2161  if (gsfTrack.isNonnull()) {
2162  get(dnn::ele_gsfTrack_normalizedChi2) = getValueNorm(gsfTrack->normalizedChi2(), 3.049f, 10.39f);
2163  get(dnn::ele_gsfTrack_numberOfValidHits) = getValueNorm(gsfTrack->numberOfValidHits(), 16.52f, 2.806f);
2164  get(dnn::ele_rel_gsfTrack_pt) =
2165  getValueNorm(gsfTrack->pt() / electrons->at(index_ele).polarP4().pt(), 1.355f, 16.81f);
2166  get(dnn::ele_gsfTrack_pt_sig) = getValueNorm(gsfTrack->pt() / gsfTrack->ptError(), 5.046f, 3.119f);
2167  }
2168  const auto& closestCtfTrack = electrons->at(index_ele).closestCtfTrackRef();
2169  const bool has_closestCtfTrack = closestCtfTrack.isNonnull();
2170  if (has_closestCtfTrack) {
2171  get(dnn::ele_has_closestCtfTrack) = has_closestCtfTrack;
2172  get(dnn::ele_closestCtfTrack_normalizedChi2) = getValueNorm(closestCtfTrack->normalizedChi2(), 2.411f, 6.98f);
2173  get(dnn::ele_closestCtfTrack_numberOfValidHits) =
2174  getValueNorm(closestCtfTrack->numberOfValidHits(), 15.16f, 5.26f);
2175  }
2176  }
2177  }
2178 
2179  template <typename CandidateCastType, typename TauCastType>
2180  void createMuonBlockInputs(unsigned idx,
2181  const TauCastType& tau,
2182  const size_t tau_index,
2183  const edm::RefToBase<reco::BaseTau> tau_ref,
2184  const reco::Vertex& pv,
2185  double rho,
2186  const std::vector<pat::Muon>* muons,
2187  const edm::View<reco::Candidate>& pfCands,
2188  const Cell& cell_map,
2189  TauFunc tau_funcs,
2190  bool is_inner) {
2191  namespace dnn = dnn_inputs_2017_v2::MuonBlockInputs;
2192 
2193  tensorflow::Tensor& inputs = *muonTensor_.at(is_inner);
2194 
2195  const auto& get = [&](int var_index) -> float& { return inputs.tensor<float, 4>()(idx, 0, 0, var_index); };
2196 
2197  const bool valid_index_pf_muon = cell_map.count(CellObjectType::PfCand_muon);
2198  const bool valid_index_muon = cell_map.count(CellObjectType::Muon);
2199 
2200  if (!cell_map.empty()) {
2201  get(dnn::rho) = getValueNorm(rho, 21.49f, 9.713f);
2202  get(dnn::tau_pt) = getValueLinear(tau.polarP4().pt(), 20.f, 1000.f, true);
2203  get(dnn::tau_eta) = getValueLinear(tau.polarP4().eta(), -2.3f, 2.3f, false);
2204  get(dnn::tau_inside_ecal_crack) = getValue(isInEcalCrack(tau.polarP4().eta()));
2205  }
2206  if (valid_index_pf_muon) {
2207  size_t index_pf_muon = cell_map.at(CellObjectType::PfCand_muon);
2208  const auto& muon_cand = dynamic_cast<const CandidateCastType&>(pfCands.at(index_pf_muon));
2209 
2210  get(dnn::pfCand_muon_valid) = valid_index_pf_muon;
2211  get(dnn::pfCand_muon_rel_pt) = getValueNorm(pfCands.at(index_pf_muon).polarP4().pt() / tau.polarP4().pt(),
2212  is_inner ? 0.9509f : 0.0861f,
2213  is_inner ? 0.4294f : 0.4065f);
2214  get(dnn::pfCand_muon_deta) = getValueLinear(pfCands.at(index_pf_muon).polarP4().eta() - tau.polarP4().eta(),
2215  is_inner ? -0.1f : -0.5f,
2216  is_inner ? 0.1f : 0.5f,
2217  false);
2218  get(dnn::pfCand_muon_dphi) = getValueLinear(dPhi(tau.polarP4(), pfCands.at(index_pf_muon).polarP4()),
2219  is_inner ? -0.1f : -0.5f,
2220  is_inner ? 0.1f : 0.5f,
2221  false);
2222  get(dnn::pfCand_muon_pvAssociationQuality) =
2223  getValueLinear<int>(candFunc::getPvAssocationQuality(muon_cand), 0, 7, true);
2224  get(dnn::pfCand_muon_fromPV) = getValueLinear<int>(candFunc::getFromPV(muon_cand), 0, 3, true);
2225  get(dnn::pfCand_muon_puppiWeight) = is_inner ? getValue(candFunc::getPuppiWeight(muon_cand, 0.9786588f))
2226  : getValue(candFunc::getPuppiWeight(muon_cand, 0.8132477f));
2227  get(dnn::pfCand_muon_charge) = getValue(muon_cand.charge());
2228  get(dnn::pfCand_muon_lostInnerHits) = getValue<int>(candFunc::getLostInnerHits(muon_cand, 0));
2229  get(dnn::pfCand_muon_numberOfPixelHits) =
2230  getValueLinear(candFunc::getNumberOfPixelHits(muon_cand, 0), 0, 11, true);
2231  get(dnn::pfCand_muon_vertex_dx) =
2232  getValueNorm(pfCands.at(index_pf_muon).vertex().x() - pv.position().x(), -0.0007f, 0.6869f);
2233  get(dnn::pfCand_muon_vertex_dy) =
2234  getValueNorm(pfCands.at(index_pf_muon).vertex().y() - pv.position().y(), 0.0001f, 0.6784f);
2235  get(dnn::pfCand_muon_vertex_dz) =
2236  getValueNorm(pfCands.at(index_pf_muon).vertex().z() - pv.position().z(), -0.0117f, 4.097f);
2237  get(dnn::pfCand_muon_vertex_dx_tauFL) = getValueNorm(
2238  pfCands.at(index_pf_muon).vertex().x() - pv.position().x() - tau_funcs.getFlightLength(tau, tau_index).x(),
2239  -0.0001f,
2240  0.8642f);
2241  get(dnn::pfCand_muon_vertex_dy_tauFL) = getValueNorm(
2242  pfCands.at(index_pf_muon).vertex().y() - pv.position().y() - tau_funcs.getFlightLength(tau, tau_index).y(),
2243  0.0004f,
2244  0.8561f);
2245  get(dnn::pfCand_muon_vertex_dz_tauFL) = getValueNorm(
2246  pfCands.at(index_pf_muon).vertex().z() - pv.position().z() - tau_funcs.getFlightLength(tau, tau_index).z(),
2247  -0.0118f,
2248  4.405f);
2249 
2250  const bool hasTrackDetails = candFunc::getHasTrackDetails(muon_cand);
2251  if (hasTrackDetails) {
2252  get(dnn::pfCand_muon_hasTrackDetails) = hasTrackDetails;
2253  get(dnn::pfCand_muon_dxy) = getValueNorm(candFunc::getTauDxy(muon_cand), -0.0045f, 0.9655f);
2254  get(dnn::pfCand_muon_dxy_sig) =
2255  getValueNorm(std::abs(candFunc::getTauDxy(muon_cand)) / muon_cand.dxyError(), 4.575f, 42.36f);
2256  get(dnn::pfCand_muon_dz) = getValueNorm(candFunc::getTauDz(muon_cand), -0.0117f, 4.097f);
2257  get(dnn::pfCand_muon_dz_sig) =
2258  getValueNorm(std::abs(candFunc::getTauDz(muon_cand)) / muon_cand.dzError(), 80.37f, 343.3f);
2259  get(dnn::pfCand_muon_track_chi2_ndof) = getValueNorm(
2260  candFunc::getPseudoTrack(muon_cand).chi2() / candFunc::getPseudoTrack(muon_cand).ndof(), 0.69f, 1.711f);
2261  get(dnn::pfCand_muon_track_ndof) = getValueNorm(candFunc::getPseudoTrack(muon_cand).ndof(), 17.5f, 5.11f);
2262  }
2263  }
2264  if (valid_index_muon) {
2265  size_t index_muon = cell_map.at(CellObjectType::Muon);
2266 
2267  get(dnn::muon_valid) = valid_index_muon;
2268  get(dnn::muon_rel_pt) = getValueNorm(muons->at(index_muon).polarP4().pt() / tau.polarP4().pt(),
2269  is_inner ? 0.7966f : 0.2678f,
2270  is_inner ? 3.402f : 3.592f);
2271  get(dnn::muon_deta) = getValueLinear(muons->at(index_muon).polarP4().eta() - tau.polarP4().eta(),
2272  is_inner ? -0.1f : -0.5f,
2273  is_inner ? 0.1f : 0.5f,
2274  false);
2275  get(dnn::muon_dphi) = getValueLinear(dPhi(tau.polarP4(), muons->at(index_muon).polarP4()),
2276  is_inner ? -0.1f : -0.5f,
2277  is_inner ? 0.1f : 0.5f,
2278  false);
2279  get(dnn::muon_dxy) = getValueNorm(muons->at(index_muon).dB(pat::Muon::PV2D), 0.0019f, 1.039f);
2280  get(dnn::muon_dxy_sig) =
2281  getValueNorm(std::abs(muons->at(index_muon).dB(pat::Muon::PV2D)) / muons->at(index_muon).edB(pat::Muon::PV2D),
2282  8.98f,
2283  71.17f);
2284 
2285  const bool normalizedChi2_valid =
2286  muons->at(index_muon).globalTrack().isNonnull() && muons->at(index_muon).normChi2() >= 0;
2287  if (normalizedChi2_valid) {
2288  get(dnn::muon_normalizedChi2_valid) = normalizedChi2_valid;
2289  get(dnn::muon_normalizedChi2) = getValueNorm(muons->at(index_muon).normChi2(), 21.52f, 265.8f);
2290  if (muons->at(index_muon).innerTrack().isNonnull())
2291  get(dnn::muon_numberOfValidHits) = getValueNorm(muons->at(index_muon).numberOfValidHits(), 21.84f, 10.59f);
2292  }
2293  get(dnn::muon_segmentCompatibility) = getValue(muons->at(index_muon).segmentCompatibility());
2294  get(dnn::muon_caloCompatibility) = getValue(muons->at(index_muon).caloCompatibility());
2295 
2296  const bool pfEcalEnergy_valid = muons->at(index_muon).pfEcalEnergy() >= 0;
2297  if (pfEcalEnergy_valid) {
2298  get(dnn::muon_pfEcalEnergy_valid) = pfEcalEnergy_valid;
2299  get(dnn::muon_rel_pfEcalEnergy) =
2300  getValueNorm(muons->at(index_muon).pfEcalEnergy() / muons->at(index_muon).polarP4().pt(), 0.2273f, 0.4865f);
2301  }
2302 
2303  MuonHitMatchV2 hit_match(muons->at(index_muon));
2304  static const std::map<int, std::pair<int, int>> muonMatchHitVars = {
2305  {MuonSubdetId::DT, {dnn::muon_n_matches_DT_1, dnn::muon_n_hits_DT_1}},
2306  {MuonSubdetId::CSC, {dnn::muon_n_matches_CSC_1, dnn::muon_n_hits_CSC_1}},
2307  {MuonSubdetId::RPC, {dnn::muon_n_matches_RPC_1, dnn::muon_n_hits_RPC_1}}};
2308 
2309  static const std::map<int, std::vector<float>> muonMatchVarLimits = {
2310  {MuonSubdetId::DT, {2, 2, 2, 2}}, {MuonSubdetId::CSC, {6, 2, 2, 2}}, {MuonSubdetId::RPC, {7, 6, 4, 4}}};
2311 
2312  static const std::map<int, std::vector<float>> muonHitVarLimits = {{MuonSubdetId::DT, {12, 12, 12, 8}},
2313  {MuonSubdetId::CSC, {24, 12, 12, 12}},
2314  {MuonSubdetId::RPC, {4, 4, 2, 2}}};
2315 
2316  for (int subdet : hit_match.MuonHitMatchV2::consideredSubdets()) {
2317  const auto& matchHitVar = muonMatchHitVars.at(subdet);
2318  const auto& matchLimits = muonMatchVarLimits.at(subdet);
2319  const auto& hitLimits = muonHitVarLimits.at(subdet);
2320  for (int station = MuonHitMatchV2::first_station_id; station <= MuonHitMatchV2::last_station_id; ++station) {
2321  const unsigned n_matches = hit_match.nMatches(subdet, station);
2322  const unsigned n_hits = hit_match.nHits(subdet, station);
2323  get(matchHitVar.first + station - 1) = getValueLinear(n_matches, 0, matchLimits.at(station - 1), true);
2324  get(matchHitVar.second + station - 1) = getValueLinear(n_hits, 0, hitLimits.at(station - 1), true);
2325  }
2326  }
2327  }
2328  }
2329 
2330  template <typename CandidateCastType, typename TauCastType>
2331  void createHadronsBlockInputs(unsigned idx,
2332  const TauCastType& tau,
2333  const size_t tau_index,
2334  const edm::RefToBase<reco::BaseTau> tau_ref,
2335  const reco::Vertex& pv,
2336  double rho,
2337  const edm::View<reco::Candidate>& pfCands,
2338  const Cell& cell_map,
2339  TauFunc tau_funcs,
2340  bool is_inner) {
2341  namespace dnn = dnn_inputs_2017_v2::HadronBlockInputs;
2342 
2343  tensorflow::Tensor& inputs = *hadronsTensor_.at(is_inner);
2344 
2345  const auto& get = [&](int var_index) -> float& { return inputs.tensor<float, 4>()(idx, 0, 0, var_index); };
2346 
2347  const bool valid_chH = cell_map.count(CellObjectType::PfCand_chargedHadron);
2348  const bool valid_nH = cell_map.count(CellObjectType::PfCand_neutralHadron);
2349 
2350  if (!cell_map.empty()) {
2351  get(dnn::rho) = getValueNorm(rho, 21.49f, 9.713f);
2352  get(dnn::tau_pt) = getValueLinear(tau.polarP4().pt(), 20.f, 1000.f, true);
2353  get(dnn::tau_eta) = getValueLinear(tau.polarP4().eta(), -2.3f, 2.3f, false);
2354  get(dnn::tau_inside_ecal_crack) = getValue(isInEcalCrack(tau.polarP4().eta()));
2355  }
2356  if (valid_chH) {
2357  size_t index_chH = cell_map.at(CellObjectType::PfCand_chargedHadron);
2358  const auto& chH_cand = dynamic_cast<const CandidateCastType&>(pfCands.at(index_chH));
2359 
2360  get(dnn::pfCand_chHad_valid) = valid_chH;
2361  get(dnn::pfCand_chHad_rel_pt) = getValueNorm(pfCands.at(index_chH).polarP4().pt() / tau.polarP4().pt(),
2362  is_inner ? 0.2564f : 0.0194f,
2363  is_inner ? 0.8607f : 0.1865f);
2364  get(dnn::pfCand_chHad_deta) = getValueLinear(pfCands.at(index_chH).polarP4().eta() - tau.polarP4().eta(),
2365  is_inner ? -0.1f : -0.5f,
2366  is_inner ? 0.1f : 0.5f,
2367  false);
2368  get(dnn::pfCand_chHad_dphi) = getValueLinear(dPhi(tau.polarP4(), pfCands.at(index_chH).polarP4()),
2369  is_inner ? -0.1f : -0.5f,
2370  is_inner ? 0.1f : 0.5f,
2371  false);
2372  get(dnn::pfCand_chHad_leadChargedHadrCand) =
2373  getValue(&chH_cand == dynamic_cast<const CandidateCastType*>(tau.leadChargedHadrCand().get()));
2374  get(dnn::pfCand_chHad_pvAssociationQuality) =
2375  getValueLinear<int>(candFunc::getPvAssocationQuality(chH_cand), 0, 7, true);
2376  get(dnn::pfCand_chHad_fromPV) = getValueLinear<int>(candFunc::getFromPV(chH_cand), 0, 3, true);
2377  const float default_chH_pw_inner = 0.7614090f;
2378  const float default_chH_pw_outer = 0.1974930f;
2379  get(dnn::pfCand_chHad_puppiWeight) = is_inner
2380  ? getValue(candFunc::getPuppiWeight(chH_cand, default_chH_pw_inner))
2381  : getValue(candFunc::getPuppiWeight(chH_cand, default_chH_pw_outer));
2382  get(dnn::pfCand_chHad_puppiWeightNoLep) =
2383  is_inner ? getValue(candFunc::getPuppiWeightNoLep(chH_cand, default_chH_pw_inner))
2384  : getValue(candFunc::getPuppiWeightNoLep(chH_cand, default_chH_pw_outer));
2385  get(dnn::pfCand_chHad_charge) = getValue(chH_cand.charge());
2386  get(dnn::pfCand_chHad_lostInnerHits) = getValue<int>(candFunc::getLostInnerHits(chH_cand, 0));
2387  get(dnn::pfCand_chHad_numberOfPixelHits) =
2388  getValueLinear(candFunc::getNumberOfPixelHits(chH_cand, 0), 0, 12, true);
2389  get(dnn::pfCand_chHad_vertex_dx) =
2390  getValueNorm(pfCands.at(index_chH).vertex().x() - pv.position().x(), 0.0005f, 1.735f);
2391  get(dnn::pfCand_chHad_vertex_dy) =
2392  getValueNorm(pfCands.at(index_chH).vertex().y() - pv.position().y(), -0.0008f, 1.752f);
2393  get(dnn::pfCand_chHad_vertex_dz) =
2394  getValueNorm(pfCands.at(index_chH).vertex().z() - pv.position().z(), -0.0201f, 8.333f);
2395  get(dnn::pfCand_chHad_vertex_dx_tauFL) = getValueNorm(
2396  pfCands.at(index_chH).vertex().x() - pv.position().x() - tau_funcs.getFlightLength(tau, tau_index).x(),
2397  -0.0014f,
2398  1.93f);
2399  get(dnn::pfCand_chHad_vertex_dy_tauFL) = getValueNorm(
2400  pfCands.at(index_chH).vertex().y() - pv.position().y() - tau_funcs.getFlightLength(tau, tau_index).y(),
2401  0.0022f,
2402  1.948f);
2403  get(dnn::pfCand_chHad_vertex_dz_tauFL) = getValueNorm(
2404  pfCands.at(index_chH).vertex().z() - pv.position().z() - tau_funcs.getFlightLength(tau, tau_index).z(),
2405  -0.0138f,
2406  8.622f);
2407 
2408  const bool hasTrackDetails = candFunc::getHasTrackDetails(chH_cand);
2409  if (hasTrackDetails) {
2410  get(dnn::pfCand_chHad_hasTrackDetails) = hasTrackDetails;
2411  get(dnn::pfCand_chHad_dxy) = getValueNorm(candFunc::getTauDxy(chH_cand), -0.012f, 2.386f);
2412  get(dnn::pfCand_chHad_dxy_sig) =
2413  getValueNorm(std::abs(candFunc::getTauDxy(chH_cand)) / chH_cand.dxyError(), 6.417f, 36.28f);
2414  get(dnn::pfCand_chHad_dz) = getValueNorm(candFunc::getTauDz(chH_cand), -0.0246f, 7.618f);
2415  get(dnn::pfCand_chHad_dz_sig) =
2416  getValueNorm(std::abs(candFunc::getTauDz(chH_cand)) / chH_cand.dzError(), 301.3f, 491.1f);
2417  get(dnn::pfCand_chHad_track_chi2_ndof) =
2418  candFunc::getPseudoTrack(chH_cand).ndof() > 0
2419  ? getValueNorm(candFunc::getPseudoTrack(chH_cand).chi2() / candFunc::getPseudoTrack(chH_cand).ndof(),
2420  0.7876f,
2421  3.694f)
2422  : 0;
2423  get(dnn::pfCand_chHad_track_ndof) =
2424  candFunc::getPseudoTrack(chH_cand).ndof() > 0
2425  ? getValueNorm(candFunc::getPseudoTrack(chH_cand).ndof(), 13.92f, 6.581f)
2426  : 0;
2427  }
2428  float hcal_fraction = candFunc::getHCalFraction(chH_cand, disable_hcalFraction_workaround_);
2429  get(dnn::pfCand_chHad_hcalFraction) = getValue(hcal_fraction);
2430  get(dnn::pfCand_chHad_rawCaloFraction) = getValueLinear(candFunc::getRawCaloFraction(chH_cand), 0.f, 2.6f, true);
2431  }
2432  if (valid_nH) {
2433  size_t index_nH = cell_map.at(CellObjectType::PfCand_neutralHadron);
2434  const auto& nH_cand = dynamic_cast<const CandidateCastType&>(pfCands.at(index_nH));
2435 
2436  get(dnn::pfCand_nHad_valid) = valid_nH;
2437  get(dnn::pfCand_nHad_rel_pt) = getValueNorm(pfCands.at(index_nH).polarP4().pt() / tau.polarP4().pt(),
2438  is_inner ? 0.3163f : 0.0502f,
2439  is_inner ? 0.2769f : 0.4266f);
2440  get(dnn::pfCand_nHad_deta) = getValueLinear(pfCands.at(index_nH).polarP4().eta() - tau.polarP4().eta(),
2441  is_inner ? -0.1f : -0.5f,
2442  is_inner ? 0.1f : 0.5f,
2443  false);
2444  get(dnn::pfCand_nHad_dphi) = getValueLinear(
2445  dPhi(tau.polarP4(), pfCands.at(index_nH).polarP4()), is_inner ? -0.1f : -0.5f, is_inner ? 0.1f : 0.5f, false);
2446  get(dnn::pfCand_nHad_puppiWeight) = is_inner ? getValue(candFunc::getPuppiWeight(nH_cand, 0.9798355f))
2447  : getValue(candFunc::getPuppiWeight(nH_cand, 0.7813260f));
2448  get(dnn::pfCand_nHad_puppiWeightNoLep) = is_inner ? getValue(candFunc::getPuppiWeightNoLep(nH_cand, 0.9046796f))
2449  : getValue(candFunc::getPuppiWeightNoLep(nH_cand, 0.6554860f));
2450  float hcal_fraction = candFunc::getHCalFraction(nH_cand, disable_hcalFraction_workaround_);
2451  get(dnn::pfCand_nHad_hcalFraction) = getValue(hcal_fraction);
2452  }
2453  }
2454 
2455  template <typename dnn, typename CandidateCastType, typename TauCastType>
2456  tensorflow::Tensor createInputsV1(const TauCastType& tau,
2457  const size_t tau_index,
2458  const edm::RefToBase<reco::BaseTau> tau_ref,
2459  const std::vector<pat::Electron>* electrons,
2460  const std::vector<pat::Muon>* muons,
2461  TauFunc tau_funcs) const {
2462  static constexpr bool check_all_set = false;
2463  static constexpr float default_value_for_set_check = -42;
2464 
2465  tensorflow::Tensor inputs(tensorflow::DT_FLOAT, {1, dnn_inputs_2017v1::NumberOfInputs});
2466  const auto& get = [&](int var_index) -> float& { return inputs.matrix<float>()(0, var_index); };
2467  auto leadChargedHadrCand = dynamic_cast<const CandidateCastType*>(tau.leadChargedHadrCand().get());
2468 
2469  if (check_all_set) {
2470  for (int var_index = 0; var_index < dnn::NumberOfInputs; ++var_index) {
2471  get(var_index) = default_value_for_set_check;
2472  }
2473  }
2474 
2475  get(dnn::pt) = tau.p4().pt();
2476  get(dnn::eta) = tau.p4().eta();
2477  get(dnn::mass) = tau.p4().mass();
2478  get(dnn::decayMode) = tau.decayMode();
2479  get(dnn::chargedIsoPtSum) = tau_funcs.getChargedIsoPtSum(tau, tau_ref);
2480  get(dnn::neutralIsoPtSum) = tau_funcs.getNeutralIsoPtSum(tau, tau_ref);
2481  get(dnn::neutralIsoPtSumWeight) = tau_funcs.getNeutralIsoPtSumWeight(tau, tau_ref);
2482  get(dnn::photonPtSumOutsideSignalCone) = tau_funcs.getPhotonPtSumOutsideSignalCone(tau, tau_ref);
2483  get(dnn::puCorrPtSum) = tau_funcs.getPuCorrPtSum(tau, tau_ref);
2484  get(dnn::dxy) = tau_funcs.getdxy(tau, tau_index);
2485  get(dnn::dxy_sig) = tau_funcs.getdxySig(tau, tau_index);
2486  get(dnn::dz) = leadChargedHadrCand ? candFunc::getTauDz(*leadChargedHadrCand) : default_value;
2487  get(dnn::ip3d) = tau_funcs.getip3d(tau, tau_index);
2488  get(dnn::ip3d_sig) = tau_funcs.getip3dSig(tau, tau_index);
2489  get(dnn::hasSecondaryVertex) = tau_funcs.getHasSecondaryVertex(tau, tau_index);
2490  get(dnn::flightLength_r) = tau_funcs.getFlightLength(tau, tau_index).R();
2491  get(dnn::flightLength_dEta) = dEta(tau_funcs.getFlightLength(tau, tau_index), tau.p4());
2492  get(dnn::flightLength_dPhi) = dPhi(tau_funcs.getFlightLength(tau, tau_index), tau.p4());
2493  get(dnn::flightLength_sig) = tau_funcs.getFlightLengthSig(tau, tau_index);
2494  get(dnn::leadChargedHadrCand_pt) = leadChargedHadrCand ? leadChargedHadrCand->p4().Pt() : default_value;
2495  get(dnn::leadChargedHadrCand_dEta) =
2496  leadChargedHadrCand ? dEta(leadChargedHadrCand->p4(), tau.p4()) : default_value;
2497  get(dnn::leadChargedHadrCand_dPhi) =
2498  leadChargedHadrCand ? dPhi(leadChargedHadrCand->p4(), tau.p4()) : default_value;
2499  get(dnn::leadChargedHadrCand_mass) = leadChargedHadrCand ? leadChargedHadrCand->p4().mass() : default_value;
2502  get(dnn::pt_weighted_dr_signal) = reco::tau::pt_weighted_dr_signal(tau, tau.decayMode());
2503  get(dnn::pt_weighted_dr_iso) = reco::tau::pt_weighted_dr_iso(tau, tau.decayMode());
2504  get(dnn::leadingTrackNormChi2) = tau_funcs.getLeadingTrackNormChi2(tau);
2505  get(dnn::e_ratio) = reco::tau::eratio(tau);
2506  get(dnn::gj_angle_diff) = calculateGottfriedJacksonAngleDifference(tau, tau_index, tau_funcs);
2507  get(dnn::n_photons) = reco::tau::n_photons_total(tau);
2508  get(dnn::emFraction) = tau_funcs.getEmFraction(tau);
2509  get(dnn::has_gsf_track) = leadChargedHadrCand && std::abs(leadChargedHadrCand->pdgId()) == 11;
2510  get(dnn::inside_ecal_crack) = isInEcalCrack(tau.p4().Eta());
2511  auto gsf_ele = findMatchedElectron(tau, electrons, 0.3);
2512  get(dnn::gsf_ele_matched) = gsf_ele != nullptr;
2513  get(dnn::gsf_ele_pt) = gsf_ele != nullptr ? gsf_ele->p4().Pt() : default_value;
2514  get(dnn::gsf_ele_dEta) = gsf_ele != nullptr ? dEta(gsf_ele->p4(), tau.p4()) : default_value;
2515  get(dnn::gsf_ele_dPhi) = gsf_ele != nullptr ? dPhi(gsf_ele->p4(), tau.p4()) : default_value;
2516  get(dnn::gsf_ele_mass) = gsf_ele != nullptr ? gsf_ele->p4().mass() : default_value;
2517  calculateElectronClusterVars(gsf_ele, get(dnn::gsf_ele_Ee), get(dnn::gsf_ele_Egamma));
2518  get(dnn::gsf_ele_Pin) = gsf_ele != nullptr ? gsf_ele->trackMomentumAtVtx().R() : default_value;
2519  get(dnn::gsf_ele_Pout) = gsf_ele != nullptr ? gsf_ele->trackMomentumOut().R() : default_value;
2520  get(dnn::gsf_ele_EtotOverPin) = get(dnn::gsf_ele_Pin) > 0
2521  ? (get(dnn::gsf_ele_Ee) + get(dnn::gsf_ele_Egamma)) / get(dnn::gsf_ele_Pin)
2522  : default_value;
2523  get(dnn::gsf_ele_Eecal) = gsf_ele != nullptr ? gsf_ele->ecalEnergy() : default_value;
2524  get(dnn::gsf_ele_dEta_SeedClusterTrackAtCalo) =
2525  gsf_ele != nullptr ? gsf_ele->deltaEtaSeedClusterTrackAtCalo() : default_value;
2526  get(dnn::gsf_ele_dPhi_SeedClusterTrackAtCalo) =
2527  gsf_ele != nullptr ? gsf_ele->deltaPhiSeedClusterTrackAtCalo() : default_value;
2528  get(dnn::gsf_ele_mvaIn_sigmaEtaEta) = gsf_ele != nullptr ? gsf_ele->mvaInput().sigmaEtaEta : default_value;
2529  get(dnn::gsf_ele_mvaIn_hadEnergy) = gsf_ele != nullptr ? gsf_ele->mvaInput().hadEnergy : default_value;
2530  get(dnn::gsf_ele_mvaIn_deltaEta) = gsf_ele != nullptr ? gsf_ele->mvaInput().deltaEta : default_value;
2531 
2532  get(dnn::gsf_ele_Chi2NormGSF) = default_value;
2533  get(dnn::gsf_ele_GSFNumHits) = default_value;
2534  get(dnn::gsf_ele_GSFTrackResol) = default_value;
2535  get(dnn::gsf_ele_GSFTracklnPt) = default_value;
2536  if (gsf_ele != nullptr && gsf_ele->gsfTrack().isNonnull()) {
2537  get(dnn::gsf_ele_Chi2NormGSF) = gsf_ele->gsfTrack()->normalizedChi2();
2538  get(dnn::gsf_ele_GSFNumHits) = gsf_ele->gsfTrack()->numberOfValidHits();
2539  if (gsf_ele->gsfTrack()->pt() > 0) {
2540  get(dnn::gsf_ele_GSFTrackResol) = gsf_ele->gsfTrack()->ptError() / gsf_ele->gsfTrack()->pt();
2541  get(dnn::gsf_ele_GSFTracklnPt) = std::log10(gsf_ele->gsfTrack()->pt());
2542  }
2543  }
2544 
2545  get(dnn::gsf_ele_Chi2NormKF) = default_value;
2546  get(dnn::gsf_ele_KFNumHits) = default_value;
2547  if (gsf_ele != nullptr && gsf_ele->closestCtfTrackRef().isNonnull()) {
2548  get(dnn::gsf_ele_Chi2NormKF) = gsf_ele->closestCtfTrackRef()->normalizedChi2();
2549  get(dnn::gsf_ele_KFNumHits) = gsf_ele->closestCtfTrackRef()->numberOfValidHits();
2550  }
2551  get(dnn::leadChargedCand_etaAtEcalEntrance) = tau_funcs.getEtaAtEcalEntrance(tau);
2552  get(dnn::leadChargedCand_pt) = leadChargedHadrCand->pt();
2553 
2554  get(dnn::leadChargedHadrCand_HoP) = default_value;
2555  get(dnn::leadChargedHadrCand_EoP) = default_value;
2556  if (leadChargedHadrCand->pt() > 0) {
2557  get(dnn::leadChargedHadrCand_HoP) = tau_funcs.getEcalEnergyLeadingChargedHadr(tau) / leadChargedHadrCand->pt();
2558  get(dnn::leadChargedHadrCand_EoP) = tau_funcs.getHcalEnergyLeadingChargedHadr(tau) / leadChargedHadrCand->pt();
2559  }
2560 
2561  MuonHitMatchV1 muon_hit_match;
2562  if (tau.leadPFChargedHadrCand().isNonnull() && tau.leadPFChargedHadrCand()->muonRef().isNonnull())
2563  muon_hit_match.addMatchedMuon(*tau.leadPFChargedHadrCand()->muonRef(), tau);
2564 
2565  auto matched_muons = muon_hit_match.findMatchedMuons(tau, muons, 0.3, 5);
2566  for (auto muon : matched_muons)
2567  muon_hit_match.addMatchedMuon(*muon, tau);
2568  muon_hit_match.fillTensor<dnn>(get, tau, default_value);
2569 
2570  LorentzVectorXYZ signalChargedHadrCands_sumIn, signalChargedHadrCands_sumOut;
2572  tau.signalChargedHadrCands(),
2573  signalChargedHadrCands_sumIn,
2574  signalChargedHadrCands_sumOut,
2575  get(dnn::signalChargedHadrCands_sum_innerSigCone_pt),
2576  get(dnn::signalChargedHadrCands_sum_innerSigCone_dEta),
2577  get(dnn::signalChargedHadrCands_sum_innerSigCone_dPhi),
2578  get(dnn::signalChargedHadrCands_sum_innerSigCone_mass),
2579  get(dnn::signalChargedHadrCands_sum_outerSigCone_pt),
2580  get(dnn::signalChargedHadrCands_sum_outerSigCone_dEta),
2581  get(dnn::signalChargedHadrCands_sum_outerSigCone_dPhi),
2582  get(dnn::signalChargedHadrCands_sum_outerSigCone_mass),
2583  get(dnn::signalChargedHadrCands_nTotal_innerSigCone),
2584  get(dnn::signalChargedHadrCands_nTotal_outerSigCone));
2585 
2586  LorentzVectorXYZ signalNeutrHadrCands_sumIn, signalNeutrHadrCands_sumOut;
2588  tau.signalNeutrHadrCands(),
2589  signalNeutrHadrCands_sumIn,
2590  signalNeutrHadrCands_sumOut,
2591  get(dnn::signalNeutrHadrCands_sum_innerSigCone_pt),
2592  get(dnn::signalNeutrHadrCands_sum_innerSigCone_dEta),
2593  get(dnn::signalNeutrHadrCands_sum_innerSigCone_dPhi),
2594  get(dnn::signalNeutrHadrCands_sum_innerSigCone_mass),
2595  get(dnn::signalNeutrHadrCands_sum_outerSigCone_pt),
2596  get(dnn::signalNeutrHadrCands_sum_outerSigCone_dEta),
2597  get(dnn::signalNeutrHadrCands_sum_outerSigCone_dPhi),
2598  get(dnn::signalNeutrHadrCands_sum_outerSigCone_mass),
2599  get(dnn::signalNeutrHadrCands_nTotal_innerSigCone),
2600  get(dnn::signalNeutrHadrCands_nTotal_outerSigCone));
2601 
2602  LorentzVectorXYZ signalGammaCands_sumIn, signalGammaCands_sumOut;
2604  tau.signalGammaCands(),
2605  signalGammaCands_sumIn,
2606  signalGammaCands_sumOut,
2607  get(dnn::signalGammaCands_sum_innerSigCone_pt),
2608  get(dnn::signalGammaCands_sum_innerSigCone_dEta),
2609  get(dnn::signalGammaCands_sum_innerSigCone_dPhi),
2610  get(dnn::signalGammaCands_sum_innerSigCone_mass),
2611  get(dnn::signalGammaCands_sum_outerSigCone_pt),
2612  get(dnn::signalGammaCands_sum_outerSigCone_dEta),
2613  get(dnn::signalGammaCands_sum_outerSigCone_dPhi),
2614  get(dnn::signalGammaCands_sum_outerSigCone_mass),
2615  get(dnn::signalGammaCands_nTotal_innerSigCone),
2616  get(dnn::signalGammaCands_nTotal_outerSigCone));
2617 
2618  LorentzVectorXYZ isolationChargedHadrCands_sum;
2620  tau.isolationChargedHadrCands(),
2621  isolationChargedHadrCands_sum,
2622  get(dnn::isolationChargedHadrCands_sum_pt),
2623  get(dnn::isolationChargedHadrCands_sum_dEta),
2624  get(dnn::isolationChargedHadrCands_sum_dPhi),
2625  get(dnn::isolationChargedHadrCands_sum_mass),
2626  get(dnn::isolationChargedHadrCands_nTotal));
2627 
2628  LorentzVectorXYZ isolationNeutrHadrCands_sum;
2630  tau.isolationNeutrHadrCands(),
2631  isolationNeutrHadrCands_sum,
2632  get(dnn::isolationNeutrHadrCands_sum_pt),
2633  get(dnn::isolationNeutrHadrCands_sum_dEta),
2634  get(dnn::isolationNeutrHadrCands_sum_dPhi),
2635  get(dnn::isolationNeutrHadrCands_sum_mass),
2636  get(dnn::isolationNeutrHadrCands_nTotal));
2637 
2638  LorentzVectorXYZ isolationGammaCands_sum;
2640  tau.isolationGammaCands(),
2641  isolationGammaCands_sum,
2642  get(dnn::isolationGammaCands_sum_pt),
2643  get(dnn::isolationGammaCands_sum_dEta),
2644  get(dnn::isolationGammaCands_sum_dPhi),
2645  get(dnn::isolationGammaCands_sum_mass),
2646  get(dnn::isolationGammaCands_nTotal));
2647 
2648  get(dnn::tau_visMass_innerSigCone) = (signalGammaCands_sumIn + signalChargedHadrCands_sumIn).mass();
2649 
2650  if (check_all_set) {
2651  for (int var_index = 0; var_index < dnn::NumberOfInputs; ++var_index) {
2652  if (get(var_index) == default_value_for_set_check)
2653  throw cms::Exception("DeepTauId: variable with index = ") << var_index << " is not set.";
2654  }
2655  }
2656 
2657  return inputs;
2658  }
2659 
2660  static void calculateElectronClusterVars(const pat::Electron* ele, float& elecEe, float& elecEgamma) {
2661  if (ele) {
2662  elecEe = elecEgamma = 0;
2663  auto superCluster = ele->superCluster();
2664  if (superCluster.isNonnull() && superCluster.isAvailable() && superCluster->clusters().isNonnull() &&
2665  superCluster->clusters().isAvailable()) {
2666  for (auto iter = superCluster->clustersBegin(); iter != superCluster->clustersEnd(); ++iter) {
2667  const double energy = (*iter)->energy();
2668  if (iter == superCluster->clustersBegin())
2669  elecEe += energy;
2670  else
2671  elecEgamma += energy;
2672  }
2673  }
2674  } else {
2675  elecEe = elecEgamma = default_value;
2676  }
2677  }
2678 
2679  template <typename CandidateCollection, typename TauCastType>
2680  static void processSignalPFComponents(const TauCastType& tau,
2682  LorentzVectorXYZ& p4_inner,
2683  LorentzVectorXYZ& p4_outer,
2684  float& pt_inner,
2685  float& dEta_inner,
2686  float& dPhi_inner,
2687  float& m_inner,
2688  float& pt_outer,
2689  float& dEta_outer,
2690  float& dPhi_outer,
2691  float& m_outer,
2692  float& n_inner,
2693  float& n_outer) {
2694  p4_inner = LorentzVectorXYZ(0, 0, 0, 0);
2695  p4_outer = LorentzVectorXYZ(0, 0, 0, 0);
2696  n_inner = 0;
2697  n_outer = 0;
2698 
2699  const double innerSigCone_radius = getInnerSignalConeRadius(tau.pt());
2700  for (const auto& cand : candidates) {
2701  const double dR = reco::deltaR(cand->p4(), tau.leadChargedHadrCand()->p4());
2702  const bool isInside_innerSigCone = dR < innerSigCone_radius;
2703  if (isInside_innerSigCone) {
2704  p4_inner += cand->p4();
2705  ++n_inner;
2706  } else {
2707  p4_outer += cand->p4();
2708  ++n_outer;
2709  }
2710  }
2711 
2712  pt_inner = n_inner != 0 ? p4_inner.Pt() : default_value;
2713  dEta_inner = n_inner != 0 ? dEta(p4_inner, tau.p4()) : default_value;
2714  dPhi_inner = n_inner != 0 ? dPhi(p4_inner, tau.p4()) : default_value;
2715  m_inner = n_inner != 0 ? p4_inner.mass() : default_value;
2716 
2717  pt_outer = n_outer != 0 ? p4_outer.Pt() : default_value;
2718  dEta_outer = n_outer != 0 ? dEta(p4_outer, tau.p4()) : default_value;
2719  dPhi_outer = n_outer != 0 ? dPhi(p4_outer, tau.p4()) : default_value;
2720  m_outer = n_outer != 0 ? p4_outer.mass() : default_value;
2721  }
2722 
2723  template <typename CandidateCollection, typename TauCastType>
2724  static void processIsolationPFComponents(const TauCastType& tau,
2726  LorentzVectorXYZ& p4,
2727  float& pt,
2728  float& d_eta,
2729  float& d_phi,
2730  float& m,
2731  float& n) {
2732  p4 = LorentzVectorXYZ(0, 0, 0, 0);
2733  n = 0;
2734 
2735  for (const auto& cand : candidates) {
2736  p4 += cand->p4();
2737  ++n;
2738  }
2739 
2740  pt = n != 0 ? p4.Pt() : default_value;
2741  d_eta = n != 0 ? dEta(p4, tau.p4()) : default_value;
2742  d_phi = n != 0 ? dPhi(p4, tau.p4()) : default_value;
2743  m = n != 0 ? p4.mass() : default_value;
2744  }
2745 
2746  static double getInnerSignalConeRadius(double pt) {
2747  static constexpr double min_pt = 30., min_radius = 0.05, cone_opening_coef = 3.;
2748  // This is equivalent of the original formula (std::max(std::min(0.1, 3.0/pt), 0.05)
2749  return std::max(cone_opening_coef / std::max(pt, min_pt), min_radius);
2750  }
2751 
2752  // Copied from https://github.com/cms-sw/cmssw/blob/CMSSW_9_4_X/RecoTauTag/RecoTau/plugins/PATTauDiscriminationByMVAIsolationRun2.cc#L218
2753  template <typename TauCastType>
2754  static bool calculateGottfriedJacksonAngleDifference(const TauCastType& tau,
2755  const size_t tau_index,
2756  double& gj_diff,
2757  TauFunc tau_funcs) {
2758  if (tau_funcs.getHasSecondaryVertex(tau, tau_index)) {
2759  static constexpr double mTau = 1.77682;
2760  const double mAOne = tau.p4().M();
2761  const double pAOneMag = tau.p();
2762  const double argumentThetaGJmax = (std::pow(mTau, 2) - std::pow(mAOne, 2)) / (2 * mTau * pAOneMag);
2763  const double argumentThetaGJmeasured = tau.p4().Vect().Dot(tau_funcs.getFlightLength(tau, tau_index)) /
2764  (pAOneMag * tau_funcs.getFlightLength(tau, tau_index).R());
2765  if (std::abs(argumentThetaGJmax) <= 1. && std::abs(argumentThetaGJmeasured) <= 1.) {
2766  double thetaGJmax = std::asin(argumentThetaGJmax);
2767  double thetaGJmeasured = std::acos(argumentThetaGJmeasured);
2768  gj_diff = thetaGJmeasured - thetaGJmax;
2769  return true;
2770  }
2771  }
2772  return false;
2773  }
2774 
2775  template <typename TauCastType>
2776  static float calculateGottfriedJacksonAngleDifference(const TauCastType& tau,
2777  const size_t tau_index,
2778  TauFunc tau_funcs) {
2779  double gj_diff;
2780  if (calculateGottfriedJacksonAngleDifference(tau, tau_index, gj_diff, tau_funcs))
2781  return static_cast<float>(gj_diff);
2782  return default_value;
2783  }
2784 
2785  static bool isInEcalCrack(double eta) {
2786  const double abs_eta = std::abs(eta);
2787  return abs_eta > 1.46 && abs_eta < 1.558;
2788  }
2789 
2790  template <typename TauCastType>
2791  static const pat::Electron* findMatchedElectron(const TauCastType& tau,
2792  const std::vector<pat::Electron>* electrons,
2793  double deltaR) {
2794  const double dR2 = deltaR * deltaR;
2795  const pat::Electron* matched_ele = nullptr;
2796  for (const auto& ele : *electrons) {
2797  if (reco::deltaR2(tau.p4(), ele.p4()) < dR2 && (!matched_ele || matched_ele->pt() < ele.pt())) {
2798  matched_ele = &ele;
2799  }
2800  }
2801  return matched_ele;
2802  }
2803 
2804 private:
2813  const unsigned version_;
2814  const int debug_level;
2815  const bool disable_dxy_pca_;
2818  std::unique_ptr<tensorflow::Tensor> tauBlockTensor_;
2819  std::array<std::unique_ptr<tensorflow::Tensor>, 2> eGammaTensor_, muonTensor_, hadronsTensor_, convTensor_,
2821  const bool save_inputs_;
2822  std::ofstream* json_file_;
2825 
2826  //boolean to check if discriminator indices are already mapped
2827  bool discrIndicesMapped_ = false;
2828  std::map<BasicDiscriminator, size_t> basicDiscrIndexMap_;
2829  std::map<BasicDiscriminator, size_t> basicDiscrdR03IndexMap_;
2830 };
2831 
float puppiWeight() const
void createConvFeatures(const TauCastType &tau, const size_t tau_index, const edm::RefToBase< reco::BaseTau > tau_ref, const reco::Vertex &pv, double rho, const std::vector< pat::Electron > *electrons, const std::vector< pat::Muon > *muons, const edm::View< reco::Candidate > &pfCands, const CellGrid &grid, TauFunc tau_funcs, bool is_inner)
Definition: DeepTauId.cc:1746
virtual float dz(size_t ipv=0) const
dz with respect to the PV[ipv]
static constexpr float default_value
Definition: DeepTauId.cc:1103
constexpr double deltaPhi(double phi1, double phi2)
Definition: deltaPhi.h:26
void createMuonBlockInputs(unsigned idx, const TauCastType &tau, const size_t tau_index, const edm::RefToBase< reco::BaseTau > tau_ref, const reco::Vertex &pv, double rho, const std::vector< pat::Muon > *muons, const edm::View< reco::Candidate > &pfCands, const Cell &cell_map, TauFunc tau_funcs, bool is_inner)
Definition: DeepTauId.cc:2180
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
Definition: DeepTauId.cc:1147
unsigned int n_photons_total(const reco::PFTau &tau)
return total number of pf photon candidates with pT&gt;500 MeV, which are associated to signal ...
std::array< std::unique_ptr< tensorflow::Tensor >, 2 > hadronsTensor_
Definition: DeepTauId.cc:2819
std::map< BasicDiscriminator, size_t > basicDiscrdR03IndexMap_
Definition: DeepTauId.cc:2829
ParameterDescriptionBase * addOptional(U const &iLabel, T const &value)
bool isNonnull() const
Checks for non-null.
Definition: Ref.h:238
static void processIsolationPFComponents(const TauCastType &tau, const CandidateCollection &candidates, LorentzVectorXYZ &p4, float &pt, float &d_eta, float &d_phi, float &m, float &n)
Definition: DeepTauId.cc:2724
tuple cfg
Definition: looper.py:296
void checkInputs(const tensorflow::Tensor &inputs, const std::string &block_name, int n_inputs, const CellGrid *grid=nullptr) const
Definition: DeepTauId.cc:1306
double rawEcalEnergy() const
return corrected Ecal energy
Definition: PFCandidate.h:224
static std::unique_ptr< deep_tau::DeepTauCache > initializeGlobalCache(const edm::ParameterSet &cfg)
Definition: DeepTauId.cc:1250
double pt() const final
transverse momentum
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
float puppiWeightNoLep() const
Weight from full PUPPI.
static void processSignalPFComponents(const TauCastType &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:2680
float pt_weighted_dr_signal(const reco::PFTau &tau, int dm)
float hcalEnergyLeadChargedHadrCand() const
return hcal energy from LeadChargedHadrCand
Definition: Tau.h:308
float hcalFraction() const
const bool disable_dxy_pca_
Definition: DeepTauId.cc:2815
static float getValueLinear(T value, float min_value, float max_value, bool positive)
Definition: DeepTauId.cc:1265
static const pat::Electron * findMatchedElectron(const TauCastType &tau, const std::vector< pat::Electron > *electrons, double deltaR)
Definition: DeepTauId.cc:2791
constexpr bool isNotFinite(T x)
Definition: isFinite.h:9
void createHadronsBlockInputs(unsigned idx, const TauCastType &tau, const size_t tau_index, const edm::RefToBase< reco::BaseTau > tau_ref, const reco::Vertex &pv, double rho, const edm::View< reco::Candidate > &pfCands, const Cell &cell_map, TauFunc tau_funcs, bool is_inner)
Definition: DeepTauId.cc:2331
void fillGrids(const TauCastType &tau, const Collection &objects, CellGrid &inner_grid, CellGrid &outer_grid)
Definition: DeepTauId.cc:1685
const bool save_inputs_
Definition: DeepTauId.cc:2821
std::array< std::unique_ptr< tensorflow::Tensor >, 2 > zeroOutputTensor_
Definition: DeepTauId.cc:2819
float dxy() const
Definition: Tau.h:277
std::map< BasicDiscriminator, size_t > basicDiscrIndexMap_
Definition: DeepTauId.cc:2828
int file_counter_
Definition: DeepTauId.cc:2824
const reco::Track * bestTrack() const override
Definition: PFCandidate.h:150
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
const DeepTauCache * cache_
Definition: DeepTauBase.h:135
float dzError() const override
uncertainty on dz
Definition: PFCandidate.h:159
tuple disable_hcalFraction_workaround
static double getInnerSignalConeRadius(double pt)
Definition: DeepTauId.cc:2746
std::ofstream * json_file_
Definition: DeepTauId.cc:2822
const tensorflow::GraphDef & getGraph(const std::string &name="") const
Definition: DeepTauBase.h:58
static bool isAbove(double value, double min)
Definition: DeepTauId.cc:1281
static bool isInEcalCrack(double eta)
Definition: DeepTauId.cc:2785
std::string to_string(const V &value)
Definition: OMSAccess.h:71
void setCellConvFeatures(tensorflow::Tensor &convTensor, const tensorflow::Tensor &features, unsigned batch_idx, int eta_index, int phi_index)
Definition: DeepTauId.cc:1827
const unsigned version_
Definition: DeepTauId.cc:2813
float emFraction() const
Definition: PFTau.cc:340
float ip3d_Sig() const
float tauID(const std::string &name) const
reco::SuperClusterRef superCluster() const override
override the reco::GsfElectron::superCluster method, to access the internal storage of the superclust...
void countMatches(const reco::Muon &muon, std::vector< int > &numMatchesDT, std::vector< int > &numMatchesCSC, std::vector< int > &numMatchesRPC)
int pdgId() const override
PDG identifier.
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
edm::RefProd< PFTauCollection > PFTauRefProd
references to PFTau collection
Definition: PFTauFwd.h:15
assert(be >=bs)
const std::map< ValueQuantityType, double > min_value
tensorflow::Tensor createInputsV1(const TauCastType &tau, const size_t tau_index, const edm::RefToBase< reco::BaseTau > tau_ref, const std::vector< pat::Electron > *electrons, const std::vector< pat::Muon > *muons, TauFunc tau_funcs) const
Definition: DeepTauId.cc:2456
const Point & position() const
position
Definition: Vertex.h:127
std::map< std::string, Output > OutputCollection
Definition: DeepTauBase.h:91
static const double deltaEta
Definition: CaloConstants.h:8
static const OutputCollection & GetOutputs()
Definition: DeepTauId.cc:1105
static std::string const input
Definition: EdmProvDump.cc:47
static const std::vector< BasicDiscriminator > requiredBasicDiscriminatorsdR03_
Definition: DeepTauBase.h:139
std::array< std::unique_ptr< tensorflow::Tensor >, 2 > convTensor_
Definition: DeepTauId.cc:2819
DeepTauId(const edm::ParameterSet &cfg, const deep_tau::DeepTauCache *cache)
Definition: DeepTauId.cc:1190
OutputCollection outputs_
Definition: DeepTauBase.h:134
float ip3d_error() const
Definition: Tau.h:291
static const int tauID
Definition: TopGenEvent.h:20
char const * label
tuple disable_CellIndex_workaround
std::string output_layer_
Definition: DeepTauId.cc:2812
static constexpr float pi
Definition: DeepTauId.cc:1257
bool is_first_block_
Definition: DeepTauId.cc:2823
static float getValue(T value)
Definition: DeepTauId.cc:1260
CellObjectType
Definition: DeepTauId.cc:964
const PVAssociationQuality pvAssociationQuality() const
float ip3d() const
Definition: Tau.h:290
std::vector< float > features(const reco::PreId &ecal, const reco::PreId &hcal, double rho, const reco::BeamSpot &spot, noZS::EcalClusterLazyTools &ecalTools)
float pt_weighted_deta_strip(const reco::PFTau &tau, int dm)
const PVAssoc fromPV(size_t ipv=0) const
reco::TrackRef outerTrack() const override
reference to Track reconstructed in the muon detector only (reimplemented from reco::Muon) ...
Definition: Muon.h:76
float dzError() const override
uncertainty on dz
const pat::tau::TauPFEssential::Vector & flightLength() const
Definition: Tau.h:284
const std::map< BasicDiscriminator, size_t > matchDiscriminatorIndices(edm::Event &event, edm::EDGetTokenT< reco::TauDiscriminatorContainer > discriminatorContainerToken, std::vector< BasicDiscriminator > requiredDiscr)
Definition: DeepTauId.cc:1115
ParameterSet const & parameterSet(StableProvenance const &provenance, ProcessHistory const &history)
Definition: Provenance.cc:11
LostInnerHits lostInnerHits() const
void run(Session *session, const NamedTensorList &inputs, const std::vector< std::string > &outputNames, std::vector< Tensor > *outputs, const thread::ThreadPoolOptions &threadPoolOptions)
Definition: TensorFlow.cc:213
void saveInputs(const tensorflow::Tensor &inputs, const std::string &block_name, int n_inputs, const CellGrid *grid=nullptr)
Definition: DeepTauId.cc:1362
const bool disable_CellIndex_workaround_
Definition: DeepTauId.cc:2817
float ecalEnergyLeadChargedHadrCand() const
Definition: Tau.h:306
static float getValueNorm(T value, float mean, float sigma, float n_sigmas_max=5)
Definition: DeepTauId.cc:1275
T get() const
get a component
std::string input_layer_
Definition: DeepTauId.cc:2812
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
float pt_weighted_dr_iso(const reco::PFTau &tau, int dm)
T operator[](int i) const
virtual const reco::Track & pseudoTrack() const
void createEgammaBlockInputs(unsigned idx, const TauCastType &tau, const size_t tau_index, const edm::RefToBase< reco::BaseTau > tau_ref, const reco::Vertex &pv, double rho, const std::vector< pat::Electron > *electrons, const edm::View< reco::Candidate > &pfCands, const Cell &cell_map, TauFunc tau_funcs, bool is_inner)
Definition: DeepTauId.cc:1944
static void globalEndJob(const deep_tau::DeepTauCache *cache_)
Definition: DeepTauId.cc:1254
bool hasSecondaryVertex() const
Definition: Tau.h:283
static const std::vector< BasicDiscriminator > requiredBasicDiscriminators_
Definition: DeepTauBase.h:138
DeepTauBase(const edm::ParameterSet &cfg, const OutputCollection &outputs, const DeepTauCache *cache)
Definition: DeepTauBase.cc:91
ParameterDescriptionBase * add(U const &iLabel, T const &value)
const_reference_type get(ProductID id, size_t idx) const
Definition: ValueMap.h:144
int numberOfPixelHits() const
Analysis-level tau class.
Definition: Tau.h:53
float rawHcalFraction() const
Set the fraction of Hcal needed isolated charged hadrons.
#define M_PI
bool hasTrackDetails() const
Return true if a bestTrack can be extracted from this Candidate.
constexpr auto deltaR(const T1 &t1, const T2 &t2) -> decltype(t1.eta())
Definition: deltaR.h:30
tensorflow::Tensor getPredictions(edm::Event &event, edm::Handle< TauCollection > taus) override
Definition: DeepTauId.cc:1423
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
bool isTauIDAvailable(const std::string &name) const
Returns true if a specific ID is available in this pat::Tau.
virtual int pdgId() const =0
PDG identifier.
caConstants::TupleMultiplicity const CAHitNtupletGeneratorKernelsGPU::HitToTuple const cms::cuda::AtomicPairCounter GPUCACell const *__restrict__ cells
tensorflow::Tensor getPartialPredictions(bool is_inner)
Definition: DeepTauId.cc:1721
const pat::tau::TauPFEssential::Point & dxy_PCA() const
Definition: Tau.h:276
static bool calculateGottfriedJacksonAngleDifference(const TauCastType &tau, const size_t tau_index, double &gj_diff, TauFunc tau_funcs)
Definition: DeepTauId.cc:2754
edm::EDGetTokenT< edm::AssociationVector< reco::PFTauRefProd, std::vector< reco::PFTauTransverseImpactParameterRef > > > pfTauTransverseImpactParameters_token_
Definition: DeepTauId.cc:2811
constexpr auto deltaR2(const T1 &t1, const T2 &t2) -> decltype(t1.eta())
Definition: deltaR.h:16
edm::ValueMap< SingleTauDiscriminatorContainer > TauDiscriminatorContainer
bool discrIndicesMapped_
Definition: DeepTauId.cc:2827
void createTauBlockInputs(const TauCastType &tau, const size_t &tau_index, const edm::RefToBase< reco::BaseTau > tau_ref, const reco::Vertex &pv, double rho, TauFunc tau_funcs)
Definition: DeepTauId.cc:1838
float pt_weighted_dphi_strip(const reco::PFTau &tau, int dm)
void getPredictionsV2(TauCollection::const_reference &tau, const size_t tau_index, const edm::RefToBase< reco::BaseTau > tau_ref, const std::vector< pat::Electron > *electrons, const std::vector< pat::Muon > *muons, const edm::View< reco::Candidate > &pfCands, const reco::Vertex &pv, double rho, std::vector< tensorflow::Tensor > &pred_vector, TauFunc tau_funcs)
Definition: DeepTauId.cc:1563
const HitPattern & hitPattern() const
Access the hit pattern, indicating in which Tracker layers the track has hits.
Definition: TrackBase.h:504
float eratio(const reco::PFTau &tau)
return ratio of energy in ECAL over sum of energy in ECAL and HCAL
uint8_t andPrediscriminants_
Definition: DeepTauBase.h:111
static constexpr int RPC
Definition: MuonSubdetId.h:13
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
Analysis-level electron class.
Definition: Electron.h:51
std::vector< MuonChamberMatch > & matches()
get muon matching information
Definition: Muon.h:145
void add(std::string const &label, ParameterSetDescription const &psetDescription)
caConstants::TupleMultiplicity const CAHitNtupletGeneratorKernelsGPU::HitToTuple const cms::cuda::AtomicPairCounter GPUCACell const *__restrict__ uint32_t const *__restrict__ gpuPixelDoublets::CellNeighborsVector const gpuPixelDoublets::CellTracksVector const GPUCACell::OuterHitOfCell const int32_t nHits
edm::Ref< PFTauTransverseImpactParameterCollection > PFTauTransverseImpactParameterRef
presistent reference to a PFTauTransverseImpactParameter
static const std::map< BasicDiscriminator, std::string > stringFromDiscriminator_
Definition: DeepTauBase.h:137
edm::EDGetTokenT< reco::TauDiscriminatorContainer > basicTauDiscriminators_inputToken_
Definition: DeepTauId.cc:2808
int numberOfLostHits(HitCategory category) const
Definition: HitPattern.h:891
float emFraction_MVA() const
return emFraction_MVA
Definition: Tau.h:318
bool operator<(DTCELinkId const &lhs, DTCELinkId const &rhs)
Definition: DTCELinkId.h:70
float rawCaloFraction() const
static float calculateGottfriedJacksonAngleDifference(const TauCastType &tau, const size_t tau_index, TauFunc tau_funcs)
Definition: DeepTauId.cc:2776
static bool calculateElectronClusterVarsV2(const pat::Electron &ele, float &cc_ele_energy, float &cc_gamma_energy, int &cc_n_gamma)
Definition: DeepTauId.cc:1283
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:41
float flightLengthSig() const
Definition: Tau.h:285
float dxy_Sig() const
std::array< std::unique_ptr< tensorflow::Tensor >, 2 > eGammaTensor_
Definition: DeepTauId.cc:2819
tuple muons
Definition: patZpeak.py:41
const bool disable_hcalFraction_workaround_
Definition: DeepTauId.cc:2816
float leadingTrackNormChi2() const
return normalized chi2 of leading track
Definition: Tau.h:301
tuple pfTauTransverseImpactParameters
edm::EDGetTokenT< reco::TauDiscriminatorContainer > basicTauDiscriminatorsdR03_inputToken_
Definition: DeepTauId.cc:2809
string end
Definition: dataset.py:937
const std::map< ValueQuantityType, double > max_value
const_reference at(size_type pos) const
tuple cout
Definition: gather_cfg.py:144
std::pair< typename Association::data_type::first_type, double > match(Reference key, Association association, bool bestMatchByMaxValue)
Generic matching function.
Definition: Utils.h:10
float lead_track_chi2(const reco::PFTau &tau)
return chi2 of the leading track ==&gt; deprecated? &lt;==
const int debug_level
Definition: DeepTauId.cc:2814
std::vector< TauDiscInfo< pat::PATTauDiscriminator > > patPrediscriminants_
Definition: DeepTauBase.h:112
const PFCandidatePtr leadPFChargedHadrCand() const
Getters for different PFCandidates for PFTaus made from PFCandidates.
Definition: PFTau.cc:165
tuple basicTauDiscriminators
vars
Definition: DeepTauId.cc:164
constexpr char Electron[]
Definition: modules.cc:12
static constexpr int DT
Definition: MuonSubdetId.h:11
Log< level::Warning, false > LogWarning
float etaAtEcalEntranceLeadChargedCand() const
return etaAtEcalEntrance from LeadChargedCand
Definition: Tau.h:314
virtual float dxy() const
dxy with respect to the PV ref
std::array< std::unique_ptr< tensorflow::Tensor >, 2 > muonTensor_
Definition: DeepTauId.cc:2819
edm::EDGetTokenT< std::vector< pat::Electron > > electrons_token_
Definition: DeepTauId.cc:2805
edm::EDGetTokenT< std::vector< pat::Muon > > muons_token_
Definition: DeepTauId.cc:2806
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
tuple basicTauDiscriminatorsdR03
static constexpr int CSC
Definition: MuonSubdetId.h:12
edm::EDGetTokenT< double > rho_token_
Definition: DeepTauId.cc:2807
bool isIsolatedChargedHadron() const
static void calculateElectronClusterVars(const pat::Electron *ele, float &elecEe, float &elecEgamma)
Definition: DeepTauId.cc:2660
T const & const_reference
Definition: View.h:82
static const std::string subdets[7]
Definition: TrackUtils.cc:60
edm::EDGetTokenT< CandidateCollection > pfcandToken_
Definition: DeepTauBase.h:130
void getPredictionsV1(TauCollection::const_reference &tau, const size_t tau_index, const edm::RefToBase< reco::BaseTau > tau_ref, const std::vector< pat::Electron > *electrons, const std::vector< pat::Muon > *muons, std::vector< tensorflow::Tensor > &pred_vector, TauFunc tau_funcs)
Definition: DeepTauId.cc:1550
Analysis-level muon class.
Definition: Muon.h:51
ROOT::Math::LorentzVector< ROOT::Math::PxPyPzE4D< double >> LorentzVectorXYZ
Definition: DeepTauBase.h:75
std::vector< TauDiscInfo< reco::PFTauDiscriminator > > recoPrediscriminants_
Definition: DeepTauBase.h:113
tuple size
Write out results.
void countHits(const reco::Muon &muon, std::vector< int > &numHitsDT, std::vector< int > &numHitsCSC, std::vector< int > &numHitsRPC)
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
double rawHcalEnergy() const
return raw Hcal energy
Definition: PFCandidate.h:236
constexpr int NumberOfOutputs
Definition: DeepTauId.cc:19
def cache
Definition: utilities.py:3
std::unique_ptr< tensorflow::Tensor > tauBlockTensor_
Definition: DeepTauId.cc:2818
tensorflow::Session & getSession(const std::string &name="") const
Definition: DeepTauBase.h:57
virtual const LorentzVector & p4() const =0
four-momentum Lorentz vector
float dxy_error() const
Definition: Tau.h:278
double energy() const final
energy
edm::EDGetTokenT< reco::VertexCollection > vtxToken_
Definition: DeepTauBase.h:131