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  // Class for the towers info as they should be in GCT
248  public:
251  Et_t towerEm = 0.;
254  Et_t towerEt = 0.;
255  ap_uint<1> isBarrel = 0x1;
256  ap_uint<1> stale = 0x0;
257  ap_uint<1> stale4seed = 0x0;
258  };
259 
260  // Class for the clusters info as they should arrive from HGCAL
262  public:
273  ap_uint<1> stale = 0x0;
274  };
275 
276  // Classes for the tower clusters
278  public:
279  Et_t towerEm = 0.;
282 
283  void fill(SimpleTowerHit Tower) {
284  towerEm = Tower.towerEm;
285  towerHad = Tower.towerHad;
286  l1egTowerEt = Tower.l1egTowerEt;
287  }
288  };
289 
291  public:
293  ap_uint<1> barrelSeeded = 0x0;
294  ap_uint<1> filled[45];
295 
296  void fill(int idx, SimpleTowerHit Tower) {
297  towerHits[idx].fill(Tower);
298  filled[idx] = 0x1;
299  }
300 
301  void init() {
302  SimplifiedTower emptyT;
303  std::fill(towerHits, towerHits + 44, emptyT);
304  std::fill(filled, filled + 44, 0x0);
305  }
306  };
307 
309  public:
312 
313  void fill(SimpleTowerHit Tower) {
314  seedIeta = Tower.towerIeta;
315  seedIphi = Tower.towerIphi;
316  }
317  };
318 
319  // INFO : now variables are in GCT precision, they should be in NN precision
320  // after scaling, i.e. something like ap_fixed<16, 6, AP_TRN, AP_SAT>, when the
321  // full hls4ml emulation is available
323  public:
332 
333  void fill(SimpleHGCluster Cluster) {
334  pt = Cluster.pt;
335  eta = Cluster.eta;
336  showerlength = Cluster.showerlength;
338  spptot = Cluster.spptot;
339  szz = Cluster.szz;
340  srrtot = Cluster.srrtot;
341  meanz = Cluster.meanz;
342  }
343  };
344 
346  int clNxMIdx,
347  std::vector<tensorflow::Tensor> outputsIdent,
348  std::vector<tensorflow::Tensor> outputsCalib,
349  std::vector<InputTowerCluster_pstn> clustersNxM_pstn);
350 };
351 
352 /*
353 â–ˆâ–ˆâ–ˆâ–ˆâ–ˆâ–ˆâ–ˆâ–ˆ ██ ██ ██████ ████████ █████ ██ ██ ███ ███ ██ ███ ██ █████ ████████ ██████ ██████
354  ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ████ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██
355  ██ ███████ █████ ██ ███████ ██ ██ ██ ████ ██ ██ ██ ██ ██ ███████ ██ ██ ██ ██████
356  ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
357  ██ ██ ██ ██████ ██ ██ ██ ███████ ██ ██ ██ ██ ████ ██ ██ ██ ██████ ██ ██
358 */
359 
360 std::unique_ptr<NNmodels_GlobalCache> L1NNCaloTauEmulator::initializeGlobalCache(const edm::ParameterSet& iConfig) {
361  edm::LogInfo("Initialization") << "Init NN models Global Cache " << std::endl;
362 
363  std::unique_ptr<NNmodels_GlobalCache> GlobalCache(new NNmodels_GlobalCache);
364 
365  GlobalCache->CNNmodel_CB_path = iConfig.getParameter<std::string>("CNNmodel_CB_path");
366  GlobalCache->DNNident_CB_path = iConfig.getParameter<std::string>("DNNident_CB_path");
367  GlobalCache->DNNcalib_CB_path = iConfig.getParameter<std::string>("DNNcalib_CB_path");
368  GlobalCache->CNNmodel_CE_path = iConfig.getParameter<std::string>("CNNmodel_CE_path");
369  GlobalCache->DNNident_CE_path = iConfig.getParameter<std::string>("DNNident_CE_path");
370  GlobalCache->DNNcalib_CE_path = iConfig.getParameter<std::string>("DNNcalib_CE_path");
371  GlobalCache->FeatScaler_CE_path = iConfig.getParameter<std::string>("FeatScaler_CE_path");
372 
373  // Create sessions for Tensorflow inferece
374  (GlobalCache->CNNmodel_CB) = tensorflow::loadGraphDef(edm::FileInPath((GlobalCache->CNNmodel_CB_path)).fullPath());
375  (GlobalCache->CNNmodel_CBsession) = tensorflow::createSession((GlobalCache->CNNmodel_CB));
376 
377  (GlobalCache->DNNident_CB) = tensorflow::loadGraphDef(edm::FileInPath((GlobalCache->DNNident_CB_path)).fullPath());
378  (GlobalCache->DNNident_CBsession) = tensorflow::createSession((GlobalCache->DNNident_CB));
379 
380  (GlobalCache->DNNcalib_CB) = tensorflow::loadGraphDef(edm::FileInPath((GlobalCache->DNNcalib_CB_path)).fullPath());
381  (GlobalCache->DNNcalib_CBsession) = tensorflow::createSession((GlobalCache->DNNcalib_CB));
382 
383  (GlobalCache->CNNmodel_CE) = tensorflow::loadGraphDef(edm::FileInPath((GlobalCache->CNNmodel_CE_path)).fullPath());
384  (GlobalCache->CNNmodel_CEsession) = tensorflow::createSession((GlobalCache->CNNmodel_CE));
385 
386  (GlobalCache->DNNident_CE) = tensorflow::loadGraphDef(edm::FileInPath((GlobalCache->DNNident_CE_path)).fullPath());
387  (GlobalCache->DNNident_CEsession) = tensorflow::createSession((GlobalCache->DNNident_CE));
388 
389  (GlobalCache->DNNcalib_CE) = tensorflow::loadGraphDef(edm::FileInPath((GlobalCache->DNNcalib_CE_path)).fullPath());
390  (GlobalCache->DNNcalib_CEsession) = tensorflow::createSession((GlobalCache->DNNcalib_CE));
391 
392  // Read features scaler
393  boost::property_tree::read_json(edm::FileInPath((GlobalCache->FeatScaler_CE_path)).fullPath(),
394  (GlobalCache->FeatScaler_CE));
395 
396  return GlobalCache;
397 }
398 
399 // ----Constructor and Destructor -----
401  : l1TowersToken(consumes<l1tp2::CaloTowerCollection>(iConfig.getParameter<edm::InputTag>("l1CaloTowers"))),
402  hgcalTowersToken(consumes<l1t::HGCalTowerBxCollection>(iConfig.getParameter<edm::InputTag>("hgcalTowers"))),
403 
404  HGClusterToken(
405  consumes<l1t::HGCalMulticlusterBxCollection>(iConfig.getParameter<edm::InputTag>("HgcalClusters"))),
406  scenario(UseEmInterp::No),
407  preEmId(iConfig.getParameter<std::string>("preEmId")),
408  VsPuId(iConfig.getParameter<edm::ParameterSet>("VsPuId")),
409 
410  EcalEtMinForClustering(iConfig.getParameter<double>("EcalEtMinForClustering")),
411  HcalEtMinForClustering(iConfig.getParameter<double>("HcalEtMinForClustering")),
412  EtMinForSeeding(iConfig.getParameter<double>("EtMinForSeeding")),
413  EtaRestriction(iConfig.getParameter<double>("EtaRestriction")),
414  CB_CE_split(iConfig.getParameter<double>("CB_CE_split")),
415  PuidThr(iConfig.getParameter<double>("PuidThr")),
416 
417  IdWp90_CB(iConfig.getParameter<double>("IdWp90_CB")),
418  IdWp95_CB(iConfig.getParameter<double>("IdWp95_CB")),
419  IdWp99_CB(iConfig.getParameter<double>("IdWp99_CB")),
420 
421  IdWp90_CE(iConfig.getParameter<double>("IdWp90_CE")),
422  IdWp95_CE(iConfig.getParameter<double>("IdWp95_CE")),
423  IdWp99_CE(iConfig.getParameter<double>("IdWp99_CE")) {
424  // Initialize HGCAL BDTs
425  if (!VsPuId.method().empty()) {
427  }
428 
432 
433  // Create produced outputs
434  produces<BXVector<l1t::Tau>>("L1NNCaloTauCollectionBXV");
435 
436  // Settings output
437  edm::LogInfo("Settings") << "EtaRestriction = " << EtaRestriction << " (" << intEtaRestriction << ")"
438  << " , CB_CE_split = " << CB_CE_split << "(" << intCB_CE_split
439  << ") , EtMinForSeeding = " << EtMinForSeeding
440  << " , HcalTpEtMin = " << HcalEtMinForClustering
441  << " , EcalTpEtMin = " << EcalEtMinForClustering << " , PuidThr = " << PuidThr << "("
442  << intPuidThr << ")" << std::endl;
443 }
444 
446  // Output collection
447  std::unique_ptr<BXVector<l1t::Tau>> L1NNCaloTauCollectionBXV(new l1t::TauBxCollection);
448 
449  // Create and Fill collection of all calotowers and their attributes
450  std::vector<SimpleTowerHit> l1CaloTowers;
451 
453  int warnings = 0;
454  for (auto& hit : *l1CaloTowerHandle.product()) {
455  // Skip this weird towers and store warning
456  if (hit.towerIEta() == -1016 && hit.towerIPhi() == -962) {
457  warnings += 1;
458  continue;
459  }
460 
461  SimpleTowerHit l1Hit;
462  l1Hit.isBarrel = 0x1;
463  l1Hit.l1egTowerEt = apfixedQuantizer(hit.l1egTowerEt(), PTET_LSB, ET_W);
464  l1Hit.towerEm = apfixedQuantizer(hit.ecalTowerEt(), PTET_LSB, ET_W);
465  l1Hit.towerHad = apfixedQuantizer(hit.hcalTowerEt(), PTET_LSB, ET_W);
466  l1Hit.towerEt = apfixedQuantizer(hit.ecalTowerEt() + hit.hcalTowerEt() + hit.l1egTowerEt(), PTET_LSB, ET_W);
467  l1Hit.towerIeta = hit.towerIEta();
468  l1Hit.towerIphi = hit.towerIPhi();
469 
470  l1CaloTowers.push_back(l1Hit);
471  }
472  if (warnings != 0) {
473  edm::LogWarning("BrokenTowers") << " ** WARNING : FOUND " << warnings
474  << " TOWERS WITH towerIeta=-1016 AND towerIphi=-962" << std::endl;
475  }
476 
478  for (auto& hit : *hgcalTowersHandle.product()) {
479  SimpleTowerHit l1Hit;
480  l1Hit.isBarrel = 0x0;
481  l1Hit.l1egTowerEt = 0.0;
482  l1Hit.towerEm = apfixedQuantizer(hit.etEm(), PTET_LSB, ET_W);
483  l1Hit.towerHad = apfixedQuantizer(hit.etHad(), PTET_LSB, ET_W);
484  l1Hit.towerEt = apfixedQuantizer(hit.etEm() + hit.etHad(), PTET_LSB, ET_W);
485  l1Hit.towerIeta = makeEndcapHwIEta(hit.eta());
486  l1Hit.towerIphi = makeEndcapHwIPhi(hit.phi());
487 
488  l1CaloTowers.push_back(l1Hit);
489  }
490 
491  // Sort the ECAL+HCAL+L1EGs tower sums based on total ET
493  return a.towerEt > b.towerEt;
494  });
495 
496  // Create and Fill the collection of 3D clusters and their attributes
497  std::vector<SimpleHGCluster> AllHGClusters;
499 
500  for (auto cl3dIt = HGClusterHandle->begin(0); cl3dIt != HGClusterHandle->end(0); ++cl3dIt) {
501  auto& cl3d = *cl3dIt;
502 
503  // Implement cl3d PU ID as done in
504  // https://github.com/cms-sw/cmssw/blob/master/L1Trigger/Phase2L1ParticleFlow/plugins/PFClusterProducerFromHGC3DClusters.cc#L120
505  bool isEM = preEmId(*cl3dIt);
506  l1t::PFCluster cluster(cl3d.pt(), cl3d.eta(), cl3d.phi(), cl3d.hOverE());
507  if (scenario == UseEmInterp::EmOnly) // for emID objs, use EM interp as pT and set H = 0
508  {
509  if (isEM) {
510  float pt_new = cl3d.iPt(l1t::HGCalMulticluster::EnergyInterpretation::EM);
511  float hoe_new = 0.;
512  cluster = l1t::PFCluster(pt_new, cl3d.eta(), cl3d.phi(), hoe_new, isEM);
513  }
514  } else if (scenario == UseEmInterp::AllKeepHad) // for all objs, replace EM part with EM interp, preserve H
515  {
516  float had_old = cl3d.pt() - cluster.emEt();
517  float em_new = cl3d.iPt(l1t::HGCalMulticluster::EnergyInterpretation::EM);
518  float pt_new = had_old + em_new;
519  float hoe_new = em_new > 0 ? (had_old / em_new) : -1;
520  cluster = l1t::PFCluster(pt_new, cl3d.eta(), cl3d.phi(), hoe_new, isEM);
521  } else if (scenario == UseEmInterp::AllKeepTot) // for all objs, replace EM part with EM interp, preserve pT
522  {
523  float em_new = cl3d.iPt(l1t::HGCalMulticluster::EnergyInterpretation::EM);
524  float hoe_new = em_new > 0 ? (cl3d.pt() / em_new - 1) : -1;
525  cluster = l1t::PFCluster(cl3d.pt(), cl3d.eta(), cl3d.phi(), hoe_new, isEM);
526  }
527 
528  float idScore = -1.;
529  if (!VsPuId.method().empty()) {
530  idScore = VsPuId.passID(*cl3dIt, cluster);
531  idScore = cluster.egVsPUMVAOut();
532  }
533 
534  float eta_hgcalCoord = correctInputEtaCl3d(cl3d.eta());
535  float meanz_hgcalCoord = correctInputMeanzCl3d(cl3d.zBarycenter());
536 
537  SimpleHGCluster HGCluster;
538  HGCluster.pt = apfixedQuantizer(cl3d.pt(), PTET_LSB, PT_W);
539  HGCluster.eta = apintQuantizer(eta_hgcalCoord, ETAPHI_LSB, ETAPHI_W);
540  HGCluster.phi = apintQuantizer(cl3d.phi(), ETAPHI_LSB, ETAPHI_W);
541  HGCluster.showerlength = cl3d.showerLength();
542  HGCluster.coreshowerlength = cl3d.coreShowerLength();
543  HGCluster.spptot = apintQuantizer(cl3d.sigmaPhiPhiTot(), SHAPEFEAT_LSB, SHAPEFEAT_W);
544  HGCluster.szz = apintQuantizer(cl3d.sigmaZZ(), SZZ_LSB, SHAPEFEAT_W);
545  HGCluster.srrtot = apintQuantizer(cl3d.sigmaRRTot(), SHAPEFEAT_LSB, SHAPEFEAT_W);
546  HGCluster.meanz = apintQuantizer(meanz_hgcalCoord, MEANZ_LSB, MEANZ_W);
547  HGCluster.PUid = apintQuantizer(idScore, PUID_LSB, PUID_W);
548 
549  AllHGClusters.push_back(HGCluster);
550  }
551 
552  // Order the collection in pt (the input to the GCT will be pt ordered)
553  std::sort(begin(AllHGClusters), end(AllHGClusters), [](const SimpleHGCluster& a, SimpleHGCluster& b) {
554  return a.pt > b.pt;
555  });
556 
557  /*
558  // END OF SOFTWARE PRECISION SECTION
559  // up to here treated inputs from simulation with SW precision
560  // to massage them into the HW precision varibales as they are
561  // forseen (roughly) to be available at the GCT Sum card level
562  // ------------------------------------------------------------- */
563 
564  // Make NxM TowerClusters and HGClusters collections for TauMinator
565  std::vector<InputTowerCluster> l1TowerClustersNxM_CB;
566  std::vector<InputTowerCluster_pstn> l1TowerClustersNxM_CB_pstn;
567  std::vector<InputTowerCluster> l1TowerClustersNxM_CE;
568  std::vector<InputTowerCluster_pstn> l1TowerClustersNxM_CE_pstn;
569  std::vector<InputHGCluster> HGClusters;
570 
571  // Supporting collection of endcap clusters before cl3d matching
572  std::vector<InputTowerCluster> AllL1TowerClustersNxM_CE;
573  std::vector<InputTowerCluster_pstn> AllL1TowerClustersNxM_CE_pstn;
574 
575  int Nclusters_CB = 0;
576  int AllNclusters_CE = 0;
577  bool caloTauSeedingFinished = false;
578  // Loop for seeding of clNxM objects
579  while (!caloTauSeedingFinished) {
580  InputTowerCluster clNxM;
581  clNxM.init();
582  InputTowerCluster_pstn clNxM_pstn;
583  bool seeded = false;
584 
585  for (auto& l1CaloTower : l1CaloTowers) {
586  // Skip seeding in towers that would make the cluster extend in HF
587  // Skip l1CaloTowers which are already used by this clusters' mask
588  if (ap_abs(l1CaloTower.towerIeta) > Eta_limit || ap_abs(l1CaloTower.towerIeta) > intEtaRestriction ||
589  l1CaloTower.stale4seed) {
590  continue;
591  }
592 
593  // If not seded do the seeding
594  if (!seeded) {
595  // The leading unused tower has ET < min, stop jet clustering
596  if (l1CaloTower.towerEt < EtMinForSeeding) {
597  caloTauSeedingFinished = true;
598  continue;
599  }
600 
601  clNxM.fill(seedIdx, l1CaloTower);
602  clNxM_pstn.fill(l1CaloTower);
603  if (l1CaloTower.isBarrel) {
604  clNxM.barrelSeeded = 0x1;
605  }
606 
607  l1CaloTower.stale4seed = 0x1;
608  l1CaloTower.stale = 0x1;
609  seeded = true;
610 
611  continue;
612  }
613 
614  dIEtaPhi_t d_iEta = tower_dIEta(l1CaloTower.towerIeta, clNxM_pstn.seedIeta);
615  dIEtaPhi_t d_iPhi = dPhi<dIEtaPhi_t, IPhi_t>(l1CaloTower.towerIphi, clNxM_pstn.seedIphi);
616 
617  // Stale tower for seeding if it would lead to overalp between clusters
618  if ((ap_abs(d_iEta) <= IEta_dim - 1 && ap_abs(d_iPhi) <= IPhi_dim - 1)) {
619  l1CaloTower.stale4seed = 0x1;
620  }
621 
622  } // End for loop over TPs
623 
624  // Pushback seeds split in barrel and endcap
625  if (seeded) {
626  if (ap_abs(clNxM_pstn.seedIeta) <= intCB_CE_split) {
627  l1TowerClustersNxM_CB.push_back(clNxM);
628  l1TowerClustersNxM_CB_pstn.push_back(clNxM_pstn);
629  Nclusters_CB++;
630  } else {
631  AllL1TowerClustersNxM_CE.push_back(clNxM);
632  AllL1TowerClustersNxM_CE_pstn.push_back(clNxM_pstn);
633  AllNclusters_CE++;
634  }
635  }
636 
637  } // End while loop of TowerClusters seeding
638 
639  // Loop for barrel NxM TowerClusters clustering starting from the seeds
640  for (int clNxMIdx = 0; clNxMIdx < Nclusters_CB; clNxMIdx++) {
641  for (auto& l1CaloTower : l1CaloTowers) {
642  // Skip l1CaloTowers which are already used
643  if (l1CaloTower.stale) {
644  continue;
645  }
646 
647  dIEtaPhi_t d_iEta = tower_dIEta(l1CaloTower.towerIeta, l1TowerClustersNxM_CB_pstn[clNxMIdx].seedIeta);
648  dIEtaPhi_t d_iPhi =
649  dPhi<dIEtaPhi_t, IPhi_t>(l1CaloTower.towerIphi, l1TowerClustersNxM_CB_pstn[clNxMIdx].seedIphi);
650  int hitIdx = d_iEta * 9 + d_iPhi + seedIdx;
651 
652  // Cluster all towers in a NxM towers mask
653  if ((ap_abs(d_iEta) <= (IEta_dim - 1) / 2 && ap_abs(d_iPhi) <= (IPhi_dim - 1) / 2)) {
654  l1TowerClustersNxM_CB[clNxMIdx].fill(hitIdx, l1CaloTower);
655  l1CaloTower.stale = 0x1;
656  }
657 
658  } // End for loop over TPs
659 
660  } // End while loop of barrel TowerClusters creation
661 
662  // In the endcap cross-loop over clNxM and cl3d to match them
663  // (we can do it before full clustering just using the seed info)
664  int Nclusters_CE = 0;
665  for (int clNxMIdx = 0; clNxMIdx < AllNclusters_CE; clNxMIdx++) {
666  bool matched = false;
667  for (auto& HGCluster : AllHGClusters) {
668  // In case the clNxM or HGCluster have already been matched just continue through the list to the end
669  // only use cl3ds above 4GeV and above -0.10 pu id
670  if (matched || HGCluster.stale || HGCluster.pt < Pt_t(4.) || HGCluster.PUid < intPuidThr) {
671  continue;
672  }
673 
674  dEtaPhi_t d_iEta = tw2cl_dEta(HGCluster.eta, AllL1TowerClustersNxM_CE_pstn[clNxMIdx].seedIeta);
675  dEtaPhi_t d_iPhi = tw2cl_dPhi(HGCluster.phi, AllL1TowerClustersNxM_CE_pstn[clNxMIdx].seedIphi);
676  matched = d_iEta * d_iEta + d_iPhi * d_iPhi < R2cone;
677 
678  if (matched) {
679  HGCluster.stale = 0x1;
680  InputHGCluster cl3d;
681  cl3d.fill(HGCluster);
682  HGClusters.push_back(cl3d);
683  l1TowerClustersNxM_CE.push_back(AllL1TowerClustersNxM_CE[clNxMIdx]);
684  l1TowerClustersNxM_CE_pstn.push_back(AllL1TowerClustersNxM_CE_pstn[clNxMIdx]);
685  Nclusters_CE++;
686  }
687 
688  } // End for loop over cl3ds
689 
690  } // End for loop over clNxM
691 
692  // Loop for endcap matched NxM TowerClusters clustering starting from the seeds just found
693  for (int clNxMIdx = 0; clNxMIdx < Nclusters_CE; clNxMIdx++) {
694  for (auto& l1CaloTower : l1CaloTowers) {
695  // Skip l1CaloTowers which are already used
696  if (l1CaloTower.stale) {
697  continue;
698  }
699 
700  dIEtaPhi_t d_iEta = tower_dIEta(l1CaloTower.towerIeta, l1TowerClustersNxM_CE_pstn[clNxMIdx].seedIeta);
701  dIEtaPhi_t d_iPhi =
702  dPhi<dIEtaPhi_t, IPhi_t>(l1CaloTower.towerIphi, l1TowerClustersNxM_CE_pstn[clNxMIdx].seedIphi);
703  int hitIdx = d_iEta * 9 + d_iPhi + seedIdx;
704 
705  // Cluster all towers in a NxM towers mask
706  if ((ap_abs(d_iEta) <= (IEta_dim - 1) / 2 && ap_abs(d_iPhi) <= (IPhi_dim - 1) / 2)) {
707  l1TowerClustersNxM_CE[clNxMIdx].fill(hitIdx, l1CaloTower);
708  l1CaloTower.stale = 0x1;
709  }
710 
711  } // End for loop over TPs
712 
713  } // End while loop of barrel TowerClusters creation
714 
715  // Barrel TauMinator application
717  int batchSize_CB = (int)(Nclusters_CB);
718  tensorflow::TensorShape imageShape_CB({batchSize_CB, IEta_dim, IPhi_dim, 2});
719  tensorflow::TensorShape positionShape_CB({batchSize_CB, 2});
720  tensorflow::Tensor TowerClusterImage_CB(tensorflow::DT_FLOAT, imageShape_CB);
721  tensorflow::Tensor TowerClusterPosition_CB(tensorflow::DT_FLOAT, positionShape_CB);
722 
723  for (int clNxMIdx = 0; clNxMIdx < Nclusters_CB; clNxMIdx++) {
724  // Fill inputs for Tensorflow inference
725  for (int eta = 0; eta < IEta_dim; ++eta) {
726  for (int phi = 0; phi < IPhi_dim; ++phi) {
727  int towerIdx = eta * IPhi_dim + phi;
728  TowerClusterImage_CB.tensor<float, 4>()(clNxMIdx, eta, phi, 0) =
729  (l1TowerClustersNxM_CB[clNxMIdx].towerHits[towerIdx].l1egTowerEt.to_float() +
730  l1TowerClustersNxM_CB[clNxMIdx].towerHits[towerIdx].towerEm.to_float());
731  TowerClusterImage_CB.tensor<float, 4>()(clNxMIdx, eta, phi, 1) =
732  (l1TowerClustersNxM_CB[clNxMIdx].towerHits[towerIdx].towerHad.to_float());
733  }
734  }
735 
736  TowerClusterPosition_CB.tensor<float, 2>()(clNxMIdx, 0) = floatIEta(l1TowerClustersNxM_CB_pstn[clNxMIdx].seedIeta);
737  TowerClusterPosition_CB.tensor<float, 2>()(clNxMIdx, 1) = floatIPhi(l1TowerClustersNxM_CB_pstn[clNxMIdx].seedIphi);
738  }
739 
740  if (batchSize_CB >
741  0) // from CMSSW_14_0_X tensorflow does not seem to be able to deal with a tensor of dimension 0 anymore
742  {
743  // Apply CNN model
744  tensorflow::NamedTensorList CNNmodel_CBinputList = {{"TowerClusterImage", TowerClusterImage_CB},
745  {"TowerClusterPosition", TowerClusterPosition_CB}};
746  std::vector<tensorflow::Tensor> CNNmodel_CBoutputs;
747  tensorflow::run((globalCache()->CNNmodel_CBsession),
748  CNNmodel_CBinputList,
749  {"TauMinator_CB_conv/middleMan/concat"},
750  &CNNmodel_CBoutputs);
751  tensorflow::NamedTensorList DNN_CBinputsList = {{"middleMan", CNNmodel_CBoutputs[0]}};
752 
753  // Apply DNN for identification
754  std::vector<tensorflow::Tensor> DNN_CBoutputsIdent;
755  tensorflow::run((globalCache()->DNNident_CBsession),
756  DNN_CBinputsList,
757  {"TauMinator_CB_ident/sigmoid_IDout/Sigmoid"},
758  &DNN_CBoutputsIdent);
759 
760  // Apply DNN for calibration
761  std::vector<tensorflow::Tensor> DNN_CBoutputsCalib;
762  tensorflow::run((globalCache()->DNNcalib_CBsession),
763  DNN_CBinputsList,
764  {"TauMinator_CB_calib/DNNout/MatMul"},
765  &DNN_CBoutputsCalib);
766 
767  // Fill the output collection of L1 taus with the barrel candidates
768  for (int clNxMIdx = 0; clNxMIdx < Nclusters_CB; clNxMIdx++) {
769  l1t::Tau l1Tau =
770  MakeTauCandidate(true, clNxMIdx, DNN_CBoutputsIdent, DNN_CBoutputsCalib, l1TowerClustersNxM_CB_pstn);
771  if (l1Tau.pt() < 0) {
772  continue;
773  }
774  L1NNCaloTauCollectionBXV->push_back(0, l1Tau);
775  }
776  }
777 
778  // Endcap TauMinator application
779  int batchSize_CE = (int)(Nclusters_CE);
780  tensorflow::TensorShape imageShape_CE({batchSize_CE, IEta_dim, IPhi_dim, 2});
781  tensorflow::TensorShape positionShape_CE({batchSize_CE, 2});
782  tensorflow::TensorShape cl3dfeatShape_CE({batchSize_CE, 8});
783  tensorflow::Tensor TowerClusterImage_CE(tensorflow::DT_FLOAT, imageShape_CE);
784  tensorflow::Tensor TowerClusterPosition_CE(tensorflow::DT_FLOAT, positionShape_CE);
785  tensorflow::Tensor Cl3dShapeFeatures_CE(tensorflow::DT_FLOAT, cl3dfeatShape_CE);
786 
787  for (int clNxMIdx = 0; clNxMIdx < Nclusters_CE; clNxMIdx++) {
788  // Indexing of cl3ds is the same as the one of clNxMs
789  InputHGCluster HGClu = HGClusters[clNxMIdx];
790 
791  // Fill inputs for Tensorflow inference
792  for (int eta = 0; eta < IEta_dim; ++eta) {
793  for (int phi = 0; phi < IPhi_dim; ++phi) {
794  int towerIdx = eta * IPhi_dim + phi;
795  TowerClusterImage_CE.tensor<float, 4>()(clNxMIdx, eta, phi, 0) =
796  (l1TowerClustersNxM_CE[clNxMIdx].towerHits[towerIdx].l1egTowerEt.to_float() +
797  l1TowerClustersNxM_CE[clNxMIdx].towerHits[towerIdx].towerEm.to_float());
798  TowerClusterImage_CE.tensor<float, 4>()(clNxMIdx, eta, phi, 1) =
799  (l1TowerClustersNxM_CE[clNxMIdx].towerHits[towerIdx].towerHad.to_float());
800  }
801  }
802 
803  TowerClusterPosition_CE.tensor<float, 2>()(clNxMIdx, 0) = floatIEta(l1TowerClustersNxM_CE_pstn[clNxMIdx].seedIeta);
804  TowerClusterPosition_CE.tensor<float, 2>()(clNxMIdx, 1) = floatIPhi(l1TowerClustersNxM_CE_pstn[clNxMIdx].seedIphi);
805 
806  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 0) = inputScaler(HGClu.pt.to_float(), "pt");
807  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 1) = inputScaler(abs(floatEta(HGClu.eta)), "eta");
808  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 2) = inputScaler(HGClu.showerlength.to_float(), "showerlength");
809  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 3) =
810  inputScaler(HGClu.coreshowerlength.to_float(), "coreshowerlength");
811  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 4) = inputScaler(floatShape(HGClu.spptot), "spptot");
812  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 5) = inputScaler(floatSzz(HGClu.szz), "szz");
813  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 6) = inputScaler(floatShape(HGClu.srrtot), "srrtot");
814  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 7) = inputScaler(floatMeanZHgcalCoord(HGClu.meanz), "meanz");
815  }
816 
817  if (batchSize_CE >
818  0) // from CMSSW_14_0_X tensorflow does not seem to be able to deal with a tensor of dimension 0 anymore
819  {
820  // Apply CNN model
821  tensorflow::NamedTensorList CNNmodel_CEinputList = {{"TowerClusterImage", TowerClusterImage_CE},
822  {"TowerClusterPosition", TowerClusterPosition_CE},
823  {"AssociatedCl3dFeatures", Cl3dShapeFeatures_CE}};
824  std::vector<tensorflow::Tensor> CNNmodel_CEoutputs;
825  tensorflow::run((globalCache()->CNNmodel_CEsession),
826  CNNmodel_CEinputList,
827  {"TauMinator_CE_conv/middleMan/concat"},
828  &CNNmodel_CEoutputs);
829  tensorflow::NamedTensorList DNN_CEinputsList = {{"middleMan", CNNmodel_CEoutputs[0]}};
830 
831  // Apply DNN for identification
832  std::vector<tensorflow::Tensor> DNN_CEoutputsIdent;
833  tensorflow::run((globalCache()->DNNident_CEsession),
834  DNN_CEinputsList,
835  {"TauMinator_CE_ident/sigmoid_IDout/Sigmoid"},
836  &DNN_CEoutputsIdent);
837 
838  // Apply DNN for calibration
839  std::vector<tensorflow::Tensor> DNN_CEoutputsCalib;
840  tensorflow::run((globalCache()->DNNcalib_CEsession),
841  DNN_CEinputsList,
842  {"TauMinator_CE_calib/LIN_DNNout/Relu"},
843  &DNN_CEoutputsCalib);
844 
845  // Fill the output collection of L1 taus with the endcap candidates
846  for (int clNxMIdx = 0; clNxMIdx < Nclusters_CE; clNxMIdx++) {
847  l1t::Tau l1Tau =
848  MakeTauCandidate(false, clNxMIdx, DNN_CEoutputsIdent, DNN_CEoutputsCalib, l1TowerClustersNxM_CE_pstn);
849  if (l1Tau.pt() < 0) {
850  continue;
851  }
852  L1NNCaloTauCollectionBXV->push_back(0, l1Tau);
853  }
854  }
855 
856  // Fill output
857  iEvent.put(std::move(L1NNCaloTauCollectionBXV), "L1NNCaloTauCollectionBXV");
858 
859 } // End of produce function
860 
861 template <class outPrecision, class inPrecision>
862 outPrecision L1NNCaloTauEmulator::dPhi(inPrecision iPhi_1, inPrecision iPhi_2) {
863  outPrecision dphi = iPhi_1 - iPhi_2;
864 
865  outPrecision dphi0 = dphi > outPrecision(INTPHI_PI) ? outPrecision(dphi - INTPHI_2PI) : dphi;
866  outPrecision dphi1 = dphi <= outPrecision(-INTPHI_PI) ? outPrecision(dphi + INTPHI_2PI) : dphi;
867 
868  outPrecision result = dphi > outPrecision(0) ? dphi0 : dphi1;
869 
870  return result;
871 }
872 
874  ap_int<12> mult = iEta_1 * iEta_2;
875  dIEtaPhi_t result = iEta_1 - iEta_2;
876  if (mult < 0) {
877  result = iEta_1 > 0 ? result - 1 : result + 1;
878  }
879 
880  return result;
881 }
882 
884  EtaPhi_t shiftediPhi_2 = iPhi_2 <= IPhi_t(36) ? EtaPhi_t(iPhi_2) : EtaPhi_t(iPhi_2 - INTPHI_2PI + 1);
885 
886  EtaPhi_t fineiPhi_2 = shiftediPhi_2 * (IETAPHI_LSB / ETAPHI_LSB);
887  // subrtaction of half rescaling corrects from edge to center of tower
888  fineiPhi_2 = fineiPhi_2 > EtaPhi_t(0) ? EtaPhi_t(fineiPhi_2 - (IETAPHI_LSB / ETAPHI_LSB) / 2)
889  : EtaPhi_t(fineiPhi_2 + (IETAPHI_LSB / ETAPHI_LSB) / 2);
890 
891  return dPhi<dEtaPhi_t, EtaPhi_t>(iPhi_1, fineiPhi_2);
892 }
893 
895  // change from hgcal frame to barrel-centered frame
896  EtaPhi_t framechangeCl3d = 303; // 303*pi/720 = 1.322
897  iEta_1 = iEta_1 > EtaPhi_t(0) ? EtaPhi_t(iEta_1 + framechangeCl3d) : EtaPhi_t(iEta_1 - framechangeCl3d);
898 
899  // the actual depth is 330 but 329 corrects for 0.0808 tower
900  EtaPhi_t barrelEtaDepth = 329;
901  EtaPhi_t fineiEta_2 = barrelEtaDepth + (iEta_2 - IETAHGCAL_OFFSET) * (IETAHGCAL_LSB / ETAPHI_LSB);
902 
903  return iEta_1 - fineiEta_2;
904 }
905 
907  IEta_t ieta = floor(eta / IETAHGCAL_LSB);
908  // +1 because flooring gets it 1 unit lower when negative
909  ieta = ieta < IEta_t(0) ? IEta_t(ieta + 1) : ieta;
910 
911  return ieta;
912 }
913 
915  phi = phi < 0 ? phi + 2 * M_PI : phi;
916 
917  // +1 because tower 0 does not exist
918  return floor(phi / IETAPHI_LSB) + 1;
919 }
920 
921 template <int W>
922 ap_int<W> L1NNCaloTauEmulator::ap_abs(ap_int<W> x) {
923  ap_int<W> result;
924  if (x < 0) {
925  result = -x;
926  } else {
927  result = x;
928  }
929 
930  return result;
931 }
932 
933 template <int W, int I, ap_q_mode _AP_Q, ap_o_mode _AP_O>
934 ap_ufixed<W, I> L1NNCaloTauEmulator::ap_abs(ap_fixed<W, I, _AP_Q, _AP_O> x) {
935  ap_ufixed<W, I> result;
936  if (x < 0) {
937  result = -x;
938  } else {
939  result = x;
940  }
941 
942  return result;
943 }
944 
945 float L1NNCaloTauEmulator::apfixedQuantizer(float inputF, float LSB, int nbits) {
946  return min(floor(inputF / LSB), float(pow(2, nbits) - 1)) * LSB;
947 }
948 
949 int L1NNCaloTauEmulator::apintQuantizer(float inputF, float LSB, int nbits) {
950  return min(floor(inputF / LSB), float(pow(2, nbits) - 1));
951 }
952 
953 float L1NNCaloTauEmulator::inputScaler(float inputF, std::string feature) {
954  float mean = (globalCache()->FeatScaler_CE).get_child(feature).get<float>("mean");
955  float std = (globalCache()->FeatScaler_CE).get_child(feature).get<float>("std");
956 
957  return (inputF - mean) / std;
958 }
959 
961  return eta > 0 ? eta - ETAHGCAL_OFFSET : eta + ETAHGCAL_OFFSET;
962 }
963 
964 float L1NNCaloTauEmulator::correctInputMeanzCl3d(float meanz) { return CM2MM * (abs(meanz) - MEANZ_OFFSET); }
965 
967  // transform eta of towers from integer to float, correcting for different barrel/endcap LSB
968  float feta;
969  if (abs(eta) > IETAHGCAL_OFFSET) {
970  if (eta > 0) {
972  (eta.to_float() - IETAHGCAL_OFFSET) * IETAHGCAL_LSB;
973  } else {
975  (eta.to_float() + IETAHGCAL_OFFSET) * IETAHGCAL_LSB;
976  }
977  } else {
978  feta = eta.to_float() * IETAPHI_LSB;
979  }
980 
981  // shift by half a tower to consider the tower center instead of the edge
982  return feta > 0 ? feta - IETAPHI_LSB / 2 : feta + IETAPHI_LSB / 2;
983 }
984 
986  float fphi = phi.to_float();
987  // add 2pi + 1 because tower 0 does not exist
988  fphi = fphi > INTPHI_PI ? fphi - INTPHI_2PI + 1 : fphi;
989  fphi *= IETAPHI_LSB;
990 
991  // shift by half a tower to consider the tower center instead of the edge
992  return fphi > 0 ? fphi - IETAPHI_LSB / 2 : fphi + IETAPHI_LSB / 2;
993 }
994 
996  bool isBarrel,
997  int clNxMIdx,
998  std::vector<tensorflow::Tensor> outputsIdent,
999  std::vector<tensorflow::Tensor> outputsCalib,
1000  std::vector<L1NNCaloTauEmulator::InputTowerCluster_pstn> clustersNxM_pstn) {
1001  int seedIeta = clustersNxM_pstn[clNxMIdx].seedIeta;
1002  int seedIphi = clustersNxM_pstn[clNxMIdx].seedIphi;
1003 
1004  if (seedIeta > intEtaRestriction) {
1005  return l1t::Tau(reco::Candidate::PolarLorentzVector(-1, 0, 0, 0), -1, 0, 0, 0, 0);
1006  ;
1007  }
1008 
1009  float tau_IDscore = outputsIdent[0].matrix<float>()(0, clNxMIdx);
1010  float tau_calibPt = outputsCalib[0].matrix<float>()(0, clNxMIdx);
1011  float tau_eta = floatIEta(seedIeta);
1012  float tau_phi = floatIPhi(seedIphi);
1013 
1014  // Assign increasing quality to higher scoring candidates
1015  int quality = 0;
1016  if (isBarrel) {
1017  // 99% WP
1018  if (tau_IDscore > IdWp99_CB) {
1019  quality = 1;
1020  }
1021  // 95% WP
1022  if (tau_IDscore > IdWp95_CB) {
1023  quality = 2;
1024  }
1025  // 90% WP
1026  if (tau_IDscore > IdWp90_CB) {
1027  quality = 3;
1028  }
1029  } else {
1030  // 99% WP
1031  if (tau_IDscore > IdWp99_CE) {
1032  quality = 1;
1033  }
1034  // 95% WP
1035  if (tau_IDscore > IdWp95_CE) {
1036  quality = 2;
1037  }
1038  // 90% WP
1039  if (tau_IDscore > IdWp90_CE) {
1040  quality = 3;
1041  }
1042  }
1043 
1045 
1046  // store ID score multiplied by 10E4 to have good precision even using the Phase1 tau int iso format
1047  // (this is stored just in case for possible additional offline studies)
1048  // tau initialisation = (p4, pt, eta, phi, qual, iso)
1049  l1t::Tau l1Tau = l1t::Tau(tauP4, tau_calibPt, tau_eta, tau_phi, quality, tau_IDscore * 10E4);
1050  l1Tau.setTowerIEta(seedIeta);
1051  l1Tau.setTowerIPhi(seedIphi);
1052 
1053  return l1Tau;
1054 }
1055 
1058 
1059  desc.add<edm::InputTag>("l1CaloTowers", edm::InputTag("l1tEGammaClusterEmuProducer", "L1CaloTowerCollection"));
1060  desc.add<edm::InputTag>("hgcalTowers", edm::InputTag("l1tHGCalTowerProducer", "HGCalTowerProcessor"));
1061  desc.add<edm::InputTag>("HgcalClusters",
1062  edm::InputTag("l1tHGCalBackEndLayer2Producer", "HGCalBackendLayer2Processor3DClustering"));
1063 
1064  desc.add<std::string>("preEmId", "hOverE < 0.3 && hOverE >= 0");
1065  {
1067  psd0.add<bool>("isPUFilter", true);
1068  psd0.add<std::string>("preselection", "");
1069  psd0.add<std::string>("method", "BDT");
1070  {
1072  vpsd2.add<std::string>("name");
1073  vpsd2.add<std::string>("value");
1074  std::vector<edm::ParameterSet> temp2;
1075  temp2.reserve(5);
1076  {
1077  edm::ParameterSet temp3;
1078  temp3.addParameter<std::string>("name", "eMax");
1079  temp3.addParameter<std::string>("value", "eMax()");
1080  temp2.push_back(temp3);
1081  }
1082  {
1083  edm::ParameterSet temp3;
1084  temp3.addParameter<std::string>("name", "eMaxOverE");
1085  temp3.addParameter<std::string>("value", "eMax()/energy()");
1086  temp2.push_back(temp3);
1087  }
1088  {
1089  edm::ParameterSet temp3;
1090  temp3.addParameter<std::string>("name", "sigmaPhiPhiTot");
1091  temp3.addParameter<std::string>("value", "sigmaPhiPhiTot()");
1092  temp2.push_back(temp3);
1093  }
1094  {
1095  edm::ParameterSet temp3;
1096  temp3.addParameter<std::string>("name", "sigmaRRTot");
1097  temp3.addParameter<std::string>("value", "sigmaRRTot()");
1098  temp2.push_back(temp3);
1099  }
1100  {
1101  edm::ParameterSet temp3;
1102  temp3.addParameter<std::string>("name", "triggerCells90percent");
1103  temp3.addParameter<std::string>("value", "triggerCells90percent()");
1104  temp2.push_back(temp3);
1105  }
1106  psd0.addVPSet("variables", vpsd2, temp2);
1107  }
1108  psd0.add<std::string>(
1109  "weightsFile", "L1Trigger/Phase2L1ParticleFlow/data/hgcal_egID/Photon_Pion_vs_Neutrino_BDTweights_1116.xml.gz");
1110  psd0.add<std::string>("wp", "-0.10");
1111  desc.add<edm::ParameterSetDescription>("VsPuId", psd0);
1112  }
1113 
1114  desc.add<double>("EcalEtMinForClustering", 0.0);
1115  desc.add<double>("HcalEtMinForClustering", 0.0);
1116  desc.add<double>("EtMinForSeeding", 2.5);
1117  desc.add<double>("EtaRestriction", 2.4);
1118  desc.add<double>("CB_CE_split", 1.55);
1119  desc.add<double>("PuidThr", -0.1);
1120 
1121  desc.add<std::string>("CNNmodel_CB_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/v22/CNNmodel_CB.pb");
1122  desc.add<std::string>("DNNident_CB_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/v22/DNNident_CB.pb");
1123  desc.add<std::string>("DNNcalib_CB_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/v22/DNNcalib_CB.pb");
1124  desc.add<std::string>("CNNmodel_CE_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/v22/CNNmodel_CE.pb");
1125  desc.add<std::string>("DNNident_CE_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/v22/DNNident_CE.pb");
1126  desc.add<std::string>("DNNcalib_CE_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/v22/DNNcalib_CE.pb");
1127  desc.add<std::string>("FeatScaler_CE_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/Cl3dFeatScaler_CE.json");
1128 
1129  desc.add<double>("IdWp90_CB", 0.706);
1130  desc.add<double>("IdWp95_CB", 0.3432);
1131  desc.add<double>("IdWp99_CB", 0.0337);
1132  desc.add<double>("IdWp90_CE", 0.5711);
1133  desc.add<double>("IdWp95_CE", 0.2742);
1134  desc.add<double>("IdWp99_CE", 0.0394);
1135 
1136  desc.add<bool>("DEBUG", false);
1137 
1138  descriptions.add("l1tNNCaloTauEmulator", desc);
1139 }
1140 
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
std::string fullPath() const
Definition: FileInPath.cc:161
static constexpr int PT_W
GraphDef * loadGraphDef(const std::string &pbFile)
Definition: TensorFlow.cc:129
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:268
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:146
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
void setLogging(const std::string &level="3")
Definition: TensorFlow.cc:90
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
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 *)
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