CMS 3D CMS Logo

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