DigitizedClusterCorrelator

Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
#ifndef DataFormats_L1TCalorimeterPhase2_DigitizedClusterCorrelator_h
#define DataFormats_L1TCalorimeterPhase2_DigitizedClusterCorrelator_h

#include <ap_int.h>
#include <vector>

namespace l1tp2 {

  class DigitizedClusterCorrelator {
  private:
    // Data
    unsigned long long int clusterData;
    unsigned int idxGCTCard;  // 0, 1, or 2

    // Constants
    static constexpr unsigned int n_towers_eta = 34;  // in GCT card unique region
    static constexpr unsigned int n_towers_phi = 24;  // in GCT card unique region
    static constexpr unsigned int n_crystals_in_tower = 5;
    static constexpr float LSB_PT = 0.5;                 // 0.5 GeV
    static constexpr float ETA_RANGE_ONE_SIDE = 1.4841;  // barrel goes from (-1.4841, +1.4841)
    static constexpr float LSB_ETA = ((2 * ETA_RANGE_ONE_SIDE) / (n_towers_eta * n_crystals_in_tower));  // (2.8 / 170)
    static constexpr float LSB_PHI = ((2 * M_PI) / (3 * n_towers_phi * n_crystals_in_tower));            // (2 pi * 360)

    static constexpr unsigned int n_bits_pt = 12;            // 12 bits allocated for pt
    static constexpr unsigned int n_bits_unused_start = 63;  // unused bits start at bit 63

    // "top" of the correlator card #0 in GCT coordinates is iPhi tower index 24
    static constexpr int correlatorCard0_tower_iphi_offset = 24;
    // same but for correlator cards #1 and 2 (cards wrap around phi = 180 degrees):
    static constexpr int correlatorCard1_tower_iphi_offset = 48;
    static constexpr int correlatorCard2_tower_iphi_offset = 0;

    // Private member functions to perform digitization
    ap_uint<12> digitizePt(float pt_f) {
      float maxPt_f = (std::pow(2, n_bits_pt) - 1) * LSB_PT;
      // If pT exceeds the maximum (extremely unlikely), saturate the value
      if (pt_f >= maxPt_f) {
        return (ap_uint<12>)0xFFF;
      }

      return (ap_uint<12>)(pt_f / LSB_PT);
    }

    ap_uint<8> digitizeIEtaCr(unsigned int iEtaCr) { return (ap_uint<8>)iEtaCr; }

    ap_uint<7> digitizeIPhiCr(unsigned int iPhiCr) { return (ap_uint<7>)iPhiCr; }

    // To-do: HoE is not defined for clusters
    ap_uint<4> digitizeHoE(unsigned int hoe) { return (ap_uint<4>)hoe; }
    ap_uint<2> digitizeHoeFlag(unsigned int hoeFlag) { return (ap_uint<2>)hoeFlag; }

    ap_uint<3> digitizeIso(unsigned int iso) { return (ap_uint<3>)iso; }
    ap_uint<2> digitizeIsoFlag(unsigned int isoFlag) { return (ap_uint<2>)isoFlag; }

    // To-do: fb: no information yet
    ap_uint<6> digitizeFb(unsigned int fb) { return (ap_uint<6>)fb; }

    // To-do: timing: no information yet
    ap_uint<5> digitizeTiming(unsigned int timing) { return (ap_uint<5>)timing; }

    // Shape: shower shape working point
    ap_uint<2> digitizeShapeFlag(unsigned int shapeFlag) { return (ap_uint<2>)shapeFlag; }

    // TO-DO: Brems: was brems applied (NOT STORED YET IN GCT)
    ap_uint<2> digitizeBrems(unsigned int brems) { return (ap_uint<2>)brems; }

  public:
    DigitizedClusterCorrelator() { clusterData = 0x0; }

    DigitizedClusterCorrelator(ap_uint<64> data) { clusterData = data; }

    // Constructor from digitized inputs
    DigitizedClusterCorrelator(ap_uint<12> pt,
                               ap_uint<8> etaCr,
                               ap_uint<7> phiCr,
                               ap_uint<4> hoe,
                               ap_uint<2> hoeFlag,
                               ap_uint<3> iso,
                               ap_uint<2> isoFlag,
                               ap_uint<6> fb,
                               ap_uint<5> timing,
                               ap_uint<2> shapeFlag,
                               ap_uint<2> brems,
                               int iGCTCard,
                               bool fullydigitizedInputs) {
      (void)fullydigitizedInputs;
      clusterData = ((ap_uint<64>)pt) | (((ap_uint<64>)etaCr) << 12) | (((ap_uint<64>)phiCr) << 20) |
                    (((ap_uint<64>)hoe) << 27) | (((ap_uint<64>)hoeFlag) << 31) | (((ap_uint<64>)iso) << 36) |
                    (((ap_uint<64>)isoFlag) << 38) | (((ap_uint<64>)fb) << 44) | (((ap_uint<64>)timing) << 49) |
                    (((ap_uint<64>)shapeFlag << 51)) | (((ap_uint<64>)brems << 53));
      idxGCTCard = iGCTCard;
    }

    // Constructor from float inputs
    DigitizedClusterCorrelator(float pt_f,
                               unsigned int iEtaCr,
                               unsigned int iPhiCr,
                               unsigned int hoe,
                               unsigned int hoeFlag,
                               unsigned int iso,
                               unsigned int isoFlag,
                               unsigned int fb,
                               unsigned int timing,
                               unsigned int shapeFlag,
                               unsigned int brems,
                               int iGCTCard) {
      clusterData = (((ap_uint<64>)digitizePt(pt_f)) | ((ap_uint<64>)digitizeIEtaCr(iEtaCr) << 12) |
                     ((ap_uint<64>)digitizeIPhiCr(iPhiCr) << 20) | ((ap_uint<64>)digitizeHoE(hoe) << 27) |
                     ((ap_uint<64>)digitizeHoeFlag(hoeFlag) << 31) | ((ap_uint<64>)digitizeIso(iso) << 36) |
                     ((ap_uint<64>)digitizeIsoFlag(isoFlag) << 38) | ((ap_uint<64>)digitizeFb(fb) << 44) |
                     ((ap_uint<64>)digitizeTiming(timing) << 49) | ((ap_uint<64>)digitizeShapeFlag(shapeFlag) << 51) |
                     ((ap_uint<64>)digitizeBrems(brems) << 53));
      idxGCTCard = iGCTCard;
    }

    ap_uint<64> data() const { return clusterData; }

    // Other getters
    float ptLSB() const { return LSB_PT; }
    ap_uint<12> pt() const { return (clusterData & 0xFFF); }
    float ptFloat() const { return (pt() * ptLSB()); }

    // crystal eta in the correlator region (LSB: 2.8/170)
    ap_uint<8> eta() const { return ((clusterData >> 12) & 0xFF); }  // (eight 1's) 0b11111111 = 0xFF

    // crystal phi in the correlator region (LSB: 2pi/360)
    ap_uint<7> phi() const { return ((clusterData >> 20) & 0x7F); }  // (seven 1's) 0b1111111 = 0x7F

    // HoE value and flag: not defined yet in the emulator
    ap_uint<4> hoe() const { return ((clusterData >> 27) & 0xF); }      // (four 1's) 0b1111 = 0xF
    ap_uint<2> hoeFlag() const { return ((clusterData >> 31) & 0x3); }  // (two 1's) 0b11 = 0x3

    // Raw isolation sum: not saved in the emulator
    ap_uint<3> iso() const { return ((clusterData >> 36) & 0x7); }

    // iso flag: two bits, least significant bit is the standalone WP (true or false), second bit is the looseTk WP (true or false)
    // e.g. 0b01 : standalone iso flag passed, loose Tk iso flag did not pass
    ap_uint<2> isoFlags() const { return ((clusterData >> 38) & 0x3); }  // (two 1's) 0b11 = 0x3
    bool passes_iso() const { return (isoFlags() & 0x1); }               // standalone iso WP
    bool passes_looseTkiso() const { return (isoFlags() & 0x2); }        // loose Tk iso WP

    // fb and timing: not saved in the current emulator
    ap_uint<6> fb() const { return ((clusterData >> 44) & 0x3F); }
    ap_uint<5> timing() const { return ((clusterData >> 49) & 0x1F); }

    // shower shape shape flag: two bits, least significant bit is the standalone WP, second bit is the looseTk WP
    // e.g. 0b01 : standalone shower shape flag passed, loose Tk shower shape flag did not pass
    ap_uint<2> shapeFlags() const { return ((clusterData >> 51) & 0x3); }

    bool passes_ss() const { return (shapeFlags() & 0x1); }         // standalone shower shape WP
    bool passes_looseTkss() const { return (shapeFlags() & 0x2); }  // loose Tk shower shape WP

    // brems: not saved in the current emulator
    ap_uint<2> brems() const { return ((clusterData >> 53) & 0x3); }

    // which GCT card (0, 1, or 2)
    unsigned int cardNumber() const { return idxGCTCard; }

    const int unusedBitsStart() const { return n_bits_unused_start; }

    // Other checks
    bool passNullBitsCheck(void) const { return ((data() >> unusedBitsStart()) == 0x0); }

    // Get real eta (does not depend on card number). crystal iEta = 0 starts at real eta -1.4841.
    // LSB_ETA/2 is to add half a crystal width to get the center of the crystal in eta
    float realEta() const { return (float)((-1 * ETA_RANGE_ONE_SIDE) + (eta() * LSB_ETA) + (LSB_ETA / 2)); }

    // Get real phi (uses card number).
    float realPhi() const {
      // each card starts at a different real phi
      int offset_tower = 0;
      if (cardNumber() == 0) {
        offset_tower = correlatorCard0_tower_iphi_offset;
      } else if (cardNumber() == 1) {
        offset_tower = correlatorCard1_tower_iphi_offset;
      } else if (cardNumber() == 2) {
        offset_tower = correlatorCard2_tower_iphi_offset;
      }
      int thisPhi = (phi() + (offset_tower * n_crystals_in_tower));
      // crystal iPhi = 0 starts at real phi = -180 degrees
      // LSB_PHI/2 is to add half a crystal width to get the center of the crystal in phi
      return (float)((-1 * M_PI) + (thisPhi * LSB_PHI) + (LSB_PHI / 2));
    }
  };

  // Collection typedef
  typedef std::vector<l1tp2::DigitizedClusterCorrelator> DigitizedClusterCorrelatorCollection;

}  // namespace l1tp2

#endif