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
721  int batchSize_CB = (int)(Nclusters_CB);
722  tensorflow::TensorShape imageShape_CB({batchSize_CB, IEta_dim, IPhi_dim, 2});
723  tensorflow::TensorShape positionShape_CB({batchSize_CB, 2});
724  tensorflow::Tensor TowerClusterImage_CB(tensorflow::DT_FLOAT, imageShape_CB);
725  tensorflow::Tensor TowerClusterPosition_CB(tensorflow::DT_FLOAT, positionShape_CB);
726 
727  for (int clNxMIdx = 0; clNxMIdx < Nclusters_CB; clNxMIdx++) {
728  // Fill inputs for Tensorflow inference
729  for (int eta = 0; eta < IEta_dim; ++eta) {
730  for (int phi = 0; phi < IPhi_dim; ++phi) {
731  int towerIdx = eta * IPhi_dim + phi;
732  TowerClusterImage_CB.tensor<float, 4>()(clNxMIdx, eta, phi, 0) =
733  (l1TowerClustersNxM_CB[clNxMIdx].towerHits[towerIdx].l1egTowerEt.to_float() +
734  l1TowerClustersNxM_CB[clNxMIdx].towerHits[towerIdx].towerEm.to_float());
735  TowerClusterImage_CB.tensor<float, 4>()(clNxMIdx, eta, phi, 1) =
736  (l1TowerClustersNxM_CB[clNxMIdx].towerHits[towerIdx].towerHad.to_float());
737  }
738  }
739 
740  TowerClusterPosition_CB.tensor<float, 2>()(clNxMIdx, 0) = floatIEta(l1TowerClustersNxM_CB_pstn[clNxMIdx].seedIeta);
741  TowerClusterPosition_CB.tensor<float, 2>()(clNxMIdx, 1) = floatIPhi(l1TowerClustersNxM_CB_pstn[clNxMIdx].seedIphi);
742  }
743 
744  if (batchSize_CB >
745  0) // from CMSSW_14_0_X tensorflow does not seem to be able to deal with a tensor of dimension 0 anymore
746  {
747  // Apply CNN model
748  tensorflow::NamedTensorList CNNmodel_CBinputList = {{"TowerClusterImage", TowerClusterImage_CB},
749  {"TowerClusterPosition", TowerClusterPosition_CB}};
750  std::vector<tensorflow::Tensor> CNNmodel_CBoutputs;
751  tensorflow::run((globalCache()->CNNmodel_CBsession),
752  CNNmodel_CBinputList,
753  {"TauMinator_CB_conv/middleMan/concat"},
754  &CNNmodel_CBoutputs);
755  tensorflow::NamedTensorList DNN_CBinputsList = {{"middleMan", CNNmodel_CBoutputs[0]}};
756 
757  // Apply DNN for identification
758  std::vector<tensorflow::Tensor> DNN_CBoutputsIdent;
759  tensorflow::run((globalCache()->DNNident_CBsession),
760  DNN_CBinputsList,
761  {"TauMinator_CB_ident/sigmoid_IDout/Sigmoid"},
762  &DNN_CBoutputsIdent);
763 
764  // Apply DNN for calibration
765  std::vector<tensorflow::Tensor> DNN_CBoutputsCalib;
766  tensorflow::run((globalCache()->DNNcalib_CBsession),
767  DNN_CBinputsList,
768  {"TauMinator_CB_calib/DNNout/MatMul"},
769  &DNN_CBoutputsCalib);
770 
771  // Fill the output collection of L1 taus with the barrel candidates
772  for (int clNxMIdx = 0; clNxMIdx < Nclusters_CB; clNxMIdx++) {
773  l1t::Tau l1Tau =
774  MakeTauCandidate(true, clNxMIdx, DNN_CBoutputsIdent, DNN_CBoutputsCalib, l1TowerClustersNxM_CB_pstn);
775  if (l1Tau.pt() < 0) {
776  continue;
777  }
778  L1NNCaloTauCollectionBXV->push_back(0, l1Tau);
779  }
780  }
781 
782  // Endcap TauMinator application
783  int batchSize_CE = (int)(Nclusters_CE);
784  tensorflow::TensorShape imageShape_CE({batchSize_CE, IEta_dim, IPhi_dim, 2});
785  tensorflow::TensorShape positionShape_CE({batchSize_CE, 2});
786  tensorflow::TensorShape cl3dfeatShape_CE({batchSize_CE, 8});
787  tensorflow::Tensor TowerClusterImage_CE(tensorflow::DT_FLOAT, imageShape_CE);
788  tensorflow::Tensor TowerClusterPosition_CE(tensorflow::DT_FLOAT, positionShape_CE);
789  tensorflow::Tensor Cl3dShapeFeatures_CE(tensorflow::DT_FLOAT, cl3dfeatShape_CE);
790 
791  for (int clNxMIdx = 0; clNxMIdx < Nclusters_CE; clNxMIdx++) {
792  // Indexing of cl3ds is the same as the one of clNxMs
793  InputHGCluster HGClu = HGClusters[clNxMIdx];
794 
795  // Fill inputs for Tensorflow inference
796  for (int eta = 0; eta < IEta_dim; ++eta) {
797  for (int phi = 0; phi < IPhi_dim; ++phi) {
798  int towerIdx = eta * IPhi_dim + phi;
799  TowerClusterImage_CE.tensor<float, 4>()(clNxMIdx, eta, phi, 0) =
800  (l1TowerClustersNxM_CE[clNxMIdx].towerHits[towerIdx].l1egTowerEt.to_float() +
801  l1TowerClustersNxM_CE[clNxMIdx].towerHits[towerIdx].towerEm.to_float());
802  TowerClusterImage_CE.tensor<float, 4>()(clNxMIdx, eta, phi, 1) =
803  (l1TowerClustersNxM_CE[clNxMIdx].towerHits[towerIdx].towerHad.to_float());
804  }
805  }
806 
807  TowerClusterPosition_CE.tensor<float, 2>()(clNxMIdx, 0) = floatIEta(l1TowerClustersNxM_CE_pstn[clNxMIdx].seedIeta);
808  TowerClusterPosition_CE.tensor<float, 2>()(clNxMIdx, 1) = floatIPhi(l1TowerClustersNxM_CE_pstn[clNxMIdx].seedIphi);
809 
810  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 0) = inputScaler(HGClu.pt.to_float(), "pt");
811  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 1) = inputScaler(abs(floatEta(HGClu.eta)), "eta");
812  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 2) = inputScaler(HGClu.showerlength.to_float(), "showerlength");
813  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 3) =
814  inputScaler(HGClu.coreshowerlength.to_float(), "coreshowerlength");
815  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 4) = inputScaler(floatShape(HGClu.spptot), "spptot");
816  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 5) = inputScaler(floatSzz(HGClu.szz), "szz");
817  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 6) = inputScaler(floatShape(HGClu.srrtot), "srrtot");
818  Cl3dShapeFeatures_CE.tensor<float, 2>()(clNxMIdx, 7) = inputScaler(floatMeanZHgcalCoord(HGClu.meanz), "meanz");
819  }
820 
821  if (batchSize_CE >
822  0) // from CMSSW_14_0_X tensorflow does not seem to be able to deal with a tensor of dimension 0 anymore
823  {
824  // Apply CNN model
825  tensorflow::NamedTensorList CNNmodel_CEinputList = {{"TowerClusterImage", TowerClusterImage_CE},
826  {"TowerClusterPosition", TowerClusterPosition_CE},
827  {"AssociatedCl3dFeatures", Cl3dShapeFeatures_CE}};
828  std::vector<tensorflow::Tensor> CNNmodel_CEoutputs;
829  tensorflow::run((globalCache()->CNNmodel_CEsession),
830  CNNmodel_CEinputList,
831  {"TauMinator_CE_conv/middleMan/concat"},
832  &CNNmodel_CEoutputs);
833  tensorflow::NamedTensorList DNN_CEinputsList = {{"middleMan", CNNmodel_CEoutputs[0]}};
834 
835  // Apply DNN for identification
836  std::vector<tensorflow::Tensor> DNN_CEoutputsIdent;
837  tensorflow::run((globalCache()->DNNident_CEsession),
838  DNN_CEinputsList,
839  {"TauMinator_CE_ident/sigmoid_IDout/Sigmoid"},
840  &DNN_CEoutputsIdent);
841 
842  // Apply DNN for calibration
843  std::vector<tensorflow::Tensor> DNN_CEoutputsCalib;
844  tensorflow::run((globalCache()->DNNcalib_CEsession),
845  DNN_CEinputsList,
846  {"TauMinator_CE_calib/LIN_DNNout/Relu"},
847  &DNN_CEoutputsCalib);
848 
849  // Fill the output collection of L1 taus with the endcap candidates
850  for (int clNxMIdx = 0; clNxMIdx < Nclusters_CE; clNxMIdx++) {
851  l1t::Tau l1Tau =
852  MakeTauCandidate(false, clNxMIdx, DNN_CEoutputsIdent, DNN_CEoutputsCalib, l1TowerClustersNxM_CE_pstn);
853  if (l1Tau.pt() < 0) {
854  continue;
855  }
856  L1NNCaloTauCollectionBXV->push_back(0, l1Tau);
857  }
858  }
859 
860  // Fill output
861  iEvent.put(std::move(L1NNCaloTauCollectionBXV), "L1NNCaloTauCollectionBXV");
862 
863 } // End of produce function
864 
865 template <class outPrecision, class inPrecision>
866 outPrecision L1NNCaloTauEmulator::dPhi(inPrecision iPhi_1, inPrecision iPhi_2) {
867  outPrecision dphi = iPhi_1 - iPhi_2;
868 
869  outPrecision dphi0 = dphi > outPrecision(INTPHI_PI) ? outPrecision(dphi - INTPHI_2PI) : dphi;
870  outPrecision dphi1 = dphi <= outPrecision(-INTPHI_PI) ? outPrecision(dphi + INTPHI_2PI) : dphi;
871 
872  outPrecision result = dphi > outPrecision(0) ? dphi0 : dphi1;
873 
874  return result;
875 }
876 
878  ap_int<12> mult = iEta_1 * iEta_2;
879  dIEtaPhi_t result = iEta_1 - iEta_2;
880  if (mult < 0) {
881  result = iEta_1 > 0 ? result - 1 : result + 1;
882  }
883 
884  return result;
885 }
886 
888  EtaPhi_t shiftediPhi_2 = iPhi_2 <= IPhi_t(36) ? EtaPhi_t(iPhi_2) : EtaPhi_t(iPhi_2 - INTPHI_2PI + 1);
889 
890  EtaPhi_t fineiPhi_2 = shiftediPhi_2 * (IETAPHI_LSB / ETAPHI_LSB);
891  // subrtaction of half rescaling corrects from edge to center of tower
892  fineiPhi_2 = fineiPhi_2 > EtaPhi_t(0) ? EtaPhi_t(fineiPhi_2 - (IETAPHI_LSB / ETAPHI_LSB) / 2)
893  : EtaPhi_t(fineiPhi_2 + (IETAPHI_LSB / ETAPHI_LSB) / 2);
894 
895  return dPhi<dEtaPhi_t, EtaPhi_t>(iPhi_1, fineiPhi_2);
896 }
897 
899  // change from hgcal frame to barrel-centered frame
900  EtaPhi_t framechangeCl3d = 303; // 303*pi/720 = 1.322
901  iEta_1 = iEta_1 > EtaPhi_t(0) ? EtaPhi_t(iEta_1 + framechangeCl3d) : EtaPhi_t(iEta_1 - framechangeCl3d);
902 
903  // the actual depth is 330 but 329 corrects for 0.0808 tower
904  EtaPhi_t barrelEtaDepth = 329;
905  EtaPhi_t fineiEta_2 = barrelEtaDepth + (iEta_2 - IETAHGCAL_OFFSET) * (IETAHGCAL_LSB / ETAPHI_LSB);
906 
907  return iEta_1 - fineiEta_2;
908 }
909 
911  IEta_t ieta = floor(eta / IETAHGCAL_LSB);
912  // +1 because flooring gets it 1 unit lower when negative
913  ieta = ieta < IEta_t(0) ? IEta_t(ieta + 1) : ieta;
914 
915  return ieta;
916 }
917 
919  phi = phi < 0 ? phi + 2 * M_PI : phi;
920 
921  // +1 because tower 0 does not exist
922  return floor(phi / IETAPHI_LSB) + 1;
923 }
924 
925 template <int W>
926 ap_int<W> L1NNCaloTauEmulator::ap_abs(ap_int<W> x) {
927  ap_int<W> result;
928  if (x < 0) {
929  result = -x;
930  } else {
931  result = x;
932  }
933 
934  return result;
935 }
936 
937 template <int W, int I, ap_q_mode _AP_Q, ap_o_mode _AP_O>
938 ap_ufixed<W, I> L1NNCaloTauEmulator::ap_abs(ap_fixed<W, I, _AP_Q, _AP_O> x) {
939  ap_ufixed<W, I> result;
940  if (x < 0) {
941  result = -x;
942  } else {
943  result = x;
944  }
945 
946  return result;
947 }
948 
949 float L1NNCaloTauEmulator::apfixedQuantizer(float inputF, float LSB, int nbits) {
950  return min(floor(inputF / LSB), float(pow(2, nbits) - 1)) * LSB;
951 }
952 
953 int L1NNCaloTauEmulator::apintQuantizer(float inputF, float LSB, int nbits) {
954  return min(floor(inputF / LSB), float(pow(2, nbits) - 1));
955 }
956 
957 float L1NNCaloTauEmulator::inputScaler(float inputF, std::string feature) {
958  float mean = (globalCache()->FeatScaler_CE).get_child(feature).get<float>("mean");
959  float std = (globalCache()->FeatScaler_CE).get_child(feature).get<float>("std");
960 
961  return (inputF - mean) / std;
962 }
963 
965  return eta > 0 ? eta - ETAHGCAL_OFFSET : eta + ETAHGCAL_OFFSET;
966 }
967 
968 float L1NNCaloTauEmulator::correctInputMeanzCl3d(float meanz) { return CM2MM * (abs(meanz) - MEANZ_OFFSET); }
969 
971  // transform eta of towers from integer to float, correcting for different barrel/endcap LSB
972  float feta;
973  if (abs(eta) > IETAHGCAL_OFFSET) {
974  if (eta > 0) {
976  (eta.to_float() - IETAHGCAL_OFFSET) * IETAHGCAL_LSB;
977  } else {
979  (eta.to_float() + IETAHGCAL_OFFSET) * IETAHGCAL_LSB;
980  }
981  } else {
982  feta = eta.to_float() * IETAPHI_LSB;
983  }
984 
985  // shift by half a tower to consider the tower center instead of the edge
986  return feta > 0 ? feta - IETAPHI_LSB / 2 : feta + IETAPHI_LSB / 2;
987 }
988 
990  float fphi = phi.to_float();
991  // add 2pi + 1 because tower 0 does not exist
992  fphi = fphi > INTPHI_PI ? fphi - INTPHI_2PI + 1 : fphi;
993  fphi *= IETAPHI_LSB;
994 
995  // shift by half a tower to consider the tower center instead of the edge
996  return fphi > 0 ? fphi - IETAPHI_LSB / 2 : fphi + IETAPHI_LSB / 2;
997 }
998 
1000  bool isBarrel,
1001  int clNxMIdx,
1002  std::vector<tensorflow::Tensor> outputsIdent,
1003  std::vector<tensorflow::Tensor> outputsCalib,
1004  std::vector<L1NNCaloTauEmulator::InputTowerCluster_pstn> clustersNxM_pstn) {
1005  int seedIeta = clustersNxM_pstn[clNxMIdx].seedIeta;
1006  int seedIphi = clustersNxM_pstn[clNxMIdx].seedIphi;
1007 
1008  if (seedIeta > intEtaRestriction) {
1009  return l1t::Tau(reco::Candidate::PolarLorentzVector(-1, 0, 0, 0), -1, 0, 0, 0, 0);
1010  ;
1011  }
1012 
1013  float tau_IDscore = outputsIdent[0].matrix<float>()(0, clNxMIdx);
1014  float tau_calibPt = outputsCalib[0].matrix<float>()(0, clNxMIdx);
1015  float tau_eta = floatIEta(seedIeta);
1016  float tau_phi = floatIPhi(seedIphi);
1017 
1018  // Assign increasing quality to higher scoring candidates
1019  int quality = 0;
1020  if (isBarrel) {
1021  // 99% WP
1022  if (tau_IDscore > IdWp99_CB) {
1023  quality = 1;
1024  }
1025  // 95% WP
1026  if (tau_IDscore > IdWp95_CB) {
1027  quality = 2;
1028  }
1029  // 90% WP
1030  if (tau_IDscore > IdWp90_CB) {
1031  quality = 3;
1032  }
1033  } else {
1034  // 99% WP
1035  if (tau_IDscore > IdWp99_CE) {
1036  quality = 1;
1037  }
1038  // 95% WP
1039  if (tau_IDscore > IdWp95_CE) {
1040  quality = 2;
1041  }
1042  // 90% WP
1043  if (tau_IDscore > IdWp90_CE) {
1044  quality = 3;
1045  }
1046  }
1047 
1049 
1050  // store ID score multiplied by 10E4 to have good precision even using the Phase1 tau int iso format
1051  // (this is stored just in case for possible additional offline studies)
1052  // tau initialisation = (p4, pt, eta, phi, qual, iso)
1053  l1t::Tau l1Tau = l1t::Tau(tauP4, tau_calibPt, tau_eta, tau_phi, quality, tau_IDscore * 10E4);
1054  l1Tau.setTowerIEta(seedIeta);
1055  l1Tau.setTowerIPhi(seedIphi);
1056 
1057  return l1Tau;
1058 }
1059 
1062 
1063  desc.add<edm::InputTag>("l1CaloTowers", edm::InputTag("l1tEGammaClusterEmuProducer", "L1CaloTowerCollection"));
1064  desc.add<edm::InputTag>("hgcalTowers", edm::InputTag("l1tHGCalTowerProducer", "HGCalTowerProcessor"));
1065  desc.add<edm::InputTag>("HgcalClusters",
1066  edm::InputTag("l1tHGCalBackEndLayer2Producer", "HGCalBackendLayer2Processor3DClustering"));
1067 
1068  desc.add<std::string>("preEmId", "hOverE < 0.3 && hOverE >= 0");
1069  {
1071  psd0.add<bool>("isPUFilter", true);
1072  psd0.add<std::string>("preselection", "");
1073  psd0.add<std::string>("method", "BDT");
1074  {
1076  vpsd2.add<std::string>("name");
1077  vpsd2.add<std::string>("value");
1078  std::vector<edm::ParameterSet> temp2;
1079  temp2.reserve(5);
1080  {
1081  edm::ParameterSet temp3;
1082  temp3.addParameter<std::string>("name", "eMax");
1083  temp3.addParameter<std::string>("value", "eMax()");
1084  temp2.push_back(temp3);
1085  }
1086  {
1087  edm::ParameterSet temp3;
1088  temp3.addParameter<std::string>("name", "eMaxOverE");
1089  temp3.addParameter<std::string>("value", "eMax()/energy()");
1090  temp2.push_back(temp3);
1091  }
1092  {
1093  edm::ParameterSet temp3;
1094  temp3.addParameter<std::string>("name", "sigmaPhiPhiTot");
1095  temp3.addParameter<std::string>("value", "sigmaPhiPhiTot()");
1096  temp2.push_back(temp3);
1097  }
1098  {
1099  edm::ParameterSet temp3;
1100  temp3.addParameter<std::string>("name", "sigmaRRTot");
1101  temp3.addParameter<std::string>("value", "sigmaRRTot()");
1102  temp2.push_back(temp3);
1103  }
1104  {
1105  edm::ParameterSet temp3;
1106  temp3.addParameter<std::string>("name", "triggerCells90percent");
1107  temp3.addParameter<std::string>("value", "triggerCells90percent()");
1108  temp2.push_back(temp3);
1109  }
1110  psd0.addVPSet("variables", vpsd2, temp2);
1111  }
1112  psd0.add<std::string>(
1113  "weightsFile", "L1Trigger/Phase2L1ParticleFlow/data/hgcal_egID/Photon_Pion_vs_Neutrino_BDTweights_1116.xml.gz");
1114  psd0.add<std::string>("wp", "-0.10");
1115  desc.add<edm::ParameterSetDescription>("VsPuId", psd0);
1116  }
1117 
1118  desc.add<double>("EcalEtMinForClustering", 0.0);
1119  desc.add<double>("HcalEtMinForClustering", 0.0);
1120  desc.add<double>("EtMinForSeeding", 2.5);
1121  desc.add<double>("EtaRestriction", 2.4);
1122  desc.add<double>("CB_CE_split", 1.55);
1123  desc.add<double>("PuidThr", -0.1);
1124 
1125  desc.add<std::string>("CNNmodel_CB_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/v22/CNNmodel_CB.pb");
1126  desc.add<std::string>("DNNident_CB_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/v22/DNNident_CB.pb");
1127  desc.add<std::string>("DNNcalib_CB_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/v22/DNNcalib_CB.pb");
1128  desc.add<std::string>("CNNmodel_CE_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/v22/CNNmodel_CE.pb");
1129  desc.add<std::string>("DNNident_CE_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/v22/DNNident_CE.pb");
1130  desc.add<std::string>("DNNcalib_CE_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/v22/DNNcalib_CE.pb");
1131  desc.add<std::string>("FeatScaler_CE_path", "L1Trigger/L1CaloTrigger/data/Phase2_NNCaloTaus/Cl3dFeatScaler_CE.json");
1132 
1133  desc.add<double>("IdWp90_CB", 0.706);
1134  desc.add<double>("IdWp95_CB", 0.3432);
1135  desc.add<double>("IdWp99_CB", 0.0337);
1136  desc.add<double>("IdWp90_CE", 0.5711);
1137  desc.add<double>("IdWp95_CE", 0.2742);
1138  desc.add<double>("IdWp99_CE", 0.0394);
1139 
1140  desc.add<bool>("DEBUG", false);
1141 
1142  descriptions.add("l1tNNCaloTauEmulator", desc);
1143 }
1144 
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:281
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
#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 *)
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