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