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