CMS 3D CMS Logo

Phase2L1CaloEGammaUtils.h
Go to the documentation of this file.
1 //------------------------------------
2 // Helper functions for Phase2L1CaloEGammaEmulator.cc
3 //------------------------------------
4 #ifndef L1Trigger_L1CaloTrigger_Phase2L1CaloEGammaUtils
5 #define L1Trigger_L1CaloTrigger_Phase2L1CaloEGammaUtils
6 
7 #include <ap_int.h>
8 #include <cstdio>
9 #include <fstream>
10 #include <iomanip>
11 #include <iostream>
12 
16 
17 // Output collections
23 
26 
27 namespace p2eg {
28 
29  static constexpr int n_towers_Eta = 34;
30  static constexpr int n_towers_Phi = 72;
31  static constexpr int n_towers_halfPhi = 36;
32  static constexpr int n_towers_cardEta = 17; // new: equivalent to n_towers_per_link
33  static constexpr int n_towers_cardPhi = 4;
34  static constexpr int n_crystals_cardEta = (n_towers_Eta * n_towers_cardEta);
35  static constexpr int n_crystals_cardPhi = (n_towers_Phi * n_towers_cardPhi);
36 
37  // outputs
38  static constexpr int n_links_card = 4; // 4 links per card
39  static constexpr int n_clusters_link = 2; // 2 clusters sent out in each link
40  static constexpr int n_clusters_4link = 8; // 8 clusters sent out in 4 links
41  static constexpr int n_towers_per_link = 17;
42 
43  static constexpr int CRYSTALS_IN_TOWER_ETA = 5;
44  static constexpr int CRYSTALS_IN_TOWER_PHI = 5;
45 
46  static constexpr int TOWER_IN_ETA = 3; // number of towers in eta, in one 3x4 region (barrel)
47  static constexpr int TOWER_IN_PHI = 4; // number of towers in phi, in one 3x4 region (barrel)
48 
49  static constexpr int CRYSTAL_IN_ETA = 15; // number of crystals in eta, in one 3x4 region (barrel)
50  static constexpr int CRYSTAL_IN_PHI = 20; // number of crystals in phi, in one 3x4 region (barrel)
51 
52  static constexpr float ECAL_eta_range = 1.4841;
53  static constexpr float half_crystal_size = 0.00873;
54 
55  static constexpr float slideIsoPtThreshold = 80;
56  static constexpr float a0_80 = 0.85, a1_80 = 0.0080, a0 = 0.21; // passes_iso
57  static constexpr float b0 = 0.38, b1 = 1.9, b2 = 0.05; // passes_looseTkiso
58  static constexpr float c0_ss = 0.94, c1_ss = 0.052, c2_ss = 0.044; // passes_ss
59  static constexpr float d0 = 0.96, d1 = 0.0003; // passes_photon
60  static constexpr float e0_looseTkss = 0.944, e1_looseTkss = 0.65, e2_looseTkss = 0.4; // passes_looseTkss
61  static constexpr float cut_500_MeV = 0.5;
62 
63  static constexpr float ECAL_LSB = 0.125; // to convert from int to float (GeV) multiply by LSB
64  static constexpr float HCAL_LSB = 0.5;
65 
66  static constexpr int N_CLUSTERS_PER_REGION = 4; // number of clusters per ECAL region
67  static constexpr int N_REGIONS_PER_CARD = 6; // number of ECAL regions per card
68 
69  // GCT constants
70  static constexpr int N_RCTCARDS_PHI = 8;
71  static constexpr int N_RCTGCT_FIBERS = 4;
72  static constexpr int N_RCTTOWERS_FIBER = 17;
73  static constexpr int N_RCTCLUSTERS_FIBER = 2;
74 
75  static constexpr int N_GCTCARDS = 3;
76  static constexpr int N_GCTCORR_FIBERS = 48;
77  static constexpr int N_GCTTOWERS_FIBER = 17;
78  static constexpr int N_GCTCLUSTERS_FIBER = 2;
79 
80  static constexpr int N_GCTINTERNAL_FIBERS = 64;
81  static constexpr int N_GCTPOSITIVE_FIBERS = 32;
82  static constexpr int N_GCTETA = 34;
83  static constexpr int N_GCTPHI = 32;
84 
85  // for emulator: "top" of the GCT card in phi is tower idx 20, for GCT card #0:
86  static constexpr int GCTCARD_0_TOWER_IPHI_OFFSET = 20;
87  // same but for GCT cards #1 and 2 (cards wrap around phi = 180 degrees):
88  static constexpr int GCTCARD_1_TOWER_IPHI_OFFSET = 44;
89  static constexpr int GCTCARD_2_TOWER_IPHI_OFFSET = 68;
90 
91  static constexpr int N_GCTTOWERS_CLUSTER_ISO_ONESIDE = 5; // window size of isolation sum (5x5 in towers)
92 
93  /*
94  * Convert HCAL ET to ECAL ET convention
95  */
96  inline ap_uint<12> convertHcalETtoEcalET(ap_uint<12> HCAL) {
97  float hcalEtAsFloat = HCAL * HCAL_LSB;
98  return (ap_uint<12>(hcalEtAsFloat / ECAL_LSB));
99  }
100 
102  // RCT: indexing helper functions
104 
105  // Assert that the card index is within bounds. (Valid cc: 0 to 35, since there are 36 RCT cards)
106  inline bool isValidCard(int cc) { return ((cc > -1) && (cc < 36)); }
107 
108  // RCT Cards: need to know their min/max crystal boundaries.
109 
110  // For a card (ranging from 0 to 35, since there are 36 cards), return the iEta of the crystal with max iEta.
111  // This represents the card boundaries in eta (identical to getEtaMax_card in the original emulator)
112  inline int getCard_iEtaMax(int cc) {
114 
115  int etamax = 0;
116  if (cc % 2 == 0) // Even card: negative eta
117  etamax = (n_towers_cardEta * CRYSTALS_IN_TOWER_ETA - 1); // First eta half. 5 crystals in eta in 1 tower.
118  else // Odd card: positive eta
120  return etamax;
121  }
122 
123  // Same as above but for minimum iEta.
124  inline int getCard_iEtaMin(int cc) {
125  int etamin = 0;
126  if (cc % 2 == 0) // Even card: negative eta
127  etamin = (0);
128  else // Odd card: positive eta
130  return etamin;
131  }
132 
133  // Same as above but for maximum iPhi.
134  inline int getCard_iPhiMax(int cc) {
135  int phimax = ((cc / 2) + 1) * 4 * CRYSTALS_IN_TOWER_PHI - 1;
136  return phimax;
137  }
138 
139  // Same as above but for minimum iPhi.
140  inline int getCard_iPhiMin(int cc) {
141  int phimin = (cc / 2) * 4 * CRYSTALS_IN_TOWER_PHI;
142  return phimin;
143  }
144 
145  // Given the RCT card number (0-35), get the crystal iEta of the "bottom left" corner
146  inline int getCard_refCrystal_iEta(int cc) {
147  if ((cc % 2) == 1) { // if cc is odd (positive eta)
148  return (17 * CRYSTALS_IN_TOWER_ETA);
149  } else { // if cc is even (negative eta) the bottom left corner is further in eta, hence +4
150  return ((16 * CRYSTALS_IN_TOWER_ETA) + 4);
151  }
152  }
153 
154  // Given the RCT card number (0-35), get the global crystal iPhi of the "bottom left" corner (0- 71*5)
155  inline int getCard_refCrystal_iPhi(int cc) {
156  if ((cc % 2) == 1) {
157  // if cc is odd: positive eta
158  return int(cc / 2) * TOWER_IN_PHI * CRYSTALS_IN_TOWER_PHI;
159  } else {
160  // if cc is even, the bottom left corner is further in phi, hence the +4 and -1
161  return (((int(cc / 2) * TOWER_IN_PHI) + 4) * CRYSTALS_IN_TOWER_PHI) - 1;
162  }
163  }
164 
165  // Towers: Go from real (eta, phi) to tower absolute ID
166 
167  /*
168  * For a real eta, get the tower absolute Eta index (possible values are 0-33, since there
169  * are 34 towers in eta. (Adapted from getTower_absoluteEtaID)
170  */
171  inline int getTower_absEtaID(float eta) {
172  float size_cell = 2 * ECAL_eta_range / n_towers_Eta;
173  int etaID = int((eta + ECAL_eta_range) / size_cell);
174  return etaID;
175  }
176 
177  /*
178  * Same as above, but for phi.
179  * Possible values range from 0-71 (Adapted from getTower_absolutePhiID)
180  */
181  inline int getTower_absPhiID(float phi) {
182  float size_cell = 2 * M_PI / n_towers_Phi;
183  int phiID = int((phi + M_PI) / size_cell);
184  return phiID;
185  }
186 
187  // Towers: Go from firmware specifics (RCT card, tower number in link, and link number (all firmware convention))
188  // to tower absolute ID.
189 
190  /*
191  * Get the global tower iEta (0-31) from the firmware card, tower number (0-16), and link (0-3). Respects the fact that
192  * in the firmware, negative eta cards are "rotated" (link 0, tower 0) starts in the "top right" corner if we
193  * look at a diagram of the barrel region.
194  */
195  inline int getAbsID_iEta_fromFirmwareCardTowerLink(int nCard, int nTower, int nLink) {
196  // iEta only depends on the tower position in the link
197  (void)nCard;
198  (void)nLink;
199  if ((nCard % 2) == 1) { // if cc is odd (positive eta), e.g. nTower = 0 will correspond to absolute iEta ID 17.
200  return n_towers_per_link + nTower;
201  } else { // if cc is even (negative eta): e.g. nTower = 0 will correspond to absolute iEta ID 16.
202  return (16 - nTower);
203  }
204  }
205 
206  /*
207  * Get the global tower iPhi (0-71) from the firmware card, tower number (0-16), and link (0-3).
208  */
209  inline int getAbsID_iPhi_fromFirmwareCardTowerLink(int nCard, int nTower, int nLink) {
210  // iPhi only depends on the card and link number
211  (void)nTower;
212  if ((nCard % 2) == 1) { // if cc is odd (positive eta),
213  // e.g. cc=3, link #2, global iPhi = int(3/2) * 4 + 2 = 6
214  return (int(nCard / 2) * TOWER_IN_PHI) + nLink;
215  } else { // if cc is even (negative eta)
216  // e.g. cc=4, link #2, global iPhi = int(4/2) * 4 + (4 - 2 - 1)
217  // = 2*4 + 1
218  // = 9
219  // minus one is because TOWER_IN_PHI is 4
220  return (int(nCard / 2) * TOWER_IN_PHI) + (TOWER_IN_PHI - nLink - 1);
221  }
222  }
223 
224  // Towers: Go from absolute ID, back to real eta and phi.
225 
226  /*
227  * From the tower absolute ID in eta (0-33), get the real eta of the tower center
228  * Same as getTowerEta_fromAbsoluteID in previous CMSSW emulator
229  */
230  inline float getTowerEta_fromAbsID(int id) {
231  float size_cell = 2 * ECAL_eta_range / n_towers_Eta;
232  float eta = (id * size_cell) - ECAL_eta_range + 0.5 * size_cell;
233  return eta;
234  }
235 
236  /*
237  * From the tower absolute ID in phi (0-71), get the real phi of the tower center
238  * Same as getTowerPhi_fromAbsoluteID in previous CMSSW emulator
239  */
240  inline float getTowerPhi_fromAbsID(int id) {
241  float size_cell = 2 * M_PI / n_towers_Phi;
242  float phi = (id * size_cell) - M_PI + 0.5 * size_cell;
243  return phi;
244  }
245 
246  /*
247  * Get the RCT card region that a crystal is in, given the "local" iEta of the crystal
248  * 0 is region closest to eta = 0. Regions 0, 1, 2, 3, 4 are in the barrel, Region 5 is in overlap
249  */
250  inline int getRegionNumber(const int local_iEta) {
251  int no = int(local_iEta / (TOWER_IN_ETA * CRYSTALS_IN_TOWER_ETA));
252  assert(no < 6);
253  return no;
254  }
255 
256  /*******************************************************************/
257  /* RCT classes and structs */
258  /*******************************************************************/
259 
260  /*
261  * Represents one input HCAL or ECAL hit.
262  */
264  private:
265  float pt_ = 0;
266  float energy_ = 0.;
267  ap_uint<10> et_uint_;
268  GlobalVector position_; // As opposed to GlobalPoint, so we can add them (for weighted average)
271 
272  public:
273  // tool functions
274  inline void setPt() { pt_ = (position_.mag2() > 0) ? energy_ * sin(position_.theta()) : 0; };
275  inline void setEnergy(float et) { energy_ = et / sin(position_.theta()); };
276  inline void setEt_uint(ap_uint<10> et_uint) { et_uint_ = et_uint; }
277  inline void setPosition(const GlobalVector& pos) { position_ = pos; };
278  inline void setIdHcal(const HcalDetId& idhcal) { id_hcal_ = idhcal; };
279  inline void setId(const EBDetId& id) { id_ = id; };
280 
281  inline float pt() const { return pt_; };
282  inline float energy() const { return energy_; };
283  inline ap_uint<10> et_uint() const { return et_uint_; };
284  inline const GlobalVector& position() const { return position_; };
285  inline const EBDetId& id() const { return id_; };
286 
287  /*
288  * Get crystal's iEta from real eta. (identical to getCrystal_etaID in L1EGammaCrystalsEmulatorProducer.cc)
289  * This "global" iEta ranges from 0 to (33*5) since there are 34 towers in eta in the full detector,
290  * each with five crystals in eta.
291  */
292  int crystaliEta(void) const {
293  float size_cell = 2 * ECAL_eta_range / (CRYSTALS_IN_TOWER_ETA * n_towers_Eta);
294  int iEta = int((position().eta() + ECAL_eta_range) / size_cell);
295  return iEta;
296  }
297 
298  /*
299  * Get crystal's iPhi from real phi. (identical to getCrystal_phiID in L1EGammaCrystalsEmulatorProducer.cc)
300  * This "global" iPhi ranges from 0 to (71*5) since there are 72 towers in phi in the full detector, each with five crystals in eta.
301  */
302  int crystaliPhi(void) const {
303  float phi = position().phi();
304  float size_cell = 2 * M_PI / (CRYSTALS_IN_TOWER_PHI * n_towers_Phi);
305  int iPhi = int((phi + M_PI) / size_cell);
306  return iPhi;
307  }
308 
309  /*
310  * Check if it falls within the boundary of a card.
311  */
312  bool isInCard(int cc) const {
313  return (crystaliPhi() <= getCard_iPhiMax(cc) && crystaliPhi() >= getCard_iPhiMin(cc) &&
315  };
316 
317  /*
318  * For a crystal with real eta, and falling in card cc, get its local iEta
319  * relative to the bottom left corner of the card (possible local iEta ranges from 0 to 17 * 5,
320  * since in one card, there are 17 towers in eta, each with 5 crystals in eta.
321  */
322  int crystalLocaliEta(int cc) const { return abs(getCard_refCrystal_iEta(cc) - crystaliEta()); }
323 
324  /*
325  * Same as above, but for iPhi (possible local iPhi ranges from 0 to (3*5), since in one card,
326  * there are 4 towers in phi, each with 5 crystals in phi.
327  */
328  int crystalLocaliPhi(int cc) const { return abs(getCard_refCrystal_iPhi(cc) - crystaliPhi()); }
329 
330  /*
331  * Print hit info
332  */
334  std::cout << "[printHitInfo]: [" << description << "]"
335  << " hit with energy " << pt() << " at eta " << position().eta() << ", phi " << position().phi()
336  << std::endl;
337  }
338  };
339 
340  /*******************************************************************/
341 
342  /*
343  * linkECAL class: represents one ECAL link (one tower: 5x5 crystals)
344  */
345 
346  class linkECAL {
347  private:
349 
350  public:
351  // constructor
352  linkECAL() {}
353 
354  // Set members
355  inline void zeroOut() { // zero out the crystalE array
356  for (int i = 0; i < CRYSTALS_IN_TOWER_ETA; i++) {
357  for (int j = 0; j < CRYSTALS_IN_TOWER_PHI; j++) {
358  crystalE[i][j] = 0;
359  }
360  }
361  };
362  inline void setCrystalE(int iEta, int iPhi, ap_uint<10> energy) {
365  crystalE[iEta][iPhi] = energy;
366  };
367  inline void addCrystalE(int iEta, int iPhi, ap_uint<10> energy) {
370  crystalE[iEta][iPhi] += energy;
371  };
372 
373  // Access members
374  inline ap_uint<10> getCrystalE(int iEta, int iPhi) {
375  assert(iEta < 5);
376  assert(iPhi < 5);
377  return crystalE[iEta][iPhi];
378  };
379  };
380 
381  /*******************************************************************/
382 
383  /*
384  * region3x4 class: represents one 3x4 ECAL region. The region stores no
385  * information about which card it is located in.
386  * idx: 0-4. Region 0 is the one closest to eta = 0, counting outwards in eta
387  */
388 
389  class region3x4 {
390  private:
391  int idx_ = -1;
393 
394  public:
395  // constructor
396  region3x4() { idx_ = -1; }
397 
398  // copy constructor
400  idx_ = other.idx_;
401  for (int i = 0; i < TOWER_IN_ETA; i++) {
402  for (int j = 0; j < TOWER_IN_PHI; j++) {
403  linksECAL[i][j] = other.linksECAL[i][j];
404  }
405  }
406  }
407 
408  // overload operator= to use copy constructor
410  const region3x4& newRegion(other);
411  return newRegion;
412  };
413 
414  // set members
415  inline void zeroOut() {
416  for (int i = 0; i < TOWER_IN_ETA; i++) {
417  for (int j = 0; j < TOWER_IN_PHI; j++) {
418  linksECAL[i][j].zeroOut();
419  }
420  }
421  };
422  inline void setIdx(int idx) { idx_ = idx; };
423 
424  // get members
425  inline float getIdx() const { return idx_; };
426  inline linkECAL& getLinkECAL(int iEta, int iPhi) { return linksECAL[iEta][iPhi]; };
427  };
428 
429  /*******************************************************************/
430 
431  /*
432  * towerHCAL class: represents one HCAL tower
433  */
434 
435  class towerHCAL {
436  private:
437  ap_uint<10> et = 0;
438  ap_uint<6> fb = 0;
439 
440  public:
441  // set members
442  inline void zeroOut() {
443  et = 0;
444  fb = 0;
445  };
446  inline void addEt(ap_uint<10> newEt) { et += newEt; };
447 
448  // get members
449  inline ap_uint<10> getEt() { return et; };
450  };
451 
452  /*******************************************************************/
453 
454  /*
455  * towers3x4 class: represents 3x4 array of HCAL towers. idx = 0, 1, ... 4 are the barrel gion
456  */
457 
458  class towers3x4 {
459  private:
460  int idx_ = -1;
462 
463  public:
464  // constructor
465  towers3x4() { idx_ = -1; };
466 
467  // copy constructor
469  idx_ = other.idx_;
470  for (int i = 0; i < TOWER_IN_ETA; i++) {
471  for (int j = 0; j < TOWER_IN_PHI; j++) {
472  towersHCAL[i][j] = other.towersHCAL[i][j];
473  }
474  };
475  };
476 
477  // overload operator= to use copy constructor
479  const towers3x4& newRegion(other);
480  return newRegion;
481  };
482 
483  // set members
484  inline void zeroOut() {
485  for (int i = 0; i < TOWER_IN_ETA; i++) {
486  for (int j = 0; j < TOWER_IN_PHI; j++) {
487  towersHCAL[i][j].zeroOut();
488  }
489  }
490  };
491  inline void setIdx(int idx) { idx_ = idx; };
492 
493  // get members
494  inline float getIdx() const { return idx_; };
495  inline towerHCAL& getTowerHCAL(int iEta, int iPhi) { return towersHCAL[iEta][iPhi]; };
496  };
497 
498  /*******************************************************************/
499 
500  /*
501  * card class: represents one RCT card. Each card has five 3x4 regions and one 2x4 region,
502  * which is represented by a 3x4 region with its third row zero'd out.
503  * idx 0-35: odd values of cardIdx span eta = 0 to eta = 1.41
504  * even values of cardIdx span eta = -1.41 to eta = 0
505  * The realEta and realPhi arrays store the (eta, phi) of the center of the towers.
506  */
507 
508  class card {
509  private:
510  int idx_ = -1;
513 
514  public:
515  // constructor
516  card() {
517  idx_ = -1;
518  for (int i = 0; i < N_REGIONS_PER_CARD; i++) {
523  }
524  };
525 
526  // copy constructor
527  card(const card& other) {
528  idx_ = other.idx_;
529  for (int i = 0; i < N_REGIONS_PER_CARD; i++) {
530  card3x4Regions[i] = other.card3x4Regions[i];
531  card3x4Towers[i] = other.card3x4Towers[i];
532  }
533  };
534 
535  // overload operator= to use copy constructor
537  const card& newCard(other);
538  return newCard;
539  };
540 
541  // set members
542  inline void setIdx(int idx) { idx_ = idx; };
543  inline void zeroOut() {
544  for (int i = 0; i < N_REGIONS_PER_CARD; i++) {
547  };
548  };
549 
550  // get members
551  inline float getIdx() const { return idx_; };
552  inline region3x4& getRegion3x4(int idx) {
554  return card3x4Regions[idx];
555  }
556  inline towers3x4& getTowers3x4(int idx) {
558  return card3x4Towers[idx];
559  }
560  };
561 
562  /*******************************************************************/
563 
564  /*
565  * Crystal class for RCT
566  */
567 
568  class crystal {
569  public:
570  ap_uint<10> energy;
571 
573  energy = 0;
574  // timing = 0;
575  }
576 
577  crystal(ap_uint<10> energy) { // To-do: add timing information
578  this->energy = energy;
579  // this->timing = 0;
580  }
581 
582  crystal& operator=(const crystal& rhs) {
583  energy = rhs.energy;
584  // timing = rhs.timing;
585  return *this;
586  }
587  };
588 
589  /*
590  * crystalMax class for RCT
591  */
592  class crystalMax {
593  public:
594  ap_uint<10> energy = 0;
595  uint8_t phiMax = 0;
596  uint8_t etaMax = 0;
597  };
598 
599  class ecaltp_t {
600  public:
601  ap_uint<10> energy;
602  ap_uint<5> phi;
603  ap_uint<5> eta;
604  };
605 
606  class etaStrip_t {
607  public:
628  };
629 
630  class ecalRegion_t {
631  public:
647  };
648 
650  public:
666  };
667 
668  class tower_t {
669  public:
670  ap_uint<16> data = 0;
671 
672  tower_t() = default;
673  tower_t(ap_uint<12> et, ap_uint<4> hoe) { data = (et) | (((ap_uint<16>)hoe) << 12); }
674 
675  ap_uint<12> et() { return (data & 0xFFF); }
676  ap_uint<4> hoe() { return ((data >> 12) & 0xF); }
677 
678  float getEt() { return (float)et() * ECAL_LSB; }
679 
680  operator uint16_t() { return (uint16_t)data; }
681 
682  // Only for ECAL towers! Apply calibration and modify the et() value.
683  void applyCalibration(float factor) {
684  // Get the new pT as a float
685  float newEt = getEt() * factor;
686 
687  // Convert the new pT to an unsigned int (16 bits so we can take the logical OR with the bit mask later)
688  ap_uint<16> newEt_uint = (ap_uint<16>)(int)(newEt * 8.0);
689  // Make sure the first four bits are zero
690  newEt_uint = (newEt_uint & 0x0FFF);
691 
692  // Modify 'data'
693  ap_uint<16> bitMask = 0xF000; // last twelve digits are zero
694  data = (data & bitMask); // zero out the last twelve digits
695  data = (data | newEt_uint); // write in the new ET
696  }
697  /*
698  * For towers: Calculate H/E ratio given the ECAL and HCAL energies and modify the hoe() value.
699  */
700  void getHoverE(ap_uint<12> ECAL, ap_uint<12> HCAL_inHcalConvention) {
701  // Convert HCAL ET to ECAL ET convention
702  ap_uint<12> HCAL = convertHcalETtoEcalET(HCAL_inHcalConvention);
703  ap_uint<4> hoeOut;
704  ap_uint<1> hoeLSB = 0;
705  ap_uint<4> hoe = 0;
706  ap_uint<12> A;
707  ap_uint<12> B;
708 
709  A = (ECAL > HCAL) ? ECAL : HCAL;
710  B = (ECAL > HCAL) ? HCAL : ECAL;
711 
712  if (ECAL == 0 || HCAL == 0 || HCAL >= ECAL)
713  hoeLSB = 0;
714  else
715  hoeLSB = 1;
716  if (A > B) {
717  if (A > 2 * B)
718  hoe = 0x1;
719  if (A > 4 * B)
720  hoe = 0x2;
721  if (A > 8 * B)
722  hoe = 0x3;
723  if (A > 16 * B)
724  hoe = 0x4;
725  if (A > 32 * B)
726  hoe = 0x5;
727  if (A > 64 * B)
728  hoe = 0x6;
729  if (A > 128 * B)
730  hoe = 0x7;
731  }
732  hoeOut = hoeLSB | (hoe << 1);
733  ap_uint<16> hoeOutLong =
734  ((((ap_uint<16>)hoeOut) << 12) | 0x0000); // e.g. 0b ____ 0000 0000 0000 where ___ are the hoe digits
735  // Take the logical OR to preserve the saturation and tower ET bits
736  ap_uint<16> bitMask = 0x0FFF; // 0000 1111 1111 1111 : zero-out the HoE bits
737  data = (data & bitMask); // zero-out the HoE bits
738  data = (data | hoeOutLong); // write in the new HoE bits
739  }
740  };
741 
742  class clusterInfo {
743  public:
744  ap_uint<10> seedEnergy = 0;
745  ap_uint<15> energy = 0;
746  ap_uint<15> et5x5 = 0;
747  ap_uint<15> et2x5 = 0;
748  ap_uint<5> phiMax = 0;
749  ap_uint<5> etaMax = 0;
750  ap_uint<2> brems = 0;
751  };
752 
753  //--------------------------------------------------------//
754 
755  /*
756  * Cluster class for RCT.
757  */
758  class Cluster {
759  public:
760  ap_uint<28> data;
761  int regionIdx; // region is 0 through 4 in barrel, 5 for overlap in barrel+endcap
762  float calib; // ECAL energy calibration factor
763  ap_uint<2> brems; // brems flag
764  ap_uint<15> et5x5; // et5x5 sum in towers around cluster
765  ap_uint<15> et2x5; // et2x5 sum in towers around cluster
766  bool is_ss; // shower shape flag
767  bool is_looseTkss; // loose Tk shower shape flag
768  bool is_iso; // isolation flag (not computed until GCT)
769  bool is_looseTkiso; // isolation flag (not computed until GCT)
770 
772  data = 0;
773  regionIdx = -1;
774  calib = 1.0;
775  brems = 0;
776  et5x5 = 0;
777  et2x5 = 0;
778  is_ss = false;
779  is_looseTkss = false;
780  is_iso = false;
781  is_looseTkiso = false;
782  }
783 
784  Cluster(ap_uint<12> clusterEnergy,
785  ap_uint<5> towerEta,
786  ap_uint<2> towerPhi,
787  ap_uint<3> clusterEta,
788  ap_uint<3> clusterPhi,
789  ap_uint<3> satur,
790  ap_uint<15> clusterEt5x5 = 0,
791  ap_uint<15> clusterEt2x5 = 0,
792  ap_uint<2> clusterBrems = 0,
793  float clusterCalib = 1.0,
794  bool cluster_is_ss = false,
795  bool cluster_is_looseTkss = false,
796  bool cluster_is_iso = false,
797  bool cluster_is_looseTkiso = false,
798  int clusterRegionIdx = 0) {
799  data = (clusterEnergy) | (((ap_uint<32>)towerEta) << 12) | (((ap_uint<32>)towerPhi) << 17) |
800  (((ap_uint<32>)clusterEta) << 19) | (((ap_uint<32>)clusterPhi) << 22) | (((ap_uint<32>)satur) << 25);
801  regionIdx = clusterRegionIdx, et5x5 = clusterEt5x5;
802  et2x5 = clusterEt2x5;
803  brems = clusterBrems;
804  calib = clusterCalib;
805  is_ss = cluster_is_ss;
806  is_looseTkss = cluster_is_looseTkss;
807  is_iso = cluster_is_iso;
808  is_looseTkiso = cluster_is_looseTkiso;
809  }
810 
811  void setRegionIdx(int regIdx) { regionIdx = regIdx; } // Newly added
812 
813  ap_uint<12> clusterEnergy() const { return (data & 0xFFF); }
814  ap_uint<5> towerEta() const { return ((data >> 12) & 0x1F); } // goes from 0 to 3 (need region for full info)
815  ap_uint<2> towerPhi() const { return ((data >> 17) & 0x3); }
816  ap_uint<3> clusterEta() const { return ((data >> 19) & 0x7); }
817  ap_uint<3> clusterPhi() const { return ((data >> 22) & 0x7); }
818  ap_uint<3> satur() const { return ((data >> 25) & 0x7); }
819  ap_uint<15> uint_et2x5() const { return et2x5; }
820  ap_uint<15> uint_et5x5() const { return et5x5; }
821 
822  operator uint32_t() const { return (ap_uint<28>)data; }
823  int region() const { return regionIdx; } // Newly added
824  int getBrems() const { return (int)brems; }
825  float getCalib() const { return (float)calib; }
826  float getPt() const { return ((float)clusterEnergy() * ECAL_LSB); } // Return pT as a float
827  float getEt5x5() const { return ((float)et5x5 * ECAL_LSB); } // Return ET5x5 as a float
828  float getEt2x5() const { return ((float)et2x5 * ECAL_LSB); } // Return ET2x5 as a float
829 
830  int towerEtaInCard() { return ((int)(region() * TOWER_IN_ETA) + towerEta()); }
831 
832  bool getIsSS() { return is_ss; }
833  bool getIsLooseTkss() { return is_looseTkss; }
834  bool getIsIso() { return is_iso; }
835  bool getIsLooseTkIso() { return is_looseTkiso; }
836 
837  /*
838  * Apply calibration (float) to the pT in-place.
839  */
840  void applyCalibration(float factor) {
841  float newPt = getPt() * factor;
842  // Convert the new pT to an unsigned int, 28 bits to take the logical OR with the mask
843  ap_uint<28> newPt_uint = (ap_uint<28>)(int)(newPt / ECAL_LSB);
844  // Make sure that the new pT only takes up the last twelve bits
845  newPt_uint = (newPt_uint & 0x0000FFF);
846 
847  // Modify 'data'
848  ap_uint<28> bitMask = 0xFFFF000; // last twelve digits are zero
849  data = (data & bitMask); // zero out the last twelve digits
850  data = (data | newPt_uint); // write in the new ET
851  }
852 
853  // Get Cluster crystal iEta from card number, region, tower eta, and cluster eta indices
855  int crystalEta_in_card =
857  if ((cc % 2) == 1) {
858  return (getCard_refCrystal_iEta(cc) + crystalEta_in_card);
859  } else {
860  // if card is even (negative eta)
861  return (getCard_refCrystal_iEta(cc) - crystalEta_in_card);
862  }
863  }
864 
865  // Get Cluster crystal iPhi from card number, region, tower eta, and cluster phi indices
867  int crystalPhi_in_card = (towerPhi() * CRYSTALS_IN_TOWER_PHI) + clusterPhi();
868  if ((cc % 2) == 1) {
869  // if card is odd (positive eta)
870  return (getCard_refCrystal_iPhi(cc) + crystalPhi_in_card);
871  } else {
872  // if card is even (negative eta)
873  return (getCard_refCrystal_iPhi(cc) - crystalPhi_in_card);
874  }
875  }
876 
877  // Get real eta
878  const float realEta(int cc) {
879  float size_cell = 2 * ECAL_eta_range / (CRYSTALS_IN_TOWER_ETA * n_towers_Eta);
881  }
882 
883  // Get real phi
884  const float realPhi(int cc) {
885  float size_cell = 2 * M_PI / (CRYSTALS_IN_TOWER_PHI * n_towers_Phi);
886  return crystaliPhiFromCardRegionInfo(cc) * size_cell - M_PI + half_crystal_size;
887  }
888 
889  // Print info
891  std::cout << "[Print Cluster class info:] [" << description << "]: "
892  << "card " << cc << ", "
893  << "et (float): " << getPt() << ", "
894  << "eta: " << realEta(cc) << ", "
895  << "phi: " << realPhi(cc) << std::endl;
896  }
897  };
898 
899  /*
900  * Compare the ET of two clusters (pass this to std::sort to get clusters sorted in decreasing ET).
901  */
902  inline bool compareClusterET(const Cluster& lhs, const Cluster& rhs) {
903  return (lhs.clusterEnergy() > rhs.clusterEnergy());
904  }
905 
906  /*******************************************************************/
907  /* RCT helper functions */
908  /*******************************************************************/
909  ecalRegion_t initStructure(crystal temporary[CRYSTAL_IN_ETA][CRYSTAL_IN_PHI]);
910  ecaltp_t bestOf2(const ecaltp_t ecaltp0, const ecaltp_t ecaltp1);
911  ecaltp_t getPeakBin20N(const etaStrip_t etaStrip);
912  crystalMax getPeakBin15N(const etaStripPeak_t etaStrip);
913  void getECALTowersEt(crystal tempX[CRYSTAL_IN_ETA][CRYSTAL_IN_PHI], ap_uint<12> towerEt[12]);
914  clusterInfo getClusterPosition(const ecalRegion_t ecalRegion);
915  Cluster packCluster(ap_uint<15>& clusterEt, ap_uint<5>& etaMax_t, ap_uint<5>& phiMax_t);
917  ap_uint<5> seed_eta,
918  ap_uint<5> seed_phi,
919  ap_uint<2> brems);
920  clusterInfo getBremsValuesPos(crystal tempX[CRYSTAL_IN_ETA][CRYSTAL_IN_PHI],
921  ap_uint<5> seed_eta,
922  ap_uint<5> seed_phi);
923  clusterInfo getBremsValuesNeg(crystal tempX[CRYSTAL_IN_ETA][CRYSTAL_IN_PHI],
924  ap_uint<5> seed_eta,
925  ap_uint<5> seed_phi);
926  clusterInfo getClusterValues(crystal tempX[CRYSTAL_IN_ETA][CRYSTAL_IN_PHI], ap_uint<5> seed_eta, ap_uint<5> seed_phi);
928  void stitchClusterOverRegionBoundary(std::vector<Cluster>& cluster_list, int towerEtaUpper, int towerEtaLower, int cc);
929 
930  /*******************************************************************/
931  /* Cluster flags */
932  /*******************************************************************/
933  inline bool passes_iso(float pt, float iso) {
934  bool is_iso = true;
935  if (pt > 130)
936  is_iso = true;
937  else if (pt < slideIsoPtThreshold) {
938  if (!((a0_80 - a1_80 * pt) > iso))
939  is_iso = false;
940  } else {
941  if (iso > a0)
942  is_iso = false;
943  }
944  return is_iso;
945  }
946 
947  inline bool passes_looseTkiso(float pt, float iso) {
948  bool is_iso;
949  if (pt > 130)
950  is_iso = true;
951  else
952  is_iso = (b0 + b1 * std::exp(-b2 * pt) > iso);
953  return is_iso;
954  }
955 
956  inline bool passes_ss(float pt, float ss) {
957  bool is_ss;
958  if (pt > 130)
959  is_ss = true;
960  else
961  is_ss = ((c0_ss + c1_ss * std::exp(-c2_ss * pt)) <= ss);
962  return is_ss;
963  }
964 
965  inline bool passes_looseTkss(float pt, float ss) {
966  bool is_ss;
967  if (pt > 130)
968  is_ss = true;
969  else
970  is_ss = ((e0_looseTkss - e1_looseTkss * std::exp(-e2_looseTkss * pt)) <= ss);
971  return is_ss;
972  }
973 
974  /*******************************************************************/
975  /* GCT classes. */
976  /*******************************************************************/
977 
978  class RCTcluster_t {
979  public:
980  ap_uint<12> et;
981  ap_uint<5> towEta; // goes from 0 to 17 (vs. class Cluster in the RCT emulator)
982  ap_uint<2> towPhi;
983  ap_uint<3> crEta;
984  ap_uint<3> crPhi;
985 
986  ap_uint<12> iso;
987  ap_uint<15> et2x5;
988  ap_uint<15> et5x5;
989  bool is_ss;
991  bool is_iso;
993  ap_uint<2> brems;
994 
995  int nGCTCard;
996  };
997 
998  class RCTtower_t {
999  public:
1000  ap_uint<12> et;
1001  ap_uint<4> hoe;
1002  // For CMSSW outputs, not firmware
1003  ap_uint<12> ecalEt;
1004  ap_uint<12> hcalEt;
1005  };
1006 
1008  public:
1011  };
1012 
1013  class RCTcard_t {
1014  public:
1016  };
1017 
1018  class GCTcard_t {
1019  public:
1022  };
1023 
1025  public:
1026  bool isPositiveEta; // is cluster in positive eta side or not
1027  ap_uint<12> et;
1028  ap_uint<6> towEta;
1029  ap_uint<7> towPhi;
1030  ap_uint<3> crEta;
1031  ap_uint<3> crPhi;
1032  ap_uint<12> iso;
1033 
1034  ap_uint<15> et2x5;
1035  ap_uint<15> et5x5;
1036  bool is_ss;
1038  bool is_iso;
1040 
1041  unsigned int hoe; // not defined
1042  unsigned int fb; // not defined
1043  unsigned int timing; // not defined
1044  ap_uint<2>
1045  brems; // 0 if no brems applied, 1 or 2 if brems applied (one for + direction, one for - direction: check firmware)
1046 
1047  float relIso; // for analyzer only, not firmware
1048  int nGCTCard; // for analyzer only, not firmware
1049 
1050  inline float etFloat() const { return ((float)et * ECAL_LSB); } // Return energy as a float
1051  inline float isoFloat() const { return ((float)iso * ECAL_LSB); } // Return energy as a float
1052  inline float et2x5Float() const { return ((float)et2x5 * ECAL_LSB); } // Return energy as a float
1053  inline float et5x5Float() const { return ((float)et5x5 * ECAL_LSB); } // Return energy as a float
1054  inline float relIsoFloat() const { return relIso; } // relIso is a float already
1055 
1056  inline int etInt() const { return et; }
1057  inline int isoInt() const { return iso; }
1058 
1059  inline int standaloneWP() const { return (is_iso && is_ss); }
1060  inline int looseL1TkMatchWP() const { return (is_looseTkiso && is_looseTkss); }
1061  inline int photonWP() const { return 1; } // NOTE: NO PHOTON WP
1062 
1063  inline int passesShowerShape() const { return is_ss; }
1064 
1065  /*
1066  * Initialize from RCTcluster_t.
1067  */
1068  void initFromRCTCluster(int iRCTcardIndex, bool isPosEta, const RCTcluster_t& rctCluster) {
1069  isPositiveEta = isPosEta;
1070 
1071  et = rctCluster.et;
1072  towEta = rctCluster.towEta;
1073  if (isPositiveEta) {
1074  towPhi = rctCluster.towPhi + (iRCTcardIndex * 4);
1075  } else {
1076  towPhi = (3 - rctCluster.towPhi) + (iRCTcardIndex * 4);
1077  }
1078  crEta = rctCluster.crEta;
1079  if (isPositiveEta) {
1080  crPhi = rctCluster.crPhi;
1081  } else {
1082  crPhi = (4 - rctCluster.crPhi);
1083  }
1084  et2x5 = rctCluster.et2x5;
1085  et5x5 = rctCluster.et5x5;
1086  is_ss = rctCluster.is_ss;
1087  is_looseTkss = rctCluster.is_looseTkss;
1088  iso = 0; // initialize: no info from RCT, so set it to null
1089  relIso = 0; // initialize: no info from RCT, so set it to null
1090  is_iso = false; // initialize: no info from RCT, so set it to false
1091  is_looseTkiso = false; // initialize: no info from RCT, so set it to false
1092  hoe = 0; // initialize: no info from RCT, so set it to null
1093  fb = 0; // initialize: no info from RCT, so set it to null
1094  timing = 0; // initialize: no info from RCT, so set it to null
1095  brems = rctCluster.brems;
1096  nGCTCard = rctCluster.nGCTCard;
1097  }
1098 
1099  /*
1100  * Get GCT cluster c's iEta (global iEta convention), (0-33*5). Called in realEta().
1101  */
1102  int globalClusteriEta(void) const {
1103  // First get the "iEta/iPhi" in the GCT card. i.e. in the diagram where the barrel is split up into three GCT cards,
1104  // (iEta, iPhi) = (0, 0) is the top left corner of the GCT card.
1105  int iEta_in_gctCard;
1106  if (!isPositiveEta) {
1107  // Negative eta: c.towEta and c.crEta count outwards from the real eta = 0 center line, so to convert to the barrel diagram global iEta
1108  // (global iEta = 0 from LHS of page), do (17*5 - 1) minus the GCT value.
1109  // e.g. If in GCT, a negative card's cluster had iEta = 84, this would be global iEta = 0.
1110  iEta_in_gctCard =
1112  } else {
1113  // c.towEta and c.crEta count outwards from the real eta = 0 center line, so for positive
1114  // eta we need to add the 17*5 offset so that positive eta 0+epsilon starts at 17*5.
1115  // e.g. If in GCT, a positive card's cluster had iEta = 0, this would be global iEta = 85.
1116  // e.g. If in GCT, a positive card's cluster had iEta = 84, this would be global iEta = 169.
1117  iEta_in_gctCard = ((N_GCTTOWERS_FIBER * CRYSTALS_IN_TOWER_ETA) + ((towEta * CRYSTALS_IN_TOWER_ETA) + crEta));
1118  }
1119  // Last, convert to the global iEta/iPhi in the barrel region. For eta these two indices are the same (but this is not true for phi).
1120  int iEta_in_barrel = iEta_in_gctCard;
1121  return iEta_in_barrel;
1122  }
1123 
1124  /*
1125  * Get GCT cluster iPhi (global convention, (0-71*5)). Called in realPhi().
1126  * Use with getPhi_fromCrystaliPhi from Phase2L1RCT.h to convert from GCT cluster to real phi.
1127  * If returnGlobalGCTiPhi is true (Default value) then return the iPhi in the entire GCT barrel. Otherwise
1128  * just return the iPhi in the current GCT card.
1129  */
1130  int globalClusteriPhi(bool returnGlobalGCTiPhi = true) const {
1131  int iPhi_in_gctCard = ((towPhi * CRYSTALS_IN_TOWER_PHI) + crPhi);
1132  // If we should return the global GCT iPhi, get the iPhi offset due to the number of the GCT card
1133  int iPhi_card_offset = 0;
1134  if (returnGlobalGCTiPhi) {
1135  if (nGCTCard == 0)
1137  else if (nGCTCard == 1)
1139  else if (nGCTCard == 2)
1141  }
1142  // Detector wraps around in phi: modulo number of crystals in phi (n_towers_Phi = 72)
1143  int iPhi_in_barrel = (iPhi_card_offset + iPhi_in_gctCard) % (n_towers_Phi * CRYSTALS_IN_TOWER_PHI);
1144  return iPhi_in_barrel;
1145  }
1146 
1147  /*
1148  * Each cluster falls in a tower: get this tower iEta in the GCT card (same as global) given the cluster's info.
1149  */
1150  int globalToweriEta(void) const { return (int)(globalClusteriEta() / 5); }
1151 
1152  /*
1153  * Each cluster falls in a tower: get this tower iPhi in global given the cluster's info.
1154  */
1155  int globalToweriPhi(void) const {
1156  bool getGlobalIndex = true;
1157  return (int)(globalClusteriPhi(getGlobalIndex) / 5);
1158  }
1159 
1160  /*
1161  * Get tower iPhi IN GCT CARD
1162  */
1163  int inCardToweriPhi(void) const {
1164  bool getGlobalIndex = false;
1165  return (int)(globalClusteriPhi(getGlobalIndex) / 5);
1166  }
1167 
1168  /*
1169  * Get tower iEta IN GCT CARD (conveniently the same as global eta)
1170  */
1171  int inCardToweriEta(void) const { return (int)(globalClusteriEta() / 5); }
1172 
1173  /*
1174  * Get GCT cluster's real eta from global iEta (0-33*5).
1175  */
1176  float realEta(void) const {
1177  float size_cell = 2 * ECAL_eta_range / (CRYSTALS_IN_TOWER_ETA * n_towers_Eta);
1178  return globalClusteriEta() * size_cell - ECAL_eta_range + half_crystal_size;
1179  }
1180 
1181  /*
1182  * Get GCT cluster's real eta from global iPhi (0-71*5).
1183  */
1184  float realPhi(void) const {
1185  float size_cell = 2 * M_PI / (CRYSTALS_IN_TOWER_PHI * n_towers_Phi);
1186  return globalClusteriPhi() * size_cell - M_PI + half_crystal_size;
1187  }
1188 
1189  /*
1190  * Return the 4-vector.
1191  */
1194  }
1195 
1196  /*
1197  * Compute relative isolation and set its flags in-place, assuming that the isolation is already computed.
1198  */
1199  void setRelIsoAndFlags(void) {
1200  float relativeIsolationAsFloat = 0;
1201  if (et > 0) {
1202  relativeIsolationAsFloat = (isoFloat() / etFloat());
1203  } else {
1204  relativeIsolationAsFloat = 0;
1205  }
1206  relIso = relativeIsolationAsFloat;
1209  }
1210 
1211  /*
1212  * Create a l1tp2::CaloCrystalCluster object.
1213  */
1215  l1tp2::CaloCrystalCluster caloCrystalCluster(
1216  p4(),
1217  etFloat(), // convert to float
1218  0, // supposed to be H over E in the constructor but we do not store/use this information
1219  relIsoFloat(), // for consistency with the old emulator, in this field save (iso energy sum)/(cluster energy)
1220  0, // DetId seedCrystal
1221  0, // puCorrPt
1222  0, // brems: not propagated to output (0, 1, or 2 as computed in firmware)
1223  0, // et2x2 (not calculated)
1224  et2x5Float(), // et2x5 (save float)
1225  0, // et3x5 (not calculated)
1226  et5x5Float(), // et5x5 (save float)
1227  standaloneWP(), // standalone WP
1228  false, // electronWP98: not computed
1229  false, // photonWP80: not computed
1230  false, // electronWP90: not computed
1231  false, // looseL1TkMatchWP: not computed
1232  false // stage2effMatch: not computed
1233  );
1234 
1235  // Flags
1236  std::map<std::string, float> params;
1237  params["standaloneWP_showerShape"] = is_ss;
1238  params["standaloneWP_isolation"] = is_iso;
1239  params["trkMatchWP_showerShape"] = is_looseTkss;
1240  params["trkMatchWP_isolation"] = is_looseTkiso;
1241  caloCrystalCluster.setExperimentalParams(params);
1242 
1243  return caloCrystalCluster;
1244  }
1245 
1246  /*
1247  * Create a l1t::EGamma object.
1248  */
1250  // n.b. No photon WP, photonWP() always returns true
1251  int quality =
1252  (standaloneWP() * std::pow(2, 0)) + (looseL1TkMatchWP() * std::pow(2, 1)) + (photonWP() * std::pow(2, 2));
1253 
1254  // The constructor zeros out everyhing except the p4()
1256 
1257  // Write in fields that were zerod out
1258  eg.setRawEt(etInt()); // et as int
1259  eg.setTowerIEta(globalToweriEta()); // 0-33 in barrel
1260  eg.setTowerIPhi(globalToweriPhi()); // 0-71 in barrel
1261  eg.setIsoEt(isoInt()); // raw isolation sum as int
1262  eg.setShape(passesShowerShape()); // write shower shape flag to this field
1263  return eg;
1264  }
1265 
1266  /*
1267  * Create a l1tp2::DigitizedClusterCorrelator object, with corrTowPhiOffset specifying the offset necessary to correct the tower phi to the region
1268  * unique to each GCT card.
1269  */
1272  etFloat(), // technically we are just multiplying and then dividing again by the LSB
1273  towEta,
1274  towPhi - corrTowPhiOffset,
1275  crEta,
1276  crPhi,
1277  hoe,
1278  is_iso,
1279  fb,
1280  timing,
1281  is_ss,
1282  brems,
1283  nGCTCard);
1284  }
1285 
1286  /*
1287  * Create a l1tp2::DigitizedClusterGT object
1288  */
1290  // Constructor arguments take phi, then eta
1292  }
1293 
1294  /*
1295  * Print GCT cluster information.
1296  */
1298  std::cout << "[PrintGCTClusterInfo:] [" << description << "]: "
1299  << "et (float): " << etFloat() << ", "
1300  << "eta: " << realEta() << ", "
1301  << "phi: " << realPhi() << ", "
1302  << "isPositiveEta " << isPositiveEta << ", "
1303  << "towEta: " << towEta << ", "
1304  << "towPhi: " << towPhi << ", "
1305  << "crEta: " << crEta << ", "
1306  << "crPhi: " << crPhi << ", "
1307  << "iso (GeV): " << isoFloat() << ", "
1308  << "rel iso (unitless float): " << relIsoFloat() << ", "
1309  << "et2x5 (GeV): " << et2x5Float() << ", "
1310  << "et5x5 (GeV): " << et5x5Float() << ", "
1311  << "is_ss: " << is_ss << ", "
1312  << "is_looseTkss" << is_looseTkss << ", "
1313  << "is_iso: " << is_iso << ", "
1314  << "is_looseTkiso: " << is_looseTkiso << ", "
1315  << "brems: " << brems << std::endl;
1316  }
1317  };
1318 
1319  class GCTtower_t {
1320  public:
1321  ap_uint<12> et;
1322  ap_uint<4> hoe;
1323  ap_uint<2> fb; // not defined yet in emulator
1324  // For CMSSW outputs, not firmware
1325  ap_uint<12> ecalEt;
1326  ap_uint<12> hcalEt;
1327 
1328  inline float totalEtFloat() const {
1329  return ((float)et * ECAL_LSB);
1330  } // Return total energy as a float (assuming the energy uses the ECAL LSB convention)
1331  inline float ecalEtFloat() const { return ((float)ecalEt * ECAL_LSB); } // Return ECAL energy as a float
1332  inline float hcalEtFloat() const {
1333  return ((float)hcalEt * HCAL_LSB);
1334  } // Return HCAL energy as a float, use HCAL LSB
1335 
1336  /*
1337  * Initialize from RCTtower_t.
1338  */
1339  void initFromRCTTower(const RCTtower_t& rctTower) {
1340  et = rctTower.et;
1341  hoe = rctTower.hoe;
1342  ecalEt = rctTower.ecalEt;
1343  hcalEt = rctTower.hcalEt;
1344  }
1345 
1346  /*
1347  * Correlator fiber convention -> Global GCT convention
1348  * Get tower's global (iEta) from the GCTCorrFiber index [0, 64) and the tower's postion in the fiber [0, 17).
1349  * Recall that GCTCorrFiber is [0, 32) for negative eta and [32, 64) for positive eta. The tower's position in the fiber [0, 17)
1350  * always counts outwards from real eta = 0.
1351  * Use in conjunction with (float) getTowerEta_fromAbsID(int id) from Phase2L1RCT.h to get a tower's real eta.
1352  */
1353  int globalToweriEta(unsigned int nGCTCard, unsigned int gctCorrFiberIdx, unsigned int posInFiber) {
1354  (void)nGCTCard; // not needed
1355  bool isTowerInPositiveEta = (gctCorrFiberIdx < N_GCTPOSITIVE_FIBERS); // N_GCTPOSITIVE_FIBERS = 32
1356  int global_toweriEta;
1357  if (isTowerInPositiveEta) {
1358  global_toweriEta = (N_GCTTOWERS_FIBER + posInFiber); // N_GCTTOWERS_FIBER = 17
1359  } else {
1360  // e.g. For negative eta, posInFiber = 0 is at real eta = 0, and global tower iEta is 17 - 1 - 0 = 16
1361  // posInFiber = 16 is at real eta = -1.4841, and global tower iEta is 17 - 1 - 16 = 0.
1362  global_toweriEta = (N_GCTTOWERS_FIBER - 1 - posInFiber);
1363  }
1364  return global_toweriEta;
1365  }
1366 
1367  /*
1368  * Correlator fiber convention -> Global GCT convention
1369  * Get tower's global (iPhi) from the GCT card number (0, 1, 2), and the GCTCorrFiber index [0, 64).
1370  * GCTCorrFiber is [0, 32) for negative eta and [32, 64) for positive eta. In the phi direction, fiber index #0 has the same phi
1371  * as fiber index #32, so only the (fiber index modulo 32) matters for the phi direction.
1372  * The tower's position in the fiber doesn't matter; in each fiber the phi is the same.
1373  * Use in conjunction with (float) getTowerPhi_fromAbsID(int id) from Phase2L1RCT.h to get a tower's real phi.
1374  */
1375  int globalToweriPhi(unsigned int nGCTCard, unsigned int gctCorrFiberIdx, unsigned int posInFiber) {
1376  (void)posInFiber; // not needed
1377  unsigned int effectiveFiberIdx = (gctCorrFiberIdx % N_GCTPOSITIVE_FIBERS); // N_GCTPOSITIVE_FIBERS = 32
1378  int toweriPhi_card_offset = 0;
1379  if (nGCTCard == 0)
1380  toweriPhi_card_offset = GCTCARD_0_TOWER_IPHI_OFFSET;
1381  else if (nGCTCard == 1)
1382  toweriPhi_card_offset = GCTCARD_1_TOWER_IPHI_OFFSET;
1383  else if (nGCTCard == 2)
1384  toweriPhi_card_offset = GCTCARD_2_TOWER_IPHI_OFFSET;
1385 
1386  // as explained above, effectiveFiberIdx is [0, 32). n_towers_Phi = 72:
1387  int global_tower_iPhi = (toweriPhi_card_offset + effectiveFiberIdx) % (n_towers_Phi);
1388  return global_tower_iPhi;
1389  }
1390 
1391  /*
1392  * For fulltowers that are indexed by GCT local index: eta
1393  */
1394  int globalToweriEtaFromGCTcardiEta(int gctCard_tower_iEta) {
1395  int global_iEta = gctCard_tower_iEta;
1396  return global_iEta;
1397  }
1398 
1399  /*
1400  * For fulltowers that are indexed by GCT local index: phi. Very similar to globalToweriPhi function but keep them separate for clarity.
1401  */
1402  int globalToweriPhiFromGCTcardiPhi(unsigned int nGCTCard, int gctCard_tower_iPhi) {
1403  assert(nGCTCard <= 2); // Make sure the card number is valid
1404  int toweriPhi_card_offset = 0;
1405  if (nGCTCard == 0)
1406  toweriPhi_card_offset = GCTCARD_0_TOWER_IPHI_OFFSET;
1407  else if (nGCTCard == 1)
1408  toweriPhi_card_offset = GCTCARD_1_TOWER_IPHI_OFFSET;
1409  else if (nGCTCard == 2)
1410  toweriPhi_card_offset = GCTCARD_2_TOWER_IPHI_OFFSET;
1411 
1412  int global_iPhi = (toweriPhi_card_offset + gctCard_tower_iPhi) % (n_towers_Phi); // n_towers_Phi = 72
1413  return global_iPhi;
1414  }
1415 
1416  /*
1417  * Method to create a l1tp2::CaloTower object from the fiber and tower-in-fiber indices.
1418  * nGCTCard (0, 1, 2) is needed to determine the absolute eta/phi.
1419  * iFiber and iTowerInFiber are the indices of the tower in the card, e.g. GCTinternal.GCTCorrFiber[iFiber].GCTtowers[iTowerInFiber]
1420  */
1421  l1tp2::CaloTower createCaloTowerFromFiberIdx(int nGCTCard, int iFiber, int iTowerInFiber) {
1422  l1tp2::CaloTower l1CaloTower;
1423  l1CaloTower.setEcalTowerEt(ecalEtFloat()); // float: ECAL divide by 8.0
1424  l1CaloTower.setHcalTowerEt(hcalEtFloat()); // float: HCAL multiply by LSB
1425  int global_tower_iEta = globalToweriEta(nGCTCard, iFiber, iTowerInFiber);
1426  int global_tower_iPhi = globalToweriPhi(nGCTCard, iFiber, iTowerInFiber);
1427  l1CaloTower.setTowerIEta(global_tower_iEta);
1428  l1CaloTower.setTowerIPhi(global_tower_iPhi);
1429  l1CaloTower.setTowerEta(getTowerEta_fromAbsID(global_tower_iEta));
1430  l1CaloTower.setTowerPhi(getTowerPhi_fromAbsID(global_tower_iPhi));
1431  return l1CaloTower;
1432  }
1433 
1434  /*
1435  * Method to create a l1tp2::CaloTower object from the global tower ieta and iphi.
1436  */
1437  l1tp2::CaloTower createFullTowerFromCardIdx(int nGCTCard, int gctCard_tower_iEta, int gctCard_tower_iPhi) {
1438  l1tp2::CaloTower l1CaloTower;
1439  // Store total Et (HCAL+ECAL) in the ECAL Et member
1440  l1CaloTower.setEcalTowerEt(totalEtFloat());
1441  int global_tower_iEta = globalToweriEtaFromGCTcardiEta(gctCard_tower_iEta);
1442  int global_tower_iPhi = globalToweriPhiFromGCTcardiPhi(nGCTCard, gctCard_tower_iPhi);
1443  l1CaloTower.setTowerIEta(global_tower_iEta);
1444  l1CaloTower.setTowerIPhi(global_tower_iPhi);
1445  l1CaloTower.setTowerEta(getTowerEta_fromAbsID(global_tower_iEta));
1446  l1CaloTower.setTowerPhi(getTowerPhi_fromAbsID(global_tower_iPhi));
1447  return l1CaloTower;
1448  }
1449 
1450  /*
1451  * Method to create a l1tp2::DigitizedTowerCorrelator, from the GCT card number, the fiber index *inside the GCT card* (excluding overlap region),
1452  * and the index of the tower inside the fiber.
1453  */
1455  unsigned int indexFiber,
1456  unsigned int indexTower) {
1457  return l1tp2::DigitizedTowerCorrelator(totalEtFloat(), hoe, fb, indexCard, indexFiber, indexTower);
1458  }
1459 
1460  /*
1461  * Print GCTtower_t tower information.
1462  */
1463  void printGCTTowerInfoFromGlobalIdx(int global_tower_iEta, int global_tower_iPhi, std::string description = "") {
1464  std::cout << "[Print GCTtower_t class info from global idx:] [" << description << "]: "
1465  << "total et (float): " << totalEtFloat() << ", "
1466  << "ecal et (float): " << ecalEtFloat() << ", "
1467  << "hcal et (float): " << hcalEtFloat() << ", "
1468  << "fb: " << fb << ", "
1469  << "global tower ieta: " << global_tower_iEta << ", "
1470  << "global tower iphi: " << global_tower_iPhi << ", "
1471  << "eta: " << getTowerEta_fromAbsID(global_tower_iEta) << ", "
1472  << "phi: " << getTowerPhi_fromAbsID(global_tower_iPhi) << std::endl;
1473  }
1474  };
1475 
1477  public:
1480  };
1481 
1482  class GCTtoCorr_t {
1483  public:
1485  };
1486 
1488  public:
1490 
1491  void computeClusterIsolationInPlace(int nGCTCard) {
1492  for (unsigned int iFiber = 0; iFiber < N_GCTINTERNAL_FIBERS; iFiber++) {
1493  for (unsigned int iCluster = 0; iCluster < N_GCTCLUSTERS_FIBER; iCluster++) {
1494  // We will only save clusters with > 0 GeV, so only need to do this for clusters with >0 energy
1495  if (GCTCorrfiber[iFiber].GCTclusters[iCluster].et == 0) {
1496  GCTCorrfiber[iFiber].GCTclusters[iCluster].iso = 0;
1497  continue;
1498  }
1499 
1500  ap_uint<12> uint_isolation = 0;
1501 
1502  // do not add the GCT card off-set, so we remain in the gct local card iEta/iPhi
1503  int toweriEta_in_GCT_card = GCTCorrfiber[iFiber].GCTclusters[iCluster].inCardToweriEta();
1504  int toweriPhi_in_GCT_card = GCTCorrfiber[iFiber].GCTclusters[iCluster].inCardToweriPhi();
1505 
1506  // If cluster is in the overlap region, do not compute isolation
1507  bool inOverlapWithAnotherGCTCard = (((toweriPhi_in_GCT_card >= 0) && (toweriPhi_in_GCT_card < 4)) ||
1508  ((toweriPhi_in_GCT_card >= 28) && (toweriPhi_in_GCT_card < 32)));
1509  if (inOverlapWithAnotherGCTCard) {
1510  GCTCorrfiber[iFiber].GCTclusters[iCluster].iso = 0;
1511  continue;
1512  }
1513 
1514  // Size 5x5 in towers: include the overlap-region-between-GCT-cards-if-applicable. In eta direction, the min and max towers (inclusive!) are:
1515  int isoWindow_toweriEta_in_GCT_card_min = std::max(0, toweriEta_in_GCT_card - 2);
1516  int isoWindow_toweriEta_in_GCT_card_max = std::min(toweriEta_in_GCT_card + 2, N_GCTETA - 1); // N_GCTETA = 34
1517  // e.g. if our window is centered at tower_iEta = 5, we want to sum towers_iEta 3, 4, (5), 6, 7, inclusive
1518  // e.g. if our window is near the boundary, tower_iEta = 32, we want to sum towers_iEta 30, 31, (32), 33
1519  // inclusive (but there are only N_GCTETA = 34 towers, so we stop at tower_iEta = 33)
1520 
1521  // in phi direction, the min and max towers (inclusive!) are:
1522  int isoWindow_toweriPhi_in_GCT_card_min = std::max(0, toweriPhi_in_GCT_card - 2);
1523  int isoWindow_toweriPhi_in_GCT_card_max = std::min(toweriPhi_in_GCT_card + 2, N_GCTPHI - 1);
1524 
1525  // Keep track of the number of towers we summed over
1526  int nTowersSummed = 0;
1527 
1528  // First add any nearby clusters to the isolation
1529  for (unsigned int candFiber = 0; candFiber < N_GCTINTERNAL_FIBERS; candFiber++) {
1530  for (unsigned int candCluster = 0; candCluster < N_GCTCLUSTERS_FIBER; candCluster++) {
1531  // Do not double-count the cluster we are calculating the isolation for
1532  if (!((candFiber == iFiber) && (candCluster == iCluster))) {
1533  // Only consider clusters with et > 0 for isolation sum
1534  if (GCTCorrfiber[candFiber].GCTclusters[candCluster].et > 0) {
1535  // Get the candidate cluster's tower iEta and iPhi in GCT card
1536  int candidate_toweriEta = GCTCorrfiber[candFiber].GCTclusters[candCluster].inCardToweriEta();
1537  int candidate_toweriPhi = GCTCorrfiber[candFiber].GCTclusters[candCluster].inCardToweriPhi();
1538 
1539  // If the tower that the candidate cluster is in, is within a 5x5 window, add the candidate cluster energy's to the isolation as a proxy for the ECAL energy
1540  if (((candidate_toweriEta >= isoWindow_toweriEta_in_GCT_card_min) &&
1541  (candidate_toweriEta <= isoWindow_toweriEta_in_GCT_card_max)) &&
1542  ((candidate_toweriPhi >= isoWindow_toweriPhi_in_GCT_card_min) &&
1543  (candidate_toweriPhi <= isoWindow_toweriPhi_in_GCT_card_max))) {
1544  uint_isolation += GCTCorrfiber[candFiber].GCTclusters[candCluster].et;
1545  }
1546  }
1547  }
1548  }
1549  }
1550 
1551  // From "tower index in GCT card", get which fiber it is in (out of 64 fibers), and which tower it is inside the fiber (out of 17 towers)
1552  for (int iEta = isoWindow_toweriEta_in_GCT_card_min; iEta <= isoWindow_toweriEta_in_GCT_card_max; iEta++) {
1553  for (int iPhi = isoWindow_toweriPhi_in_GCT_card_min; iPhi <= isoWindow_toweriPhi_in_GCT_card_max; iPhi++) {
1554  nTowersSummed += 1;
1555 
1556  int indexInto64Fibers;
1557  int indexInto17TowersInFiber;
1558 
1559  bool isTowerInPositiveEta = (iEta >= N_GCTTOWERS_FIBER);
1560  if (isTowerInPositiveEta) {
1561  // phi index is simple (e.g. if real phi = +80 degrees, iPhi in GCT = 31)
1562  indexInto64Fibers = iPhi;
1563  // if real eta = 1.47, iEta in GCT card = 33. If real eta = 0.0, iEta in GCT = 17, so iEta in fiber = 17%17 = 0.
1564  indexInto17TowersInFiber = (iEta % 17);
1565  } else {
1566  // add offset (e.g. if real phi = +80 degrees, iPhi in GCT = 31, and my index into GCT fibers 31 + 32 = 63)
1567  indexInto64Fibers = (iPhi + N_GCTPOSITIVE_FIBERS);
1568  // e.g. if real eta = 0, iEta innew GCT card = 16, i.e. our index into the GCT fiber is 16-16 = 0
1569  indexInto17TowersInFiber = (16 - iEta);
1570  }
1571 
1572  ap_uint<12> ecalEt = GCTCorrfiber[indexInto64Fibers].GCTtowers[indexInto17TowersInFiber].ecalEt;
1573  uint_isolation += ecalEt;
1574  }
1575  }
1576 
1577  // Scale the isolation sum up if we summed over fewer than (5x5) = 25 towers
1578  float scaleFactor =
1580 
1581  uint_isolation = (ap_uint<12>)(((float)uint_isolation) * scaleFactor);
1582 
1583  // Set the iso in the cluster
1584  GCTCorrfiber[iFiber].GCTclusters[iCluster].iso = uint_isolation;
1585  }
1586  }
1587  }
1588 
1589  void setIsolationInfo(void) {
1590  for (unsigned int iFiber = 0; iFiber < N_GCTINTERNAL_FIBERS; iFiber++) {
1591  for (unsigned int iCluster = 0; iCluster < N_GCTCLUSTERS_FIBER; iCluster++) {
1592  // update the cluster's isolation information
1593  GCTCorrfiber[iFiber].GCTclusters[iCluster].setRelIsoAndFlags();
1594  }
1595  }
1596  }
1597  };
1598 
1600  public:
1602 
1603  // Write contents to output CMSSW collection. Note the use of the GCTtower_t method that creates the
1604  // l1tp2::CaloTower object from the global eta/phi.
1605  void writeToPFOutput(int nGCTCard, std::unique_ptr<l1tp2::CaloTowerCollection> const& gctFullTowers) {
1606  for (unsigned int iEta = 0; iEta < N_GCTETA; iEta++) {
1607  for (unsigned int iPhi = 0; iPhi < N_GCTPHI; iPhi++) {
1608  GCTtower_t thisFullTower = GCTtower[iEta][iPhi];
1609  gctFullTowers->push_back(thisFullTower.createFullTowerFromCardIdx(nGCTCard, iEta, iPhi));
1610  }
1611  }
1612  }
1613  };
1614 
1615  /* For each GCT card (3 of them in total, for barrel + endcap), list the sixteen
1616  * RCT cards that fall in them. The first eight are in positive eta, the next
1617  * eight are in negative eta (see figure of one GCT card). The RCT cards themselves
1618  * run from 0 to 35 (see RCT figure).
1619  * Hard-coded because the GCT cards wrap around the barrel region.
1620  * Used only to convert the RCT emulator outputs to the GCT emulator inputs.
1621  */
1622  static const unsigned int GCTcardtoRCTcardnumber[N_GCTCARDS][N_RCTCARDS_PHI * 2] = {
1623  // GCT Card 0
1624  {11, 13, 15, 17, 19, 21, 23, 25, 10, 12, 14, 16, 18, 20, 22, 24},
1625 
1626  // GCT Card 1
1627  {23, 25, 27, 29, 31, 33, 35, 1, 22, 24, 26, 28, 30, 32, 34, 0},
1628 
1629  // GCT Card 2
1630  {35, 1, 3, 5, 7, 9, 11, 13, 34, 0, 2, 4, 6, 8, 10, 12}};
1631 
1632  /*
1633  * Helper function to monitor l1tp2::CaloTower members.
1634  */
1636  std::cout << "[Print l1tp2::CaloTower info:] [" << description << "]: "
1637  << ".ecalTowerEta() (float): " << thisTower.ecalTowerEt() << ", "
1638  << ".hcalTowerEta() (float): " << thisTower.hcalTowerEt() << ", "
1639  << ".towerIEta(): " << thisTower.towerIEta() << ", "
1640  << ".towerIPhi(): " << thisTower.towerIPhi() << ", "
1641  << ".towerEta() " << thisTower.towerEta() << ", "
1642  << ".towerPhi() " << thisTower.towerPhi() << std::endl;
1643  }
1644 
1645  void algo_top(const GCTcard_t& GCTcard,
1646  GCTtoCorr_t& GCTtoCorr,
1647  unsigned int nGCTCard,
1648  std::unique_ptr<l1tp2::CaloCrystalClusterCollection> const& gctClusters,
1649  std::unique_ptr<l1tp2::CaloTowerCollection> const& gctTowers,
1650  std::unique_ptr<l1tp2::CaloTowerCollection> const& gctFullTowers,
1651  std::unique_ptr<l1t::EGammaBxCollection> const& gctEGammas,
1652  std::unique_ptr<l1tp2::DigitizedClusterCorrelatorCollection> const& gctDigitizedClustersCorrelator,
1653  std::unique_ptr<l1tp2::DigitizedTowerCorrelatorCollection> const& gctDigitizedTowersCorrelator,
1654  std::unique_ptr<l1tp2::DigitizedClusterGTCollection> const& gctDigitizedClustersGT,
1656 
1657  GCTinternal_t getClustersTowers(const GCTcard_t& GCTcard, unsigned int nGCTCard);
1658 
1659  void doProximityAndBremsStitching(const RCTcard_t (&inputCards)[N_RCTCARDS_PHI],
1660  RCTcard_t (&outputCards)[N_RCTCARDS_PHI],
1661  int iStartingCard,
1662  bool isPositiveEta);
1663 
1664  GCTcard_t getClustersCombined(const GCTcard_t& GCTcard, unsigned int nGCTCard);
1665 
1666  GCTintTowers_t getFullTowers(const GCTinternal_t& GCTinternal);
1667 
1669  const GCTinternal_t& GCTinternal,
1670  GCTtoCorr_t& GCTtoCorrOutput,
1671  std::unique_ptr<l1tp2::CaloCrystalClusterCollection> const& gctClustersOutput,
1672  std::unique_ptr<l1tp2::CaloTowerCollection> const& gctTowersOutput,
1673  std::unique_ptr<l1t::EGammaBxCollection> const& gctEGammas,
1674  std::unique_ptr<l1tp2::DigitizedClusterCorrelatorCollection> const& gctDigitizedClustersCorrelator,
1675  std::unique_ptr<l1tp2::DigitizedTowerCorrelatorCollection> const& gctDigitizedTowersCorrelator,
1676  std::unique_ptr<l1tp2::DigitizedClusterGTCollection> const& gctDigitizedClustersGT,
1677  int nGCTCard,
1678  int fiberStart,
1679  int fiberEnd,
1680  int corrFiberIndexOffset,
1681  int corrTowPhiOffset);
1682 
1683 } // namespace p2eg
1684 
1685 #endif
static constexpr float ECAL_eta_range
static constexpr float half_crystal_size
void setRawEt(short int pt)
Definition: EGamma.cc:32
void applyCalibration(float factor)
region3x4 card3x4Regions[N_REGIONS_PER_CARD]
GCTCorrfiber_t GCTCorrfiber[N_GCTCORR_FIBERS]
ap_uint< 3 > clusterEta() const
int crystalLocaliEta(int cc) const
float ecalTowerEt() const
Definition: CaloTower.h:35
static constexpr int N_GCTCLUSTERS_FIBER
static constexpr float b1
void getECALTowersEt(crystal tempX[CRYSTAL_IN_ETA][CRYSTAL_IN_PHI], ap_uint< 12 > towerEt[12])
card operator=(const card &other)
GCTtower_t GCTtower[N_GCTETA][N_GCTPHI]
static constexpr int N_GCTTOWERS_CLUSTER_ISO_ONESIDE
Definition: APVGainStruct.h:7
const bool isValid(const Frame &aFrame, const FrameQuality &aQuality, const uint16_t aExpectedPos)
RCTcluster_t RCTclusters[N_RCTCLUSTERS_FIBER]
ap_uint< 15 > uint_et2x5() const
l1tp2::CaloCrystalCluster createCaloCrystalCluster(void) const
int getCard_iEtaMax(int cc)
static constexpr float c2_ss
bool passes_iso(float pt, float iso)
void setEcalTowerEt(float et)
Definition: CaloTower.h:49
static constexpr float e2_looseTkss
GCTCorrfiber_t GCTCorrfiber[N_GCTINTERNAL_FIBERS]
int towerIPhi() const
Definition: CaloTower.h:37
uint32_t cc[maxCellsPerHit]
Definition: gpuFishbone.h:49
Geom::Phi< T > phi() const
Definition: PV3DBase.h:66
static constexpr int GCTCARD_1_TOWER_IPHI_OFFSET
void printl1tp2TowerInfo(l1tp2::CaloTower thisTower, std::string description="")
clusterInfo getClusterValues(crystal tempX[CRYSTAL_IN_ETA][CRYSTAL_IN_PHI], ap_uint< 5 > seed_eta, ap_uint< 5 > seed_phi)
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
linkECAL & getLinkECAL(int iEta, int iPhi)
T eta() const
Definition: PV3DBase.h:73
void setTowerIPhi(int iPhi)
Definition: CaloTower.h:51
void setIdHcal(const HcalDetId &idhcal)
int crystalLocaliPhi(int cc) const
clusterInfo getClusterPosition(const ecalRegion_t ecalRegion)
Definition: Phase2L1RCT.h:1060
static constexpr int n_towers_Eta
static constexpr int n_clusters_4link
void setPosition(const GlobalVector &pos)
static constexpr float a1_80
int getCard_iPhiMin(int cc)
l1tp2::CaloTower createFullTowerFromCardIdx(int nGCTCard, int gctCard_tower_iEta, int gctCard_tower_iPhi)
void addCrystalE(int iEta, int iPhi, ap_uint< 10 > energy)
void setRegionIdx(int regIdx)
reco::Candidate::PolarLorentzVector p4(void) const
static constexpr int N_GCTPOSITIVE_FIBERS
int globalToweriPhi(unsigned int nGCTCard, unsigned int gctCorrFiberIdx, unsigned int posInFiber)
static constexpr int N_GCTTOWERS_FIBER
static constexpr int n_crystals_cardPhi
int getAbsID_iPhi_fromFirmwareCardTowerLink(int nCard, int nTower, int nLink)
static constexpr int n_towers_Phi
T mag2() const
Definition: PV3DBase.h:63
assert(be >=bs)
ap_uint< 15 > uint_et5x5() const
ap_uint< 10 > crystalE[CRYSTALS_IN_TOWER_ETA][CRYSTALS_IN_TOWER_PHI]
static constexpr int N_REGIONS_PER_CARD
static constexpr int N_CLUSTERS_PER_REGION
RCTtower_t RCTtowers[N_RCTTOWERS_FIBER]
int globalToweriEta(unsigned int nGCTCard, unsigned int gctCorrFiberIdx, unsigned int posInFiber)
bool isInCard(int cc) const
static constexpr int GCTCARD_0_TOWER_IPHI_OFFSET
void removeClusterFromCrystal(crystal temp[CRYSTAL_IN_ETA][CRYSTAL_IN_PHI], ap_uint< 5 > seed_eta, ap_uint< 5 > seed_phi, ap_uint< 2 > brems)
TEMPL(T2) struct Divides void
Definition: Factorize.h:24
Cluster(ap_uint< 12 > clusterEnergy, ap_uint< 5 > towerEta, ap_uint< 2 > towerPhi, ap_uint< 3 > clusterEta, ap_uint< 3 > clusterPhi, ap_uint< 3 > satur, ap_uint< 15 > clusterEt5x5=0, ap_uint< 15 > clusterEt2x5=0, ap_uint< 2 > clusterBrems=0, float clusterCalib=1.0, bool cluster_is_ss=false, bool cluster_is_looseTkss=false, bool cluster_is_iso=false, bool cluster_is_looseTkiso=false, int clusterRegionIdx=0)
GCTcluster_t GCTclusters[N_GCTCLUSTERS_FIBER]
crystal(ap_uint< 10 > energy)
void setHcalTowerEt(float et)
Definition: CaloTower.h:50
static constexpr int CRYSTAL_IN_ETA
void setTowerIEta(int iEta)
Definition: CaloTower.h:52
float getTowerPhi_fromAbsID(int id)
int getCard_refCrystal_iEta(int cc)
void printHitInfo(std::string description="") const
string quality
int globalClusteriPhi(bool returnGlobalGCTiPhi=true) const
crystal & operator=(const crystal &rhs)
static constexpr float c0_ss
bool passes_ss(float pt, float ss)
tower_t()=default
Cluster getClusterFromRegion3x4(crystal temp[CRYSTAL_IN_ETA][CRYSTAL_IN_PHI])
static constexpr int n_towers_per_link
void setTowerPhi(float phi)
Definition: CaloTower.h:53
ecalRegion_t initStructure(crystal temporary[CRYSTAL_IN_ETA][CRYSTAL_IN_PHI])
void printGCTTowerInfoFromGlobalIdx(int global_tower_iEta, int global_tower_iPhi, std::string description="")
ecaltp_t getPeakBin20N(const etaStrip_t etaStrip)
Definition: Phase2L1RCT.h:950
region3x4 operator=(const region3x4 &other)
card(const card &other)
static constexpr int N_GCTPHI
ap_uint< 5 > towerEta() const
l1t::EGamma createL1TEGamma(void) const
const GlobalVector & position() const
static constexpr float HCAL_LSB
void computeClusterIsolationInPlace(int nGCTCard)
RCTcard_t RCTcardEtaNeg[N_RCTCARDS_PHI]
float getTowerEta_fromAbsID(int id)
static constexpr float slideIsoPtThreshold
static constexpr int N_RCTCARDS_PHI
towerHCAL & getTowerHCAL(int iEta, int iPhi)
void setIdx(int idx)
l1tp2::DigitizedClusterGT createDigitizedClusterGT(bool isValid) const
ap_uint< 3 > satur() const
static constexpr int N_RCTTOWERS_FIBER
static constexpr int GCTCARD_2_TOWER_IPHI_OFFSET
int globalToweriPhiFromGCTcardiPhi(unsigned int nGCTCard, int gctCard_tower_iPhi)
static constexpr float ECAL_LSB
GCTcard_t getClustersCombined(const GCTcard_t &GCTcard, unsigned int nGCTCard)
Definition: Phase2L1GCT.h:98
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
static constexpr int n_towers_cardPhi
static constexpr int N_RCTGCT_FIBERS
tower_t(ap_uint< 12 > et, ap_uint< 4 > hoe)
constexpr G4double scaleFactor
towerHCAL towersHCAL[TOWER_IN_ETA][TOWER_IN_PHI]
int towerIEta() const
Definition: CaloTower.h:38
ap_uint< 10 > et_uint() const
static constexpr int N_RCTCLUSTERS_FIBER
void stitchClusterOverRegionBoundary(std::vector< Cluster > &cluster_list, int towerEtaUpper, int towerEtaLower, int cc)
Definition: Phase2L1RCT.h:1478
ap_uint< 3 > clusterPhi() const
const float realPhi(int cc)
l1tp2::DigitizedClusterCorrelator createDigitizedClusterCorrelator(const int corrTowPhiOffset) const
int getRegionNumber(const int local_iEta)
int getCard_iPhiMax(int cc)
int getCard_iEtaMin(int cc)
l1tp2::CaloTower createCaloTowerFromFiberIdx(int nGCTCard, int iFiber, int iTowerInFiber)
static constexpr float cut_500_MeV
void setTowerEta(float eta)
Definition: CaloTower.h:54
static constexpr int n_clusters_link
#define M_PI
static constexpr int N_GCTINTERNAL_FIBERS
void addEt(ap_uint< 10 > newEt)
static constexpr int TOWER_IN_PHI
towers3x4(const towers3x4 &other)
Definition: HCAL.py:1
static constexpr float a0_80
int getTower_absPhiID(float phi)
static constexpr float c1_ss
const EBDetId & id() const
void setTowerIEta(short int ieta)
Definition: EGamma.cc:28
float towerPhi() const
Definition: CaloTower.h:39
ap_uint< 10 > getCrystalE(int iEta, int iPhi)
GCTintTowers_t getFullTowers(const GCTinternal_t &GCTinternal)
Definition: Phase2L1GCT.h:241
const int crystaliPhiFromCardRegionInfo(int cc)
void printClusterInfo(int cc, std::string description="")
const float realEta(int cc)
void setShape(short int s)
Definition: EGamma.cc:40
towers3x4 operator=(const towers3x4 &other)
float hcalTowerEt() const
Definition: CaloTower.h:36
static constexpr int TOWER_IN_ETA
static constexpr int N_GCTCARDS
void writeToCorrelatorAndGTOutputs(const GCTinternal_t &GCTinternal, GCTtoCorr_t &GCTtoCorrOutput, std::unique_ptr< l1tp2::CaloCrystalClusterCollection > const &gctClustersOutput, std::unique_ptr< l1tp2::CaloTowerCollection > const &gctTowersOutput, std::unique_ptr< l1t::EGammaBxCollection > const &gctEGammas, std::unique_ptr< l1tp2::DigitizedClusterCorrelatorCollection > const &gctDigitizedClustersCorrelator, std::unique_ptr< l1tp2::DigitizedTowerCorrelatorCollection > const &gctDigitizedTowersCorrelator, std::unique_ptr< l1tp2::DigitizedClusterGTCollection > const &gctDigitizedClustersGT, int nGCTCard, int fiberStart, int fiberEnd, int corrFiberIndexOffset, int corrTowPhiOffset)
Definition: Phase2L1GCT.h:294
void setIsoEt(short int iso)
Definition: EGamma.cc:34
ap_uint< 2 > towerPhi() const
region3x4 & getRegion3x4(int idx)
void getHoverE(ap_uint< 12 > ECAL, ap_uint< 12 > HCAL_inHcalConvention)
clusterInfo getBremsValuesPos(crystal tempX[CRYSTAL_IN_ETA][CRYSTAL_IN_PHI], ap_uint< 5 > seed_eta, ap_uint< 5 > seed_phi)
int globalClusteriEta(void) const
void doProximityAndBremsStitching(const RCTcard_t(&inputCards)[N_RCTCARDS_PHI], RCTcard_t(&outputCards)[N_RCTCARDS_PHI], int iStartingCard, bool isPositiveEta)
void setEt_uint(ap_uint< 10 > et_uint)
static constexpr int N_GCTETA
static constexpr int N_GCTCORR_FIBERS
bool passes_looseTkiso(float pt, float iso)
void initFromRCTCluster(int iRCTcardIndex, bool isPosEta, const RCTcluster_t &rctCluster)
region3x4(const region3x4 &other)
void applyCalibration(float factor)
static constexpr float e0_looseTkss
RCTtoGCTfiber_t RCTtoGCTfiber[N_RCTGCT_FIBERS]
int globalToweriEtaFromGCTcardiEta(int gctCard_tower_iEta)
void setId(const EBDetId &id)
bool passes_looseTkss(float pt, float ss)
void setExperimentalParams(const std::map< std::string, float > &params)
static constexpr int n_crystals_cardEta
static constexpr float d1
RCTcard_t RCTcardEtaPos[N_RCTCARDS_PHI]
ap_uint< 12 > clusterEnergy() const
int getTower_absEtaID(float eta)
towers3x4 & getTowers3x4(int idx)
bool isValidCard(int cc)
l1tp2::DigitizedTowerCorrelator createDigitizedTowerCorrelator(unsigned int indexCard, unsigned int indexFiber, unsigned int indexTower)
static constexpr int CRYSTALS_IN_TOWER_ETA
void setTowerIPhi(short int iphi)
Definition: EGamma.cc:30
int getCard_refCrystal_iPhi(int cc)
const int crystaliEtaFromCardRegionInfo(int cc)
Definition: APVGainStruct.h:7
static constexpr int n_towers_halfPhi
crystalMax getPeakBin15N(const etaStripPeak_t etaStrip)
Definition: Phase2L1RCT.h:982
Cluster packCluster(ap_uint< 15 > &clusterEt, ap_uint< 5 > &etaMax_t, ap_uint< 5 > &phiMax_t)
Definition: Phase2L1RCT.h:1099
void printGCTClusterInfo(std::string description="")
static constexpr float b2
float towerEta() const
Definition: CaloTower.h:40
clusterInfo getBremsValuesNeg(crystal tempX[CRYSTAL_IN_ETA][CRYSTAL_IN_PHI], ap_uint< 5 > seed_eta, ap_uint< 5 > seed_phi)
float getIdx() const
static constexpr int n_towers_cardEta
static constexpr float d0
static constexpr float b0
GCTtower_t GCTtowers[N_GCTTOWERS_FIBER]
GCTinternal_t getClustersTowers(const GCTcard_t &GCTcard, unsigned int nGCTCard)
Definition: Phase2L1GCT.h:196
static constexpr int n_links_card
void writeToPFOutput(int nGCTCard, std::unique_ptr< l1tp2::CaloTowerCollection > const &gctFullTowers)
void algo_top(const GCTcard_t &GCTcard, GCTtoCorr_t &GCTtoCorr, unsigned int nGCTCard, std::unique_ptr< l1tp2::CaloCrystalClusterCollection > const &gctClusters, std::unique_ptr< l1tp2::CaloTowerCollection > const &gctTowers, std::unique_ptr< l1tp2::CaloTowerCollection > const &gctFullTowers, std::unique_ptr< l1t::EGammaBxCollection > const &gctEGammas, std::unique_ptr< l1tp2::DigitizedClusterCorrelatorCollection > const &gctDigitizedClustersCorrelator, std::unique_ptr< l1tp2::DigitizedTowerCorrelatorCollection > const &gctDigitizedTowersCorrelator, std::unique_ptr< l1tp2::DigitizedClusterGTCollection > const &gctDigitizedClustersGT, l1tp2::ParametricCalibration calib_)
Definition: Phase2L1GCT.h:367
static constexpr float a0
towers3x4 card3x4Towers[N_REGIONS_PER_CARD]
void setCrystalE(int iEta, int iPhi, ap_uint< 10 > energy)
ap_uint< 12 > convertHcalETtoEcalET(ap_uint< 12 > HCAL)
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
void initFromRCTTower(const RCTtower_t &rctTower)
static constexpr int CRYSTAL_IN_PHI
ecaltp_t bestOf2(const ecaltp_t ecaltp0, const ecaltp_t ecaltp1)
Definition: Phase2L1RCT.h:940
linkECAL linksECAL[TOWER_IN_ETA][TOWER_IN_PHI]
static constexpr int CRYSTALS_IN_TOWER_PHI
Geom::Theta< T > theta() const
Definition: PV3DBase.h:72
int getAbsID_iEta_fromFirmwareCardTowerLink(int nCard, int nTower, int nLink)
bool compareClusterET(const Cluster &lhs, const Cluster &rhs)
static const unsigned int GCTcardtoRCTcardnumber[N_GCTCARDS][N_RCTCARDS_PHI *2]
math::PtEtaPhiMLorentzVector PolarLorentzVector
Lorentz vector.
Definition: Candidate.h:38
static constexpr float e1_looseTkss