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