diff --git a/DataFormats/L1TCorrelator/interface/TkElectron.h b/DataFormats/L1TCorrelator/interface/TkElectron.h index 9f1ac1eaeeff0..c5b70d79598fb 100644 --- a/DataFormats/L1TCorrelator/interface/TkElectron.h +++ b/DataFormats/L1TCorrelator/interface/TkElectron.h @@ -39,16 +39,18 @@ namespace l1t { float trkzVtx() const { return trkzVtx_; } double trackCurvature() const { return trackCurvature_; } - + float idScore() const { return idScore_; } // ---------- member functions --------------------------- void setTrkzVtx(float TrkzVtx) { trkzVtx_ = TrkzVtx; } void setTrackCurvature(double trackCurvature) { trackCurvature_ = trackCurvature; } + void setIdScore(float score) { idScore_ = score; } private: edm::Ptr trkPtr_; float trkzVtx_; double trackCurvature_; + float idScore_; }; } // namespace l1t #endif diff --git a/DataFormats/L1TCorrelator/src/classes_def.xml b/DataFormats/L1TCorrelator/src/classes_def.xml index 0685c6bc1356e..6b5acaf05cbc1 100644 --- a/DataFormats/L1TCorrelator/src/classes_def.xml +++ b/DataFormats/L1TCorrelator/src/classes_def.xml @@ -44,7 +44,8 @@ - + + diff --git a/DataFormats/L1TParticleFlow/interface/PFCandidate.h b/DataFormats/L1TParticleFlow/interface/PFCandidate.h index c6d52246a6fa5..567eb6f80b7fb 100644 --- a/DataFormats/L1TParticleFlow/interface/PFCandidate.h +++ b/DataFormats/L1TParticleFlow/interface/PFCandidate.h @@ -48,9 +48,13 @@ namespace l1t { void setZ0(float z0) { setVertex(reco::Particle::Point(0, 0, z0)); } void setDxy(float dxy) { dxy_ = dxy; } + void setCaloEta(float caloeta) { caloEta_ = caloeta; } + void setCaloPhi(float calophi) { caloPhi_ = calophi; } float z0() const { return vz(); } float dxy() const { return dxy_; } + float caloEta() const { return caloEta_; } + float caloPhi() const { return caloPhi_; } int16_t hwZ0() const { return hwZ0_; } int16_t hwDxy() const { return hwDxy_; } @@ -70,7 +74,7 @@ namespace l1t { PFClusterRef clusterRef_; PFTrackRef trackRef_; MuonRef muonRef_; - float dxy_, puppiWeight_; + float dxy_, puppiWeight_, caloEta_, caloPhi_; int16_t hwZ0_, hwDxy_; uint16_t hwTkQuality_, hwPuppiWeight_, hwEmID_; diff --git a/DataFormats/L1TParticleFlow/interface/PFCluster.h b/DataFormats/L1TParticleFlow/interface/PFCluster.h index 1851746b51d19..2272ccbe353db 100644 --- a/DataFormats/L1TParticleFlow/interface/PFCluster.h +++ b/DataFormats/L1TParticleFlow/interface/PFCluster.h @@ -22,10 +22,14 @@ namespace l1t { float ptError = 0, int hwpt = 0, int hweta = 0, - int hwphi = 0) + int hwphi = 0, + float absZBarycenter = 0., + float sigmaRR = 0.) : L1Candidate(PolarLorentzVector(pt, eta, phi, 0), hwpt, hweta, hwphi, /*hwQuality=*/isEM ? 1 : 0), hOverE_(hOverE), - ptError_(ptError) { + ptError_(ptError), + absZBarycenter_(absZBarycenter), + sigmaRR_(sigmaRR) { setPdgId(isEM ? 22 : 130); // photon : non-photon(K0) } PFCluster( @@ -37,6 +41,12 @@ namespace l1t { float hOverE() const { return hOverE_; } void setHOverE(float hOverE) { hOverE_ = hOverE; } + void setSigmaRR(float sigmaRR) { sigmaRR_ = sigmaRR; } + float absZBarycenter() const { return absZBarycenter_; } + + void setAbsZBarycenter(float absZBarycenter) { absZBarycenter_ = absZBarycenter; } + float sigmaRR() const { return sigmaRR_; } + float emEt() const { if (hOverE_ == -1) return 0; @@ -68,6 +78,9 @@ namespace l1t { private: float hOverE_, ptError_, egVsPionMVAOut_, egVsPUMVAOut_; + // HGC dedicated quantities (0ed by default) + float absZBarycenter_, sigmaRR_; + ConstituentsAndFractions constituents_; }; diff --git a/DataFormats/L1TParticleFlow/interface/bit_encoding.h b/DataFormats/L1TParticleFlow/interface/bit_encoding.h index 9aa7446e75962..695594179d573 100644 --- a/DataFormats/L1TParticleFlow/interface/bit_encoding.h +++ b/DataFormats/L1TParticleFlow/interface/bit_encoding.h @@ -58,4 +58,34 @@ inline void l1pf_pattern_unpack(const ap_uint data[], T objs[N]) { } } +template +inline void l1pf_pattern_pack_slim(const T objs[N], ap_uint data[]) { +#ifdef __SYNTHESIS__ +#pragma HLS inline +#pragma HLS inline region recursive +#endif + assert(T::BITWIDTH_SLIM <= NB); + for (unsigned int i = 0; i < N; ++i) { +#ifdef __SYNTHESIS__ +#pragma HLS unroll +#endif + data[i + OFFS] = objs[i].pack_slim(); + } +} + +template +inline void l1pf_pattern_unpack_slim(const ap_uint data[], T objs[N]) { +#ifdef __SYNTHESIS__ +#pragma HLS inline +#pragma HLS inline region recursive +#endif + assert(T::BITWIDTH_SLIM <= NB); + for (unsigned int i = 0; i < N; ++i) { +#ifdef __SYNTHESIS__ +#pragma HLS unroll +#endif + objs[i] = T::unpack(data[i + OFFS]); + } +} + #endif diff --git a/DataFormats/L1TParticleFlow/interface/datatypes.h b/DataFormats/L1TParticleFlow/interface/datatypes.h index f56e7b36c2495..be802bc540b6e 100644 --- a/DataFormats/L1TParticleFlow/interface/datatypes.h +++ b/DataFormats/L1TParticleFlow/interface/datatypes.h @@ -39,6 +39,12 @@ namespace l1ct { 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; + // 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; @@ -149,6 +155,11 @@ namespace l1ct { constexpr float Z0_LSB = 0.05; constexpr float DXY_LSB = 0.05; 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(); } @@ -164,6 +175,9 @@ namespace l1ct { inline float floatDxy(dxy_t dxy) { return dxy.to_float() * DXY_LSB; } inline float floatPuppiW(puppiWgt_t puppiw) { return puppiw.to_float() * PUPPIW_LSB; } 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 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; } @@ -194,6 +208,9 @@ namespace l1ct { 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; } diff --git a/DataFormats/L1TParticleFlow/interface/layer1_emulator.h b/DataFormats/L1TParticleFlow/interface/layer1_emulator.h index 8262d6b645940..4a7709bbf52e0 100644 --- a/DataFormats/L1TParticleFlow/interface/layer1_emulator.h +++ b/DataFormats/L1TParticleFlow/interface/layer1_emulator.h @@ -39,7 +39,7 @@ namespace l1ct { }; struct TkObjEmu : public TkObj { - uint16_t hwChi2, hwStubs; + uint16_t hwChi2; float simPt, simCaloEta, simCaloPhi, simVtxEta, simVtxPhi, simZ0, simD0; const l1t::PFTrack *src = nullptr; bool read(std::fstream &from); @@ -48,7 +48,6 @@ namespace l1ct { TkObj::clear(); src = nullptr; hwChi2 = 0; - hwStubs = 0; simPt = 0; simCaloEta = 0; simCaloPhi = 0; @@ -196,6 +195,7 @@ namespace l1ct { const l1t::PFTrack *srcTrack = nullptr; // we use an index to the standalone object needed to retrieve a Ref when putting int sta_idx; + float idScore; bool read(std::fstream &from); bool write(std::fstream &to) const; void clear() { @@ -203,6 +203,7 @@ namespace l1ct { srcCluster = nullptr; srcTrack = nullptr; sta_idx = -1; + idScore = -999; clearIsoVars(); } @@ -334,7 +335,7 @@ namespace l1ct { }; struct Event { - enum { VERSION = 11 }; + enum { VERSION = 12 }; uint32_t run, lumi; uint64_t event; RawInputs raw; diff --git a/DataFormats/L1TParticleFlow/interface/layer1_objs.h b/DataFormats/L1TParticleFlow/interface/layer1_objs.h index 83765fc4b2b10..48af69b993de1 100644 --- a/DataFormats/L1TParticleFlow/interface/layer1_objs.h +++ b/DataFormats/L1TParticleFlow/interface/layer1_objs.h @@ -12,10 +12,13 @@ namespace l1ct { phi_t hwPhi; // relative to the region center, at calo pt_t hwEmPt; emid_t hwEmID; + srrtot_t hwSrrTot; + meanz_t hwMeanZ; + hoe_t hwHoe; inline bool operator==(const HadCaloObj &other) const { return hwPt == other.hwPt && hwEta == other.hwEta && hwPhi == other.hwPhi && hwEmPt == other.hwEmPt && - hwEmID == other.hwEmID; + hwEmID == other.hwEmID && hwSrrTot == other.hwSrrTot && hwMeanZ == other.hwMeanZ && hwHoe == other.hwHoe; } inline bool operator>(const HadCaloObj &other) const { return hwPt > other.hwPt; } @@ -27,6 +30,9 @@ namespace l1ct { hwPhi = 0; hwEmPt = 0; hwEmID = 0; + hwSrrTot = 0; + hwMeanZ = 0; + hwHoe = 0; } int intPt() const { return Scales::intPt(hwPt); } @@ -37,10 +43,16 @@ namespace l1ct { float floatEmPt() const { return Scales::floatPt(hwEmPt); } float floatEta() const { return Scales::floatEta(hwEta); } float floatPhi() const { return Scales::floatPhi(hwPhi); } + float floatSrrTot() const { return Scales::floatSrrTot(hwSrrTot); }; + float floatMeanZ() const { return Scales::floatMeanZ(hwMeanZ); }; + float floatHoe() const { return Scales::floatHoe(hwHoe); }; bool hwIsEM() const { return hwEmID != 0; } - static const int BITWIDTH = pt_t::width + eta_t::width + phi_t::width + pt_t::width + emid_t::width; + static const int BITWIDTH_SLIM = pt_t::width + eta_t::width + phi_t::width + pt_t::width + emid_t::width; + + static const int BITWIDTH = BITWIDTH_SLIM + srrtot_t::width + meanz_t::width + hoe_t::width; + inline ap_uint pack() const { ap_uint ret; unsigned int start = 0; @@ -49,8 +61,12 @@ namespace l1ct { pack_into_bits(ret, start, hwPhi); pack_into_bits(ret, start, hwEmPt); pack_into_bits(ret, start, hwEmID); + pack_into_bits(ret, start, hwSrrTot); + pack_into_bits(ret, start, hwMeanZ); + pack_into_bits(ret, start, hwHoe); return ret; } + inline static HadCaloObj unpack(const ap_uint &src) { HadCaloObj ret; unsigned int start = 0; @@ -59,8 +75,13 @@ namespace l1ct { unpack_from_bits(src, start, ret.hwPhi); unpack_from_bits(src, start, ret.hwEmPt); unpack_from_bits(src, start, ret.hwEmID); + unpack_from_bits(src, start, ret.hwSrrTot); + unpack_from_bits(src, start, ret.hwMeanZ); + unpack_from_bits(src, start, ret.hwHoe); return ret; } + + inline ap_uint pack_slim() const { return pack()(BITWIDTH_SLIM - 1, 0); } }; inline void clear(HadCaloObj &c) { c.clear(); } @@ -70,10 +91,13 @@ namespace l1ct { eta_t hwEta; // relative to the region center, at calo phi_t hwPhi; // relative to the region center, at calo emid_t hwEmID; + srrtot_t hwSrrTot; + meanz_t hwMeanZ; + hoe_t hwHoe; inline bool operator==(const EmCaloObj &other) const { return hwPt == other.hwPt && hwEta == other.hwEta && hwPhi == other.hwPhi && hwPtErr == other.hwPtErr && - hwEmID == other.hwEmID; + hwEmID == other.hwEmID && hwSrrTot == other.hwSrrTot && hwMeanZ == other.hwMeanZ && hwHoe == other.hwHoe; } inline bool operator>(const EmCaloObj &other) const { return hwPt > other.hwPt; } @@ -85,6 +109,9 @@ namespace l1ct { hwEta = 0; hwPhi = 0; hwEmID = 0; + hwSrrTot = 0; + hwMeanZ = 0; + hwHoe = 0; } int intPt() const { return Scales::intPt(hwPt); } @@ -95,8 +122,14 @@ namespace l1ct { float floatPtErr() const { return Scales::floatPt(hwPtErr); } float floatEta() const { return Scales::floatEta(hwEta); } float floatPhi() const { return Scales::floatPhi(hwPhi); } + float floatSrrTot() const { return Scales::floatSrrTot(hwSrrTot); }; + float floatMeanZ() const { return Scales::floatMeanZ(hwMeanZ); }; + float floatHoe() const { return Scales::floatHoe(hwHoe); }; + + static const int BITWIDTH_SLIM = pt_t::width + eta_t::width + phi_t::width + pt_t::width + emid_t::width; + + static const int BITWIDTH = BITWIDTH_SLIM + srrtot_t::width + meanz_t::width + hoe_t::width; - static const int BITWIDTH = pt_t::width + eta_t::width + phi_t::width + pt_t::width + emid_t::width; inline ap_uint pack() const { ap_uint ret; unsigned int start = 0; @@ -105,6 +138,9 @@ namespace l1ct { pack_into_bits(ret, start, hwPhi); pack_into_bits(ret, start, hwPtErr); pack_into_bits(ret, start, hwEmID); + pack_into_bits(ret, start, hwSrrTot); + pack_into_bits(ret, start, hwMeanZ); + pack_into_bits(ret, start, hwHoe); return ret; } inline static EmCaloObj unpack(const ap_uint &src) { @@ -115,8 +151,14 @@ namespace l1ct { unpack_from_bits(src, start, ret.hwPhi); unpack_from_bits(src, start, ret.hwPtErr); unpack_from_bits(src, start, ret.hwEmID); + unpack_from_bits(src, start, ret.hwSrrTot); + unpack_from_bits(src, start, ret.hwMeanZ); + unpack_from_bits(src, start, ret.hwHoe); + return ret; } + + inline ap_uint pack_slim() const { return pack()(BITWIDTH_SLIM - 1, 0); } }; inline void clear(EmCaloObj &c) { c.clear(); } @@ -130,6 +172,11 @@ namespace l1ct { z0_t hwZ0; dxy_t hwDxy; tkquality_t hwQuality; + stub_t hwStubs; + redChi2Bin_t hwRedChi2RZ; // 4 bits + redChi2Bin_t hwRedChi2RPhi; // 4 bits + //FIXME: 3 bits would be enough + redChi2Bin_t hwRedChi2Bend; // 4 bits enum TkQuality { PFLOOSE = 1, PFTIGHT = 2 }; bool isPFLoose() const { return hwQuality[0]; } @@ -140,7 +187,8 @@ namespace l1ct { inline bool operator==(const TkObj &other) const { return hwPt == other.hwPt && hwEta == other.hwEta && hwPhi == other.hwPhi && hwDEta == other.hwDEta && hwDPhi == other.hwDPhi && hwZ0 == other.hwZ0 && hwDxy == other.hwDxy && hwCharge == other.hwCharge && - hwQuality == other.hwQuality; + hwQuality == other.hwQuality && hwStubs == other.hwStubs && hwRedChi2RZ == other.hwRedChi2RZ && + hwRedChi2RPhi == other.hwRedChi2RPhi && hwRedChi2Bend == other.hwRedChi2Bend; } inline bool operator>(const TkObj &other) const { return hwPt > other.hwPt; } @@ -156,6 +204,10 @@ namespace l1ct { hwDxy = 0; hwCharge = false; hwQuality = 0; + hwStubs = 0; + hwRedChi2RZ = 0; + hwRedChi2RPhi = 0; + hwRedChi2Bend = 0; } int intPt() const { return Scales::intPt(hwPt); } @@ -174,8 +226,12 @@ namespace l1ct { float floatZ0() const { return Scales::floatZ0(hwZ0); } float floatDxy() const { return Scales::floatDxy(hwDxy); } - static const int BITWIDTH = pt_t::width + eta_t::width + phi_t::width + tkdeta_t::width + tkdphi_t::width + 1 + - z0_t::width + dxy_t::width + tkquality_t::width; + static const int BITWIDTH_SLIM = pt_t::width + eta_t::width + phi_t::width + tkdeta_t::width + tkdphi_t::width + 1 + + z0_t::width + dxy_t::width + tkquality_t::width; + + static const int BITWIDTH = + BITWIDTH_SLIM + stub_t::width + redChi2Bin_t::width + redChi2Bin_t::width + redChi2Bin_t::width; + inline ap_uint pack() const { ap_uint ret; unsigned int start = 0; @@ -188,6 +244,10 @@ namespace l1ct { pack_into_bits(ret, start, hwZ0); pack_into_bits(ret, start, hwDxy); pack_into_bits(ret, start, hwQuality); + pack_into_bits(ret, start, hwStubs); + pack_into_bits(ret, start, hwRedChi2RZ); + pack_into_bits(ret, start, hwRedChi2RPhi); + pack_into_bits(ret, start, hwRedChi2Bend); return ret; } inline static TkObj unpack(const ap_uint &src) { @@ -202,8 +262,13 @@ namespace l1ct { unpack_from_bits(src, start, ret.hwZ0); unpack_from_bits(src, start, ret.hwDxy); unpack_from_bits(src, start, ret.hwQuality); + unpack_from_bits(src, start, ret.hwStubs); + unpack_from_bits(src, start, ret.hwRedChi2RZ); + unpack_from_bits(src, start, ret.hwRedChi2RPhi); + unpack_from_bits(src, start, ret.hwRedChi2Bend); return ret; } + inline ap_uint pack_slim() const { return pack()(BITWIDTH_SLIM - 1, 0); } }; inline void clear(TkObj &c) { c.clear(); } diff --git a/DataFormats/L1TParticleFlow/src/PFCandidate.cc b/DataFormats/L1TParticleFlow/src/PFCandidate.cc index 964e55687ec86..36907c32df2ad 100644 --- a/DataFormats/L1TParticleFlow/src/PFCandidate.cc +++ b/DataFormats/L1TParticleFlow/src/PFCandidate.cc @@ -5,6 +5,8 @@ l1t::PFCandidate::PFCandidate( : L1Candidate(p, hwpt, hweta, hwphi, /*hwQuality=*/int(kind)), dxy_(0), puppiWeight_(puppiWeight), + caloEta_(0), + caloPhi_(0), hwZ0_(0), hwDxy_(0), hwTkQuality_(0), diff --git a/DataFormats/L1TParticleFlow/src/classes_def.xml b/DataFormats/L1TParticleFlow/src/classes_def.xml index 5f90ab44bb63d..c0ec668e42d2e 100644 --- a/DataFormats/L1TParticleFlow/src/classes_def.xml +++ b/DataFormats/L1TParticleFlow/src/classes_def.xml @@ -1,6 +1,7 @@ - + + @@ -19,7 +20,8 @@ - + + @@ -67,4 +69,3 @@ - diff --git a/DataFormats/L1TParticleFlow/src/layer1_emulator.cpp b/DataFormats/L1TParticleFlow/src/layer1_emulator.cpp index f0b56b1c25022..3f1284413bbf7 100644 --- a/DataFormats/L1TParticleFlow/src/layer1_emulator.cpp +++ b/DataFormats/L1TParticleFlow/src/layer1_emulator.cpp @@ -34,14 +34,14 @@ bool l1ct::EmCaloObjEmu::write(std::fstream& to) const { return writeObj(from, *this) && readVar(from, hwChi2) && readVar(from, hwStubs) && readVar(from, simPt) && - readVar(from, simCaloEta) && readVar(from, simCaloPhi) && readVar(from, simVtxEta) && - readVar(from, simVtxPhi) && readVar(from, simZ0) && readVar(from, simD0); + return readObj(from, *this) && readVar(from, hwChi2) && readVar(from, simPt) && readVar(from, simCaloEta) && + readVar(from, simCaloPhi) && readVar(from, simVtxEta) && readVar(from, simVtxPhi) && readVar(from, simZ0) && + readVar(from, simD0); } bool l1ct::TkObjEmu::write(std::fstream& to) const { - return writeObj(*this, to) && writeVar(hwChi2, to) && writeVar(hwStubs, to) && writeVar(simPt, to) && - writeVar(simCaloEta, to) && writeVar(simCaloPhi, to) && writeVar(simVtxEta, to) && writeVar(simVtxPhi, to) && - writeVar(simZ0, to) && writeVar(simD0, to); + return writeObj(*this, to) && writeVar(hwChi2, to) && writeVar(simPt, to) && writeVar(simCaloEta, to) && + writeVar(simCaloPhi, to) && writeVar(simVtxEta, to) && writeVar(simVtxPhi, to) && writeVar(simZ0, to) && + writeVar(simD0, to); } bool l1ct::MuObjEmu::read(std::fstream& from) { diff --git a/L1Trigger/Phase2L1ParticleFlow/interface/common/inversion.h b/L1Trigger/Phase2L1ParticleFlow/interface/common/inversion.h new file mode 100644 index 0000000000000..bf784f7bdbb5a --- /dev/null +++ b/L1Trigger/Phase2L1ParticleFlow/interface/common/inversion.h @@ -0,0 +1,63 @@ +#ifndef CC_INVERSION_H__ +#define CC_INVERSION_H__ + +namespace l1ct { + + constexpr int ceillog2(int x) { return (x <= 2) ? 1 : 1 + ceillog2((x + 1) / 2); } + + template + inline float real_val_from_idx(unsigned i) { + // Treat the index as the top N bits + static constexpr int NB = ceillog2(N); // number of address bits for table + data_T x(0); + // The MSB of 1 is implicit in the table + x[x.width - 1] = 1; + // So we can use the next NB bits for real data + x(x.width - 2, x.width - NB - 1) = i; + return (float)x; + } + + template + inline unsigned idx_from_real_val(data_T x) { + // Slice the top N bits to get an index into the table + static constexpr int NB = ceillog2(N); // number of address bits for table + // Slice the top-1 NB bits of the value + // the MSB of '1' is implicit, so only slice below that + ap_uint y = x(x.width - 2, x.width - NB - 1); + return (unsigned)y(NB - 1, 0); + } + + template + void init_invert_table(table_T table_out[N]) { + // The template data_T is the data type used to address the table + for (unsigned i = 0; i < N; i++) { + float x = real_val_from_idx(i); + table_T inv_x = 1 / x; + table_out[i] = inv_x; + } + } + + template + table_t invert_with_shift(in_t in) { + table_t inv_table[N]; + init_invert_table(inv_table); + + // find the first '1' in the denominator + int msb = 0; + for (int b = 0; b < in.width; b++) { + // #pragma HLS unroll + if (in[b]) + msb = b; + } + // shift up the denominator such that the left-most bit (msb) is '1' + in_t in_shifted = in << (in.width - msb - 1); + // lookup the inverse of the shifted input + int idx = idx_from_real_val(in_shifted); + table_t inv_in = inv_table[idx]; + // shift the output back + table_t out = inv_in << (in.width - msb - 1); + return out; + } + +} // namespace l1ct +#endif \ No newline at end of file diff --git a/L1Trigger/Phase2L1ParticleFlow/interface/conifer.h b/L1Trigger/Phase2L1ParticleFlow/interface/conifer.h index eb258b6088127..f2c6efedc4676 100644 --- a/L1Trigger/Phase2L1ParticleFlow/interface/conifer.h +++ b/L1Trigger/Phase2L1ParticleFlow/interface/conifer.h @@ -1,8 +1,12 @@ #ifndef L1TRIGGER_PHASE2L1PARTICLEFLOW_CONNIFER_H #define L1TRIGGER_PHASE2L1PARTICLEFLOW_CONNIFER_H -#include "FWCore/Utilities/interface/Exception.h" #include "nlohmann/json.hpp" #include +#ifdef CMSSW_GIT_HASH +#include "FWCore/Utilities/interface/Exception.h" +#else +#include +#endif namespace conifer { @@ -115,18 +119,25 @@ namespace conifer { std::vector decision_function(std::vector x) const { /* Do the prediction */ +#ifdef CMSSW_GIT_HASH if (x.size() != n_features) { throw cms::Exception("RuntimeError") << "Conifer : Size of feature vector mismatches expected n_features" << std::endl; } +#else + if (x.size() != n_features) { + throw std::runtime_error("Conifer : Size of feature vector mismatches expected n_features"); + } +#endif std::vector values; std::vector> values_trees; values_trees.resize(n_classes); values.resize(n_classes, U(0)); for (unsigned int i = 0; i < n_classes; i++) { - std::transform(trees.begin(), trees.end(), std::back_inserter(values_trees.at(i)), [&i, &x](auto tree_v) { - return tree_v.at(i).decision_function(x); - }); + std::transform(trees.begin(), + trees.end(), + std::back_inserter(values_trees.at(i)), + [&i, &x](std::vector> tree_v) { return tree_v.at(i).decision_function(x); }); if (useAddTree) { values.at(i) = init_predict_.at(i); values.at(i) += reduce>(values_trees.at(i), add); @@ -152,4 +163,4 @@ namespace conifer { } // namespace conifer -#endif \ No newline at end of file +#endif diff --git a/L1Trigger/Phase2L1ParticleFlow/interface/egamma/pftkegalgo_ref.h b/L1Trigger/Phase2L1ParticleFlow/interface/egamma/pftkegalgo_ref.h index b75be595ee9df..560325e46cb0c 100644 --- a/L1Trigger/Phase2L1ParticleFlow/interface/egamma/pftkegalgo_ref.h +++ b/L1Trigger/Phase2L1ParticleFlow/interface/egamma/pftkegalgo_ref.h @@ -4,6 +4,8 @@ #include "DataFormats/L1TParticleFlow/interface/layer1_emulator.h" #include "DataFormats/L1TParticleFlow/interface/egamma.h" #include "DataFormats/L1TParticleFlow/interface/pf.h" +#include "L1Trigger/Phase2L1ParticleFlow/interface/conifer.h" +#include "L1Trigger/Phase2L1ParticleFlow/interface/common/inversion.h" namespace edm { class ParameterSet; @@ -30,6 +32,8 @@ namespace l1ct { std::vector dEtaValues; std::vector dPhiValues; float trkQualityPtMin; // GeV + bool doCompositeTkEle; + unsigned int nCompCandPerCluster; bool writeEgSta; struct IsoParameters { @@ -53,6 +57,18 @@ namespace l1ct { bool doPfIso; EGIsoEleObjEmu::IsoType hwIsoTypeTkEle; EGIsoObjEmu::IsoType hwIsoTypeTkEm; + + struct CompIDParameters { + CompIDParameters(const edm::ParameterSet &); + CompIDParameters(double bdtScore_loose_wp, double bdtScore_tight_wp, const std::string &model) + : bdtScore_loose_wp(bdtScore_loose_wp), bdtScore_tight_wp(bdtScore_tight_wp), conifer_model(model) {} + const double bdtScore_loose_wp; // XGBOOST score + const double bdtScore_tight_wp; // XGBOOST score + const std::string conifer_model; + }; + + CompIDParameters compIDparams; + int debug = 0; PFTkEGAlgoEmuConfig(const edm::ParameterSet &iConfig); @@ -72,6 +88,8 @@ namespace l1ct { const std::vector &dEtaValues = {0.015, 0.01}, const std::vector &dPhiValues = {0.07, 0.07}, float trkQualityPtMin = 10., + bool doCompositeTkEle = false, + unsigned int nCompCandPerCluster = 4, bool writeEgSta = false, const IsoParameters &tkIsoParams_tkEle = {2., 0.6, 0.03, 0.2}, const IsoParameters &tkIsoParams_tkEm = {2., 0.6, 0.07, 0.3}, @@ -81,6 +99,7 @@ namespace l1ct { bool doPfIso = false, EGIsoEleObjEmu::IsoType hwIsoTypeTkEle = EGIsoEleObjEmu::IsoType::TkIso, EGIsoObjEmu::IsoType hwIsoTypeTkEm = EGIsoObjEmu::IsoType::TkIsoPV, + const CompIDParameters &compIDparams = {-4, 0.214844, "compositeID.json"}, int debug = 0) : nTRACK(nTrack), @@ -99,6 +118,8 @@ namespace l1ct { dEtaValues(dEtaValues), dPhiValues(dPhiValues), trkQualityPtMin(trkQualityPtMin), + doCompositeTkEle(doCompositeTkEle), + nCompCandPerCluster(nCompCandPerCluster), writeEgSta(writeEgSta), tkIsoParams_tkEle(tkIsoParams_tkEle), tkIsoParams_tkEm(tkIsoParams_tkEm), @@ -108,12 +129,13 @@ namespace l1ct { doPfIso(doPfIso), hwIsoTypeTkEle(hwIsoTypeTkEle), hwIsoTypeTkEm(hwIsoTypeTkEm), + compIDparams(compIDparams), debug(debug) {} }; class PFTkEGAlgoEmulator { public: - PFTkEGAlgoEmulator(const PFTkEGAlgoEmuConfig &config) : cfg(config), debug_(cfg.debug) {} + PFTkEGAlgoEmulator(const PFTkEGAlgoEmuConfig &config); virtual ~PFTkEGAlgoEmulator() {} @@ -132,13 +154,33 @@ namespace l1ct { bool writeEgSta() const { return cfg.writeEgSta; } + typedef ap_fixed<21, 12, AP_RND_CONV, AP_SAT> bdt_feature_t; + typedef ap_fixed<12, 3, AP_RND_CONV, AP_SAT> bdt_score_t; + private: void link_emCalo2emCalo(const std::vector &emcalo, std::vector &emCalo2emCalo) const; - void link_emCalo2tk(const PFRegionEmu &r, - const std::vector &emcalo, - const std::vector &track, - std::vector &emCalo2tk) const; + void link_emCalo2tk_elliptic(const PFRegionEmu &r, + const std::vector &emcalo, + const std::vector &track, + std::vector &emCalo2tk) const; + + void link_emCalo2tk_composite(const PFRegionEmu &r, + const std::vector &emcalo, + const std::vector &track, + std::vector &emCalo2tk, + std::vector &emCaloTkBdtScore) const; + + struct CompositeCandidate { + unsigned int cluster_idx; + unsigned int track_idx; + double dpt; // For sorting + }; + + float compute_composite_score(CompositeCandidate &cand, + const std::vector &emcalo, + const std::vector &track, + const PFTkEGAlgoEmuConfig::CompIDParameters ¶ms) const; //FIXME: still needed float deltaPhi(float phi1, float phi2) const; @@ -152,6 +194,7 @@ namespace l1ct { const std::vector &track, const std::vector &emCalo2emCalo, const std::vector &emCalo2tk, + const std::vector &emCaloTkBdtScore, std::vector &egstas, std::vector &egobjs, std::vector &egeleobjs) const; @@ -165,6 +208,7 @@ namespace l1ct { const unsigned int hwQual, const pt_t ptCorr, const int tk_idx, + const float bdtScore, const std::vector &components = {}) const; EGObjEmu &addEGStaToPF(std::vector &egobjs, @@ -182,7 +226,8 @@ namespace l1ct { const EmCaloObjEmu &calo, const TkObjEmu &track, const unsigned int hwQual, - const pt_t ptCorr) const; + const pt_t ptCorr, + const float bdtScore) const; // FIXME: reimplemented from PFAlgoEmulatorBase template @@ -309,6 +354,7 @@ namespace l1ct { z0_t z0) const; PFTkEGAlgoEmuConfig cfg; + conifer::BDT, false> *composite_bdt_; int debug_; }; } // namespace l1ct diff --git a/L1Trigger/Phase2L1ParticleFlow/interface/l1-converters/tkinput_ref.h b/L1Trigger/Phase2L1ParticleFlow/interface/l1-converters/tkinput_ref.h index 585156036ca9a..2545a6dabc243 100644 --- a/L1Trigger/Phase2L1ParticleFlow/interface/l1-converters/tkinput_ref.h +++ b/L1Trigger/Phase2L1ParticleFlow/interface/l1-converters/tkinput_ref.h @@ -22,14 +22,24 @@ namespace l1ct { }; TrackInputEmulator(const edm::ParameterSet &iConfig); - TrackInputEmulator(Region = Region::Endcap, Encoding encoding = Encoding::Stepping, bool bitwise = true); + TrackInputEmulator(Region = Region::Endcap, + Encoding encoding = Encoding::Stepping, + bool bitwise = true, + bool slim = true); std::pair decodeTrack(ap_uint<96> tkword, const l1ct::PFRegionEmu §or) const { - return decodeTrack(tkword, sector, bitwise_); + return decodeTrack(tkword, sector, bitwise_, slim_); } std::pair decodeTrack(ap_uint<96> tkword, const l1ct::PFRegionEmu §or, - bool bitwise) const; + bool bitwise) const { + return decodeTrack(tkword, sector, bitwise, slim_); + } + + std::pair decodeTrack(ap_uint<96> tkword, + const l1ct::PFRegionEmu §or, + bool bitwise, + bool slim) const; //== Unpackers == static bool valid(const ap_uint<96> &tkword) { return tkword[95]; } @@ -151,6 +161,15 @@ namespace l1ct { const std::vector &tanlLUT() const { return tanlLUT_; } const std::vector &ptLUT() const { return ptLUT_; } + unsigned int countSetBits(unsigned int n) const { + unsigned int count = 0; + while (n) { + n &= (n - 1); + count++; + } + return count; + } + protected: // utilities template @@ -175,6 +194,9 @@ namespace l1ct { /// Whether to run the bitwise accurate or floating point conversions bool bitwise_; + /// Whether to unpack and populate also nstubs and various chi2 variables (needed for CompibedID in the endcap) + bool slim_; + /// Main constants float rInvToPt_, phiScale_, z0Scale_; diff --git a/L1Trigger/Phase2L1ParticleFlow/plugins/L1TCorrelatorLayer1Producer.cc b/L1Trigger/Phase2L1ParticleFlow/plugins/L1TCorrelatorLayer1Producer.cc index f5599d121d0b9..f53e14e2a5fc7 100644 --- a/L1Trigger/Phase2L1ParticleFlow/plugins/L1TCorrelatorLayer1Producer.cc +++ b/L1Trigger/Phase2L1ParticleFlow/plugins/L1TCorrelatorLayer1Producer.cc @@ -72,7 +72,6 @@ class L1TCorrelatorLayer1Producer : public edm::stream::EDProducer<> { std::unique_ptr l1tkegalgo_; std::unique_ptr l1tkegsorter_; - bool writeEgSta_; // Region dump const std::string regionDumpName_; bool writeRawHgcalCluster_; @@ -114,6 +113,7 @@ class L1TCorrelatorLayer1Producer : public edm::stream::EDProducer<> { std::unique_ptr fetchEmCalo() const; std::unique_ptr fetchTracks() const; std::unique_ptr fetchPF() const; + std::unique_ptr> fetchDecodedTracks() const; void putPuppi(edm::Event &iEvent) const; void putEgStaObjects(edm::Event &iEvent, @@ -175,6 +175,7 @@ L1TCorrelatorLayer1Producer::L1TCorrelatorLayer1Producer(const edm::ParameterSet #if 0 // LATER produces("TKVtx"); #endif + produces>("DecodedTK"); for (const auto &tag : iConfig.getParameter>("emClusters")) { emCands_.push_back(consumes(tag)); @@ -364,6 +365,7 @@ void L1TCorrelatorLayer1Producer::produce(edm::Event &iEvent, const edm::EventSe iEvent.put(fetchEmCalo(), "EmCalo"); iEvent.put(fetchHadCalo(), "Calo"); iEvent.put(fetchTracks(), "TK"); + iEvent.put(fetchDecodedTracks(), "DecodedTK"); // Then do the vertexing, and save it out std::vector z0s; @@ -636,7 +638,6 @@ void L1TCorrelatorLayer1Producer::addDecodedTrack(l1ct::DetectorSector> &sec, const l1t::PFCluster &c) { ap_uint<256> cwrd = 0; - ap_uint<14> w_pt = round(c.pt() / 0.25); + ap_ufixed<14, 12, AP_RND_CONV, AP_SAT> w_pt = c.pt(); ap_uint<14> w_empt = round(c.emEt() / 0.25); constexpr float ETAPHI_LSB = M_PI / 720; ap_int<9> w_eta = round(sec.region.localEta(c.eta()) / ETAPHI_LSB); ap_int<9> w_phi = round(sec.region.localPhi(c.phi()) / ETAPHI_LSB); ap_uint<10> w_qual = c.hwQual(); - - cwrd(13, 0) = w_pt; + // NOTE: this is an arbitrary choice to keep the rounding consistent with the "addDecodedHadCalo" one + ap_uint<13> w_srrtot = round(c.sigmaRR() * l1ct::Scales::SRRTOT_SCALE / l1ct::Scales::SRRTOT_LSB); + ap_uint<12> w_meanz = round(c.absZBarycenter()); + // NOTE: the calibration can actually make hoe become negative....we add a small protection for now + // We use ap_ufixed to handle saturation and rounding + ap_ufixed<10, 5, AP_RND_CONV, AP_SAT> w_hoe = c.hOverE(); + + cwrd(13, 0) = w_pt.range(); cwrd(27, 14) = w_empt; cwrd(72, 64) = w_eta; cwrd(81, 73) = w_phi; cwrd(115, 106) = w_qual; + // FIXME: we add the variables use by composite-ID. The definitin will have to be reviewd once the + // hgc format is better defined. For now we use + // hwMeanZ = word 1 bits 30-19 + // hwSrrTot = word 3 bits 21 - 9 + // hoe = word 1 bits 63-52 (currently spare in the interface) + cwrd(213, 201) = w_srrtot; + cwrd(94, 83) = w_meanz; + cwrd(127, 116) = w_hoe.range(); + sec.obj.push_back(cwrd); } void L1TCorrelatorLayer1Producer::addDecodedEmCalo(l1ct::DetectorSector &sec, const l1t::PFCluster &c) { l1ct::EmCaloObjEmu calo; + // set the endcap-sepcific variables to default value: + calo.clear(); calo.hwPt = l1ct::Scales::makePtFromFloat(c.pt()); calo.hwEta = l1ct::Scales::makeGlbEta(c.eta()) - sec.region.hwEtaCenter; // important to enforce that the region boundary is on a discrete value @@ -841,6 +863,37 @@ std::unique_ptr L1TCorrelatorLayer1Producer::fetchTr return ret; } +std::unique_ptr> L1TCorrelatorLayer1Producer::fetchDecodedTracks() const { + auto ret = std::make_unique>(); + for (const auto &r : event_.decoded.track) { + const auto ® = r.region; + for (const auto &p : r.obj) { + if (p.hwPt == 0 || !reg.isFiducial(p)) + continue; + reco::Particle::PolarLorentzVector p4( + p.floatPt(), reg.floatGlbEta(p.hwVtxEta()), reg.floatGlbPhi(p.hwVtxPhi()), 0); + + reco::Particle::Point vtx(0, 0, p.floatZ0()); + + ret->emplace_back(l1t::PFTrack(p.intCharge(), + reco::Particle::LorentzVector(p4), + vtx, + p.src->track(), + 0, + reg.floatGlbEta(p.hwEta), + reg.floatGlbPhi(p.hwPhi), + -1, + -1, + p.hwQuality.to_int(), + false, + p.intPt(), + p.intEta(), + p.intPhi())); + } + } + return ret; +} + std::unique_ptr L1TCorrelatorLayer1Producer::fetchPF() const { auto ret = std::make_unique(); for (unsigned int ir = 0, nr = event_.pfinputs.size(); ir < nr; ++ir) { @@ -861,6 +914,9 @@ std::unique_ptr L1TCorrelatorLayer1Producer::fetchPF ret->back().setHwZ0(p.hwZ0); ret->back().setHwDxy(p.hwDxy); ret->back().setHwTkQuality(p.hwTkQuality); + ret->back().setCaloEta(reg.floatGlbEtaOf(p)); + ret->back().setCaloPhi(reg.floatGlbPhiOf(p)); + setRefs_(ret->back(), p); } for (const auto &p : event_.out[ir].pfneutral) { @@ -871,6 +927,8 @@ std::unique_ptr L1TCorrelatorLayer1Producer::fetchPF p.hwId.isPhoton() ? l1t::PFCandidate::Photon : l1t::PFCandidate::NeutralHadron; ret->emplace_back(type, 0, p4, 1, p.intPt(), p.intEta(), p.intPhi()); ret->back().setHwEmID(p.hwEmID); + ret->back().setCaloEta(reg.floatGlbEtaOf(p)); + ret->back().setCaloPhi(reg.floatGlbPhiOf(p)); setRefs_(ret->back(), p); } } @@ -1042,6 +1100,7 @@ void L1TCorrelatorLayer1Producer::putEgObjects(edm::Event &iEvent, tkele.setHwQual(egele.hwQual); tkele.setPFIsol(egele.floatRelIso(l1ct::EGIsoEleObjEmu::IsoType::PfIso)); tkele.setEgBinaryWord(egele.pack()); + tkele.setIdScore(egele.idScore); tkeles->push_back(tkele); nele_obj.push_back(tkeles->size() - 1); } diff --git a/L1Trigger/Phase2L1ParticleFlow/plugins/L1TCtL2EgProducer.cc b/L1Trigger/Phase2L1ParticleFlow/plugins/L1TCtL2EgProducer.cc index 99b0251eff85b..54399d8a497a3 100644 --- a/L1Trigger/Phase2L1ParticleFlow/plugins/L1TCtL2EgProducer.cc +++ b/L1Trigger/Phase2L1ParticleFlow/plugins/L1TCtL2EgProducer.cc @@ -351,7 +351,8 @@ void L1TCtL2EgProducer::convertToEmu(const l1t::TkElectron &tkele, emu.setHwIso(EGIsoEleObjEmu::IsoType::PfIso, l1ct::Scales::makeIso(tkele.pfIsol() * tkele.pt())); emu.setHwIso(EGIsoEleObjEmu::IsoType::PuppiIso, l1ct::Scales::makeIso(tkele.puppiIsol() * tkele.pt())); // std::cout << "[convertToEmu] TkEle pt: " << emu.hwPt << " eta: " << emu.hwEta << " phi: " << emu.hwPhi << " staidx: " << emu.sta_idx << std::endl; - + // FIXME: this is temporary while waiting to move the BDT score to the FW object + emu.idScore = tkele.idScore(); boarOut.egelectron.push_back(emu); } @@ -421,6 +422,7 @@ l1t::TkElectron L1TCtL2EgProducer::convertFromEmu(const l1ct::EGIsoEleObjEmu &eg tkele.setPFIsol(egele.floatRelIso(l1ct::EGIsoEleObjEmu::IsoType::PfIso)); tkele.setPuppiIsol(egele.floatRelIso(l1ct::EGIsoEleObjEmu::IsoType::PuppiIso)); tkele.setEgBinaryWord(gteg.pack()); + tkele.setIdScore(egele.idScore); return tkele; } diff --git a/L1Trigger/Phase2L1ParticleFlow/plugins/PFClusterProducerFromHGC3DClusters.cc b/L1Trigger/Phase2L1ParticleFlow/plugins/PFClusterProducerFromHGC3DClusters.cc index 7d393fe347bd9..0a76d751f90c0 100644 --- a/L1Trigger/Phase2L1ParticleFlow/plugins/PFClusterProducerFromHGC3DClusters.cc +++ b/L1Trigger/Phase2L1ParticleFlow/plugins/PFClusterProducerFromHGC3DClusters.cc @@ -129,7 +129,8 @@ void l1tpf::PFClusterProducerFromHGC3DClusters::produce(edm::Event &iEvent, cons //float em_old = cluster.emEt(); float em_new = it->iPt(l1t::HGCalMulticluster::EnergyInterpretation::EM); float pt_new = had_old + em_new; - float hoe_new = em_new > 0 ? (had_old / em_new) : -1; + // FIXME: -1 can be a problem for later stages of the processing. For now we set it to something which saturates the hoe variable + float hoe_new = em_new > 0 ? (had_old / em_new) : 999; cluster = l1t::PFCluster(pt_new, it->eta(), it->phi(), hoe_new, /*isEM=*/isEM); //printf("Scenario %d: pt %7.2f eta %+5.3f em %7.2f, EMI %7.2f, h/e % 8.3f --> pt %7.2f, em %7.2f, h/e % 8.3f\n", // 2, pt, it->eta(), em_old, em_new, hoe, cluster.pt(), cluster.emEt(), cluster.hOverE()); @@ -156,6 +157,10 @@ void l1tpf::PFClusterProducerFromHGC3DClusters::produce(edm::Event &iEvent, cons corrector_.correctPt(cluster); cluster.setPtError(resol_(cluster.pt(), std::abs(cluster.eta()))); + // We se the cluster shape variables used downstream + cluster.setAbsZBarycenter(fabs(it->zBarycenter())); + cluster.setSigmaRR(it->sigmaRRTot()); + out->push_back(cluster); out->back().addConstituent(edm::Ptr(multiclusters, multiclusters->key(it))); if (hasEmId_) { diff --git a/L1Trigger/Phase2L1ParticleFlow/python/l1TkEgAlgoEmulator_cfi.py b/L1Trigger/Phase2L1ParticleFlow/python/l1TkEgAlgoEmulator_cfi.py index 3d1621b655d56..4b267ff987db1 100644 --- a/L1Trigger/Phase2L1ParticleFlow/python/l1TkEgAlgoEmulator_cfi.py +++ b/L1Trigger/Phase2L1ParticleFlow/python/l1TkEgAlgoEmulator_cfi.py @@ -1,6 +1,5 @@ import FWCore.ParameterSet.Config as cms - tkEgAlgoParameters = cms.PSet( nTRACK=cms.uint32(50), # very large numbers for first test nTRACK_EGIN=cms.uint32(50), # very large numbers for first test @@ -50,7 +49,15 @@ doTkIso=cms.bool(True), doPfIso=cms.bool(True), hwIsoTypeTkEle=cms.uint32(0), - hwIsoTypeTkEm=cms.uint32(2) + hwIsoTypeTkEm=cms.uint32(2), + doCompositeTkEle=cms.bool(False), + nCompCandPerCluster=cms.uint32(3), + compositeParametersTkEle=cms.PSet( + # the working points are cuts on BDT output logits log(p/1-p) + loose_wp=cms.double(-0.732422), + tight_wp=cms.double(0.214844), + model=cms.string("L1Trigger/Phase2L1ParticleFlow/data/compositeID.json") + ), ) tkEgSorterParameters = cms.PSet( diff --git a/L1Trigger/Phase2L1ParticleFlow/python/l1TkEgAlgo_cfi.py b/L1Trigger/Phase2L1ParticleFlow/python/l1TkEgAlgo_cfi.py deleted file mode 100644 index 500121131a360..0000000000000 --- a/L1Trigger/Phase2L1ParticleFlow/python/l1TkEgAlgo_cfi.py +++ /dev/null @@ -1,47 +0,0 @@ -import FWCore.ParameterSet.Config as cms - -tkEgConfig = cms.PSet( - debug=cms.untracked.int32(0), - doBremRecovery=cms.bool(True), - doTkIsolation=cms.bool(True), - filterHwQuality=cms.bool(True), - caloHwQual=cms.int32(4), - dEtaMaxBrem=cms.double(0.02), - dPhiMaxBrem=cms.double(0.1), - absEtaBoundaries=cms.vdouble(0.0, 0.9, 1.5), - dEtaValues=cms.vdouble(0.025, 0.015, 0.01), # last was 0.0075 in TDR - dPhiValues=cms.vdouble(0.07, 0.07, 0.07), - caloEtMin=cms.double(0.0), - trkQualityPtMin=cms.double(10.0), - trkQualityChi2=cms.double(1e10), - writeEgSta=cms.bool(True), - tkIsoParametersTkEm=cms.PSet( - tkQualityPtMin=cms.double(2.), - dZ=cms.double(0.6), - dRMin=cms.double(0.07), - dRMax=cms.double(0.30), - tkQualityChi2Max=cms.double(100), - ), - tkIsoParametersTkEle=cms.PSet( - tkQualityPtMin=cms.double(2.), - dZ=cms.double(0.6), - dRMin=cms.double(0.03), - dRMax=cms.double(0.20), - tkQualityChi2Max=cms.double(1e10), - ), - pfIsoParametersTkEm=cms.PSet( - tkQualityPtMin=cms.double(1.), - dZ=cms.double(0.6), - dRMin=cms.double(0.07), - dRMax=cms.double(0.30), - tkQualityChi2Max=cms.double(100), - ), - pfIsoParametersTkEle=cms.PSet( - tkQualityPtMin=cms.double(1.), - dZ=cms.double(0.6), - dRMin=cms.double(0.03), - dRMax=cms.double(0.20), - tkQualityChi2Max=cms.double(1e10), - ) - -) diff --git a/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer1_cff.py b/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer1_cff.py index e0b2e6542ae5d..ac92502e74128 100644 --- a/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer1_cff.py +++ b/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer1_cff.py @@ -29,6 +29,7 @@ region = cms.string("barrel"), trackWordEncoding = cms.string("biased"), bitwiseAccurate = cms.bool(True), + slimDataFormat = cms.bool(True), ptLUTBits = cms.uint32(11), etaLUTBits = cms.uint32(10), etaPreOffs = cms.int32(0), @@ -169,6 +170,7 @@ region = cms.string("endcap"), trackWordEncoding = cms.string("biased"), bitwiseAccurate = cms.bool(True), + slimDataFormat = cms.bool(False), ptLUTBits = cms.uint32(11), etaLUTBits = cms.uint32(11), etaPreOffs = cms.int32(0), @@ -261,7 +263,9 @@ doBremRecovery=True, doEndcapHwQual=True, writeBeforeBremRecovery=False, - writeEGSta=True), + writeEGSta=True, + doCompositeTkEle=True, + trkQualityPtMin=0.), # This should be 10 GeV when doCompositeTkEle=False tkEgSorterParameters=tkEgSorterParameters.clone( nObjToSort = 5 ), @@ -290,8 +294,15 @@ writeRawHgcalCluster = cms.untracked.bool(True) ) + l1tLayer1HGCalExtended = l1tLayer1HGCal.clone(tracks = ('l1tPFTracksFromL1TracksExtended')) +l1tLayer1HGCalElliptic = l1tLayer1HGCal.clone( + tkEgAlgoParameters = l1tLayer1HGCal.tkEgAlgoParameters.clone( + doCompositeTkEle = False, + trkQualityPtMin = 10.) +) + l1tLayer1HGCalNoTK = cms.EDProducer("L1TCorrelatorLayer1Producer", tracks = cms.InputTag(''), muons = cms.InputTag('l1tSAMuonsGmt','promptSAMuons'), @@ -522,6 +533,50 @@ ) ) +l1tLayer1EGElliptic = cms.EDProducer( + "L1TEGMultiMerger", + tkElectrons=cms.VPSet( + cms.PSet( + instance=cms.string("L1TkEleEE"), + pfProducers=cms.VInputTag( + cms.InputTag("l1tLayer1HGCalElliptic", 'L1TkEle') + ) + ), + cms.PSet( + instance=cms.string("L1TkEleEB"), + pfProducers=cms.VInputTag( + cms.InputTag("l1tLayer1Barrel", 'L1TkEle') + ) + ) + ), + tkEms=cms.VPSet( + cms.PSet( + instance=cms.string("L1TkEmEE"), + pfProducers=cms.VInputTag( + cms.InputTag("l1tLayer1HGCalElliptic", 'L1TkEm'), + cms.InputTag("l1tLayer1HGCalNoTK", 'L1TkEm') + ) + ), + cms.PSet( + instance=cms.string("L1TkEmEB"), + pfProducers=cms.VInputTag( + cms.InputTag("l1tLayer1Barrel", 'L1TkEm') + ) + ) + ), + tkEgs=cms.VPSet( + cms.PSet( + instance=cms.string("L1EgEE"), + pfProducers=cms.VInputTag( + cms.InputTag("l1tLayer1HGCalElliptic", 'L1Eg'), + cms.InputTag("l1tLayer1HGCalNoTK", 'L1Eg') + ) + ) + ) +) + + + L1TLayer1TaskInputsTask = cms.Task( l1tPFClustersFromL1EGClusters, l1tPFClustersFromCombinedCaloHCal, @@ -540,5 +595,7 @@ l1tLayer1HF, l1tLayer1, l1tLayer1Extended, - l1tLayer1EG + l1tLayer1HGCalElliptic, + l1tLayer1EG, + l1tLayer1EGElliptic ) diff --git a/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer2EG_cff.py b/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer2EG_cff.py index f9d9196a1611e..c0e7943579dfa 100644 --- a/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer2EG_cff.py +++ b/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer2EG_cff.py @@ -150,8 +150,46 @@ # ) ) +l1tLayer2EGElliptic = l1tLayer2EG.clone( + tkElectrons=cms.VPSet( + cms.PSet( + pfProducer=cms.InputTag("l1tLayer1HGCalElliptic", 'L1TkElePerBoard'), + channels=cms.vint32(3, 4) + ), + cms.PSet( + pfProducer=cms.InputTag("l1tLayer1Barrel", 'L1TkElePerBoard'), + channels=cms.vint32(0, 1, 2) + ), + ), + tkEms=cms.VPSet( + cms.PSet( + pfProducer=cms.InputTag("l1tLayer1HGCalElliptic", 'L1TkEmPerBoard'), + channels=cms.vint32(3, 4) + ), + cms.PSet( + pfProducer=cms.InputTag("l1tLayer1HGCalNoTK", 'L1TkEmPerBoard'), + channels=cms.vint32(-1) + ), + cms.PSet( + pfProducer=cms.InputTag("l1tLayer1Barrel", 'L1TkEmPerBoard'), + channels=cms.vint32(0, 1, 2) + ), + ), + tkEgs=cms.VPSet( + cms.PSet( + pfProducer=cms.InputTag("l1tLayer1HGCalElliptic", 'L1Eg'), + channels=cms.vint32(-1) + ), + cms.PSet( + pfProducer=cms.InputTag("l1tLayer1HGCalNoTK", 'L1Eg'), + channels=cms.vint32(-1) + ), + ), +) + L1TLayer2EGTask = cms.Task( l1tLayer2Deregionizer, - l1tLayer2EG + l1tLayer2EG, + l1tLayer2EGElliptic ) diff --git a/L1Trigger/Phase2L1ParticleFlow/src/egamma/pfeginput_ref.cpp b/L1Trigger/Phase2L1ParticleFlow/src/egamma/pfeginput_ref.cpp index 71716e7f542c2..560e0eb96df7f 100644 --- a/L1Trigger/Phase2L1ParticleFlow/src/egamma/pfeginput_ref.cpp +++ b/L1Trigger/Phase2L1ParticleFlow/src/egamma/pfeginput_ref.cpp @@ -31,6 +31,10 @@ void EGInputSelectorEmulator::select_eginput(const l1ct::HadCaloObjEmu &in, out.hwPtErr = 0; // shift to get rid of PFEM ID bit (more usable final EG quality) out.hwEmID = (in.hwEmID >> 1); + + out.hwSrrTot = in.hwSrrTot; + out.hwMeanZ = in.hwMeanZ; + out.hwHoe = in.hwHoe; valid_out = (in.hwEmID & cfg.idMask) != 0; } diff --git a/L1Trigger/Phase2L1ParticleFlow/src/egamma/pftkegalgo_ref.cpp b/L1Trigger/Phase2L1ParticleFlow/src/egamma/pftkegalgo_ref.cpp index 2fc881879455d..984dca69f36a5 100644 --- a/L1Trigger/Phase2L1ParticleFlow/src/egamma/pftkegalgo_ref.cpp +++ b/L1Trigger/Phase2L1ParticleFlow/src/egamma/pftkegalgo_ref.cpp @@ -7,6 +7,7 @@ #include #include #include +#include using namespace l1ct; @@ -30,6 +31,8 @@ l1ct::PFTkEGAlgoEmuConfig::PFTkEGAlgoEmuConfig(const edm::ParameterSet &pset) dEtaValues(pset.getParameter>("dEtaValues")), dPhiValues(pset.getParameter>("dPhiValues")), trkQualityPtMin(pset.getParameter("trkQualityPtMin")), + doCompositeTkEle(pset.getParameter("doCompositeTkEle")), + nCompCandPerCluster(pset.getParameter("nCompCandPerCluster")), writeEgSta(pset.getParameter("writeEGSta")), tkIsoParams_tkEle(pset.getParameter("tkIsoParametersTkEle")), tkIsoParams_tkEm(pset.getParameter("tkIsoParametersTkEm")), @@ -39,6 +42,7 @@ l1ct::PFTkEGAlgoEmuConfig::PFTkEGAlgoEmuConfig(const edm::ParameterSet &pset) doPfIso(pset.getParameter("doPfIso")), hwIsoTypeTkEle(static_cast(pset.getParameter("hwIsoTypeTkEle"))), hwIsoTypeTkEm(static_cast(pset.getParameter("hwIsoTypeTkEm"))), + compIDparams(pset.getParameter("compositeParametersTkEle")), debug(pset.getUntrackedParameter("debug", 0)) {} l1ct::PFTkEGAlgoEmuConfig::IsoParameters::IsoParameters(const edm::ParameterSet &pset) @@ -47,8 +51,25 @@ l1ct::PFTkEGAlgoEmuConfig::IsoParameters::IsoParameters(const edm::ParameterSet pset.getParameter("dRMin"), pset.getParameter("dRMax")) {} +l1ct::PFTkEGAlgoEmuConfig::CompIDParameters::CompIDParameters(const edm::ParameterSet &pset) + : CompIDParameters(pset.getParameter("loose_wp"), + pset.getParameter("tight_wp"), + pset.getParameter("model")) {} + #endif +PFTkEGAlgoEmulator::PFTkEGAlgoEmulator(const PFTkEGAlgoEmuConfig &config) + : cfg(config), composite_bdt_(nullptr), debug_(cfg.debug) { + if (cfg.doCompositeTkEle) { +#ifdef CMSSW_GIT_HASH + auto resolvedFileName = edm::FileInPath(cfg.compIDparams.conifer_model).fullPath(); +#else + auto resolvedFileName = cfg.compIDparams.conifer_model; +#endif + composite_bdt_ = new conifer::BDT(resolvedFileName); + } +} + void PFTkEGAlgoEmulator::toFirmware(const PFInputRegion &in, PFRegion ®ion, EmCaloObj emcalo[/*nCALO*/], @@ -109,10 +130,10 @@ void PFTkEGAlgoEmulator::link_emCalo2emCalo(const std::vector &emc } } -void PFTkEGAlgoEmulator::link_emCalo2tk(const PFRegionEmu &r, - const std::vector &emcalo, - const std::vector &track, - std::vector &emCalo2tk) const { +void PFTkEGAlgoEmulator::link_emCalo2tk_elliptic(const PFRegionEmu &r, + const std::vector &emcalo, + const std::vector &track, + std::vector &emCalo2tk) const { unsigned int nTrackMax = std::min(track.size(), cfg.nTRACK_EGIN); for (int ic = 0, nc = emcalo.size(); ic < nc; ++ic) { auto &calo = emcalo[ic]; @@ -146,6 +167,90 @@ void PFTkEGAlgoEmulator::link_emCalo2tk(const PFRegionEmu &r, } } +void PFTkEGAlgoEmulator::link_emCalo2tk_composite(const PFRegionEmu &r, + const std::vector &emcalo, + const std::vector &track, + std::vector &emCalo2tk, + std::vector &emCaloTkBdtScore) const { + unsigned int nTrackMax = std::min(track.size(), cfg.nTRACK_EGIN); + for (int ic = 0, nc = emcalo.size(); ic < nc; ++ic) { + auto &calo = emcalo[ic]; + + std::vector candidates; + + for (unsigned int itk = 0; itk < nTrackMax; ++itk) { + const auto &tk = track[itk]; + if (tk.floatPt() <= cfg.trkQualityPtMin) + continue; + + float d_phi = deltaPhi(tk.floatPhi(), calo.floatPhi()); + float d_eta = tk.floatEta() - calo.floatEta(); // We only use it squared + float dR2 = (d_phi * d_phi) + (d_eta * d_eta); + + if (dR2 < 0.04) { + // Only store indices, dR and dpT for now. The other quantities are computed only for the best nCandPerCluster. + CompositeCandidate cand; + cand.cluster_idx = ic; + cand.track_idx = itk; + cand.dpt = std::abs(tk.floatPt() - calo.floatPt()); + candidates.push_back(cand); + } + } + // FIXME: find best sort criteria, for now we use dpt + std::sort(candidates.begin(), + candidates.end(), + [](const CompositeCandidate &a, const CompositeCandidate &b) -> bool { return a.dpt < b.dpt; }); + unsigned int nCandPerCluster = std::min(candidates.size(), cfg.nCompCandPerCluster); + if (nCandPerCluster == 0) + continue; + + float maxScore = -999; + int ibest = -1; + for (unsigned int icand = 0; icand < nCandPerCluster; icand++) { + auto &cand = candidates[icand]; + const std::vector &emcalo_sel = emcalo; + float score = compute_composite_score(cand, emcalo_sel, track, cfg.compIDparams); + if ((score > cfg.compIDparams.bdtScore_loose_wp) && (score > maxScore)) { + maxScore = score; + ibest = icand; + } + } + if (ibest != -1) { + emCalo2tk[ic] = candidates[ibest].track_idx; + emCaloTkBdtScore[ic] = maxScore; + } + } +} + +float PFTkEGAlgoEmulator::compute_composite_score(CompositeCandidate &cand, + const std::vector &emcalo, + const std::vector &track, + const PFTkEGAlgoEmuConfig::CompIDParameters ¶ms) const { + // Get the cluster/track objects that form the composite candidate + const auto &calo = emcalo[cand.cluster_idx]; + const auto &tk = track[cand.track_idx]; + + // Prepare the input features + bdt_feature_t hoe = calo.hwHoe; + bdt_feature_t tkpt = tk.hwPt; + bdt_feature_t srrtot = calo.hwSrrTot; + bdt_feature_t deta = tk.hwEta - calo.hwEta; + ap_ufixed<18, 0> calo_invPt = l1ct::invert_with_shift, 1024>(calo.hwPt); + bdt_feature_t dpt = tk.hwPt * calo_invPt; + bdt_feature_t meanz = calo.hwMeanZ; + bdt_feature_t dphi = tk.hwPhi - calo.hwPhi; + bdt_feature_t nstubs = tk.hwStubs; + bdt_feature_t chi2rphi = tk.hwRedChi2RPhi; + bdt_feature_t chi2rz = tk.hwRedChi2RZ; + bdt_feature_t chi2bend = tk.hwRedChi2Bend; + + // Run BDT inference + std::vector inputs = {tkpt, hoe, srrtot, deta, dphi, dpt, meanz, nstubs, chi2rphi, chi2rz, chi2bend}; + std::vector bdt_score = composite_bdt_->decision_function(inputs); + + return bdt_score[0]; +} + void PFTkEGAlgoEmulator::sel_emCalo(unsigned int nmax_sel, const std::vector &emcalo, std::vector &emcalo_sel) const { @@ -171,7 +276,6 @@ void PFTkEGAlgoEmulator::run(const PFInputRegion &in, OutputRegion &out) const { << std::endl; } } - // FIXME: can be removed in the endcap since now running with the "interceptor". // Might still be needed in barrel // filter and select first N elements of input clusters @@ -183,12 +287,18 @@ void PFTkEGAlgoEmulator::run(const PFInputRegion &in, OutputRegion &out) const { link_emCalo2emCalo(emcalo_sel, emCalo2emCalo); std::vector emCalo2tk(emcalo_sel.size(), -1); - link_emCalo2tk(in.region, emcalo_sel, in.track, emCalo2tk); + std::vector emCaloTkBdtScore(emcalo_sel.size(), -999); + + if (cfg.doCompositeTkEle) { + link_emCalo2tk_composite(in.region, emcalo_sel, in.track, emCalo2tk, emCaloTkBdtScore); + } else { + link_emCalo2tk_elliptic(in.region, emcalo_sel, in.track, emCalo2tk); + } out.egsta.clear(); std::vector egobjs; std::vector egeleobjs; - eg_algo(in.region, emcalo_sel, in.track, emCalo2emCalo, emCalo2tk, out.egsta, egobjs, egeleobjs); + eg_algo(in.region, emcalo_sel, in.track, emCalo2emCalo, emCalo2tk, emCaloTkBdtScore, out.egsta, egobjs, egeleobjs); unsigned int nEGOut = std::min(cfg.nEM_EGOUT, egobjs.size()); unsigned int nEGEleOut = std::min(cfg.nEM_EGOUT, egeleobjs.size()); @@ -205,6 +315,7 @@ void PFTkEGAlgoEmulator::eg_algo(const PFRegionEmu ®ion, const std::vector &track, const std::vector &emCalo2emCalo, const std::vector &emCalo2tk, + const std::vector &emCaloTkBdtScore, std::vector &egstas, std::vector &egobjs, std::vector &egeleobjs) const { @@ -220,6 +331,7 @@ void PFTkEGAlgoEmulator::eg_algo(const PFRegionEmu ®ion, << " phi " << calo.hwPhi << std::endl; int itk = emCalo2tk[ic]; + float bdt = emCaloTkBdtScore[ic]; // check if brem recovery is on if (!cfg.doBremRecovery || cfg.writeBeforeBremRecovery) { @@ -232,7 +344,7 @@ void PFTkEGAlgoEmulator::eg_algo(const PFRegionEmu ®ion, egQual = calo.hwEmID | 0x8; } - addEgObjsToPF(egstas, egobjs, egeleobjs, emcalo, track, ic, egQual, calo.hwPt, itk); + addEgObjsToPF(egstas, egobjs, egeleobjs, emcalo, track, ic, egQual, calo.hwPt, itk, bdt); } if (!cfg.doBremRecovery) @@ -255,7 +367,7 @@ void PFTkEGAlgoEmulator::eg_algo(const PFRegionEmu ®ion, // 2. create EG objects with brem recovery // NOTE: duplicating the object is suboptimal but this is done for keeping things as in TDR code... - addEgObjsToPF(egstas, egobjs, egeleobjs, emcalo, track, ic, calo.hwEmID, ptBremReco, itk, components); + addEgObjsToPF(egstas, egobjs, egeleobjs, emcalo, track, ic, calo.hwEmID, ptBremReco, itk, bdt, components); } } @@ -309,7 +421,8 @@ EGIsoEleObjEmu &PFTkEGAlgoEmulator::addEGIsoEleToPF(std::vector const EmCaloObjEmu &calo, const TkObjEmu &track, const unsigned int hwQual, - const pt_t ptCorr) const { + const pt_t ptCorr, + const float bdtScore) const { EGIsoEleObjEmu egiso; egiso.clear(); egiso.hwPt = ptCorr; @@ -317,9 +430,14 @@ EGIsoEleObjEmu &PFTkEGAlgoEmulator::addEGIsoEleToPF(std::vector egiso.hwPhi = calo.hwPhi; unsigned int egHwQual = hwQual; if (cfg.doEndcapHwQual) { - // 1. zero-suppress the loose EG-ID (bit 1) - // 2. for now use the standalone tight definition (bit 0) to set the tight point for eles (bit 1) - egHwQual = (hwQual & 0x9) | ((hwQual & 0x1) << 1); + if (cfg.doCompositeTkEle) { + // tight ele WP is set for tight BDT score + egHwQual = (hwQual & 0x9) | ((bdtScore >= cfg.compIDparams.bdtScore_tight_wp) << 1); + } else { + // 1. zero-suppress the loose EG-ID (bit 1) + // 2. for now use the standalone tight definition (bit 0) to set the tight point for eles (bit 1) + egHwQual = (hwQual & 0x9) | ((hwQual & 0x1) << 1); + } } egiso.hwQual = egHwQual; egiso.hwDEta = track.hwVtxEta() - egiso.hwEta; @@ -328,6 +446,7 @@ EGIsoEleObjEmu &PFTkEGAlgoEmulator::addEGIsoEleToPF(std::vector egiso.hwCharge = track.hwCharge; egiso.srcCluster = calo.src; egiso.srcTrack = track.src; + egiso.idScore = bdtScore; egobjs.push_back(egiso); if (debug_ > 2) @@ -346,6 +465,7 @@ void PFTkEGAlgoEmulator::addEgObjsToPF(std::vector &egstas, const unsigned int hwQual, const pt_t ptCorr, const int tk_idx, + const float bdtScore, const std::vector &components) const { int sta_idx = -1; if (writeEgSta()) { @@ -355,7 +475,7 @@ void PFTkEGAlgoEmulator::addEgObjsToPF(std::vector &egstas, EGIsoObjEmu &egobj = addEGIsoToPF(egobjs, emcalo[calo_idx], hwQual, ptCorr); egobj.sta_idx = sta_idx; if (tk_idx != -1) { - EGIsoEleObjEmu &eleobj = addEGIsoEleToPF(egeleobjs, emcalo[calo_idx], track[tk_idx], hwQual, ptCorr); + EGIsoEleObjEmu &eleobj = addEGIsoEleToPF(egeleobjs, emcalo[calo_idx], track[tk_idx], hwQual, ptCorr, bdtScore); eleobj.sta_idx = sta_idx; } } diff --git a/L1Trigger/Phase2L1ParticleFlow/src/l1-converters/hgcalinputt_ref.cpp b/L1Trigger/Phase2L1ParticleFlow/src/l1-converters/hgcalinputt_ref.cpp index d1777586ca753..4851eccc06b71 100644 --- a/L1Trigger/Phase2L1ParticleFlow/src/l1-converters/hgcalinputt_ref.cpp +++ b/L1Trigger/Phase2L1ParticleFlow/src/l1-converters/hgcalinputt_ref.cpp @@ -8,6 +8,10 @@ l1ct::HadCaloObjEmu l1ct::HgcalClusterDecoderEmulator::decode(const ap_uint<256> ap_int<9> w_eta = in(72, 64); ap_int<9> w_phi = in(81, 73); ap_uint<10> w_qual = in(115, 106); + ap_uint<13> w_srrtot = in(213, 201); + ap_uint<12> w_meanz = in(94, 83); + // FIXME: we use a spare space in the word for hoe which is not in the current interface + ap_uint<12> w_hoe = in(127, 116); l1ct::HadCaloObjEmu out; out.clear(); @@ -17,5 +21,9 @@ l1ct::HadCaloObjEmu l1ct::HgcalClusterDecoderEmulator::decode(const ap_uint<256> out.hwEmPt = w_empt * l1ct::pt_t(l1ct::Scales::INTPT_LSB); out.hwEmID = w_qual; + out.hwSrrTot = w_srrtot * l1ct::srrtot_t(l1ct::Scales::SRRTOT_LSB); + out.hwMeanZ = (w_meanz == 0) ? l1ct::meanz_t(0) : l1ct::meanz_t(w_meanz - l1ct::meanz_t(l1ct::Scales::MEANZ_OFFSET)); + out.hwHoe = w_hoe * l1ct::hoe_t(l1ct::Scales::HOE_LSB); + return out; } diff --git a/L1Trigger/Phase2L1ParticleFlow/src/l1-converters/tkinput_ref.cpp b/L1Trigger/Phase2L1ParticleFlow/src/l1-converters/tkinput_ref.cpp index 4f707e49cc3cc..ca61b38eb3eb6 100644 --- a/L1Trigger/Phase2L1ParticleFlow/src/l1-converters/tkinput_ref.cpp +++ b/L1Trigger/Phase2L1ParticleFlow/src/l1-converters/tkinput_ref.cpp @@ -37,7 +37,8 @@ namespace { l1ct::TrackInputEmulator::TrackInputEmulator(const edm::ParameterSet &iConfig) : TrackInputEmulator(parseRegion(iConfig.getParameter("region")), parseEncoding(iConfig.getParameter("trackWordEncoding")), - iConfig.getParameter("bitwiseAccurate")) { + iConfig.getParameter("bitwiseAccurate"), + iConfig.getParameter("slimDataFormat")) { if (region_ != Region::Endcap && region_ != Region::Barrel) { edm::LogError("TrackInputEmulator") << "region '" << iConfig.getParameter("region") << "' is not yet supported"; @@ -81,10 +82,11 @@ l1ct::TrackInputEmulator::TrackInputEmulator(const edm::ParameterSet &iConfig) #endif -l1ct::TrackInputEmulator::TrackInputEmulator(Region region, Encoding encoding, bool bitwise) +l1ct::TrackInputEmulator::TrackInputEmulator(Region region, Encoding encoding, bool bitwise, bool slim) : region_(region), encoding_(encoding), bitwise_(bitwise), + slim_(slim), rInvToPt_(31199.5), phiScale_(0.00038349520), z0Scale_(0.00999469), @@ -100,7 +102,8 @@ l1ct::TrackInputEmulator::TrackInputEmulator(Region region, Encoding encoding, b std::pair l1ct::TrackInputEmulator::decodeTrack(ap_uint<96> tkword, const l1ct::PFRegionEmu §or, - bool bitwise) const { + bool bitwise, + bool slim) const { l1ct::TkObjEmu ret; ret.clear(); auto z0 = signedZ0(tkword); @@ -162,7 +165,6 @@ std::pair l1ct::TrackInputEmulator::decodeTrack(ap_uint<96 fDEta = floatDEtaHGCal(z0, Rinv, tanl); fDPhi = floatDPhiHGCal(z0, Rinv, tanl); } - ret.hwDPhi = std::round(fDPhi); ret.hwDEta = std::round(fDEta); ret.hwPhi = std::round(fvtxPhi - fDPhi * ret.intCharge()); @@ -171,6 +173,14 @@ std::pair l1ct::TrackInputEmulator::decodeTrack(ap_uint<96 ret.hwZ0 = l1ct::Scales::makeZ0(floatZ0(z0)); } + if (!slim) { + ap_uint<7> w_hitPattern = tkword(15, 9); + ret.hwStubs = countSetBits(w_hitPattern); + ret.hwRedChi2RZ = tkword(35, 32); + ret.hwRedChi2RPhi = tkword(67, 64); + ret.hwRedChi2Bend = tkword(18, 16); + } + oksel = ret.hwQuality != 0; } return std::make_pair(ret, oksel);