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