CMS 3D CMS Logo

L1NNCaloTauEmulator.cc
Go to the documentation of this file.
1 /* -*- C++ -*-
2 
3 Package: L1CaloTrigger
4 Class: L1NNCaloTauEmulator
5 Frinedly name: The TauMinator
6 
7 \class L1NNCaloTauEmulator L1NNCaloTauEmulator.cc
8 
9 Description:
10 Perform firmware-exact emulation of the l1tNNCaloTauProducer
11 that implements the NN Calo Tau.
12 (Perform reconstruction and identification of tau
13 candidates at L1 Trigger with a CNN.)
14 
15 Implementation:
16 The implementation is done forseeing the integration
17 of the algorithm in the GCT Sum card. This means that
18 the full detector information can be accessed at the same
19 time (ECAL, HCAL, HGCAL full eta-phi coverage). This will
20 come in the form of arrays of towers and clusters.
21 Given that the emulators of the upstream algortihms are
22 not fully determined yet, this emulator takes as input
23 the simulation-based information, manipulates with software
24 precision to pruduce the arrays of towers and clusters as
25 they should be available in the GCT sum card.
26 Only then the actual fixed point algorithm emulation arrives.
27 
28 ** INFO : THE NNs ARE APPLIED USING THE TENSORFLOW SOFTWARE
29  the implementation of full emulation via hls4ml is ongoing
30  (it has already been shown in other contexts that tensorflow
31  softwrae and full emulation are very close to each other)
32 
33 Original Author: Jona Motta
34 Created: Tue June 7th 2023
35 
36 */
37 
38 #include <iostream>
39 #include <vector>
40 #include <cmath>
41 
42 #include "boost/property_tree/ptree.hpp"
43 #include "boost/property_tree/json_parser.hpp"
44 
45 #include "ap_int.h"
46 #include "ap_fixed.h"
47 // #include "hls4ml/emulator.h"
48 
58 
66 
69 
73 
75 
80 
85  boost::property_tree::ptree FeatScaler_CE;
86 
87  tensorflow::GraphDef* CNNmodel_CB;
88  tensorflow::GraphDef* DNNident_CB;
89  tensorflow::GraphDef* DNNcalib_CB;
90 
91  tensorflow::Session* CNNmodel_CBsession;
92  tensorflow::Session* DNNident_CBsession;
93  tensorflow::Session* DNNcalib_CBsession;
94 
95  tensorflow::GraphDef* CNNmodel_CE;
96  tensorflow::GraphDef* DNNident_CE;
97  tensorflow::GraphDef* DNNcalib_CE;
98 
99  tensorflow::Session* CNNmodel_CEsession;
100  tensorflow::Session* DNNident_CEsession;
101  tensorflow::Session* DNNcalib_CEsession;
102 };
103 
104 class L1NNCaloTauEmulator : public edm::stream::EDProducer<edm::GlobalCache<NNmodels_GlobalCache>> {
105 public:
107 
108  static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
109  static std::unique_ptr<NNmodels_GlobalCache> initializeGlobalCache(const edm::ParameterSet&);
110  static void globalEndJob(const NNmodels_GlobalCache*) { /*do nothing*/ }
111 
112 private:
113  // ----fixed LSBs, Nbits, scales, and types----
114  static constexpr int INTPHI_PI = 36;
115  static constexpr int INTPHI_2PI = 2 * INTPHI_PI;
117 
118  static constexpr int FINEINTPHI_PI = 720;
121 
122  static constexpr float SHAPEFEAT_LSB = 0.0000153; // pow(2, -16)
123  static constexpr float SZZ_LSB = SHAPEFEAT_LSB * 100;
124  static constexpr float ETAHGCAL_OFFSET = 1.321; // inferred from hgcal schematics
125  static constexpr float IETAHGCAL_LSBp = 0.0808; // inferred from simulation
126  static constexpr float IETAHGCAL_LSB = 0.0845; // inferred from simulation
127  static constexpr float PUID_LSB = 0.00390625; // pow(2, -8)
128  static constexpr float MEANZ_OFFSET = 321.05; // inferred from hgcal schematics
129  static constexpr int IETAHGCAL_OFFSET = 17;
130  static constexpr float MEANZ_LSB = 0.5;
131  static constexpr float PTET_LSB = 0.25;
132  static constexpr float CM2MM = 10;
133  static constexpr int R2cone = 0.25 / ETAPHI_LSB / ETAPHI_LSB;
134 
135  static constexpr int SHAPEFEAT_W = 16; // maximum forseen per shape
136  static constexpr int DETAPHI_W = 12;
137  static constexpr int DIETAPHI_W = 8;
138  static constexpr int IETAPHI_W = 7;
139  static constexpr int SHOWLEN_W = 6;
140  static constexpr int ETAPHI_W = 11; // precision going to correlator
141  static constexpr int MEANZ_W = 12;
142  static constexpr int PUID_W = 9;
143 
144  static constexpr int PT_W = 14;
145  static constexpr int PT_I = 12;
146  static constexpr int ET_W = 10;
147  static constexpr int ET_I = 8;
148 
149  // forseen precision of the HLS4ML emulation of the NNs
150  static constexpr int CALIBPT_W = 10;
151  static constexpr int CALIBPT_I = 9;
152  static constexpr int ID_W = 8;
153  static constexpr int ID_I = 1;
154 
155  typedef ap_ufixed<PT_W, PT_I, AP_TRN, AP_SAT> Pt_t;
156  typedef ap_ufixed<ET_W, ET_I, AP_TRN, AP_SAT> Et_t;
157 
158  typedef ap_ufixed<CALIBPT_W, CALIBPT_I, AP_TRN, AP_SAT> CalibPt_t;
159  typedef ap_ufixed<ID_W, ID_I, AP_TRN, AP_SAT> Id_t;
160 
161  typedef ap_uint<SHAPEFEAT_W> ShapeFeat_t;
162  typedef ap_int<DIETAPHI_W> dIEtaPhi_t;
163  typedef ap_int<DETAPHI_W> dEtaPhi_t;
164  typedef ap_uint<SHOWLEN_W> ShowLen_t;
165  typedef ap_int<ETAPHI_W> EtaPhi_t;
166  typedef ap_uint<IETAPHI_W> IPhi_t;
167  typedef ap_int<IETAPHI_W> IEta_t;
168  typedef ap_uint<MEANZ_W> Meanz_t;
169  typedef ap_int<PUID_W> PUid_t;
170 
171  // ----fixed dimensions of tower clusters----
172  const int seedIdx = 22;
173  const int IEta_dim = 5;
174  const int IPhi_dim = 9;
175  const int Eta_limit = 33;
176 
177  //----edm control---
178  void produce(edm::Event&, const edm::EventSetup&) override;
179 
180  //----private functions----
181  template <class outPrecision, class inPrecision>
182  outPrecision dPhi(inPrecision iPhi_1, inPrecision iPhi_2);
183  dIEtaPhi_t tower_dIEta(IEta_t iEta_1, IEta_t iEta_2);
185  dEtaPhi_t tw2cl_dEta(EtaPhi_t iEta_1, IEta_t iEta_2);
186  IEta_t makeEndcapHwIEta(float eta);
187  IPhi_t makeEndcapHwIPhi(float phi);
188  float apfixedQuantizer(float inputF, float LSB, int nbits);
189  int apintQuantizer(float inputF, float LSB, int nbits);
190  float inputScaler(float inputF, std::string feature);
191  float correctInputEtaCl3d(float eta);
192  float correctInputMeanzCl3d(float meanz);
193 
194  inline float floatPt(Pt_t pt) { return pt.to_float(); }
195  inline float floatEt(Et_t et) { return et.to_float(); }
196  inline float floatEta(EtaPhi_t eta) { return eta.to_float() * ETAPHI_LSB; }
197  inline float floatPhi(EtaPhi_t phi) { return phi.to_float() * ETAPHI_LSB; }
198  inline float floatShape(ShapeFeat_t shape) { return shape.to_float() * SHAPEFEAT_LSB; };
199  inline float floatSzz(ShapeFeat_t szz) { return szz.to_float() * SZZ_LSB; };
200  inline float floatMeanZ(Meanz_t meanz) { return meanz.to_float() * MEANZ_LSB + MEANZ_OFFSET; };
201  inline float floatMeanZHgcalCoord(Meanz_t meanz) { return meanz.to_float() * MEANZ_LSB; };
202  inline float floatPuId(PUid_t pu) { return pu.to_float() * PUID_LSB; };
203  float floatIEta(IEta_t eta);
204  float floatIPhi(IPhi_t phi);
205 
206  template <int W>
207  ap_int<W> ap_abs(ap_int<W> x);
208  template <int W, int I, ap_q_mode _AP_Q, ap_o_mode _AP_O>
209  ap_ufixed<W, I> ap_abs(ap_fixed<W, I, _AP_Q, _AP_O> x);
210 
211  //----tokens and handles----
214 
217 
220 
221  //----private variables----
226 
231  double CB_CE_split;
232  double PuidThr;
233 
234  double IdWp90_CB;
235  double IdWp95_CB;
236  double IdWp99_CB;
237 
238  double IdWp90_CE;
239  double IdWp95_CE;
240  double IdWp99_CE;
241 
245 
246  bool DEBUG;
247 
248  // Class for the towers info as they should be in GCT
250  public:
253  Et_t towerEm = 0.;
256  Et_t towerEt = 0.;
257  ap_uint<1> isBarrel = 0x1;
258  ap_uint<1> stale = 0x0;
259  ap_uint<1> stale4seed = 0x0;
260  };
261 
262  // Class for the clusters info as they should arrive from HGCAL
264  public:
275  ap_uint<1> stale = 0x0;
276  };
277 
278  // Classes for the tower clusters
280  public:
281  Et_t towerEm = 0.;
284 
285  void fill(SimpleTowerHit Tower) {
286  towerEm = Tower.towerEm;
287  towerHad = Tower.towerHad;
288  l1egTowerEt = Tower.l1egTowerEt;
289  }
290  };
291 
293  public:
295  ap_uint<1> barrelSeeded = 0x0;
296  ap_uint<1> filled[45];
297 
298  void fill(int idx, SimpleTowerHit Tower) {
299  towerHits[idx].fill(Tower);
300  filled[idx] = 0x1;
301  }
302 
303  void init() {
304  SimplifiedTower emptyT;
305  std::fill(towerHits, towerHits + 44, emptyT);
306  std::fill(filled, filled + 44, 0x0);
307  }
308  };
309 
311  public:
314 
315  void fill(SimpleTowerHit Tower) {
316  seedIeta = Tower.towerIeta;
317  seedIphi = Tower.towerIphi;
318  }
319  };
320 
321  // INFO : now variables are in GCT precision, they should be in NN precision
322  // after scaling, i.e. something like ap_fixed<16, 6, AP_TRN, AP_SAT>, when the
323  // full hls4ml emulation is available
325  public:
334 
335  void fill(SimpleHGCluster Cluster) {
336  pt = Cluster.pt;
337  eta = Cluster.eta;
338  showerlength = Cluster.showerlength;
340  spptot = Cluster.spptot;
341  szz = Cluster.szz;
342  srrtot = Cluster.srrtot;
343  meanz = Cluster.meanz;
344  }
345  };
346 
348  int clNxMIdx,
349  std::vector<tensorflow::Tensor> outputsIdent,
350  std::vector<tensorflow::Tensor> outputsCalib,
351  std::vector<InputTowerCluster_pstn> clustersNxM_pstn);
352 };
353 
354 /*
355 â–ˆâ–ˆâ–ˆâ–ˆâ–ˆâ–ˆâ–ˆâ–ˆ ██ ██ ██████ ████████ █████ ██ ██ ███ ███ ██ ███ ██ █████ ████████ ██████ ██████
356  ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ████ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██
357  ██ ███████ █████ ██ ███████ ██ ██ ██ ████ ██ ██ ██ ██ ██ ███████ ██ ██ ██ ██████
358  ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
359  ██ ██ ██ ██████ ██ ██ ██ ███████ ██ ██ ██ ██ ████ ██ ██ ██ ██████ ██ ██
360 */
361 
362 std::unique_ptr<NNmodels_GlobalCache> L1NNCaloTauEmulator::initializeGlobalCache(const edm::ParameterSet& iConfig) {
363  edm::LogInfo("Initialization") << "Init NN models Global Cache " << std::endl;
364 
365  std::unique_ptr<NNmodels_GlobalCache> GlobalCache(new NNmodels_GlobalCache);
366 
367  GlobalCache->CNNmodel_CB_path = iConfig.getParameter<std::string>("CNNmodel_CB_path");
368  GlobalCache->DNNident_CB_path = iConfig.getParameter<std::string>("DNNident_CB_path");
369  GlobalCache->DNNcalib_CB_path = iConfig.getParameter<std::string>("DNNcalib_CB_path");
370  GlobalCache->CNNmodel_CE_path = iConfig.getParameter<std::string>("CNNmodel_CE_path");
371  GlobalCache->DNNident_CE_path = iConfig.getParameter<std::string>("DNNident_CE_path");
372  GlobalCache->DNNcalib_CE_path = iConfig.getParameter<std::string>("DNNcalib_CE_path");
373  GlobalCache->FeatScaler_CE_path = iConfig.getParameter<std::string>("FeatScaler_CE_path");
374 
375  // Create sessions for Tensorflow inferece
376  (GlobalCache->CNNmodel_CB) = tensorflow::loadGraphDef(edm::FileInPath((GlobalCache->CNNmodel_CB_path)).fullPath());
377  (GlobalCache->CNNmodel_CBsession) = tensorflow::createSession((GlobalCache->CNNmodel_CB));
378 
379  (GlobalCache->DNNident_CB) = tensorflow::loadGraphDef(edm::FileInPath((GlobalCache->DNNident_CB_path)).fullPath());
380  (GlobalCache->DNNident_CBsession) = tensorflow::createSession((GlobalCache->DNNident_CB));
381 
382  (GlobalCache->DNNcalib_CB) = tensorflow::loadGraphDef(edm::FileInPath((GlobalCache->DNNcalib_CB_path)).fullPath());
383  (GlobalCache->DNNcalib_CBsession) = tensorflow::createSession((GlobalCache->DNNcalib_CB));
384 
385  (GlobalCache->CNNmodel_CE) = tensorflow::loadGraphDef(edm::FileInPath((GlobalCache->CNNmodel_CE_path)).fullPath());
386  (GlobalCache->CNNmodel_CEsession) = tensorflow::createSession((GlobalCache->CNNmodel_CE));
387 
388  (GlobalCache->DNNident_CE) = tensorflow::loadGraphDef(edm::FileInPath((GlobalCache->DNNident_CE_path)).fullPath());
389  (GlobalCache->DNNident_CEsession) = tensorflow::createSession((GlobalCache->DNNident_CE));
390 
391  (GlobalCache->DNNcalib_CE) = tensorflow::loadGraphDef(edm::FileInPath((GlobalCache->DNNcalib_CE_path)).fullPath());
392  (GlobalCache->DNNcalib_CEsession) = tensorflow::createSession((GlobalCache->DNNcalib_CE));
393 
394  // Read features scaler
395  boost::property_tree::read_json(edm::FileInPath((GlobalCache->FeatScaler_CE_path)).fullPath(),
396  (GlobalCache->FeatScaler_CE));
397 
398  return GlobalCache;
399 }
400 
401 // ----Constructor and Destructor -----
403  : l1TowersToken(consumes<l1tp2::CaloTowerCollection>(iConfig.getParameter<edm::InputTag>("l1CaloTowers"))),
404  hgcalTowersToken(consumes<l1t::HGCalTowerBxCollection>(iConfig.getParameter<edm::InputTag>("hgcalTowers"))),
405 
406  HGClusterToken(
407  consumes<l1t::HGCalMulticlusterBxCollection>(iConfig.getParameter<edm::InputTag>("HgcalClusters"))),
408  scenario(UseEmInterp::No),
409  preEmId(iConfig.getParameter<std::string>("preEmId")),
410  VsPuId(iConfig.getParameter<edm::ParameterSet>("VsPuId")),
411 
412  EcalEtMinForClustering(iConfig.getParameter<double>("EcalEtMinForClustering")),
413  HcalEtMinForClustering(iConfig.getParameter<double>("HcalEtMinForClustering")),
414  EtMinForSeeding(iConfig.getParameter<double>("EtMinForSeeding")),
415  EtaRestriction(iConfig.getParameter<double>("EtaRestriction")),
416  CB_CE_split(iConfig.getParameter<double>("CB_CE_split")),
417  PuidThr(iConfig.getParameter<double>("PuidThr")),
418 
419  IdWp90_CB(iConfig.getParameter<double>("IdWp90_CB")),
420  IdWp95_CB(iConfig.getParameter<double>("IdWp95_CB")),
421  IdWp99_CB(iConfig.getParameter<double>("IdWp99_CB")),
422 
423  IdWp90_CE(iConfig.getParameter<double>("IdWp90_CE")),
424  IdWp95_CE(iConfig.getParameter<double>("IdWp95_CE")),
425  IdWp99_CE(iConfig.getParameter<double>("IdWp99_CE")),
426 
427  DEBUG(iConfig.getParameter<bool>("DEBUG")) {
428  // Initialize HGCAL BDTs
429  if (!VsPuId.method().empty()) {
431  }
432 
436 
437  // Create produced outputs
438  produces<BXVector<l1t::Tau>>("L1NNCaloTauCollectionBXV");
439 
440  // Settings output
441  edm::LogInfo("Settings") << "EtaRestriction = " << EtaRestriction << " (" << intEtaRestriction << ")"
442  << " , CB_CE_split = " << CB_CE_split << "(" << intCB_CE_split
443  << ") , EtMinForSeeding = " << EtMinForSeeding
444  << " , HcalTpEtMin = " << HcalEtMinForClustering
445  << " , EcalTpEtMin = " << EcalEtMinForClustering << " , PuidThr = " << PuidThr << "("
446  << intPuidThr << ")" << std::endl;
447 }
448 
450  // Output collection
451  std::unique_ptr<BXVector<l1t::Tau>> L1NNCaloTauCollectionBXV(new l1t::TauBxCollection);
452 
453  // Create and Fill collection of all calotowers and their attributes
454  std::vector<SimpleTowerHit> l1CaloTowers;
455 
457  int warnings = 0;
458  for (auto& hit : *l1CaloTowerHandle.product()) {
459  // Skip this weird towers and store warning
460  if (hit.towerIEta() == -1016 && hit.towerIPhi() == -962) {
461  warnings += 1;
462  continue;
463  }
464 
465  SimpleTowerHit l1Hit;
466  l1Hit.isBarrel = 0x1;
467  l1Hit.l1egTowerEt = apfixedQuantizer(hit.l1egTowerEt(), PTET_LSB, ET_W);
468  l1Hit.towerEm = apfixedQuantizer(hit.ecalTowerEt(), PTET_LSB, ET_W);
469  l1Hit.towerHad = apfixedQuantizer(hit.hcalTowerEt(), PTET_LSB, ET_W);
470  l1Hit.towerEt = apfixedQuantizer(hit.ecalTowerEt() + hit.hcalTowerEt() + hit.l1egTowerEt(), PTET_LSB, ET_W);
471  l1Hit.towerIeta = hit.towerIEta();
472  l1Hit.towerIphi = hit.towerIPhi();
473 
474  l1CaloTowers.push_back(l1Hit);
475  }
476  if (warnings != 0 && DEBUG) {
477  edm::LogWarning("BrokenTowers") << " ** WARNING : FOUND " << warnings
478  << " TOWERS WITH towerIeta=-1016 AND towerIphi=-962" << std::endl;
479  }
480 
482  for (auto& hit : *hgcalTowersHandle.product()) {
483  SimpleTowerHit l1Hit;
484  l1Hit.isBarrel = 0x0;
485  l1Hit.l1egTowerEt = 0.0;
486  l1Hit.towerEm = apfixedQuantizer(hit.etEm(), PTET_LSB, ET_W);
487  l1Hit.towerHad = apfixedQuantizer(hit.etHad(), PTET_LSB, ET_W);
488  l1Hit.towerEt = apfixedQuantizer(hit.etEm() + hit.etHad(), PTET_LSB, ET_W);
489  l1Hit.towerIeta = makeEndcapHwIEta(hit.eta());
490  l1Hit.towerIphi = makeEndcapHwIPhi(hit.phi());
491 
492  l1CaloTowers.push_back(l1Hit);
493  }
494 
495  // Sort the ECAL+HCAL+L1EGs tower sums based on total ET
497  return a.towerEt > b.towerEt;
498  });
499 
500  // Create and Fill the collection of 3D clusters and their attributes
501  std::vector<SimpleHGCluster> AllHGClusters;
503 
504  for (auto cl3dIt = HGClusterHandle->begin(0); cl3dIt != HGClusterHandle->end(0); ++cl3dIt) {
505  auto& cl3d = *cl3dIt;
506 
507  // Implement cl3d PU ID as done in
508  // https://github.com/cms-sw/cmssw/blob/master/L1Trigger/Phase2L1ParticleFlow/plugins/PFClusterProducerFromHGC3DClusters.cc#L120
509  bool isEM = preEmId(*cl3dIt);
510  l1t::PFCluster cluster(cl3d.pt(), cl3d.eta(), cl3d.phi(), cl3d.hOverE());
511  if (scenario == UseEmInterp::EmOnly) // for emID objs, use EM interp as pT and set H = 0
512  {
513  if (isEM) {
514  float pt_new = cl3d.iPt(l1t::HGCalMulticluster::EnergyInterpretation::EM);
515  float hoe_new = 0.;
516  cluster = l1t::PFCluster(pt_new, cl3d.eta(), cl3d.phi(), hoe_new, isEM);
517  }
518  } else if (scenario == UseEmInterp::AllKeepHad) // for all objs, replace EM part with EM interp, preserve H
519  {
520  float had_old = cl3d.pt() - cluster.emEt();
521  float em_new = cl3d.iPt(l1t::HGCalMulticluster::EnergyInterpretation::EM);
522  float pt_new = had_old + em_new;
523  float hoe_new = em_new > 0 ? (had_old / em_new) : -1;
524  cluster = l1t::PFCluster(pt_new, cl3d.eta(), cl3d.phi(), hoe_new, isEM);
525  } else if (scenario == UseEmInterp::AllKeepTot) // for all objs, replace EM part with EM interp, preserve pT
526  {
527  float em_new = cl3d.iPt(l1t::HGCalMulticluster::EnergyInterpretation::EM);
528  float hoe_new = em_new > 0 ? (cl3d.pt() / em_new - 1) : -1;
529  cluster = l1t::PFCluster(cl3d.pt(), cl3d.eta(), cl3d.phi(), hoe_new, isEM);
530  }
531 
532  float idScore = -1.;
533  if (!VsPuId.method().empty()) {
534  idScore = VsPuId.passID(*cl3dIt, cluster);
535  idScore = cluster.egVsPUMVAOut();
536  }
537 
538  float eta_hgcalCoord = correctInputEtaCl3d(cl3d.eta());
539  float meanz_hgcalCoord = correctInputMeanzCl3d(cl3d.zBarycenter());
540 
541  SimpleHGCluster HGCluster;
542  HGCluster.pt = apfixedQuantizer(cl3d.pt(), PTET_LSB, PT_W);
543  HGCluster.eta = apintQuantizer(eta_hgcalCoord, ETAPHI_LSB, ETAPHI_W);
544  HGCluster.phi = apintQuantizer(cl3d.phi(), ETAPHI_LSB, ETAPHI_W);
545  HGCluster.showerlength = cl3d.showerLength();
546  HGCluster.coreshowerlength = cl3d.coreShowerLength();
547  HGCluster.spptot = apintQuantizer(cl3d.sigmaPhiPhiTot(), SHAPEFEAT_LSB, SHAPEFEAT_W);
548  HGCluster.szz = apintQuantizer(cl3d.sigmaZZ(), SZZ_LSB, SHAPEFEAT_W);
549  HGCluster.srrtot = apintQuantizer(cl3d.sigmaRRTot(), SHAPEFEAT_LSB, SHAPEFEAT_W);
550  HGCluster.meanz = apintQuantizer(meanz_hgcalCoord, MEANZ_LSB, MEANZ_W);
551  HGCluster.PUid = apintQuantizer(idScore, PUID_LSB, PUID_W);
552 
553  AllHGClusters.push_back(HGCluster);
554  }
555 
556  // Order the collection in pt (the input to the GCT will be pt ordered)
557  std::sort(begin(AllHGClusters), end(AllHGClusters), [](const SimpleHGCluster& a, SimpleHGCluster& b) {
558  return a.pt > b.pt;
559  });
560 
561  /*
562  // END OF SOFTWARE PRECISION SECTION
563  // up to here treated inputs from simulation with SW precision
564  // to massage them into the HW precision varibales as they are
565  // forseen (roughly) to be available at the GCT Sum card level
566  // ------------------------------------------------------------- */
567 
568  // Make NxM TowerClusters and HGClusters collections for TauMinator
569  std::vector<InputTowerCluster> l1TowerClustersNxM_CB;
570  std::vector<InputTowerCluster_pstn> l1TowerClustersNxM_CB_pstn;
571  std::vector<InputTowerCluster> l1TowerClustersNxM_CE;
572  std::vector<InputTowerCluster_pstn> l1TowerClustersNxM_CE_pstn;
573  std::vector<InputHGCluster> HGClusters;
574 
575  // Supporting collection of endcap clusters before cl3d matching
576  std::vector<InputTowerCluster> AllL1TowerClustersNxM_CE;
577  std::vector<InputTowerCluster_pstn> AllL1TowerClustersNxM_CE_pstn;
578 
579  int Nclusters_CB = 0;
580  int AllNclusters_CE = 0;
581  bool caloTauSeedingFinished = false;
582  // Loop for seeding of clNxM objects
583  while (!caloTauSeedingFinished) {
584  InputTowerCluster clNxM;
585  clNxM.init();
586  InputTowerCluster_pstn clNxM_pstn;
587  bool seeded = false;
588 
589  for (auto& l1CaloTower : l1CaloTowers) {
590  // Skip seeding in towers that would make the cluster extend in HF
591  // Skip l1CaloTowers which are already used by this clusters' mask
592  if (ap_abs(l1CaloTower.towerIeta) > Eta_limit || ap_abs(l1CaloTower.towerIeta) > intEtaRestriction ||
593  l1CaloTower.stale4seed) {
594  continue;
595  }
596 
597  // If not seded do the seeding
598  if (!seeded) {
599  // The leading unused tower has ET < min, stop jet clustering
600  if (l1CaloTower.towerEt < EtMinForSeeding) {
601  caloTauSeedingFinished = true;
602  continue;
603  }
604 
605  clNxM.fill(seedIdx, l1CaloTower);
606  clNxM_pstn.fill(l1CaloTower);
607  if (l1CaloTower.isBarrel) {
608  clNxM.barrelSeeded = 0x1;
609  }
610 
611  l1CaloTower.stale4seed = 0x1;
612  l1CaloTower.stale = 0x1;
613  seeded = true;
614 
615  continue;
616  }
617 
618  dIEtaPhi_t d_iEta = tower_dIEta(l1CaloTower.towerIeta, clNxM_pstn.seedIeta);
619  dIEtaPhi_t d_iPhi = dPhi<dIEtaPhi_t, IPhi_t>(l1CaloTower.towerIphi, clNxM_pstn.seedIphi);
620 
621  // Stale tower for seeding if it would lead to overalp between clusters
622  if ((ap_abs(d_iEta) <= IEta_dim - 1 && ap_abs(d_iPhi) <= IPhi_dim - 1)) {
623  l1CaloTower.stale4seed = 0x1;
624  }
625 
626  } // End for loop over TPs
627 
628  // Pushback seeds split in barrel and endcap
629  if (seeded) {
630  if (ap_abs(clNxM_pstn.seedIeta) <= intCB_CE_split) {
631  l1TowerClustersNxM_CB.push_back(clNxM);
632  l1TowerClustersNxM_CB_pstn.push_back(clNxM_pstn);
633  Nclusters_CB++;
634  } else {
635  AllL1TowerClustersNxM_CE.push_back(clNxM);
636  AllL1TowerClustersNxM_CE_pstn.push_back(clNxM_pstn);
637  AllNclusters_CE++;
638  }
639  }
640 
641  } // End while loop of TowerClusters seeding
642 
643  // Loop for barrel NxM TowerClusters clustering starting from the seeds
644  for (int clNxMIdx = 0; clNxMIdx < Nclusters_CB; clNxMIdx++) {
645  for (auto& l1CaloTower : l1CaloTowers) {
646  // Skip l1CaloTowers which are already used
647  if (l1CaloTower.stale) {
648  continue;
649  }
650 
651  dIEtaPhi_t d_iEta = tower_dIEta(l1CaloTower.towerIeta, l1TowerClustersNxM_CB_pstn[clNxMIdx].seedIeta);
652  dIEtaPhi_t d_iPhi =
653  dPhi<dIEtaPhi_t, IPhi_t>(l1CaloTower.towerIphi, l1TowerClustersNxM_CB_pstn[clNxMIdx].seedIphi);
654  int hitIdx = d_iEta * 9 + d_iPhi + seedIdx;
655 
656  // Cluster all towers in a NxM towers mask
657  if ((ap_abs(d_iEta) <= (IEta_dim - 1) / 2 && ap_abs(d_iPhi) <= (IPhi_dim - 1) / 2)) {
658  l1TowerClustersNxM_CB[clNxMIdx].fill(hitIdx, l1CaloTower);
659  l1CaloTower.stale = 0x1;
660  }
661 
662  } // End for loop over TPs
663 
664  } // End while loop of barrel TowerClusters creation
665 
666  // In the endcap cross-loop over clNxM and cl3d to match them
667  // (we can do it before full clustering just using the seed info)
668  int Nclusters_CE = 0;
669  for (int clNxMIdx = 0; clNxMIdx < AllNclusters_CE; clNxMIdx++) {
670  bool matched = false;
671  for (auto& HGCluster : AllHGClusters) {
672  // In case the clNxM or HGCluster have already been matched just continue through the list to the end
673  // only use cl3ds above 4GeV and above -0.10 pu id
674  if (matched || HGCluster.stale || HGCluster.pt < Pt_t(4.) || HGCluster.PUid < intPuidThr) {
675  continue;
676  }
677 
678  dEtaPhi_t d_iEta = tw2cl_dEta(HGCluster.eta, AllL1TowerClustersNxM_CE_pstn[clNxMIdx].seedIeta);
679  dEtaPhi_t d_iPhi = tw2cl_dPhi(HGCluster.phi, AllL1TowerClustersNxM_CE_pstn[clNxMIdx].seedIphi);
680  matched = d_iEta * d_iEta + d_iPhi * d_iPhi < R2cone;
681 
682  if (matched) {
683  HGCluster.stale = 0x1;
684  InputHGCluster cl3d;
685  cl3d.fill(HGCluster);
686  HGClusters.push_back(cl3d);
687  l1TowerClustersNxM_CE.push_back(AllL1TowerClustersNxM_CE[clNxMIdx]);
688  l1TowerClustersNxM_CE_pstn.push_back(AllL1TowerClustersNxM_CE_pstn[clNxMIdx]);
689  Nclusters_CE++;
690  }
691 
692  } // End for loop over cl3ds
693 
694  } // End for loop over clNxM
695 
696  // Loop for endcap matched NxM TowerClusters clustering starting from the seeds just found
697  for (int clNxMIdx = 0; clNxMIdx < Nclusters_CE; clNxMIdx++) {
698  for (auto& l1CaloTower : l1CaloTowers) {
699  // Skip l1CaloTowers which are already used
700  if (l1CaloTower.stale) {
701  continue;
702  }
703 
704  dIEtaPhi_t d_iEta = tower_dIEta(l1CaloTower.towerIeta, l1TowerClustersNxM_CE_pstn[clNxMIdx].seedIeta);
705  dIEtaPhi_t d_iPhi =
706  dPhi<dIEtaPhi_t, IPhi_t>(l1CaloTower.towerIphi, l1TowerClustersNxM_CE_pstn[clNxMIdx].seedIphi);
707  int hitIdx = d_iEta * 9 + d_iPhi + seedIdx;
708 
709  // Cluster all towers in a NxM towers mask
710  if ((ap_abs(d_iEta) <= (IEta_dim - 1) / 2 && ap_abs(d_iPhi) <= (IPhi_dim - 1) / 2)) {
711  l1TowerClustersNxM_CE[clNxMIdx].fill(hitIdx, l1CaloTower);
712  l1CaloTower.stale = 0x1;
713  }
714 
715  } // End for loop over TPs
716 
717  } // End while loop of barrel TowerClusters creation
718 
719  // Barrel TauMinator application
720  int batchSize_CB = (int)(Nclusters_CB);
721  tensorflow::TensorShape imageShape_CB({batchSize_CB, IEta_dim, IPhi_dim, 2});
722  tensorflow::TensorShape positionShape_CB({batchSize_CB, 2});
723  tensorflow::Tensor TowerClusterImage_CB(tensorflow::DT_FLOAT, imageShape_CB);
724  tensorflow::Tensor TowerClusterPosition_CB(tensorflow::DT_FLOAT, positionShape_CB);
725 
726  for (int clNxMIdx = 0; clNxMIdx < Nclusters_CB; clNxMIdx++) {
727  // Fill inputs for Tensorflow inference
728  for (int eta = 0; eta < IEta_dim; ++eta) {
729  for (int phi = 0; phi < IPhi_dim; ++phi) {
730  int towerIdx = eta * IPhi_dim + phi;
731  TowerClusterImage_CB.tensor<float, 4>()(clNxMIdx, eta, phi, 0) =
732  (l1TowerClustersNxM_CB[clNxMIdx].towerHits[towerIdx].l1egTowerEt.to_float() +
733  l1TowerClustersNxM_CB[clNxMIdx].towerHits[towerIdx].towerEm.to_float());
734  TowerClusterImage_CB.tensor<float, 4>()(clNxMIdx, eta, phi, 1) =
735  (l1TowerClustersNxM_CB[clNxMIdx].towerHits[towerIdx].towerHad.to_float());
736  }
737  }
738 
739  TowerClusterPosition_CB.tensor<float, 2>()(clNxMIdx, 0) = floatIEta(l1TowerClustersNxM_CB_pstn[clNxMIdx].seedIeta);
740  TowerClusterPosition_CB.tensor<float, 2>()(clNxMIdx, 1) = floatIPhi(l1TowerClustersNxM_CB_pstn[clNxMIdx].seedIphi);
741  }
742 
743  if (batchSize_CB >
744  0) // from CMSSW_14_0_X tensorflow does not seem to be able to deal with a tensor of dimension 0 anymore
745  {
746  // Apply CNN model
747  tensorflow::NamedTensorList CNNmodel_CBinputList = {{"TowerClusterImage", TowerClusterImage_CB},
748  {"TowerClusterPosition", TowerClusterPosition_CB}};
749  std::vector<tensorflow::Tensor> CNNmodel_CBoutputs;
750  tensorflow::run((globalCache()->CNNmodel_CBsession),
751  CNNmodel_CBinputList,
752  {"TauMinator_CB_conv/middleMan/concat"},
753  &CNNmodel_CBoutputs);
754  tensorflow::NamedTensorList DNN_CBinputsList = {{"middleMan", CNNmodel_CBoutputs[0]}};
755 
756  // Apply DNN for identification
757  std::vector<tensorflow::Tensor> DNN_CBoutputsIdent;
758  tensorflow::run((globalCache()->DNNident_CBsession),
759  DNN_CBinputsList,
760  {"TauMinator_CB_ident/sigmoid_IDout/Sigmoid"},
761  &DNN_CBoutputsIdent);
762 
763  // Apply DNN for calibration
764  std::vector<tensorflow::Tensor> DNN_CBoutputsCalib;
765  tensorflow::run((globalCache()->DNNcalib_CBsession),
766  DNN_CBinputsList,
767  {"TauMinator_CB_calib/DNNout/MatMul"},
768  &DNN_CBoutputsCalib);
769 
770  // Fill the output collection of L1 taus with the barrel candidates
771  for (int clNxMIdx = 0; clNxMIdx < Nclusters_CB; clNxMIdx++) {
772  l1t::Tau l1Tau =
773  MakeTauCandidate(true, clNxMIdx, DNN_CBoutputsIdent, DNN_CBoutputsCalib, l1TowerClustersNxM_CB_pstn);
774  if (l1Tau.pt() < 0) {
775  continue;
776  }
777  L1NNCaloTauCollectionBXV->push_back(0, l1Tau);
778  }
779  }
780 
781  // Endcap TauMinator application
782  int batchSize_CE = (int)(Nclusters_CE);
783  tensorflow::TensorShape imageShape_CE({batchSize_CE, IEta_dim, IPhi_dim, 2});
784  tensorflow::TensorShape positionShape_CE({batchSize_CE, 2});
785  tensorflow::TensorShape cl3dfeatShape_CE({batchSize_CE, 8});
786  tensorflow::Tensor TowerClusterImage_CE(tensorflow::DT_FLOAT, imageShape_CE);
787  tensorflow::Tensor TowerClusterPosition_CE(tensorflow::DT_FLOAT, positionShape_CE);
788  tensorflow::Tensor Cl3dShapeFeatures_CE(tensorflow::DT_FLOAT, cl3dfeatShape_CE);
789 
790  for (int clNxMIdx = 0; clNxMIdx < Nclusters_CE; clNxMIdx++) {
791  // Indexing of cl3ds is the same as the one of clNxMs
792  InputHGCluster HGClu = HGClusters[clNxMIdx];
793 
794  // Fill inputs for Tensorflow inference
795  for (int eta = 0; eta < IEta_dim; ++eta) {
796  for (int phi = 0; phi < IPhi_dim; ++phi) {
797  int towerIdx = eta * IPhi_dim + phi;
798  TowerClusterImage_CE.tensor<float, 4>()(clNxMIdx, eta, phi, 0) =
799  (l1TowerClustersNxM_CE[clNxMIdx].towerHits[towerIdx].l1egTowerEt.to_float() +
800  l1TowerClustersNxM_CE[clNxMIdx].towerHits[towerIdx].towerEm.to_float());
801  TowerClusterImage_CE.tensor<float, 4>()(clNxMIdx, eta, phi, 1) =
802  (l1TowerClustersNxM_CE[clNxMIdx].towerHits[towerIdx].towerHad.to_float());
803  }
804  }
805 
806  TowerClusterPosition_CE.tensor<float, 2>()(clNxMIdx, 0) = floatIEta(l1TowerClustersNxM_CE_pstn[clNxMIdx].seedIeta);
807  TowerClusterPosition_CE.tensor<float, 2>()(clNxMIdx, 1) = floatIPhi(l1TowerClustersNxM_CE_pstn[clNxMIdx].seedIphi);
808 
809  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 0) = inputScaler(HGClu.pt.to_float(), "pt");
810  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 1) = inputScaler(abs(floatEta(HGClu.eta)), "eta");
811  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 2) = inputScaler(HGClu.showerlength.to_float(), "showerlength");
812  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 3) =
813  inputScaler(HGClu.coreshowerlength.to_float(), "coreshowerlength");
814  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 4) = inputScaler(floatShape(HGClu.spptot), "spptot");
815  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 5) = inputScaler(floatSzz(HGClu.szz), "szz");
816  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 6) = inputScaler(floatShape(HGClu.srrtot), "srrtot");
817  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 7) = inputScaler(floatMeanZHgcalCoord(HGClu.meanz), "meanz");
818  }
819 
820  if (batchSize_CE >
821  0) // from CMSSW_14_0_X tensorflow does not seem to be able to deal with a tensor of dimension 0 anymore
822  {
823  // Apply CNN model
824  tensorflow::NamedTensorList CNNmodel_CEinputList = {{"TowerClusterImage", TowerClusterImage_CE},
825  {"TowerClusterPosition", TowerClusterPosition_CE},
826  {"AssociatedCl3dFeatures", Cl3dShapeFeatures_CE}};
827  std::vector<tensorflow::Tensor> CNNmodel_CEoutputs;
828  tensorflow::run((globalCache()->CNNmodel_CEsession),
829  CNNmodel_CEinputList,
830  {"TauMinator_CE_conv/middleMan/concat"},
831  &CNNmodel_CEoutputs);
832  tensorflow::NamedTensorList DNN_CEinputsList = {{"middleMan", CNNmodel_CEoutputs[0]}};
833 
834  // Apply DNN for identification
835  std::vector<tensorflow::Tensor> DNN_CEoutputsIdent;
836  tensorflow::run((globalCache()->DNNident_CEsession),
837  DNN_CEinputsList,
838  {"TauMinator_CE_ident/sigmoid_IDout/Sigmoid"},
839  &DNN_CEoutputsIdent);
840 
841  // Apply DNN for calibration
842  std::vector<tensorflow::Tensor> DNN_CEoutputsCalib;
843  tensorflow::run((globalCache()->DNNcalib_CEsession),
844  DNN_CEinputsList,
845  {"TauMinator_CE_calib/LIN_DNNout/Relu"},
846  &DNN_CEoutputsCalib);
847 
848  // Fill the output collection of L1 taus with the endcap candidates
849  for (int clNxMIdx = 0; clNxMIdx < Nclusters_CE; clNxMIdx++) {
850  l1t::Tau l1Tau =
851  MakeTauCandidate(false, clNxMIdx, DNN_CEoutputsIdent, DNN_CEoutputsCalib, l1TowerClustersNxM_CE_pstn);
852  if (l1Tau.pt() < 0) {
853  continue;
854  }
855  L1NNCaloTauCollectionBXV->push_back(0, l1Tau);
856  }
857  }
858 
859  // Fill output
860  iEvent.put(std::move(L1NNCaloTauCollectionBXV), "L1NNCaloTauCollectionBXV");
861 
862 } // End of produce function
863 
864 template <class outPrecision, class inPrecision>
865 outPrecision L1NNCaloTauEmulator::dPhi(inPrecision iPhi_1, inPrecision iPhi_2) {
866  outPrecision dphi = iPhi_1 - iPhi_2;
867 
868  outPrecision dphi0 = dphi > outPrecision(INTPHI_PI) ? outPrecision(dphi - INTPHI_2PI) : dphi;
869  outPrecision dphi1 = dphi <= outPrecision(-INTPHI_PI) ? outPrecision(dphi + INTPHI_2PI) : dphi;
870 
871  outPrecision result = dphi > outPrecision(0) ? dphi0 : dphi1;
872 
873  return result;
874 }
875 
877  ap_int<12> mult = iEta_1 * iEta_2;
878  dIEtaPhi_t result = iEta_1 - iEta_2;
879  if (mult < 0) {
880  result = iEta_1 > 0 ? result - 1 : result + 1;
881  }
882 
883  return result;
884 }
885 
887  EtaPhi_t shiftediPhi_2 = iPhi_2 <= IPhi_t(36) ? EtaPhi_t(iPhi_2) : EtaPhi_t(iPhi_2 - INTPHI_2PI + 1);
888 
889  EtaPhi_t fineiPhi_2 = shiftediPhi_2 * (IETAPHI_LSB / ETAPHI_LSB);
890  // subrtaction of half rescaling corrects from edge to center of tower
891  fineiPhi_2 = fineiPhi_2 > EtaPhi_t(0) ? EtaPhi_t(fineiPhi_2 - (IETAPHI_LSB / ETAPHI_LSB) / 2)
892  : EtaPhi_t(fineiPhi_2 + (IETAPHI_LSB / ETAPHI_LSB) / 2);
893 
894  return dPhi<dEtaPhi_t, EtaPhi_t>(iPhi_1, fineiPhi_2);
895 }
896 
898  // change from hgcal frame to barrel-centered frame
899  EtaPhi_t framechangeCl3d = 303; // 303*pi/720 = 1.322
900  iEta_1 = iEta_1 > EtaPhi_t(0) ? EtaPhi_t(iEta_1 + framechangeCl3d) : EtaPhi_t(iEta_1 - framechangeCl3d);
901 
902  // the actual depth is 330 but 329 corrects for 0.0808 tower
903  EtaPhi_t barrelEtaDepth = 329;
904  EtaPhi_t fineiEta_2 = barrelEtaDepth + (iEta_2 - IETAHGCAL_OFFSET) * (IETAHGCAL_LSB / ETAPHI_LSB);
905 
906  return iEta_1 - fineiEta_2;
907 }
908 
910  IEta_t ieta = floor(eta / IETAHGCAL_LSB);
911  // +1 because flooring gets it 1 unit lower when negative
912  ieta = ieta < IEta_t(0) ? IEta_t(ieta + 1) : ieta;
913 
914  return ieta;
915 }
916 
918  phi = phi < 0 ? phi + 2 * M_PI : phi;
919 
920  // +1 because tower 0 does not exist
921  return floor(phi / IETAPHI_LSB) + 1;
922 }
923 
924 template <int W>
925 ap_int<W> L1NNCaloTauEmulator::ap_abs(ap_int<W> x) {
926  ap_int<W> result;
927  if (x < 0) {
928  result = -x;
929  } else {
930  result = x;
931  }
932 
933  return result;
934 }
935 
936 template <int W, int I, ap_q_mode _AP_Q, ap_o_mode _AP_O>
937 ap_ufixed<W, I> L1NNCaloTauEmulator::ap_abs(ap_fixed<W, I, _AP_Q, _AP_O> x) {
938  ap_ufixed<W, I> result;
939  if (x < 0) {
940  result = -x;
941  } else {
942  result = x;
943  }
944 
945  return result;
946 }
947 
948 float L1NNCaloTauEmulator::apfixedQuantizer(float inputF, float LSB, int nbits) {
949  return min(floor(inputF / LSB), float(pow(2, nbits) - 1)) * LSB;
950 }
951 
952 int L1NNCaloTauEmulator::apintQuantizer(float inputF, float LSB, int nbits) {
953  return min(floor(inputF / LSB), float(pow(2, nbits) - 1));
954 }
955 
956 float L1NNCaloTauEmulator::inputScaler(float inputF, std::string feature) {
957  float mean = (globalCache()->FeatScaler_CE).get_child(feature).get<float>("mean");
958  float std = (globalCache()->FeatScaler_CE).get_child(feature).get<float>("std");
959 
960  return (inputF - mean) / std;
961 }
962 
964  return eta > 0 ? eta - ETAHGCAL_OFFSET : eta + ETAHGCAL_OFFSET;
965 }
966 
967 float L1NNCaloTauEmulator::correctInputMeanzCl3d(float meanz) { return CM2MM * (abs(meanz) - MEANZ_OFFSET); }
968 
970  // transform eta of towers from integer to float, correcting for different barrel/endcap LSB
971  float feta;
972  if (abs(eta) > IETAHGCAL_OFFSET) {
973  if (eta > 0) {
975  (eta.to_float() - IETAHGCAL_OFFSET) * IETAHGCAL_LSB;
976  } else {
978  (eta.to_float() + IETAHGCAL_OFFSET) * IETAHGCAL_LSB;
979  }
980  } else {
981  feta = eta.to_float() * IETAPHI_LSB;
982  }
983 
984  // shift by half a tower to consider the tower center instead of the edge
985  return feta > 0 ? feta - IETAPHI_LSB / 2 : feta + IETAPHI_LSB / 2;
986 }
987 
989  float fphi = phi.to_float();
990  // add 2pi + 1 because tower 0 does not exist
991  fphi = fphi > INTPHI_PI ? fphi - INTPHI_2PI + 1 : fphi;
992  fphi *= IETAPHI_LSB;
993 
994  // shift by half a tower to consider the tower center instead of the edge
995  return fphi > 0 ? fphi - IETAPHI_LSB / 2 : fphi + IETAPHI_LSB / 2;
996 }
997 
999  bool isBarrel,
1000  int clNxMIdx,
1001  std::vector<tensorflow::Tensor> outputsIdent,
1002  std::vector<tensorflow::Tensor> outputsCalib,
1003  std::vector<L1NNCaloTauEmulator::InputTowerCluster_pstn> clustersNxM_pstn) {
1004  int seedIeta = clustersNxM_pstn[clNxMIdx].seedIeta;
1005  int seedIphi = clustersNxM_pstn[clNxMIdx].seedIphi;
1006 
1007  if (seedIeta > intEtaRestriction) {
1008  return l1t::Tau(reco::Candidate::PolarLorentzVector(-1, 0, 0, 0), -1, 0, 0, 0, 0);
1009  ;
1010  }
1011 
1012  float tau_IDscore = outputsIdent[0].matrix<float>()(0, clNxMIdx);
1013  float tau_calibPt = outputsCalib[0].matrix<float>()(0, clNxMIdx);
1014  float tau_eta = floatIEta(seedIeta);
1015  float tau_phi = floatIPhi(seedIphi);
1016 
1017  // Assign increasing quality to higher scoring candidates
1018  int quality = 0;
1019  if (isBarrel) {
1020  // 99% WP
1021  if (tau_IDscore > IdWp99_CB) {
1022  quality = 1;
1023  }
1024  // 95% WP
1025  if (tau_IDscore > IdWp95_CB) {
1026  quality = 2;
1027  }
1028  // 90% WP
1029  if (tau_IDscore > IdWp90_CB) {
1030  quality = 3;
1031  }
1032  } else {
1033  // 99% WP
1034  if (tau_IDscore > IdWp99_CE) {
1035  quality = 1;
1036  }
1037  // 95% WP
1038  if (tau_IDscore > IdWp95_CE) {
1039  quality = 2;
1040  }
1041  // 90% WP
1042  if (tau_IDscore > IdWp90_CE) {
1043  quality = 3;
1044  }
1045  }
1046 
1048 
1049  // store ID score multiplied by 10E4 to have good precision even using the Phase1 tau int iso format
1050  // (this is stored just in case for possible additional offline studies)
1051  // tau initialisation = (p4, pt, eta, phi, qual, iso)
1052  l1t::Tau l1Tau = l1t::Tau(tauP4, tau_calibPt, tau_eta, tau_phi, quality, tau_IDscore * 10E4);
1053  l1Tau.setTowerIEta(seedIeta);
1054  l1Tau.setTowerIPhi(seedIphi);
1055 
1056  return l1Tau;
1057 }
1058 
1061 
1062  desc.add<edm::InputTag>("l1CaloTowers", edm::InputTag("l1tEGammaClusterEmuProducer", "L1CaloTowerCollection"));
1063  desc.add<edm::InputTag>("hgcalTowers", edm::InputTag("l1tHGCalTowerProducer", "HGCalTowerProcessor"));
1064  desc.add<edm::InputTag>("HgcalClusters",
1065  edm::InputTag("l1tHGCalBackEndLayer2Producer", "HGCalBackendLayer2Processor3DClustering"));
1066 
1067  desc.add<std::string>("preEmId", "hOverE < 0.3 && hOverE >= 0");
1068  {
1070  psd0.add<bool>("isPUFilter", true);
1071  psd0.add<std::string>("preselection", "");
1072  psd0.add<std::string>("method", "BDT");
1073  {
1075  vpsd2.add<std::string>("name");
1076  vpsd2.add<std::string>("value");
1077  std::vector<edm::ParameterSet> temp2;
1078  temp2.reserve(5);
1079  {
1080  edm::ParameterSet temp3;
1081  temp3.addParameter<std::string>("name", "eMax");
1082  temp3.addParameter<std::string>("value", "eMax()");
1083  temp2.push_back(temp3);
1084  }
1085  {
1086  edm::ParameterSet temp3;
1087  temp3.addParameter<std::string>("name", "eMaxOverE");
1088  temp3.addParameter<std::string>("value", "eMax()/energy()");
1089  temp2.push_back(temp3);
1090  }
1091  {
1092  edm::ParameterSet temp3;
1093  temp3.addParameter<std::string>("name", "sigmaPhiPhiTot");
1094  temp3.addParameter<std::string>("value", "sigmaPhiPhiTot()");
1095  temp2.push_back(temp3);
1096  }
1097  {
1098  edm::ParameterSet temp3;
1099  temp3.addParameter<std::string>("name", "sigmaRRTot");
1100  temp3.addParameter<std::string>("value", "sigmaRRTot()");
1101  temp2.push_back(temp3);
1102  }
1103  {
1104  edm::ParameterSet temp3;
1105  temp3.addParameter<std::string>("name", "triggerCells90percent");
1106  temp3.addParameter<std::string>("value", "triggerCells90percent()");
1107  temp2.push_back(temp3);
1108  }
1109  psd0.addVPSet("variables", vpsd2, temp2);
1110  }
1111  psd0.add<std::string>(
1112  "weightsFile", "L1Trigger/Phase2L1ParticleFlow/data/hgcal_egID/Photon_Pion_vs_Neutrino_BDTweights_1116.xml.gz");
1113  psd0.add<std::string>("wp", "-0.10");
1114  desc.add<edm::ParameterSetDescription>("VsPuId", psd0);
1115  }
1116 
1117  desc.add<double>("EcalEtMinForClustering", 0.0);
1118  desc.add<double>("HcalEtMinForClustering", 0.0);
1119  desc.add<double>("EtMinForSeeding", 2.5);
1120  desc.add<double>("EtaRestriction", 2.4);
1121  desc.add<double>("CB_CE_split", 1.55);
1122  desc.add<double>("PuidThr", -0.1);
1123 
1124  desc.add<std::string>("CNNmodel_CB_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/v22/CNNmodel_CB.pb");
1125  desc.add<std::string>("DNNident_CB_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/v22/DNNident_CB.pb");
1126  desc.add<std::string>("DNNcalib_CB_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/v22/DNNcalib_CB.pb");
1127  desc.add<std::string>("CNNmodel_CE_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/v22/CNNmodel_CE.pb");
1128  desc.add<std::string>("DNNident_CE_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/v22/DNNident_CE.pb");
1129  desc.add<std::string>("DNNcalib_CE_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/v22/DNNcalib_CE.pb");
1130  desc.add<std::string>("FeatScaler_CE_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/Cl3dFeatScaler_CE.json");
1131 
1132  desc.add<double>("IdWp90_CB", 0.706);
1133  desc.add<double>("IdWp95_CB", 0.3432);
1134  desc.add<double>("IdWp99_CB", 0.0337);
1135  desc.add<double>("IdWp90_CE", 0.5711);
1136  desc.add<double>("IdWp95_CE", 0.2742);
1137  desc.add<double>("IdWp99_CE", 0.0394);
1138 
1139  desc.add<bool>("DEBUG", false);
1140 
1141  descriptions.add("l1tNNCaloTauEmulator", desc);
1142 }
1143 
boost::property_tree::ptree FeatScaler_CE
ap_int< IETAPHI_W > IEta_t
tensorflow::Session * CNNmodel_CEsession
tensorflow::GraphDef * DNNident_CB
edm::EDGetToken hgcalTowersToken
ap_uint< MEANZ_W > Meanz_t
std::vector< NamedTensor > NamedTensorList
Definition: TensorFlow.h:31
static constexpr int ID_I
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
tensorflow::GraphDef * CNNmodel_CB
static constexpr int CALIBPT_W
static constexpr int PUID_W
int apintQuantizer(float inputF, float LSB, int nbits)
outPrecision dPhi(inPrecision iPhi_1, inPrecision iPhi_2)
ParameterDescriptionBase * addVPSet(U const &iLabel, ParameterSetDescription const &validator, std::vector< ParameterSet > const &defaults)
static constexpr int ET_W
static void globalEndJob(const NNmodels_GlobalCache *)
StringCutObjectSelector< l1t::HGCalMulticluster > preEmId
double pt() const final
transverse momentum
static constexpr float MEANZ_LSB
static constexpr int INTPHI_PI
static constexpr int PT_W
GraphDef * loadGraphDef(const std::string &pbFile)
Definition: TensorFlow.cc:119
Definition: Tau.h:20
static constexpr int INTPHI_2PI
static constexpr int FINEINTPHI_2PI
edm::Handle< l1tp2::CaloTowerCollection > l1CaloTowerHandle
T const * product() const
Definition: Handle.h:70
static constexpr int SHOWLEN_W
static constexpr float ETAHGCAL_OFFSET
ap_ufixed< CALIBPT_W, CALIBPT_I, AP_TRN, AP_SAT > CalibPt_t
static constexpr int DETAPHI_W
tensorflow::Session * DNNident_CBsession
tensorflow::Session * DNNcalib_CEsession
static constexpr float MEANZ_OFFSET
delete x;
Definition: CaloConfig.h:22
float floatPuId(PUid_t pu)
static std::unique_ptr< NNmodels_GlobalCache > initializeGlobalCache(const edm::ParameterSet &)
scenario
Definition: constants.h:219
dEtaPhi_t tw2cl_dPhi(EtaPhi_t iPhi_1, IPhi_t iPhi_2)
static constexpr int MEANZ_W
void fill(SimpleHGCluster Cluster)
float floatEta(EtaPhi_t eta)
tensorflow::Session * DNNident_CEsession
float correctInputMeanzCl3d(float meanz)
BXVector< HGCalTower > HGCalTowerBxCollection
Definition: HGCalTower.h:10
static constexpr int SHAPEFEAT_W
string quality
static constexpr float IETAHGCAL_LSBp
ap_int< DIETAPHI_W > dIEtaPhi_t
int iEvent
Definition: GenABIO.cc:224
tensorflow::GraphDef * DNNcalib_CE
ap_int< DETAPHI_W > dEtaPhi_t
ap_ufixed< PT_W, PT_I, AP_TRN, AP_SAT > Pt_t
void addParameter(std::string const &name, T const &value)
Definition: ParameterSet.h:136
float floatSzz(ShapeFeat_t szz)
BXVector< HGCalMulticluster > HGCalMulticlusterBxCollection
void run(Session *session, const NamedTensorList &inputs, const std::vector< std::string > &outputNames, std::vector< Tensor > *outputs, const thread::ThreadPoolOptions &threadPoolOptions)
Definition: TensorFlow.cc:271
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
tensorflow::GraphDef * CNNmodel_CE
static constexpr float PTET_LSB
float inputScaler(float inputF, std::string feature)
#define DEFINE_FWK_MODULE(type)
Definition: MakerMacros.h:16
ap_int< ETAPHI_W > EtaPhi_t
IEta_t makeEndcapHwIEta(float eta)
static constexpr int ID_W
ParameterDescriptionBase * add(U const &iLabel, T const &value)
IPhi_t makeEndcapHwIPhi(float phi)
void produce(edm::Event &, const edm::EventSetup &) override
ap_int< W > ap_abs(ap_int< W > x)
dIEtaPhi_t tower_dIEta(IEta_t iEta_1, IEta_t iEta_2)
l1tpf::HGC3DClusterEgID VsPuId
static constexpr int CALIBPT_I
static constexpr int ET_I
#define M_PI
tensorflow::Session * DNNcalib_CBsession
Session * createSession()
Definition: TensorFlow.cc:136
float apfixedQuantizer(float inputF, float LSB, int nbits)
ap_ufixed< ID_W, ID_I, AP_TRN, AP_SAT > Id_t
Log< level::Info, false > LogInfo
edm::Handle< l1t::HGCalTowerBxCollection > hgcalTowersHandle
static constexpr float PUID_LSB
float correctInputEtaCl3d(float eta)
static constexpr int IETAPHI_W
static constexpr float SZZ_LSB
ap_uint< SHOWLEN_W > ShowLen_t
static constexpr int IETAHGCAL_OFFSET
static constexpr int R2cone
float floatIPhi(IPhi_t phi)
tensorflow::Session * CNNmodel_CBsession
static constexpr int FINEINTPHI_PI
static constexpr float CM2MM
double b
Definition: hdecay.h:120
void add(std::string const &label, ParameterSetDescription const &psetDescription)
edm::EDGetTokenT< l1t::HGCalMulticlusterBxCollection > HGClusterToken
float floatIEta(IEta_t eta)
l1t::Tau MakeTauCandidate(bool isBarrel, int clNxMIdx, std::vector< tensorflow::Tensor > outputsIdent, std::vector< tensorflow::Tensor > outputsCalib, std::vector< InputTowerCluster_pstn > clustersNxM_pstn)
static constexpr int DIETAPHI_W
static constexpr int PT_I
HLT enums.
tensorflow::GraphDef * DNNcalib_CB
float floatPhi(EtaPhi_t phi)
float floatShape(ShapeFeat_t shape)
double a
Definition: hdecay.h:121
ap_ufixed< ET_W, ET_I, AP_TRN, AP_SAT > Et_t
#define DEBUG
Definition: DMRChecker.cc:120
static constexpr float IETAPHI_LSB
ap_uint< SHAPEFEAT_W > ShapeFeat_t
static constexpr float SHAPEFEAT_LSB
float x
static constexpr float IETAHGCAL_LSB
L1NNCaloTauEmulator(const edm::ParameterSet &, const NNmodels_GlobalCache *)
const std::string & fullPath() const
Definition: FileInPath.cc:144
edm::Handle< l1t::HGCalMulticlusterBxCollection > HGClusterHandle
void fill(int idx, SimpleTowerHit Tower)
float floatMeanZ(Meanz_t meanz)
Log< level::Warning, false > LogWarning
static constexpr float ETAPHI_LSB
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
float passID(l1t::HGCalMulticluster c, l1t::PFCluster &cpf)
static constexpr int ETAPHI_W
tensorflow::GraphDef * DNNident_CE
dEtaPhi_t tw2cl_dEta(EtaPhi_t iEta_1, IEta_t iEta_2)
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
def move(src, dest)
Definition: eostools.py:511
ap_uint< IETAPHI_W > IPhi_t
float floatMeanZHgcalCoord(Meanz_t meanz)
edm::EDGetTokenT< l1tp2::CaloTowerCollection > l1TowersToken
math::PtEtaPhiMLorentzVector PolarLorentzVector
Lorentz vector.
Definition: Candidate.h:38