PID

PTYPE

ParticleID

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 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
#ifndef DataFormats_L1TParticleFlow_datatypes_h
#define DataFormats_L1TParticleFlow_datatypes_h

#include <ap_int.h>
#include <cassert>
#include <cmath>

namespace l1ct {

  typedef ap_ufixed<14, 12, AP_TRN, AP_SAT> pt_t;
  typedef ap_ufixed<17, 15, AP_TRN, AP_SAT> mass2_t;  // can store up to 256 GeV with 0.5 GeV precision
  typedef ap_ufixed<10, 8, AP_TRN, AP_SAT> pt10_t;
  typedef ap_fixed<16, 14, AP_TRN, AP_SAT> dpt_t;
  typedef ap_ufixed<28, 24, AP_TRN, AP_SAT> pt2_t;
  typedef ap_int<10> eta_t;
  typedef ap_int<10> phi_t;
  typedef ap_int<6> tkdeta_t;
  typedef ap_uint<7> tkdphi_t;
  typedef ap_int<12> glbeta_t;
  typedef ap_int<11> glbphi_t;
  typedef ap_int<5> vtx_t;
  typedef ap_int<10> z0_t;         // 40cm / 0.1
  typedef ap_uint<8> dxy_t;        // sqrt(32)cm / 0.004 packed into 8 bit for l1ct
  typedef ap_uint<3> tkquality_t;  // tbd
  typedef ap_ufixed<9, 1, AP_RND_CONV, AP_WRAP> puppiWgt_t;
  typedef ap_uint<6> emid_t;
  typedef ap_uint<14> tk2em_dr_t;
  typedef ap_uint<14> tk2calo_dr_t;
  typedef ap_uint<10> em2calo_dr_t;
  typedef ap_uint<13> tk2calo_dq_t;
  typedef ap_uint<4> egquality_t;
  typedef ap_uint<3> stub_t;
  typedef ap_ufixed<10, 1, AP_TRN, AP_SAT> srrtot_t;
  typedef ap_uint<8> meanz_t;  // mean - MEANZ_OFFSET(= 320 cm)
  typedef ap_ufixed<10, 5, AP_TRN, AP_SAT> hoe_t;
  typedef ap_uint<4> redChi2Bin_t;
  typedef ap_fixed<10, 1, AP_RND_CONV, AP_SAT> id_score_t;  // ID score to be between -1 (background) and 1 (signal)
  typedef ap_ufixed<8, 1, AP_RND_CONV, AP_SAT> jet_tag_score_t;  // 8 bit jet jet probability from 0 to 1

  // FIXME: adjust range 10-11bits -> 1/4 - 1/2TeV is probably more than enough for all reasonable use cases
  typedef ap_ufixed<11, 9, AP_TRN, AP_SAT> iso_t;

  struct ParticleID {
    ap_uint<3> bits;
    enum PID {
      NONE = 0,
      HADZERO = 0,
      PHOTON = 1,
      HADMINUS = 2,
      HADPLUS = 3,
      ELEMINUS = 4,
      ELEPLUS = 5,
      MUMINUS = 6,
      MUPLUS = 7
    };
    enum PTYPE { HAD = 0, EM = 1, MU = 2 };

    ParticleID(PID val = NONE) : bits(val) {}
    ParticleID &operator=(PID val) {
      bits = val;
      return *this;
    }

    int rawId() const { return bits.to_int(); }
    bool isPhoton() const {
#ifndef __SYNTHESIS__
      assert(neutral());
#endif
      return bits[0];
    }
    bool isMuon() const { return bits[2] && bits[1]; }
    bool isElectron() const { return bits[2] && !bits[1]; }
    bool isChargedHadron() const { return !bits[2] && bits[1]; }
    bool charge() const {
#ifndef __SYNTHESIS__
      assert(charged());
#endif
      return bits[0]; /* 1 if positive, 0 if negative */
    }

    bool chargeOrNull() const {  // doesn't throw on null id
      return bits[0];
    }
    bool charged() const { return bits[1] || bits[2]; };
    bool neutral() const { return !charged(); }
    int intCharge() const { return charged() ? (charge() ? +1 : -1) : 0; }

    void clear() { bits = 0; }

    static ParticleID mkChHad(bool charge) { return ParticleID(charge ? HADPLUS : HADMINUS); }
    static ParticleID mkElectron(bool charge) { return ParticleID(charge ? ELEPLUS : ELEMINUS); }
    static ParticleID mkMuon(bool charge) { return ParticleID(charge ? MUPLUS : MUMINUS); }

    inline bool operator==(const ParticleID &other) const { return bits == other.bits; }

    inline int pdgId() const {
      switch (bits.to_int()) {
        case HADZERO:
          return 130;
        case PHOTON:
          return 22;
        case HADMINUS:
          return -211;
        case HADPLUS:
          return +211;
        case ELEMINUS:
          return +11;
        case ELEPLUS:
          return -11;
        case MUMINUS:
          return +13;
        case MUPLUS:
          return -13;
      }
      return 0;
    }

    inline int oldId() const {
      //{ PID_Charged=0, PID_Neutral=1, PID_Photon=2, PID_Electron=3, PID_Muon=4 };
      switch (bits.to_int()) {
        case HADZERO:
          return 1;
        case PHOTON:
          return 2;
        case HADMINUS:
          return 0;
        case HADPLUS:
          return 0;
        case ELEMINUS:
          return 3;
        case ELEPLUS:
          return 3;
        case MUMINUS:
          return 4;
        case MUPLUS:
          return 4;
      }
      return -1;
    }
  };

  namespace Scales {
    constexpr int INTPHI_PI = 720;
    constexpr int INTPHI_TWOPI = 2 * INTPHI_PI;
    constexpr float INTPT_LSB = 0.25;
    constexpr float ETAPHI_LSB = M_PI / INTPHI_PI;
    constexpr float Z0_LSB = 0.05;
    constexpr float DXY_LSB = 0.00390625;    // -16 to 16 / 2**13 from track word
    constexpr float DXYSQRT_LSB = 0.015625;  //sqrt(abs(dxy)) 4/2**8 (8 bit for l1ct dxy)
    constexpr float PUPPIW_LSB = 1.0 / 256;
    constexpr float MEANZ_OFFSET = 320.;
    constexpr float SRRTOT_LSB = 0.0019531250;  // pow(2, -9)
    constexpr unsigned int SRRTOT_SCALE = 64;   // pow(2, 6)
    constexpr float HOE_LSB = 0.031250000;      // pow(2, -5)

    inline float floatPt(pt_t pt) { return pt.to_float(); }
    inline float floatPt(dpt_t pt) { return pt.to_float(); }
    inline float floatPt(pt2_t pt2) { return pt2.to_float(); }
    inline int intPt(pt_t pt) {
      ap_uint<pt_t::width> rawPt = pt.range();
      return rawPt.to_int();
    }
    inline int intPt(dpt_t pt) {
      ap_int<dpt_t::width> rawPt = pt.range();
      return rawPt.to_int();
    }
    inline float floatEta(eta_t eta) { return eta.to_float() * ETAPHI_LSB; }
    inline float floatPhi(phi_t phi) { return phi.to_float() * ETAPHI_LSB; }
    inline float floatEta(tkdeta_t eta) { return eta.to_float() * ETAPHI_LSB; }
    inline float floatPhi(tkdphi_t phi) { return phi.to_float() * ETAPHI_LSB; }
    inline float floatEta(glbeta_t eta) { return eta.to_float() * ETAPHI_LSB; }
    inline float floatPhi(glbphi_t phi) { return phi.to_float() * ETAPHI_LSB; }
    inline float floatZ0(z0_t z0) { return z0.to_float() * Z0_LSB; }
    inline float floatDxy(dxy_t dxy) { return dxy.to_float() * DXYSQRT_LSB; }  // l1ct stores sqrt(dxy)
    inline float floatPuppiW(puppiWgt_t puppiw) { return puppiw.to_float(); }
    inline float floatIso(iso_t iso) { return iso.to_float(); }
    inline float floatSrrTot(srrtot_t srrtot) { return srrtot.to_float() / SRRTOT_SCALE; };
    inline float floatMeanZ(meanz_t meanz) { return meanz + MEANZ_OFFSET; };
    inline float floatHoe(hoe_t hoe) { return hoe.to_float(); };
    inline float floatIDScore(id_score_t score) { return score.to_float(); };
    inline float floatMass(mass2_t mass) { return mass.to_float(); }

    inline pt_t makePt(int pt) { return ap_ufixed<16, 14>(pt) >> 2; }
    inline dpt_t makeDPt(int dpt) { return ap_fixed<18, 16>(dpt) >> 2; }
    inline pt_t makePtFromFloat(float pt) { return pt_t(0.25 * std::round(pt * 4)); }
    inline dpt_t makeDPtFromFloat(float dpt) { return dpt_t(dpt); }
    inline z0_t makeZ0(float z0) { return z0_t(std::round(z0 / Z0_LSB)); }
    inline dxy_t makeDxy(float dxy) { return dxy_t(std::round(dxy / DXYSQRT_LSB)); }  // l1ct stores sqrt(dxy)

    inline ap_uint<pt_t::width> ptToInt(pt_t pt) {
      // note: this can be synthethized, e.g. when pT is used as intex in a LUT
      ap_uint<pt_t::width> ret = 0;
      ret(pt_t::width - 1, 0) = pt(pt_t::width - 1, 0);
      return ret;
    }

    inline ap_int<dpt_t::width> ptToInt(dpt_t pt) {
      // note: this can be synthethized, e.g. when pT is used as intex in a LUT
      ap_uint<dpt_t::width> ret = 0;
      ret(dpt_t::width - 1, 0) = pt(dpt_t::width - 1, 0);
      return ret;
    }

    inline phi_t makePhi(float phi) { return round(phi / ETAPHI_LSB); }
    inline eta_t makeEta(float eta) { return round(eta / ETAPHI_LSB); }
    inline glbeta_t makeGlbEta(float eta) { return round(eta / ETAPHI_LSB); }
    inline glbeta_t makeGlbEtaRoundEven(float eta) { return 2 * std::round(eta / ETAPHI_LSB / 2); }

    inline glbphi_t makeGlbPhi(float phi) { return round(phi / ETAPHI_LSB); }
    inline iso_t makeIso(float iso) { return iso_t(0.25 * round(iso * 4)); }

    inline int makeDR2FromFloatDR(float dr) { return ceil(dr * dr / ETAPHI_LSB / ETAPHI_LSB); }
    inline srrtot_t makeSrrTot(float var) { return srrtot_t(SRRTOT_LSB * round(var * SRRTOT_SCALE / SRRTOT_LSB)); };
    inline meanz_t makeMeanZ(float var) { return round(var - MEANZ_OFFSET); };
    inline hoe_t makeHoe(float var) { return hoe_t(HOE_LSB * round(var / HOE_LSB)); };

    inline float maxAbsEta() { return ((1 << (eta_t::width - 1)) - 1) * ETAPHI_LSB; }
    inline float maxAbsPhi() { return ((1 << (phi_t::width - 1)) - 1) * ETAPHI_LSB; }
    inline float maxAbsGlbEta() { return ((1 << (glbeta_t::width - 1)) - 1) * ETAPHI_LSB; }
    inline float maxAbsGlbPhi() { return ((1 << (glbphi_t::width - 1)) - 1) * ETAPHI_LSB; }
  }  // namespace Scales

  inline int dr2_int(eta_t eta1, phi_t phi1, eta_t eta2, phi_t phi2) {
    ap_int<eta_t::width + 1> deta = (eta1 - eta2);
    ap_int<phi_t::width + 1> dphi = (phi1 - phi2);
    return deta * deta + dphi * dphi;
  }

}  // namespace l1ct

#endif