CMS 3D CMS Logo

DeepTauId.cc
Go to the documentation of this file.
1 /*
2  * \class DeepTauId
3  *
4  * Tau identification using Deep NN.
5  *
6  * \author Konstantin Androsov, INFN Pisa
7  * Christian Veelken, Tallinn
8  */
9 
15 
16 #include <fstream>
17 #include "oneapi/tbb/concurrent_unordered_set.h"
18 
19 namespace deep_tau {
20  constexpr int NumberOfOutputs = 4;
21 }
22 
23 namespace {
24 
25  namespace dnn_inputs_v2 {
26  constexpr int number_of_inner_cell = 11;
27  constexpr int number_of_outer_cell = 21;
28  constexpr int number_of_conv_features = 64;
29  namespace TauBlockInputs {
30  enum vars {
31  rho = 0,
32  tau_pt,
33  tau_eta,
34  tau_phi,
35  tau_mass,
36  tau_E_over_pt,
37  tau_charge,
38  tau_n_charged_prongs,
39  tau_n_neutral_prongs,
40  chargedIsoPtSum,
41  chargedIsoPtSumdR03_over_dR05,
42  footprintCorrection,
43  neutralIsoPtSum,
44  neutralIsoPtSumWeight_over_neutralIsoPtSum,
45  neutralIsoPtSumWeightdR03_over_neutralIsoPtSum,
46  neutralIsoPtSumdR03_over_dR05,
47  photonPtSumOutsideSignalCone,
48  puCorrPtSum,
49  tau_dxy_pca_x,
50  tau_dxy_pca_y,
51  tau_dxy_pca_z,
52  tau_dxy_valid,
53  tau_dxy,
54  tau_dxy_sig,
55  tau_ip3d_valid,
56  tau_ip3d,
57  tau_ip3d_sig,
58  tau_dz,
59  tau_dz_sig_valid,
60  tau_dz_sig,
61  tau_flightLength_x,
62  tau_flightLength_y,
63  tau_flightLength_z,
64  tau_flightLength_sig,
65  tau_pt_weighted_deta_strip,
66  tau_pt_weighted_dphi_strip,
67  tau_pt_weighted_dr_signal,
68  tau_pt_weighted_dr_iso,
69  tau_leadingTrackNormChi2,
70  tau_e_ratio_valid,
71  tau_e_ratio,
72  tau_gj_angle_diff_valid,
73  tau_gj_angle_diff,
74  tau_n_photons,
75  tau_emFraction,
76  tau_inside_ecal_crack,
77  leadChargedCand_etaAtEcalEntrance_minus_tau_eta,
78  NumberOfInputs
79  };
80  std::vector<int> varsToDrop = {
81  tau_phi, tau_dxy_pca_x, tau_dxy_pca_y, tau_dxy_pca_z}; // indices of vars to be dropped in the full var enum
82  } // namespace TauBlockInputs
83 
84  namespace EgammaBlockInputs {
85  enum vars {
86  rho = 0,
87  tau_pt,
88  tau_eta,
89  tau_inside_ecal_crack,
90  pfCand_ele_valid,
91  pfCand_ele_rel_pt,
92  pfCand_ele_deta,
93  pfCand_ele_dphi,
94  pfCand_ele_pvAssociationQuality,
95  pfCand_ele_puppiWeight,
96  pfCand_ele_charge,
97  pfCand_ele_lostInnerHits,
98  pfCand_ele_numberOfPixelHits,
99  pfCand_ele_vertex_dx,
100  pfCand_ele_vertex_dy,
101  pfCand_ele_vertex_dz,
102  pfCand_ele_vertex_dx_tauFL,
103  pfCand_ele_vertex_dy_tauFL,
104  pfCand_ele_vertex_dz_tauFL,
105  pfCand_ele_hasTrackDetails,
106  pfCand_ele_dxy,
107  pfCand_ele_dxy_sig,
108  pfCand_ele_dz,
109  pfCand_ele_dz_sig,
110  pfCand_ele_track_chi2_ndof,
111  pfCand_ele_track_ndof,
112  ele_valid,
113  ele_rel_pt,
114  ele_deta,
115  ele_dphi,
116  ele_cc_valid,
117  ele_cc_ele_rel_energy,
118  ele_cc_gamma_rel_energy,
119  ele_cc_n_gamma,
120  ele_rel_trackMomentumAtVtx,
121  ele_rel_trackMomentumAtCalo,
122  ele_rel_trackMomentumOut,
123  ele_rel_trackMomentumAtEleClus,
124  ele_rel_trackMomentumAtVtxWithConstraint,
125  ele_rel_ecalEnergy,
126  ele_ecalEnergy_sig,
127  ele_eSuperClusterOverP,
128  ele_eSeedClusterOverP,
129  ele_eSeedClusterOverPout,
130  ele_eEleClusterOverPout,
131  ele_deltaEtaSuperClusterTrackAtVtx,
132  ele_deltaEtaSeedClusterTrackAtCalo,
133  ele_deltaEtaEleClusterTrackAtCalo,
134  ele_deltaPhiEleClusterTrackAtCalo,
135  ele_deltaPhiSuperClusterTrackAtVtx,
136  ele_deltaPhiSeedClusterTrackAtCalo,
137  ele_mvaInput_earlyBrem,
138  ele_mvaInput_lateBrem,
139  ele_mvaInput_sigmaEtaEta,
140  ele_mvaInput_hadEnergy,
141  ele_mvaInput_deltaEta,
142  ele_gsfTrack_normalizedChi2,
143  ele_gsfTrack_numberOfValidHits,
144  ele_rel_gsfTrack_pt,
145  ele_gsfTrack_pt_sig,
146  ele_has_closestCtfTrack,
147  ele_closestCtfTrack_normalizedChi2,
148  ele_closestCtfTrack_numberOfValidHits,
149  pfCand_gamma_valid,
150  pfCand_gamma_rel_pt,
151  pfCand_gamma_deta,
152  pfCand_gamma_dphi,
153  pfCand_gamma_pvAssociationQuality,
154  pfCand_gamma_fromPV,
155  pfCand_gamma_puppiWeight,
156  pfCand_gamma_puppiWeightNoLep,
157  pfCand_gamma_lostInnerHits,
158  pfCand_gamma_numberOfPixelHits,
159  pfCand_gamma_vertex_dx,
160  pfCand_gamma_vertex_dy,
161  pfCand_gamma_vertex_dz,
162  pfCand_gamma_vertex_dx_tauFL,
163  pfCand_gamma_vertex_dy_tauFL,
164  pfCand_gamma_vertex_dz_tauFL,
165  pfCand_gamma_hasTrackDetails,
166  pfCand_gamma_dxy,
167  pfCand_gamma_dxy_sig,
168  pfCand_gamma_dz,
169  pfCand_gamma_dz_sig,
170  pfCand_gamma_track_chi2_ndof,
171  pfCand_gamma_track_ndof,
172  NumberOfInputs
173  };
174  }
175 
176  namespace MuonBlockInputs {
177  enum vars {
178  rho = 0,
179  tau_pt,
180  tau_eta,
181  tau_inside_ecal_crack,
182  pfCand_muon_valid,
183  pfCand_muon_rel_pt,
184  pfCand_muon_deta,
185  pfCand_muon_dphi,
186  pfCand_muon_pvAssociationQuality,
187  pfCand_muon_fromPV,
188  pfCand_muon_puppiWeight,
189  pfCand_muon_charge,
190  pfCand_muon_lostInnerHits,
191  pfCand_muon_numberOfPixelHits,
192  pfCand_muon_vertex_dx,
193  pfCand_muon_vertex_dy,
194  pfCand_muon_vertex_dz,
195  pfCand_muon_vertex_dx_tauFL,
196  pfCand_muon_vertex_dy_tauFL,
197  pfCand_muon_vertex_dz_tauFL,
198  pfCand_muon_hasTrackDetails,
199  pfCand_muon_dxy,
200  pfCand_muon_dxy_sig,
201  pfCand_muon_dz,
202  pfCand_muon_dz_sig,
203  pfCand_muon_track_chi2_ndof,
204  pfCand_muon_track_ndof,
205  muon_valid,
206  muon_rel_pt,
207  muon_deta,
208  muon_dphi,
209  muon_dxy,
210  muon_dxy_sig,
211  muon_normalizedChi2_valid,
212  muon_normalizedChi2,
213  muon_numberOfValidHits,
214  muon_segmentCompatibility,
215  muon_caloCompatibility,
216  muon_pfEcalEnergy_valid,
217  muon_rel_pfEcalEnergy,
218  muon_n_matches_DT_1,
219  muon_n_matches_DT_2,
220  muon_n_matches_DT_3,
221  muon_n_matches_DT_4,
222  muon_n_matches_CSC_1,
223  muon_n_matches_CSC_2,
224  muon_n_matches_CSC_3,
225  muon_n_matches_CSC_4,
226  muon_n_matches_RPC_1,
227  muon_n_matches_RPC_2,
228  muon_n_matches_RPC_3,
229  muon_n_matches_RPC_4,
230  muon_n_hits_DT_1,
231  muon_n_hits_DT_2,
232  muon_n_hits_DT_3,
233  muon_n_hits_DT_4,
234  muon_n_hits_CSC_1,
235  muon_n_hits_CSC_2,
236  muon_n_hits_CSC_3,
237  muon_n_hits_CSC_4,
238  muon_n_hits_RPC_1,
239  muon_n_hits_RPC_2,
240  muon_n_hits_RPC_3,
241  muon_n_hits_RPC_4,
242  NumberOfInputs
243  };
244  }
245 
246  namespace HadronBlockInputs {
247  enum vars {
248  rho = 0,
249  tau_pt,
250  tau_eta,
251  tau_inside_ecal_crack,
252  pfCand_chHad_valid,
253  pfCand_chHad_rel_pt,
254  pfCand_chHad_deta,
255  pfCand_chHad_dphi,
256  pfCand_chHad_leadChargedHadrCand,
257  pfCand_chHad_pvAssociationQuality,
258  pfCand_chHad_fromPV,
259  pfCand_chHad_puppiWeight,
260  pfCand_chHad_puppiWeightNoLep,
261  pfCand_chHad_charge,
262  pfCand_chHad_lostInnerHits,
263  pfCand_chHad_numberOfPixelHits,
264  pfCand_chHad_vertex_dx,
265  pfCand_chHad_vertex_dy,
266  pfCand_chHad_vertex_dz,
267  pfCand_chHad_vertex_dx_tauFL,
268  pfCand_chHad_vertex_dy_tauFL,
269  pfCand_chHad_vertex_dz_tauFL,
270  pfCand_chHad_hasTrackDetails,
271  pfCand_chHad_dxy,
272  pfCand_chHad_dxy_sig,
273  pfCand_chHad_dz,
274  pfCand_chHad_dz_sig,
275  pfCand_chHad_track_chi2_ndof,
276  pfCand_chHad_track_ndof,
277  pfCand_chHad_hcalFraction,
278  pfCand_chHad_rawCaloFraction,
279  pfCand_nHad_valid,
280  pfCand_nHad_rel_pt,
281  pfCand_nHad_deta,
282  pfCand_nHad_dphi,
283  pfCand_nHad_puppiWeight,
284  pfCand_nHad_puppiWeightNoLep,
285  pfCand_nHad_hcalFraction,
286  NumberOfInputs
287  };
288  }
289  } // namespace dnn_inputs_v2
290 
291  float getTauID(const pat::Tau& tau, const std::string& tauID, float default_value = -999., bool assert_input = true) {
292  static tbb::concurrent_unordered_set<std::string> isFirstWarning;
293  if (tau.isTauIDAvailable(tauID)) {
294  return tau.tauID(tauID);
295  } else {
296  if (assert_input) {
297  throw cms::Exception("DeepTauId")
298  << "Exception in <getTauID>: No tauID '" << tauID << "' available in pat::Tau given as function argument.";
299  }
300  if (isFirstWarning.insert(tauID).second) {
301  edm::LogWarning("DeepTauID") << "Warning in <getTauID>: No tauID '" << tauID
302  << "' available in pat::Tau given as function argument."
303  << " Using default_value = " << default_value << " instead." << std::endl;
304  }
305  return default_value;
306  }
307  }
308 
309  struct TauFunc {
310  const reco::TauDiscriminatorContainer* basicTauDiscriminatorCollection;
311  const reco::TauDiscriminatorContainer* basicTauDiscriminatordR03Collection;
314 
316  std::map<BasicDiscr, size_t> indexMap;
317  std::map<BasicDiscr, size_t> indexMapdR03;
318 
319  const float getChargedIsoPtSum(const reco::PFTau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
320  return (*basicTauDiscriminatorCollection)[tau_ref].rawValues.at(indexMap.at(BasicDiscr::ChargedIsoPtSum));
321  }
322  const float getChargedIsoPtSum(const pat::Tau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
323  return getTauID(tau, "chargedIsoPtSum");
324  }
325  const float getChargedIsoPtSumdR03(const reco::PFTau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
326  return (*basicTauDiscriminatordR03Collection)[tau_ref].rawValues.at(indexMapdR03.at(BasicDiscr::ChargedIsoPtSum));
327  }
328  const float getChargedIsoPtSumdR03(const pat::Tau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
329  return getTauID(tau, "chargedIsoPtSumdR03");
330  }
331  const float getFootprintCorrectiondR03(const reco::PFTau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
332  return (*basicTauDiscriminatordR03Collection)[tau_ref].rawValues.at(
333  indexMapdR03.at(BasicDiscr::FootprintCorrection));
334  }
335  const float getFootprintCorrectiondR03(const pat::Tau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
336  return getTauID(tau, "footprintCorrectiondR03");
337  }
338  const float getFootprintCorrection(const pat::Tau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
339  return getTauID(tau, "footprintCorrection");
340  }
341  const float getNeutralIsoPtSum(const reco::PFTau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
342  return (*basicTauDiscriminatorCollection)[tau_ref].rawValues.at(indexMap.at(BasicDiscr::NeutralIsoPtSum));
343  }
344  const float getNeutralIsoPtSum(const pat::Tau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
345  return getTauID(tau, "neutralIsoPtSum");
346  }
347  const float getNeutralIsoPtSumdR03(const reco::PFTau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
348  return (*basicTauDiscriminatordR03Collection)[tau_ref].rawValues.at(indexMapdR03.at(BasicDiscr::NeutralIsoPtSum));
349  }
350  const float getNeutralIsoPtSumdR03(const pat::Tau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
351  return getTauID(tau, "neutralIsoPtSumdR03");
352  }
353  const float getNeutralIsoPtSumWeight(const reco::PFTau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
354  return (*basicTauDiscriminatorCollection)[tau_ref].rawValues.at(indexMap.at(BasicDiscr::NeutralIsoPtSumWeight));
355  }
356  const float getNeutralIsoPtSumWeight(const pat::Tau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
357  return getTauID(tau, "neutralIsoPtSumWeight");
358  }
359  const float getNeutralIsoPtSumdR03Weight(const reco::PFTau& tau,
360  const edm::RefToBase<reco::BaseTau> tau_ref) const {
361  return (*basicTauDiscriminatordR03Collection)[tau_ref].rawValues.at(
362  indexMapdR03.at(BasicDiscr::NeutralIsoPtSumWeight));
363  }
364  const float getNeutralIsoPtSumdR03Weight(const pat::Tau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
365  return getTauID(tau, "neutralIsoPtSumWeightdR03");
366  }
367  const float getPhotonPtSumOutsideSignalCone(const reco::PFTau& tau,
368  const edm::RefToBase<reco::BaseTau> tau_ref) const {
369  return (*basicTauDiscriminatorCollection)[tau_ref].rawValues.at(
370  indexMap.at(BasicDiscr::PhotonPtSumOutsideSignalCone));
371  }
372  const float getPhotonPtSumOutsideSignalCone(const pat::Tau& tau,
373  const edm::RefToBase<reco::BaseTau> tau_ref) const {
374  return getTauID(tau, "photonPtSumOutsideSignalCone");
375  }
376  const float getPhotonPtSumOutsideSignalConedR03(const reco::PFTau& tau,
377  const edm::RefToBase<reco::BaseTau> tau_ref) const {
378  return (*basicTauDiscriminatordR03Collection)[tau_ref].rawValues.at(
379  indexMapdR03.at(BasicDiscr::PhotonPtSumOutsideSignalCone));
380  }
381  const float getPhotonPtSumOutsideSignalConedR03(const pat::Tau& tau,
382  const edm::RefToBase<reco::BaseTau> tau_ref) const {
383  return getTauID(tau, "photonPtSumOutsideSignalConedR03");
384  }
385  const float getPuCorrPtSum(const reco::PFTau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
386  return (*basicTauDiscriminatorCollection)[tau_ref].rawValues.at(indexMap.at(BasicDiscr::PUcorrPtSum));
387  }
388  const float getPuCorrPtSum(const pat::Tau& tau, const edm::RefToBase<reco::BaseTau> tau_ref) const {
389  return getTauID(tau, "puCorrPtSum");
390  }
391 
392  auto getdxyPCA(const reco::PFTau& tau, const size_t tau_index) const {
393  return pfTauTransverseImpactParameters->value(tau_index)->dxy_PCA();
394  }
395  auto getdxyPCA(const pat::Tau& tau, const size_t tau_index) const { return tau.dxy_PCA(); }
396  auto getdxy(const reco::PFTau& tau, const size_t tau_index) const {
397  return pfTauTransverseImpactParameters->value(tau_index)->dxy();
398  }
399  auto getdxy(const pat::Tau& tau, const size_t tau_index) const { return tau.dxy(); }
400  auto getdxyError(const reco::PFTau& tau, const size_t tau_index) const {
401  return pfTauTransverseImpactParameters->value(tau_index)->dxy_error();
402  }
403  auto getdxyError(const pat::Tau& tau, const size_t tau_index) const { return tau.dxy_error(); }
404  auto getdxySig(const reco::PFTau& tau, const size_t tau_index) const {
405  return pfTauTransverseImpactParameters->value(tau_index)->dxy_Sig();
406  }
407  auto getdxySig(const pat::Tau& tau, const size_t tau_index) const { return tau.dxy_Sig(); }
408  auto getip3d(const reco::PFTau& tau, const size_t tau_index) const {
409  return pfTauTransverseImpactParameters->value(tau_index)->ip3d();
410  }
411  auto getip3d(const pat::Tau& tau, const size_t tau_index) const { return tau.ip3d(); }
412  auto getip3dError(const reco::PFTau& tau, const size_t tau_index) const {
413  return pfTauTransverseImpactParameters->value(tau_index)->ip3d_error();
414  }
415  auto getip3dError(const pat::Tau& tau, const size_t tau_index) const { return tau.ip3d_error(); }
416  auto getip3dSig(const reco::PFTau& tau, const size_t tau_index) const {
417  return pfTauTransverseImpactParameters->value(tau_index)->ip3d_Sig();
418  }
419  auto getip3dSig(const pat::Tau& tau, const size_t tau_index) const { return tau.ip3d_Sig(); }
420  auto getHasSecondaryVertex(const reco::PFTau& tau, const size_t tau_index) const {
421  return pfTauTransverseImpactParameters->value(tau_index)->hasSecondaryVertex();
422  }
423  auto getHasSecondaryVertex(const pat::Tau& tau, const size_t tau_index) const { return tau.hasSecondaryVertex(); }
424  auto getFlightLength(const reco::PFTau& tau, const size_t tau_index) const {
425  return pfTauTransverseImpactParameters->value(tau_index)->flightLength();
426  }
427  auto getFlightLength(const pat::Tau& tau, const size_t tau_index) const { return tau.flightLength(); }
428  auto getFlightLengthSig(const reco::PFTau& tau, const size_t tau_index) const {
429  return pfTauTransverseImpactParameters->value(tau_index)->flightLengthSig();
430  }
431  auto getFlightLengthSig(const pat::Tau& tau, const size_t tau_index) const { return tau.flightLengthSig(); }
432 
433  auto getLeadingTrackNormChi2(const reco::PFTau& tau) { return reco::tau::lead_track_chi2(tau); }
434  auto getLeadingTrackNormChi2(const pat::Tau& tau) { return tau.leadingTrackNormChi2(); }
435  auto getEmFraction(const pat::Tau& tau) { return tau.emFraction_MVA(); }
436  auto getEmFraction(const reco::PFTau& tau) { return tau.emFraction(); }
437  auto getEtaAtEcalEntrance(const pat::Tau& tau) { return tau.etaAtEcalEntranceLeadChargedCand(); }
438  auto getEtaAtEcalEntrance(const reco::PFTau& tau) {
439  return tau.leadPFChargedHadrCand()->positionAtECALEntrance().eta();
440  }
441  auto getEcalEnergyLeadingChargedHadr(const reco::PFTau& tau) { return tau.leadPFChargedHadrCand()->ecalEnergy(); }
442  auto getEcalEnergyLeadingChargedHadr(const pat::Tau& tau) { return tau.ecalEnergyLeadChargedHadrCand(); }
443  auto getHcalEnergyLeadingChargedHadr(const reco::PFTau& tau) { return tau.leadPFChargedHadrCand()->hcalEnergy(); }
444  auto getHcalEnergyLeadingChargedHadr(const pat::Tau& tau) { return tau.hcalEnergyLeadChargedHadrCand(); }
445 
446  template <typename PreDiscrType>
447  bool passPrediscriminants(const PreDiscrType prediscriminants,
448  const size_t andPrediscriminants,
449  const edm::RefToBase<reco::BaseTau> tau_ref) {
450  bool passesPrediscriminants = (andPrediscriminants ? 1 : 0);
451  // check tau passes prediscriminants
452  size_t nPrediscriminants = prediscriminants.size();
453  for (size_t iDisc = 0; iDisc < nPrediscriminants; ++iDisc) {
454  // current discriminant result for this tau
455  double discResult = (*prediscriminants[iDisc].handle)[tau_ref];
456  uint8_t thisPasses = (discResult > prediscriminants[iDisc].cut) ? 1 : 0;
457 
458  // if we are using the AND option, as soon as one fails,
459  // the result is FAIL and we can quit looping.
460  // if we are using the OR option as soon as one passes,
461  // the result is pass and we can quit looping
462 
463  // truth table
464  // | result (thisPasses)
465  // | F | T
466  //-----------------------------------
467  // AND(T) | res=fails | continue
468  // | break |
469  //-----------------------------------
470  // OR (F) | continue | res=passes
471  // | | break
472 
473  if (thisPasses ^ andPrediscriminants) //XOR
474  {
475  passesPrediscriminants = (andPrediscriminants ? 0 : 1); //NOR
476  break;
477  }
478  }
479  return passesPrediscriminants;
480  }
481  };
482 
483  namespace candFunc {
484  auto getTauDz(const reco::PFCandidate& cand) { return cand.bestTrack()->dz(); }
485  auto getTauDz(const pat::PackedCandidate& cand) { return cand.dz(); }
486  auto getTauDZSigValid(const reco::PFCandidate& cand) {
487  return cand.bestTrack() != nullptr && std::isnormal(cand.bestTrack()->dz()) && std::isnormal(cand.dzError()) &&
488  cand.dzError() > 0;
489  }
490  auto getTauDZSigValid(const pat::PackedCandidate& cand) {
491  return cand.hasTrackDetails() && std::isnormal(cand.dz()) && std::isnormal(cand.dzError()) && cand.dzError() > 0;
492  }
493  auto getTauDxy(const reco::PFCandidate& cand) { return cand.bestTrack()->dxy(); }
494  auto getTauDxy(const pat::PackedCandidate& cand) { return cand.dxy(); }
495  auto getPvAssocationQuality(const reco::PFCandidate& cand) { return 0.7013f; }
496  auto getPvAssocationQuality(const pat::PackedCandidate& cand) { return cand.pvAssociationQuality(); }
497  auto getPuppiWeight(const reco::PFCandidate& cand, const float aod_value) { return aod_value; }
498  auto getPuppiWeight(const pat::PackedCandidate& cand, const float aod_value) { return cand.puppiWeight(); }
499  auto getPuppiWeightNoLep(const reco::PFCandidate& cand, const float aod_value) { return aod_value; }
500  auto getPuppiWeightNoLep(const pat::PackedCandidate& cand, const float aod_value) {
501  return cand.puppiWeightNoLep();
502  }
503  auto getLostInnerHits(const reco::PFCandidate& cand, float default_value) {
504  return cand.bestTrack() != nullptr
505  ? cand.bestTrack()->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_INNER_HITS)
506  : default_value;
507  }
508  auto getLostInnerHits(const pat::PackedCandidate& cand, float default_value) { return cand.lostInnerHits(); }
509  auto getNumberOfPixelHits(const reco::PFCandidate& cand, float default_value) {
510  return cand.bestTrack() != nullptr
511  ? cand.bestTrack()->hitPattern().numberOfLostHits(reco::HitPattern::MISSING_INNER_HITS)
512  : default_value;
513  }
514  auto getNumberOfPixelHits(const pat::PackedCandidate& cand, float default_value) {
515  return cand.numberOfPixelHits();
516  }
517  auto getHasTrackDetails(const reco::PFCandidate& cand) { return cand.bestTrack() != nullptr; }
518  auto getHasTrackDetails(const pat::PackedCandidate& cand) { return cand.hasTrackDetails(); }
519  auto getPseudoTrack(const reco::PFCandidate& cand) { return *cand.bestTrack(); }
520  auto getPseudoTrack(const pat::PackedCandidate& cand) { return cand.pseudoTrack(); }
521  auto getFromPV(const reco::PFCandidate& cand) { return 0.9994f; }
522  auto getFromPV(const pat::PackedCandidate& cand) { return cand.fromPV(); }
523  auto getHCalFraction(const reco::PFCandidate& cand, bool disable_hcalFraction_workaround) {
524  return cand.rawHcalEnergy() / (cand.rawHcalEnergy() + cand.rawEcalEnergy());
525  }
526  auto getHCalFraction(const pat::PackedCandidate& cand, bool disable_hcalFraction_workaround) {
527  float hcal_fraction = 0.;
529  // CV: use consistent definition for pfCand_chHad_hcalFraction
530  // in DeepTauId.cc code and in TauMLTools/Production/plugins/TauTupleProducer.cc
531  hcal_fraction = cand.hcalFraction();
532  } else {
533  // CV: backwards compatibility with DeepTau training v2p1 used during Run 2
534  if (cand.pdgId() == 1 || cand.pdgId() == 130) {
535  hcal_fraction = cand.hcalFraction();
536  } else if (cand.isIsolatedChargedHadron()) {
537  hcal_fraction = cand.rawHcalFraction();
538  }
539  }
540  return hcal_fraction;
541  }
542  auto getRawCaloFraction(const reco::PFCandidate& cand) {
543  return (cand.rawEcalEnergy() + cand.rawHcalEnergy()) / cand.energy();
544  }
545  auto getRawCaloFraction(const pat::PackedCandidate& cand) { return cand.rawCaloFraction(); }
546  }; // namespace candFunc
547 
548  template <typename LVector1, typename LVector2>
549  float dEta(const LVector1& p4, const LVector2& tau_p4) {
550  return static_cast<float>(p4.eta() - tau_p4.eta());
551  }
552 
553  template <typename LVector1, typename LVector2>
554  float dPhi(const LVector1& p4_1, const LVector2& p4_2) {
555  return static_cast<float>(reco::deltaPhi(p4_2.phi(), p4_1.phi()));
556  }
557 
558  struct MuonHitMatchV2 {
559  static constexpr size_t n_muon_stations = 4;
560  static constexpr int first_station_id = 1;
561  static constexpr int last_station_id = first_station_id + n_muon_stations - 1;
562  using CountArray = std::array<unsigned, n_muon_stations>;
563  using CountMap = std::map<int, CountArray>;
564 
565  const std::vector<int>& consideredSubdets() {
566  static const std::vector<int> subdets = {MuonSubdetId::DT, MuonSubdetId::CSC, MuonSubdetId::RPC};
567  return subdets;
568  }
569 
570  const std::string& subdetName(int subdet) {
571  static const std::map<int, std::string> subdet_names = {
572  {MuonSubdetId::DT, "DT"}, {MuonSubdetId::CSC, "CSC"}, {MuonSubdetId::RPC, "RPC"}};
573  if (!subdet_names.count(subdet))
574  throw cms::Exception("MuonHitMatch") << "Subdet name for subdet id " << subdet << " not found.";
575  return subdet_names.at(subdet);
576  }
577 
578  size_t getStationIndex(int station, bool throw_exception) const {
579  if (station < first_station_id || station > last_station_id) {
580  if (throw_exception)
581  throw cms::Exception("MuonHitMatch") << "Station id is out of range";
583  }
584  return static_cast<size_t>(station - 1);
585  }
586 
587  MuonHitMatchV2(const pat::Muon& muon) {
588  for (int subdet : consideredSubdets()) {
589  n_matches[subdet].fill(0);
590  n_hits[subdet].fill(0);
591  }
592 
593  countMatches(muon, n_matches);
594  countHits(muon, n_hits);
595  }
596 
597  void countMatches(const pat::Muon& muon, CountMap& n_matches) {
598  for (const auto& segment : muon.matches()) {
599  if (segment.segmentMatches.empty() && segment.rpcMatches.empty())
600  continue;
601  if (n_matches.count(segment.detector())) {
602  const size_t station_index = getStationIndex(segment.station(), true);
603  ++n_matches.at(segment.detector()).at(station_index);
604  }
605  }
606  }
607 
608  void countHits(const pat::Muon& muon, CountMap& n_hits) {
609  if (muon.outerTrack().isNonnull()) {
610  const auto& hit_pattern = muon.outerTrack()->hitPattern();
611  for (int hit_index = 0; hit_index < hit_pattern.numberOfAllHits(reco::HitPattern::TRACK_HITS); ++hit_index) {
612  auto hit_id = hit_pattern.getHitPattern(reco::HitPattern::TRACK_HITS, hit_index);
613  if (hit_id == 0)
614  break;
615  if (hit_pattern.muonHitFilter(hit_id) && (hit_pattern.getHitType(hit_id) == TrackingRecHit::valid ||
616  hit_pattern.getHitType(hit_id) == TrackingRecHit::bad)) {
617  const size_t station_index = getStationIndex(hit_pattern.getMuonStation(hit_id), false);
618  if (station_index < n_muon_stations) {
619  CountArray* muon_n_hits = nullptr;
620  if (hit_pattern.muonDTHitFilter(hit_id))
621  muon_n_hits = &n_hits.at(MuonSubdetId::DT);
622  else if (hit_pattern.muonCSCHitFilter(hit_id))
623  muon_n_hits = &n_hits.at(MuonSubdetId::CSC);
624  else if (hit_pattern.muonRPCHitFilter(hit_id))
625  muon_n_hits = &n_hits.at(MuonSubdetId::RPC);
626 
627  if (muon_n_hits)
628  ++muon_n_hits->at(station_index);
629  }
630  }
631  }
632  }
633  }
634 
635  unsigned nMatches(int subdet, int station) const {
636  if (!n_matches.count(subdet))
637  throw cms::Exception("MuonHitMatch") << "Subdet " << subdet << " not found.";
638  const size_t station_index = getStationIndex(station, true);
639  return n_matches.at(subdet).at(station_index);
640  }
641 
642  unsigned nHits(int subdet, int station) const {
643  if (!n_hits.count(subdet))
644  throw cms::Exception("MuonHitMatch") << "Subdet " << subdet << " not found.";
645  const size_t station_index = getStationIndex(station, true);
646  return n_hits.at(subdet).at(station_index);
647  }
648 
649  unsigned countMuonStationsWithMatches(int first_station, int last_station) const {
650  static const std::map<int, std::vector<bool>> masks = {
651  {MuonSubdetId::DT, {false, false, false, false}},
652  {MuonSubdetId::CSC, {true, false, false, false}},
653  {MuonSubdetId::RPC, {false, false, false, false}},
654  };
655  const size_t first_station_index = getStationIndex(first_station, true);
656  const size_t last_station_index = getStationIndex(last_station, true);
657  unsigned cnt = 0;
658  for (size_t n = first_station_index; n <= last_station_index; ++n) {
659  for (const auto& match : n_matches) {
660  if (!masks.at(match.first).at(n) && match.second.at(n) > 0)
661  ++cnt;
662  }
663  }
664  return cnt;
665  }
666 
667  unsigned countMuonStationsWithHits(int first_station, int last_station) const {
668  static const std::map<int, std::vector<bool>> masks = {
669  {MuonSubdetId::DT, {false, false, false, false}},
670  {MuonSubdetId::CSC, {false, false, false, false}},
671  {MuonSubdetId::RPC, {false, false, false, false}},
672  };
673 
674  const size_t first_station_index = getStationIndex(first_station, true);
675  const size_t last_station_index = getStationIndex(last_station, true);
676  unsigned cnt = 0;
677  for (size_t n = first_station_index; n <= last_station_index; ++n) {
678  for (const auto& hit : n_hits) {
679  if (!masks.at(hit.first).at(n) && hit.second.at(n) > 0)
680  ++cnt;
681  }
682  }
683  return cnt;
684  }
685 
686  private:
687  CountMap n_matches, n_hits;
688  };
689 
690  enum class CellObjectType {
691  PfCand_electron,
692  PfCand_muon,
693  PfCand_chargedHadron,
694  PfCand_neutralHadron,
695  PfCand_gamma,
696  Electron,
697  Muon,
698  Other
699  };
700 
701  template <typename Object>
702  CellObjectType GetCellObjectType(const Object&);
703  template <>
704  CellObjectType GetCellObjectType(const pat::Electron&) {
706  }
707  template <>
708  CellObjectType GetCellObjectType(const pat::Muon&) {
709  return CellObjectType::Muon;
710  }
711 
712  template <>
713  CellObjectType GetCellObjectType(reco::Candidate const& cand) {
714  static const std::map<int, CellObjectType> obj_types = {{11, CellObjectType::PfCand_electron},
715  {13, CellObjectType::PfCand_muon},
716  {22, CellObjectType::PfCand_gamma},
717  {130, CellObjectType::PfCand_neutralHadron},
718  {211, CellObjectType::PfCand_chargedHadron}};
719 
720  auto iter = obj_types.find(std::abs(cand.pdgId()));
721  if (iter == obj_types.end())
722  return CellObjectType::Other;
723  return iter->second;
724  }
725 
726  using Cell = std::map<CellObjectType, size_t>;
727  struct CellIndex {
728  int eta, phi;
729 
730  bool operator<(const CellIndex& other) const {
731  if (eta != other.eta)
732  return eta < other.eta;
733  return phi < other.phi;
734  }
735  };
736 
737  class CellGrid {
738  public:
739  using Map = std::map<CellIndex, Cell>;
740  using const_iterator = Map::const_iterator;
741 
742  CellGrid(unsigned n_cells_eta,
743  unsigned n_cells_phi,
744  double cell_size_eta,
745  double cell_size_phi,
747  : nCellsEta(n_cells_eta),
748  nCellsPhi(n_cells_phi),
749  nTotal(nCellsEta * nCellsPhi),
750  cellSizeEta(cell_size_eta),
751  cellSizePhi(cell_size_phi),
752  disable_CellIndex_workaround_(disable_CellIndex_workaround) {
753  if (nCellsEta % 2 != 1 || nCellsEta < 1)
754  throw cms::Exception("DeepTauId") << "Invalid number of eta cells.";
755  if (nCellsPhi % 2 != 1 || nCellsPhi < 1)
756  throw cms::Exception("DeepTauId") << "Invalid number of phi cells.";
757  if (cellSizeEta <= 0 || cellSizePhi <= 0)
758  throw cms::Exception("DeepTauId") << "Invalid cell size.";
759  }
760 
761  int maxEtaIndex() const { return static_cast<int>((nCellsEta - 1) / 2); }
762  int maxPhiIndex() const { return static_cast<int>((nCellsPhi - 1) / 2); }
763  double maxDeltaEta() const { return cellSizeEta * (0.5 + maxEtaIndex()); }
764  double maxDeltaPhi() const { return cellSizePhi * (0.5 + maxPhiIndex()); }
765  int getEtaTensorIndex(const CellIndex& cellIndex) const { return cellIndex.eta + maxEtaIndex(); }
766  int getPhiTensorIndex(const CellIndex& cellIndex) const { return cellIndex.phi + maxPhiIndex(); }
767 
768  bool tryGetCellIndex(double deltaEta, double deltaPhi, CellIndex& cellIndex) const {
769  const auto getCellIndex = [this](double x, double maxX, double size, int& index) {
770  const double absX = std::abs(x);
771  if (absX > maxX)
772  return false;
773  double absIndex;
774  if (disable_CellIndex_workaround_) {
775  // CV: use consistent definition for CellIndex
776  // in DeepTauId.cc code and new DeepTau trainings
777  absIndex = std::floor(absX / size + 0.5);
778  } else {
779  // CV: backwards compatibility with DeepTau training v2p1 used during Run 2
780  absIndex = std::floor(std::abs(absX / size - 0.5));
781  }
782  index = static_cast<int>(std::copysign(absIndex, x));
783  return true;
784  };
785 
786  return getCellIndex(deltaEta, maxDeltaEta(), cellSizeEta, cellIndex.eta) &&
787  getCellIndex(deltaPhi, maxDeltaPhi(), cellSizePhi, cellIndex.phi);
788  }
789 
790  size_t num_valid_cells() const { return cells.size(); }
791  Cell& operator[](const CellIndex& cellIndex) { return cells[cellIndex]; }
792  const Cell& at(const CellIndex& cellIndex) const { return cells.at(cellIndex); }
793  size_t count(const CellIndex& cellIndex) const { return cells.count(cellIndex); }
794  const_iterator find(const CellIndex& cellIndex) const { return cells.find(cellIndex); }
795  const_iterator begin() const { return cells.begin(); }
796  const_iterator end() const { return cells.end(); }
797 
798  public:
799  const unsigned nCellsEta, nCellsPhi, nTotal;
800  const double cellSizeEta, cellSizePhi;
801 
802  private:
803  std::map<CellIndex, Cell> cells;
804  const bool disable_CellIndex_workaround_;
805  };
806 } // anonymous namespace
807 
809 const std::map<bd, std::string> deep_tau::DeepTauBase::stringFromDiscriminator_{
810  {bd::ChargedIsoPtSum, "ChargedIsoPtSum"},
811  {bd::NeutralIsoPtSum, "NeutralIsoPtSum"},
812  {bd::NeutralIsoPtSumWeight, "NeutralIsoPtSumWeight"},
813  {bd::FootprintCorrection, "TauFootprintCorrection"},
814  {bd::PhotonPtSumOutsideSignalCone, "PhotonPtSumOutsideSignalCone"},
815  {bd::PUcorrPtSum, "PUcorrPtSum"}};
816 const std::vector<bd> deep_tau::DeepTauBase::requiredBasicDiscriminators_ = {bd::ChargedIsoPtSum,
817  bd::NeutralIsoPtSum,
818  bd::NeutralIsoPtSumWeight,
819  bd::PhotonPtSumOutsideSignalCone,
820  bd::PUcorrPtSum};
821 const std::vector<bd> deep_tau::DeepTauBase::requiredBasicDiscriminatorsdR03_ = {bd::ChargedIsoPtSum,
822  bd::NeutralIsoPtSum,
823  bd::NeutralIsoPtSumWeight,
824  bd::PhotonPtSumOutsideSignalCone,
825  bd::FootprintCorrection};
826 
828 public:
829  static constexpr float default_value = -999.;
830 
831  static const OutputCollection& GetOutputs() {
832  static constexpr size_t e_index = 0, mu_index = 1, tau_index = 2, jet_index = 3;
833  static const OutputCollection outputs_ = {
834  {"VSe", Output({tau_index}, {e_index, tau_index})},
835  {"VSmu", Output({tau_index}, {mu_index, tau_index})},
836  {"VSjet", Output({tau_index}, {jet_index, tau_index})},
837  };
838  return outputs_;
839  }
840 
841  const std::map<BasicDiscriminator, size_t> matchDiscriminatorIndices(
842  edm::Event& event,
843  edm::EDGetTokenT<reco::TauDiscriminatorContainer> discriminatorContainerToken,
844  std::vector<BasicDiscriminator> requiredDiscr) {
845  std::map<std::string, size_t> discrIndexMapStr;
846  auto const aHandle = event.getHandle(discriminatorContainerToken);
847  auto const aProv = aHandle.provenance();
848  if (aProv == nullptr)
849  aHandle.whyFailed()->raise();
850  const auto& psetsFromProvenance = edm::parameterSet(aProv->stable(), event.processHistory());
851  auto const idlist = psetsFromProvenance.getParameter<std::vector<edm::ParameterSet>>("IDdefinitions");
852  for (size_t j = 0; j < idlist.size(); ++j) {
853  std::string idname = idlist[j].getParameter<std::string>("IDname");
854  if (discrIndexMapStr.count(idname)) {
855  throw cms::Exception("DeepTauId")
856  << "basic discriminator " << idname << " appears more than once in the input.";
857  }
858  discrIndexMapStr[idname] = j;
859  }
860 
861  //translate to a map of <BasicDiscriminator, index> and check if all discriminators are present
862  std::map<BasicDiscriminator, size_t> discrIndexMap;
863  for (size_t i = 0; i < requiredDiscr.size(); i++) {
864  if (discrIndexMapStr.find(stringFromDiscriminator_.at(requiredDiscr[i])) == discrIndexMapStr.end())
865  throw cms::Exception("DeepTauId") << "Basic Discriminator " << stringFromDiscriminator_.at(requiredDiscr[i])
866  << " was not provided in the config file.";
867  else
868  discrIndexMap[requiredDiscr[i]] = discrIndexMapStr[stringFromDiscriminator_.at(requiredDiscr[i])];
869  }
870  return discrIndexMap;
871  }
872 
875  desc.add<edm::InputTag>("electrons", edm::InputTag("slimmedElectrons"));
876  desc.add<edm::InputTag>("muons", edm::InputTag("slimmedMuons"));
877  desc.add<edm::InputTag>("taus", edm::InputTag("slimmedTaus"));
878  desc.add<edm::InputTag>("pfcands", edm::InputTag("packedPFCandidates"));
879  desc.add<edm::InputTag>("vertices", edm::InputTag("offlineSlimmedPrimaryVertices"));
880  desc.add<edm::InputTag>("rho", edm::InputTag("fixedGridRhoAll"));
881  desc.add<std::vector<std::string>>("graph_file",
882  {"RecoTauTag/TrainingFiles/data/DeepTauId/deepTau_2017v2p6_e6.pb"});
883  desc.add<bool>("mem_mapped", false);
884  desc.add<unsigned>("year", 2017);
885  desc.add<unsigned>("version", 2);
886  desc.add<unsigned>("sub_version", 1);
887  desc.add<int>("debug_level", 0);
888  desc.add<bool>("disable_dxy_pca", false);
889  desc.add<bool>("disable_hcalFraction_workaround", false);
890  desc.add<bool>("disable_CellIndex_workaround", false);
891  desc.add<bool>("save_inputs", false);
892  desc.add<bool>("is_online", false);
893 
894  desc.add<std::vector<std::string>>("VSeWP", {"-1."});
895  desc.add<std::vector<std::string>>("VSmuWP", {"-1."});
896  desc.add<std::vector<std::string>>("VSjetWP", {"-1."});
897 
898  desc.addUntracked<edm::InputTag>("basicTauDiscriminators", edm::InputTag("basicTauDiscriminators"));
899  desc.addUntracked<edm::InputTag>("basicTauDiscriminatorsdR03", edm::InputTag("basicTauDiscriminatorsdR03"));
900  desc.add<edm::InputTag>("pfTauTransverseImpactParameters", edm::InputTag("hpsPFTauTransverseImpactParameters"));
901 
902  {
903  edm::ParameterSetDescription pset_Prediscriminants;
904  pset_Prediscriminants.add<std::string>("BooleanOperator", "and");
905  {
907  psd1.add<double>("cut");
908  psd1.add<edm::InputTag>("Producer");
909  pset_Prediscriminants.addOptional<edm::ParameterSetDescription>("decayMode", psd1);
910  }
911  desc.add<edm::ParameterSetDescription>("Prediscriminants", pset_Prediscriminants);
912  }
913 
914  descriptions.add("DeepTau", desc);
915  }
916 
917 public:
920  electrons_token_(consumes<std::vector<pat::Electron>>(cfg.getParameter<edm::InputTag>("electrons"))),
921  muons_token_(consumes<std::vector<pat::Muon>>(cfg.getParameter<edm::InputTag>("muons"))),
922  rho_token_(consumes<double>(cfg.getParameter<edm::InputTag>("rho"))),
924  cfg.getUntrackedParameter<edm::InputTag>("basicTauDiscriminators"))),
926  cfg.getUntrackedParameter<edm::InputTag>("basicTauDiscriminatorsdR03"))),
928  consumes<edm::AssociationVector<reco::PFTauRefProd, std::vector<reco::PFTauTransverseImpactParameterRef>>>(
929  cfg.getParameter<edm::InputTag>("pfTauTransverseImpactParameters"))),
930  year_(cfg.getParameter<unsigned>("year")),
931  version_(cfg.getParameter<unsigned>("version")),
932  sub_version_(cfg.getParameter<unsigned>("sub_version")),
933  debug_level(cfg.getParameter<int>("debug_level")),
934  disable_dxy_pca_(cfg.getParameter<bool>("disable_dxy_pca")),
935  disable_hcalFraction_workaround_(cfg.getParameter<bool>("disable_hcalFraction_workaround")),
936  disable_CellIndex_workaround_(cfg.getParameter<bool>("disable_CellIndex_workaround")),
937  save_inputs_(cfg.getParameter<bool>("save_inputs")),
938  json_file_(nullptr),
939  file_counter_(0) {
940  if (version_ == 2) {
941  using namespace dnn_inputs_v2;
942  namespace sc = deep_tau::Scaling;
943  tauInputs_indices_.resize(TauBlockInputs::NumberOfInputs);
944  std::iota(std::begin(tauInputs_indices_), std::end(tauInputs_indices_), 0);
945 
946  if (sub_version_ == 1) {
947  tauBlockTensor_ = std::make_unique<tensorflow::Tensor>(
948  tensorflow::DT_FLOAT, tensorflow::TensorShape{1, TauBlockInputs::NumberOfInputs});
950  } else if (sub_version_ == 5) {
951  std::sort(TauBlockInputs::varsToDrop.begin(), TauBlockInputs::varsToDrop.end());
952  for (auto v : TauBlockInputs::varsToDrop) {
953  tauInputs_indices_.at(v) = -1; // set index to -1
954  for (std::size_t i = v + 1; i < TauBlockInputs::NumberOfInputs; ++i)
955  tauInputs_indices_.at(i) -= 1; // shift all the following indices by 1
956  }
957  tauBlockTensor_ = std::make_unique<tensorflow::Tensor>(
958  tensorflow::DT_FLOAT,
959  tensorflow::TensorShape{1,
960  static_cast<int>(TauBlockInputs::NumberOfInputs) -
961  static_cast<int>(TauBlockInputs::varsToDrop.size())});
962  if (year_ == 2026) {
964  } else {
966  }
967  } else
968  throw cms::Exception("DeepTauId") << "subversion " << sub_version_ << " is not supported.";
969 
970  std::map<std::vector<bool>, std::vector<sc::FeatureT>> GridFeatureTypes_map = {
971  {{false}, {sc::FeatureT::TauFlat, sc::FeatureT::GridGlobal}}, // feature types without inner/outer grid split
972  {{false, true},
973  {sc::FeatureT::PfCand_electron,
974  sc::FeatureT::PfCand_muon, // feature types with inner/outer grid split
975  sc::FeatureT::PfCand_chHad,
976  sc::FeatureT::PfCand_nHad,
977  sc::FeatureT::PfCand_gamma,
980 
981  // check that sizes of mean/std/lim_min/lim_max vectors are equal between each other
982  for (const auto& p : GridFeatureTypes_map) {
983  for (auto is_inner : p.first) {
984  for (auto featureType : p.second) {
985  const sc::ScalingParams& sp = scalingParamsMap_->at(std::make_pair(featureType, is_inner));
986  if (!(sp.mean_.size() == sp.std_.size() && sp.mean_.size() == sp.lim_min_.size() &&
987  sp.mean_.size() == sp.lim_max_.size()))
988  throw cms::Exception("DeepTauId") << "sizes of scaling parameter vectors do not match between each other";
989  }
990  }
991  }
992 
993  for (size_t n = 0; n < 2; ++n) {
994  const bool is_inner = n == 0;
995  const auto n_cells = is_inner ? number_of_inner_cell : number_of_outer_cell;
996  eGammaTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
997  tensorflow::DT_FLOAT, tensorflow::TensorShape{1, 1, 1, EgammaBlockInputs::NumberOfInputs});
998  muonTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
999  tensorflow::DT_FLOAT, tensorflow::TensorShape{1, 1, 1, MuonBlockInputs::NumberOfInputs});
1000  hadronsTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
1001  tensorflow::DT_FLOAT, tensorflow::TensorShape{1, 1, 1, HadronBlockInputs::NumberOfInputs});
1002  convTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
1003  tensorflow::DT_FLOAT, tensorflow::TensorShape{1, n_cells, n_cells, number_of_conv_features});
1004  zeroOutputTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
1005  tensorflow::DT_FLOAT, tensorflow::TensorShape{1, 1, 1, number_of_conv_features});
1006 
1007  eGammaTensor_[is_inner]->flat<float>().setZero();
1008  muonTensor_[is_inner]->flat<float>().setZero();
1009  hadronsTensor_[is_inner]->flat<float>().setZero();
1010 
1011  setCellConvFeatures(*zeroOutputTensor_[is_inner], getPartialPredictions(is_inner), 0, 0, 0);
1012  }
1013  } else {
1014  throw cms::Exception("DeepTauId") << "version " << version_ << " is not supported.";
1015  }
1016  }
1017 
1018  static std::unique_ptr<deep_tau::DeepTauCache> initializeGlobalCache(const edm::ParameterSet& cfg) {
1019  return DeepTauBase::initializeGlobalCache(cfg);
1020  }
1021 
1022  static void globalEndJob(const deep_tau::DeepTauCache* cache_) { return DeepTauBase::globalEndJob(cache_); }
1023 
1024 private:
1025  static constexpr float pi = M_PI;
1026 
1027  template <typename T>
1028  static float getValue(T value) {
1029  return std::isnormal(value) ? static_cast<float>(value) : 0.f;
1030  }
1031 
1032  template <typename T>
1033  static float getValueLinear(T value, float min_value, float max_value, bool positive) {
1034  const float fixed_value = getValue(value);
1035  const float clamped_value = std::clamp(fixed_value, min_value, max_value);
1036  float transformed_value = (clamped_value - min_value) / (max_value - min_value);
1037  if (!positive)
1038  transformed_value = transformed_value * 2 - 1;
1039  return transformed_value;
1040  }
1041 
1042  template <typename T>
1043  static float getValueNorm(T value, float mean, float sigma, float n_sigmas_max = 5) {
1044  const float fixed_value = getValue(value);
1045  const float norm_value = (fixed_value - mean) / sigma;
1046  return std::clamp(norm_value, -n_sigmas_max, n_sigmas_max);
1047  }
1048 
1049  static bool isAbove(double value, double min) { return std::isnormal(value) && value > min; }
1050 
1052  float& cc_ele_energy,
1053  float& cc_gamma_energy,
1054  int& cc_n_gamma) {
1055  cc_ele_energy = cc_gamma_energy = 0;
1056  cc_n_gamma = 0;
1057  const auto& superCluster = ele.superCluster();
1058  if (superCluster.isNonnull() && superCluster.isAvailable() && superCluster->clusters().isNonnull() &&
1059  superCluster->clusters().isAvailable()) {
1060  for (auto iter = superCluster->clustersBegin(); iter != superCluster->clustersEnd(); ++iter) {
1061  const float energy = static_cast<float>((*iter)->energy());
1062  if (iter == superCluster->clustersBegin())
1063  cc_ele_energy += energy;
1064  else {
1065  cc_gamma_energy += energy;
1066  ++cc_n_gamma;
1067  }
1068  }
1069  return true;
1070  } else
1071  return false;
1072  }
1073 
1074  inline void checkInputs(const tensorflow::Tensor& inputs,
1075  const std::string& block_name,
1076  int n_inputs,
1077  const CellGrid* grid = nullptr) const {
1078  if (debug_level >= 1) {
1079  std::cout << "<checkInputs>: block_name = " << block_name << std::endl;
1080  if (block_name == "input_tau") {
1081  for (int input_index = 0; input_index < n_inputs; ++input_index) {
1082  float input = inputs.matrix<float>()(0, input_index);
1083  if (edm::isNotFinite(input)) {
1084  throw cms::Exception("DeepTauId")
1085  << "in the " << block_name
1086  << ", input is not finite, i.e. infinite or NaN, for input_index = " << input_index;
1087  }
1088  if (debug_level >= 2) {
1089  std::cout << block_name << "[var = " << input_index << "] = " << std::setprecision(5) << std::fixed << input
1090  << std::endl;
1091  }
1092  }
1093  } else {
1094  assert(grid);
1095  int n_eta, n_phi;
1096  if (block_name.find("input_inner") != std::string::npos) {
1097  n_eta = 5;
1098  n_phi = 5;
1099  } else if (block_name.find("input_outer") != std::string::npos) {
1100  n_eta = 10;
1101  n_phi = 10;
1102  } else
1103  assert(0);
1104  int eta_phi_index = 0;
1105  for (int eta = -n_eta; eta <= n_eta; ++eta) {
1106  for (int phi = -n_phi; phi <= n_phi; ++phi) {
1107  const CellIndex cell_index{eta, phi};
1108  const auto cell_iter = grid->find(cell_index);
1109  if (cell_iter != grid->end()) {
1110  for (int input_index = 0; input_index < n_inputs; ++input_index) {
1111  float input = inputs.tensor<float, 4>()(eta_phi_index, 0, 0, input_index);
1112  if (edm::isNotFinite(input)) {
1113  throw cms::Exception("DeepTauId")
1114  << "in the " << block_name << ", input is not finite, i.e. infinite or NaN, for eta = " << eta
1115  << ", phi = " << phi << ", input_index = " << input_index;
1116  }
1117  if (debug_level >= 2) {
1118  std::cout << block_name << "[eta = " << eta << "][phi = " << phi << "][var = " << input_index
1119  << "] = " << std::setprecision(5) << std::fixed << input << std::endl;
1120  }
1121  }
1122  eta_phi_index += 1;
1123  }
1124  }
1125  }
1126  }
1127  }
1128  }
1129 
1130  inline void saveInputs(const tensorflow::Tensor& inputs,
1131  const std::string& block_name,
1132  int n_inputs,
1133  const CellGrid* grid = nullptr) {
1134  if (debug_level >= 1) {
1135  std::cout << "<saveInputs>: block_name = " << block_name << std::endl;
1136  }
1137  if (!is_first_block_)
1138  (*json_file_) << ", ";
1139  (*json_file_) << "\"" << block_name << "\": [";
1140  if (block_name == "input_tau") {
1141  for (int input_index = 0; input_index < n_inputs; ++input_index) {
1142  float input = inputs.matrix<float>()(0, input_index);
1143  if (input_index != 0)
1144  (*json_file_) << ", ";
1145  (*json_file_) << input;
1146  }
1147  } else {
1148  assert(grid);
1149  int n_eta, n_phi;
1150  if (block_name.find("input_inner") != std::string::npos) {
1151  n_eta = 5;
1152  n_phi = 5;
1153  } else if (block_name.find("input_outer") != std::string::npos) {
1154  n_eta = 10;
1155  n_phi = 10;
1156  } else
1157  assert(0);
1158  int eta_phi_index = 0;
1159  for (int eta = -n_eta; eta <= n_eta; ++eta) {
1160  if (eta != -n_eta)
1161  (*json_file_) << ", ";
1162  (*json_file_) << "[";
1163  for (int phi = -n_phi; phi <= n_phi; ++phi) {
1164  if (phi != -n_phi)
1165  (*json_file_) << ", ";
1166  (*json_file_) << "[";
1167  const CellIndex cell_index{eta, phi};
1168  const auto cell_iter = grid->find(cell_index);
1169  for (int input_index = 0; input_index < n_inputs; ++input_index) {
1170  float input = 0.;
1171  if (cell_iter != grid->end()) {
1172  input = inputs.tensor<float, 4>()(eta_phi_index, 0, 0, input_index);
1173  }
1174  if (input_index != 0)
1175  (*json_file_) << ", ";
1176  (*json_file_) << input;
1177  }
1178  if (cell_iter != grid->end()) {
1179  eta_phi_index += 1;
1180  }
1181  (*json_file_) << "]";
1182  }
1183  (*json_file_) << "]";
1184  }
1185  }
1186  (*json_file_) << "]";
1187  is_first_block_ = false;
1188  }
1189 
1190 private:
1192  // Empty dummy vectors
1193  const std::vector<pat::Electron> electron_collection_default;
1194  const std::vector<pat::Muon> muon_collection_default;
1195  const reco::TauDiscriminatorContainer basicTauDiscriminators_default;
1196  const reco::TauDiscriminatorContainer basicTauDiscriminatorsdR03_default;
1198  pfTauTransverseImpactParameters_default;
1199 
1200  const std::vector<pat::Electron>* electron_collection;
1201  const std::vector<pat::Muon>* muon_collection;
1206 
1207  if (!is_online_) {
1208  electron_collection = &event.get(electrons_token_);
1209  muon_collection = &event.get(muons_token_);
1210  pfTauTransverseImpactParameters = &pfTauTransverseImpactParameters_default;
1211  basicTauDiscriminators = &basicTauDiscriminators_default;
1212  basicTauDiscriminatorsdR03 = &basicTauDiscriminatorsdR03_default;
1213  } else {
1214  electron_collection = &electron_collection_default;
1215  muon_collection = &muon_collection_default;
1219 
1220  // Get indices for discriminators
1221  if (!discrIndicesMapped_) {
1226  discrIndicesMapped_ = true;
1227  }
1228  }
1229 
1230  TauFunc tauIDs = {basicTauDiscriminators,
1235 
1237  event.getByToken(pfcandToken_, pfCands);
1238 
1240  event.getByToken(vtxToken_, vertices);
1241 
1243  event.getByToken(rho_token_, rho);
1244 
1245  auto const& eventnr = event.id().event();
1246 
1247  tensorflow::Tensor predictions(tensorflow::DT_FLOAT, {static_cast<int>(taus->size()), deep_tau::NumberOfOutputs});
1248 
1249  for (size_t tau_index = 0; tau_index < taus->size(); ++tau_index) {
1250  const edm::RefToBase<reco::BaseTau> tauRef = taus->refAt(tau_index);
1251 
1252  std::vector<tensorflow::Tensor> pred_vector;
1253 
1254  bool passesPrediscriminants;
1255  if (is_online_) {
1256  passesPrediscriminants = tauIDs.passPrediscriminants<std::vector<TauDiscInfo<reco::PFTauDiscriminator>>>(
1258  } else {
1259  passesPrediscriminants = tauIDs.passPrediscriminants<std::vector<TauDiscInfo<pat::PATTauDiscriminator>>>(
1261  }
1262 
1263  if (passesPrediscriminants) {
1264  if (version_ == 2) {
1265  if (is_online_) {
1266  getPredictionsV2<reco::PFCandidate, reco::PFTau>(taus->at(tau_index),
1267  tau_index,
1268  tauRef,
1269  electron_collection,
1270  muon_collection,
1271  *pfCands,
1272  vertices->at(0),
1273  *rho,
1274  eventnr,
1275  pred_vector,
1276  tauIDs);
1277  } else
1278  getPredictionsV2<pat::PackedCandidate, pat::Tau>(taus->at(tau_index),
1279  tau_index,
1280  tauRef,
1281  electron_collection,
1282  muon_collection,
1283  *pfCands,
1284  vertices->at(0),
1285  *rho,
1286  eventnr,
1287  pred_vector,
1288  tauIDs);
1289  } else {
1290  throw cms::Exception("DeepTauId") << "version " << version_ << " is not supported.";
1291  }
1292 
1293  for (int k = 0; k < deep_tau::NumberOfOutputs; ++k) {
1294  const float pred = pred_vector[0].flat<float>()(k);
1295  if (!(pred >= 0 && pred <= 1))
1296  throw cms::Exception("DeepTauId")
1297  << "invalid prediction = " << pred << " for tau_index = " << tau_index << ", pred_index = " << k;
1298  predictions.matrix<float>()(tau_index, k) = pred;
1299  }
1300  } else {
1301  // This else statement was added as a part of the DeepTau@HLT development. It does not affect the current state
1302  // of offline DeepTauId code as there the preselection is not used (it was added in the DeepTau@HLT). It returns
1303  // default values for deepTau score if the preselection failed. Before this statement the values given for this tau
1304  // were random. k == 2 corresponds to the tau score and all other k values to e, mu and jets. By defining in this way
1305  // the final score is -1.
1306  for (int k = 0; k < deep_tau::NumberOfOutputs; ++k) {
1307  predictions.matrix<float>()(tau_index, k) = (k == 2) ? -1.f : 2.f;
1308  }
1309  }
1310  }
1311  return predictions;
1312  }
1313 
1314  template <typename CandidateCastType, typename TauCastType>
1316  const size_t tau_index,
1317  const edm::RefToBase<reco::BaseTau> tau_ref,
1318  const std::vector<pat::Electron>* electrons,
1319  const std::vector<pat::Muon>* muons,
1320  const edm::View<reco::Candidate>& pfCands,
1321  const reco::Vertex& pv,
1322  double rho,
1323  const edm::EventNumber_t& eventnr,
1324  std::vector<tensorflow::Tensor>& pred_vector,
1325  TauFunc tau_funcs) {
1326  using namespace dnn_inputs_v2;
1327  if (debug_level >= 2) {
1328  std::cout << "<DeepTauId::getPredictionsV2 (moduleLabel = " << moduleDescription().moduleLabel()
1329  << ")>:" << std::endl;
1330  std::cout << " tau: pT = " << tau.pt() << ", eta = " << tau.eta() << ", phi = " << tau.phi()
1331  << ", eventnr = " << eventnr << std::endl;
1332  }
1333  CellGrid inner_grid(number_of_inner_cell, number_of_inner_cell, 0.02, 0.02, disable_CellIndex_workaround_);
1334  CellGrid outer_grid(number_of_outer_cell, number_of_outer_cell, 0.05, 0.05, disable_CellIndex_workaround_);
1335  fillGrids(dynamic_cast<const TauCastType&>(tau), *electrons, inner_grid, outer_grid);
1336  fillGrids(dynamic_cast<const TauCastType&>(tau), *muons, inner_grid, outer_grid);
1337  fillGrids(dynamic_cast<const TauCastType&>(tau), pfCands, inner_grid, outer_grid);
1338 
1339  createTauBlockInputs<CandidateCastType>(
1340  dynamic_cast<const TauCastType&>(tau), tau_index, tau_ref, pv, rho, tau_funcs);
1341  checkInputs(*tauBlockTensor_, "input_tau", static_cast<int>(tauBlockTensor_->shape().dim_size(1)));
1342  createConvFeatures<CandidateCastType>(dynamic_cast<const TauCastType&>(tau),
1343  tau_index,
1344  tau_ref,
1345  pv,
1346  rho,
1347  electrons,
1348  muons,
1349  pfCands,
1350  inner_grid,
1351  tau_funcs,
1352  true);
1353  checkInputs(*eGammaTensor_[true], "input_inner_egamma", EgammaBlockInputs::NumberOfInputs, &inner_grid);
1354  checkInputs(*muonTensor_[true], "input_inner_muon", MuonBlockInputs::NumberOfInputs, &inner_grid);
1355  checkInputs(*hadronsTensor_[true], "input_inner_hadrons", HadronBlockInputs::NumberOfInputs, &inner_grid);
1356  createConvFeatures<CandidateCastType>(dynamic_cast<const TauCastType&>(tau),
1357  tau_index,
1358  tau_ref,
1359  pv,
1360  rho,
1361  electrons,
1362  muons,
1363  pfCands,
1364  outer_grid,
1365  tau_funcs,
1366  false);
1367  checkInputs(*eGammaTensor_[false], "input_outer_egamma", EgammaBlockInputs::NumberOfInputs, &outer_grid);
1368  checkInputs(*muonTensor_[false], "input_outer_muon", MuonBlockInputs::NumberOfInputs, &outer_grid);
1369  checkInputs(*hadronsTensor_[false], "input_outer_hadrons", HadronBlockInputs::NumberOfInputs, &outer_grid);
1370 
1371  if (save_inputs_) {
1372  std::string json_file_name = "DeepTauId_" + std::to_string(eventnr) + "_" + std::to_string(tau_index) + ".json";
1373  json_file_ = new std::ofstream(json_file_name.data());
1374  is_first_block_ = true;
1375  (*json_file_) << "{";
1376  saveInputs(*tauBlockTensor_, "input_tau", static_cast<int>(tauBlockTensor_->shape().dim_size(1)));
1377  saveInputs(
1378  *eGammaTensor_[true], "input_inner_egamma", dnn_inputs_v2::EgammaBlockInputs::NumberOfInputs, &inner_grid);
1379  saveInputs(*muonTensor_[true], "input_inner_muon", dnn_inputs_v2::MuonBlockInputs::NumberOfInputs, &inner_grid);
1380  saveInputs(
1381  *hadronsTensor_[true], "input_inner_hadrons", dnn_inputs_v2::HadronBlockInputs::NumberOfInputs, &inner_grid);
1382  saveInputs(
1383  *eGammaTensor_[false], "input_outer_egamma", dnn_inputs_v2::EgammaBlockInputs::NumberOfInputs, &outer_grid);
1384  saveInputs(*muonTensor_[false], "input_outer_muon", dnn_inputs_v2::MuonBlockInputs::NumberOfInputs, &outer_grid);
1385  saveInputs(
1386  *hadronsTensor_[false], "input_outer_hadrons", dnn_inputs_v2::HadronBlockInputs::NumberOfInputs, &outer_grid);
1387  (*json_file_) << "}";
1388  delete json_file_;
1389  ++file_counter_;
1390  }
1391 
1392  tensorflow::run(&(cache_->getSession("core")),
1393  {{"input_tau", *tauBlockTensor_},
1394  {"input_inner", *convTensor_.at(true)},
1395  {"input_outer", *convTensor_.at(false)}},
1396  {"main_output/Softmax"},
1397  &pred_vector);
1398  if (debug_level >= 1) {
1399  std::cout << "output = { ";
1400  for (int idx = 0; idx < deep_tau::NumberOfOutputs; ++idx) {
1401  if (idx > 0)
1402  std::cout << ", ";
1404  if (idx == 0)
1405  label = "e";
1406  else if (idx == 1)
1407  label = "mu";
1408  else if (idx == 2)
1409  label = "tau";
1410  else if (idx == 3)
1411  label = "jet";
1412  else
1413  assert(0);
1414  std::cout << label << " = " << pred_vector[0].flat<float>()(idx);
1415  }
1416  std::cout << " }" << std::endl;
1417  }
1418  }
1419 
1420  template <typename Collection, typename TauCastType>
1421  void fillGrids(const TauCastType& tau, const Collection& objects, CellGrid& inner_grid, CellGrid& outer_grid) {
1422  static constexpr double outer_dR2 = 0.25; //0.5^2
1423  const double inner_radius = getInnerSignalConeRadius(tau.polarP4().pt());
1424  const double inner_dR2 = std::pow(inner_radius, 2);
1425 
1426  const auto addObject = [&](size_t n, double deta, double dphi, CellGrid& grid) {
1427  const auto& obj = objects.at(n);
1428  const CellObjectType obj_type = GetCellObjectType(obj);
1429  if (obj_type == CellObjectType::Other)
1430  return;
1431  CellIndex cell_index;
1432  if (grid.tryGetCellIndex(deta, dphi, cell_index)) {
1433  Cell& cell = grid[cell_index];
1434  auto iter = cell.find(obj_type);
1435  if (iter != cell.end()) {
1436  const auto& prev_obj = objects.at(iter->second);
1437  if (obj.polarP4().pt() > prev_obj.polarP4().pt())
1438  iter->second = n;
1439  } else {
1440  cell[obj_type] = n;
1441  }
1442  }
1443  };
1444 
1445  for (size_t n = 0; n < objects.size(); ++n) {
1446  const auto& obj = objects.at(n);
1447  const double deta = obj.polarP4().eta() - tau.polarP4().eta();
1448  const double dphi = reco::deltaPhi(obj.polarP4().phi(), tau.polarP4().phi());
1449  const double dR2 = std::pow(deta, 2) + std::pow(dphi, 2);
1450  if (dR2 < inner_dR2)
1451  addObject(n, deta, dphi, inner_grid);
1452  if (dR2 < outer_dR2)
1453  addObject(n, deta, dphi, outer_grid);
1454  }
1455  }
1456 
1457  tensorflow::Tensor getPartialPredictions(bool is_inner) {
1458  std::vector<tensorflow::Tensor> pred_vector;
1459  if (is_inner) {
1460  tensorflow::run(&(cache_->getSession("inner")),
1461  {
1462  {"input_inner_egamma", *eGammaTensor_.at(is_inner)},
1463  {"input_inner_muon", *muonTensor_.at(is_inner)},
1464  {"input_inner_hadrons", *hadronsTensor_.at(is_inner)},
1465  },
1466  {"inner_all_dropout_4/Identity"},
1467  &pred_vector);
1468  } else {
1469  tensorflow::run(&(cache_->getSession("outer")),
1470  {
1471  {"input_outer_egamma", *eGammaTensor_.at(is_inner)},
1472  {"input_outer_muon", *muonTensor_.at(is_inner)},
1473  {"input_outer_hadrons", *hadronsTensor_.at(is_inner)},
1474  },
1475  {"outer_all_dropout_4/Identity"},
1476  &pred_vector);
1477  }
1478  return pred_vector.at(0);
1479  }
1480 
1481  template <typename CandidateCastType, typename TauCastType>
1482  void createConvFeatures(const TauCastType& tau,
1483  const size_t tau_index,
1484  const edm::RefToBase<reco::BaseTau> tau_ref,
1485  const reco::Vertex& pv,
1486  double rho,
1487  const std::vector<pat::Electron>* electrons,
1488  const std::vector<pat::Muon>* muons,
1489  const edm::View<reco::Candidate>& pfCands,
1490  const CellGrid& grid,
1491  TauFunc tau_funcs,
1492  bool is_inner) {
1493  if (debug_level >= 2) {
1494  std::cout << "<DeepTauId::createConvFeatures (is_inner = " << is_inner << ")>:" << std::endl;
1495  }
1496  tensorflow::Tensor& convTensor = *convTensor_.at(is_inner);
1497  eGammaTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
1498  tensorflow::DT_FLOAT,
1499  tensorflow::TensorShape{
1500  (long long int)grid.num_valid_cells(), 1, 1, dnn_inputs_v2::EgammaBlockInputs::NumberOfInputs});
1501  muonTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
1502  tensorflow::DT_FLOAT,
1503  tensorflow::TensorShape{
1504  (long long int)grid.num_valid_cells(), 1, 1, dnn_inputs_v2::MuonBlockInputs::NumberOfInputs});
1505  hadronsTensor_[is_inner] = std::make_unique<tensorflow::Tensor>(
1506  tensorflow::DT_FLOAT,
1507  tensorflow::TensorShape{
1508  (long long int)grid.num_valid_cells(), 1, 1, dnn_inputs_v2::HadronBlockInputs::NumberOfInputs});
1509 
1510  eGammaTensor_[is_inner]->flat<float>().setZero();
1511  muonTensor_[is_inner]->flat<float>().setZero();
1512  hadronsTensor_[is_inner]->flat<float>().setZero();
1513 
1514  unsigned idx = 0;
1515  for (int eta = -grid.maxEtaIndex(); eta <= grid.maxEtaIndex(); ++eta) {
1516  for (int phi = -grid.maxPhiIndex(); phi <= grid.maxPhiIndex(); ++phi) {
1517  if (debug_level >= 2) {
1518  std::cout << "processing ( eta = " << eta << ", phi = " << phi << " )" << std::endl;
1519  }
1520  const CellIndex cell_index{eta, phi};
1521  const auto cell_iter = grid.find(cell_index);
1522  if (cell_iter != grid.end()) {
1523  if (debug_level >= 2) {
1524  std::cout << " creating inputs for ( eta = " << eta << ", phi = " << phi << " ): idx = " << idx
1525  << std::endl;
1526  }
1527  const Cell& cell = cell_iter->second;
1528  createEgammaBlockInputs<CandidateCastType>(
1529  idx, tau, tau_index, tau_ref, pv, rho, electrons, pfCands, cell, tau_funcs, is_inner);
1530  createMuonBlockInputs<CandidateCastType>(
1531  idx, tau, tau_index, tau_ref, pv, rho, muons, pfCands, cell, tau_funcs, is_inner);
1532  createHadronsBlockInputs<CandidateCastType>(
1533  idx, tau, tau_index, tau_ref, pv, rho, pfCands, cell, tau_funcs, is_inner);
1534  idx += 1;
1535  } else {
1536  if (debug_level >= 2) {
1537  std::cout << " skipping creation of inputs, because ( eta = " << eta << ", phi = " << phi
1538  << " ) is not in the grid !!" << std::endl;
1539  }
1540  }
1541  }
1542  }
1543 
1544  const auto predTensor = getPartialPredictions(is_inner);
1545  idx = 0;
1546  for (int eta = -grid.maxEtaIndex(); eta <= grid.maxEtaIndex(); ++eta) {
1547  for (int phi = -grid.maxPhiIndex(); phi <= grid.maxPhiIndex(); ++phi) {
1548  const CellIndex cell_index{eta, phi};
1549  const int eta_index = grid.getEtaTensorIndex(cell_index);
1550  const int phi_index = grid.getPhiTensorIndex(cell_index);
1551 
1552  const auto cell_iter = grid.find(cell_index);
1553  if (cell_iter != grid.end()) {
1554  setCellConvFeatures(convTensor, predTensor, idx, eta_index, phi_index);
1555  idx += 1;
1556  } else {
1557  setCellConvFeatures(convTensor, *zeroOutputTensor_[is_inner], 0, eta_index, phi_index);
1558  }
1559  }
1560  }
1561  }
1562 
1563  void setCellConvFeatures(tensorflow::Tensor& convTensor,
1564  const tensorflow::Tensor& features,
1565  unsigned batch_idx,
1566  int eta_index,
1567  int phi_index) {
1568  for (int n = 0; n < dnn_inputs_v2::number_of_conv_features; ++n) {
1569  convTensor.tensor<float, 4>()(0, eta_index, phi_index, n) = features.tensor<float, 4>()(batch_idx, 0, 0, n);
1570  }
1571  }
1572 
1573  template <typename CandidateCastType, typename TauCastType>
1574  void createTauBlockInputs(const TauCastType& tau,
1575  const size_t& tau_index,
1576  const edm::RefToBase<reco::BaseTau> tau_ref,
1577  const reco::Vertex& pv,
1578  double rho,
1579  TauFunc tau_funcs) {
1580  namespace dnn = dnn_inputs_v2::TauBlockInputs;
1581  namespace sc = deep_tau::Scaling;
1582  sc::FeatureT ft = sc::FeatureT::TauFlat;
1583  const sc::ScalingParams& sp = scalingParamsMap_->at(std::make_pair(ft, false));
1584 
1585  tensorflow::Tensor& inputs = *tauBlockTensor_;
1586  inputs.flat<float>().setZero();
1587 
1588  const auto& get = [&](int var_index) -> float& {
1589  return inputs.matrix<float>()(0, tauInputs_indices_.at(var_index));
1590  };
1591 
1592  auto leadChargedHadrCand = dynamic_cast<const CandidateCastType*>(tau.leadChargedHadrCand().get());
1593 
1594  get(dnn::rho) = sp.scale(rho, tauInputs_indices_[dnn::rho]);
1595  get(dnn::tau_pt) = sp.scale(tau.polarP4().pt(), tauInputs_indices_[dnn::tau_pt]);
1596  get(dnn::tau_eta) = sp.scale(tau.polarP4().eta(), tauInputs_indices_[dnn::tau_eta]);
1597  if (sub_version_ == 1) {
1598  get(dnn::tau_phi) = getValueLinear(tau.polarP4().phi(), -pi, pi, false);
1599  }
1600  get(dnn::tau_mass) = sp.scale(tau.polarP4().mass(), tauInputs_indices_[dnn::tau_mass]);
1601  get(dnn::tau_E_over_pt) = sp.scale(tau.p4().energy() / tau.p4().pt(), tauInputs_indices_[dnn::tau_E_over_pt]);
1602  get(dnn::tau_charge) = sp.scale(tau.charge(), tauInputs_indices_[dnn::tau_charge]);
1603  get(dnn::tau_n_charged_prongs) = sp.scale(tau.decayMode() / 5 + 1, tauInputs_indices_[dnn::tau_n_charged_prongs]);
1604  get(dnn::tau_n_neutral_prongs) = sp.scale(tau.decayMode() % 5, tauInputs_indices_[dnn::tau_n_neutral_prongs]);
1605  get(dnn::chargedIsoPtSum) =
1606  sp.scale(tau_funcs.getChargedIsoPtSum(tau, tau_ref), tauInputs_indices_[dnn::chargedIsoPtSum]);
1607  get(dnn::chargedIsoPtSumdR03_over_dR05) =
1608  sp.scale(tau_funcs.getChargedIsoPtSumdR03(tau, tau_ref) / tau_funcs.getChargedIsoPtSum(tau, tau_ref),
1609  tauInputs_indices_[dnn::chargedIsoPtSumdR03_over_dR05]);
1610  if (sub_version_ == 1)
1611  get(dnn::footprintCorrection) =
1612  sp.scale(tau_funcs.getFootprintCorrectiondR03(tau, tau_ref), tauInputs_indices_[dnn::footprintCorrection]);
1613  else if (sub_version_ == 5)
1614  get(dnn::footprintCorrection) =
1615  sp.scale(tau_funcs.getFootprintCorrection(tau, tau_ref), tauInputs_indices_[dnn::footprintCorrection]);
1616 
1617  get(dnn::neutralIsoPtSum) =
1618  sp.scale(tau_funcs.getNeutralIsoPtSum(tau, tau_ref), tauInputs_indices_[dnn::neutralIsoPtSum]);
1619  get(dnn::neutralIsoPtSumWeight_over_neutralIsoPtSum) =
1620  sp.scale(tau_funcs.getNeutralIsoPtSumWeight(tau, tau_ref) / tau_funcs.getNeutralIsoPtSum(tau, tau_ref),
1621  tauInputs_indices_[dnn::neutralIsoPtSumWeight_over_neutralIsoPtSum]);
1622  get(dnn::neutralIsoPtSumWeightdR03_over_neutralIsoPtSum) =
1623  sp.scale(tau_funcs.getNeutralIsoPtSumdR03Weight(tau, tau_ref) / tau_funcs.getNeutralIsoPtSum(tau, tau_ref),
1624  tauInputs_indices_[dnn::neutralIsoPtSumWeightdR03_over_neutralIsoPtSum]);
1625  get(dnn::neutralIsoPtSumdR03_over_dR05) =
1626  sp.scale(tau_funcs.getNeutralIsoPtSumdR03(tau, tau_ref) / tau_funcs.getNeutralIsoPtSum(tau, tau_ref),
1627  tauInputs_indices_[dnn::neutralIsoPtSumdR03_over_dR05]);
1628  get(dnn::photonPtSumOutsideSignalCone) = sp.scale(tau_funcs.getPhotonPtSumOutsideSignalCone(tau, tau_ref),
1629  tauInputs_indices_[dnn::photonPtSumOutsideSignalCone]);
1630  get(dnn::puCorrPtSum) = sp.scale(tau_funcs.getPuCorrPtSum(tau, tau_ref), tauInputs_indices_[dnn::puCorrPtSum]);
1631  // The global PCA coordinates were used as inputs during the NN training, but it was decided to disable
1632  // them for the inference, because modeling of dxy_PCA in MC poorly describes the data, and x and y coordinates
1633  // in data results outside of the expected 5 std. dev. input validity range. On the other hand,
1634  // these coordinates are strongly era-dependent. Kept as comment to document what NN expects.
1635  if (sub_version_ == 1) {
1636  if (!disable_dxy_pca_) {
1637  auto const pca = tau_funcs.getdxyPCA(tau, tau_index);
1638  get(dnn::tau_dxy_pca_x) = sp.scale(pca.x(), tauInputs_indices_[dnn::tau_dxy_pca_x]);
1639  get(dnn::tau_dxy_pca_y) = sp.scale(pca.y(), tauInputs_indices_[dnn::tau_dxy_pca_y]);
1640  get(dnn::tau_dxy_pca_z) = sp.scale(pca.z(), tauInputs_indices_[dnn::tau_dxy_pca_z]);
1641  } else {
1642  get(dnn::tau_dxy_pca_x) = 0;
1643  get(dnn::tau_dxy_pca_y) = 0;
1644  get(dnn::tau_dxy_pca_z) = 0;
1645  }
1646  }
1647 
1648  const bool tau_dxy_valid =
1649  isAbove(tau_funcs.getdxy(tau, tau_index), -10) && isAbove(tau_funcs.getdxyError(tau, tau_index), 0);
1650  if (tau_dxy_valid) {
1651  get(dnn::tau_dxy_valid) = sp.scale(tau_dxy_valid, tauInputs_indices_[dnn::tau_dxy_valid]);
1652  get(dnn::tau_dxy) = sp.scale(tau_funcs.getdxy(tau, tau_index), tauInputs_indices_[dnn::tau_dxy]);
1653  get(dnn::tau_dxy_sig) =
1654  sp.scale(std::abs(tau_funcs.getdxy(tau, tau_index)) / tau_funcs.getdxyError(tau, tau_index),
1655  tauInputs_indices_[dnn::tau_dxy_sig]);
1656  }
1657  const bool tau_ip3d_valid =
1658  isAbove(tau_funcs.getip3d(tau, tau_index), -10) && isAbove(tau_funcs.getip3dError(tau, tau_index), 0);
1659  if (tau_ip3d_valid) {
1660  get(dnn::tau_ip3d_valid) = sp.scale(tau_ip3d_valid, tauInputs_indices_[dnn::tau_ip3d_valid]);
1661  get(dnn::tau_ip3d) = sp.scale(tau_funcs.getip3d(tau, tau_index), tauInputs_indices_[dnn::tau_ip3d]);
1662  get(dnn::tau_ip3d_sig) =
1663  sp.scale(std::abs(tau_funcs.getip3d(tau, tau_index)) / tau_funcs.getip3dError(tau, tau_index),
1664  tauInputs_indices_[dnn::tau_ip3d_sig]);
1665  }
1666  if (leadChargedHadrCand) {
1667  const bool hasTrackDetails = candFunc::getHasTrackDetails(*leadChargedHadrCand);
1668  const float tau_dz = (is_online_ && !hasTrackDetails) ? 0 : candFunc::getTauDz(*leadChargedHadrCand);
1669  get(dnn::tau_dz) = sp.scale(tau_dz, tauInputs_indices_[dnn::tau_dz]);
1670  get(dnn::tau_dz_sig_valid) =
1671  sp.scale(candFunc::getTauDZSigValid(*leadChargedHadrCand), tauInputs_indices_[dnn::tau_dz_sig_valid]);
1672  const double dzError = hasTrackDetails ? leadChargedHadrCand->dzError() : -999.;
1673  get(dnn::tau_dz_sig) = sp.scale(std::abs(tau_dz) / dzError, tauInputs_indices_[dnn::tau_dz_sig]);
1674  }
1675  get(dnn::tau_flightLength_x) =
1676  sp.scale(tau_funcs.getFlightLength(tau, tau_index).x(), tauInputs_indices_[dnn::tau_flightLength_x]);
1677  get(dnn::tau_flightLength_y) =
1678  sp.scale(tau_funcs.getFlightLength(tau, tau_index).y(), tauInputs_indices_[dnn::tau_flightLength_y]);
1679  get(dnn::tau_flightLength_z) =
1680  sp.scale(tau_funcs.getFlightLength(tau, tau_index).z(), tauInputs_indices_[dnn::tau_flightLength_z]);
1681  if (sub_version_ == 1)
1682  get(dnn::tau_flightLength_sig) = 0.55756444; //This value is set due to a bug in the training
1683  else if (sub_version_ == 5)
1684  get(dnn::tau_flightLength_sig) =
1685  sp.scale(tau_funcs.getFlightLengthSig(tau, tau_index), tauInputs_indices_[dnn::tau_flightLength_sig]);
1686 
1687  get(dnn::tau_pt_weighted_deta_strip) = sp.scale(reco::tau::pt_weighted_deta_strip(tau, tau.decayMode()),
1688  tauInputs_indices_[dnn::tau_pt_weighted_deta_strip]);
1689 
1690  get(dnn::tau_pt_weighted_dphi_strip) = sp.scale(reco::tau::pt_weighted_dphi_strip(tau, tau.decayMode()),
1691  tauInputs_indices_[dnn::tau_pt_weighted_dphi_strip]);
1692  get(dnn::tau_pt_weighted_dr_signal) = sp.scale(reco::tau::pt_weighted_dr_signal(tau, tau.decayMode()),
1693  tauInputs_indices_[dnn::tau_pt_weighted_dr_signal]);
1694  get(dnn::tau_pt_weighted_dr_iso) =
1695  sp.scale(reco::tau::pt_weighted_dr_iso(tau, tau.decayMode()), tauInputs_indices_[dnn::tau_pt_weighted_dr_iso]);
1696  get(dnn::tau_leadingTrackNormChi2) =
1697  sp.scale(tau_funcs.getLeadingTrackNormChi2(tau), tauInputs_indices_[dnn::tau_leadingTrackNormChi2]);
1698  const auto eratio = reco::tau::eratio(tau);
1699  const bool tau_e_ratio_valid = std::isnormal(eratio) && eratio > 0.f;
1700  get(dnn::tau_e_ratio_valid) = sp.scale(tau_e_ratio_valid, tauInputs_indices_[dnn::tau_e_ratio_valid]);
1701  get(dnn::tau_e_ratio) = tau_e_ratio_valid ? sp.scale(eratio, tauInputs_indices_[dnn::tau_e_ratio]) : 0.f;
1702  const double gj_angle_diff = calculateGottfriedJacksonAngleDifference(tau, tau_index, tau_funcs);
1703  const bool tau_gj_angle_diff_valid = (std::isnormal(gj_angle_diff) || gj_angle_diff == 0) && gj_angle_diff >= 0;
1704  get(dnn::tau_gj_angle_diff_valid) =
1705  sp.scale(tau_gj_angle_diff_valid, tauInputs_indices_[dnn::tau_gj_angle_diff_valid]);
1706  get(dnn::tau_gj_angle_diff) =
1707  tau_gj_angle_diff_valid ? sp.scale(gj_angle_diff, tauInputs_indices_[dnn::tau_gj_angle_diff]) : 0;
1708  get(dnn::tau_n_photons) = sp.scale(reco::tau::n_photons_total(tau), tauInputs_indices_[dnn::tau_n_photons]);
1709  get(dnn::tau_emFraction) = sp.scale(tau_funcs.getEmFraction(tau), tauInputs_indices_[dnn::tau_emFraction]);
1710 
1711  get(dnn::tau_inside_ecal_crack) =
1712  sp.scale(isInEcalCrack(tau.p4().eta()), tauInputs_indices_[dnn::tau_inside_ecal_crack]);
1713  get(dnn::leadChargedCand_etaAtEcalEntrance_minus_tau_eta) =
1714  sp.scale(tau_funcs.getEtaAtEcalEntrance(tau) - tau.p4().eta(),
1715  tauInputs_indices_[dnn::leadChargedCand_etaAtEcalEntrance_minus_tau_eta]);
1716  }
1717 
1718  template <typename CandidateCastType, typename TauCastType>
1720  const TauCastType& tau,
1721  const size_t tau_index,
1722  const edm::RefToBase<reco::BaseTau> tau_ref,
1723  const reco::Vertex& pv,
1724  double rho,
1725  const std::vector<pat::Electron>* electrons,
1726  const edm::View<reco::Candidate>& pfCands,
1727  const Cell& cell_map,
1728  TauFunc tau_funcs,
1729  bool is_inner) {
1730  namespace dnn = dnn_inputs_v2::EgammaBlockInputs;
1731  namespace sc = deep_tau::Scaling;
1732  sc::FeatureT ft_global = sc::FeatureT::GridGlobal;
1733  sc::FeatureT ft_PFe = sc::FeatureT::PfCand_electron;
1734  sc::FeatureT ft_PFg = sc::FeatureT::PfCand_gamma;
1736 
1737  // needed to remap indices from scaling vectors to those from dnn_inputs_v2::EgammaBlockInputs
1738  int PFe_index_offset = scalingParamsMap_->at(std::make_pair(ft_global, false)).mean_.size();
1739  int e_index_offset = PFe_index_offset + scalingParamsMap_->at(std::make_pair(ft_PFe, false)).mean_.size();
1740  int PFg_index_offset = e_index_offset + scalingParamsMap_->at(std::make_pair(ft_e, false)).mean_.size();
1741 
1742  // to account for swapped order of PfCand_gamma and Electron blocks for v2p5 training w.r.t. v2p1
1743  int fill_index_offset_e = 0;
1744  int fill_index_offset_PFg = 0;
1745  if (sub_version_ == 5) {
1746  fill_index_offset_e =
1747  scalingParamsMap_->at(std::make_pair(ft_PFg, false)).mean_.size(); // size of PF gamma features
1748  fill_index_offset_PFg =
1749  -scalingParamsMap_->at(std::make_pair(ft_e, false)).mean_.size(); // size of Electron features
1750  }
1751 
1752  tensorflow::Tensor& inputs = *eGammaTensor_.at(is_inner);
1753 
1754  const auto& get = [&](int var_index) -> float& { return inputs.tensor<float, 4>()(idx, 0, 0, var_index); };
1755 
1756  const bool valid_index_pf_ele = cell_map.count(CellObjectType::PfCand_electron);
1757  const bool valid_index_pf_gamma = cell_map.count(CellObjectType::PfCand_gamma);
1758  const bool valid_index_ele = cell_map.count(CellObjectType::Electron);
1759 
1760  if (!cell_map.empty()) {
1761  const sc::ScalingParams& sp = scalingParamsMap_->at(std::make_pair(ft_global, false));
1762  get(dnn::rho) = sp.scale(rho, dnn::rho);
1763  get(dnn::tau_pt) = sp.scale(tau.polarP4().pt(), dnn::tau_pt);
1764  get(dnn::tau_eta) = sp.scale(tau.polarP4().eta(), dnn::tau_eta);
1765  get(dnn::tau_inside_ecal_crack) = sp.scale(isInEcalCrack(tau.polarP4().eta()), dnn::tau_inside_ecal_crack);
1766  }
1767  if (valid_index_pf_ele) {
1768  const sc::ScalingParams& sp = scalingParamsMap_->at(std::make_pair(ft_PFe, is_inner));
1769  size_t index_pf_ele = cell_map.at(CellObjectType::PfCand_electron);
1770  const auto& ele_cand = dynamic_cast<const CandidateCastType&>(pfCands.at(index_pf_ele));
1771 
1772  get(dnn::pfCand_ele_valid) = sp.scale(valid_index_pf_ele, dnn::pfCand_ele_valid - PFe_index_offset);
1773  get(dnn::pfCand_ele_rel_pt) =
1774  sp.scale(ele_cand.polarP4().pt() / tau.polarP4().pt(), dnn::pfCand_ele_rel_pt - PFe_index_offset);
1775  get(dnn::pfCand_ele_deta) =
1776  sp.scale(ele_cand.polarP4().eta() - tau.polarP4().eta(), dnn::pfCand_ele_deta - PFe_index_offset);
1777  get(dnn::pfCand_ele_dphi) =
1778  sp.scale(dPhi(tau.polarP4(), ele_cand.polarP4()), dnn::pfCand_ele_dphi - PFe_index_offset);
1779  get(dnn::pfCand_ele_pvAssociationQuality) = sp.scale<int>(
1780  candFunc::getPvAssocationQuality(ele_cand), dnn::pfCand_ele_pvAssociationQuality - PFe_index_offset);
1781  get(dnn::pfCand_ele_puppiWeight) = is_inner ? sp.scale(candFunc::getPuppiWeight(ele_cand, 0.9906834f),
1782  dnn::pfCand_ele_puppiWeight - PFe_index_offset)
1783  : sp.scale(candFunc::getPuppiWeight(ele_cand, 0.9669586f),
1784  dnn::pfCand_ele_puppiWeight - PFe_index_offset);
1785  get(dnn::pfCand_ele_charge) = sp.scale(ele_cand.charge(), dnn::pfCand_ele_charge - PFe_index_offset);
1786  get(dnn::pfCand_ele_lostInnerHits) =
1787  sp.scale<int>(candFunc::getLostInnerHits(ele_cand, 0), dnn::pfCand_ele_lostInnerHits - PFe_index_offset);
1788  get(dnn::pfCand_ele_numberOfPixelHits) =
1789  sp.scale(candFunc::getNumberOfPixelHits(ele_cand, 0), dnn::pfCand_ele_numberOfPixelHits - PFe_index_offset);
1790  get(dnn::pfCand_ele_vertex_dx) =
1791  sp.scale(ele_cand.vertex().x() - pv.position().x(), dnn::pfCand_ele_vertex_dx - PFe_index_offset);
1792  get(dnn::pfCand_ele_vertex_dy) =
1793  sp.scale(ele_cand.vertex().y() - pv.position().y(), dnn::pfCand_ele_vertex_dy - PFe_index_offset);
1794  get(dnn::pfCand_ele_vertex_dz) =
1795  sp.scale(ele_cand.vertex().z() - pv.position().z(), dnn::pfCand_ele_vertex_dz - PFe_index_offset);
1796  get(dnn::pfCand_ele_vertex_dx_tauFL) =
1797  sp.scale(ele_cand.vertex().x() - pv.position().x() - tau_funcs.getFlightLength(tau, tau_index).x(),
1798  dnn::pfCand_ele_vertex_dx_tauFL - PFe_index_offset);
1799  get(dnn::pfCand_ele_vertex_dy_tauFL) =
1800  sp.scale(ele_cand.vertex().y() - pv.position().y() - tau_funcs.getFlightLength(tau, tau_index).y(),
1801  dnn::pfCand_ele_vertex_dy_tauFL - PFe_index_offset);
1802  get(dnn::pfCand_ele_vertex_dz_tauFL) =
1803  sp.scale(ele_cand.vertex().z() - pv.position().z() - tau_funcs.getFlightLength(tau, tau_index).z(),
1804  dnn::pfCand_ele_vertex_dz_tauFL - PFe_index_offset);
1805 
1806  const bool hasTrackDetails = candFunc::getHasTrackDetails(ele_cand);
1807  if (hasTrackDetails) {
1808  get(dnn::pfCand_ele_hasTrackDetails) =
1809  sp.scale(hasTrackDetails, dnn::pfCand_ele_hasTrackDetails - PFe_index_offset);
1810  get(dnn::pfCand_ele_dxy) = sp.scale(candFunc::getTauDxy(ele_cand), dnn::pfCand_ele_dxy - PFe_index_offset);
1811  get(dnn::pfCand_ele_dxy_sig) = sp.scale(std::abs(candFunc::getTauDxy(ele_cand)) / ele_cand.dxyError(),
1812  dnn::pfCand_ele_dxy_sig - PFe_index_offset);
1813  get(dnn::pfCand_ele_dz) = sp.scale(candFunc::getTauDz(ele_cand), dnn::pfCand_ele_dz - PFe_index_offset);
1814  get(dnn::pfCand_ele_dz_sig) = sp.scale(std::abs(candFunc::getTauDz(ele_cand)) / ele_cand.dzError(),
1815  dnn::pfCand_ele_dz_sig - PFe_index_offset);
1816  get(dnn::pfCand_ele_track_chi2_ndof) =
1817  candFunc::getPseudoTrack(ele_cand).ndof() > 0
1818  ? sp.scale(candFunc::getPseudoTrack(ele_cand).chi2() / candFunc::getPseudoTrack(ele_cand).ndof(),
1819  dnn::pfCand_ele_track_chi2_ndof - PFe_index_offset)
1820  : 0;
1821  get(dnn::pfCand_ele_track_ndof) =
1822  candFunc::getPseudoTrack(ele_cand).ndof() > 0
1823  ? sp.scale(candFunc::getPseudoTrack(ele_cand).ndof(), dnn::pfCand_ele_track_ndof - PFe_index_offset)
1824  : 0;
1825  }
1826  }
1827  if (valid_index_pf_gamma) {
1828  const sc::ScalingParams& sp = scalingParamsMap_->at(std::make_pair(ft_PFg, is_inner));
1829  size_t index_pf_gamma = cell_map.at(CellObjectType::PfCand_gamma);
1830  const auto& gamma_cand = dynamic_cast<const CandidateCastType&>(pfCands.at(index_pf_gamma));
1831 
1832  get(dnn::pfCand_gamma_valid + fill_index_offset_PFg) =
1833  sp.scale(valid_index_pf_gamma, dnn::pfCand_gamma_valid - PFg_index_offset);
1834  get(dnn::pfCand_gamma_rel_pt + fill_index_offset_PFg) =
1835  sp.scale(gamma_cand.polarP4().pt() / tau.polarP4().pt(), dnn::pfCand_gamma_rel_pt - PFg_index_offset);
1836  get(dnn::pfCand_gamma_deta + fill_index_offset_PFg) =
1837  sp.scale(gamma_cand.polarP4().eta() - tau.polarP4().eta(), dnn::pfCand_gamma_deta - PFg_index_offset);
1838  get(dnn::pfCand_gamma_dphi + fill_index_offset_PFg) =
1839  sp.scale(dPhi(tau.polarP4(), gamma_cand.polarP4()), dnn::pfCand_gamma_dphi - PFg_index_offset);
1840  get(dnn::pfCand_gamma_pvAssociationQuality + fill_index_offset_PFg) = sp.scale<int>(
1841  candFunc::getPvAssocationQuality(gamma_cand), dnn::pfCand_gamma_pvAssociationQuality - PFg_index_offset);
1842  get(dnn::pfCand_gamma_fromPV + fill_index_offset_PFg) =
1843  sp.scale<int>(candFunc::getFromPV(gamma_cand), dnn::pfCand_gamma_fromPV - PFg_index_offset);
1844  get(dnn::pfCand_gamma_puppiWeight + fill_index_offset_PFg) =
1845  is_inner ? sp.scale(candFunc::getPuppiWeight(gamma_cand, 0.9084110f),
1846  dnn::pfCand_gamma_puppiWeight - PFg_index_offset)
1847  : sp.scale(candFunc::getPuppiWeight(gamma_cand, 0.4211567f),
1848  dnn::pfCand_gamma_puppiWeight - PFg_index_offset);
1849  get(dnn::pfCand_gamma_puppiWeightNoLep + fill_index_offset_PFg) =
1850  is_inner ? sp.scale(candFunc::getPuppiWeightNoLep(gamma_cand, 0.8857716f),
1851  dnn::pfCand_gamma_puppiWeightNoLep - PFg_index_offset)
1852  : sp.scale(candFunc::getPuppiWeightNoLep(gamma_cand, 0.3822604f),
1853  dnn::pfCand_gamma_puppiWeightNoLep - PFg_index_offset);
1854  get(dnn::pfCand_gamma_lostInnerHits + fill_index_offset_PFg) =
1855  sp.scale<int>(candFunc::getLostInnerHits(gamma_cand, 0), dnn::pfCand_gamma_lostInnerHits - PFg_index_offset);
1856  get(dnn::pfCand_gamma_numberOfPixelHits + fill_index_offset_PFg) = sp.scale(
1857  candFunc::getNumberOfPixelHits(gamma_cand, 0), dnn::pfCand_gamma_numberOfPixelHits - PFg_index_offset);
1858  get(dnn::pfCand_gamma_vertex_dx + fill_index_offset_PFg) =
1859  sp.scale(gamma_cand.vertex().x() - pv.position().x(), dnn::pfCand_gamma_vertex_dx - PFg_index_offset);
1860  get(dnn::pfCand_gamma_vertex_dy + fill_index_offset_PFg) =
1861  sp.scale(gamma_cand.vertex().y() - pv.position().y(), dnn::pfCand_gamma_vertex_dy - PFg_index_offset);
1862  get(dnn::pfCand_gamma_vertex_dz + fill_index_offset_PFg) =
1863  sp.scale(gamma_cand.vertex().z() - pv.position().z(), dnn::pfCand_gamma_vertex_dz - PFg_index_offset);
1864  get(dnn::pfCand_gamma_vertex_dx_tauFL + fill_index_offset_PFg) =
1865  sp.scale(gamma_cand.vertex().x() - pv.position().x() - tau_funcs.getFlightLength(tau, tau_index).x(),
1866  dnn::pfCand_gamma_vertex_dx_tauFL - PFg_index_offset);
1867  get(dnn::pfCand_gamma_vertex_dy_tauFL + fill_index_offset_PFg) =
1868  sp.scale(gamma_cand.vertex().y() - pv.position().y() - tau_funcs.getFlightLength(tau, tau_index).y(),
1869  dnn::pfCand_gamma_vertex_dy_tauFL - PFg_index_offset);
1870  get(dnn::pfCand_gamma_vertex_dz_tauFL + fill_index_offset_PFg) =
1871  sp.scale(gamma_cand.vertex().z() - pv.position().z() - tau_funcs.getFlightLength(tau, tau_index).z(),
1872  dnn::pfCand_gamma_vertex_dz_tauFL - PFg_index_offset);
1873  const bool hasTrackDetails = candFunc::getHasTrackDetails(gamma_cand);
1874  if (hasTrackDetails) {
1875  get(dnn::pfCand_gamma_hasTrackDetails + fill_index_offset_PFg) =
1876  sp.scale(hasTrackDetails, dnn::pfCand_gamma_hasTrackDetails - PFg_index_offset);
1877  get(dnn::pfCand_gamma_dxy + fill_index_offset_PFg) =
1878  sp.scale(candFunc::getTauDxy(gamma_cand), dnn::pfCand_gamma_dxy - PFg_index_offset);
1879  get(dnn::pfCand_gamma_dxy_sig + fill_index_offset_PFg) =
1880  sp.scale(std::abs(candFunc::getTauDxy(gamma_cand)) / gamma_cand.dxyError(),
1881  dnn::pfCand_gamma_dxy_sig - PFg_index_offset);
1882  get(dnn::pfCand_gamma_dz + fill_index_offset_PFg) =
1883  sp.scale(candFunc::getTauDz(gamma_cand), dnn::pfCand_gamma_dz - PFg_index_offset);
1884  get(dnn::pfCand_gamma_dz_sig + fill_index_offset_PFg) =
1885  sp.scale(std::abs(candFunc::getTauDz(gamma_cand)) / gamma_cand.dzError(),
1886  dnn::pfCand_gamma_dz_sig - PFg_index_offset);
1887  get(dnn::pfCand_gamma_track_chi2_ndof + fill_index_offset_PFg) =
1888  candFunc::getPseudoTrack(gamma_cand).ndof() > 0
1889  ? sp.scale(candFunc::getPseudoTrack(gamma_cand).chi2() / candFunc::getPseudoTrack(gamma_cand).ndof(),
1890  dnn::pfCand_gamma_track_chi2_ndof - PFg_index_offset)
1891  : 0;
1892  get(dnn::pfCand_gamma_track_ndof + fill_index_offset_PFg) =
1893  candFunc::getPseudoTrack(gamma_cand).ndof() > 0
1894  ? sp.scale(candFunc::getPseudoTrack(gamma_cand).ndof(), dnn::pfCand_gamma_track_ndof - PFg_index_offset)
1895  : 0;
1896  }
1897  }
1898  if (valid_index_ele) {
1899  const sc::ScalingParams& sp = scalingParamsMap_->at(std::make_pair(ft_e, is_inner));
1900  size_t index_ele = cell_map.at(CellObjectType::Electron);
1901  const auto& ele = electrons->at(index_ele);
1902 
1903  get(dnn::ele_valid + fill_index_offset_e) = sp.scale(valid_index_ele, dnn::ele_valid - e_index_offset);
1904  get(dnn::ele_rel_pt + fill_index_offset_e) =
1905  sp.scale(ele.polarP4().pt() / tau.polarP4().pt(), dnn::ele_rel_pt - e_index_offset);
1906  get(dnn::ele_deta + fill_index_offset_e) =
1907  sp.scale(ele.polarP4().eta() - tau.polarP4().eta(), dnn::ele_deta - e_index_offset);
1908  get(dnn::ele_dphi + fill_index_offset_e) =
1909  sp.scale(dPhi(tau.polarP4(), ele.polarP4()), dnn::ele_dphi - e_index_offset);
1910 
1911  float cc_ele_energy, cc_gamma_energy;
1912  int cc_n_gamma;
1913  const bool cc_valid = calculateElectronClusterVarsV2(ele, cc_ele_energy, cc_gamma_energy, cc_n_gamma);
1914  if (cc_valid) {
1915  get(dnn::ele_cc_valid + fill_index_offset_e) = sp.scale(cc_valid, dnn::ele_cc_valid - e_index_offset);
1916  get(dnn::ele_cc_ele_rel_energy + fill_index_offset_e) =
1917  sp.scale(cc_ele_energy / ele.polarP4().pt(), dnn::ele_cc_ele_rel_energy - e_index_offset);
1918  get(dnn::ele_cc_gamma_rel_energy + fill_index_offset_e) =
1919  sp.scale(cc_gamma_energy / cc_ele_energy, dnn::ele_cc_gamma_rel_energy - e_index_offset);
1920  get(dnn::ele_cc_n_gamma + fill_index_offset_e) = sp.scale(cc_n_gamma, dnn::ele_cc_n_gamma - e_index_offset);
1921  }
1922  get(dnn::ele_rel_trackMomentumAtVtx + fill_index_offset_e) =
1923  sp.scale(ele.trackMomentumAtVtx().R() / ele.polarP4().pt(), dnn::ele_rel_trackMomentumAtVtx - e_index_offset);
1924  get(dnn::ele_rel_trackMomentumAtCalo + fill_index_offset_e) = sp.scale(
1925  ele.trackMomentumAtCalo().R() / ele.polarP4().pt(), dnn::ele_rel_trackMomentumAtCalo - e_index_offset);
1926  get(dnn::ele_rel_trackMomentumOut + fill_index_offset_e) =
1927  sp.scale(ele.trackMomentumOut().R() / ele.polarP4().pt(), dnn::ele_rel_trackMomentumOut - e_index_offset);
1928  get(dnn::ele_rel_trackMomentumAtEleClus + fill_index_offset_e) = sp.scale(
1929  ele.trackMomentumAtEleClus().R() / ele.polarP4().pt(), dnn::ele_rel_trackMomentumAtEleClus - e_index_offset);
1930  get(dnn::ele_rel_trackMomentumAtVtxWithConstraint + fill_index_offset_e) =
1931  sp.scale(ele.trackMomentumAtVtxWithConstraint().R() / ele.polarP4().pt(),
1932  dnn::ele_rel_trackMomentumAtVtxWithConstraint - e_index_offset);
1933  get(dnn::ele_rel_ecalEnergy + fill_index_offset_e) =
1934  sp.scale(ele.ecalEnergy() / ele.polarP4().pt(), dnn::ele_rel_ecalEnergy - e_index_offset);
1935  get(dnn::ele_ecalEnergy_sig + fill_index_offset_e) =
1936  sp.scale(ele.ecalEnergy() / ele.ecalEnergyError(), dnn::ele_ecalEnergy_sig - e_index_offset);
1937  get(dnn::ele_eSuperClusterOverP + fill_index_offset_e) =
1938  sp.scale(ele.eSuperClusterOverP(), dnn::ele_eSuperClusterOverP - e_index_offset);
1939  get(dnn::ele_eSeedClusterOverP + fill_index_offset_e) =
1940  sp.scale(ele.eSeedClusterOverP(), dnn::ele_eSeedClusterOverP - e_index_offset);
1941  get(dnn::ele_eSeedClusterOverPout + fill_index_offset_e) =
1942  sp.scale(ele.eSeedClusterOverPout(), dnn::ele_eSeedClusterOverPout - e_index_offset);
1943  get(dnn::ele_eEleClusterOverPout + fill_index_offset_e) =
1944  sp.scale(ele.eEleClusterOverPout(), dnn::ele_eEleClusterOverPout - e_index_offset);
1945  get(dnn::ele_deltaEtaSuperClusterTrackAtVtx + fill_index_offset_e) =
1946  sp.scale(ele.deltaEtaSuperClusterTrackAtVtx(), dnn::ele_deltaEtaSuperClusterTrackAtVtx - e_index_offset);
1947  get(dnn::ele_deltaEtaSeedClusterTrackAtCalo + fill_index_offset_e) =
1948  sp.scale(ele.deltaEtaSeedClusterTrackAtCalo(), dnn::ele_deltaEtaSeedClusterTrackAtCalo - e_index_offset);
1949  get(dnn::ele_deltaEtaEleClusterTrackAtCalo + fill_index_offset_e) =
1950  sp.scale(ele.deltaEtaEleClusterTrackAtCalo(), dnn::ele_deltaEtaEleClusterTrackAtCalo - e_index_offset);
1951  get(dnn::ele_deltaPhiEleClusterTrackAtCalo + fill_index_offset_e) =
1952  sp.scale(ele.deltaPhiEleClusterTrackAtCalo(), dnn::ele_deltaPhiEleClusterTrackAtCalo - e_index_offset);
1953  get(dnn::ele_deltaPhiSuperClusterTrackAtVtx + fill_index_offset_e) =
1954  sp.scale(ele.deltaPhiSuperClusterTrackAtVtx(), dnn::ele_deltaPhiSuperClusterTrackAtVtx - e_index_offset);
1955  get(dnn::ele_deltaPhiSeedClusterTrackAtCalo + fill_index_offset_e) =
1956  sp.scale(ele.deltaPhiSeedClusterTrackAtCalo(), dnn::ele_deltaPhiSeedClusterTrackAtCalo - e_index_offset);
1957  const bool mva_valid =
1958  (ele.mvaInput().earlyBrem > -2) ||
1959  (year_ !=
1960  2026); // Known issue that input can be invalid in Phase2 samples (early/lateBrem==-2, hadEnergy==0, sigmaEtaEta/deltaEta==3.40282e+38). Unknown if also in Run2/3, so don't change there
1961  if (mva_valid) {
1962  get(dnn::ele_mvaInput_earlyBrem + fill_index_offset_e) =
1963  sp.scale(ele.mvaInput().earlyBrem, dnn::ele_mvaInput_earlyBrem - e_index_offset);
1964  get(dnn::ele_mvaInput_lateBrem + fill_index_offset_e) =
1965  sp.scale(ele.mvaInput().lateBrem, dnn::ele_mvaInput_lateBrem - e_index_offset);
1966  get(dnn::ele_mvaInput_sigmaEtaEta + fill_index_offset_e) =
1967  sp.scale(ele.mvaInput().sigmaEtaEta, dnn::ele_mvaInput_sigmaEtaEta - e_index_offset);
1968  get(dnn::ele_mvaInput_hadEnergy + fill_index_offset_e) =
1969  sp.scale(ele.mvaInput().hadEnergy, dnn::ele_mvaInput_hadEnergy - e_index_offset);
1970  get(dnn::ele_mvaInput_deltaEta + fill_index_offset_e) =
1971  sp.scale(ele.mvaInput().deltaEta, dnn::ele_mvaInput_deltaEta - e_index_offset);
1972  }
1973  const auto& gsfTrack = ele.gsfTrack();
1974  if (gsfTrack.isNonnull()) {
1975  get(dnn::ele_gsfTrack_normalizedChi2 + fill_index_offset_e) =
1976  sp.scale(gsfTrack->normalizedChi2(), dnn::ele_gsfTrack_normalizedChi2 - e_index_offset);
1977  get(dnn::ele_gsfTrack_numberOfValidHits + fill_index_offset_e) =
1978  sp.scale(gsfTrack->numberOfValidHits(), dnn::ele_gsfTrack_numberOfValidHits - e_index_offset);
1979  get(dnn::ele_rel_gsfTrack_pt + fill_index_offset_e) =
1980  sp.scale(gsfTrack->pt() / ele.polarP4().pt(), dnn::ele_rel_gsfTrack_pt - e_index_offset);
1981  get(dnn::ele_gsfTrack_pt_sig + fill_index_offset_e) =
1982  sp.scale(gsfTrack->pt() / gsfTrack->ptError(), dnn::ele_gsfTrack_pt_sig - e_index_offset);
1983  }
1984  const auto& closestCtfTrack = ele.closestCtfTrackRef();
1985  const bool has_closestCtfTrack = closestCtfTrack.isNonnull();
1986  if (has_closestCtfTrack) {
1987  get(dnn::ele_has_closestCtfTrack + fill_index_offset_e) =
1988  sp.scale(has_closestCtfTrack, dnn::ele_has_closestCtfTrack - e_index_offset);
1989  get(dnn::ele_closestCtfTrack_normalizedChi2 + fill_index_offset_e) =
1990  sp.scale(closestCtfTrack->normalizedChi2(), dnn::ele_closestCtfTrack_normalizedChi2 - e_index_offset);
1991  get(dnn::ele_closestCtfTrack_numberOfValidHits + fill_index_offset_e) =
1992  sp.scale(closestCtfTrack->numberOfValidHits(), dnn::ele_closestCtfTrack_numberOfValidHits - e_index_offset);
1993  }
1994  }
1995  }
1996 
1997  template <typename CandidateCastType, typename TauCastType>
1999  const TauCastType& tau,
2000  const size_t tau_index,
2001  const edm::RefToBase<reco::BaseTau> tau_ref,
2002  const reco::Vertex& pv,
2003  double rho,
2004  const std::vector<pat::Muon>* muons,
2005  const edm::View<reco::Candidate>& pfCands,
2006  const Cell& cell_map,
2007  TauFunc tau_funcs,
2008  bool is_inner) {
2009  namespace dnn = dnn_inputs_v2::MuonBlockInputs;
2010  namespace sc = deep_tau::Scaling;
2011  sc::FeatureT ft_global = sc::FeatureT::GridGlobal;
2012  sc::FeatureT ft_PFmu = sc::FeatureT::PfCand_muon;
2014 
2015  // needed to remap indices from scaling vectors to those from dnn_inputs_v2::MuonBlockInputs
2016  int PFmu_index_offset = scalingParamsMap_->at(std::make_pair(ft_global, false)).mean_.size();
2017  int mu_index_offset = PFmu_index_offset + scalingParamsMap_->at(std::make_pair(ft_PFmu, false)).mean_.size();
2018 
2019  tensorflow::Tensor& inputs = *muonTensor_.at(is_inner);
2020 
2021  const auto& get = [&](int var_index) -> float& { return inputs.tensor<float, 4>()(idx, 0, 0, var_index); };
2022 
2023  const bool valid_index_pf_muon = cell_map.count(CellObjectType::PfCand_muon);
2024  const bool valid_index_muon = cell_map.count(CellObjectType::Muon);
2025 
2026  if (!cell_map.empty()) {
2027  const sc::ScalingParams& sp = scalingParamsMap_->at(std::make_pair(ft_global, false));
2028  get(dnn::rho) = sp.scale(rho, dnn::rho);
2029  get(dnn::tau_pt) = sp.scale(tau.polarP4().pt(), dnn::tau_pt);
2030  get(dnn::tau_eta) = sp.scale(tau.polarP4().eta(), dnn::tau_eta);
2031  get(dnn::tau_inside_ecal_crack) = sp.scale(isInEcalCrack(tau.polarP4().eta()), dnn::tau_inside_ecal_crack);
2032  }
2033  if (valid_index_pf_muon) {
2034  const sc::ScalingParams& sp = scalingParamsMap_->at(std::make_pair(ft_PFmu, is_inner));
2035  size_t index_pf_muon = cell_map.at(CellObjectType::PfCand_muon);
2036  const auto& muon_cand = dynamic_cast<const CandidateCastType&>(pfCands.at(index_pf_muon));
2037 
2038  get(dnn::pfCand_muon_valid) = sp.scale(valid_index_pf_muon, dnn::pfCand_muon_valid - PFmu_index_offset);
2039  get(dnn::pfCand_muon_rel_pt) =
2040  sp.scale(muon_cand.polarP4().pt() / tau.polarP4().pt(), dnn::pfCand_muon_rel_pt - PFmu_index_offset);
2041  get(dnn::pfCand_muon_deta) =
2042  sp.scale(muon_cand.polarP4().eta() - tau.polarP4().eta(), dnn::pfCand_muon_deta - PFmu_index_offset);
2043  get(dnn::pfCand_muon_dphi) =
2044  sp.scale(dPhi(tau.polarP4(), muon_cand.polarP4()), dnn::pfCand_muon_dphi - PFmu_index_offset);
2045  get(dnn::pfCand_muon_pvAssociationQuality) = sp.scale<int>(
2046  candFunc::getPvAssocationQuality(muon_cand), dnn::pfCand_muon_pvAssociationQuality - PFmu_index_offset);
2047  get(dnn::pfCand_muon_fromPV) =
2048  sp.scale<int>(candFunc::getFromPV(muon_cand), dnn::pfCand_muon_fromPV - PFmu_index_offset);
2049  get(dnn::pfCand_muon_puppiWeight) = is_inner ? sp.scale(candFunc::getPuppiWeight(muon_cand, 0.9786588f),
2050  dnn::pfCand_muon_puppiWeight - PFmu_index_offset)
2051  : sp.scale(candFunc::getPuppiWeight(muon_cand, 0.8132477f),
2052  dnn::pfCand_muon_puppiWeight - PFmu_index_offset);
2053  get(dnn::pfCand_muon_charge) = sp.scale(muon_cand.charge(), dnn::pfCand_muon_charge - PFmu_index_offset);
2054  get(dnn::pfCand_muon_lostInnerHits) =
2055  sp.scale<int>(candFunc::getLostInnerHits(muon_cand, 0), dnn::pfCand_muon_lostInnerHits - PFmu_index_offset);
2056  get(dnn::pfCand_muon_numberOfPixelHits) = sp.scale(candFunc::getNumberOfPixelHits(muon_cand, 0),
2057  dnn::pfCand_muon_numberOfPixelHits - PFmu_index_offset);
2058  get(dnn::pfCand_muon_vertex_dx) =
2059  sp.scale(muon_cand.vertex().x() - pv.position().x(), dnn::pfCand_muon_vertex_dx - PFmu_index_offset);
2060  get(dnn::pfCand_muon_vertex_dy) =
2061  sp.scale(muon_cand.vertex().y() - pv.position().y(), dnn::pfCand_muon_vertex_dy - PFmu_index_offset);
2062  get(dnn::pfCand_muon_vertex_dz) =
2063  sp.scale(muon_cand.vertex().z() - pv.position().z(), dnn::pfCand_muon_vertex_dz - PFmu_index_offset);
2064  get(dnn::pfCand_muon_vertex_dx_tauFL) =
2065  sp.scale(muon_cand.vertex().x() - pv.position().x() - tau_funcs.getFlightLength(tau, tau_index).x(),
2066  dnn::pfCand_muon_vertex_dx_tauFL - PFmu_index_offset);
2067  get(dnn::pfCand_muon_vertex_dy_tauFL) =
2068  sp.scale(muon_cand.vertex().y() - pv.position().y() - tau_funcs.getFlightLength(tau, tau_index).y(),
2069  dnn::pfCand_muon_vertex_dy_tauFL - PFmu_index_offset);
2070  get(dnn::pfCand_muon_vertex_dz_tauFL) =
2071  sp.scale(muon_cand.vertex().z() - pv.position().z() - tau_funcs.getFlightLength(tau, tau_index).z(),
2072  dnn::pfCand_muon_vertex_dz_tauFL - PFmu_index_offset);
2073 
2074  const bool hasTrackDetails = candFunc::getHasTrackDetails(muon_cand);
2075  if (hasTrackDetails) {
2076  get(dnn::pfCand_muon_hasTrackDetails) =
2077  sp.scale(hasTrackDetails, dnn::pfCand_muon_hasTrackDetails - PFmu_index_offset);
2078  get(dnn::pfCand_muon_dxy) = sp.scale(candFunc::getTauDxy(muon_cand), dnn::pfCand_muon_dxy - PFmu_index_offset);
2079  get(dnn::pfCand_muon_dxy_sig) = sp.scale(std::abs(candFunc::getTauDxy(muon_cand)) / muon_cand.dxyError(),
2080  dnn::pfCand_muon_dxy_sig - PFmu_index_offset);
2081  get(dnn::pfCand_muon_dz) = sp.scale(candFunc::getTauDz(muon_cand), dnn::pfCand_muon_dz - PFmu_index_offset);
2082  get(dnn::pfCand_muon_dz_sig) = sp.scale(std::abs(candFunc::getTauDz(muon_cand)) / muon_cand.dzError(),
2083  dnn::pfCand_muon_dz_sig - PFmu_index_offset);
2084  get(dnn::pfCand_muon_track_chi2_ndof) =
2085  candFunc::getPseudoTrack(muon_cand).ndof() > 0
2086  ? sp.scale(candFunc::getPseudoTrack(muon_cand).chi2() / candFunc::getPseudoTrack(muon_cand).ndof(),
2087  dnn::pfCand_muon_track_chi2_ndof - PFmu_index_offset)
2088  : 0;
2089  get(dnn::pfCand_muon_track_ndof) =
2090  candFunc::getPseudoTrack(muon_cand).ndof() > 0
2091  ? sp.scale(candFunc::getPseudoTrack(muon_cand).ndof(), dnn::pfCand_muon_track_ndof - PFmu_index_offset)
2092  : 0;
2093  }
2094  }
2095  if (valid_index_muon) {
2096  const sc::ScalingParams& sp = scalingParamsMap_->at(std::make_pair(ft_mu, is_inner));
2097  size_t index_muon = cell_map.at(CellObjectType::Muon);
2098  const auto& muon = muons->at(index_muon);
2099 
2100  get(dnn::muon_valid) = sp.scale(valid_index_muon, dnn::muon_valid - mu_index_offset);
2101  get(dnn::muon_rel_pt) = sp.scale(muon.polarP4().pt() / tau.polarP4().pt(), dnn::muon_rel_pt - mu_index_offset);
2102  get(dnn::muon_deta) = sp.scale(muon.polarP4().eta() - tau.polarP4().eta(), dnn::muon_deta - mu_index_offset);
2103  get(dnn::muon_dphi) = sp.scale(dPhi(tau.polarP4(), muon.polarP4()), dnn::muon_dphi - mu_index_offset);
2104  get(dnn::muon_dxy) = sp.scale(muon.dB(pat::Muon::PV2D), dnn::muon_dxy - mu_index_offset);
2105  get(dnn::muon_dxy_sig) =
2106  sp.scale(std::abs(muon.dB(pat::Muon::PV2D)) / muon.edB(pat::Muon::PV2D), dnn::muon_dxy_sig - mu_index_offset);
2107 
2108  const bool normalizedChi2_valid = muon.globalTrack().isNonnull() && muon.normChi2() >= 0;
2109  if (normalizedChi2_valid) {
2110  get(dnn::muon_normalizedChi2_valid) =
2111  sp.scale(normalizedChi2_valid, dnn::muon_normalizedChi2_valid - mu_index_offset);
2112  get(dnn::muon_normalizedChi2) = sp.scale(muon.normChi2(), dnn::muon_normalizedChi2 - mu_index_offset);
2113  if (muon.innerTrack().isNonnull())
2114  get(dnn::muon_numberOfValidHits) =
2115  sp.scale(muon.numberOfValidHits(), dnn::muon_numberOfValidHits - mu_index_offset);
2116  }
2117  get(dnn::muon_segmentCompatibility) =
2118  sp.scale(muon.segmentCompatibility(), dnn::muon_segmentCompatibility - mu_index_offset);
2119  get(dnn::muon_caloCompatibility) =
2120  sp.scale(muon.caloCompatibility(), dnn::muon_caloCompatibility - mu_index_offset);
2121 
2122  const bool pfEcalEnergy_valid = muon.pfEcalEnergy() >= 0;
2123  if (pfEcalEnergy_valid) {
2124  get(dnn::muon_pfEcalEnergy_valid) =
2125  sp.scale(pfEcalEnergy_valid, dnn::muon_pfEcalEnergy_valid - mu_index_offset);
2126  get(dnn::muon_rel_pfEcalEnergy) =
2127  sp.scale(muon.pfEcalEnergy() / muon.polarP4().pt(), dnn::muon_rel_pfEcalEnergy - mu_index_offset);
2128  }
2129 
2130  MuonHitMatchV2 hit_match(muon);
2131  static const std::map<int, std::pair<int, int>> muonMatchHitVars = {
2132  {MuonSubdetId::DT, {dnn::muon_n_matches_DT_1, dnn::muon_n_hits_DT_1}},
2133  {MuonSubdetId::CSC, {dnn::muon_n_matches_CSC_1, dnn::muon_n_hits_CSC_1}},
2134  {MuonSubdetId::RPC, {dnn::muon_n_matches_RPC_1, dnn::muon_n_hits_RPC_1}}};
2135 
2136  for (int subdet : hit_match.MuonHitMatchV2::consideredSubdets()) {
2137  const auto& matchHitVar = muonMatchHitVars.at(subdet);
2138  for (int station = MuonHitMatchV2::first_station_id; station <= MuonHitMatchV2::last_station_id; ++station) {
2139  const unsigned n_matches = hit_match.nMatches(subdet, station);
2140  const unsigned n_hits = hit_match.nHits(subdet, station);
2141  get(matchHitVar.first + station - 1) = sp.scale(n_matches, matchHitVar.first + station - 1 - mu_index_offset);
2142  get(matchHitVar.second + station - 1) = sp.scale(n_hits, matchHitVar.second + station - 1 - mu_index_offset);
2143  }
2144  }
2145  }
2146  }
2147 
2148  template <typename CandidateCastType, typename TauCastType>
2150  const TauCastType& tau,
2151  const size_t tau_index,
2152  const edm::RefToBase<reco::BaseTau> tau_ref,
2153  const reco::Vertex& pv,
2154  double rho,
2155  const edm::View<reco::Candidate>& pfCands,
2156  const Cell& cell_map,
2157  TauFunc tau_funcs,
2158  bool is_inner) {
2159  namespace dnn = dnn_inputs_v2::HadronBlockInputs;
2160  namespace sc = deep_tau::Scaling;
2161  sc::FeatureT ft_global = sc::FeatureT::GridGlobal;
2162  sc::FeatureT ft_PFchH = sc::FeatureT::PfCand_chHad;
2163  sc::FeatureT ft_PFnH = sc::FeatureT::PfCand_nHad;
2164 
2165  // needed to remap indices from scaling vectors to those from dnn_inputs_v2::HadronBlockInputs
2166  int PFchH_index_offset = scalingParamsMap_->at(std::make_pair(ft_global, false)).mean_.size();
2167  int PFnH_index_offset = PFchH_index_offset + scalingParamsMap_->at(std::make_pair(ft_PFchH, false)).mean_.size();
2168 
2169  tensorflow::Tensor& inputs = *hadronsTensor_.at(is_inner);
2170 
2171  const auto& get = [&](int var_index) -> float& { return inputs.tensor<float, 4>()(idx, 0, 0, var_index); };
2172 
2173  const bool valid_chH = cell_map.count(CellObjectType::PfCand_chargedHadron);
2174  const bool valid_nH = cell_map.count(CellObjectType::PfCand_neutralHadron);
2175 
2176  if (!cell_map.empty()) {
2177  const sc::ScalingParams& sp = scalingParamsMap_->at(std::make_pair(ft_global, false));
2178  get(dnn::rho) = sp.scale(rho, dnn::rho);
2179  get(dnn::tau_pt) = sp.scale(tau.polarP4().pt(), dnn::tau_pt);
2180  get(dnn::tau_eta) = sp.scale(tau.polarP4().eta(), dnn::tau_eta);
2181  get(dnn::tau_inside_ecal_crack) = sp.scale(isInEcalCrack(tau.polarP4().eta()), dnn::tau_inside_ecal_crack);
2182  }
2183  if (valid_chH) {
2184  const sc::ScalingParams& sp = scalingParamsMap_->at(std::make_pair(ft_PFchH, is_inner));
2185  size_t index_chH = cell_map.at(CellObjectType::PfCand_chargedHadron);
2186  const auto& chH_cand = dynamic_cast<const CandidateCastType&>(pfCands.at(index_chH));
2187 
2188  get(dnn::pfCand_chHad_valid) = sp.scale(valid_chH, dnn::pfCand_chHad_valid - PFchH_index_offset);
2189  get(dnn::pfCand_chHad_rel_pt) =
2190  sp.scale(chH_cand.polarP4().pt() / tau.polarP4().pt(), dnn::pfCand_chHad_rel_pt - PFchH_index_offset);
2191  get(dnn::pfCand_chHad_deta) =
2192  sp.scale(chH_cand.polarP4().eta() - tau.polarP4().eta(), dnn::pfCand_chHad_deta - PFchH_index_offset);
2193  get(dnn::pfCand_chHad_dphi) =
2194  sp.scale(dPhi(tau.polarP4(), chH_cand.polarP4()), dnn::pfCand_chHad_dphi - PFchH_index_offset);
2195  get(dnn::pfCand_chHad_leadChargedHadrCand) =
2196  sp.scale(&chH_cand == dynamic_cast<const CandidateCastType*>(tau.leadChargedHadrCand().get()),
2197  dnn::pfCand_chHad_leadChargedHadrCand - PFchH_index_offset);
2198  get(dnn::pfCand_chHad_pvAssociationQuality) = sp.scale<int>(
2199  candFunc::getPvAssocationQuality(chH_cand), dnn::pfCand_chHad_pvAssociationQuality - PFchH_index_offset);
2200  get(dnn::pfCand_chHad_fromPV) =
2201  sp.scale<int>(candFunc::getFromPV(chH_cand), dnn::pfCand_chHad_fromPV - PFchH_index_offset);
2202  const float default_chH_pw_inner = 0.7614090f;
2203  const float default_chH_pw_outer = 0.1974930f;
2204  get(dnn::pfCand_chHad_puppiWeight) = is_inner ? sp.scale(candFunc::getPuppiWeight(chH_cand, default_chH_pw_inner),
2205  dnn::pfCand_chHad_puppiWeight - PFchH_index_offset)
2206  : sp.scale(candFunc::getPuppiWeight(chH_cand, default_chH_pw_outer),
2207  dnn::pfCand_chHad_puppiWeight - PFchH_index_offset);
2208  get(dnn::pfCand_chHad_puppiWeightNoLep) =
2209  is_inner ? sp.scale(candFunc::getPuppiWeightNoLep(chH_cand, default_chH_pw_inner),
2210  dnn::pfCand_chHad_puppiWeightNoLep - PFchH_index_offset)
2211  : sp.scale(candFunc::getPuppiWeightNoLep(chH_cand, default_chH_pw_outer),
2212  dnn::pfCand_chHad_puppiWeightNoLep - PFchH_index_offset);
2213  get(dnn::pfCand_chHad_charge) = sp.scale(chH_cand.charge(), dnn::pfCand_chHad_charge - PFchH_index_offset);
2214  get(dnn::pfCand_chHad_lostInnerHits) =
2215  sp.scale<int>(candFunc::getLostInnerHits(chH_cand, 0), dnn::pfCand_chHad_lostInnerHits - PFchH_index_offset);
2216  get(dnn::pfCand_chHad_numberOfPixelHits) = sp.scale(candFunc::getNumberOfPixelHits(chH_cand, 0),
2217  dnn::pfCand_chHad_numberOfPixelHits - PFchH_index_offset);
2218  get(dnn::pfCand_chHad_vertex_dx) =
2219  sp.scale(chH_cand.vertex().x() - pv.position().x(), dnn::pfCand_chHad_vertex_dx - PFchH_index_offset);
2220  get(dnn::pfCand_chHad_vertex_dy) =
2221  sp.scale(chH_cand.vertex().y() - pv.position().y(), dnn::pfCand_chHad_vertex_dy - PFchH_index_offset);
2222  get(dnn::pfCand_chHad_vertex_dz) =
2223  sp.scale(chH_cand.vertex().z() - pv.position().z(), dnn::pfCand_chHad_vertex_dz - PFchH_index_offset);
2224  get(dnn::pfCand_chHad_vertex_dx_tauFL) =
2225  sp.scale(chH_cand.vertex().x() - pv.position().x() - tau_funcs.getFlightLength(tau, tau_index).x(),
2226  dnn::pfCand_chHad_vertex_dx_tauFL - PFchH_index_offset);
2227  get(dnn::pfCand_chHad_vertex_dy_tauFL) =
2228  sp.scale(chH_cand.vertex().y() - pv.position().y() - tau_funcs.getFlightLength(tau, tau_index).y(),
2229  dnn::pfCand_chHad_vertex_dy_tauFL - PFchH_index_offset);
2230  get(dnn::pfCand_chHad_vertex_dz_tauFL) =
2231  sp.scale(chH_cand.vertex().z() - pv.position().z() - tau_funcs.getFlightLength(tau, tau_index).z(),
2232  dnn::pfCand_chHad_vertex_dz_tauFL - PFchH_index_offset);
2233 
2234  const bool hasTrackDetails = candFunc::getHasTrackDetails(chH_cand);
2235  if (hasTrackDetails) {
2236  get(dnn::pfCand_chHad_hasTrackDetails) =
2237  sp.scale(hasTrackDetails, dnn::pfCand_chHad_hasTrackDetails - PFchH_index_offset);
2238  get(dnn::pfCand_chHad_dxy) =
2239  sp.scale(candFunc::getTauDxy(chH_cand), dnn::pfCand_chHad_dxy - PFchH_index_offset);
2240  get(dnn::pfCand_chHad_dxy_sig) = sp.scale(std::abs(candFunc::getTauDxy(chH_cand)) / chH_cand.dxyError(),
2241  dnn::pfCand_chHad_dxy_sig - PFchH_index_offset);
2242  get(dnn::pfCand_chHad_dz) = sp.scale(candFunc::getTauDz(chH_cand), dnn::pfCand_chHad_dz - PFchH_index_offset);
2243  get(dnn::pfCand_chHad_dz_sig) = sp.scale(std::abs(candFunc::getTauDz(chH_cand)) / chH_cand.dzError(),
2244  dnn::pfCand_chHad_dz_sig - PFchH_index_offset);
2245  get(dnn::pfCand_chHad_track_chi2_ndof) =
2246  candFunc::getPseudoTrack(chH_cand).ndof() > 0
2247  ? sp.scale(candFunc::getPseudoTrack(chH_cand).chi2() / candFunc::getPseudoTrack(chH_cand).ndof(),
2248  dnn::pfCand_chHad_track_chi2_ndof - PFchH_index_offset)
2249  : 0;
2250  get(dnn::pfCand_chHad_track_ndof) =
2251  candFunc::getPseudoTrack(chH_cand).ndof() > 0
2252  ? sp.scale(candFunc::getPseudoTrack(chH_cand).ndof(), dnn::pfCand_chHad_track_ndof - PFchH_index_offset)
2253  : 0;
2254  }
2255  float hcal_fraction = candFunc::getHCalFraction(chH_cand, disable_hcalFraction_workaround_);
2256  get(dnn::pfCand_chHad_hcalFraction) =
2257  sp.scale(hcal_fraction, dnn::pfCand_chHad_hcalFraction - PFchH_index_offset);
2258  get(dnn::pfCand_chHad_rawCaloFraction) =
2259  sp.scale(candFunc::getRawCaloFraction(chH_cand), dnn::pfCand_chHad_rawCaloFraction - PFchH_index_offset);
2260  }
2261  if (valid_nH) {
2262  const sc::ScalingParams& sp = scalingParamsMap_->at(std::make_pair(ft_PFnH, is_inner));
2263  size_t index_nH = cell_map.at(CellObjectType::PfCand_neutralHadron);
2264  const auto& nH_cand = dynamic_cast<const CandidateCastType&>(pfCands.at(index_nH));
2265 
2266  get(dnn::pfCand_nHad_valid) = sp.scale(valid_nH, dnn::pfCand_nHad_valid - PFnH_index_offset);
2267  get(dnn::pfCand_nHad_rel_pt) =
2268  sp.scale(nH_cand.polarP4().pt() / tau.polarP4().pt(), dnn::pfCand_nHad_rel_pt - PFnH_index_offset);
2269  get(dnn::pfCand_nHad_deta) =
2270  sp.scale(nH_cand.polarP4().eta() - tau.polarP4().eta(), dnn::pfCand_nHad_deta - PFnH_index_offset);
2271  get(dnn::pfCand_nHad_dphi) =
2272  sp.scale(dPhi(tau.polarP4(), nH_cand.polarP4()), dnn::pfCand_nHad_dphi - PFnH_index_offset);
2273  get(dnn::pfCand_nHad_puppiWeight) = is_inner ? sp.scale(candFunc::getPuppiWeight(nH_cand, 0.9798355f),
2274  dnn::pfCand_nHad_puppiWeight - PFnH_index_offset)
2275  : sp.scale(candFunc::getPuppiWeight(nH_cand, 0.7813260f),
2276  dnn::pfCand_nHad_puppiWeight - PFnH_index_offset);
2277  get(dnn::pfCand_nHad_puppiWeightNoLep) = is_inner
2278  ? sp.scale(candFunc::getPuppiWeightNoLep(nH_cand, 0.9046796f),
2279  dnn::pfCand_nHad_puppiWeightNoLep - PFnH_index_offset)
2280  : sp.scale(candFunc::getPuppiWeightNoLep(nH_cand, 0.6554860f),
2281  dnn::pfCand_nHad_puppiWeightNoLep - PFnH_index_offset);
2282  float hcal_fraction = candFunc::getHCalFraction(nH_cand, disable_hcalFraction_workaround_);
2283  get(dnn::pfCand_nHad_hcalFraction) = sp.scale(hcal_fraction, dnn::pfCand_nHad_hcalFraction - PFnH_index_offset);
2284  }
2285  }
2286 
2287  static void calculateElectronClusterVars(const pat::Electron* ele, float& elecEe, float& elecEgamma) {
2288  if (ele) {
2289  elecEe = elecEgamma = 0;
2290  auto superCluster = ele->superCluster();
2291  if (superCluster.isNonnull() && superCluster.isAvailable() && superCluster->clusters().isNonnull() &&
2292  superCluster->clusters().isAvailable()) {
2293  for (auto iter = superCluster->clustersBegin(); iter != superCluster->clustersEnd(); ++iter) {
2294  const double energy = (*iter)->energy();
2295  if (iter == superCluster->clustersBegin())
2296  elecEe += energy;
2297  else
2298  elecEgamma += energy;
2299  }
2300  }
2301  } else {
2302  elecEe = elecEgamma = default_value;
2303  }
2304  }
2305 
2306  template <typename CandidateCollection, typename TauCastType>
2307  static void processSignalPFComponents(const TauCastType& tau,
2309  LorentzVectorXYZ& p4_inner,
2310  LorentzVectorXYZ& p4_outer,
2311  float& pt_inner,
2312  float& dEta_inner,
2313  float& dPhi_inner,
2314  float& m_inner,
2315  float& pt_outer,
2316  float& dEta_outer,
2317  float& dPhi_outer,
2318  float& m_outer,
2319  float& n_inner,
2320  float& n_outer) {
2321  p4_inner = LorentzVectorXYZ(0, 0, 0, 0);
2322  p4_outer = LorentzVectorXYZ(0, 0, 0, 0);
2323  n_inner = 0;
2324  n_outer = 0;
2325 
2326  const double innerSigCone_radius = getInnerSignalConeRadius(tau.pt());
2327  for (const auto& cand : candidates) {
2328  const double dR = reco::deltaR(cand->p4(), tau.leadChargedHadrCand()->p4());
2329  const bool isInside_innerSigCone = dR < innerSigCone_radius;
2330  if (isInside_innerSigCone) {
2331  p4_inner += cand->p4();
2332  ++n_inner;
2333  } else {
2334  p4_outer += cand->p4();
2335  ++n_outer;
2336  }
2337  }
2338 
2339  pt_inner = n_inner != 0 ? p4_inner.Pt() : default_value;
2340  dEta_inner = n_inner != 0 ? dEta(p4_inner, tau.p4()) : default_value;
2341  dPhi_inner = n_inner != 0 ? dPhi(p4_inner, tau.p4()) : default_value;
2342  m_inner = n_inner != 0 ? p4_inner.mass() : default_value;
2343 
2344  pt_outer = n_outer != 0 ? p4_outer.Pt() : default_value;
2345  dEta_outer = n_outer != 0 ? dEta(p4_outer, tau.p4()) : default_value;
2346  dPhi_outer = n_outer != 0 ? dPhi(p4_outer, tau.p4()) : default_value;
2347  m_outer = n_outer != 0 ? p4_outer.mass() : default_value;
2348  }
2349 
2350  template <typename CandidateCollection, typename TauCastType>
2351  static void processIsolationPFComponents(const TauCastType& tau,
2353  LorentzVectorXYZ& p4,
2354  float& pt,
2355  float& d_eta,
2356  float& d_phi,
2357  float& m,
2358  float& n) {
2359  p4 = LorentzVectorXYZ(0, 0, 0, 0);
2360  n = 0;
2361 
2362  for (const auto& cand : candidates) {
2363  p4 += cand->p4();
2364  ++n;
2365  }
2366 
2367  pt = n != 0 ? p4.Pt() : default_value;
2368  d_eta = n != 0 ? dEta(p4, tau.p4()) : default_value;
2369  d_phi = n != 0 ? dPhi(p4, tau.p4()) : default_value;
2370  m = n != 0 ? p4.mass() : default_value;
2371  }
2372 
2373  static double getInnerSignalConeRadius(double pt) {
2374  static constexpr double min_pt = 30., min_radius = 0.05, cone_opening_coef = 3.;
2375  // This is equivalent of the original formula (std::max(std::min(0.1, 3.0/pt), 0.05)
2376  return std::max(cone_opening_coef / std::max(pt, min_pt), min_radius);
2377  }
2378 
2379  // Copied from https://github.com/cms-sw/cmssw/blob/CMSSW_9_4_X/RecoTauTag/RecoTau/plugins/PATTauDiscriminationByMVAIsolationRun2.cc#L218
2380  template <typename TauCastType>
2381  static bool calculateGottfriedJacksonAngleDifference(const TauCastType& tau,
2382  const size_t tau_index,
2383  double& gj_diff,
2384  TauFunc tau_funcs) {
2385  if (tau_funcs.getHasSecondaryVertex(tau, tau_index)) {
2386  static constexpr double mTau = 1.77682;
2387  const double mAOne = tau.p4().M();
2388  const double pAOneMag = tau.p();
2389  const double argumentThetaGJmax = (std::pow(mTau, 2) - std::pow(mAOne, 2)) / (2 * mTau * pAOneMag);
2390  const double argumentThetaGJmeasured = tau.p4().Vect().Dot(tau_funcs.getFlightLength(tau, tau_index)) /
2391  (pAOneMag * tau_funcs.getFlightLength(tau, tau_index).R());
2392  if (std::abs(argumentThetaGJmax) <= 1. && std::abs(argumentThetaGJmeasured) <= 1.) {
2393  double thetaGJmax = std::asin(argumentThetaGJmax);
2394  double thetaGJmeasured = std::acos(argumentThetaGJmeasured);
2395  gj_diff = thetaGJmeasured - thetaGJmax;
2396  return true;
2397  }
2398  }
2399  return false;
2400  }
2401 
2402  template <typename TauCastType>
2403  static float calculateGottfriedJacksonAngleDifference(const TauCastType& tau,
2404  const size_t tau_index,
2405  TauFunc tau_funcs) {
2406  double gj_diff;
2407  if (calculateGottfriedJacksonAngleDifference(tau, tau_index, gj_diff, tau_funcs))
2408  return static_cast<float>(gj_diff);
2409  return default_value;
2410  }
2411 
2412  static bool isInEcalCrack(double eta) {
2413  const double abs_eta = std::abs(eta);
2414  return abs_eta > 1.46 && abs_eta < 1.558;
2415  }
2416 
2417  template <typename TauCastType>
2418  static const pat::Electron* findMatchedElectron(const TauCastType& tau,
2419  const std::vector<pat::Electron>* electrons,
2420  double deltaR) {
2421  const double dR2 = deltaR * deltaR;
2422  const pat::Electron* matched_ele = nullptr;
2423  for (const auto& ele : *electrons) {
2424  if (reco::deltaR2(tau.p4(), ele.p4()) < dR2 && (!matched_ele || matched_ele->pt() < ele.pt())) {
2425  matched_ele = &ele;
2426  }
2427  }
2428  return matched_ele;
2429  }
2430 
2431 private:
2440  const unsigned year_;
2441  const unsigned version_;
2442  const unsigned sub_version_;
2443  const int debug_level;
2444  const bool disable_dxy_pca_;
2447  std::unique_ptr<tensorflow::Tensor> tauBlockTensor_;
2448  std::array<std::unique_ptr<tensorflow::Tensor>, 2> eGammaTensor_, muonTensor_, hadronsTensor_, convTensor_,
2450  const std::map<std::pair<deep_tau::Scaling::FeatureT, bool>, deep_tau::Scaling::ScalingParams>* scalingParamsMap_;
2451  const bool save_inputs_;
2452  std::ofstream* json_file_;
2455  std::vector<int> tauInputs_indices_;
2456 
2457  //boolean to check if discriminator indices are already mapped
2458  bool discrIndicesMapped_ = false;
2459  std::map<BasicDiscriminator, size_t> basicDiscrIndexMap_;
2460  std::map<BasicDiscriminator, size_t> basicDiscrdR03IndexMap_;
2461 };
2462 
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:1482
size
Write out results.
static constexpr float default_value
Definition: DeepTauId.cc:829
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:1998
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
Definition: DeepTauId.cc:873
ROOT::Math::LorentzVector< ROOT::Math::PxPyPzE4D< double > > LorentzVectorXYZ
Definition: DeepTauBase.h:75
unsigned int n_photons_total(const reco::PFTau &tau)
return total number of pf photon candidates with pT>500 MeV, which are associated to signal ...
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
std::array< std::unique_ptr< tensorflow::Tensor >, 2 > hadronsTensor_
Definition: DeepTauId.cc:2448
std::map< BasicDiscriminator, size_t > basicDiscrdR03IndexMap_
Definition: DeepTauId.cc:2460
ParameterDescriptionBase * addOptional(U const &iLabel, T const &value)
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:2351
static std::unique_ptr< deep_tau::DeepTauCache > initializeGlobalCache(const edm::ParameterSet &cfg)
Definition: DeepTauId.cc:1018
double pt() const final
transverse momentum
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:2307
float pt_weighted_dr_signal(const reco::PFTau &tau, int dm)
const bool disable_dxy_pca_
Definition: DeepTauId.cc:2444
static float getValueLinear(T value, float min_value, float max_value, bool positive)
Definition: DeepTauId.cc:1033
static const pat::Electron * findMatchedElectron(const TauCastType &tau, const std::vector< pat::Electron > *electrons, double deltaR)
Definition: DeepTauId.cc:2418
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:2149
void fillGrids(const TauCastType &tau, const Collection &objects, CellGrid &inner_grid, CellGrid &outer_grid)
Definition: DeepTauId.cc:1421
const bool save_inputs_
Definition: DeepTauId.cc:2451
std::array< std::unique_ptr< tensorflow::Tensor >, 2 > zeroOutputTensor_
Definition: DeepTauId.cc:2448
std::map< BasicDiscriminator, size_t > basicDiscrIndexMap_
Definition: DeepTauId.cc:2459
int file_counter_
Definition: DeepTauId.cc:2454
const DeepTauCache * cache_
Definition: DeepTauBase.h:135
static double getInnerSignalConeRadius(double pt)
Definition: DeepTauId.cc:2373
std::ofstream * json_file_
Definition: DeepTauId.cc:2452
unsigned long long EventNumber_t
static bool isAbove(double value, double min)
Definition: DeepTauId.cc:1049
static bool isInEcalCrack(double eta)
Definition: DeepTauId.cc:2412
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:1563
const unsigned version_
Definition: DeepTauId.cc:2441
const unsigned sub_version_
Definition: DeepTauId.cc:2442
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)
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, const edm::EventNumber_t &eventnr, std::vector< tensorflow::Tensor > &pred_vector, TauFunc tau_funcs)
Definition: DeepTauId.cc:1315
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
ParameterSet const & parameterSet(StableProvenance const &provenance, ProcessHistory const &history)
Definition: Provenance.cc:11
std::map< std::string, Output > OutputCollection
Definition: DeepTauBase.h:91
static const double deltaEta
Definition: CaloConstants.h:8
const std::map< std::pair< deep_tau::Scaling::FeatureT, bool >, deep_tau::Scaling::ScalingParams > * scalingParamsMap_
Definition: DeepTauId.cc:2450
static const OutputCollection & GetOutputs()
Definition: DeepTauId.cc:831
static std::string const input
Definition: EdmProvDump.cc:50
static const std::vector< BasicDiscriminator > requiredBasicDiscriminatorsdR03_
Definition: DeepTauBase.h:139
Definition: HeavyIon.h:7
std::array< std::unique_ptr< tensorflow::Tensor >, 2 > convTensor_
Definition: DeepTauId.cc:2448
DeepTauId(const edm::ParameterSet &cfg, const deep_tau::DeepTauCache *cache)
Definition: DeepTauId.cc:918
const std::map< std::pair< FeatureT, bool >, ScalingParams > scalingParamsMap_v2p5
OutputCollection outputs_
Definition: DeepTauBase.h:134
static const int tauID
Definition: TopGenEvent.h:20
char const * label
std::string output_layer_
Definition: DeepTauId.cc:2439
static constexpr float pi
Definition: DeepTauId.cc:1025
bool is_first_block_
Definition: DeepTauId.cc:2453
static float getValue(T value)
Definition: DeepTauId.cc:1028
CellObjectType
Definition: DeepTauId.cc:690
const unsigned year_
Definition: DeepTauId.cc:2440
Definition: Muon.py:1
float pt_weighted_deta_strip(const reco::PFTau &tau, int dm)
std::vector< float > features(const reco::PreId &ecal, const reco::PreId &hcal, double rho, const reco::BeamSpot &spot, noZS::EcalClusterLazyTools &ecalTools)
const std::map< BasicDiscriminator, size_t > matchDiscriminatorIndices(edm::Event &event, edm::EDGetTokenT< reco::TauDiscriminatorContainer > discriminatorContainerToken, std::vector< BasicDiscriminator > requiredDiscr)
Definition: DeepTauId.cc:841
void run(Session *session, const NamedTensorList &inputs, const std::vector< std::string > &outputNames, std::vector< Tensor > *outputs, const thread::ThreadPoolOptions &threadPoolOptions)
Definition: TensorFlow.cc:286
void saveInputs(const tensorflow::Tensor &inputs, const std::string &block_name, int n_inputs, const CellGrid *grid=nullptr)
Definition: DeepTauId.cc:1130
const bool disable_CellIndex_workaround_
Definition: DeepTauId.cc:2446
static float getValueNorm(T value, float mean, float sigma, float n_sigmas_max=5)
Definition: DeepTauId.cc:1043
def pv(vc)
Definition: MetAnalyzer.py:7
std::string input_layer_
Definition: DeepTauId.cc:2439
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
float pt_weighted_dr_iso(const reco::PFTau &tau, int dm)
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:1719
double f[11][100]
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
static void globalEndJob(const deep_tau::DeepTauCache *cache_)
Definition: DeepTauId.cc:1022
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
Definition: value.py:1
ParameterDescriptionBase * add(U const &iLabel, T const &value)
void checkInputs(const tensorflow::Tensor &inputs, const std::string &block_name, int n_inputs, const CellGrid *grid=nullptr) const
Definition: DeepTauId.cc:1074
tensorflow::Session & getSession(const std::string &name="") const
Definition: DeepTauBase.h:57
const_reference at(size_type pos) const
Analysis-level tau class.
Definition: Tau.h:53
const std::map< std::pair< FeatureT, bool >, ScalingParams > scalingParamsMap_v2p1
#define M_PI
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:1191
tensorflow::Tensor getPartialPredictions(bool is_inner)
Definition: DeepTauId.cc:1457
static bool calculateGottfriedJacksonAngleDifference(const TauCastType &tau, const size_t tau_index, double &gj_diff, TauFunc tau_funcs)
Definition: DeepTauId.cc:2381
edm::EDGetTokenT< edm::AssociationVector< reco::PFTauRefProd, std::vector< reco::PFTauTransverseImpactParameterRef > > > pfTauTransverseImpactParameters_token_
Definition: DeepTauId.cc:2438
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:2458
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:1574
float pt_weighted_dphi_strip(const reco::PFTau &tau, int dm)
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
Analysis-level electron class.
Definition: Electron.h:51
void add(std::string const &label, ParameterSetDescription const &psetDescription)
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:2435
bool operator<(DTCELinkId const &lhs, DTCELinkId const &rhs)
Definition: DTCELinkId.h:70
static float calculateGottfriedJacksonAngleDifference(const TauCastType &tau, const size_t tau_index, TauFunc tau_funcs)
Definition: DeepTauId.cc:2403
static bool calculateElectronClusterVarsV2(const pat::Electron &ele, float &cc_ele_energy, float &cc_gamma_energy, int &cc_n_gamma)
Definition: DeepTauId.cc:1051
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:41
fixed size matrix
HLT enums.
std::array< std::unique_ptr< tensorflow::Tensor >, 2 > eGammaTensor_
Definition: DeepTauId.cc:2448
const bool disable_hcalFraction_workaround_
Definition: DeepTauId.cc:2445
def cache(function)
Definition: utilities.py:3
edm::EDGetTokenT< reco::TauDiscriminatorContainer > basicTauDiscriminatorsdR03_inputToken_
Definition: DeepTauId.cc:2436
const std::map< ValueQuantityType, double > max_value
std::vector< int > tauInputs_indices_
Definition: DeepTauId.cc:2455
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 ==> deprecated? <==
const int debug_level
Definition: DeepTauId.cc:2443
std::vector< TauDiscInfo< pat::PATTauDiscriminator > > patPrediscriminants_
Definition: DeepTauBase.h:112
vars
Definition: DeepTauId.cc:30
static constexpr int DT
Definition: MuonSubdetId.h:11
Log< level::Warning, false > LogWarning
std::array< std::unique_ptr< tensorflow::Tensor >, 2 > muonTensor_
Definition: DeepTauId.cc:2448
edm::EDGetTokenT< std::vector< pat::Electron > > electrons_token_
Definition: DeepTauId.cc:2432
TupleMultiplicity< TrackerTraits > const *__restrict__ uint32_t nHits
edm::EDGetTokenT< std::vector< pat::Muon > > muons_token_
Definition: DeepTauId.cc:2433
T operator[](int i) const
long double T
static constexpr int CSC
Definition: MuonSubdetId.h:12
edm::EDGetTokenT< double > rho_token_
Definition: DeepTauId.cc:2434
static void calculateElectronClusterVars(const pat::Electron *ele, float &elecEe, float &elecEgamma)
Definition: DeepTauId.cc:2287
T const & const_reference
Definition: View.h:82
static const std::string subdets[7]
Definition: TrackUtils.cc:60
const std::map< std::pair< FeatureT, bool >, ScalingParams > scalingParamsMap_PhaseIIv2p5
edm::EDGetTokenT< CandidateCollection > pfcandToken_
Definition: DeepTauBase.h:130
Analysis-level muon class.
Definition: Muon.h:51
std::vector< TauDiscInfo< reco::PFTauDiscriminator > > recoPrediscriminants_
Definition: DeepTauBase.h:113
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
Definition: event.py:1
constexpr int NumberOfOutputs
Definition: DeepTauId.cc:20
std::unique_ptr< tensorflow::Tensor > tauBlockTensor_
Definition: DeepTauId.cc:2447
edm::EDGetTokenT< reco::VertexCollection > vtxToken_
Definition: DeepTauBase.h:131