diff --git a/.gitignore b/.gitignore index 89543e26bf3d1..20e86694c3ab4 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,6 @@ __init__.py # ignore files under the top level $CMSSW_BASE/src directory, but not its subdirectories /* !/*/ + + +L1Trigger/L1THGCalUtilities/test/HGCS2*.txt diff --git a/DataFormats/L1THGCal/BuildFile.xml b/DataFormats/L1THGCal/BuildFile.xml index aaba3b9a72339..a8ae4c639bf07 100644 --- a/DataFormats/L1THGCal/BuildFile.xml +++ b/DataFormats/L1THGCal/BuildFile.xml @@ -7,6 +7,7 @@ + diff --git a/DataFormats/L1THGCal/interface/HGCalClusterT.h b/DataFormats/L1THGCal/interface/HGCalClusterT.h index cddd611ce0779..d27d33d7af70a 100644 --- a/DataFormats/L1THGCal/interface/HGCalClusterT.h +++ b/DataFormats/L1THGCal/interface/HGCalClusterT.h @@ -179,6 +179,69 @@ namespace l1t { void triggerCells67percent(float triggerCells67percent) { triggerCells67percent_ = triggerCells67percent; } void triggerCells90percent(float triggerCells90percent) { triggerCells90percent_ = triggerCells90percent; } + // Firmware-specific cluster properties + unsigned long int hw_sigma_e_quotient() const { return hw_sigma_e_quotient_; } + unsigned long int hw_sigma_e_fraction() const { return hw_sigma_e_fraction_; } + unsigned long int hw_mean_z_quotient() const { return hw_mean_z_quotient_; } + unsigned long int hw_mean_z_fraction() const { return hw_mean_z_fraction_; } + unsigned long int hw_mean_phi_quotient() const { return hw_mean_phi_quotient_; } + unsigned long int hw_mean_phi_fraction() const { return hw_mean_phi_fraction_; } + unsigned long int hw_mean_eta_quotient() const { return hw_mean_eta_quotient_; } + unsigned long int hw_mean_eta_fraction() const { return hw_mean_eta_fraction_; } + unsigned long int hw_mean_roz_quotient() const { return hw_mean_roz_quotient_; } + unsigned long int hw_mean_roz_fraction() const { return hw_mean_roz_fraction_; } + unsigned long int hw_sigma_z_quotient() const { return hw_sigma_z_quotient_; } + unsigned long int hw_sigma_z_fraction() const { return hw_sigma_z_fraction_; } + unsigned long int hw_sigma_phi_quotient() const { return hw_sigma_phi_quotient_; } + unsigned long int hw_sigma_phi_fraction() const { return hw_sigma_phi_fraction_; } + unsigned long int hw_sigma_eta_quotient() const { return hw_sigma_eta_quotient_; } + unsigned long int hw_sigma_eta_fraction() const { return hw_sigma_eta_fraction_; } + unsigned long int hw_sigma_roz_quotient() const { return hw_sigma_roz_quotient_; } + unsigned long int hw_sigma_roz_fraction() const { return hw_sigma_roz_fraction_; } + unsigned long int hw_e_em_over_e_quotient() const { return hw_e_em_over_e_quotient_; } + unsigned long int hw_e_em_over_e_fraction() const { return hw_e_em_over_e_fraction_; } + unsigned long int hw_e_em_core_over_e_em_quotient() const { return hw_e_em_core_over_e_em_quotient_; } + unsigned long int hw_e_em_core_over_e_em_fraction() const { return hw_e_em_core_over_e_em_fraction_; } + unsigned long int hw_e_h_early_over_e_quotient() const { return hw_e_h_early_over_e_quotient_; } + unsigned long int hw_e_h_early_over_e_fraction() const { return hw_e_h_early_over_e_fraction_; } + + void hw_sigma_e_quotient(unsigned long int sigma_e_quotient) { hw_sigma_e_quotient_ = sigma_e_quotient; } + void hw_sigma_e_fraction(unsigned long int sigma_e_fraction) { hw_sigma_e_fraction_ = sigma_e_fraction; } + void hw_mean_z_quotient(unsigned long int mean_z_quotient) { hw_mean_z_quotient_ = mean_z_quotient; } + void hw_mean_z_fraction(unsigned long int mean_z_fraction) { hw_mean_z_fraction_ = mean_z_fraction; } + void hw_mean_phi_quotient(unsigned long int mean_phi_quotient) { hw_mean_phi_quotient_ = mean_phi_quotient; } + void hw_mean_phi_fraction(unsigned long int mean_phi_fraction) { hw_mean_phi_fraction_ = mean_phi_fraction; } + void hw_mean_eta_quotient(unsigned long int mean_eta_quotient) { hw_mean_eta_quotient_ = mean_eta_quotient; } + void hw_mean_eta_fraction(unsigned long int mean_eta_fraction) { hw_mean_eta_fraction_ = mean_eta_fraction; } + void hw_mean_roz_quotient(unsigned long int mean_roz_quotient) { hw_mean_roz_quotient_ = mean_roz_quotient; } + void hw_mean_roz_fraction(unsigned long int mean_roz_fraction) { hw_mean_roz_fraction_ = mean_roz_fraction; } + void hw_sigma_z_quotient(unsigned long int sigma_z_quotient) { hw_sigma_z_quotient_ = sigma_z_quotient; } + void hw_sigma_z_fraction(unsigned long int sigma_z_fraction) { hw_sigma_z_fraction_ = sigma_z_fraction; } + void hw_sigma_phi_quotient(unsigned long int sigma_phi_quotient) { hw_sigma_phi_quotient_ = sigma_phi_quotient; } + void hw_sigma_phi_fraction(unsigned long int sigma_phi_fraction) { hw_sigma_phi_fraction_ = sigma_phi_fraction; } + void hw_sigma_eta_quotient(unsigned long int sigma_eta_quotient) { hw_sigma_eta_quotient_ = sigma_eta_quotient; } + void hw_sigma_eta_fraction(unsigned long int sigma_eta_fraction) { hw_sigma_eta_fraction_ = sigma_eta_fraction; } + void hw_sigma_roz_quotient(unsigned long int sigma_roz_quotient) { hw_sigma_roz_quotient_ = sigma_roz_quotient; } + void hw_sigma_roz_fraction(unsigned long int sigma_roz_fraction) { hw_sigma_roz_fraction_ = sigma_roz_fraction; } + void hw_e_em_over_e_quotient(unsigned long int e_em_over_e_quotient) { + hw_e_em_over_e_quotient_ = e_em_over_e_quotient; + } + void hw_e_em_over_e_fraction(unsigned long int e_em_over_e_fraction) { + hw_e_em_over_e_fraction_ = e_em_over_e_fraction; + } + void hw_e_em_core_over_e_em_quotient(unsigned long int e_em_core_over_e_em_quotient) { + hw_e_em_core_over_e_em_quotient_ = e_em_core_over_e_em_quotient; + } + void hw_e_em_core_over_e_em_fraction(unsigned long int e_em_core_over_e_em_fraction) { + hw_e_em_core_over_e_em_fraction_ = e_em_core_over_e_em_fraction; + } + void hw_e_h_early_over_e_quotient(unsigned long int e_h_early_over_e_quotient) { + hw_e_h_early_over_e_quotient_ = e_h_early_over_e_quotient; + } + void hw_e_h_early_over_e_fraction(unsigned long int e_h_early_over_e_fraction) { + hw_e_h_early_over_e_fraction_ = e_h_early_over_e_fraction; + } + /* operators */ bool operator<(const HGCalClusterT& cl) const { return mipPt() < cl.mipPt(); } bool operator>(const HGCalClusterT& cl) const { return cl < *this; } @@ -221,6 +284,32 @@ namespace l1t { float triggerCells67percent_ = 0.; float triggerCells90percent_ = 0.; + // firmware-specific cluster properties + unsigned long int hw_sigma_e_quotient_ = 0; + unsigned long int hw_sigma_e_fraction_ = 0; + unsigned long int hw_mean_z_quotient_ = 0; + unsigned long int hw_mean_z_fraction_ = 0; + unsigned long int hw_mean_phi_quotient_ = 0; + unsigned long int hw_mean_phi_fraction_ = 0; + unsigned long int hw_mean_eta_quotient_ = 0; + unsigned long int hw_mean_eta_fraction_ = 0; + unsigned long int hw_mean_roz_quotient_ = 0; + unsigned long int hw_mean_roz_fraction_ = 0; + unsigned long int hw_sigma_z_quotient_ = 0; + unsigned long int hw_sigma_z_fraction_ = 0; + unsigned long int hw_sigma_phi_quotient_ = 0; + unsigned long int hw_sigma_phi_fraction_ = 0; + unsigned long int hw_sigma_eta_quotient_ = 0; + unsigned long int hw_sigma_eta_fraction_ = 0; + unsigned long int hw_sigma_roz_quotient_ = 0; + unsigned long int hw_sigma_roz_fraction_ = 0; + unsigned long int hw_e_em_over_e_quotient_ = 0; + unsigned long int hw_e_em_over_e_fraction_ = 0; + unsigned long int hw_e_em_core_over_e_em_quotient_ = 0; + unsigned long int hw_e_em_core_over_e_em_fraction_ = 0; + unsigned long int hw_e_h_early_over_e_quotient_ = 0; + unsigned long int hw_e_h_early_over_e_fraction_ = 0; + void updateP4AndPosition(const edm::Ptr& c, bool updateCentre = true, float fraction = 1.) { double cMipt = c->mipPt() * fraction; double cPt = c->pt() * fraction; diff --git a/DataFormats/L1THGCal/interface/HGCalCluster_HW.h b/DataFormats/L1THGCal/interface/HGCalCluster_HW.h new file mode 100644 index 0000000000000..aca57583b4f81 --- /dev/null +++ b/DataFormats/L1THGCal/interface/HGCalCluster_HW.h @@ -0,0 +1,294 @@ +#ifndef DataFormats_L1THGCal_HGCalCluster_HW_h +#define DataFormats_L1THGCal_HGCalCluster_HW_h + +#include "DataFormats/L1TParticleFlow/interface/bit_encoding.h" + +#include +// #include + +namespace l1thgcfirmware { + + typedef ap_uint<14> e_t; // E, E_EM + typedef ap_uint<4> gctbits_t; + typedef ap_uint<8> eFraction_t; + typedef ap_uint<6> nLayer_t; + + typedef ap_uint<10> eta_t; + typedef ap_int<9> phi_t; + typedef ap_uint<12> z_t; + typedef ap_uint<1> spare_w2_t; + typedef ap_uint<10> nTC_t; + typedef ap_uint<7> qualFlags_t; + + typedef ap_uint<7> sigma_E_t; + typedef ap_uint<13> spare_w3_t; + typedef ap_uint<7> sigma_z_t; + typedef ap_uint<7> sigma_phi_t; + typedef ap_uint<5> sigma_eta_t; + typedef ap_uint<7> sigma_roz_t; + + static constexpr int wordLength = 64; + static constexpr int nWordsPerCluster = 4; + typedef uint64_t ClusterWord; + typedef std::array ClusterWords; + + namespace Scales { + constexpr float ET_LSB = 1./1024; + constexpr float ET_HGCALtoL1_SCALE = 1. / 256; + constexpr float ET_L1_LSB = 0.25; + + constexpr int INTPHI_PI = 720; + constexpr float ETAPHI_LSB = M_PI / INTPHI_PI; + constexpr float Z_LSB = 0.05; + constexpr float SIGMA_ROZ_ROZ_LSB = 0.0001920625; // 0.024584/2^(7), max r/z / nBits + + inline float floatEt(e_t et) { return et.to_float() * ET_L1_LSB; } + inline float floatEta(eta_t eta) { return eta.to_float() * ETAPHI_LSB; } + inline float floatPhi(phi_t phi) { return phi.to_float() * ETAPHI_LSB + M_PI/2; } + inline float floatZ(z_t z) { return z.to_float() * Z_LSB; } + inline float floatSigmaRozRoz(sigma_roz_t sigmaRozRoz) { return sigmaRozRoz.to_float() * SIGMA_ROZ_ROZ_LSB; } + + inline e_t HGCaltoL1_et(double et) { + return round(et * Scales::ET_HGCALtoL1_SCALE); + } + + inline z_t HGCaltoL1_z(double z) { + return round(z); // Same scale on both sides of interface + } + + inline phi_t HGCaltoL1_phi(float phi, bool& saturatedPhi, bool& nominalPhi) { + phi_t hw_phi = 0; + + // Temporary fix. First line is what we should use, assuming phi LSB of pi/3456 + // But steps before CP block don't like this, and put TCs in the wrong bins - to be debugged + // So for now, where earlier steps are used to produce input for testing CP block in hardware, + // use original LSB (pi/1944) for earlier steps, and convert to CP-block LSB here + // const int hw_phi10b = int( round( phi * (5./24) ) ) - 360; + const int hw_phi10b = int( round( phi * (3456./1944) * (5./24) ) ) - 360; + nominalPhi = ( hw_phi10b < 240 ) && ( hw_phi10b > -241 ); + if( hw_phi10b > 255 ) { + hw_phi = 255; + saturatedPhi = true; + } + else if ( hw_phi10b < -256 ) { + hw_phi = -256; + saturatedPhi = true; + } + else { + hw_phi = hw_phi10b; + saturatedPhi = false; + } + return hw_phi; + } + + inline eFraction_t makeL1EFraction(float num, float denom) { + float frac = round(256 * num / denom); + if ( frac >= 256. ) frac = 255.; + return frac; + }; + + + } + + + struct HGCalCluster_HW { + + // First word + e_t e; + e_t e_em; + gctbits_t gctBits; + eFraction_t fractionInCE_E; + eFraction_t fractionInCoreCE_E; + eFraction_t fractionInEarlyCE_E; + nLayer_t firstLayer; + + // Second word + eta_t w_eta; + phi_t w_phi; + z_t w_z; + spare_w2_t spare_w2 = 0; + nTC_t nTC; + qualFlags_t qualFlags; + + // Third word + sigma_E_t sigma_E; + nLayer_t lastLayer; + nLayer_t showerLength; + spare_w3_t spare_w3 = 0; + sigma_z_t sigma_z; + sigma_phi_t sigma_phi; + nLayer_t coreShowerLength; + sigma_eta_t sigma_eta; + sigma_roz_t sigma_roz; + + inline bool operator==(const HGCalCluster_HW &other) const { + return e == other.e && e_em == other.e_em && w_eta == other.w_eta && w_phi == other.w_phi && w_z == other.w_z && sigma_roz == other.sigma_roz && fractionInCE_E == other.fractionInCE_E; + } + + inline bool operator!=(const HGCalCluster_HW &other) const { + return !(*this == other); + } + + inline void clear() { + e = 0; + e_em = 0; + gctBits = 0; + fractionInCE_E = 0; + fractionInCoreCE_E = 0; + fractionInEarlyCE_E = 0; + firstLayer = 0; + w_eta = 0; + w_phi = 0; + w_z = 0; + nTC = 0; + qualFlags = 0; + sigma_E = 0; + lastLayer = 0; + showerLength = 0; + spare_w3 = 0; + sigma_z = 0; + sigma_phi = 0; + coreShowerLength = 0; + sigma_eta = 0; + sigma_roz = 0; + } + + // float floatE() const { return Scales::floatE(e); } + // float floatE_EM() const { return Scales::floatE(e_em); } + // float floatFraction() const { return Scales::floatEta(hwEta); } + + static const int BITWIDTH_FIRSTWORD = e_t::width + e_t::width + gctbits_t::width + eFraction_t::width + eFraction_t::width + eFraction_t::width + nLayer_t::width; + inline ap_uint pack_firstWord() const { + ap_uint ret; + unsigned int start = 0; + pack_into_bits(ret, start, e); + pack_into_bits(ret, start, e_em); + pack_into_bits(ret, start, gctBits); + pack_into_bits(ret, start, fractionInCE_E); + pack_into_bits(ret, start, fractionInCoreCE_E); + pack_into_bits(ret, start, fractionInEarlyCE_E); + pack_into_bits(ret, start, firstLayer); + return ret; + } + + static const int BITWIDTH_SECONDWORD = eta_t::width + phi_t::width + z_t::width + spare_w2_t::width + nTC_t::width + qualFlags_t::width; + inline ap_uint pack_secondWord() const { + ap_uint ret; + unsigned int start = 0; + pack_into_bits(ret, start, w_eta); + pack_into_bits(ret, start, w_phi); + pack_into_bits(ret, start, w_z); + pack_into_bits(ret, start, spare_w2); + pack_into_bits(ret, start, nTC); + pack_into_bits(ret, start, qualFlags); + return ret; + } + + static const int BITWIDTH_THIRDWORD = sigma_E_t::width + nLayer_t::width + nLayer_t::width + spare_w3_t::width + sigma_z_t::width + sigma_phi_t::width + nLayer_t::width + sigma_eta_t::width + sigma_roz_t::width; + inline ap_uint pack_thirdWord() const { + ap_uint ret; + unsigned int start = 0; + pack_into_bits(ret, start, sigma_E); + pack_into_bits(ret, start, lastLayer); + pack_into_bits(ret, start, showerLength); + pack_into_bits(ret, start, spare_w3); + pack_into_bits(ret, start, sigma_z); + pack_into_bits(ret, start, sigma_phi); + pack_into_bits(ret, start, coreShowerLength); + pack_into_bits(ret, start, sigma_eta); + pack_into_bits(ret, start, sigma_roz); + return ret; + } + + inline ClusterWords pack() const { + ClusterWords packed; + ap_uint firstWord = this->pack_firstWord(); + ap_uint secondWord = this->pack_secondWord(); + ap_uint thirdWord = this->pack_thirdWord(); + packed[0] = firstWord; + packed[1] = secondWord; + packed[2] = thirdWord; + packed[3] = 0; + return packed; + } + + inline static void unpack_firstWord(const ap_uint &src, HGCalCluster_HW& cluster) { + cluster.initFromBits_firstWord(src); + return; + } + + inline void initFromBits_firstWord(const ap_uint &src ) { + unsigned int start = 0; + unpack_from_bits(src, start, e); + unpack_from_bits(src, start, e_em); + unpack_from_bits(src, start, gctBits); + unpack_from_bits(src, start, fractionInCE_E); + unpack_from_bits(src, start, fractionInCoreCE_E); + unpack_from_bits(src, start, fractionInEarlyCE_E); + unpack_from_bits(src, start, firstLayer); + } + + inline static void unpack_secondWord(const ap_uint &src, HGCalCluster_HW& cluster) { + cluster.initFromBits_secondWord(src); + return; + } + + inline void initFromBits_secondWord(const ap_uint &src ) { + unsigned int start = 0; + unpack_from_bits(src, start, w_eta); + unpack_from_bits(src, start, w_phi); + unpack_from_bits(src, start, w_z); + unpack_from_bits(src, start, spare_w2); + unpack_from_bits(src, start, nTC); + unpack_from_bits(src, start, qualFlags); + + } + + inline static void unpack_thirdWord(const ap_uint &src, HGCalCluster_HW& cluster) { + cluster.initFromBits_thirdWord(src); + return; + } + + inline void initFromBits_thirdWord(const ap_uint &src ) { + unsigned int start = 0; + unpack_from_bits(src, start, sigma_E); + unpack_from_bits(src, start, lastLayer); + unpack_from_bits(src, start, showerLength); + unpack_from_bits(src, start, spare_w3); + unpack_from_bits(src, start, sigma_z); + unpack_from_bits(src, start, sigma_phi); + unpack_from_bits(src, start, coreShowerLength); + unpack_from_bits(src, start, sigma_eta); + unpack_from_bits(src, start, sigma_roz); + } + + + inline static HGCalCluster_HW unpack(const ClusterWords &src) { + HGCalCluster_HW cluster; + ap_uint firstWord = src[0]; + unpack_firstWord( firstWord, cluster ); + ap_uint secondWord = src[1]; + unpack_secondWord( secondWord, cluster ); + ap_uint thirdWord = src[2]; + unpack_thirdWord( thirdWord, cluster ); + return cluster; + } + + inline void setGCTBits() { + ap_uint<1> gctBit0 = fractionInCE_E > 64; + ap_uint<1> gctBit1 = fractionInCoreCE_E > 64; + ap_uint<1> gctBit2 = fractionInEarlyCE_E > 64; + ap_uint<1> gctBit3 = e_em > 64; + gctBits = (gctBit3, gctBit2, gctBit1, gctBit0); + } + + inline void setQualityFlags( bool qualFracCE_E, bool qualFracCoreCE_E, bool qualFracEarlyCE_H, bool saturatedTC, unsigned int shapeQuality, bool saturatedPhi, bool nominalPhi ) { + qualFlags = (ap_uint<1>(saturatedTC), ap_uint<1>(qualFracCE_E), ap_uint<1>(qualFracCoreCE_E), ap_uint<1>(qualFracEarlyCE_H), ap_uint<1>(shapeQuality), ap_uint<1>(saturatedPhi), ap_uint<1>(nominalPhi)); + } + }; + + inline void clear(HGCalCluster_HW &c) { c.clear(); } + +} // namespace l1thgcfirmware + +#endif \ No newline at end of file diff --git a/DataFormats/L1THGCal/interface/HGCalMulticluster.h b/DataFormats/L1THGCal/interface/HGCalMulticluster.h index 3df4591998e7f..398c04912e8ae 100644 --- a/DataFormats/L1THGCal/interface/HGCalMulticluster.h +++ b/DataFormats/L1THGCal/interface/HGCalMulticluster.h @@ -7,6 +7,7 @@ #include "DataFormats/L1THGCal/interface/HGCalCluster.h" #include #include +#include namespace l1t { @@ -33,7 +34,7 @@ namespace l1t { hOverEValid_ = true; } - enum EnergyInterpretation { EM = 0 }; + enum EnergyInterpretation { EM = 0, EM_CORE = 1, H_EARLY = 2 }; void saveEnergyInterpretation(const HGCalMulticluster::EnergyInterpretation eInt, double energy); @@ -90,6 +91,40 @@ namespace l1t { float hOverE_; bool hOverEValid_; std::map energyInterpretationFractions_; + + public: + // Types for firmware representation of cluster data sent to L1T + // These are duplicated with those in interface/backend_emulator/HGCalCluster_SA.h + // Can we define in one place? + static constexpr int wordLength = 64; + static constexpr int nWordsPerCluster = 4; + typedef uint64_t ClusterWord; + typedef std::array ClusterWords; + void setHwData( ClusterWords clusterWords ) { hwData_ = clusterWords; } + ClusterWords getHwData() const { return hwData_; } + void setHwSector( unsigned int sector ) { hwSector_ = sector; } + unsigned int getHwSector() const { return hwSector_; } + void setHwZSide( int zside ) { hwZSide_ = zside; } + int getHwZSide() const { return hwZSide_; } + + // Types for firmware representation of cluster sum data, input to cluster properties step + static constexpr int clusterSumWordLength = 64; + static constexpr int nWordsPerClusterSum = 8; + typedef uint64_t ClusterSumWord; + typedef std::array ClusterSumWords; + void setHwClusterSumData( ClusterSumWords clusterSumWords ) { hwClusterSumData_ = clusterSumWords; } + ClusterSumWords getHwClusterSumData() const { return hwClusterSumData_; } + + private: + ClusterWords hwData_; + ClusterSumWords hwClusterSumData_; + // Store sector number for pattern files + // TODO check if detID of emulated cluster always gives same sector + // Emulated cluster takes detID of first TC added to it, which is not necessarily a TC in the seed histo bin + unsigned int hwSector_; + // Safe to take zside from the detID of the emualted cluster + // But keep consistent with sector for now + int hwZSide_; }; typedef BXVector HGCalMulticlusterBxCollection; diff --git a/DataFormats/L1THGCal/src/classes_def.xml b/DataFormats/L1THGCal/src/classes_def.xml index 0cf6b02cad815..fa1c655b93cf7 100644 --- a/DataFormats/L1THGCal/src/classes_def.xml +++ b/DataFormats/L1THGCal/src/classes_def.xml @@ -30,7 +30,8 @@ - + + @@ -47,7 +48,10 @@ - + + + + diff --git a/DataFormats/L1TParticleFlow/interface/datatypes.h b/DataFormats/L1TParticleFlow/interface/datatypes.h index be802bc540b6e..2d791fcd7b362 100644 --- a/DataFormats/L1TParticleFlow/interface/datatypes.h +++ b/DataFormats/L1TParticleFlow/interface/datatypes.h @@ -41,9 +41,10 @@ namespace l1ct { 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_uint<9> meanz_t; // from front face, in 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) // 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; @@ -155,7 +156,7 @@ 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 MEANZ_LSB = 0.4; 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) @@ -163,8 +164,8 @@ namespace l1ct { 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) { return (ap_ufixed<16, 14>(pt) << 2).to_int(); } - inline int intPt(dpt_t pt) { return (ap_fixed<18, 16>(pt) << 2).to_int(); } + inline int intPt(pt_t pt) { return ap_uint(pt.range()).to_int(); } + inline int intPt(dpt_t pt) { return ap_int(pt.range()).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; } @@ -176,8 +177,9 @@ namespace l1ct { 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 floatMeanZ(meanz_t meanz) { return meanz.to_float() * MEANZ_LSB; }; inline float floatHoe(hoe_t hoe) { return hoe.to_float(); }; + inline float floatIDScore(id_score_t score) { return score.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; } @@ -209,7 +211,7 @@ namespace l1ct { 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 meanz_t makeMeanZ(float var) { return round(var / MEANZ_LSB); }; 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; } diff --git a/DataFormats/L1TParticleFlow/interface/egamma.h b/DataFormats/L1TParticleFlow/interface/egamma.h index 457b1700d1021..4a61e317a6a15 100644 --- a/DataFormats/L1TParticleFlow/interface/egamma.h +++ b/DataFormats/L1TParticleFlow/interface/egamma.h @@ -87,6 +87,7 @@ namespace l1ct { z0_t hwZ0; tkdeta_t hwDEta; // relative to the region center, at calo tkdphi_t hwDPhi; // relative to the region center, at calo + id_score_t hwIDScore; bool hwCharge; phi_t hwVtxPhi() const { return hwCharge ? hwPhi + hwDPhi : hwPhi - hwDPhi; } @@ -95,7 +96,7 @@ namespace l1ct { inline bool operator==(const EGIsoEleObj &other) const { return hwPt == other.hwPt && hwEta == other.hwEta && hwPhi == other.hwPhi && hwQual == other.hwQual && hwIso == other.hwIso && hwDEta == other.hwDEta && hwDPhi == other.hwDPhi && hwZ0 == other.hwZ0 && - hwCharge == other.hwCharge; + hwIDScore == other.hwIDScore && hwCharge == other.hwCharge; } inline bool operator>(const EGIsoEleObj &other) const { return hwPt > other.hwPt; } @@ -110,6 +111,7 @@ namespace l1ct { hwDEta = 0; hwDPhi = 0; hwZ0 = 0; + hwIDScore = 0; hwCharge = false; } @@ -119,8 +121,10 @@ namespace l1ct { float floatVtxEta() const { return Scales::floatEta(hwVtxEta()); } float floatVtxPhi() const { return Scales::floatPhi(hwVtxPhi()); } float floatZ0() const { return Scales::floatZ0(hwZ0); } + float floatIDScore() const { return Scales::floatIDScore(hwIDScore); } - static const int BITWIDTH = EGIsoObj::BITWIDTH + tkdeta_t::width + tkdphi_t::width + z0_t::width + 1; + static const int BITWIDTH = + EGIsoObj::BITWIDTH + tkdeta_t::width + tkdphi_t::width + z0_t::width + id_score_t::width + 1; inline ap_uint pack() const { ap_uint ret; unsigned int start = 0; @@ -133,6 +137,7 @@ namespace l1ct { pack_into_bits(ret, start, hwDPhi); pack_into_bits(ret, start, hwZ0); pack_bool_into_bits(ret, start, hwCharge); + pack_into_bits(ret, start, hwIDScore); return ret; } inline static EGIsoEleObj unpack(const ap_uint &src) { @@ -152,6 +157,7 @@ namespace l1ct { unpack_from_bits(src, start, hwDPhi); unpack_from_bits(src, start, hwZ0); unpack_bool_from_bits(src, start, hwCharge); + unpack_from_bits(src, start, hwIDScore); } l1gt::Electron toGT() const { diff --git a/DataFormats/L1TParticleFlow/interface/layer1_emulator.h b/DataFormats/L1TParticleFlow/interface/layer1_emulator.h index fcb415d426017..f3a1b2d90cea5 100644 --- a/DataFormats/L1TParticleFlow/interface/layer1_emulator.h +++ b/DataFormats/L1TParticleFlow/interface/layer1_emulator.h @@ -195,7 +195,6 @@ namespace l1ct { const l1t::PFTrack *srcTrack; // 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,7 +202,6 @@ namespace l1ct { srcCluster = nullptr; srcTrack = nullptr; sta_idx = -1; - idScore = -999; clearIsoVars(); } @@ -335,7 +333,7 @@ namespace l1ct { }; struct Event { - enum { VERSION = 12 }; + enum { VERSION = 13 }; 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 48af69b993de1..49435b6fa7ab1 100644 --- a/DataFormats/L1TParticleFlow/interface/layer1_objs.h +++ b/DataFormats/L1TParticleFlow/interface/layer1_objs.h @@ -43,9 +43,15 @@ 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); }; + float floatSrrTot() const { return Scales::floatSrrTot(hwSrrTot); } + float floatMeanZ() const { return Scales::floatMeanZ(hwMeanZ); } + float floatHoe() const { return Scales::floatHoe(hwHoe); } + int intSrrTot() const { + // bits_to_unt64() is not defined under __SYNTHESIS__ + return ap_uint(hwSrrTot.range()).to_int(); + } + int intMeanZ() const { return hwMeanZ.to_int(); } + int intHoe() const { return ap_uint(hwHoe.range()).to_int(); } bool hwIsEM() const { return hwEmID != 0; } @@ -125,6 +131,12 @@ namespace l1ct { float floatSrrTot() const { return Scales::floatSrrTot(hwSrrTot); }; float floatMeanZ() const { return Scales::floatMeanZ(hwMeanZ); }; float floatHoe() const { return Scales::floatHoe(hwHoe); }; + int intSrrTot() const { + // bits_to_unt64() is not defined under __SYNTHESIS__ + return ap_uint(hwSrrTot.range()).to_int(); + } + int intMeanZ() const { return hwMeanZ.to_int(); } + int intHoe() const { return ap_uint(hwHoe.range()).to_int(); } static const int BITWIDTH_SLIM = pt_t::width + eta_t::width + phi_t::width + pt_t::width + emid_t::width; diff --git a/L1Trigger/Configuration/python/SimL1Emulator_cff.py b/L1Trigger/Configuration/python/SimL1Emulator_cff.py index 5dc7ba09569f6..ec40a2b4d3579 100644 --- a/L1Trigger/Configuration/python/SimL1Emulator_cff.py +++ b/L1Trigger/Configuration/python/SimL1Emulator_cff.py @@ -144,6 +144,12 @@ _phase2_siml1emulator.add( l1tTkMuonsGmt ) _phase2_siml1emulator.add( l1tSAMuonsGmt ) +## fix for low-pt muons, this collection is a copy of the l1tTkMuonsGmt collection +## in which we only keep those low pt muons with an SA muon associated to it. Threshold +## for this cutoff is configurable. +l1tTkMuonsGmtLowPtFix = l1tGMTFilteredMuons.clone() +_phase2_siml1emulator.add( l1tTkMuonsGmtLowPtFix ) + # Tracker Objects # ######################################################################## from L1Trigger.L1TTrackMatch.l1tTrackJets_cfi import * diff --git a/L1Trigger/DemonstratorTools/BuildFile.xml b/L1Trigger/DemonstratorTools/BuildFile.xml index 692d3965bb994..a0e9d37b75993 100644 --- a/L1Trigger/DemonstratorTools/BuildFile.xml +++ b/L1Trigger/DemonstratorTools/BuildFile.xml @@ -5,6 +5,7 @@ + diff --git a/L1Trigger/DemonstratorTools/interface/BoardData.h b/L1Trigger/DemonstratorTools/interface/BoardData.h index f68c8c3d83ddb..9c25462e5191e 100644 --- a/L1Trigger/DemonstratorTools/interface/BoardData.h +++ b/L1Trigger/DemonstratorTools/interface/BoardData.h @@ -22,6 +22,8 @@ namespace l1t::demo { const std::string& name() const; + void name(const std::string& aName); + std::map::const_iterator begin() const; std::map::iterator begin(); diff --git a/L1Trigger/DemonstratorTools/interface/BoardDataWriter.h b/L1Trigger/DemonstratorTools/interface/BoardDataWriter.h index 30e7cd3369df7..a3d54b0562065 100644 --- a/L1Trigger/DemonstratorTools/interface/BoardDataWriter.h +++ b/L1Trigger/DemonstratorTools/interface/BoardDataWriter.h @@ -24,6 +24,7 @@ namespace l1t::demo { BoardDataWriter(FileFormat, const std::string& filePath, + const std::string& fileExt, const size_t framesPerBX, const size_t tmux, const size_t maxFramesPerFile, @@ -31,12 +32,16 @@ namespace l1t::demo { BoardDataWriter(FileFormat, const std::string& filePath, + const std::string& fileExt, const size_t framesPerBX, const size_t tmux, const size_t maxFramesPerFile, const std::map>&, const std::map&); + // Set ID string that's written at start of board data files + void setBoardDataFileID(const std::string&); + void addEvent(const EventData& data); // If there are events that have not been written to file, forces creation of a board data file containing them @@ -50,6 +55,9 @@ namespace l1t::demo { FileFormat fileFormat_; + // ID string that's written at start of board data files + std::string boardDataFileID_; + std::function filePathGen_; std::vector fileNames_; diff --git a/L1Trigger/DemonstratorTools/interface/FileFormat.h b/L1Trigger/DemonstratorTools/interface/FileFormat.h index 06d5bc15b7bcb..b17b12044530a 100644 --- a/L1Trigger/DemonstratorTools/interface/FileFormat.h +++ b/L1Trigger/DemonstratorTools/interface/FileFormat.h @@ -6,7 +6,12 @@ namespace l1t::demo { - enum class FileFormat { APx, EMP, X20 }; + enum class FileFormat { + APx, + EMPv1, //< Format used in EMP until version 0.6.x + EMPv2, //< Format used in EMP from verison 0.7.0 + X2O + }; std::ostream& operator<<(std::ostream&, FileFormat); diff --git a/L1Trigger/DemonstratorTools/interface/Frame.h b/L1Trigger/DemonstratorTools/interface/Frame.h index 00534443bb57d..8abd16a061f6d 100644 --- a/L1Trigger/DemonstratorTools/interface/Frame.h +++ b/L1Trigger/DemonstratorTools/interface/Frame.h @@ -18,8 +18,9 @@ namespace l1t::demo { ap_uint<64> data{0}; bool valid{false}; bool strobe{true}; - bool start{false}; - bool end{false}; + bool startOfOrbit{false}; + bool startOfPacket{false}; + bool endOfPacket{false}; }; } // namespace l1t::demo diff --git a/L1Trigger/DemonstratorTools/plugins/GTTFileWriter.cc b/L1Trigger/DemonstratorTools/plugins/GTTFileWriter.cc index b28157833db59..a9fe05c34a399 100644 --- a/L1Trigger/DemonstratorTools/plugins/GTTFileWriter.cc +++ b/L1Trigger/DemonstratorTools/plugins/GTTFileWriter.cc @@ -164,6 +164,7 @@ GTTFileWriter::GTTFileWriter(const edm::ParameterSet& iConfig) etMissToken_(consumes>(iConfig.getUntrackedParameter("etmiss"))), fileWriterInputTracks_(l1t::demo::parseFileFormat(iConfig.getUntrackedParameter("format")), iConfig.getUntrackedParameter("inputFilename"), + iConfig.getUntrackedParameter("fileExtension"), kFramesPerTMUXPeriod, kGTTBoardTMUX, kMaxLinesPerFile, @@ -171,6 +172,7 @@ GTTFileWriter::GTTFileWriter(const edm::ParameterSet& iConfig) kChannelSpecsInput), fileWriterConvertedTracks_(l1t::demo::parseFileFormat(iConfig.getUntrackedParameter("format")), iConfig.getUntrackedParameter("inputConvertedFilename"), + iConfig.getUntrackedParameter("fileExtension"), kFramesPerTMUXPeriod, kGTTBoardTMUX, kMaxLinesPerFile, @@ -178,6 +180,7 @@ GTTFileWriter::GTTFileWriter(const edm::ParameterSet& iConfig) kChannelSpecsInput), fileWriterSelectedTracks_(l1t::demo::parseFileFormat(iConfig.getUntrackedParameter("format")), iConfig.getUntrackedParameter("selectedTracksFilename"), + iConfig.getUntrackedParameter("fileExtension"), kFramesPerTMUXPeriod, kGTTBoardTMUX, kMaxLinesPerFile, @@ -186,6 +189,7 @@ GTTFileWriter::GTTFileWriter(const edm::ParameterSet& iConfig) fileWriterVertexAssociatedTracks_( l1t::demo::parseFileFormat(iConfig.getUntrackedParameter("format")), iConfig.getUntrackedParameter("vertexAssociatedTracksFilename"), + iConfig.getUntrackedParameter("fileExtension"), kFramesPerTMUXPeriod, kGTTBoardTMUX, kMaxLinesPerFile, @@ -193,12 +197,14 @@ GTTFileWriter::GTTFileWriter(const edm::ParameterSet& iConfig) kChannelSpecsInput), fileWriterOutputToCorrelator_(l1t::demo::parseFileFormat(iConfig.getUntrackedParameter("format")), iConfig.getUntrackedParameter("outputCorrelatorFilename"), + iConfig.getUntrackedParameter("fileExtension"), kFramesPerTMUXPeriod, kGTTBoardTMUX, kMaxLinesPerFile, kChannelSpecsOutputToCorrelator), fileWriterOutputToGlobalTrigger_(l1t::demo::parseFileFormat(iConfig.getUntrackedParameter("format")), iConfig.getUntrackedParameter("outputGlobalTriggerFilename"), + iConfig.getUntrackedParameter("fileExtension"), kFramesPerTMUXPeriod, kGTTBoardTMUX, kMaxLinesPerFile, @@ -310,6 +316,7 @@ void GTTFileWriter::fillDescriptions(edm::ConfigurationDescriptions& description desc.addUntracked("outputCorrelatorFilename", "L1GTTOutputToCorrelatorFile"); desc.addUntracked("outputGlobalTriggerFilename", "L1GTTOutputToGlobalTriggerFile"); desc.addUntracked("format", "APx"); + desc.addUntracked("fileExtension", "txt"); descriptions.add("GTTFileWriter", desc); } diff --git a/L1Trigger/DemonstratorTools/python/GTTFileWriter_cff.py b/L1Trigger/DemonstratorTools/python/GTTFileWriter_cff.py index 61c4c46929041..c859d23bd5b45 100644 --- a/L1Trigger/DemonstratorTools/python/GTTFileWriter_cff.py +++ b/L1Trigger/DemonstratorTools/python/GTTFileWriter_cff.py @@ -15,5 +15,6 @@ vertexAssociatedTracksFilename = cms.untracked.string("L1GTTVertexAssociatedTracksFile"), outputCorrelatorFilename = cms.untracked.string("L1GTTOutputToCorrelatorFile"), outputGlobalTriggerFilename = cms.untracked.string("L1GTTOutputToGlobalTriggerFile"), + FileExtension = cms.untracked.string("txt"), format = cms.untracked.string("APx") ) diff --git a/L1Trigger/DemonstratorTools/src/BoardData.cc b/L1Trigger/DemonstratorTools/src/BoardData.cc index 2a40b5c3d6fec..f6d4992bfb40d 100644 --- a/L1Trigger/DemonstratorTools/src/BoardData.cc +++ b/L1Trigger/DemonstratorTools/src/BoardData.cc @@ -14,6 +14,8 @@ namespace l1t::demo { const std::string& BoardData::name() const { return name_; } + void BoardData::name(const std::string& aName) { name_ = aName; } + std::map::const_iterator BoardData::begin() const { return data_.begin(); } std::map::iterator BoardData::begin() { return data_.begin(); } diff --git a/L1Trigger/DemonstratorTools/src/BoardDataReader.cc b/L1Trigger/DemonstratorTools/src/BoardDataReader.cc index 161f62d4974fb..3665c2f503128 100644 --- a/L1Trigger/DemonstratorTools/src/BoardDataReader.cc +++ b/L1Trigger/DemonstratorTools/src/BoardDataReader.cc @@ -75,14 +75,14 @@ namespace l1t::demo { bool expectValid(((j - framesBeforeFirstPacket) % eventLength) < packetLength); - if (expectValid) { - if (not chanData.at(j).valid) - throw std::runtime_error("Frame " + std::to_string(j) + " on channel " + - std::to_string(indices.at(tmuxIndex)) + - " is invalid, but expected valid frame"); - } else if (chanData.at(j).valid) - throw std::runtime_error("Frame " + std::to_string(j) + " on channel " + - std::to_string(indices.at(tmuxIndex)) + " is valid, but expected invalid frame"); + // if (expectValid) { + // if (not chanData.at(j).valid) + // throw std::runtime_error("Frame " + std::to_string(j) + " on channel " + + // std::to_string(indices.at(tmuxIndex)) + + // " is invalid, but expected valid frame"); + // } else if (chanData.at(j).valid) + // throw std::runtime_error("Frame " + std::to_string(j) + " on channel " + + // std::to_string(indices.at(tmuxIndex)) + " is valid, but expected invalid frame"); } } } diff --git a/L1Trigger/DemonstratorTools/src/BoardDataWriter.cc b/L1Trigger/DemonstratorTools/src/BoardDataWriter.cc index c98a3cb5b9918..7dcd95af15696 100644 --- a/L1Trigger/DemonstratorTools/src/BoardDataWriter.cc +++ b/L1Trigger/DemonstratorTools/src/BoardDataWriter.cc @@ -9,12 +9,14 @@ namespace l1t::demo { BoardDataWriter::BoardDataWriter(FileFormat format, const std::string& path, + const std::string& fileExt, const size_t framesPerBX, const size_t tmux, const size_t maxFramesPerFile, const ChannelMap_t& channelSpecs) : fileFormat_(format), - filePathGen_([=](const size_t i) { return path + "_" + std::to_string(i) + ".txt"; }), + boardDataFileID_("CMSSW"), + filePathGen_([=](const size_t i) { return path + "_" + std::to_string(i) + "." + fileExt; }), framesPerBX_(framesPerBX), boardTMUX_(tmux), maxFramesPerFile_(maxFramesPerFile), @@ -24,6 +26,8 @@ namespace l1t::demo { channelMap_(channelSpecs) { if (channelMap_.empty()) throw std::runtime_error("BoardDataWriter channel map cannnot be empty"); + if (fileExt != "txt" && fileExt != "txt.gz" && fileExt != "txt.xz") + throw std::runtime_error("BoardDataWriter fileExt must be one of txt, txt.gz, txt.xz"); for (const auto& [id, value] : channelMap_) { const auto& [spec, indices] = value; @@ -50,12 +54,16 @@ namespace l1t::demo { BoardDataWriter::BoardDataWriter(FileFormat format, const std::string& path, + const std::string& fileExt, const size_t framesPerBX, const size_t tmux, const size_t maxFramesPerFile, const std::map>& channelMap, const std::map& channelSpecs) - : BoardDataWriter(format, path, framesPerBX, tmux, maxFramesPerFile, mergeMaps(channelMap, channelSpecs)) {} + : BoardDataWriter( + format, path, fileExt, framesPerBX, tmux, maxFramesPerFile, mergeMaps(channelMap, channelSpecs)) {} + + void BoardDataWriter::setBoardDataFileID(const std::string& aId) { boardDataFileID_ = aId; } void BoardDataWriter::addEvent(const EventData& eventData) { // Check that data is supplied for each channel @@ -90,9 +98,9 @@ namespace l1t::demo { // Override flags for start & end of event BoardData::Channel::iterator it(boardData_.at(chanIndex).end() - 1); - it->end = true; + it->endOfPacket = true; it -= (channelData.size() - 1); - it->start = true; + it->startOfPacket = true; // Pad link with non-valid frames boardData_.at(chanIndex).insert( @@ -114,6 +122,19 @@ namespace l1t::demo { for (auto& x : boardData_) x.second.resize(maxFramesPerFile_); + // For each channel: Assert start_of_orbit for first clock cycle that start is asserted + for (auto& x : boardData_) { + for (auto& frame : x.second) { + if (frame.startOfPacket) { + frame.startOfOrbit = true; + break; + } + } + } + + // Set ID field for board data files + boardData_.name(boardDataFileID_); + // Write board data object to file const std::string filePath = filePathGen_(fileNames_.size()); write(boardData_, filePath, fileFormat_); @@ -144,4 +165,4 @@ namespace l1t::demo { pendingEvents_ = 0; } -} // namespace l1t::demo \ No newline at end of file +} // namespace l1t::demo diff --git a/L1Trigger/DemonstratorTools/src/FileFormat.cc b/L1Trigger/DemonstratorTools/src/FileFormat.cc index d51110af1308d..741b26c595bdb 100644 --- a/L1Trigger/DemonstratorTools/src/FileFormat.cc +++ b/L1Trigger/DemonstratorTools/src/FileFormat.cc @@ -10,11 +10,14 @@ namespace l1t::demo { case FileFormat::APx: os << "APx"; break; - case FileFormat::EMP: - os << "EMP"; + case FileFormat::EMPv1: + os << "EMPv1"; break; - case FileFormat::X20: - os << "X20"; + case FileFormat::EMPv2: + os << "EMPv2"; + break; + case FileFormat::X2O: + os << "X2O"; } return os; } diff --git a/L1Trigger/DemonstratorTools/src/utilities.cc b/L1Trigger/DemonstratorTools/src/utilities.cc index b35ba60c138d6..f9c13a3dcce54 100644 --- a/L1Trigger/DemonstratorTools/src/utilities.cc +++ b/L1Trigger/DemonstratorTools/src/utilities.cc @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include #ifdef CMSSW_GIT_HASH #include "FWCore/MessageLogger/interface/MessageLogger.h" @@ -68,12 +71,14 @@ namespace { namespace l1t::demo { FileFormat parseFileFormat(const std::string& s) { - static const std::unordered_map kFormatStringMap({{"EMP", FileFormat::EMP}, - {"emp", FileFormat::EMP}, + static const std::unordered_map kFormatStringMap({{"EMP", FileFormat::EMPv1}, + {"emp", FileFormat::EMPv1}, + {"EMPv1", FileFormat::EMPv1}, + {"EMPv2", FileFormat::EMPv2}, {"APx", FileFormat::APx}, {"apx", FileFormat::APx}, - {"X20", FileFormat::X20}, - {"x20", FileFormat::X20}}); + {"X2O", FileFormat::X2O}, + {"x2O", FileFormat::X2O}}); const auto it = kFormatStringMap.find(s); if (it == kFormatStringMap.end()) @@ -82,31 +87,49 @@ namespace l1t::demo { return it->second; } - BoardData readAPxFile(std::istream&, const FileFormat); + BoardData readAPxFile(std::istream&); - BoardData readEMPFile(std::istream&, const FileFormat); + BoardData readEMPFileV1(std::istream&); - BoardData readX20File(std::istream&, const FileFormat); + BoardData readEMPFileV2(std::istream&); + + BoardData readX2OFile(std::istream&); BoardData read(const std::string& filePath, const FileFormat format) { - std::ifstream file(filePath); + std::ifstream file(filePath, std::ios_base::in | std::ios_base::binary); if (not file.is_open()) throw std::runtime_error("Could not open file '" + filePath + "'"); - return read(file, format); + boost::iostreams::filtering_istream stream; + if (filePath.rfind(".gz") == filePath.length() - 3) + stream.push(boost::iostreams::gzip_decompressor()); + else if (filePath.rfind(".xz") == filePath.length() - 3) + stream.push(boost::iostreams::lzma_decompressor()); + + stream.push(file); + + return read(stream, format); } BoardData read(std::istream& file, const FileFormat format) { - if (format == FileFormat::APx) - return readAPxFile(file, format); - else if (format == FileFormat::EMP) - return readEMPFile(file, format); - else - return readX20File(file, format); + switch (format) { + case FileFormat::APx: + return readAPxFile(file); + case FileFormat::EMPv1: + return readEMPFileV1(file); + case FileFormat::EMPv2: + return readEMPFileV2(file); + case FileFormat::X2O: + return readX2OFile(file); + } + + std::ostringstream messageStream; + messageStream << "No read function registered for format " << format; + throw std::runtime_error(messageStream.str()); } - BoardData readAPxFile(std::istream& file, const FileFormat format) { + BoardData readAPxFile(std::istream& file) { std::string line; // Complain if file is empty @@ -171,8 +194,8 @@ namespace l1t::demo { else if ((count % 2) == 1) { uint16_t sbValue = std::stoul(token, nullptr, 16); dataRows.back().at((count - 1) / 2).valid = (sbValue & 0x1); - dataRows.back().at((count - 1) / 2).start = ((sbValue >> 1) & 0x1); - dataRows.back().at((count - 1) / 2).end = ((sbValue >> 3) & 0x1); + dataRows.back().at((count - 1) / 2).startOfPacket = ((sbValue >> 1) & 0x1); + dataRows.back().at((count - 1) / 2).endOfPacket = ((sbValue >> 3) & 0x1); } // Data word else @@ -187,7 +210,7 @@ namespace l1t::demo { return createBoardDataFromRows("", indices, dataRows); } - BoardData readEMPFile(std::istream& file, const FileFormat format) { + BoardData readEMPFileV1(std::istream& file) { // 1) Search for ID string std::string id, line; while (getline(file, line)) { @@ -257,15 +280,94 @@ namespace l1t::demo { return createBoardDataFromRows(id, channels, dataRows); } - BoardData readX20File(std::istream& file, const FileFormat format) { - throw std::runtime_error("Reading X20 file format not yet implemented. Will be done ASAP."); + BoardData readEMPFileV2(std::istream& file) { + // 1) Search for ID string + std::string id, line; + while (getline(file, line)) { + if (line.empty()) + continue; + if (line[0] == '#') + continue; + + if (line.rfind("ID: ", 0) != std::string::npos) { + id = line.substr(4); + break; + } else + throw std::logic_error("Found unexpected line found when searching for board ID: \"" + line + "\""); + } + + // 2) Check that next line states metadata formatting + getline(file, line); + if (line.find("Metadata: (strobe,) start of orbit, start of packet, end of packet, valid") != 0) + throw std::logic_error("Expected metadata line following 'ID' line. Instead found:" + line); + + // 3) Search for column labels (i.e. list of channels/links) + const auto tokens = searchAndTokenize(file, "Link "); + std::vector channels; + std::transform(tokens.begin(), tokens.end(), std::back_inserter(channels), [](const std::string& s) { + return std::stoull(s); + }); + + // 4) Read the main data rows + const std::regex delimiterRegex("\\s\\s+"); + static const std::regex frameRegex("([01])?([01])([01])([01])([01]) ([0-9a-fA-F]{16})"); + std::vector> dataRows; + while (file.good() and getline(file, line)) { + if (line.empty() or line[0] == '#') + continue; + + std::ostringstream prefixStream; + prefixStream << "Frame "; + prefixStream << std::setw(4) << std::setfill('0') << dataRows.size(); + prefixStream << " "; + + const std::string prefix(prefixStream.str()); + if (line.rfind(prefix, 0) == std::string::npos) + throw std::logic_error("Found unexpected line found when searching for \"" + prefix + "\": \"" + line + "\""); + + std::vector row; + std::sregex_token_iterator it(line.begin() + prefix.size(), line.end(), delimiterRegex, -1); + for (; it != std::sregex_token_iterator(); it++) { + const std::string token(it->str()); + if (token.empty()) + continue; + + std::smatch what; + if (not std::regex_match(token, what, frameRegex)) + throw std::logic_error("Token '" + token + "' doesn't match the valid format"); + + l1t::demo::Frame value; + // Import strobe if the strobe group is matched + if (what[1].matched) { + value.strobe = (what[1] == "1"); + } + + value.startOfOrbit = (what[2] == "1"); + value.startOfPacket = (what[3] == "1"); + value.endOfPacket = (what[4] == "1"); + value.valid = (what[5] == "1"); + value.data = ap_uint<64>(std::stoull(what[6].str(), nullptr, 16)); + + row.push_back(value); + } + + dataRows.push_back(row); + } + + return createBoardDataFromRows(id, channels, dataRows); + } + + BoardData readX2OFile(std::istream& file) { + throw std::runtime_error("Reading X2O file format not yet implemented. Will be done ASAP."); } - void writeAPxFile(const BoardData&, std::ostream&, const FileFormat); + void writeAPxFile(const BoardData&, std::ostream&); + + void writeEMPFileV1(const BoardData&, std::ostream&); - void writeEMPFile(const BoardData&, std::ostream&, const FileFormat); + void writeEMPFileV2(const BoardData&, std::ostream&); - void writeX20File(const BoardData&, std::ostream&, const FileFormat); + void writeX2OFile(const BoardData&, std::ostream&); void write(const BoardData& data, const std::string& filePath, const FileFormat format) { // Open file @@ -277,12 +379,19 @@ namespace l1t::demo { << "Writing board data (" << std::distance(data.begin(), data.end()) << " channels, " << data.begin()->second.size() << " frames) to file '" << filePath << "' (format: " << format << ")" << std::endl; - std::ofstream file(filePath); + + std::ofstream file(filePath, std::ios_base::out | std::ios_base::binary); if (not file.is_open()) throw std::runtime_error("Could not open file '" + filePath + "'"); - write(data, file, format); + boost::iostreams::filtering_ostream stream; + if (filePath.rfind(".gz") == filePath.length() - 3) + stream.push(boost::iostreams::gzip_compressor()); + else if (filePath.rfind(".xz") == filePath.length() - 3) + stream.push(boost::iostreams::lzma_compressor()); + stream.push(file); + write(data, stream, format); } void write(const BoardData& data, std::ostream& file, const FileFormat format) { @@ -302,18 +411,21 @@ namespace l1t::demo { // Call relevant write function switch (format) { case FileFormat::APx: - writeAPxFile(data, file, format); + writeAPxFile(data, file); return; - case FileFormat::EMP: - writeEMPFile(data, file, format); + case FileFormat::EMPv1: + writeEMPFileV1(data, file); return; - case FileFormat::X20: - writeX20File(data, file, format); + case FileFormat::EMPv2: + writeEMPFileV2(data, file); + return; + case FileFormat::X2O: + writeX2OFile(data, file); return; } } - void writeAPxFile(const BoardData& data, std::ostream& file, const FileFormat format) { + void writeAPxFile(const BoardData& data, std::ostream& file) { // Note: APx sideband encoding // Short-term, simulation only: // 0 -> Valid @@ -350,8 +462,8 @@ namespace l1t::demo { //const auto j = channel.first; const auto channelData = channel.second; uint16_t sideband = channelData.at(i).valid; - sideband |= channelData.at(i).start << 1; - sideband |= channelData.at(i).end << 3; + sideband |= channelData.at(i).startOfPacket << 1; + sideband |= channelData.at(i).endOfPacket << 3; file << " 0x" << std::setw(2) << sideband; file << " 0x" << std::setw(16) << uint64_t(channelData.at(i).data); } @@ -359,7 +471,7 @@ namespace l1t::demo { } } - void writeEMPFile(const BoardData& data, std::ostream& file, const FileFormat format) { + void writeEMPFileV1(const BoardData& data, std::ostream& file) { file << std::setfill('0'); // Board name/id @@ -398,8 +510,47 @@ namespace l1t::demo { } } - void writeX20File(const BoardData& data, std::ostream& file, const FileFormat format) { - throw std::runtime_error("Writing X20 file format not yet implemented. Will be done ASAP."); + void writeEMPFileV2(const BoardData& data, std::ostream& file) { + file << std::setfill('0'); + + // Board name/id + file << "ID: " << data.name() << std::endl; + file << "Metadata: (strobe,) start of orbit, start of packet, end of packet, valid" << std::endl; + file << std::endl; + + // Link header + file << " Link "; + std::map strobedLinkMap; + for (const auto& channel : data) { + const auto i = channel.first; + strobedLinkMap[i] = + std::any_of(channel.second.begin(), channel.second.end(), [](const Frame& x) { return not x.strobe; }); + if (strobedLinkMap.at(i)) + file << " "; + file << " " << std::setw(3) << i << " "; + } + file << std::endl; + + // Frames + const auto firstChannel = data.begin(); + for (size_t i = 0; i < firstChannel->second.size(); i++) { + file << "Frame " << std::setw(4) << i << " "; + for (const auto& channel : data) { + //const auto j = channel.first; + const auto channelData = channel.second; + file << " "; + if (strobedLinkMap.at(channel.first)) + file << std::setw(1) << channelData.at(i).strobe; + file << std::setw(1) << channelData.at(i).startOfOrbit << channelData.at(i).startOfPacket + << channelData.at(i).endOfPacket << channelData.at(i).valid; + file << " " << std::setw(16) << std::hex << uint64_t(channelData.at(i).data); + } + file << std::endl << std::dec; + } + } + + void writeX2OFile(const BoardData& data, std::ostream& file) { + throw std::runtime_error("Writing X2O file format not yet implemented. Will be done ASAP."); } } // namespace l1t::demo diff --git a/L1Trigger/DemonstratorTools/test/gtt/createFirmwareInputFiles_cfg.py b/L1Trigger/DemonstratorTools/test/gtt/createFirmwareInputFiles_cfg.py index 6f720104d9db5..bf73082319f6b 100644 --- a/L1Trigger/DemonstratorTools/test/gtt/createFirmwareInputFiles_cfg.py +++ b/L1Trigger/DemonstratorTools/test/gtt/createFirmwareInputFiles_cfg.py @@ -15,7 +15,7 @@ 'EMP', # default value VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.string, - "File format (APx, EMP or X20)") + "File format (APx, EMP or X2O)") options.register('threads', 1, # default value VarParsing.VarParsing.multiplicity.singleton, diff --git a/L1Trigger/DemonstratorTools/test/gtt/example_vertex_emp.txt b/L1Trigger/DemonstratorTools/test/gtt/example_vertex_empV1.txt similarity index 100% rename from L1Trigger/DemonstratorTools/test/gtt/example_vertex_emp.txt rename to L1Trigger/DemonstratorTools/test/gtt/example_vertex_empV1.txt diff --git a/L1Trigger/DemonstratorTools/test/gtt/example_vertex_empV2.txt b/L1Trigger/DemonstratorTools/test/gtt/example_vertex_empV2.txt new file mode 100644 index 0000000000000..a415a333a4cc4 --- /dev/null +++ b/L1Trigger/DemonstratorTools/test/gtt/example_vertex_empV2.txt @@ -0,0 +1,176 @@ +ID: CMSSW +Metadata: (strobe,) start of orbit, start of packet, end of packet, valid + + Link 000 +Frame 0000 0000 0000000000000000 +Frame 0001 0000 0000000000000000 +Frame 0002 0000 0000000000000000 +Frame 0003 0000 0000000000000000 +Frame 0004 0000 0000000000000000 +Frame 0005 0000 0000000000000000 +Frame 0006 0000 0000000000000000 +Frame 0007 0000 0000000000000000 +Frame 0008 0000 0000000000000000 +Frame 0009 0000 0000000000000000 +Frame 0010 1101 0000000000000001 +Frame 0011 0001 0000000000000001 +Frame 0012 0001 0000000000000001 +Frame 0013 0001 0000000000000001 +Frame 0014 0001 0000000000000000 +Frame 0015 0001 0000000000000000 +Frame 0016 0001 0000000000000000 +Frame 0017 0001 0000000000000000 +Frame 0018 0001 0000000000000000 +Frame 0019 0011 0000000000000000 +Frame 0020 0000 0000000000000000 +Frame 0021 0000 0000000000000000 +Frame 0022 0000 0000000000000000 +Frame 0023 0000 0000000000000000 +Frame 0024 0000 0000000000000000 +Frame 0025 0000 0000000000000000 +Frame 0026 0000 0000000000000000 +Frame 0027 0000 0000000000000000 +Frame 0028 0000 0000000000000000 +Frame 0029 0000 0000000000000000 +Frame 0030 0000 0000000000000000 +Frame 0031 0000 0000000000000000 +Frame 0032 0000 0000000000000000 +Frame 0033 0000 0000000000000000 +Frame 0034 0000 0000000000000000 +Frame 0035 0000 0000000000000000 +Frame 0036 0000 0000000000000000 +Frame 0037 0000 0000000000000000 +Frame 0038 0000 0000000000000000 +Frame 0039 0000 0000000000000000 +Frame 0040 0000 0000000000000000 +Frame 0041 0000 0000000000000000 +Frame 0042 0000 0000000000000000 +Frame 0043 0000 0000000000000000 +Frame 0044 0000 0000000000000000 +Frame 0045 0000 0000000000000000 +Frame 0046 0000 0000000000000000 +Frame 0047 0000 0000000000000000 +Frame 0048 0000 0000000000000000 +Frame 0049 0000 0000000000000000 +Frame 0050 0000 0000000000000000 +Frame 0051 0000 0000000000000000 +Frame 0052 0000 0000000000000000 +Frame 0053 0000 0000000000000000 +Frame 0054 0000 0000000000000000 +Frame 0055 0000 0000000000000000 +Frame 0056 0000 0000000000000000 +Frame 0057 0000 0000000000000000 +Frame 0058 0000 0000000000000000 +Frame 0059 0000 0000000000000000 +Frame 0060 0000 0000000000000000 +Frame 0061 0000 0000000000000000 +Frame 0062 0000 0000000000000000 +Frame 0063 0000 0000000000000000 +Frame 0064 0101 0000000000000001 +Frame 0065 0001 0000000000000001 +Frame 0066 0001 0000000000000000 +Frame 0067 0001 0000000000000000 +Frame 0068 0001 0000000000000000 +Frame 0069 0001 0000000000000000 +Frame 0070 0001 0000000000000000 +Frame 0071 0001 0000000000000000 +Frame 0072 0001 0000000000000000 +Frame 0073 0011 0000000000000000 +Frame 0074 0000 0000000000000000 +Frame 0075 0000 0000000000000000 +Frame 0076 0000 0000000000000000 +Frame 0077 0000 0000000000000000 +Frame 0078 0000 0000000000000000 +Frame 0079 0000 0000000000000000 +Frame 0080 0000 0000000000000000 +Frame 0081 0000 0000000000000000 +Frame 0082 0000 0000000000000000 +Frame 0083 0000 0000000000000000 +Frame 0084 0000 0000000000000000 +Frame 0085 0000 0000000000000000 +Frame 0086 0000 0000000000000000 +Frame 0087 0000 0000000000000000 +Frame 0088 0000 0000000000000000 +Frame 0089 0000 0000000000000000 +Frame 0090 0000 0000000000000000 +Frame 0091 0000 0000000000000000 +Frame 0092 0000 0000000000000000 +Frame 0093 0000 0000000000000000 +Frame 0094 0000 0000000000000000 +Frame 0095 0000 0000000000000000 +Frame 0096 0000 0000000000000000 +Frame 0097 0000 0000000000000000 +Frame 0098 0000 0000000000000000 +Frame 0099 0000 0000000000000000 +Frame 0100 0000 0000000000000000 +Frame 0101 0000 0000000000000000 +Frame 0102 0000 0000000000000000 +Frame 0103 0000 0000000000000000 +Frame 0104 0000 0000000000000000 +Frame 0105 0000 0000000000000000 +Frame 0106 0000 0000000000000000 +Frame 0107 0000 0000000000000000 +Frame 0108 0000 0000000000000000 +Frame 0109 0000 0000000000000000 +Frame 0110 0000 0000000000000000 +Frame 0111 0000 0000000000000000 +Frame 0112 0000 0000000000000000 +Frame 0113 0000 0000000000000000 +Frame 0114 0000 0000000000000000 +Frame 0115 0000 0000000000000000 +Frame 0116 0000 0000000000000000 +Frame 0117 0000 0000000000000000 +Frame 0118 0101 0000000000000001 +Frame 0119 0001 0000000000000001 +Frame 0120 0001 0000000000000001 +Frame 0121 0001 0000000000000001 +Frame 0122 0001 0000000000000001 +Frame 0123 0001 0000000000000001 +Frame 0124 0001 0000000000000001 +Frame 0125 0001 0000000000000001 +Frame 0126 0001 0000000000000000 +Frame 0127 0011 0000000000000000 +Frame 0128 0000 0000000000000000 +Frame 0129 0000 0000000000000000 +Frame 0130 0000 0000000000000000 +Frame 0131 0000 0000000000000000 +Frame 0132 0000 0000000000000000 +Frame 0133 0000 0000000000000000 +Frame 0134 0000 0000000000000000 +Frame 0135 0000 0000000000000000 +Frame 0136 0000 0000000000000000 +Frame 0137 0000 0000000000000000 +Frame 0138 0000 0000000000000000 +Frame 0139 0000 0000000000000000 +Frame 0140 0000 0000000000000000 +Frame 0141 0000 0000000000000000 +Frame 0142 0000 0000000000000000 +Frame 0143 0000 0000000000000000 +Frame 0144 0000 0000000000000000 +Frame 0145 0000 0000000000000000 +Frame 0146 0000 0000000000000000 +Frame 0147 0000 0000000000000000 +Frame 0148 0000 0000000000000000 +Frame 0149 0000 0000000000000000 +Frame 0150 0000 0000000000000000 +Frame 0151 0000 0000000000000000 +Frame 0152 0000 0000000000000000 +Frame 0153 0000 0000000000000000 +Frame 0154 0000 0000000000000000 +Frame 0155 0000 0000000000000000 +Frame 0156 0000 0000000000000000 +Frame 0157 0000 0000000000000000 +Frame 0158 0000 0000000000000000 +Frame 0159 0000 0000000000000000 +Frame 0160 0000 0000000000000000 +Frame 0161 0000 0000000000000000 +Frame 0162 0000 0000000000000000 +Frame 0163 0000 0000000000000000 +Frame 0164 0000 0000000000000000 +Frame 0165 0000 0000000000000000 +Frame 0166 0000 0000000000000000 +Frame 0167 0000 0000000000000000 +Frame 0168 0000 0000000000000000 +Frame 0169 0000 0000000000000000 +Frame 0170 0000 0000000000000000 +Frame 0171 0000 0000000000000000 diff --git a/L1Trigger/DemonstratorTools/test/gtt/verifyFirmwareOutput_cfg.py b/L1Trigger/DemonstratorTools/test/gtt/verifyFirmwareOutput_cfg.py index ae64cf0329e65..132953bc08de7 100644 --- a/L1Trigger/DemonstratorTools/test/gtt/verifyFirmwareOutput_cfg.py +++ b/L1Trigger/DemonstratorTools/test/gtt/verifyFirmwareOutput_cfg.py @@ -11,7 +11,7 @@ 'EMP', # default value VarParsing.VarParsing.multiplicity.singleton, VarParsing.VarParsing.varType.string, - "File format (APx, EMP or X20)") + "File format (APx, EMP or X2O)") options.parseArguments() inputFiles = [] diff --git a/L1Trigger/L1THGCal/BuildFile.xml b/L1Trigger/L1THGCal/BuildFile.xml index ac1f64cda7e43..4015804fd9067 100644 --- a/L1Trigger/L1THGCal/BuildFile.xml +++ b/L1Trigger/L1THGCal/BuildFile.xml @@ -7,6 +7,7 @@ + diff --git a/L1Trigger/L1THGCal/interface/HGCalAlgoWrapperBase.h b/L1Trigger/L1THGCal/interface/HGCalAlgoWrapperBase.h index 9172e808bf9ac..4ffca6c91b00e 100644 --- a/L1Trigger/L1THGCal/interface/HGCalAlgoWrapperBase.h +++ b/L1Trigger/L1THGCal/interface/HGCalAlgoWrapperBase.h @@ -11,9 +11,9 @@ #include "DataFormats/L1THGCal/interface/HGCalTowerMap.h" typedef HGCalAlgoWrapperBaseT< - std::pair>, const std::vector>>, + const std::vector>>, std::pair, - std::pair> + std::tuple> HGCalHistoClusteringWrapperBase; typedef HGCalAlgoWrapperBaseT>, diff --git a/L1Trigger/L1THGCal/interface/HGCalTriggerGeometryBase.h b/L1Trigger/L1THGCal/interface/HGCalTriggerGeometryBase.h index 6f4ba1c4f4331..2380d679e8220 100644 --- a/L1Trigger/L1THGCal/interface/HGCalTriggerGeometryBase.h +++ b/L1Trigger/L1THGCal/interface/HGCalTriggerGeometryBase.h @@ -82,6 +82,7 @@ class HGCalTriggerGeometryBase { virtual bool disconnectedModule(const unsigned module_id) const = 0; virtual unsigned lastTriggerLayer() const = 0; virtual unsigned triggerLayer(const unsigned id) const = 0; + virtual const std::vector& triggerLayers() const = 0; protected: void setEEGeometry(const HGCalGeometry* geom) { hgc_ee_geometry_ = geom; } diff --git a/L1Trigger/L1THGCal/interface/backend_emulator/CentroidHelper.h b/L1Trigger/L1THGCal/interface/backend_emulator/CentroidHelper.h new file mode 100644 index 0000000000000..dd9fb58d60759 --- /dev/null +++ b/L1Trigger/L1THGCal/interface/backend_emulator/CentroidHelper.h @@ -0,0 +1,64 @@ +#ifndef __L1Trigger_L1THGCal_CentroidHelper_h__ +#define __L1Trigger_L1THGCal_CentroidHelper_h__ + +#include + +namespace l1thgcfirmware { + + class CentroidHelper { + public: + CentroidHelper() : CentroidHelper(0, 0, 0, 0, 0, 0, 0, false) {} + CentroidHelper(unsigned int clock, unsigned int index, unsigned int dataValid) + : CentroidHelper(clock, index, 0, 0, 0, 0, 0, dataValid) {} + CentroidHelper(unsigned int clock, + unsigned int index, + unsigned int column, + unsigned int row, + unsigned int energy, + unsigned int X, + unsigned int Y, + unsigned int dataValid) + : clock_(clock), + index_(index), + column_(column), + row_(row), + energy_(energy), + x_(X), + y_(Y), + dataValid_(dataValid) {} + ~CentroidHelper() {} + + // Getters + unsigned int clock() const { return clock_; } + unsigned int index() const { return index_; } + unsigned int column() const { return column_; } + unsigned int row() const { return row_; } + unsigned int energy() const { return energy_; } + unsigned int X() const { return x_; } + unsigned int Y() const { return y_; } + bool dataValid() const { return dataValid_; } + + // Setters + void setClock(const unsigned int clock) { clock_ = clock; } + void setIndex(const unsigned int index) { index_ = index; } + + private: + unsigned int clock_; + unsigned int index_; + unsigned int column_; + unsigned int row_; + unsigned int energy_; + unsigned int x_; + unsigned int y_; + bool dataValid_; + }; + + typedef std::unique_ptr CentroidHelperPtr; + typedef std::vector CentroidHelperPtrCollection; + typedef std::vector CentroidHelperPtrCollections; + + typedef std::shared_ptr CentroidHelperShrPtr; + typedef std::vector CentroidHelperShrPtrCollection; +} // namespace l1thgcfirmware + +#endif diff --git a/L1Trigger/L1THGCal/interface/backend_emulator/DistServer.h b/L1Trigger/L1THGCal/interface/backend_emulator/DistServer.h new file mode 100644 index 0000000000000..66da3a5c03798 --- /dev/null +++ b/L1Trigger/L1THGCal/interface/backend_emulator/DistServer.h @@ -0,0 +1,29 @@ +#ifndef __L1Trigger_L1THGCal_DistServer_h__ +#define __L1Trigger_L1THGCal_DistServer_h__ + +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalTriggerCell_SA.h" + +#include + +namespace l1thgcfirmware { + + class DistServer { + public: + DistServer(unsigned int nInputs, unsigned int nOutputs, unsigned int nInterleaving); + ~DistServer() {} + + HGCalTriggerCellSAShrPtrCollection clock(HGCalTriggerCellSAShrPtrCollection&); + + unsigned int nOutputs() const { return nOutputs_; } + unsigned int nInterleaving() const { return nInterleaving_; } + + private: + unsigned int nOutputs_; + unsigned int nInterleaving_; + + l1thgcfirmware::HGCalTriggerCellSAShrPtrCollections inputs_; + std::vector > addr_; + }; +} // namespace l1thgcfirmware + +#endif diff --git a/L1Trigger/L1THGCal/interface/backend_emulator/HGCalCluster_SA.h b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalCluster_SA.h new file mode 100644 index 0000000000000..8905fffde1f2d --- /dev/null +++ b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalCluster_SA.h @@ -0,0 +1,297 @@ +#ifndef L1Trigger_L1THGCal_HGCalCluster_SA_h +#define L1Trigger_L1THGCal_HGCalCluster_SA_h + +#include "HGCalTriggerCell_SA.h" +#include "HGCalHistoClusteringConfig_SA.h" +#include "DataFormats/L1THGCal/interface/HGCalCluster_HW.h" + +#include +#include +#include +#include +#include + +#include "ap_int.h" + +namespace l1thgcfirmware { + + class HGCalCluster { + public: + HGCalCluster(unsigned int clock, unsigned int index, bool frameValid, bool dataValid) + : clock_(clock), + index_(index), + layerBits_(0), + frameValid_(frameValid), + dataValid_(dataValid), + n_tc_(0), + e_(0), + e_em_(0), + e_em_core_(0), + e_h_early_(0), + w_(0), + n_tc_w_(0), + w2_(0), + wz_(0), + weta_(0), + wphi_(0), + wroz_(0), + wz2_(0), + weta2_(0), + wphi2_(0), + wroz2_(0), + layerbits_(0), + sat_tc_(false), + shapeq_(1), + sigma_e_quotient_(0), + sigma_e_fraction_(0), + mean_z_quotient_(0), + mean_z_fraction_(0), + mean_phi_quotient_(0), + mean_phi_fraction_(0), + mean_eta_quotient_(0), + mean_eta_fraction_(0), + mean_roz_quotient_(0), + mean_roz_fraction_(0), + sigma_z_quotient_(0), + sigma_z_fraction_(0), + sigma_phi_quotient_(0), + sigma_phi_fraction_(0), + sigma_eta_quotient_(0), + sigma_eta_fraction_(0), + sigma_roz_quotient_(0), + sigma_roz_fraction_(0), + first_layer_(0), + last_layer_(0), + shower_len_(0), + core_shower_len_(0), + e_em_over_e_quotient_(0), + e_em_over_e_fraction_(0), + e_em_core_over_e_em_quotient_(0), + e_em_core_over_e_em_fraction_(0), + e_h_early_over_e_quotient_(0), + e_h_early_over_e_fraction_(0) {} + + ~HGCalCluster() {} + + // Firmware representation of cluster sum (input to cluster properties step) + static constexpr int clusterSumWordLength = 64; + static constexpr int nWordsPerClusterSum = 8; + static constexpr int allClusterSumWordsLength = clusterSumWordLength * nWordsPerClusterSum; + typedef uint64_t ClusterSumWord; + typedef std::array ClusterSumWords; + + std::pair sigma_energy(unsigned int N_TC_W, + unsigned long int Sum_W2, + unsigned int Sum_W); + std::pair mean_coordinate(unsigned int Sum_Wc, unsigned int Sum_W); + std::pair sigma_coordinate(unsigned int Sum_W, + unsigned long int Sum_Wc2, + unsigned int Sum_Wc); + std::pair energy_ratio(unsigned int E_N, unsigned int E_D); + std::vector showerLengthProperties(unsigned long int layerBits); + + // Setters + void setClock(const unsigned int clock) { clock_ = clock; } + void setIndex(const unsigned int index) { index_ = index; } + void setDataValid(const bool dataValid) { dataValid_ = dataValid; } + + void set_n_tc(unsigned int n_tc) { n_tc_ = n_tc; } + void set_e(unsigned int e) { e_ = e; } + void set_e_em(unsigned int e_em) { e_em_ = e_em; } + void set_e_em_core(unsigned int e_em_core) { e_em_core_ = e_em_core; } + void set_e_h_early(unsigned int e_h_early) { e_h_early_ = e_h_early; } + void set_w(unsigned int w) { w_ = w; } + void set_n_tc_w(unsigned int n_tc_w) { n_tc_w_ = n_tc_w; } + void set_w2(unsigned long int w2) { w2_ = w2; } + void set_wz(unsigned int wz) { wz_ = wz; } + void set_weta(unsigned int weta) { weta_ = weta; } + void set_wphi(unsigned int wphi) { wphi_ = wphi; } + void set_wroz(unsigned int wroz) { wroz_ = wroz; } + void set_wz2(unsigned long int wz2) { wz2_ = wz2; } + void set_weta2(unsigned long int weta2) { weta2_ = weta2; } + void set_wphi2(unsigned long int wphi2) { wphi2_ = wphi2; } + void set_wroz2(unsigned long int wroz2) { wroz2_ = wroz2; } + void set_layerbits(unsigned long int layerbits) { layerbits_ = layerbits; } + void set_sat_tc(bool sat_tc) { sat_tc_ = sat_tc; } + void set_shapeq(unsigned int shapeq) { shapeq_ = shapeq; } + + void set_sigma_e_quotient(unsigned long int sigma_e_quotient) { sigma_e_quotient_ = sigma_e_quotient; } + void set_sigma_e_fraction(unsigned long int sigma_e_fraction) { sigma_e_fraction_ = sigma_e_fraction; } + void set_mean_z_quotient(unsigned long int mean_z_quotient) { mean_z_quotient_ = mean_z_quotient; } + void set_mean_z_fraction(unsigned long int mean_z_fraction) { mean_z_fraction_ = mean_z_fraction; } + void set_mean_phi_quotient(unsigned long int mean_phi_quotient) { mean_phi_quotient_ = mean_phi_quotient; } + void set_mean_phi_fraction(unsigned long int mean_phi_fraction) { mean_phi_fraction_ = mean_phi_fraction; } + void set_mean_eta_quotient(unsigned long int mean_eta_quotient) { mean_eta_quotient_ = mean_eta_quotient; } + void set_mean_eta_fraction(unsigned long int mean_eta_fraction) { mean_eta_fraction_ = mean_eta_fraction; } + void set_mean_roz_quotient(unsigned long int mean_roz_quotient) { mean_roz_quotient_ = mean_roz_quotient; } + void set_mean_roz_fraction(unsigned long int mean_roz_fraction) { mean_roz_fraction_ = mean_roz_fraction; } + void set_sigma_z_quotient(unsigned long int sigma_z_quotient) { sigma_z_quotient_ = sigma_z_quotient; } + void set_sigma_z_fraction(unsigned long int sigma_z_fraction) { sigma_z_fraction_ = sigma_z_fraction; } + void set_sigma_phi_quotient(unsigned long int sigma_phi_quotient) { sigma_phi_quotient_ = sigma_phi_quotient; } + void set_sigma_phi_fraction(unsigned long int sigma_phi_fraction) { sigma_phi_fraction_ = sigma_phi_fraction; } + void set_sigma_eta_quotient(unsigned long int sigma_eta_quotient) { sigma_eta_quotient_ = sigma_eta_quotient; } + void set_sigma_eta_fraction(unsigned long int sigma_eta_fraction) { sigma_eta_fraction_ = sigma_eta_fraction; } + void set_sigma_roz_quotient(unsigned long int sigma_roz_quotient) { sigma_roz_quotient_ = sigma_roz_quotient; } + void set_sigma_roz_fraction(unsigned long int sigma_roz_fraction) { sigma_roz_fraction_ = sigma_roz_fraction; } + void set_firstLayer(unsigned long int FirstLayer) { first_layer_ = FirstLayer; } + void set_lastLayer(unsigned long int LastLayer) { last_layer_ = LastLayer; } + void set_showerLen(unsigned long int ShowerLen) { shower_len_ = ShowerLen; } + void set_coreShowerLen(unsigned long int CoreShowerLen) { core_shower_len_ = CoreShowerLen; } + void set_e_em_over_e_quotient(unsigned long int quotient) { e_em_over_e_quotient_ = quotient; } + void set_e_em_over_e_fraction(unsigned long int fraction) { e_em_over_e_fraction_ = fraction; } + void set_e_em_core_over_e_em_quotient(unsigned long int quotient) { e_em_core_over_e_em_quotient_ = quotient; } + void set_e_em_core_over_e_em_fraction(unsigned long int fraction) { e_em_core_over_e_em_fraction_ = fraction; } + void set_e_h_early_over_e_quotient(unsigned long int quotient) { e_h_early_over_e_quotient_ = quotient; } + void set_e_h_early_over_e_fraction(unsigned long int fraction) { e_h_early_over_e_fraction_ = fraction; } + + void add_constituent(HGCalTriggerCellSAShrPtr constituent) { constituents_.emplace_back(constituent); } + + // Getters + unsigned int clock() const { return clock_; } + unsigned int index() const { return index_; } + bool frameValid() const { return frameValid_; } + bool dataValid() const { return dataValid_; } + + unsigned int n_tc() const { return n_tc_; } + unsigned int e() const { return e_; } + unsigned int e_em() const { return e_em_; } + unsigned int e_em_core() const { return e_em_core_; } + unsigned int e_h_early() const { return e_h_early_; } + unsigned int w() const { return w_; } + unsigned int n_tc_w() const { return n_tc_w_; } + unsigned long int w2() const { return w2_; } + unsigned long int wz() const { return wz_; } + unsigned long int weta() const { return weta_; } + unsigned long int wphi() const { return wphi_; } + unsigned long int wroz() const { return wroz_; } + unsigned long int wz2() const { return wz2_; } + unsigned long int weta2() const { return weta2_; } + unsigned long int wphi2() const { return wphi2_; } + unsigned long int wroz2() const { return wroz2_; } + unsigned long int layerbits() const { return layerbits_; } + bool sat_tc() const { return sat_tc_; } + unsigned int shapeq() const { return shapeq_; } + + unsigned long int sigma_e_quotient() const { return sigma_e_quotient_; } + unsigned long int sigma_e_fraction() const { return sigma_e_fraction_; } + unsigned long int mean_z_quotient() const { return mean_z_quotient_; } + unsigned long int mean_z_fraction() const { return mean_z_fraction_; } + unsigned long int mean_phi_quotient() const { return mean_phi_quotient_; } + unsigned long int mean_phi_fraction() const { return mean_phi_fraction_; } + unsigned long int mean_eta_quotient() const { return mean_eta_quotient_; } + unsigned long int mean_eta_fraction() const { return mean_eta_fraction_; } + unsigned long int mean_roz_quotient() const { return mean_roz_quotient_; } + unsigned long int mean_roz_fraction() const { return mean_roz_fraction_; } + unsigned long int sigma_z_quotient() const { return sigma_z_quotient_; } + unsigned long int sigma_z_fraction() const { return sigma_z_fraction_; } + unsigned long int sigma_phi_quotient() const { return sigma_phi_quotient_; } + unsigned long int sigma_phi_fraction() const { return sigma_phi_fraction_; } + unsigned long int sigma_eta_quotient() const { return sigma_eta_quotient_; } + unsigned long int sigma_eta_fraction() const { return sigma_eta_fraction_; } + unsigned long int sigma_roz_quotient() const { return sigma_roz_quotient_; } + unsigned long int sigma_roz_fraction() const { return sigma_roz_fraction_; } + unsigned long int firstLayer() const { return first_layer_; } + unsigned long int lastLayer() const { return last_layer_; } + unsigned long int showerLen() const { return shower_len_; } + unsigned long int coreShowerLen() const { return core_shower_len_; } + unsigned long int e_em_over_e_quotient() const { return e_em_over_e_quotient_; } + unsigned long int e_em_over_e_fraction() const { return e_em_over_e_fraction_; } + unsigned long int e_em_core_over_e_em_quotient() const { return e_em_core_over_e_em_quotient_; } + unsigned long int e_em_core_over_e_em_fraction() const { return e_em_core_over_e_em_fraction_; } + unsigned long int e_h_early_over_e_quotient() const { return e_h_early_over_e_quotient_; } + unsigned long int e_h_early_over_e_fraction() const { return e_h_early_over_e_fraction_; } + + HGCalTriggerCellSAShrPtrCollection& constituents() { return constituents_; } + + // Operators + const HGCalCluster& operator+=(HGCalCluster& hc); + + // Format data into firmware representation + HGCalCluster_HW convertToL1TFormat( const ClusterAlgoConfig& config ); + void formatFirstWord( const ClusterAlgoConfig& config, HGCalCluster_HW& hwCluster ); + void formatSecondWord( const ClusterAlgoConfig& config, HGCalCluster_HW& hwCluster ); + void formatThirdWord( const ClusterAlgoConfig& config, HGCalCluster_HW& hwCluster ); + void formatFourthWord( const ClusterAlgoConfig& config, HGCalCluster_HW& hwCluster ); + + // Conversion of roz to eta (and sigma roz) + double convertRozToEta( const ClusterAlgoConfig& config ); + double convertSigmaRozRozToSigmaEtaEta( const ClusterAlgoConfig& config ); + + // Format data into firmware representation + void clearClusterSumWords(); + ClusterSumWords formatClusterSumWords( const ClusterAlgoConfig& config ); + + private: + unsigned int clock_; + unsigned int index_; + unsigned int layerBits_; + bool frameValid_; + bool dataValid_; + + unsigned int n_tc_; + unsigned int e_; + unsigned int e_em_; + unsigned int e_em_core_; + unsigned int e_h_early_; + unsigned int w_; + unsigned int n_tc_w_; + unsigned long int w2_; + unsigned int wz_; + unsigned int weta_; + unsigned int wphi_; + unsigned int wroz_; + unsigned long int wz2_; + unsigned long int weta2_; + unsigned long int wphi2_; + unsigned long int wroz2_; + unsigned long int layerbits_; + bool sat_tc_; + unsigned int shapeq_; + unsigned long int sigma_e_quotient_; + unsigned long int sigma_e_fraction_; + unsigned long int mean_z_quotient_; + unsigned long int mean_z_fraction_; + unsigned long int mean_phi_quotient_; + unsigned long int mean_phi_fraction_; + unsigned long int mean_eta_quotient_; + unsigned long int mean_eta_fraction_; + unsigned long int mean_roz_quotient_; + unsigned long int mean_roz_fraction_; + unsigned long int sigma_z_quotient_; + unsigned long int sigma_z_fraction_; + unsigned long int sigma_phi_quotient_; + unsigned long int sigma_phi_fraction_; + unsigned long int sigma_eta_quotient_; + unsigned long int sigma_eta_fraction_; + unsigned long int sigma_roz_quotient_; + unsigned long int sigma_roz_fraction_; + unsigned long int first_layer_; + unsigned long int last_layer_; + unsigned long int shower_len_; + unsigned long int core_shower_len_; + unsigned long int e_em_over_e_quotient_; + unsigned long int e_em_over_e_fraction_; + unsigned long int e_em_core_over_e_em_quotient_; + unsigned long int e_em_core_over_e_em_fraction_; + unsigned long int e_h_early_over_e_quotient_; + unsigned long int e_h_early_over_e_fraction_; + + // Extra variables, not available in firmware + // Perhaps move to separate "extra" class? + HGCalTriggerCellSAShrPtrCollection constituents_; + + // Firmware representation of cluster as sent on links to L1T + // ClusterWords packedData_; + + // Firmware representation of cluster sum (input to cluster properties) + ClusterSumWords packedData_clustersSums_; + }; + + typedef std::vector HGCalClusterSACollection; + typedef std::unique_ptr HGCalClusterSAPtr; + typedef std::vector HGCalClusterSAPtrCollection; + typedef std::vector HGCalClusterSAPtrCollections; + +} // namespace l1thgcfirmware + +#endif diff --git a/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusterProperties_SA.h b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusterProperties_SA.h new file mode 100644 index 0000000000000..26b2fdf746c5d --- /dev/null +++ b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusterProperties_SA.h @@ -0,0 +1,44 @@ +#ifndef __L1Trigger_L1THGCal_HGCalHistoClusterProperties_h__ +#define __L1Trigger_L1THGCal_HGCalHistoClusterProperties_h__ + +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalTriggerCell_SA.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/CentroidHelper.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusteringConfig_SA.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalCluster_SA.h" + +namespace l1thgcfirmware { + + class HGCalHistoClusterProperties { + public: + HGCalHistoClusterProperties(const l1thgcfirmware::ClusterAlgoConfig& config); + ~HGCalHistoClusterProperties() {} + + void runClusterProperties(const l1thgcfirmware::HGCalClusterSAPtrCollection& protoClustersIn, + const l1thgcfirmware::CentroidHelperPtrCollection& readoutFlags, + HGCalClusterSAPtrCollection& clustersOut) const; + + private: + // Cluster property steps + void clusterSum(const l1thgcfirmware::HGCalClusterSAPtrCollection& protoClusters, + const l1thgcfirmware::CentroidHelperPtrCollection& readoutFlags, + l1thgcfirmware::HGCalClusterSAPtrCollection& clusterAccumulation, + l1thgcfirmware::HGCalClusterSAPtrCollection& clusterSums) const; + void clusterProperties(l1thgcfirmware::HGCalClusterSAPtrCollection& clusterSums) const; + + // Helper functions + std::pair sigma_energy(unsigned int N_TC_W, + unsigned long int Sum_W2, + unsigned int Sum_W) const; + std::pair mean_coordinate(unsigned int Sum_Wc, unsigned int Sum_W) const; + std::pair sigma_coordinate(unsigned int Sum_W, + unsigned long int Sum_Wc2, + unsigned int Sum_Wc, + double scale = 0) const; + std::pair energy_ratio(unsigned int E_N, unsigned int E_D) const; + std::vector showerLengthProperties(unsigned long int layerBits) const; + + const l1thgcfirmware::ClusterAlgoConfig& config_; + }; +} // namespace l1thgcfirmware + +#endif \ No newline at end of file diff --git a/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusteringConfig_SA.h b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusteringConfig_SA.h new file mode 100644 index 0000000000000..cebf08e6ab3cb --- /dev/null +++ b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusteringConfig_SA.h @@ -0,0 +1,326 @@ +#ifndef __L1Trigger_L1THGCal_HGCalHistoCluteringConfig_SA_h__ +#define __L1Trigger_L1THGCal_HGCalHistoCluteringConfig_SA_h__ + +#include +#include + +namespace l1thgcfirmware { + + enum Step { + Uninitialized = -1, + Input, + Dist0, + Dist1, + Dist2, + Dist3, + Dist4, + Dist5, + TcToHc, + Hist, + Smearing1D, + NormArea, + Smearing2D, + Maxima1D, // Not actually used currently + Maxima2D, + CalcAverage, + Clusterizer, + TriggerCellToCluster, + ClusterSum + }; + + class ClusterAlgoConfig { + public: + ClusterAlgoConfig(); + + void setParameters() {} + + void setSector(const unsigned int sector) { sector_ = sector; } + unsigned int sector() const { return sector_; } + + void setZSide(const int zSide) { zSide_ = zSide; } + int zSide() const { return zSide_; } + + void setStepLatencies(const std::vector& latencies); + unsigned int getStepLatency(const Step step) const { return stepLatency_.at(step); } + unsigned int getLatencyUpToAndIncluding(const Step step) const; + + void setClusterizerOffset(const unsigned clusterizerOffset) { clusterizerOffset_ = clusterizerOffset; } + unsigned int clusterizerOffset() const { return clusterizerOffset_; } + + void setCClocks(const unsigned cClocks) { cClocks_ = cClocks; } + unsigned int cClocks() const { return cClocks_; } + + void setCInputs(const unsigned cInputs) { cInputs_ = cInputs; } + unsigned int cInputs() const { return cInputs_; } + + void setCInputs2(const unsigned cInputs2) { cInputs2_ = cInputs2; } + unsigned int cInputs2() const { return cInputs2_; } + + void setCInt(const unsigned cInt) { cInt_ = cInt; } + unsigned int cInt() const { return cInt_; } + + void setCColumns(const unsigned cColumns) { cColumns_ = cColumns; } + unsigned int cColumns() const { return cColumns_; } + + void setCRows(const unsigned cRows) { cRows_ = cRows; } + unsigned int cRows() const { return cRows_; } + + void setROverZHistOffset(const unsigned rOverZHistOffset) { rOverZHistOffset_ = rOverZHistOffset; } + unsigned int rOverZHistOffset() const { return rOverZHistOffset_; } + + void setROverZBinSize(const unsigned rOverZBinSize) { rOverZBinSize_ = rOverZBinSize; } + unsigned int rOverZBinSize() const { return rOverZBinSize_; } + + void setMaxBinsSmearing1D(const unsigned maxBinsSmearing1D) { maxBinsSmearing1D_ = maxBinsSmearing1D; } + unsigned maxBinsSmearing1D() const { return maxBinsSmearing1D_; } + void setNBitsAreaNormLUT(const unsigned nBitsAreaNormLUT) { nBitsAreaNormLUT_ = nBitsAreaNormLUT; } + unsigned nBitsAreaNormLUT() const { return nBitsAreaNormLUT_; } + unsigned int kernelWidth(unsigned int iBin) const { return kernelWidths_.at(iBin); } + unsigned int areaNormalization(unsigned int iBin) const { return areaNormalizations_.at(iBin); } + + void setROverZRange(const float rOverZRange) { rOverZRange_ = rOverZRange; } + float rOverZRange() const { return rOverZRange_; } + void setROverZNValues(const unsigned rOverZNValues) { rOverZNValues_ = rOverZNValues; } + unsigned rOverZNValues() const { return rOverZNValues_; } + void setPhiRange(const float phiRange) { phiRange_ = phiRange; } + float phiRange() const { return phiRange_; } + void setPhiNValues(const unsigned phiNValues) { phiNValues_ = phiNValues; } + unsigned phiNValues() const { return phiNValues_; } + void setPtDigiFactor(const float ptDigiFactor) { ptDigiFactor_ = ptDigiFactor; } + float ptDigiFactor() const { return ptDigiFactor_; } + + void setMinClusterPtOut(const float pt) { minClusterPtOut_ = pt; } + float minClusterPtOut() const { return minClusterPtOut_; } + + void setMaxClustersPerLink(const unsigned maxClustersPerLink) { maxClustersPerLink_ = maxClustersPerLink; } + unsigned maxClustersPerLink() const { return maxClustersPerLink_; } + void setNInputLinks(const unsigned nInputLinks) { nInputLinks_ = nInputLinks; } + unsigned nInputLinks() const { return nInputLinks_; } + + void setN60Sectors(const unsigned n60Sectors) { n60Sectors_ = n60Sectors; } + unsigned n60Sectors() const { return n60Sectors_; } + void setNCoarsePhiDist1(const unsigned nCoarsePhiDist1) { nCoarsePhiDist1_ = nCoarsePhiDist1; } + unsigned nCoarsePhiDist1() const { return nCoarsePhiDist1_; } + void setNDistServers1(const unsigned nDistServers1) { nDistServers1_ = nDistServers1; } + unsigned nDistServers1() const { return nDistServers1_; } + void setDistServer1_nIn(const unsigned distServer1_nIn) { distServer1_nIn_ = distServer1_nIn; } + unsigned distServer1_nIn() const { return distServer1_nIn_; } + void setDistServer1_nOut(const unsigned distServer1_nOut) { distServer1_nOut_ = distServer1_nOut; } + unsigned distServer1_nOut() const { return distServer1_nOut_; } + void setDistServer1_nInterleave(const unsigned distServer1_nInterleave) { + distServer1_nInterleave_ = distServer1_nInterleave; + } + unsigned distServer1_nInterleave() const { return distServer1_nInterleave_; } + void setNCoarsePhiDist2(const unsigned nCoarsePhiDist2) { nCoarsePhiDist2_ = nCoarsePhiDist2; } + unsigned nCoarsePhiDist2() const { return nCoarsePhiDist2_; } + void setNDistServers2(const unsigned nDistServers2) { nDistServers2_ = nDistServers2; } + unsigned nDistServers2() const { return nDistServers2_; } + void setDistServer2_nIn(const unsigned distServer2_nIn) { distServer2_nIn_ = distServer2_nIn; } + unsigned distServer2_nIn() const { return distServer2_nIn_; } + void setDistServer2_nOut(const unsigned distServer2_nOut) { distServer2_nOut_ = distServer2_nOut; } + unsigned distServer2_nOut() const { return distServer2_nOut_; } + void setDistServer2_nInterleave(const unsigned distServer2_nInterleave) { + distServer2_nInterleave_ = distServer2_nInterleave; + } + unsigned distServer2_nInterleave() const { return distServer2_nInterleave_; } + + void setClusterizerMagicTime(const unsigned clusterizerMagicTime) { clusterizerMagicTime_ = clusterizerMagicTime; } + unsigned int clusterizerMagicTime() const { return clusterizerMagicTime_; } + void setNFifos(const unsigned nFifos) { nFifos_ = nFifos; } + unsigned int nFifos() const { return nFifos_; } + void setNColumnsPerFifo(const unsigned nColumnsPerFifo) { nColumnsPerFifo_ = nColumnsPerFifo; } + unsigned int nColumnsPerFifo() const { return nColumnsPerFifo_; } + void setFirstSeedBin(const unsigned firstSeedBin) { firstSeedBin_ = firstSeedBin; } + unsigned int firstSeedBin() const { return firstSeedBin_; } + void setNColumnFifoVeto(const unsigned nColumnFifoVeto) { nColumnFifoVeto_ = nColumnFifoVeto; } + unsigned int nColumnFifoVeto() const { return nColumnFifoVeto_; } + + void setDeltaR2Thresholds(const std::vector dr2Thresholds) { dr2Thresholds_ = dr2Thresholds; } + unsigned int getDeltaR2Threshold(const unsigned layer) const { return dr2Thresholds_.at(layer); } + + void setNColumnsForClustering(const unsigned nColumnsForClustering) { + nColumnsForClustering_ = nColumnsForClustering; + } + unsigned int nColumnsForClustering() const { return nColumnsForClustering_; } + void setNRowsForClustering(const unsigned nRowsForClustering) { nRowsForClustering_ = nRowsForClustering; } + unsigned int nRowsForClustering() const { return nRowsForClustering_; } + + void setThresholdParams(const unsigned int a, const int b, const int c) { + thresholdMaximaParam_a_ = a; + thresholdMaximaParam_b_ = b; + thresholdMaximaParam_c_ = c; + } + unsigned int thresholdMaxima(unsigned int iBin) const { return thresholdMaximaConstants_.at(iBin); } + + void setNBinsCosLUT(const unsigned int nBinsCosLUT) { nBinsCosLUT_ = nBinsCosLUT; } + unsigned int nBinsCosLUT() const { return nBinsCosLUT_; } + void setNBitsCosLUT(const unsigned int nBitsCosLUT) { nBitsCosLUT_ = nBitsCosLUT; } + unsigned int nBitsCosLUT() const { return nBitsCosLUT_; } + + unsigned int cosLUT(unsigned int iBin) const { return cosLUT_.at(iBin); } + + void setDepths(const std::vector& depths) { + depths_.clear(); + depths_.reserve(depths.size()); + for (const auto& depth : depths) + depths_.push_back(depth); + } + const std::vector& depths() const { return depths_; } + unsigned int depth(unsigned int iLayer) const { return depths_.at(iLayer); } + + void setTriggerLayers(const std::vector& triggerLayers) { triggerLayers_ = triggerLayers; } + const std::vector& triggerLayers() const { return triggerLayers_; } + unsigned int triggerLayer(unsigned int iLayer) const { return triggerLayers_.at(iLayer); } + + void setLayerWeights_E(const std::vector layerWeights_E) { + layerWeights_E_.clear(); + layerWeights_E_.reserve(layerWeights_E.size()); + for (const auto& weight : layerWeights_E) + layerWeights_E_.push_back(weight); + } + const std::vector& layerWeights_E() const { return layerWeights_E_; } + unsigned int layerWeight_E(unsigned int iTriggerLayer) const { return layerWeights_E_.at(iTriggerLayer); } + + void setLayerWeights_E_EM(const std::vector layerWeights_E_EM) { + layerWeights_E_EM_.clear(); + layerWeights_E_EM_.reserve(layerWeights_E_EM.size()); + for (const auto& weight : layerWeights_E_EM) + layerWeights_E_EM_.push_back(weight); + } + const std::vector& layerWeights_E_EM() const { return layerWeights_E_EM_; } + unsigned int layerWeight_E_EM(unsigned int iTriggerLayer) const { return layerWeights_E_EM_.at(iTriggerLayer); } + + void setLayerWeights_E_EM_core(const std::vector layerWeights_E_EM_core) { + layerWeights_E_EM_core_.clear(); + layerWeights_E_EM_core_.reserve(layerWeights_E_EM_core.size()); + for (const auto& weight : layerWeights_E_EM_core) + layerWeights_E_EM_core_.push_back(weight); + } + const std::vector& layerWeights_E_EM_core() const { return layerWeights_E_EM_core_; } + unsigned int layerWeight_E_EM_core(unsigned int iTriggerLayer) const { + return layerWeights_E_EM_core_.at(iTriggerLayer); + } + + void setLayerWeights_E_H_early(const std::vector layerWeights_E_H_early) { + layerWeights_E_H_early_.clear(); + layerWeights_E_H_early_.reserve(layerWeights_E_H_early.size()); + for (const auto& weight : layerWeights_E_H_early) + layerWeights_E_H_early_.push_back(weight); + } + const std::vector& layerWeights_E_H_early() const { return layerWeights_E_H_early_; } + unsigned int layerWeight_E_H_early(unsigned int iTriggerLayer) const { + return layerWeights_E_H_early_.at(iTriggerLayer); + } + + void setCorrection(const unsigned correction) { correction_ = correction; } + unsigned int correction() const { return correction_; } + + void setSaturation(const unsigned saturation) { saturation_ = saturation; } + unsigned int saturation() const { return saturation_; } + + unsigned int rozToEtaLUT(unsigned int iBin) const { return rozToEtaLUT_.at(iBin); } + unsigned int sigmaRozToSigmaEtaLUT(unsigned int iBin) const { return sigmaRozToSigmaEtaLUT_.at(iBin); } + + void setNTriggerLayers(const unsigned n) { nTriggerLayers_ = n; } + unsigned int nTriggerLayers() const { return nTriggerLayers_; } + + void initializeLUTs(); + + void printConfiguration(); // For debugging + + private: + void initializeSmearingKernelConstants(unsigned int bins, unsigned int offset, unsigned int height); + void initializeThresholdMaximaConstants(unsigned int bins, unsigned int a, int b, int c); + void initializeCosLUT(); + void initializeRoZToEtaLUT(); + void initializeSigmaRoZToSigmaEtaLUT(); + + unsigned int histogramOffset_; + unsigned int clusterizerOffset_; + unsigned int cClocks_; + unsigned int cInputs_; + unsigned int cInputs2_; // Better name for variable? + unsigned int cInt_; + unsigned int cColumns_; + unsigned int cRows_; + unsigned int rOverZHistOffset_; + unsigned int rOverZBinSize_; + + // Digitisation parameters + float rOverZRange_; + unsigned rOverZNValues_; + float phiRange_; + unsigned phiNValues_; + float ptDigiFactor_; + + // Selection on output clusters + float minClusterPtOut_; + + // Input link params + unsigned int maxClustersPerLink_; + unsigned int nInputLinks_; + + // TC distribution parameters + unsigned int n60Sectors_; + unsigned int nCoarsePhiDist1_; + unsigned int nDistServers1_; + unsigned int distServer1_nIn_; + unsigned int distServer1_nOut_; + unsigned int distServer1_nInterleave_; + unsigned int nCoarsePhiDist2_; + unsigned int nDistServers2_; + unsigned int distServer2_nIn_; + unsigned int distServer2_nOut_; + unsigned int distServer2_nInterleave_; + + // Smearing and normalization parameters + unsigned int maxBinsSmearing1D_; + unsigned int nBitsAreaNormLUT_; + std::vector kernelWidths_; + std::vector areaNormalizations_; + + // Threshold maxima parameters + unsigned int thresholdMaximaParam_a_; + int thresholdMaximaParam_b_; + int thresholdMaximaParam_c_; + std::vector thresholdMaximaConstants_; + + // Clusterizer parameters + unsigned int nBinsCosLUT_; + unsigned int nBitsCosLUT_; + std::vector cosLUT_; + unsigned int nFifos_; + unsigned int nColumnsPerFifo_; + unsigned int firstSeedBin_; + unsigned int nColumnFifoVeto_; + std::vector dr2Thresholds_; + unsigned int nColumnsForClustering_; + unsigned int nRowsForClustering_; + unsigned int clusterizerMagicTime_; + + std::vector stepLatency_; + + // Parameters for triggerCellToCluster + std::vector depths_; + std::vector triggerLayers_; + std::vector layerWeights_E_; + std::vector layerWeights_E_EM_; + std::vector layerWeights_E_EM_core_; + std::vector layerWeights_E_H_early_; + unsigned int correction_; + unsigned int saturation_; + + // Parameters for cluster properties calculator + std::vector rozToEtaLUT_; + std::vector sigmaRozToSigmaEtaLUT_; + + // Trigger geometry info + unsigned int nTriggerLayers_; + + unsigned int sector_; + int zSide_; + }; + +} // namespace l1thgcfirmware + +#endif diff --git a/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusteringImpl_SA.h b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusteringImpl_SA.h new file mode 100644 index 0000000000000..b684ecd403cd0 --- /dev/null +++ b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusteringImpl_SA.h @@ -0,0 +1,37 @@ +#ifndef __L1Trigger_L1THGCal_HGCalHistoClusteringImplSA_h__ +#define __L1Trigger_L1THGCal_HGCalHistoClusteringImplSA_h__ + +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalTriggerCell_SA.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistogramCell_SA.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/CentroidHelper.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalCluster_SA.h" + +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalTCDistribution_SA.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoSeeding_SA.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClustering_SA.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusterProperties_SA.h" + +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusteringConfig_SA.h" + +namespace l1thgcfirmware { + + class HGCalHistoClusteringImplSA { + public: + HGCalHistoClusteringImplSA(const l1thgcfirmware::ClusterAlgoConfig& config); + ~HGCalHistoClusteringImplSA() {} + + void runAlgorithm(const HGCalTriggerCellSAPtrCollections& inputs, + HGCalTriggerCellSAShrPtrCollection& clusteredTCs, + HGCalClusterSAPtrCollection& clusterSums) const; + + private: + const l1thgcfirmware::ClusterAlgoConfig& config_; + l1thgcfirmware::HGCalTCDistribution tcDistribution_; + l1thgcfirmware::HGCalHistoSeeding seeding_; + l1thgcfirmware::HGCalHistoClustering clustering_; + l1thgcfirmware::HGCalHistoClusterProperties clusterProperties_; + }; + +} // namespace l1thgcfirmware + +#endif diff --git a/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClustering_SA.h b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClustering_SA.h new file mode 100644 index 0000000000000..e6fc8f8f2bd62 --- /dev/null +++ b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClustering_SA.h @@ -0,0 +1,37 @@ +#ifndef __L1Trigger_L1THGCal_HGCalHistoClustering_h__ +#define __L1Trigger_L1THGCal_HGCalHistoClustering_h__ + +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalTriggerCell_SA.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistogramCell_SA.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/CentroidHelper.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusteringConfig_SA.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalCluster_SA.h" + +namespace l1thgcfirmware { + + class HGCalHistoClustering { + public: + HGCalHistoClustering(const l1thgcfirmware::ClusterAlgoConfig& config); + ~HGCalHistoClustering() {} + + void runClustering(const l1thgcfirmware::HGCalTriggerCellSAPtrCollection& triggerCellsIn, + const l1thgcfirmware::HGCalHistogramCellSAPtrCollection& histogramIn, + l1thgcfirmware::HGCalTriggerCellSAShrPtrCollection& clusteredTriggerCellsOut, + l1thgcfirmware::CentroidHelperPtrCollection& readoutFlagsOut, + l1thgcfirmware::HGCalClusterSAPtrCollection& protoClustersOut) const; + + private: + // Clustering + void clusterizer(const l1thgcfirmware::HGCalTriggerCellSAPtrCollection& triggerCellsIn, + const l1thgcfirmware::HGCalHistogramCellSAPtrCollection& histogram, + l1thgcfirmware::HGCalTriggerCellSAShrPtrCollection& clusteredTriggerCells, + l1thgcfirmware::HGCalTriggerCellSAShrPtrCollection& unclusteredTriggerCells, + l1thgcfirmware::CentroidHelperPtrCollection& readoutFlags) const; + void triggerCellToCluster(const l1thgcfirmware::HGCalTriggerCellSAShrPtrCollection& clusteredTriggerCells, + l1thgcfirmware::HGCalClusterSAPtrCollection& clustersOut) const; + + const l1thgcfirmware::ClusterAlgoConfig& config_; + }; +} // namespace l1thgcfirmware + +#endif \ No newline at end of file diff --git a/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoSeeding_SA.h b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoSeeding_SA.h new file mode 100644 index 0000000000000..395bcfba19873 --- /dev/null +++ b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoSeeding_SA.h @@ -0,0 +1,39 @@ +#ifndef __L1Trigger_L1THGCal_HGCalHistoSeeding_h__ +#define __L1Trigger_L1THGCal_HGCalHistoSeeding_h__ + +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalTriggerCell_SA.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistogramCell_SA.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusteringConfig_SA.h" + +namespace l1thgcfirmware { + + class HGCalHistoSeeding { + public: + HGCalHistoSeeding(const l1thgcfirmware::ClusterAlgoConfig& config); + ~HGCalHistoSeeding() {} + + void runSeeding(const l1thgcfirmware::HGCalTriggerCellSAPtrCollection& triggerCellsIn, + l1thgcfirmware::HGCalHistogramCellSAPtrCollection& histogramOut) const; + + private: + // Histogram steps + void triggerCellToHistogramCell(const l1thgcfirmware::HGCalTriggerCellSAPtrCollection& triggerCellsIn, + l1thgcfirmware::HGCalHistogramCellSAPtrCollection& histogramOut) const; + void makeHistogram(const l1thgcfirmware::HGCalHistogramCellSAPtrCollection& histogramCells, + l1thgcfirmware::HGCalHistogramCellSAPtrCollection& histogramOut) const; + + // Smearing steps + void smearHistogram1D(l1thgcfirmware::HGCalHistogramCellSAPtrCollection& histogram) const; + void normalizeArea(l1thgcfirmware::HGCalHistogramCellSAPtrCollection& histogram) const; + void smearHistogram2D(l1thgcfirmware::HGCalHistogramCellSAPtrCollection& histogram) const; + + // Maxima finding + void thresholdMaximaFinder(l1thgcfirmware::HGCalHistogramCellSAPtrCollection& histogram) const; + void localMaximaFinder(l1thgcfirmware::HGCalHistogramCellSAPtrCollection& histogram) const; + void calculateAveragePosition(l1thgcfirmware::HGCalHistogramCellSAPtrCollection& histogram) const; + + const l1thgcfirmware::ClusterAlgoConfig& config_; + }; +} // namespace l1thgcfirmware + +#endif \ No newline at end of file diff --git a/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistogramCell_SA.h b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistogramCell_SA.h new file mode 100644 index 0000000000000..c2f16451d51e5 --- /dev/null +++ b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistogramCell_SA.h @@ -0,0 +1,80 @@ +#ifndef L1Trigger_L1THGCal_HGCalHistogramCell_SA_h +#define L1Trigger_L1THGCal_HGCalHistogramCell_SA_h + +#include +#include +#include +namespace l1thgcfirmware { + + class HGCalHistogramCell { + public: + HGCalHistogramCell(unsigned int clock, + unsigned int index, + unsigned int S, + unsigned int X, + unsigned int Y, + unsigned int N, + unsigned int sortKey) + : clock_(clock), + index_(index), + S_(S), + X_(X), + Y_(Y), + N_(N), + sortKey_(sortKey), + frameValid_(true), + dataValid_(true) {} + + HGCalHistogramCell() + : clock_(0), index_(0), S_(0), X_(0), Y_(0), N_(0), sortKey_(0), frameValid_(false), dataValid_(false) {} + + HGCalHistogramCell(unsigned int clock, unsigned int index, unsigned int sortKey, unsigned latencyOffset) + : HGCalHistogramCell(latencyOffset * sortKey + clock, index, 0, 0, 0, 0, sortKey) {} + + ~HGCalHistogramCell() {} + + // Setters + void setClock(const unsigned int clock) { clock_ = clock; } + void addLatency(const unsigned int latency) { clock_ += latency; } + void setIndex(const unsigned int index) { index_ = index; } + void setSortKey(const unsigned int sortKey) { sortKey_ = sortKey; } + void setS(const unsigned int S) { S_ = S; } + void setX(const unsigned int X) { X_ = X; } + void setY(const unsigned int Y) { Y_ = Y; } + void setN(const unsigned int N) { N_ = N; } + + // Getters + unsigned int clock() const { return clock_; } + unsigned int index() const { return index_; } + unsigned int S() const { return S_; } + unsigned int X() const { return X_; } + unsigned int Y() const { return Y_; } + unsigned int N() const { return N_; } + unsigned int sortKey() const { return sortKey_; } + bool frameValid() const { return frameValid_; } + bool dataValid() const { return dataValid_; } + + // Operators + const HGCalHistogramCell& operator+=(const HGCalHistogramCell& hc); + const HGCalHistogramCell operator/(const unsigned int factor) const; + const HGCalHistogramCell operator+(const HGCalHistogramCell& hc) const; + + private: + unsigned int clock_; + unsigned int index_; + unsigned int S_; // Sum of cell contents i.e. total p_T in histogram bin + unsigned int + X_; // Average X coordinate of trigger cells in a cell. Will contain sum of X coordinates whilst trigger cells are being added to this cell + unsigned int + Y_; // Average X coordinate of trigger cells in a cell. Will contain sum of Y coordinates whilst trigger cells are being added to this cell + unsigned int N_; // Number of entries (trigger cells) in a cell + unsigned int sortKey_; + bool frameValid_; + bool dataValid_; + }; + + typedef std::vector HGCalHistogramCellSACollection; + typedef std::vector> HGCalHistogramCellSAPtrCollection; +} // namespace l1thgcfirmware + +#endif diff --git a/L1Trigger/L1THGCal/interface/backend_emulator/HGCalTCDistribution_SA.h b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalTCDistribution_SA.h new file mode 100644 index 0000000000000..257caf3e8e1ea --- /dev/null +++ b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalTCDistribution_SA.h @@ -0,0 +1,62 @@ +#ifndef __L1Trigger_L1THGCal_HGCalTCDistribution_h__ +#define __L1Trigger_L1THGCal_HGCalTCDistribution_h__ + +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalTriggerCell_SA.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/DistServer.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusteringConfig_SA.h" + +#include + +namespace l1thgcfirmware { + + class HGCalTCDistribution { + public: + HGCalTCDistribution(const l1thgcfirmware::ClusterAlgoConfig& config); + ~HGCalTCDistribution() {} + + void runTriggerCellDistribution(const l1thgcfirmware::HGCalTriggerCellSAPtrCollections& triggerCellsIn, + l1thgcfirmware::HGCalTriggerCellSAPtrCollection& triggerCellsOut) const; + + private: + // TC input step + void triggerCellInput(const l1thgcfirmware::HGCalTriggerCellSAPtrCollections& inputTCs, + l1thgcfirmware::HGCalTriggerCellSAShrPtrCollection& outputTCs) const; + + // TC distribution steps + void triggerCellDistribution0(const l1thgcfirmware::HGCalTriggerCellSAShrPtrCollection& triggerCellsIn) const; + void triggerCellDistribution1( + const l1thgcfirmware::HGCalTriggerCellSAShrPtrCollection& triggerCellsIn, + l1thgcfirmware::HGCalTriggerCellSAShrPtrCollections& outTriggerCellDistributionGrid) const; + void triggerCellDistribution2( + const l1thgcfirmware::HGCalTriggerCellSAShrPtrCollections& inTriggerCellDistributionGrid, + l1thgcfirmware::HGCalTriggerCellSAShrPtrCollection& triggerCellsOut, + l1thgcfirmware::HGCalTriggerCellSAShrPtrCollections& outTriggerCellDistributionGrid) const; + void triggerCellDistribution3( + const l1thgcfirmware::HGCalTriggerCellSAShrPtrCollections& inTriggerCellDistributionGrid, + l1thgcfirmware::HGCalTriggerCellSAShrPtrCollection& triggerCellsOut, + l1thgcfirmware::HGCalTriggerCellSAShrPtrCollections& outTriggerCellDistributionGrid) const; + void triggerCellDistribution4(const l1thgcfirmware::HGCalTriggerCellSAShrPtrCollection& triggerCellsIn) const; + void triggerCellDistribution5( + const l1thgcfirmware::HGCalTriggerCellSAShrPtrCollections& inTriggerCellDistributionGrid, + l1thgcfirmware::HGCalTriggerCellSAPtrCollection& triggerCellsOut) const; + + // Useful functions + void initializeTriggerCellDistGrid(l1thgcfirmware::HGCalTriggerCellSAShrPtrCollections& grid, + unsigned int nX, + unsigned int nY) const; + + void runDistServers(const l1thgcfirmware::HGCalTriggerCellSAShrPtrCollections& gridIn, + l1thgcfirmware::HGCalTriggerCellSAShrPtrCollections& gridOut, + l1thgcfirmware::HGCalTriggerCellSAShrPtrCollection& tcsOut, + unsigned int latency, + unsigned int nDistServers, + unsigned int nInputs, + unsigned int nOutputs, + unsigned int nInterleave, + bool setOutputGrid) const; + + const l1thgcfirmware::ClusterAlgoConfig& config_; + }; +} // namespace l1thgcfirmware + +#endif \ No newline at end of file diff --git a/L1Trigger/L1THGCal/interface/backend_emulator/HGCalTriggerCell_SA.h b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalTriggerCell_SA.h new file mode 100644 index 0000000000000..a8b0dd71180df --- /dev/null +++ b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalTriggerCell_SA.h @@ -0,0 +1,89 @@ +#ifndef L1Trigger_L1THGCal_HGCalTriggerCell_SA_h +#define L1Trigger_L1THGCal_HGCalTriggerCell_SA_h + +#include +#include +#include +namespace l1thgcfirmware { + + class HGCalTriggerCell { + public: + HGCalTriggerCell() : HGCalTriggerCell(false, false, 0, 0, 0, 0) {} + HGCalTriggerCell( + bool frameValid, bool dataValid, unsigned int rOverZ, unsigned int phi, unsigned int layer, unsigned int energy) + : clock_(0), + index_(0), + rOverZ_(rOverZ), + layer_(layer), + energy_(energy), + phi_(phi), + sortKey_(0), + deltaR2_(0), + dX_(0), + Y_(0), + frameValid_(frameValid), + dataValid_(dataValid), + index_cmssw_(std::pair{-1, 01}) {} + + ~HGCalTriggerCell() {} + + // Setters + void setClock(const unsigned int clock) { clock_ = clock; } + void addLatency(const unsigned int latency) { clock_ += latency; } + void setIndex(const unsigned int index) { index_ = index; } + void setSortKey(const unsigned int sortKey) { sortKey_ = sortKey; } + void setDX(const int dX) { dX_ = dX; } + void setY(const unsigned int Y) { Y_ = Y; } + void setDeltaR2(const unsigned int deltaR2) { deltaR2_ = deltaR2; } + void setCmsswIndex(const std::pair index) { index_cmssw_ = index; } + + // Getters + unsigned int clock() const { return clock_; } + unsigned int index() const { return index_; } + unsigned int rOverZ() const { return rOverZ_; } + unsigned int layer() const { return layer_; } + unsigned int energy() const { return energy_; } + unsigned int phi() const { return phi_; } + unsigned int sortKey() const { return sortKey_; } + unsigned int deltaR2() const { return deltaR2_; } + int dX() const { return dX_; } + unsigned int Y() const { return Y_; } + bool frameValid() const { return frameValid_; } + bool dataValid() const { return dataValid_; } + const std::pair& cmsswIndex() const { return index_cmssw_; } + + // Operators + bool operator==(const HGCalTriggerCell& rhs) const; + bool operator==(const std::shared_ptr& rhs) const; + + private: + unsigned int clock_; + unsigned int index_; + unsigned int rOverZ_; + unsigned int layer_; + unsigned int energy_; + unsigned int phi_; + unsigned int sortKey_; + unsigned int deltaR2_; + int dX_; + unsigned int Y_; + bool frameValid_; + bool dataValid_; + std::pair index_cmssw_; + }; + + typedef std::vector HGCalTriggerCellSACollection; + + typedef std::unique_ptr HGCalTriggerCellSAPtr; + typedef std::vector HGCalTriggerCellSAPtrCollection; + typedef std::vector > > HGCalTriggerCellSAPtrCollections; + typedef std::vector > > > HGCalTriggerCellSAPtrCollectionss; + + typedef std::shared_ptr HGCalTriggerCellSAShrPtr; + typedef std::vector HGCalTriggerCellSAShrPtrCollection; + typedef std::vector > > HGCalTriggerCellSAShrPtrCollections; + typedef std::vector > > > + HGCalTriggerCellSAShrPtrCollectionss; +} // namespace l1thgcfirmware + +#endif diff --git a/L1Trigger/L1THGCal/plugins/backend/HGCalBackendLayer2Processor3DClustering_SA.cc b/L1Trigger/L1THGCal/plugins/backend/HGCalBackendLayer2Processor3DClustering_SA.cc index 06c04a020d93a..fa6d976fd822b 100644 --- a/L1Trigger/L1THGCal/plugins/backend/HGCalBackendLayer2Processor3DClustering_SA.cc +++ b/L1Trigger/L1THGCal/plugins/backend/HGCalBackendLayer2Processor3DClustering_SA.cc @@ -51,7 +51,7 @@ class HGCalBackendLayer2Processor3DClusteringSA : public HGCalBackendLayer2Proce l1t::HGCalClusterBxCollection& rejectedClusters = be_output.second; /* create a persistent vector of pointers to the trigger-cells */ - std::unordered_map>> tcs_per_fpga; + std::unordered_map>>> tcs_per_fpga; for (unsigned i = 0; i < collHandle->size(); ++i) { edm::Ptr tc_ptr(collHandle, i); @@ -62,26 +62,38 @@ class HGCalBackendLayer2Processor3DClusteringSA : public HGCalBackendLayer2Proce HGCalTriggerGeometryBase::geom_set stage2_fpgas = distributor_.getStage2FPGAs(stage1_fpga, possible_stage2_fpgas, tc_ptr); + // Determine the 60 degree sector within the 180 S2 sector + HGCalTriggerBackendDetId stage1_fpga_id(stage1_fpga); + auto stage1_sector = stage1_fpga_id.sector(); + bool isDuplicatedRegion = stage2_fpgas.size() > 1; for (auto& fpga : stage2_fpgas) { - tcs_per_fpga[fpga].push_back(tc_ptr); + HGCalTriggerBackendDetId stage2_fpga_id(fpga); + auto stage2_sector = stage2_fpga_id.sector(); + unsigned sector60 = 999; + if (!isDuplicatedRegion) + sector60 = 1; + else if (stage2_fpga_id.zside() == 1) { + sector60 = (stage2_sector == stage1_sector) ? 0 : 2; + } else { + sector60 = (stage2_sector == stage1_sector) ? 0 : 2; + } + + if (tcs_per_fpga[fpga].empty()) { + tcs_per_fpga[fpga].resize(3); + } + tcs_per_fpga[fpga][sector60].push_back(tc_ptr); } } // Configuration const std::pair configuration{geometry(), conf_}; - multiclusteringHistoClusteringWrapper_->configure(configuration); multiclusteringSortingTruncationWrapper_->configure(configuration); for (auto& fpga_tcs : tcs_per_fpga) { - /* create a vector of seed positions and their energy*/ - std::vector> seedPositionsEnergy; - /* call to multiclustering and compute shower shape*/ - multiclusteringHistoSeeding_->findHistoSeeds(fpga_tcs.second, seedPositionsEnergy); // Inputs - std::pair>&, const std::vector>&> - inputClustersAndSeeds{fpga_tcs.second, seedPositionsEnergy}; + const std::vector>>& inputClusters_perFPGA{fpga_tcs.second}; // Outputs l1t::HGCalMulticlusterBxCollection collCluster3D_perFPGA; l1t::HGCalMulticlusterBxCollection collCluster3D_perFPGA_sorted; @@ -90,19 +102,18 @@ class HGCalBackendLayer2Processor3DClusteringSA : public HGCalBackendLayer2Proce std::pair outputMulticlustersAndRejectedClusters_perFPGA{collCluster3D_perFPGA, rejectedClusters_perFPGA}; + HGCalTriggerBackendDetId stage2_fpga_id(fpga_tcs.first); + const auto stage2_sector = stage2_fpga_id.sector(); + const auto zSide = stage2_fpga_id.zside(); + const auto clusteringConfig = std::make_tuple(geometry(), std::ref(conf_), stage2_sector, zSide); + multiclusteringHistoClusteringWrapper_->configure(clusteringConfig); + // Process - multiclusteringHistoClusteringWrapper_->process(inputClustersAndSeeds, + multiclusteringHistoClusteringWrapper_->process(inputClusters_perFPGA, outputMulticlustersAndRejectedClusters_perFPGA); - multiclusteringSortingTruncationWrapper_->process(collCluster3D_perFPGA, collCluster3D_perFPGA_sorted); - // Call all the energy interpretation modules on the cluster collection - for (const auto& interpreter : energy_interpreters_) { - interpreter->setGeometry(geometry()); - interpreter->interpret(collCluster3D_perFPGA_sorted); - } - - for (const auto& collcluster : collCluster3D_perFPGA_sorted) { + for (const auto& collcluster : collCluster3D_perFPGA) { collCluster3D_sorted.push_back(0, collcluster); } for (const auto& rejectedcluster : rejectedClusters_perFPGA) { diff --git a/L1Trigger/L1THGCal/plugins/backend/HGCalHistoClusteringWrapper.cc b/L1Trigger/L1THGCal/plugins/backend/HGCalHistoClusteringWrapper.cc index 9ee9e48035b69..c7126ddaeda5b 100644 --- a/L1Trigger/L1THGCal/plugins/backend/HGCalHistoClusteringWrapper.cc +++ b/L1Trigger/L1THGCal/plugins/backend/HGCalHistoClusteringWrapper.cc @@ -1,17 +1,19 @@ #include "FWCore/ParameterSet/interface/ParameterSet.h" #include "L1Trigger/L1THGCal/interface/HGCalAlgoWrapperBase.h" -#include "L1Trigger/L1THGCal/interface/backend/HGCalHistoClusteringImpl_SA.h" #include "DataFormats/L1THGCal/interface/HGCalCluster.h" #include "DataFormats/L1THGCal/interface/HGCalMulticluster.h" -#include "L1Trigger/L1THGCal/interface/backend/HGCalCluster_SA.h" -#include "L1Trigger/L1THGCal/interface/backend/HGCalSeed_SA.h" -#include "L1Trigger/L1THGCal/interface/backend/HGCalMulticluster_SA.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusteringImpl_SA.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusteringConfig_SA.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalTriggerCell_SA.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalCluster_SA.h" +#include "DataFormats/ForwardDetId/interface/HGCalTriggerBackendDetId.h" #include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "Geometry/Records/interface/CaloGeometryRecord.h" #include "L1Trigger/L1THGCal/interface/HGCalTriggerGeometryBase.h" #include "L1Trigger/L1THGCal/interface/HGCalTriggerTools.h" @@ -21,166 +23,375 @@ class HGCalHistoClusteringWrapper : public HGCalHistoClusteringWrapperBase { ~HGCalHistoClusteringWrapper() override {} void configure( - const std::pair& configuration) override; + const std::tuple& + configuration) override; - void process(const std::pair>, - const std::vector>>& inputClustersAndSeeds, + void process(const std::vector>>& inputClusters, std::pair& outputMulticlustersAndRejectedClusters) const override; private: - void convertCMSSWInputs(const std::vector>& clustersPtrs, - l1thgcfirmware::HGCalClusterSACollection& clusters_SA, - const std::vector>& seeds, - l1thgcfirmware::HGCalSeedSACollection& seeds_SA) const; - void convertAlgorithmOutputs(const l1thgcfirmware::HGCalMulticlusterSACollection& multiclusters_out, - const l1thgcfirmware::HGCalClusterSACollection& rejected_clusters_out, - const std::vector>& clustersPtrs, - l1t::HGCalMulticlusterBxCollection& multiclusters, - l1t::HGCalClusterBxCollection& rejected_clusters) const; - - void clusterizeHisto(const l1thgcfirmware::HGCalClusterSACollection& inputClusters, - const l1thgcfirmware::HGCalSeedSACollection& inputSeeds, - l1thgcfirmware::HGCalMulticlusterSACollection& outputMulticlusters, - l1thgcfirmware::HGCalClusterSACollection& outputRejectedClusters) const; + void convertCMSSWInputs(const std::vector>>& clustersPtrs, + l1thgcfirmware::HGCalTriggerCellSAPtrCollections& clusters_SA) const; + void convertAlgorithmOutputs(l1thgcfirmware::HGCalClusterSAPtrCollection& clusterSums, + l1t::HGCalMulticlusterBxCollection& multiClusters_out, + const std::vector>>& inputClustersPtrs) const; + + void clusterizeHisto(const l1thgcfirmware::HGCalTriggerCellSAPtrCollections& triggerCells_in_SA, + l1thgcfirmware::HGCalTriggerCellSAShrPtrCollection& clusteredTCs, + l1thgcfirmware::HGCalTriggerCellSAShrPtrCollection& unclusteredTCs, + l1thgcfirmware::HGCalClusterSAPtrCollection& clusterSums) const; void setGeometry(const HGCalTriggerGeometryBase* const geom) { triggerTools_.setGeometry(geom); } - HGCalTriggerTools triggerTools_; + double rotatePhiToSectorZero(const double phi, const unsigned sector) const; + double rotatePhiFromSectorZero(const double phi, const unsigned sector) const; - HGCalHistoClusteringImplSA theAlgo_; + HGCalTriggerTools triggerTools_; l1thgcfirmware::ClusterAlgoConfig theConfiguration_; - static constexpr double kMidRadius_ = 2.3; + l1thgcfirmware::HGCalHistoClusteringImplSA theAlgo_; + + edm::ESHandle triggerGeometry_; }; HGCalHistoClusteringWrapper::HGCalHistoClusteringWrapper(const edm::ParameterSet& conf) - : HGCalHistoClusteringWrapperBase(conf), - theAlgo_(), - theConfiguration_(kMidRadius_, - conf.getParameter("dR_multicluster"), - conf.existsAs>("dR_multicluster_byLayer_coefficientA") - ? conf.getParameter>("dR_multicluster_byLayer_coefficientA") - : std::vector(), - conf.existsAs>("dR_multicluster_byLayer_coefficientB") - ? conf.getParameter>("dR_multicluster_byLayer_coefficientB") - : std::vector(), - conf.getParameter("minPt_multicluster")) {} - -void HGCalHistoClusteringWrapper::convertCMSSWInputs(const std::vector>& clustersPtrs, - std::vector& clusters_SA, - const std::vector>& seeds, - std::vector& seeds_SA) const { - clusters_SA.clear(); - clusters_SA.reserve(clustersPtrs.size()); - unsigned int clusterIndex = 0; - for (const auto& cluster : clustersPtrs) { - clusters_SA.emplace_back(cluster->centreProj().x(), - cluster->centreProj().y(), - cluster->centre().z(), - triggerTools_.zside(cluster->detId()), - triggerTools_.layerWithOffset(cluster->detId()), - cluster->eta(), - cluster->phi(), - cluster->pt(), - cluster->mipPt(), - clusterIndex); - ++clusterIndex; + : HGCalHistoClusteringWrapperBase(conf), theConfiguration_(), theAlgo_(theConfiguration_) {} + +void HGCalHistoClusteringWrapper::convertCMSSWInputs( + const std::vector>>& clustersPtrs, + l1thgcfirmware::HGCalTriggerCellSAPtrCollections& clusters_SA) const { + // Convert trigger cells to format required by emulator + l1thgcfirmware::HGCalTriggerCellSAPtrCollections clusters_SA_perSector60(3); + unsigned iSector60 = 0; + + for (const auto& sector60 : clustersPtrs) { + unsigned iCluster = 0; + for (const auto& cluster : sector60) { + + const GlobalPoint& position = cluster->position(); + double x = position.x(); + double y = position.y(); + double z = position.z(); + unsigned int digi_rOverZ = (std::sqrt(x * x + y * y) / std::abs(z)) * theConfiguration_.rOverZNValues() / + theConfiguration_.rOverZRange(); + + if (z > 0) + x = -x; + double phi = std::atan2(y, x); + // Rotate phi to sector 0 + auto sector = theConfiguration_.sector(); + phi = rotatePhiToSectorZero(phi, sector); + + // Ignore TCs that are outside of the nominal 180 degree S2 sector + // Assume these cannot be part of a cluster found within the central 120 degrees of the S2 sector? + if (phi < 0 || phi > M_PI) { + continue; + } + + unsigned int digi_phi = (phi)*theConfiguration_.phiNValues() / theConfiguration_.phiRange(); + unsigned int digi_energy = (cluster->pt()) * theConfiguration_.ptDigiFactor(); + + // The existing S2 firmware is assuming the TCs on one S1->S2 link originate from + // a 60 degree region of a S1 sector, and the links from one 60 degree region + // are grouped together (the first 24 links are for 0-60 degrees etc. ) + // But some of the TCs in the S1 emulation fall outside of the 60 degree region + // For now, assign these TCs to the 60 degree sector that the S2 emulation is expecting them to be in. + unsigned tcSector60 = iSector60; + const unsigned sectorPhiWidth = theConfiguration_.phiNValues()/3; + unsigned int minSectorPhi = iSector60 * sectorPhiWidth; + unsigned int maxSectorPhi = (iSector60 + 1) * sectorPhiWidth; + if (digi_phi < minSectorPhi) { + tcSector60 -= 1; + } else if (digi_phi > maxSectorPhi) { + tcSector60 += 1; + } + + clusters_SA_perSector60[tcSector60].emplace_back(std::make_unique( + true, true, digi_rOverZ, digi_phi, triggerTools_.layerWithOffset(cluster->detId()), digi_energy)); + clusters_SA_perSector60[tcSector60].back()->setCmsswIndex(std::pair{iSector60, iCluster}); + ++iCluster; + } + ++iSector60; } - seeds_SA.clear(); - seeds_SA.reserve(seeds.size()); - for (const auto& seed : seeds) { - seeds_SA.emplace_back(seed.first.x(), seed.first.y(), seed.first.z(), seed.second); + // Distribute trigger cells to links and frames + // Current firmware expects trigger cells from each S1 FPGA are ordered by r/z in time (r/z increase with frame number), and links from same 60 degree sector are grouped together + // As first (optimistic) step, all trigger cells within a 60 degree sector are combined and sorted in r/z + // Ultimately, links/ordering in time should come from S1 emulation + // Sort by r/z in each 60 degree sector + for (auto& clusters : clusters_SA_perSector60) { + std::sort(clusters.begin(), + clusters.end(), + [](const l1thgcfirmware::HGCalTriggerCellSAPtr& a, const l1thgcfirmware::HGCalTriggerCellSAPtr& b) { + return a->rOverZ() < b->rOverZ(); + }); + } + + // Distribute to links + clusters_SA.clear(); + const unsigned empty_frames = 2; + clusters_SA.resize(theConfiguration_.maxClustersPerLink() + empty_frames); + for (auto& clusters : clusters_SA) { + for (unsigned int iCluster = 0; iCluster < theConfiguration_.nInputLinks(); ++iCluster) { + clusters.push_back(std::make_unique()); + } + } + iSector60 = 0; + unsigned int nLinksPerSector60 = theConfiguration_.nInputLinks() / 3; + for (auto& sector60 : clusters_SA_perSector60) { + unsigned iCluster = 0; + for (auto& cluster : sector60) { + const unsigned empty_frames = 2; + unsigned frame = empty_frames + iCluster / nLinksPerSector60; + unsigned link = iCluster % nLinksPerSector60 + iSector60 * nLinksPerSector60; + if (frame >= theConfiguration_.maxClustersPerLink() + empty_frames) + break; + clusters_SA[frame][link] = std::move(cluster); + ++iCluster; + } + ++iSector60; } } void HGCalHistoClusteringWrapper::convertAlgorithmOutputs( - const std::vector& multiclusters_out, - const std::vector& rejected_clusters_out, - const std::vector>& clustersPtrs, - l1t::HGCalMulticlusterBxCollection& multiclustersBXCollection, - l1t::HGCalClusterBxCollection& rejected_clusters) const { - // Not doing completely the correct thing here - // Taking the multiclusters from the stand alone emulation - // Getting their consistuent clusters (stand alone objects) - // Linking back to the original CMSSW-type cluster - // And creating a CMSSW-type multicluster based from these clusters - // So the output multiclusters will not be storing bit accurate quantities (or whatever was derived by the stand along emulation) - // As these inherit from L1Candidate, could set their HW quantities to the bit accurate ones - for (const auto& rejected_cluster : rejected_clusters_out) { - rejected_clusters.push_back(0, *clustersPtrs.at(rejected_cluster.index_cmssw())); - } + l1thgcfirmware::HGCalClusterSAPtrCollection& clusterSums, + l1t::HGCalMulticlusterBxCollection& multiClusters_out, + const std::vector>>& inputClustersPtrs) const { + for (const auto& cluster : clusterSums) { - std::vector multiclusters; - multiclusters.reserve(multiclusters_out.size()); - for (unsigned int imulticluster = 0; imulticluster < multiclusters_out.size(); ++imulticluster) { - bool firstConstituent = true; - for (const auto& constituent : multiclusters_out[imulticluster].constituents()) { - if (firstConstituent) { - multiclusters.emplace_back(clustersPtrs.at(constituent.index_cmssw()), 1.); - } else { - multiclusters.at(imulticluster).addConstituent(clustersPtrs.at(constituent.index_cmssw()), 1.); - } - firstConstituent = false; + if (cluster->w() == 0 || cluster->e() == 0) + continue; + + // Convert to format expected by L1T + const auto hwData = cluster->convertToL1TFormat( theConfiguration_ ); + + // Remove if below pt threshold + double pt = l1thgcfirmware::Scales::floatEt(hwData.e); + if ( pt <= theConfiguration_.minClusterPtOut()) + continue; + + double eta = l1thgcfirmware::Scales::floatEta(hwData.w_eta); + eta *= theConfiguration_.zSide(); + + auto sector = theConfiguration_.sector(); + + double phi = l1thgcfirmware::Scales::floatPhi(hwData.w_phi); + phi = rotatePhiFromSectorZero(phi, sector); + if (theConfiguration_.zSide() == 1) { + phi = M_PI - phi; + } + phi -= (phi > M_PI) ? 2 * M_PI : 0; + math::PtEtaPhiMLorentzVector clusterP4(pt, eta, phi, 0.); + l1t::HGCalMulticluster multicluster; + multicluster.setP4(clusterP4); + + for (const auto& tc : cluster->constituents()) { + const auto& tc_cmssw = inputClustersPtrs.at(tc->cmsswIndex().first).at(tc->cmsswIndex().second); + // Add tc as constituent, but don't update any other properties of the multicluster i.e. leave them unchanged from those calculated by the emulator + multicluster.addConstituent(tc_cmssw, false, 0.); } - } - for (const auto& multicluster : multiclusters) { - multiclustersBXCollection.push_back(0, multicluster); + double emIntfraction = float(hwData.e_em) / hwData.e * multicluster.energy(); // Hack to get multicluster.iPt to return hwData.e_em + multicluster.saveEnergyInterpretation(l1t::HGCalMulticluster::EnergyInterpretation::EM, + emIntfraction); + + // double emCoreIntfraction = float(cluster->e_em_core()) / cluster->e(); + // multicluster.saveEnergyInterpretation(l1t::HGCalMulticluster::EnergyInterpretation::EM_CORE, + // emCoreIntfraction * multicluster.energy()); + + // double emHEarlyIntfraction = float(cluster->e_h_early()) / cluster->e(); + // multicluster.saveEnergyInterpretation(l1t::HGCalMulticluster::EnergyInterpretation::H_EARLY, + // emHEarlyIntfraction * multicluster.energy()); + + multicluster.zBarycenter(l1thgcfirmware::Scales::floatZ(hwData.w_z)); + + multicluster.sigmaRRTot( l1thgcfirmware::Scales::floatSigmaRozRoz(hwData.sigma_roz) ); + + // Set cluster shower shape properties + multicluster.showerLength(cluster->showerLen()); + multicluster.coreShowerLength(cluster->coreShowerLen()); + multicluster.firstLayer(cluster->firstLayer()); + multicluster.hw_sigma_e_quotient(cluster->sigma_e_quotient()); + multicluster.hw_sigma_e_fraction(cluster->sigma_e_fraction()); + multicluster.hw_mean_z_quotient(cluster->mean_z_quotient()); + multicluster.hw_mean_z_fraction(cluster->mean_z_fraction()); + multicluster.hw_mean_phi_quotient(cluster->mean_phi_quotient()); + multicluster.hw_mean_phi_fraction(cluster->mean_phi_fraction()); + multicluster.hw_mean_eta_quotient(cluster->mean_eta_quotient()); + multicluster.hw_mean_eta_fraction(cluster->mean_eta_fraction()); + multicluster.hw_mean_roz_quotient(cluster->mean_roz_quotient()); + multicluster.hw_mean_roz_fraction(cluster->mean_roz_fraction()); + multicluster.hw_sigma_z_quotient(cluster->sigma_z_quotient()); + multicluster.hw_sigma_z_fraction(cluster->sigma_z_fraction()); + multicluster.hw_sigma_phi_quotient(cluster->sigma_phi_quotient()); + multicluster.hw_sigma_phi_fraction(cluster->sigma_phi_fraction()); + multicluster.hw_sigma_eta_quotient(cluster->sigma_eta_quotient()); + multicluster.hw_sigma_eta_fraction(cluster->sigma_eta_fraction()); + multicluster.hw_sigma_roz_quotient(cluster->sigma_roz_quotient()); + multicluster.hw_sigma_roz_fraction(cluster->sigma_roz_fraction()); + multicluster.hw_e_em_over_e_quotient(cluster->e_em_over_e_quotient()); + multicluster.hw_e_em_over_e_fraction(cluster->e_em_over_e_fraction()); + multicluster.hw_e_em_core_over_e_em_quotient(cluster->e_em_core_over_e_em_quotient()); + multicluster.hw_e_em_core_over_e_em_fraction(cluster->e_em_core_over_e_em_fraction()); + multicluster.hw_e_h_early_over_e_quotient(cluster->e_h_early_over_e_quotient()); + multicluster.hw_e_h_early_over_e_fraction(cluster->e_h_early_over_e_fraction()); + + + multicluster.setHwData( hwData.pack() ); + multicluster.setHwSector( sector ); + multicluster.setHwZSide( theConfiguration_.zSide() ); + + const auto unpacked = l1thgcfirmware::HGCalCluster_HW::unpack(multicluster.getHwData()); + if ( hwData != unpacked ) { + std::cout << "Problem in unpacking words!" << std::endl; + } + + const auto hwClusterSumData = cluster->formatClusterSumWords( theConfiguration_ ); + multicluster.setHwClusterSumData( hwClusterSumData ); + + multiClusters_out.push_back(0, multicluster); } } -void HGCalHistoClusteringWrapper::process( - const std::pair>, const std::vector>>& - inputClustersAndSeeds, - std::pair& - outputMulticlustersAndRejectedClusters) const { - l1thgcfirmware::HGCalClusterSACollection clusters_SA; - l1thgcfirmware::HGCalSeedSACollection seeds_SA; - convertCMSSWInputs(inputClustersAndSeeds.first, clusters_SA, inputClustersAndSeeds.second, seeds_SA); - - l1thgcfirmware::HGCalClusterSACollection rejected_clusters_finalized_SA; - l1thgcfirmware::HGCalMulticlusterSACollection multiclusters_finalized_SA; - clusterizeHisto(clusters_SA, seeds_SA, multiclusters_finalized_SA, rejected_clusters_finalized_SA); - - convertAlgorithmOutputs(multiclusters_finalized_SA, - rejected_clusters_finalized_SA, - inputClustersAndSeeds.first, - outputMulticlustersAndRejectedClusters.first, - outputMulticlustersAndRejectedClusters.second); +void HGCalHistoClusteringWrapper::process(const std::vector>>& inputClusters, + std::pair& + outputMulticlustersAndRejectedClusters) const { + l1thgcfirmware::HGCalTriggerCellSAPtrCollections triggerCells_in_SA; + convertCMSSWInputs(inputClusters, triggerCells_in_SA); + + l1thgcfirmware::HGCalTriggerCellSAShrPtrCollection clusteredTCs_out_SA; + l1thgcfirmware::HGCalTriggerCellSAShrPtrCollection unclusteredTCs_out_SA; + l1thgcfirmware::HGCalClusterSAPtrCollection clusterSums_out_SA; + clusterizeHisto(triggerCells_in_SA, clusteredTCs_out_SA, unclusteredTCs_out_SA, clusterSums_out_SA); + + convertAlgorithmOutputs(clusterSums_out_SA, outputMulticlustersAndRejectedClusters.first, inputClusters); } void HGCalHistoClusteringWrapper::clusterizeHisto( - const l1thgcfirmware::HGCalClusterSACollection& inputClusters, - const l1thgcfirmware::HGCalSeedSACollection& inputSeeds, - l1thgcfirmware::HGCalMulticlusterSACollection& outputMulticlusters, - l1thgcfirmware::HGCalClusterSACollection& outputRejectedClusters) const { - // Call SA clustering - std::vector rejected_clusters_vec_SA; - std::vector multiclusters_vec_SA = - theAlgo_.clusterSeedMulticluster_SA(inputClusters, inputSeeds, rejected_clusters_vec_SA, theConfiguration_); - - theAlgo_.finalizeClusters_SA( - multiclusters_vec_SA, rejected_clusters_vec_SA, outputMulticlusters, outputRejectedClusters, theConfiguration_); + const l1thgcfirmware::HGCalTriggerCellSAPtrCollections& triggerCells_in_SA, + l1thgcfirmware::HGCalTriggerCellSAShrPtrCollection& clusteredTCs, + l1thgcfirmware::HGCalTriggerCellSAShrPtrCollection& unclusteredTCs, + l1thgcfirmware::HGCalClusterSAPtrCollection& clusterSums) const { + theAlgo_.runAlgorithm(triggerCells_in_SA, clusteredTCs, clusterSums); } void HGCalHistoClusteringWrapper::configure( - const std::pair& configuration) { - setGeometry(configuration.first); - - // theConfiguration_.setParameters( ... ); - - if ((!theConfiguration_.dr_byLayer_coefficientA().empty() && - (theConfiguration_.dr_byLayer_coefficientA().size() - 1) < triggerTools_.lastLayerBH()) || - (!theConfiguration_.dr_byLayer_coefficientB().empty() && - (theConfiguration_.dr_byLayer_coefficientB().size() - 1) < triggerTools_.lastLayerBH())) { - throw cms::Exception("Configuration") - << "The per-layer dR values go up to " << (theConfiguration_.dr_byLayer_coefficientA().size() - 1) << "(A) and " - << (theConfiguration_.dr_byLayer_coefficientB().size() - 1) << "(B), while layers go up to " - << triggerTools_.lastLayerBH() << "\n"; - } + const std::tuple& + configuration) { + setGeometry(std::get<0>(configuration)); + + theConfiguration_.setNTriggerLayers(std::get<0>(configuration)->lastTriggerLayer()); + theConfiguration_.setTriggerLayers(std::get<0>(configuration)->triggerLayers()); + + // std::cout << "N trigger layers : " << theConfiguration_.nTriggerLayers() << std::endl; + // for ( const auto& layer : theConfiguration_.triggerLayers() ) { + // std::cout << layer << " "; + // } + // std::cout << std::endl; + theConfiguration_.setSector(std::get<2>(configuration)); + theConfiguration_.setZSide(std::get<3>(configuration)); + + const edm::ParameterSet pset = std::get<1>(configuration) + .getParameterSet("C3d_parameters") + .getParameterSet("histoMax_C3d_clustering_parameters") + .getParameterSet("layer2FwClusteringParameters"); + + theConfiguration_.setClusterizerOffset(pset.getParameter("clusterizerOffset")); + theConfiguration_.setStepLatencies(pset.getParameter>("stepLatencies")); + theConfiguration_.setCClocks(pset.getParameter("cClocks")); + theConfiguration_.setCInputs(pset.getParameter("cInputs")); + theConfiguration_.setCInputs2(pset.getParameter("cInputs2")); + theConfiguration_.setCInt(pset.getParameter("cInt")); + theConfiguration_.setCColumns(pset.getParameter("cColumns")); + theConfiguration_.setCRows(pset.getParameter("cRows")); + theConfiguration_.setROverZHistOffset(pset.getParameter("rOverZHistOffset")); + theConfiguration_.setROverZBinSize(pset.getParameter("rOverZBinSize")); + theConfiguration_.setDepths(pset.getParameter>("depths")); + theConfiguration_.setLayerWeights_E(pset.getParameter>("layerWeights_E")); + theConfiguration_.setLayerWeights_E_EM(pset.getParameter>("layerWeights_E_EM")); + theConfiguration_.setLayerWeights_E_EM_core(pset.getParameter>("layerWeights_E_EM_core")); + theConfiguration_.setLayerWeights_E_H_early(pset.getParameter>("layerWeights_E_H_early")); + theConfiguration_.setCorrection(pset.getParameter("correction")); + theConfiguration_.setSaturation(pset.getParameter("saturation")); + const edm::ParameterSet& thresholdParams = pset.getParameterSet("thresholdMaximaParams"); + theConfiguration_.setThresholdParams(thresholdParams.getParameter("a"), + thresholdParams.getParameter("b"), + thresholdParams.getParameter("c")); + + // Digitization parameters + const edm::ParameterSet& digitizationPset = pset.getParameterSet("digiParams"); + theConfiguration_.setROverZRange(digitizationPset.getParameter("rOverZRange")); + theConfiguration_.setROverZNValues(digitizationPset.getParameter("rOverZNValues")); + theConfiguration_.setPhiRange(digitizationPset.getParameter("phiRange")); + theConfiguration_.setPhiNValues(digitizationPset.getParameter("phiNValues")); + theConfiguration_.setPtDigiFactor(digitizationPset.getParameter("ptDigiFactor")); + + // Parameters for selecting output clusters + theConfiguration_.setMinClusterPtOut(pset.getParameter("minClusterPtOut")); + + // Input links parameters + const edm::ParameterSet& inputLinksPset = pset.getParameterSet("inputLinkParams"); + theConfiguration_.setMaxClustersPerLink(inputLinksPset.getParameter("maxClustersPerLink")); + theConfiguration_.setNInputLinks(inputLinksPset.getParameter("nInputLinks")); + + // TC distribution parameters + const edm::ParameterSet& tcDistPset = pset.getParameterSet("tcDistParams"); + theConfiguration_.setN60Sectors(tcDistPset.getParameter("n60Sectors")); + theConfiguration_.setNCoarsePhiDist1(tcDistPset.getParameter("nCoarsePhiRegionsDist1")); + theConfiguration_.setNDistServers1(tcDistPset.getParameter("nDistServers1")); + theConfiguration_.setDistServer1_nIn(tcDistPset.getParameter("distServer1_nIn")); + theConfiguration_.setDistServer1_nOut(tcDistPset.getParameter("distServer1_nOut")); + theConfiguration_.setDistServer1_nInterleave(tcDistPset.getParameter("distServer1_nInterleave")); + theConfiguration_.setNCoarsePhiDist2(tcDistPset.getParameter("nCoarsePhiRegionsDist2")); + theConfiguration_.setNDistServers2(tcDistPset.getParameter("nDistServers2")); + theConfiguration_.setDistServer2_nIn(tcDistPset.getParameter("distServer2_nIn")); + theConfiguration_.setDistServer2_nOut(tcDistPset.getParameter("distServer2_nOut")); + theConfiguration_.setDistServer2_nInterleave(tcDistPset.getParameter("distServer2_nInterleave")); + + // Smearing parameters + const edm::ParameterSet& smearingPset = pset.getParameterSet("smearingParams"); + theConfiguration_.setMaxBinsSmearing1D(smearingPset.getParameter("maxBinsSmearing1D")); + theConfiguration_.setNBitsAreaNormLUT(smearingPset.getParameter("nBitsAreaNormLUT")); + + // Clusterizer parameters + const edm::ParameterSet& clusterizerPset = pset.getParameterSet("clusterizerParams"); + theConfiguration_.setNBinsCosLUT(clusterizerPset.getParameter("nBinsCosLUT")); + theConfiguration_.setNBitsCosLUT(clusterizerPset.getParameter("nBitsCosLUT")); + theConfiguration_.setNFifos(clusterizerPset.getParameter("nFifos")); + theConfiguration_.setNColumnsPerFifo(clusterizerPset.getParameter("nColumnsPerFifo")); + theConfiguration_.setClusterizerMagicTime(clusterizerPset.getParameter("clusterizerMagicTime")); + theConfiguration_.setFirstSeedBin(clusterizerPset.getParameter("firstSeedBin")); + theConfiguration_.setNColumnFifoVeto(clusterizerPset.getParameter("nColumnsFifoVeto")); + theConfiguration_.setDeltaR2Thresholds(clusterizerPset.getParameter>("deltaR2Thresholds")); + theConfiguration_.setNColumnsForClustering(clusterizerPset.getParameter("nColumnsForClustering")); + theConfiguration_.setNRowsForClustering(clusterizerPset.getParameter("nRowsForClustering")); + + theConfiguration_.initializeLUTs(); }; +double HGCalHistoClusteringWrapper::rotatePhiToSectorZero(const double phi, const unsigned sector) const { + double rotatedPhi = phi; + if (sector == 1) { + if (rotatedPhi < M_PI and rotatedPhi > 0) + rotatedPhi = rotatedPhi - (2. * M_PI / 3.); + else + rotatedPhi = rotatedPhi + (4. * M_PI / 3.); + } else if (sector == 2) { + rotatedPhi = rotatedPhi + (2. * M_PI / 3.); + } + return rotatedPhi; +} + +double HGCalHistoClusteringWrapper::rotatePhiFromSectorZero(const double phi, const unsigned sector) const { + double rotatedPhi = phi; + if (sector == 1) { + rotatedPhi += (2. * M_PI / 3.); + } else if (sector == 2) { + rotatedPhi += (4. * M_PI / 3.); + } + return rotatedPhi; +} + DEFINE_EDM_PLUGIN(HGCalHistoClusteringWrapperBaseFactory, HGCalHistoClusteringWrapper, "HGCalHistoClusteringWrapper"); diff --git a/L1Trigger/L1THGCal/plugins/geometries/HGCalTriggerGeometryV9Imp2.cc b/L1Trigger/L1THGCal/plugins/geometries/HGCalTriggerGeometryV9Imp2.cc index f57f322f96be1..e4a779a0240b4 100644 --- a/L1Trigger/L1THGCal/plugins/geometries/HGCalTriggerGeometryV9Imp2.cc +++ b/L1Trigger/L1THGCal/plugins/geometries/HGCalTriggerGeometryV9Imp2.cc @@ -59,6 +59,7 @@ class HGCalTriggerGeometryV9Imp2 : public HGCalTriggerGeometryBase { bool disconnectedModule(const unsigned) const final; unsigned lastTriggerLayer() const final { return last_trigger_layer_; } unsigned triggerLayer(const unsigned) const final; + const std::vector& triggerLayers() const final { return trigger_layers_; } private: // HSc trigger cell grouping diff --git a/L1Trigger/L1THGCal/plugins/geometries/HGCalTriggerGeometryV9Imp3.cc b/L1Trigger/L1THGCal/plugins/geometries/HGCalTriggerGeometryV9Imp3.cc index d4e80d16503b4..dad410b82928b 100644 --- a/L1Trigger/L1THGCal/plugins/geometries/HGCalTriggerGeometryV9Imp3.cc +++ b/L1Trigger/L1THGCal/plugins/geometries/HGCalTriggerGeometryV9Imp3.cc @@ -62,6 +62,7 @@ class HGCalTriggerGeometryV9Imp3 : public HGCalTriggerGeometryBase { bool disconnectedModule(const unsigned) const final; unsigned lastTriggerLayer() const final { return last_trigger_layer_; } unsigned triggerLayer(const unsigned) const final; + const std::vector& triggerLayers() const final { return trigger_layers_; } private: // HSc trigger cell grouping diff --git a/L1Trigger/L1THGCal/python/customNewProcessors.py b/L1Trigger/L1THGCal/python/customNewProcessors.py index d31c147e1f68a..b871ba788807a 100644 --- a/L1Trigger/L1THGCal/python/customNewProcessors.py +++ b/L1Trigger/L1THGCal/python/customNewProcessors.py @@ -2,6 +2,7 @@ from L1Trigger.L1THGCal.l1tHGCalBackEndLayer1Producer_cfi import layer1truncation_proc from L1Trigger.L1THGCal.l1tHGCalBackEndLayer1Producer_cfi import stage1truncation_proc from L1Trigger.L1THGCal.l1tHGCalBackEndLayer1Producer_cfi import truncation_params +from L1Trigger.L1THGCal.hgcalBackendLayer2_fwClustering_cfi import layer2ClusteringFw_Params def custom_layer1_truncation(process): parameters = layer1truncation_proc.clone() @@ -20,6 +21,7 @@ def custom_stage1_truncation(process): def custom_clustering_standalone(process): process.l1tHGCalBackEndLayer2Producer.ProcessorParameters.ProcessorName = cms.string('HGCalBackendLayer2Processor3DClusteringSA') process.l1tHGCalBackEndLayer2Producer.ProcessorParameters.DistributionParameters = truncation_params + process.l1tHGCalBackEndLayer2Producer.ProcessorParameters.C3d_parameters.histoMax_C3d_clustering_parameters.layer2FwClusteringParameters = layer2ClusteringFw_Params return process def custom_tower_standalone(process): diff --git a/L1Trigger/L1THGCal/python/hgcalBackendLayer2_fwClustering_cfi.py b/L1Trigger/L1THGCal/python/hgcalBackendLayer2_fwClustering_cfi.py new file mode 100644 index 0000000000000..ebeeca507c166 --- /dev/null +++ b/L1Trigger/L1THGCal/python/hgcalBackendLayer2_fwClustering_cfi.py @@ -0,0 +1,158 @@ +import FWCore.ParameterSet.Config as cms +from math import pi + +EE_DR_GROUP = 7 +FH_DR_GROUP = 6 +BH_DR_GROUP = 12 +dr_layerbylayer = ([0] + # no layer 0 + [7569]*EE_DR_GROUP + [13689]*EE_DR_GROUP + [30625]*EE_DR_GROUP + [54756]*EE_DR_GROUP + # EM + [54756]*FH_DR_GROUP + [85264]*FH_DR_GROUP + # FH + [85264]*BH_DR_GROUP) # BH + +layer2ClusteringFw_Params = cms.PSet( + # Latencies + # histogramOffset=cms.uint32(216), + clusterizerOffset=cms.uint32(276), + stepLatencies=cms.vuint32( 0, # Input + 1, # Dist0 + 1, # Dist1 + 6, # Dist2 + 0, # Dist3 + 1, # Dist4 + 7, # Dist5 + 1, # TcToHc + 216 + 1,# Hist, histogramOffset + 1 + 5, # Smearing1D + 3, # NormArea + 6, # Smearing2D + 0, # Maxima1D + 2, # Maxima2D + 6, # CalcAverage + 0, # Clusterizer + 18, # TriggerCellToCluster + 0 ), # ClusterSum + cClocks=cms.uint32(250), + cInputs=cms.uint32(72), + cInputs2=cms.uint32(75), + cInt=cms.uint32(90), + + minClusterPtOut=cms.double(0.5), + + # Digitzation parameters + digiParams = cms.PSet( + rOverZRange = cms.double(0.7982087279), + rOverZNValues = cms.double(8192), # 13 bits + phiRange = cms.double(pi), + phiNValues = cms.double(1944), # 12 bits, but range over 2pi is 3888 + # phiNValues = cms.double(3456), + ptDigiFactor = cms.double(1024), + # ptDigiFactor = cms.double(10000), + ), + + inputLinkParams = cms.PSet( + maxClustersPerLink = cms.uint32(210), + nInputLinks = cms.uint32(72) + ), + + # Trigger cell distribution parameters + tcDistParams = cms.PSet( + n60Sectors = cms.uint32(3), + nCoarsePhiRegionsDist1 = cms.uint32(6), + nDistServers1 = cms.uint32(15), + distServer1_nIn = cms.uint32(5), + distServer1_nOut = cms.uint32(6), + distServer1_nInterleave = cms.uint32(4), + nCoarsePhiRegionsDist2 = cms.uint32(6), + nDistServers2 = cms.uint32(18), + distServer2_nIn = cms.uint32(5), + distServer2_nOut = cms.uint32(6), + distServer2_nInterleave = cms.uint32(4), + ), + + # Histogram parameters + cColumns=cms.uint32(108), + cRows=cms.uint32(42), + rOverZHistOffset = cms.uint32(779), #440 # offset of first r/z bin in number of LSB + rOverZBinSize = cms.uint32(124), #64 # in number of LSB + + # Smearing parameters + smearingParams = cms.PSet( + maxBinsSmearing1D=cms.uint32(6), + nBitsAreaNormLUT=cms.uint32(17) + ), + + # Threshold maxima parameters + # Threshold for given histogram row (r/z bin) paramaterized as a+b*bin+c*bin^2 + thresholdMaximaParams = cms.PSet( + + a=cms.uint32(1843),#18000), + b=cms.int32(-42),#800), + c=cms.int32(1)#-20) + + # a=cms.uint32(1843),#18000), + # b=cms.int32(0),#800), + # c=cms.int32(0)#-20) + + # a=cms.uint32(1843),#18000), + # b=cms.uint32(82),#800), + # c=cms.int32(-2)#-20) + # a=cms.uint32(18000),#18000), + # b=cms.uint32(800),#800), + # c=cms.int32(-20)#-20) + ), + + # Clusterizer parameters + clusterizerParams = cms.PSet( + nBinsCosLUT = cms.uint32(77), # Number of entries in 1-cos(delta phi) LUT when clustering to seeds + nBitsCosLUT = cms.uint32(18), # Number of bits used in 1-cos(delta phi) LUT + nFifos=cms.uint32(18), + nColumnsPerFifo=cms.uint32(4), + firstSeedBin=cms.uint32(18), # First bin considered as a seed for a cluster + nColumnsFifoVeto=cms.uint32(6), # Minimum distance between seeds in neighbouring fifos) + # deltaR2Cut=cms.uint32(20000), # Delta R^2 threshold, in digitised units + deltaR2Thresholds=cms.vuint32( # Delta R^2 threshold per layer, in digitised units + dr_layerbylayer + # 0, + # 7569, 7569, 7569, 7569, 7569, 7569, 7569, + # 13689, 13689, 13689, 13689, 13689, 13689, 13689, + # 30625, 30625, 30625, 30625, 30625, 30625, 30625, + # 54756, 54756, 54756, 54756, 54756, 54756, 54756, 54756, 54756, 54756, 54756, 54756, 54756, + # 85264, 85264, 85264, 85264, 85264, 85264, 85264, 85264, 85264, 85264, 85264, 85264, 85264, 85264, 85264, 85264, 85264, 85264 + ), + nColumnsForClustering=cms.uint32(3), # Number of columns either side of column containing seed to stream for clustering + nRowsForClustering=cms.uint32(4), # Number of rows either side of row containing seed to consider during clustering + clusterizerMagicTime=cms.uint32(434), + ), + depths = cms.vuint32(0 , # No zero layer + 0 , 30 , 59 , 89 , 118 , 148 , 178 , 208 , 237 , 267 , 297 , 327 , 356 , 386 , # CE-E + 415 , 445 , 475 , 505 , 534 , 564 , 594 , 624 , 653 , 683 , 712 , 742 , 772 , 802 , # CE-E + 911 , 1020 , 1129 , 1238 , 1347 , 1456 , 1565 , 1674 , # CE-FH + 1783 , 1892 , 2001 , 2110 , 2281 , 2452 , 2623 , 2794 , 2965 , 3136 , 3307 , 3478 , 3649 , 3820 , # CE-BH + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ), + layerWeights_E = cms.vuint32(0 , # No zero layer + 1 , 1 , 1 , # CE-E (early) + 1 , 1 , 1 , 1 , 1 , # CE-E (core) + 1 , 1 , 1 , 1 , 1 , 1 , # CE-E (back) + 1 , 1 , 1 , 1 , # CE-H (early) + 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1), # CE-H (back) + layerWeights_E_EM = cms.vuint32(0 , # No zero layer + 252969 , 254280 , 255590 , # CE-E (early) + 256901 , 258212 , 259523 , 260833 , 262144 , # CE-E (core) + 263455 , 264765 , 266076 , 267387 , 268698 , 270008 , # CE-E (back) + 0 , 0 , 0 , 0 , # CE-H (early) + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ), # CE-H (back) + layerWeights_E_EM_core = cms.vuint32(0 , # No zero layer + 0 , 0 , 0 , # CE-E (early) + 256901 , 258212 , 259523 , 260833 , 262144 , # CE-E (core) + 0 , 0 , 0 , 0 , 0 , 0 , # CE-E (back) + 0 , 0 , 0 , 0 , # CE-H (early) + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ), # CE-H (back) + layerWeights_E_H_early = cms.vuint32( 0 , # No zero layer + 0 , 0 , 0 , # CE-E (early) + 0 , 0 , 0 , 0 , 0 , # CE-E (core) + 0 , 0 , 0 , 0 , 0 , 0 , # CE-E (back) + 1 , 1 , 1 , 1 , # CE-H (early) + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0), # CE-H + correction=cms.uint32(131071), # 0b011111111111111111 + saturation=cms.uint32((2 ** 19) - 1) # 524287 +) diff --git a/L1Trigger/L1THGCal/src/backend_emulator/DistServer.cc b/L1Trigger/L1THGCal/src/backend_emulator/DistServer.cc new file mode 100644 index 0000000000000..44619aa09e478 --- /dev/null +++ b/L1Trigger/L1THGCal/src/backend_emulator/DistServer.cc @@ -0,0 +1,61 @@ +#include "L1Trigger/L1THGCal/interface/backend_emulator/DistServer.h" + +#include +#include + +using namespace std; +using namespace l1thgcfirmware; + +DistServer::DistServer(unsigned int nInputs, unsigned int nOutputs, unsigned int nInterleaving) + : nOutputs_(nOutputs), nInterleaving_(nInterleaving), inputs_(nInputs) { + for (unsigned int iInput = 0; iInput < inputs_.size(); ++iInput) { + addr_.emplace_back(this->nInterleaving(), 0); + for (unsigned int iInterleave = 0; iInterleave < this->nInterleaving(); ++iInterleave) { + addr_[iInput][iInterleave] = iInterleave; + } + } +} + +// Main method of distribution server, executed on each clock +// Not enough documentation on distribution server vhdl to give meaningful comments +// Other than stating it's very complicated +HGCalTriggerCellSAShrPtrCollection DistServer::clock(HGCalTriggerCellSAShrPtrCollection& data) { + for (unsigned int iInput = 0; iInput < inputs_.size(); ++iInput) { + if (data[iInput]->dataValid()) { + inputs_[iInput].push_back(data[iInput]); + } + } + + vector > lMap(inputs_.size(), vector(nOutputs())); + + HGCalTriggerCellSAShrPtrCollection lInputs(inputs_.size(), std::make_shared()); + + for (unsigned int iInput = 0; iInput < inputs_.size(); ++iInput) { + unsigned int lAddr = addr_[iInput][0]; + if (lAddr < inputs_[iInput].size()) { + lInputs[iInput] = inputs_[iInput][lAddr]; + lMap[iInput][lInputs[iInput]->sortKey()] = true; + } + } + + for (unsigned int iInput = 0; iInput < inputs_.size(); ++iInput) { + vector& toRotate = addr_[iInput]; + std::rotate(toRotate.begin(), toRotate.begin() + 1, toRotate.end()); + } + + HGCalTriggerCellSAShrPtrCollection lOutputs(nOutputs(), std::make_shared()); + + unsigned int nOutputs = 0; + for (unsigned int iOutput = 0; iOutput < lOutputs.size(); ++iOutput) { + for (unsigned int iInput = 0; iInput < inputs_.size(); ++iInput) { + if (lMap[iInput][iOutput]) { + lOutputs[iOutput] = lInputs[iInput]; + addr_[iInput].back() += this->nInterleaving(); + nOutputs++; + break; + } + } + } + + return lOutputs; +} diff --git a/L1Trigger/L1THGCal/src/backend_emulator/HGCalCluster_SA.cc b/L1Trigger/L1THGCal/src/backend_emulator/HGCalCluster_SA.cc new file mode 100644 index 0000000000000..5cb2e851ae91f --- /dev/null +++ b/L1Trigger/L1THGCal/src/backend_emulator/HGCalCluster_SA.cc @@ -0,0 +1,267 @@ +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalCluster_SA.h" +#include +#include + +// Many useful functions for handling and manipulation of bitsets +// From L1 Track Finder DTC +// But could perhaps still just use ap_uint? +#include "DataFormats/L1TrackTrigger/interface/TTBV.h" + +using namespace l1thgcfirmware; + +const HGCalCluster& HGCalCluster::operator+=(HGCalCluster& c) { + // Not handling field widths + HGCalCluster original(*this); + this->set_n_tc(this->n_tc() + c.n_tc()); + this->set_e(this->e() + c.e()); + this->set_e_em(this->e_em() + c.e_em()); + this->set_e_em_core(this->e_em_core() + c.e_em_core()); + this->set_e_h_early(this->e_h_early() + c.e_h_early()); + this->set_w(this->w() + c.w()); + this->set_n_tc_w(this->n_tc_w() + c.n_tc_w()); + this->set_w2(this->w2() + c.w2()); + this->set_wz(this->wz() + c.wz()); + this->set_weta(this->weta() + c.weta()); + this->set_wphi(this->wphi() + c.wphi()); + this->set_wroz(this->wroz() + c.wroz()); + this->set_wz2(this->wz2() + c.wz2()); + this->set_weta2(this->weta2() + c.weta2()); + this->set_wphi2(this->wphi2() + c.wphi2()); + this->set_wroz2(this->wroz2() + c.wroz2()); + + this->set_layerbits(this->layerbits() | c.layerbits()); + this->set_sat_tc(this->sat_tc() | c.sat_tc()); + this->set_shapeq(this->shapeq() | c.shapeq()); + + const unsigned clusterWeightSat80 = 52428; // 52438000; // ((1 << 16) - 1) * 0.8; // 52428 + if (w_ <= clusterWeightSat80 && original.shapeq() == 1 && c.shapeq() == 1) { + this->set_shapeq(1); + } else { + this->set_shapeq(0); + + if (original.w() > c.w()) { + this->set_w(original.w()); + this->set_w2(original.w2()); + this->set_wz(original.wz()); + this->set_weta(original.weta()); + this->set_wphi(original.wphi()); + this->set_wroz(original.wroz()); + this->set_wz2(original.wz2()); + this->set_weta2(original.weta2()); + this->set_wphi2(original.wphi2()); + this->set_wroz2(original.wroz2()); + this->set_n_tc_w(original.n_tc_w()); + } else { + this->set_w(c.w()); + this->set_w2(c.w2()); + this->set_wz(c.wz()); + this->set_weta(c.weta()); + this->set_wphi(c.wphi()); + this->set_wroz(c.wroz()); + this->set_wz2(c.wz2()); + this->set_weta2(c.weta2()); + this->set_wphi2(c.wphi2()); + this->set_wroz2(c.wroz2()); + this->set_n_tc_w(c.n_tc_w()); + } + } + + for (const auto& constituent : c.constituents()) { + this->add_constituent(constituent); + } + + return *this; +} + + +HGCalCluster_HW HGCalCluster::convertToL1TFormat( const ClusterAlgoConfig& config ) { + + HGCalCluster_HW hwCluster; + + hwCluster.clear(); + formatFirstWord( config, hwCluster ); + formatSecondWord( config, hwCluster ); + formatThirdWord( config, hwCluster ); + formatFourthWord( config, hwCluster ); + + return hwCluster; +} + +void HGCalCluster::formatFirstWord( const ClusterAlgoConfig& config, HGCalCluster_HW& hwCluster ) { + hwCluster.e = Scales::HGCaltoL1_et(e()); + hwCluster.e_em = Scales::HGCaltoL1_et(e_em()); + hwCluster.fractionInCE_E = Scales::makeL1EFraction(e_em(), e()); + hwCluster.fractionInCoreCE_E = Scales::makeL1EFraction(e_em_core(), e_em()); + hwCluster.fractionInEarlyCE_E = Scales::makeL1EFraction(e_h_early(), e()); + hwCluster.setGCTBits(); + hwCluster.firstLayer = firstLayer(); + +} + +void HGCalCluster::formatSecondWord( const ClusterAlgoConfig& config, HGCalCluster_HW& hwCluster ) { + + hwCluster.w_eta = convertRozToEta( config ); + bool saturatedPhi = false; + bool nominalPhi = false; + hwCluster.w_phi = Scales::HGCaltoL1_phi(float(wphi())/w(), saturatedPhi, nominalPhi); + hwCluster.w_z = Scales::HGCaltoL1_z( float(wz()) / w() ); + hwCluster.nTC = n_tc(); + + // std::cout << "Packing phi : " << this->wphi() << " " << w() << " " << hwCluster.w_phi << " " << nominalPhi << std::endl; + + // Quality flags are placeholders at the moment + bool qualFracCE_E = e() != 0x3FFFFF && e_em() != 0x3FFFFF; + bool qualFracCoreCE_E = e_em_core() != 0x3FFFFF && e_em() != 0x3FFFFF; + bool qualFracEarlyCE_H = e_h_early() != 0x3FFFFF && e() != 0x3FFFFF; + hwCluster.setQualityFlags(qualFracCE_E, qualFracCoreCE_E, qualFracEarlyCE_H, sat_tc(), shapeq(), saturatedPhi, nominalPhi); +} + +void HGCalCluster::formatThirdWord( const ClusterAlgoConfig& config, HGCalCluster_HW& hwCluster ) { + + hwCluster.sigma_E = sigma_e_quotient() + sigma_e_fraction(); + hwCluster.lastLayer = lastLayer(); + hwCluster.showerLength = showerLen(); + hwCluster.sigma_z = sigma_z_quotient() + sigma_z_fraction(); + hwCluster.sigma_phi = sigma_phi_quotient() + sigma_phi_fraction(); + hwCluster.coreShowerLength = coreShowerLen(); + hwCluster.sigma_eta = convertSigmaRozRozToSigmaEtaEta( config ); + + unsigned int sigma_roz = round(sqrt( (float(w())*float(wroz2()) - float(wroz()) * float(wroz())) / ( float(w()) * float(w()) ) ) * 0.5073223114013672); + + // Emulation of a bug in firmware + // if ( sigma_roz >=256 ) sigma_roz -= 256; + while (sigma_roz >= 256) sigma_roz -= 256; + if ( sigma_roz > 127 ) sigma_roz = 127; + hwCluster.sigma_roz = sigma_roz; +} + +void HGCalCluster::formatFourthWord( const ClusterAlgoConfig& config, HGCalCluster_HW& hwCluster ) {} + +double HGCalCluster::convertRozToEta( const ClusterAlgoConfig& config ) { + // TODO : named constants for magic numbers + double roz = double(wroz())/w(); + if ( roz < 1026.9376220703125 ) roz = 1026.9376220703125; + else if ( roz > 5412.17138671875 ) roz = 5412.17138671875; + roz -= 1026.9376220703125; + roz *= 0.233510936; + roz = int(round(roz)); + if ( roz > 1023 ) roz = 1023; + return config.rozToEtaLUT(roz); +} + +double HGCalCluster::convertSigmaRozRozToSigmaEtaEta( const ClusterAlgoConfig& config ) { + // TODO : named constants for magic numbers + // Sigma eta eta calculation + bool debug = true; + double roz = wroz()/w(); + const double min_roz = 809.9324340820312; + const double max_roz = 4996.79833984375; + if ( roz < min_roz ) roz = min_roz; + else if ( roz > max_roz ) roz = max_roz; + roz -= min_roz; + const double scale = 0.015286154113709927; + roz *= scale; + roz = int(round(roz)); + if ( roz > 63 ) roz = 63; + + double sigmaRoz = ( w()*wroz2() - wroz() * wroz() )/0.5073223114013672; + const double scale_sigma = 0.220451220870018; + sigmaRoz *= scale_sigma; + sigmaRoz = int(round(sigmaRoz)); + if ( sigmaRoz > 63 ) roz = 63; + + unsigned int lutAddress = roz * 64 + sigmaRoz; + if ( lutAddress >= 4096 ) lutAddress = 4095; + return config.sigmaRozToSigmaEtaLUT(lutAddress); +} + + +void HGCalCluster::clearClusterSumWords() { + for ( auto& clusterSumWord : packedData_clustersSums_ ) { + clusterSumWord = 0; + } +} + +HGCalCluster::ClusterSumWords HGCalCluster::formatClusterSumWords( const ClusterAlgoConfig& config ) { + clearClusterSumWords(); + + const unsigned nb_nTCs = 10; + const unsigned nb_e = 22; + const unsigned nb_e_em = 22; + const unsigned nb_e_em_core = 22; + const unsigned nb_e_h_early = 22; + + const unsigned nb_w = 16; + const unsigned nb_n_tc_w = 10; + const unsigned nb_w2 = 32; + const unsigned nb_wz = 29; + // const unsigned nb_weta = 26; + const unsigned nb_wphi = 28; + const unsigned nb_wroz = 29; + + const unsigned nb_wz2 = 42; + // const unsigned nb_weta2 = 36; + const unsigned nb_wphi2 = 40; + const unsigned nb_wroz2 = 42; + const unsigned nb_layerbits = 34; + const unsigned nb_sat_tc = 1; + const unsigned nb_shapeq = 1; + + ap_uint hw_nTCs = n_tc(); + ap_uint hw_e = e(); + ap_uint hw_e_em = e_em(); + ap_uint hw_e_em_core = e_em_core(); + ap_uint hw_e_h_early = e_h_early(); + + ap_uint hw_w = w(); + ap_uint hw_n_tc_w = n_tc_w(); + ap_uint hw_w2 = w2(); + ap_uint hw_wz = wz(); + // ap_uint hw_weta = 0; + ap_uint hw_wphi = wphi() * 3456. / 1944; // Temp hack (another one...) + ap_uint hw_wroz = wroz(); + + ap_uint hw_wz2 = wz2(); + // ap_uint hw_weta2 = 0; + ap_uint hw_wphi2 = wphi2(); + ap_uint hw_wroz2 = wroz2(); + ap_uint hw_layerbits = layerbits(); + ap_uint hw_sat_tc = sat_tc(); + ap_uint hw_shapeq = shapeq(); + + const ap_uint clusterSumRecord = ( + hw_shapeq, + hw_sat_tc, + hw_layerbits, + hw_wroz2, + hw_wphi2, + // hw_weta2, + hw_wz2, + hw_wroz, + hw_wphi, + // hw_weta, + hw_wz, + hw_w2, + hw_n_tc_w, + hw_w, + hw_e_h_early, + hw_e_em_core, + hw_e_em, + hw_e, + hw_nTCs + ); + + for ( unsigned iWord = 0; iWord < nWordsPerClusterSum; ++iWord ) { + ClusterSumWord word = clusterSumRecord.range((iWord+1)*(clusterSumWordLength)-1,iWord*clusterSumWordLength).to_ulong(); + packedData_clustersSums_[iWord] = word; + } + // std::cout << "=== Cluster info ===" << std::endl; + // std::cout << "NTCs : " << n_tc() << " " << hw_nTCs << " " << hw_nTCs.to_string() << std::endl; + // std::cout << "E : " << e() << " " << hw_e << " " << hw_e.to_string() << std::endl; + // std::cout << "w : " << w() << " " << hw_w << " " << hw_w.to_string() << std::endl; + // std::cout << "n_tc_w : " << n_tc_w() << " " << hw_n_tc_w << " " << hw_n_tc_w.to_string() << std::endl; + // std::cout << "w2 : " << w2() << " " << hw_w2 << " " << hw_w2.to_string() << std::endl; + // std::cout << "Cluster sum record : " << clusterSumRecord << " " << clusterSumRecord.to_string()<< std::endl; + + return packedData_clustersSums_; +} \ No newline at end of file diff --git a/L1Trigger/L1THGCal/src/backend_emulator/HGCalHistoClusterProperties_SA.cc b/L1Trigger/L1THGCal/src/backend_emulator/HGCalHistoClusterProperties_SA.cc new file mode 100644 index 0000000000000..bc348f0068058 --- /dev/null +++ b/L1Trigger/L1THGCal/src/backend_emulator/HGCalHistoClusterProperties_SA.cc @@ -0,0 +1,220 @@ +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusterProperties_SA.h" + +#include +#include + +using namespace std; +using namespace l1thgcfirmware; + +HGCalHistoClusterProperties::HGCalHistoClusterProperties(const ClusterAlgoConfig& config) : config_(config) {} + +void HGCalHistoClusterProperties::runClusterProperties( + const l1thgcfirmware::HGCalClusterSAPtrCollection& protoClustersIn, + const CentroidHelperPtrCollection& readoutFlags, + HGCalClusterSAPtrCollection& clustersOut) const { + // Cluster properties + HGCalClusterSAPtrCollection clusterAccumulation; + clusterSum(protoClustersIn, readoutFlags, clusterAccumulation, clustersOut); + clusterProperties(clustersOut); +} + +// Accumulates/combines inputs cluster objects (each corresponding to one TC belonging to a cluster) into clusters (one per cluster made up of TCs) +void HGCalHistoClusterProperties::clusterSum(const HGCalClusterSAPtrCollection& protoClusters, + const CentroidHelperPtrCollection& readoutFlags, + HGCalClusterSAPtrCollection& clusterAccumulation, + HGCalClusterSAPtrCollection& clusterSums) const { + HGCalClusterSAPtrCollections protoClustersPerColumn(config_.cColumns()); + vector clock(config_.cColumns(), 0); + for (const auto& protoCluster : protoClusters) { + auto index = protoCluster->index(); + // Do we have to make a copy of protoCluster here? + protoClustersPerColumn.at(index).push_back(make_unique(*protoCluster)); + } + + map sums; + + for (const auto& flag : readoutFlags) { + auto accumulator = make_unique(0, 0, true, true); + const unsigned stepLatency = 23; + flag->setClock(flag->clock() + stepLatency); + + for (const auto& protoCluster : protoClustersPerColumn.at(flag->index())) { + if (protoCluster->clock() <= clock.at(flag->index())) + continue; + if (protoCluster->clock() > flag->clock()) + continue; + *accumulator += *protoCluster; + } + + clock.at(flag->index()) = flag->clock(); + accumulator->setClock(flag->clock()); + accumulator->setIndex(flag->index()); + accumulator->setDataValid(true); + + if (sums.find(flag->clock()) == sums.end()) { + const unsigned stepLatency = 7; + auto sum = make_unique(flag->clock() + stepLatency, 0, true, true); + sums[flag->clock()] = move(sum); + } + + *(sums.at(flag->clock())) += *accumulator; + + clusterAccumulation.push_back(move(accumulator)); + } + + for (auto& sum : sums) { + clusterSums.push_back(move(sum.second)); + } +} + +// Calculates properties of clusters from accumulated quantities +void HGCalHistoClusterProperties::clusterProperties(HGCalClusterSAPtrCollection& clusterSums) const { + unsigned int nTCs = 0; + for (auto& c : clusterSums) { + + if (c->n_tc_w() == 0) + continue; + std::pair sigmaEnergy = sigma_energy(c->n_tc_w(), c->w2(), c->w()); + c->set_sigma_e_quotient(sigmaEnergy.first); + c->set_sigma_e_fraction(sigmaEnergy.second); + std::pair Mean_z = mean_coordinate(c->wz(), c->w()); + c->set_mean_z_quotient(Mean_z.first); + c->set_mean_z_fraction(Mean_z.second); + std::pair Mean_phi = mean_coordinate(c->wphi(), c->w()); + c->set_mean_phi_quotient(Mean_phi.first); + c->set_mean_phi_fraction(Mean_phi.second); + std::pair Mean_eta = mean_coordinate(c->weta(), c->w()); + c->set_mean_eta_quotient(Mean_eta.first); + c->set_mean_eta_fraction(Mean_eta.second); + std::pair Mean_roz = mean_coordinate(c->wroz(), c->w()); + c->set_mean_roz_quotient(Mean_roz.first); + c->set_mean_roz_fraction(Mean_roz.second); + + const double sigma_z_scale = 0.08225179463624954; + std::pair Sigma_z = sigma_coordinate(c->w(), c->wz2(), c->wz(), sigma_z_scale); + c->set_sigma_z_quotient(Sigma_z.first); + c->set_sigma_z_fraction(Sigma_z.second); + + const double sigma_phi_scale = 0.907465934753418; + std::pair Sigma_phi = sigma_coordinate(c->w(), c->wphi2(), c->wphi(), sigma_phi_scale); + c->set_sigma_phi_quotient(Sigma_phi.first); + c->set_sigma_phi_fraction(Sigma_phi.second); + + std::pair Sigma_eta = sigma_coordinate(c->w(), c->weta2(), c->weta()); + c->set_sigma_eta_quotient(Sigma_eta.first); + c->set_sigma_eta_fraction(Sigma_eta.second); + + const double sigma_roz_scale = 0.5073223114013672; + std::pair Sigma_roz = sigma_coordinate(c->w(), c->wroz2(), c->wroz(), sigma_roz_scale); + c->set_sigma_roz_quotient(Sigma_roz.first); + c->set_sigma_roz_fraction(Sigma_roz.second); + std::vector layeroutput = showerLengthProperties(c->layerbits()); + c->set_firstLayer(layeroutput[0]); + c->set_lastLayer(layeroutput[1]); + c->set_showerLen(layeroutput[2]); + c->set_coreShowerLen(layeroutput[3]); + std::pair e_em_over_e = energy_ratio(c->e_em(), c->e()); + c->set_e_em_over_e_quotient(e_em_over_e.first); + c->set_e_em_over_e_fraction(e_em_over_e.second); + std::pair e_em_core_over_e_em = energy_ratio(c->e_em_core(), c->e()); + c->set_e_em_core_over_e_em_quotient(e_em_core_over_e_em.first); + c->set_e_em_core_over_e_em_fraction(e_em_core_over_e_em.second); + std::pair e_h_early_over_e = energy_ratio(c->e_h_early(), c->e()); + c->set_e_h_early_over_e_quotient(e_h_early_over_e.first); + c->set_e_h_early_over_e_fraction(e_h_early_over_e.second); + + nTCs += c->n_tc(); + } +} + +std::pair HGCalHistoClusterProperties::sigma_energy(unsigned int N_TC_W, + unsigned long int Sum_W2, + unsigned int Sum_W) const { + unsigned long int N = N_TC_W * Sum_W2 - pow(Sum_W, 2); + unsigned long int D = pow(N_TC_W, 2); + if (D == 0) { + return {0, 0}; + } + double intpart; + const unsigned shift = 2; // Shift by one bit, pow(2,1) + + double sigma_e = sqrt(N / D); + const double sigma_e_scale = 0.008982944302260876; + sigma_e *= sigma_e_scale; + + double frac = modf(sigma_e, &intpart) * shift; + + + return {(unsigned int)intpart, (unsigned int)frac}; +} + +std::pair HGCalHistoClusterProperties::mean_coordinate(unsigned int Sum_Wc, + unsigned int Sum_W) const { + if (Sum_W == 0) { + return {0, 0}; + } + double intpart; + const unsigned shift = 4; // Shift by one bit, pow(2,2) + double frac = modf((double)Sum_Wc / Sum_W, &intpart) * shift; + return {(unsigned int)intpart, (unsigned int)frac}; +} + +std::pair HGCalHistoClusterProperties::sigma_coordinate(unsigned int Sum_W, + unsigned long int Sum_Wc2, + unsigned int Sum_Wc, + double scale ) const { + unsigned long int N = Sum_W * Sum_Wc2 - pow(Sum_Wc, 2); + unsigned long int D = pow(Sum_W, 2); + if (D == 0) { + return {0, 0}; + } + double intpart; + const unsigned shift = 2; // Shift by one bit, pow(2,1) + + double sigma_coord = sqrt(N / D); + sigma_coord *= scale; + double frac = modf(sigma_coord, &intpart) * shift; + // std::cout << "Sigma coord : " << sigma_coord << " " << intpart << " " << frac << " " << modf(sigma_coord, &intpart) << " " << shift << std::endl; + return {(unsigned int)intpart, (unsigned int)frac}; +} + +std::pair HGCalHistoClusterProperties::energy_ratio(unsigned int e_N, + unsigned int e_D) const { + if (e_D == 0) { + return {0, 0}; + } else { + double intpart; + const unsigned shift = 256; // Shift by eight bit, pow(2,8) + double frac = modf((double)e_N / e_D, &intpart) * shift; + return {(unsigned int)intpart, (unsigned int)frac}; + } +} + +std::vector HGCalHistoClusterProperties::showerLengthProperties(unsigned long int layerBits) const { + int counter = 0; + int firstLayer = 0; + bool firstLayerFound = false; + int lastLayer = 0; + std::vector layerBits_array; + + for (unsigned int idx = 0; idx < config_.nTriggerLayers(); idx++) { + if ((layerBits & (1L << (config_.nTriggerLayers() - 1 - idx))) >= 1L) { + if (!firstLayerFound) { + firstLayer = idx + 1; + firstLayerFound = true; + } + lastLayer = idx + 1; + counter += 1; + } else { + layerBits_array.push_back(counter); + counter = 0; + } + } + int showerLen = lastLayer - firstLayer + 1; + int coreShowerLen = config_.nTriggerLayers(); + if (!layerBits_array.empty()) { + coreShowerLen = *std::max_element(layerBits_array.begin(), layerBits_array.end()); + } + + return {firstLayer, lastLayer, showerLen, coreShowerLen}; +} diff --git a/L1Trigger/L1THGCal/src/backend_emulator/HGCalHistoClusteringConfig_SA.cc b/L1Trigger/L1THGCal/src/backend_emulator/HGCalHistoClusteringConfig_SA.cc new file mode 100644 index 0000000000000..5a9513c165bef --- /dev/null +++ b/L1Trigger/L1THGCal/src/backend_emulator/HGCalHistoClusteringConfig_SA.cc @@ -0,0 +1,162 @@ +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusteringConfig_SA.h" +#include +#include +using namespace std; +using namespace l1thgcfirmware; +ClusterAlgoConfig::ClusterAlgoConfig() + : clusterizerOffset_(0), + cClocks_(0), + cInputs_(0), + cInputs2_(0), + cInt_(0), + cColumns_(0), + cRows_(0), + rOverZHistOffset_(0), + rOverZBinSize_(0), + kernelWidths_(), + areaNormalizations_(), + thresholdMaximaConstants_(), + nBinsCosLUT_(0), + cosLUT_(), + clusterizerMagicTime_(0), + stepLatency_(), + depths_(), + triggerLayers_(), + layerWeights_E_(), + layerWeights_E_EM_(), + layerWeights_E_EM_core_(), + layerWeights_E_H_early_(), + correction_(), + saturation_(), + rozToEtaLUT_() {} + +void ClusterAlgoConfig::setStepLatencies(const std::vector& latencies) { + stepLatency_.clear(); + stepLatency_.reserve(latencies.size()); + for (unsigned int iStep = 0; iStep < latencies.size(); ++iStep) { + stepLatency_.push_back(latencies.at(iStep)); + } +} + +unsigned int ClusterAlgoConfig::getLatencyUpToAndIncluding(const Step step) const { + unsigned int latency = 0; + for (int iStep = 0; iStep <= step; ++iStep) + latency += getStepLatency(Step(iStep)); + return latency; +} + +void ClusterAlgoConfig::initializeLUTs() { + initializeSmearingKernelConstants(cRows_, rOverZHistOffset_, rOverZBinSize_); + initializeThresholdMaximaConstants(cRows_, thresholdMaximaParam_a_, thresholdMaximaParam_b_, thresholdMaximaParam_c_); + initializeCosLUT(); + initializeRoZToEtaLUT(); + initializeSigmaRoZToSigmaEtaLUT(); +} + +void ClusterAlgoConfig::initializeSmearingKernelConstants(unsigned int bins, unsigned int offset, unsigned int height) { + const unsigned int lWidth0 = offset + (0.5 * height); + const unsigned int lTarget = int((maxBinsSmearing1D_ + 0.5) * lWidth0 - 0.5); + for (unsigned int iBin = 0; iBin < bins; ++iBin) { + unsigned int lCentre = lWidth0 + (height * iBin); + const unsigned int lBins = int(round(float(lTarget) / lCentre)); + + kernelWidths_.push_back(lBins); + + lCentre *= lBins; + + const unsigned int lRatio = int(round(float(lTarget) / lCentre * (0x1 << nBitsAreaNormLUT_))); + + areaNormalizations_.push_back(lRatio); + } +} + +void ClusterAlgoConfig::initializeThresholdMaximaConstants(unsigned int bins, unsigned int a, int b, int c) { + for (unsigned int iBin = 0; iBin < bins; ++iBin) { + int threshold = a + b * iBin + c * iBin * iBin; + thresholdMaximaConstants_.push_back(threshold); + } +} + +void ClusterAlgoConfig::initializeCosLUT() { + for (unsigned int iBin = 0; iBin < nBinsCosLUT_ + 1; ++iBin) { + unsigned int cosBin = round((0x1 << nBitsCosLUT_) * (1 - cos(iBin * M_PI / phiNValues_))); + cosLUT_.push_back(cosBin); + } +} + +void ClusterAlgoConfig::initializeRoZToEtaLUT() { + const float eta_min = 320 * M_PI/720; // ~1.4 + const float eta_max = 687 * M_PI/720; // ~3.0 + const float eta_LSB = M_PI/720; + + const float roz_min = 1/(sinh(eta_max)); // coming from L1T eta_max + const float roz_max = 1/(sinh(eta_min)); // coming from L1T eta_min + const float roz_LSB = (roz_max-roz_min)/pow(2,10); // coming from L1T eta_LSB; CP block needs to calculate mean(r/z) with at least 10b if we are to meet L1T eta LSB + + unsigned nEntries = 0x1<<10; + rozToEtaLUT_.reserve(nEntries); + for ( unsigned i = 0; i dEta_dMu_LUT; + dEta_dMu_LUT.reserve(nEntries_dEta_dMu_LUT); + // std::cout << "dEta/dMu LUT" << std::endl; + for ( unsigned i = 0; i sigmaRoz_LUT; + sigmaRoz_LUT.reserve(nEntries_sigmaRoz_LUT); + for ( unsigned i = 0; i roz_SigmaRoz_LUT(nEntries_roz_sigmaRoz_LUT); + sigmaRozToSigmaEtaLUT_.reserve(nEntries_roz_sigmaRoz_LUT); + for ( unsigned mu=0; mu ( 0x1<<(sigmaEta_nbits-1) ) ) sigmaEta = 0x1<<(sigmaEta_nbits-1); + sigmaRozToSigmaEtaLUT_.push_back(sigmaEta); + // std::cout << mu << " " << sigma << " " << dEta_dMu << " " << sigmaRoz << " " << sigma_eta_LSB << " " << sigmaEta << std::endl; + } + } +} \ No newline at end of file diff --git a/L1Trigger/L1THGCal/src/backend_emulator/HGCalHistoClusteringImpl_SA.cc b/L1Trigger/L1THGCal/src/backend_emulator/HGCalHistoClusteringImpl_SA.cc new file mode 100644 index 0000000000000..05ce11d6970c7 --- /dev/null +++ b/L1Trigger/L1THGCal/src/backend_emulator/HGCalHistoClusteringImpl_SA.cc @@ -0,0 +1,33 @@ +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusteringImpl_SA.h" + +using namespace std; +using namespace l1thgcfirmware; +HGCalHistoClusteringImplSA::HGCalHistoClusteringImplSA(const ClusterAlgoConfig& config) + : config_(config), tcDistribution_(config), seeding_(config), clustering_(config), clusterProperties_(config) {} + +void HGCalHistoClusteringImplSA::runAlgorithm(const HGCalTriggerCellSAPtrCollections& inputs, + HGCalTriggerCellSAShrPtrCollection& clusteredTCs, + HGCalClusterSAPtrCollection& clusterSums) const { + + // std::cout << "TC Dist" << std::endl; + // TC distribution + HGCalTriggerCellSAPtrCollection distributedTCs; + tcDistribution_.runTriggerCellDistribution(inputs, distributedTCs); + + // std::cout << "Seeding" << std::endl; + // Histogramming and seeding + HGCalHistogramCellSAPtrCollection histogram; + seeding_.runSeeding(distributedTCs, histogram); + + // std::cout << "Clustering" << std::endl; + // Clustering + HGCalClusterSAPtrCollection protoClusters; + CentroidHelperPtrCollection readoutFlags; + clustering_.runClustering(distributedTCs, histogram, clusteredTCs, readoutFlags, protoClusters); + + // std::cout << "CP" << std::endl; + // Cluster properties + clusterProperties_.runClusterProperties(protoClusters, readoutFlags, clusterSums); + // std::cout << "Done" << std::endl; + +} diff --git a/L1Trigger/L1THGCal/src/backend_emulator/HGCalHistoClustering_SA.cc b/L1Trigger/L1THGCal/src/backend_emulator/HGCalHistoClustering_SA.cc new file mode 100644 index 0000000000000..3cdb836e52595 --- /dev/null +++ b/L1Trigger/L1THGCal/src/backend_emulator/HGCalHistoClustering_SA.cc @@ -0,0 +1,328 @@ +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClustering_SA.h" + +#include +#include + +using namespace std; +using namespace l1thgcfirmware; + +HGCalHistoClustering::HGCalHistoClustering(const ClusterAlgoConfig& config) : config_(config) {} + +void HGCalHistoClustering::runClustering(const HGCalTriggerCellSAPtrCollection& triggerCellsIn, + const HGCalHistogramCellSAPtrCollection& histogramIn, + HGCalTriggerCellSAShrPtrCollection& clusteredTriggerCellsOut, + CentroidHelperPtrCollection& readoutFlagsOut, + HGCalClusterSAPtrCollection& protoClusters) const { + HGCalTriggerCellSAShrPtrCollection unclusteredTriggerCells; + clusterizer(triggerCellsIn, histogramIn, clusteredTriggerCellsOut, unclusteredTriggerCells, readoutFlagsOut); + triggerCellToCluster(clusteredTriggerCellsOut, protoClusters); +} + +// Main implementation of clustering +// Takes histogram containing seeds and streams of TCs (each stream corresponds to one column of the histogram) +// Outputs clustered and unclustered TCs, and readoutFlags which contain info on which clustered TCs belong to each cluster +// Require more comments on firmware to provide more meanginful comments here +void HGCalHistoClustering::clusterizer(const HGCalTriggerCellSAPtrCollection& triggerCellsIn, + const HGCalHistogramCellSAPtrCollection& histogram, + HGCalTriggerCellSAShrPtrCollection& clusteredTriggerCellsOut, + HGCalTriggerCellSAShrPtrCollection& unclusteredTriggerCellsOut, + CentroidHelperPtrCollection& readoutFlagsOut) const { + unsigned int seedCounter = 0; + CentroidHelperPtrCollections fifos(config_.nFifos()); + vector clock(config_.cColumns(), config_.clusterizerMagicTime()); + const unsigned dummy_entries_latched = 1; + CentroidHelperShrPtrCollection latched( + config_.nFifos() + dummy_entries_latched, + make_shared< + CentroidHelper>()); // 1 extra (dummy) entry compared to fifos, to match firmware behaviour (avoids issues with index wrap-around) + + HGCalTriggerCellSAShrPtrCollections clusteredTriggerCells(config_.cColumns(), HGCalTriggerCellSAShrPtrCollection()); + HGCalTriggerCellSAShrPtrCollections unclusteredTriggerCells(config_.cColumns(), HGCalTriggerCellSAShrPtrCollection()); + CentroidHelperPtrCollections readoutFlags(config_.cColumns()); + + HGCalTriggerCellSAShrPtrCollectionss triggerCellBuffers( + config_.cColumns(), HGCalTriggerCellSAShrPtrCollections(config_.cRows(), HGCalTriggerCellSAShrPtrCollection())); + for (const auto& tc : triggerCellsIn) { + // Temp copy of tc whilst moving from shared to unique ptr + triggerCellBuffers.at(tc->index()).at(tc->sortKey()).push_back(make_shared(*tc)); + } + + for (unsigned int iRow = 0; iRow < config_.cRows(); ++iRow) { + for (unsigned int j = 0; j < config_.nColumnsPerFifo(); ++j) { + for (unsigned int k = 0; k < config_.nFifos(); ++k) { + unsigned int col = config_.firstSeedBin() + (config_.nColumnsPerFifo() * k) + j; + const auto& cell = histogram.at(config_.cColumns() * iRow + col); + if (cell->S() > 0) { + auto ch = make_unique(cell->clock() + 1 + j, + config_.nColumnsPerFifo() * k + j, + cell->index(), + cell->sortKey(), + cell->S(), + cell->X(), + cell->Y(), + true); + fifos[k].push_back(move(ch)); + ++seedCounter; + } + } + } + } + while (seedCounter > 0) { + for (unsigned int i = 0; i < config_.nFifos(); ++i) { + if (!latched[i]->dataValid()) { + if (!fifos[i].empty()) { + latched[i] = move(fifos[i][0]); + fifos[i].erase(fifos.at(i).begin()); + } + } + } + + const unsigned dummy_entries_accepted = 2; + CentroidHelperShrPtrCollection accepted( + config_.nFifos() + dummy_entries_accepted, + make_shared< + CentroidHelper>()); // 2 extra (dummy) entry compared to fifos (1 compared to latched), to match firmware behaviour (avoids issues with index wrap-around) + CentroidHelperShrPtrCollection lastLatched(latched); + + for (unsigned int i = 0; i < config_.nFifos(); ++i) { + // Different implementation to python emulator + // For i=0, i-1=-1, which would give the last element of lastLatched in python, but is out of bounds in C++ + // Similar for i=17 (==config_.nFifos()-1) + // Need to find out intended behaviour + bool deltaMinus = + (i > 0) ? (lastLatched[i]->column() - lastLatched[i - 1]->column()) > config_.nColumnFifoVeto() : true; + bool deltaPlus = (i < config_.nFifos() - 1) + ? (lastLatched[i + 1]->column() - lastLatched[i]->column()) > config_.nColumnFifoVeto() + : true; + + bool compareEMinus = (i > 0) ? (lastLatched[i]->energy() > lastLatched[i - 1]->energy()) : true; + bool compareEPlus = + (i < config_.nFifos() - 1) ? (lastLatched[i]->energy() >= lastLatched[i + 1]->energy()) : true; + + if (lastLatched[i]->dataValid()) { + // Similar out of bounds issue here + // if ( ( !lastLatched[i+1]->dataValid() || compareEPlus || deltaPlus ) && ( !lastLatched[i-1]->dataValid() || compareEMinus || deltaMinus ) ) { + + bool accept = true; + if (lastLatched.size() > i + 1) { + if (!lastLatched[i + 1]->dataValid() || compareEPlus || deltaPlus) { + accept = true; + } else { + accept = false; + } + } + + if (i > 0) { + if (!lastLatched[i - 1]->dataValid() || compareEMinus || deltaMinus) { + accept = true; + } else { + accept = false; + } + } + + if (accept) { + accepted[i] = latched[i]; + latched[i] = make_shared(); + --seedCounter; + } + } + } + + for (const auto& a : accepted) { + if (a->dataValid()) { + for (unsigned int iCol = a->column() - config_.nColumnsForClustering(); + iCol < a->column() + config_.nColumnsForClustering() + 1; + ++iCol) { + clock[iCol] = clock[a->column()]; + } + } + } + + vector readoutFlagClocks; + + for (const auto& a : accepted) { + if (a->dataValid()) { + unsigned int T = 0; + for (unsigned int iCol = a->column() - config_.nColumnsForClustering(); + iCol < a->column() + config_.nColumnsForClustering() + 1; + ++iCol) { + const unsigned stepLatency = 8; + clock[iCol] += stepLatency; + for (int k = -1 * config_.nRowsForClustering(); k < int(config_.nRowsForClustering()) + 1; ++k) { + int row = a->row() + k; + if (row < 0) + continue; + if (row >= int(config_.cRows())) + continue; // Not in python emulator, but required to avoid out of bounds access + if (triggerCellBuffers[iCol][row].empty()) { + clock[iCol] += 1; + continue; + } + for (auto& tc : triggerCellBuffers[iCol][row]) { + clock[iCol] += 1; + unsigned int r1 = tc->rOverZ(); + unsigned int r2 = a->Y(); + int dR = r1 - r2; + unsigned int absDPhi = abs(int(tc->phi()) - int(a->X())); + unsigned int dR2 = dR * dR; + unsigned int cosTerm = (absDPhi > config_.nBinsCosLUT()) ? 2047 : config_.cosLUT(absDPhi); + + const unsigned a = 128; // 2^7 + const unsigned b = 1024; // 2^10 + dR2 += int(r1 * r2 / a) * cosTerm / b; + tc->setClock(clock[iCol] + 1); + if (clock[iCol] > T) + T = clock[iCol]; + + unsigned int dR2Cut = config_.getDeltaR2Threshold(tc->layer()); + if (dR2 < dR2Cut) { + clusteredTriggerCells[iCol].push_back(tc); + } else { + unclusteredTriggerCells[iCol].push_back(tc); + } + } + } + + for (const auto& tc : clusteredTriggerCells[iCol]) { + auto tcMatch = std::find_if( + triggerCellBuffers[iCol][tc->sortKey()].begin(), + triggerCellBuffers[iCol][tc->sortKey()].end(), + [&](const HGCalTriggerCellSAShrPtr tcToMatch) { + bool isMatch = tc->index() == tcToMatch->index() && tc->rOverZ() == tcToMatch->rOverZ() && + tc->layer() == tcToMatch->layer() && tc->energy() == tcToMatch->energy() && + tc->phi() == tcToMatch->phi() && tc->sortKey() == tcToMatch->sortKey() && + tc->deltaR2() == tcToMatch->deltaR2() && tc->dX() == tcToMatch->dX() && + tc->Y() == tcToMatch->Y() && tc->frameValid() == tcToMatch->frameValid() && + tc->dataValid() == tcToMatch->dataValid() && tc->clock() == tcToMatch->clock(); + return isMatch; + }); + + if (tcMatch != triggerCellBuffers[iCol][tc->sortKey()].end()) { + triggerCellBuffers[iCol][tc->sortKey()].erase(tcMatch); + } + } + } + + unsigned int readoutFlagClock = 0; + for (unsigned int iCol = a->column() - config_.nColumnsForClustering(); + iCol < a->column() + config_.nColumnsForClustering() + 1; + ++iCol) { + clock[iCol] = T + 1; + + CentroidHelperPtr readoutFlag = make_unique(T - 2, iCol, true); + while ( std::find(readoutFlagClocks.begin(), readoutFlagClocks.end(), readoutFlag->clock()) != readoutFlagClocks.end() ) { + readoutFlag->setClock(readoutFlag->clock() + 1); + } + readoutFlagClock = readoutFlag->clock(); + + const unsigned stepLatency = 14; + if (readoutFlag->clock() == + config_.clusterizerMagicTime() + stepLatency) { // Magic numbers - latency of which particular step? + readoutFlag->setClock(readoutFlag->clock() + 1); + } + + readoutFlags[iCol].push_back(move(readoutFlag)); + } + readoutFlagClocks.push_back(readoutFlagClock); + } + } + } + + const unsigned largeReadoutTime = 1000; + for (unsigned int i = 0; i < largeReadoutTime; + ++i) { // Magic numbers - a large number to ensure we read out all clustered trigger cells etc.? + for (unsigned int iCol = 0; iCol < config_.cColumns(); ++iCol) { + for (const auto& clustered : clusteredTriggerCells[iCol]) { + if (clustered->clock() == config_.clusterizerMagicTime() + i) { + clusteredTriggerCellsOut.push_back(clustered); + } + } + + for (const auto& unclustered : unclusteredTriggerCells[iCol]) { + if (unclustered->clock() == config_.clusterizerMagicTime() + i) { + unclusteredTriggerCellsOut.push_back(unclustered); + } + } + + for (auto& readoutFlag : readoutFlags[iCol]) { + if (readoutFlag) { + if (readoutFlag->clock() == config_.clusterizerMagicTime() + i) { + // TODO : Check if we can move the readoutFlag and leave a nullptr + // Or if the readoutFlag could be used again later on + readoutFlagsOut.push_back(move(readoutFlag)); + } + } + } + } + } +} + +// Converts clustered TCs into cluster object (one for each TC) ready for accumulation +void HGCalHistoClustering::triggerCellToCluster(const HGCalTriggerCellSAShrPtrCollection& clusteredTriggerCells, + HGCalClusterSAPtrCollection& clustersOut) const { + const unsigned int stepLatency = config_.getStepLatency(TriggerCellToCluster); + + clustersOut.clear(); + for (const auto& tc : clusteredTriggerCells) { + auto cluster = make_unique(tc->clock() + stepLatency, tc->index(), true, true); + + // Cluster from single TC + // Does this ever happen? + // Removed from newer versions of firmware in any case, but leave for now + const unsigned singleTCDeltaR2Thresh = 25000; + if (tc->deltaR2() >= singleTCDeltaR2Thresh) { + clustersOut.push_back(move(cluster)); + continue; + } + + const unsigned weightFactor = 4; + unsigned long int s_TC_W = (int(tc->energy() / weightFactor) == 0) ? 1 : tc->energy() / weightFactor; + unsigned long int s_TC_Z = config_.depth(tc->layer()); + + unsigned int triggerLayer = config_.triggerLayer(tc->layer()); + const unsigned nBitsESums = 18; // Need to double check this is correct description of constant + unsigned int s_E_EM = + ((((unsigned long int)tc->energy() * config_.layerWeight_E_EM(triggerLayer)) + config_.correction()) >> + nBitsESums); + if (s_E_EM > config_.saturation()) + s_E_EM = config_.saturation(); + + unsigned int s_E_EM_core = + (((unsigned long int)tc->energy() * config_.layerWeight_E_EM_core(triggerLayer) + config_.correction()) >> + nBitsESums); + if (s_E_EM_core > config_.saturation()) + s_E_EM_core = config_.saturation(); + + // Alternative constructor perhaps? + cluster->set_n_tc(1); + cluster->set_n_tc_w(1); + + cluster->set_e((config_.layerWeight_E(triggerLayer) == 1) ? tc->energy() : 0); + cluster->set_e_h_early((config_.layerWeight_E_H_early(triggerLayer) == 1) ? tc->energy() : 0); + + cluster->set_e_em(s_E_EM); + cluster->set_e_em_core(s_E_EM_core); + + cluster->set_w(s_TC_W); + cluster->set_w2(s_TC_W * s_TC_W); + + cluster->set_wz(s_TC_W * s_TC_Z); + cluster->set_weta(0); + cluster->set_wphi(s_TC_W * tc->phi()); + cluster->set_wroz(s_TC_W * tc->rOverZ()); + + cluster->set_wz2(s_TC_W * s_TC_Z * s_TC_Z); + cluster->set_weta2(0); + cluster->set_wphi2(s_TC_W * tc->phi() * tc->phi()); + cluster->set_wroz2(s_TC_W * tc->rOverZ() * tc->rOverZ()); + + const unsigned nTriggerLayers = 36; // Should get from config/elsewhere in CMSSW + cluster->set_layerbits(cluster->layerbits() | (((unsigned long int)1) << (nTriggerLayers - triggerLayer))); + cluster->set_sat_tc(cluster->e() == config_.saturation() || cluster->e_em() == config_.saturation()); + cluster->set_shapeq(1); + + // Temp copy of TC whilst reducing use of shared ptr + cluster->add_constituent(make_shared(*tc)); + clustersOut.push_back(move(cluster)); + } +} \ No newline at end of file diff --git a/L1Trigger/L1THGCal/src/backend_emulator/HGCalHistoSeeding_SA.cc b/L1Trigger/L1THGCal/src/backend_emulator/HGCalHistoSeeding_SA.cc new file mode 100644 index 0000000000000..4bfece71aa942 --- /dev/null +++ b/L1Trigger/L1THGCal/src/backend_emulator/HGCalHistoSeeding_SA.cc @@ -0,0 +1,230 @@ +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoSeeding_SA.h" + +#include + +using namespace std; +using namespace l1thgcfirmware; + +HGCalHistoSeeding::HGCalHistoSeeding(const ClusterAlgoConfig& config) : config_(config) {} + +void HGCalHistoSeeding::runSeeding(const HGCalTriggerCellSAPtrCollection& triggerCellsIn, + HGCalHistogramCellSAPtrCollection& histogramOut) const { + HGCalHistogramCellSAPtrCollection histoCells; + // std::cout << "TC to HC" << std::endl; + triggerCellToHistogramCell(triggerCellsIn, histoCells); + // std::cout << "Make hist" << std::endl; + makeHistogram(histoCells, histogramOut); + // std::cout << "Smearing" << std::endl; + // Smearing + smearHistogram1D(histogramOut); + normalizeArea(histogramOut); + smearHistogram2D(histogramOut); + + //Maxima finding + thresholdMaximaFinder(histogramOut); + localMaximaFinder(histogramOut); + calculateAveragePosition(histogramOut); +} + +// Convert each trigger cell into a histogram cell +// Phi bin corresponds to the stream the TC is in, r/z bin is calculated from the TC r/z +void HGCalHistoSeeding::triggerCellToHistogramCell(const HGCalTriggerCellSAPtrCollection& triggerCellsIn, + HGCalHistogramCellSAPtrCollection& histogramOut) const { + const unsigned int latency = config_.getStepLatency(TcToHc); + + histogramOut.clear(); + for (auto& tc : triggerCellsIn) { + auto hc = + make_unique(tc->clock() + latency, + tc->index(), + tc->energy(), + tc->phi(), + tc->rOverZ(), + 1, + int((tc->rOverZ() - config_.rOverZHistOffset()) / config_.rOverZBinSize())); + tc->setClock(hc->clock()); + tc->setSortKey(hc->sortKey()); + histogramOut.push_back(std::move(hc)); + } +} + +// Sum all input histogram cells (each representing one TC) to produce one histogram +void HGCalHistoSeeding::makeHistogram(const HGCalHistogramCellSAPtrCollection& histogramCells, + HGCalHistogramCellSAPtrCollection& histogramOut) const { + const unsigned int latency = config_.getLatencyUpToAndIncluding(Hist); + + histogramOut.clear(); + const unsigned latencyOffset = 4; + for (unsigned int iRow = 0; iRow < config_.cRows(); ++iRow) { + for (unsigned int iColumn = 0; iColumn < config_.cColumns(); ++iColumn) { + histogramOut.push_back(make_unique(latency, iColumn, iRow, latencyOffset)); + } + } + + for (const auto& hc : histogramCells) { + const unsigned int binIndex = config_.cColumns() * hc->sortKey() + hc->index(); + *histogramOut.at(binIndex) += *hc; + } +} + +// Smearing at constant r/z using exponentially falling 2^-n kernel +// Maximum extent of smearing (how many neighbouring bins included) can vary for each r/z bin, and is specified in the configuration +void HGCalHistoSeeding::smearHistogram1D(HGCalHistogramCellSAPtrCollection& histogram) const { + HGCalHistogramCellSACollection lHistogram; + for (unsigned int iBin = 0; iBin < histogram.size(); ++iBin) { + lHistogram.emplace_back(*histogram.at(iBin)); + } + + const unsigned int stepLatency = config_.getStepLatency(Step::Smearing1D); + for (unsigned int iBin = 0; iBin < lHistogram.size(); ++iBin) { + auto& hc = histogram.at(iBin); + hc->addLatency(stepLatency); + + const unsigned int col = hc->index(); + const unsigned int row = hc->sortKey(); + const unsigned int binIndex = config_.cColumns() * row + col; + unsigned int scale = 1; + int width = config_.kernelWidth(row); + unsigned int offset = 1; + const unsigned scaleMultiplier = 4; + const unsigned widthUpdate = 2; + const unsigned offsetUpdate = 2; + while (width > 0) { + unique_ptr l1 = make_unique(HGCalHistogramCell()); + unique_ptr l2 = make_unique(HGCalHistogramCell()); + unique_ptr r1 = make_unique(HGCalHistogramCell()); + unique_ptr r2 = make_unique(HGCalHistogramCell()); + + if (width >= 2) { + const unsigned cellWeightTwoAway = 4; + if (int(col - offset - 1) >= 0) { + l2 = make_unique(lHistogram[binIndex - offset - 1] / cellWeightTwoAway); + } + if (int(col + offset + 1) <= int(config_.cColumns() - 1)) { + r2 = make_unique(lHistogram[binIndex + offset + 1] / cellWeightTwoAway); + } + } + + const unsigned cellWeightNeighbour = 2; + if (int(col - offset) >= 0) { + l1 = make_unique(lHistogram[binIndex - offset] / cellWeightNeighbour); + } + if (int(col + offset) <= int(config_.cColumns() - 1)) { + r1 = make_unique(lHistogram[binIndex + offset] / cellWeightNeighbour); + } + *hc += ((*l2 + *l1) / scale + (*r2 + *r1) / scale); + scale *= scaleMultiplier; + width -= widthUpdate; + offset += offsetUpdate; + } + } +} + +void HGCalHistoSeeding::normalizeArea(HGCalHistogramCellSAPtrCollection& histogram) const { + const unsigned int stepLatency = config_.getStepLatency(NormArea); + for (unsigned int iBin = 0; iBin < histogram.size(); ++iBin) { + HGCalHistogramCell& hc = *histogram.at(iBin); + hc.addLatency(stepLatency); + hc.setS(int(float(hc.S()) * config_.areaNormalization(hc.sortKey()) / (0x1 << (config_.nBitsAreaNormLUT() + 1)))); + } +} + +// Smearing at constant phi with exponentially falling 2^-n kernel +// Limited to +/- 1 bin in phi (only consider nearest neighbour), so adding half of the row above and below +void HGCalHistoSeeding::smearHistogram2D(HGCalHistogramCellSAPtrCollection& histogram) const { + HGCalHistogramCellSACollection lHistogram; + for (unsigned int iBin = 0; iBin < histogram.size(); ++iBin) { + lHistogram.emplace_back(*histogram.at(iBin)); + } + const unsigned int stepLatency = config_.getStepLatency(Step::Smearing2D); + for (unsigned int iBin = 0; iBin < lHistogram.size(); ++iBin) { + auto& hc = histogram.at(iBin); + hc->addLatency(stepLatency); + + const unsigned int col = hc->index(); + const int row = hc->sortKey(); + const unsigned int binIndex = config_.cColumns() * row + col; + const unsigned cellWeight = 2; + if (row - 1 >= 0) { + *hc += (lHistogram[binIndex - config_.cColumns()] / cellWeight); + } + if (row + 1 <= int(config_.cRows() - 1)) { + *hc += (lHistogram[binIndex + config_.cColumns()] / cellWeight); + } + } +} + +// Simple threshold maxima finder +// Keep only bins passing threshold +// Threshold can vary vs r/z +void HGCalHistoSeeding::thresholdMaximaFinder(HGCalHistogramCellSAPtrCollection& histogram) const { + const unsigned int stepLatency = config_.getStepLatency(Maxima2D); + for (auto& hc : histogram) { + hc->addLatency(stepLatency); + if (hc->S() <= config_.thresholdMaxima(hc->sortKey())) { + hc->setS(0); + hc->setX(0); + hc->setY(0); + hc->setN(0); + } + } +} + +// Temporary simulation of local maxima finder +// Not an emulation of any firmware +void HGCalHistoSeeding::localMaximaFinder(HGCalHistogramCellSAPtrCollection& histogram) const { + const std::vector maximaWidths(config_.cRows(), 1); + + for (auto& hc : histogram) { + if (hc->S() > 0) { + const int colRef = hc->index(); + const int rowRef = hc->sortKey(); + bool isMaxima = true; + const int phiRange = maximaWidths.at(hc->sortKey()); + for (int colOffset = -1 * phiRange; colOffset <= phiRange; ++colOffset) { + const int col = colRef + colOffset; + if (col < 0 || col >= (int)config_.cColumns()) + continue; + for (int rowOffset = -1; rowOffset <= 1; ++rowOffset) { + const int row = rowRef + rowOffset; + if (row < 0 || row >= (int)config_.cRows()) + continue; + const unsigned int binIndex = config_.cColumns() * row + col; + const auto& bin = histogram.at(binIndex); + + if (colOffset == 0 && rowOffset == 0) + continue; + else if ((col < colRef) || (col == colRef && rowOffset == -1) || (col == colRef + 1 && rowOffset == -1)) { + if (!(hc->S() >= bin->S())) + isMaxima = false; + } else { + if (!(hc->S() > bin->S())) + isMaxima = false; + } + } + } + if (!isMaxima) { + hc->setS(0); + hc->setX(0); + hc->setY(0); + hc->setN(0); + } + } + } +} + +// Calculate average of phi and r/z (now labelled X and Y) of TCs within a bin +// As performed in firmware, where the sum of TC phi or r/z is multiplied by 2^17/N_TCs (factors stored in a LUT) +// Then result is shifted by 17 bits +void HGCalHistoSeeding::calculateAveragePosition(HGCalHistogramCellSAPtrCollection& histogram) const { + const unsigned int stepLatency = config_.getStepLatency(CalcAverage); + for (auto& hc : histogram) { + hc->addLatency(stepLatency); + const unsigned nBits = 17; + if (hc->N() > 0) { + unsigned int inv_N = int(round(float(0x1 << nBits) / hc->N())); + hc->setX((hc->X() * inv_N) >> nBits); + hc->setY((hc->Y() * inv_N) >> nBits); + } + } +} diff --git a/L1Trigger/L1THGCal/src/backend_emulator/HGCalHistogramCell_SA.cc b/L1Trigger/L1THGCal/src/backend_emulator/HGCalHistogramCell_SA.cc new file mode 100644 index 0000000000000..ce58fdc2a7cd2 --- /dev/null +++ b/L1Trigger/L1THGCal/src/backend_emulator/HGCalHistogramCell_SA.cc @@ -0,0 +1,30 @@ +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistogramCell_SA.h" + +using namespace l1thgcfirmware; + +const HGCalHistogramCell& HGCalHistogramCell::operator+=(const HGCalHistogramCell& hc) { + S_ += hc.S(); + X_ += hc.X(); + Y_ += hc.Y(); + N_ += hc.N(); + + return *this; +} + +const HGCalHistogramCell HGCalHistogramCell::operator/(const unsigned int factor) const { + HGCalHistogramCell hc(*this); + + if (factor != 0) { + hc.S_ /= factor; + hc.X_ = 0; + hc.Y_ = 0; + hc.N_ = 0; + } + return hc; +} + +const HGCalHistogramCell HGCalHistogramCell::operator+(const HGCalHistogramCell& hc) const { + HGCalHistogramCell sum(*this); + sum += hc; + return sum; +} diff --git a/L1Trigger/L1THGCal/src/backend_emulator/HGCalTCDistribution_SA.cc b/L1Trigger/L1THGCal/src/backend_emulator/HGCalTCDistribution_SA.cc new file mode 100644 index 0000000000000..b0b34e583cda8 --- /dev/null +++ b/L1Trigger/L1THGCal/src/backend_emulator/HGCalTCDistribution_SA.cc @@ -0,0 +1,217 @@ +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalTCDistribution_SA.h" + +using namespace std; +using namespace l1thgcfirmware; + +HGCalTCDistribution::HGCalTCDistribution(const ClusterAlgoConfig& config) : config_(config) {} + +// Rearranges/distributes input streams of TCs so that each output stream contains TCs corresponding to one histogram bin +void HGCalTCDistribution::runTriggerCellDistribution(const HGCalTriggerCellSAPtrCollections& triggerCellsIn, + HGCalTriggerCellSAPtrCollection& triggerCellsOut) const { + HGCalTriggerCellSAShrPtrCollection triggerCellsWork; + triggerCellInput(triggerCellsIn, triggerCellsWork); + triggerCellDistribution0(triggerCellsWork); + HGCalTriggerCellSAShrPtrCollections tcDistGrid1; + triggerCellDistribution1(triggerCellsWork, tcDistGrid1); + HGCalTriggerCellSAShrPtrCollections tcDistGrid2; + triggerCellDistribution2(tcDistGrid1, triggerCellsWork, tcDistGrid2); + HGCalTriggerCellSAShrPtrCollections tcDistGrid3; + triggerCellDistribution3(tcDistGrid2, triggerCellsWork, tcDistGrid3); + triggerCellDistribution4(triggerCellsWork); + triggerCellDistribution5(tcDistGrid3, triggerCellsOut); +} + +// Unrolls input TCs (2D vector, frame vs input/link) to 1D vector +void HGCalTCDistribution::triggerCellInput(const HGCalTriggerCellSAPtrCollections& inputTCs, + HGCalTriggerCellSAShrPtrCollection& outputTCs) const { + outputTCs.clear(); + for (unsigned int iFrame = 0; iFrame < inputTCs.size(); ++iFrame) { + for (unsigned int iInput = 0; iInput < inputTCs[iFrame].size(); ++iInput) { + auto& tc = inputTCs[iFrame][iInput]; + + tc->setIndex(iInput); + tc->setClock(iFrame + 1); + + if (tc->dataValid()) { + // Copying input TCs and converting to shared pointer to avoid further copies in TCDist + outputTCs.push_back(make_shared(*tc)); + } + } + } +} + +// Adds empty input to each group of 24, making them groups of 25 +void HGCalTCDistribution::triggerCellDistribution0(const HGCalTriggerCellSAShrPtrCollection& triggerCellsIn) const { + for (auto& tc : triggerCellsIn) { + unsigned int newIndex = tc->index() + int(tc->index() / (config_.cInputs() / config_.n60Sectors())); + tc->setIndex(newIndex); + } +} + +// In each group of 25 streams, assign coarse phi region index to sort key of each TC (0-5 within each large phi region) +void HGCalTCDistribution::triggerCellDistribution1( + const HGCalTriggerCellSAShrPtrCollection& triggerCellsIn, + HGCalTriggerCellSAShrPtrCollections& outTriggerCellDistributionGrid) const { + initializeTriggerCellDistGrid(outTriggerCellDistributionGrid, config_.cClocks(), config_.cInputs2()); + + const unsigned int stepLatency = config_.getStepLatency(Dist1); + for (auto& tc : triggerCellsIn) { + tc->addLatency(stepLatency); + unsigned int sector = int(tc->index() / (config_.cInputs2() / config_.n60Sectors())); + outTriggerCellDistributionGrid[tc->clock() - 2][tc->index()] = tc; + for (int iSortKey = config_.nCoarsePhiDist1() - 1; iSortKey >= 0; --iSortKey) { + if (int(tc->phi() % config_.phiNValues()) > + int(config_.cColumns() * iSortKey + config_.phiNValues() / config_.n60Sectors() * sector)) { + tc->setSortKey(iSortKey); + break; + } + } + } +} + +// First distribution layer +// Use 15 5-to-6 distribution servers to merge multiple streams into 15x6=90 streams +// Within each 3x25 groups of input streams, 5 distribution servers organise the TCs into 5 groups of 6 streams. The 6 streams within one group correspond to TCs with the same coarse phi index +// Not enough documentation on distribution server vhdl to give more meaningful comments +void HGCalTCDistribution::triggerCellDistribution2( + const HGCalTriggerCellSAShrPtrCollections& inTriggerCellDistributionGrid, + HGCalTriggerCellSAShrPtrCollection& triggerCellsOut, + HGCalTriggerCellSAShrPtrCollections& outTriggerCellDistributionGrid) const { + const unsigned int latency = config_.getLatencyUpToAndIncluding(Dist2); + + triggerCellsOut.clear(); + initializeTriggerCellDistGrid(outTriggerCellDistributionGrid, config_.cClocks(), config_.cInt()); + + runDistServers(inTriggerCellDistributionGrid, + outTriggerCellDistributionGrid, + triggerCellsOut, + latency, + config_.nDistServers1(), + config_.distServer1_nIn(), + config_.distServer1_nOut(), + config_.distServer1_nInterleave(), + true); +} + +// Arrange streams with the same coarse phi index within each group of 30 streams to be next to each other +// Streams then correspond to 18 groups of 5, which each group corresponding to TCs with similar phi (same coarse phi index) +void HGCalTCDistribution::triggerCellDistribution3( + const HGCalTriggerCellSAShrPtrCollections& inTriggerCellDistributionGrid, + HGCalTriggerCellSAShrPtrCollection& triggerCellsOut, + HGCalTriggerCellSAShrPtrCollections& outTriggerCellDistributionGrid) const { + triggerCellsOut.clear(); + initializeTriggerCellDistGrid(outTriggerCellDistributionGrid, config_.cClocks(), config_.cInt()); + for (unsigned int iClock = 0; iClock < config_.cClocks(); ++iClock) { + for (unsigned int i = 0; i < config_.n60Sectors(); ++i) { + for (unsigned int k = 0; k < config_.distServer1_nOut(); ++k) { + for (unsigned int j = 0; j < config_.distServer1_nIn(); ++j) { + auto& tc = inTriggerCellDistributionGrid[iClock][config_.distServer1_nOut() * config_.distServer1_nIn() * i + + config_.distServer1_nOut() * j + k]; + if (tc->dataValid()) { + tc->setIndex((config_.distServer1_nOut() * config_.distServer1_nIn() * i) + + (config_.distServer1_nIn() * k) + j); + triggerCellsOut.push_back(tc); + outTriggerCellDistributionGrid[iClock - 2][tc->index()] = tc; + } + } + } + } + } +} + +// In each group of 5 streams, assign fine phi index to each TC (0-5) +void HGCalTCDistribution::triggerCellDistribution4(const HGCalTriggerCellSAShrPtrCollection& triggerCellsIn) const { + const unsigned int stepLatency = config_.getStepLatency(Dist4); + for (auto& lCell : triggerCellsIn) { + lCell->addLatency(stepLatency); + unsigned int sector = int( + lCell->index() / + (config_.nDistServers1() / + config_ + .n60Sectors())); // Is config_.nDistServers1() / config_.n60Sectors() correct? Equal to 5, which is what's needed (don't think it's a coincidence...) + for (int iSortKey = config_.nCoarsePhiDist2() - 1; iSortKey >= 0; --iSortKey) { + if (int(lCell->phi() % config_.phiNValues()) > + int((config_.n60Sectors() * config_.distServer1_nOut() * iSortKey) + (config_.cColumns() * sector))) { + lCell->setSortKey(iSortKey); + break; + } + } + } +} + +// Second distribution layer +// Use 18 5-to-6 distribution servers to merge multiple streams into 18x6=108 streams (corresponding to the number of histogram bins in phi) +// Within each 18x5 groups of streams, 1 distribution server organises the TCs into 6 streams. The 6 streams correspond to the TCs with the same fine phi index i.e the same histogram bin in phi +// Not enough documentation on distribution server vhdl to give more meaningful comments +void HGCalTCDistribution::triggerCellDistribution5( + const HGCalTriggerCellSAShrPtrCollections& inTriggerCellDistributionGrid, + HGCalTriggerCellSAPtrCollection& triggerCellsOut) const { + const unsigned int latency = config_.getLatencyUpToAndIncluding(Dist5); + + // Dummy distribution grid? After writing the runDistServers function to avoid duplicating identical code from triggerCellDistribution2, I realised the second possible use case of runDistServers isn't completely identical i.e. the triggerCellDistributionGrid isn't used/set + HGCalTriggerCellSAShrPtrCollections outTriggerCellDistributionGrid; + HGCalTriggerCellSAShrPtrCollection triggerCellsOutTemp; + runDistServers(inTriggerCellDistributionGrid, + outTriggerCellDistributionGrid, + triggerCellsOutTemp, + latency, + config_.nDistServers2(), + config_.distServer2_nIn(), + config_.distServer2_nOut(), + config_.distServer2_nInterleave(), + false); + + // Convert final output to unique_ptr + triggerCellsOut.clear(); + for (const auto& tc : triggerCellsOutTemp) { + triggerCellsOut.push_back(make_unique(*tc)); + } +} + +// Initialize distribution grids with invalid TCs +void HGCalTCDistribution::initializeTriggerCellDistGrid(HGCalTriggerCellSAShrPtrCollections& grid, + unsigned int nX, + unsigned int nY) const { + for (unsigned int iX = 0; iX < nX; ++iX) { + HGCalTriggerCellSAShrPtrCollection temp; + for (unsigned int iY = 0; iY < nY; ++iY) { + temp.emplace_back(make_shared()); + } + grid.push_back(temp); + } +} + +// Not enough documentation on distribution server vhdl to give meaningful comments +void HGCalTCDistribution::runDistServers(const HGCalTriggerCellSAShrPtrCollections& gridIn, + HGCalTriggerCellSAShrPtrCollections& gridOut, + HGCalTriggerCellSAShrPtrCollection& tcsOut, + unsigned int latency, + unsigned int nDistServers, + unsigned int nInputs, + unsigned int nOutputs, + unsigned int nInterleave, + bool setOutputGrid) const { + vector distServers(nDistServers, DistServer(nInputs, nOutputs, nInterleave)); + + for (unsigned int iClock = 0; iClock < config_.cClocks(); ++iClock) { + for (unsigned int iDistServer = 0; iDistServer < nDistServers; ++iDistServer) { + auto first = gridIn[iClock].cbegin() + nInputs * iDistServer; + auto last = gridIn[iClock].cbegin() + nInputs * (iDistServer + 1); + HGCalTriggerCellSAShrPtrCollection inCells(first, last); + HGCalTriggerCellSAShrPtrCollection lCells = distServers[iDistServer].clock(inCells); + + for (unsigned int iOutput = 0; iOutput < lCells.size(); ++iOutput) { + auto& tc = lCells[iOutput]; + if (tc->dataValid()) { + tc->setIndex(nOutputs * iDistServer + iOutput); + tc->setClock(iClock + latency); + + tcsOut.push_back(tc); + if (setOutputGrid) { + gridOut[iClock][tc->index()] = tc; + } + } + } + } + } +} diff --git a/L1Trigger/L1THGCal/src/backend_emulator/HGCalTriggerCell_SA.cc b/L1Trigger/L1THGCal/src/backend_emulator/HGCalTriggerCell_SA.cc new file mode 100644 index 0000000000000..b842325eacfd9 --- /dev/null +++ b/L1Trigger/L1THGCal/src/backend_emulator/HGCalTriggerCell_SA.cc @@ -0,0 +1,13 @@ +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalTriggerCell_SA.h" + +using namespace l1thgcfirmware; + +bool HGCalTriggerCell::operator==(const HGCalTriggerCell& rhs) const { + bool isEqual = (this->index() == rhs.index()); + return isEqual; +} + +bool HGCalTriggerCell::operator==(const std::shared_ptr& rhs) const { + bool isEqual = (this->index() == rhs->index()); + return isEqual; +} diff --git a/L1Trigger/L1THGCalUtilities/BuildFile.xml b/L1Trigger/L1THGCalUtilities/BuildFile.xml index ead19a7b6e233..2f88756920a0c 100644 --- a/L1Trigger/L1THGCalUtilities/BuildFile.xml +++ b/L1Trigger/L1THGCalUtilities/BuildFile.xml @@ -4,6 +4,7 @@ + diff --git a/L1Trigger/L1THGCalUtilities/interface/patternFiles/codecs_clusters.h b/L1Trigger/L1THGCalUtilities/interface/patternFiles/codecs_clusters.h new file mode 100644 index 0000000000000..3fe67b4fdfe26 --- /dev/null +++ b/L1Trigger/L1THGCalUtilities/interface/patternFiles/codecs_clusters.h @@ -0,0 +1,17 @@ +#ifndef L1Trigger_L1TriggerUtilities_patternFiles_codecs_clusters_h +#define L1Trigger_L1TriggerUtilities_patternFiles_codecs_clusters_h + +#include +#include + +#include "ap_int.h" + +#include "DataFormats/Common/interface/View.h" +#include "L1Trigger/DemonstratorTools/interface/BoardData.h" +#include "DataFormats/L1THGCal/interface/HGCalCluster_HW.h" + +namespace l1thgcfirmware { + std::vector decodeClusters(const std::array>, 4> &); +} + +#endif \ No newline at end of file diff --git a/L1Trigger/L1THGCalUtilities/plugins/BuildFile.xml b/L1Trigger/L1THGCalUtilities/plugins/BuildFile.xml index 76061421f72b4..d56c4d1128689 100644 --- a/L1Trigger/L1THGCalUtilities/plugins/BuildFile.xml +++ b/L1Trigger/L1THGCalUtilities/plugins/BuildFile.xml @@ -15,3 +15,10 @@ + + + + + + + diff --git a/L1Trigger/L1THGCalUtilities/plugins/patternFiles/Stage2FileReader.cc b/L1Trigger/L1THGCalUtilities/plugins/patternFiles/Stage2FileReader.cc new file mode 100644 index 0000000000000..bb42e262605bf --- /dev/null +++ b/L1Trigger/L1THGCalUtilities/plugins/patternFiles/Stage2FileReader.cc @@ -0,0 +1,218 @@ +// -*- C++ -*- +// +// Package: L1Trigger/L1THGCalUtilities +// Class: Stage2FileReader +// +/**\class Stage2FileReader Stage2FileReader.cc L1Trigger/L1THGCalUtilities/plugins/patternFiles/Stage2FileReader.cc + + Description: EDAnalyzer for reading I/O buffer files for hardware/firmware tests of HGC stage 2 + + Implementation: + [Notes on implementation] +*/ +// +// Original Author: Emyr Clement +// Created: Tue, 13 Apr 2022 +// +// + +// system include files +#include + +// user include files +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/stream/EDProducer.h" + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/StreamID.h" + +#include "DataFormats/L1THGCal/interface/HGCalMulticluster.h" +#include "DataFormats/L1THGCal/interface/HGCalCluster_HW.h" +#include "L1Trigger/DemonstratorTools/interface/BoardDataReader.h" +#include "L1Trigger/DemonstratorTools/interface/utilities.h" +#include "L1Trigger/L1THGCalUtilities/interface/patternFiles/codecs_clusters.h" + +// +// class declaration +// + +class Stage2FileReader : public edm::stream::EDProducer<> { +public: + explicit Stage2FileReader(const edm::ParameterSet&); + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + +private: + // ----------constants, enums and typedefs --------- + static constexpr size_t kFramesPerTMUXPeriod = 9; + static constexpr size_t kGapLengthOutput = 0; + static constexpr size_t kS2BoardTMUX = 18; + static constexpr size_t kEmptyFrames = 0; + + const std::map>> + kChannelSpecsOutputToL1T = { + /* logical channel within time slice -> {{link TMUX, inter-packet gap}, vector of channel indices} */ + {{"towersAndClusters", 0}, {{kS2BoardTMUX, kGapLengthOutput}, {84}}}, + {{"towersAndClusters", 1}, {{kS2BoardTMUX, kGapLengthOutput}, {85}}}, + {{"towersAndClusters", 2}, {{kS2BoardTMUX, kGapLengthOutput}, {86}}}, + {{"towersAndClusters", 3}, {{kS2BoardTMUX, kGapLengthOutput}, {87}}} + }; + + // ----------member functions ---------------------- + void produce(edm::Event&, const edm::EventSetup&) override; + std::vector getRefHWClusters( const l1t::HGCalMulticlusterBxCollection& refClusters, const unsigned int iSector ); + void compareClustersToRef( std::vector clusters, std::vector refClusters ); + + // ----------member data --------------------------- + l1t::demo::BoardDataReader fileReader_; + + edm::EDGetTokenT refClustersToken_; + + unsigned int sector_; + unsigned int nClusters_; + +}; + +// +// class implementation +// + +Stage2FileReader::Stage2FileReader(const edm::ParameterSet& iConfig) + : fileReader_(l1t::demo::parseFileFormat(iConfig.getUntrackedParameter("format")), + iConfig.getParameter>("files"), + kFramesPerTMUXPeriod, + kS2BoardTMUX, + kEmptyFrames, + kChannelSpecsOutputToL1T), + refClustersToken_(consumes(iConfig.getUntrackedParameter("refClustersTag"))), + sector_(iConfig.getUntrackedParameter("sector")), + nClusters_(0) + { + produces(); +} + +// ------------ method called to produce the data ------------ +void Stage2FileReader::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) { + using namespace edm; +// using namespace l1t::demo::codecs; + + l1t::demo::EventData eventData(fileReader_.getNextEvent()); + + const unsigned bitsPerWord = 64; + const unsigned wordsPerCluster = 4; + std::array>, wordsPerCluster> clusterWords; + for ( unsigned iWord = 0; iWord < wordsPerCluster; ++iWord ) { + clusterWords.at(iWord) = eventData.at({"towersAndClusters", iWord}); + } + + + std::vector hwClusters = l1thgcfirmware::decodeClusters(clusterWords); + + // Ref clusters + const l1t::HGCalMulticlusterBxCollection refClusters = iEvent.get(refClustersToken_); + std::vector refHWClusters = getRefHWClusters( refClusters, sector_ ); + + compareClustersToRef( hwClusters, refHWClusters ); + std::cout << "N clusters so far : " << nClusters_ << std::endl; +} + +std::vector Stage2FileReader::getRefHWClusters( const l1t::HGCalMulticlusterBxCollection& refClusters, const unsigned int iSector ) { + + // Decode which zside and sector we are extracting data for + int zside = (iSector > 2) ? 1 : -1; + unsigned int sector = iSector % 3; + if ( zside == 1 ) { + if ( sector == 1 ) sector = 2; + else if ( sector == 2 ) sector = 1; + } + + std::vector refHWClusters; + unsigned int iCluster = 0; + for (auto cl3d_itr = refClusters.begin(0); cl3d_itr != refClusters.end(0); cl3d_itr++) { + if ( cl3d_itr->getHwZSide() != zside ) continue; + if ( cl3d_itr->getHwSector() != sector ) continue; + + ++iCluster; + if ( iCluster > 160 ) break; + + const auto& clusterWords = cl3d_itr->getHwData(); + refHWClusters.emplace_back( l1thgcfirmware::HGCalCluster_HW::unpack(clusterWords) ); + } + return refHWClusters; +} + +void Stage2FileReader::compareClustersToRef( std::vector clusters, std::vector refClusters ) { + nClusters_ += refClusters.size(); + if ( clusters.size() != refClusters.size() ) { + std::cout << "---> Different number of clusters : " << refClusters.size() << " " << clusters.size() << std::endl; + // return; + } + + bool allGood = true; + for ( unsigned int iCluster = 0; iCluster < refClusters.size(); ++iCluster ) { // BUG IN FIRMWARE!!! First event has duplicate cluster, all others missing last cluster... + if ( iCluster >= clusters.size() ) { + std::cout << "Skipping extra ref cluster : " << iCluster << std::endl; + break; + } + const auto& refCluster = refClusters.at(iCluster); + const auto& cluster = clusters.at(iCluster); // BUG IN FIRMWARE!!! First event has duplicate cluster, all others missing last cluster... + if ( cluster != refCluster ) { + std::cout << "Cluster comparison : " << iCluster << std::endl; + // Catch common/known issues + if ( cluster.sigma_roz == 127 && refCluster.sigma_roz != 127 ) { + std::cout << "Saturated sigma r/z r/z in firmware" << std::endl; + allGood = false; + continue; + } + if ( abs(refCluster.w_eta - cluster.w_eta) == 1 ) { + std::cout << "Etas differ by one bit" << std::endl; + continue; + } + if ( clusters.size() > iCluster+1) { + if ( refCluster == clusters.at(iCluster+1 )) { + std::cout << "Cluster ordering out by one" << std::endl; + continue; + } + } + std::cout << "---> e : " << refCluster.e << " " << cluster.e << std::endl; + std::cout << "---> e EM : " << refCluster.e_em << " " << cluster.e_em << std::endl; + std::cout << "---> eta : " << refCluster.w_eta << " " << cluster.w_eta << std::endl; + std::cout << "---> phi : " << refCluster.w_phi << " " << cluster.w_phi << std::endl; + std::cout << "---> z : " << refCluster.w_z << " " << cluster.w_z << std::endl; + std::cout << "---> sigma r/z : " << refCluster.sigma_roz << " " << cluster.sigma_roz << std::endl; + std::cout << "-----------------------------------" << std::endl; + allGood = false; + } + } + + if ( allGood ) std::cout << "---> Good event, all match" << std::endl; + + // for (const auto& refCluster : refClusters ) { + // std::cout << "Ref cluster : " << refCluster.e << " " << refCluster.w_z << std::endl; + // } + // for (const auto& cluster : clusters ) { + // if (cluster.e == 0 ) continue; + // std::cout << "Cluster : " << cluster.e << " " << cluster.w_z << std::endl; + // } + +} + +// ------------ method fills 'descriptions' with the allowed parameters for the module ------------ +void Stage2FileReader::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + // Stage2FileReader + edm::ParameterSetDescription desc; + desc.add>("files", + { + "HGCS2OutputToL1TFile_Sector0_0.txt", + }); + desc.addUntracked("format", "EMPv2"); + desc.addUntracked("refClustersTag", edm::InputTag("l1tHGCalBackEndLayer2Producer", "HGCalBackendLayer2Processor3DClusteringSA")); + desc.addUntracked("sector", 0); + descriptions.add("Stage2FileReader", desc); +} + +//define this as a plug-in +DEFINE_FWK_MODULE(Stage2FileReader); \ No newline at end of file diff --git a/L1Trigger/L1THGCalUtilities/plugins/patternFiles/Stage2FileWriter.cc b/L1Trigger/L1THGCalUtilities/plugins/patternFiles/Stage2FileWriter.cc new file mode 100644 index 0000000000000..d29968f1888bf --- /dev/null +++ b/L1Trigger/L1THGCalUtilities/plugins/patternFiles/Stage2FileWriter.cc @@ -0,0 +1,309 @@ +// -*- C++ -*- +// +// Package: L1Trigger/L1THGCalUtilities +// Class: Stage2FileWriter +// +/**\class Stage2FileWriter Stage2FileWriter.cc L1Trigger/L1THGCalUtilities/plugins/patternFiles/Stage2FileWriter.cc + + Description: EDAnalyzer for writing I/O buffer files for hardware/firmware tests of HGC stage 2 + + Implementation: + [Notes on implementation] +*/ +// +// Original Author: Emyr Clement +// Created: Tue, 13 Apr 2022 +// +// + +// system include files +#include + +// user include files +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/one/EDAnalyzer.h" + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/InputTag.h" + +#include "DataFormats/L1THGCal/interface/HGCalMulticluster.h" +#include "DataFormats/L1THGCal/interface/HGCalCluster_HW.h" +#include "DataFormats/Common/interface/View.h" + +#include "L1Trigger/DemonstratorTools/interface/BoardDataWriter.h" +#include "L1Trigger/DemonstratorTools/interface/utilities.h" + +#include "ap_int.h" + +// +// class declaration +// + +class Stage2FileWriter : public edm::one::EDAnalyzer { +public: + explicit Stage2FileWriter(const edm::ParameterSet&); + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + +private: + // ----------constants, enums and typedefs --------- + static constexpr size_t kFramesPerTMUXPeriod = 9; + static constexpr size_t kGapLengthOutput = 0; + static constexpr size_t kS2BoardTMUX = 18; + static constexpr size_t kMaxLinesPerFile = 648; + + const std::map>> + kChannelSpecsOutputToL1T = { + /* logical channel within time slice -> {{link TMUX, inter-packet gap}, vector of channel indices} */ + {{"towersAndClusters", 0}, {{kS2BoardTMUX, kGapLengthOutput}, {81}}}, + {{"towersAndClusters", 1}, {{kS2BoardTMUX, kGapLengthOutput}, {82}}}, + {{"towersAndClusters", 2}, {{kS2BoardTMUX, kGapLengthOutput}, {83}}}, + {{"towersAndClusters", 3}, {{kS2BoardTMUX, kGapLengthOutput}, {84}}} + }; + + const std::map>> + kChannelSpecsClusterSumsInput = { + /* logical channel within time slice -> {{link TMUX, inter-packet gap}, vector of channel indices} */ + {{"clusterSumRecord", 0}, {{kS2BoardTMUX, kGapLengthOutput}, {80}}}, + {{"clusterSumRecord", 1}, {{kS2BoardTMUX, kGapLengthOutput}, {81}}}, + {{"clusterSumRecord", 2}, {{kS2BoardTMUX, kGapLengthOutput}, {82}}}, + {{"clusterSumRecord", 3}, {{kS2BoardTMUX, kGapLengthOutput}, {83}}}, + {{"clusterSumRecord", 4}, {{kS2BoardTMUX, kGapLengthOutput}, {84}}}, + {{"clusterSumRecord", 5}, {{kS2BoardTMUX, kGapLengthOutput}, {85}}}, + {{"clusterSumRecord", 6}, {{kS2BoardTMUX, kGapLengthOutput}, {86}}}, + {{"clusterSumRecord", 7}, {{kS2BoardTMUX, kGapLengthOutput}, {87}}}, + }; + + // typedef TTTrack Track_t; + + // ----------member functions ---------------------- + void analyze(const edm::Event&, const edm::EventSetup&) override; + void endJob() override; + + std::array>, 4> encodeTowersAndClusters(const l1t::HGCalMulticlusterBxCollection&, const unsigned int iSector ); + + std::array>, 8> encodeClusterSumRecord(const l1t::HGCalMulticlusterBxCollection&, const unsigned int iSector ); + + // ----------member data --------------------------- + edm::EDGetTokenT clustersToken_; + + std::vector fileWritersOutputToL1T_; + std::vector fileWritersClusterSumsInput_; + unsigned int tmIndex_; + unsigned int eventCounter_; +}; + +// +// class implementation +// + +Stage2FileWriter::Stage2FileWriter(const edm::ParameterSet& iConfig) + : clustersToken_(consumes(iConfig.getUntrackedParameter("clusters"))), + tmIndex_(iConfig.getUntrackedParameter("tmIndex")), + eventCounter_(0) { + for ( unsigned int iFileWriter=0; iFileWriter < 6; ++iFileWriter ) { + fileWritersOutputToL1T_.emplace_back(l1t::demo::parseFileFormat(iConfig.getUntrackedParameter("format")), + std::string("hgc_sec")+std::to_string(iFileWriter)+"_tm"+std::to_string(tmIndex_)+std::string("-output-ref"), + iConfig.getUntrackedParameter("fileExtension","txt"), + kFramesPerTMUXPeriod, + kS2BoardTMUX, + kMaxLinesPerFile, + kChannelSpecsOutputToL1T); + fileWritersClusterSumsInput_.emplace_back(l1t::demo::parseFileFormat(iConfig.getUntrackedParameter("format")), + std::string("hgc_sec")+std::to_string(iFileWriter)+"_tm"+std::to_string(tmIndex_)+std::string("-input"), + iConfig.getUntrackedParameter("fileExtension"), + kFramesPerTMUXPeriod, + kS2BoardTMUX, + kMaxLinesPerFile, + kChannelSpecsClusterSumsInput); + } + } + +void Stage2FileWriter::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) { + using namespace edm; + + // Loop S2 sectors and produce pattern file for each sector + // Would be better to sort clusters into sectors first + for ( unsigned int iSector = 0; iSector < 6; ++iSector ) { + // 1) Encode tower and cluster information onto vectors containing link data + const auto outputData(encodeTowersAndClusters(iEvent.get(clustersToken_), iSector) ); + const auto clusterSumInputData(encodeClusterSumRecord(iEvent.get(clustersToken_), iSector) ); + + // 2) Pack track information into 'event data' object, and pass that to file writer + l1t::demo::EventData eventDataTowersAndClusters; + for (size_t i = 0; i < 4; i++) { + eventDataTowersAndClusters.add({"towersAndClusters", i}, outputData.at(i)); + } + fileWritersOutputToL1T_.at(iSector).addEvent(eventDataTowersAndClusters); + + l1t::demo::EventData eventDataClusterSums; + for (size_t i = 0; i < 8; i++) { + eventDataClusterSums.add({"clusterSumRecord", i}, clusterSumInputData.at(i)); + } + fileWritersClusterSumsInput_.at(iSector).addEvent(eventDataClusterSums); + } + ++eventCounter_; +} + +// ------------ method called once each job just after ending the event loop ------------ +void Stage2FileWriter::endJob() { + // Writing pending events to file before exiting + for ( unsigned int iSector = 0; iSector < 6; ++iSector ) { + fileWritersOutputToL1T_.at(iSector).flush(); + fileWritersClusterSumsInput_.at(iSector).flush(); + } +} + +// ------------ method fills 'descriptions' with the allowed parameters for the module ------------ +void Stage2FileWriter::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + // Stage2FileWriter + edm::ParameterSetDescription desc; + desc.addUntracked("clusters", edm::InputTag("hgcalBackEndLayer2Producer", "HGCalBackendLayer2Processor3DClusteringSA")); + desc.addUntracked("tmIndex", 0); + desc.addUntracked("format", "EMP"); + desc.addUntracked("fileExtension", "txt"); + descriptions.add("Stage2FileWriter", desc); +} + +std::array>, 4> Stage2FileWriter::encodeTowersAndClusters(const l1t::HGCalMulticlusterBxCollection& clusters, const unsigned int iSector ) { + std::array>, 4> output; + + // Decode which zside and sector we are extracting data for + int zside = (iSector > 2) ? 1 : -1; + unsigned int sector = iSector % 3; + if ( zside == 1 ) { + if ( sector == 1 ) sector = 2; + else if ( sector == 2 ) sector = 1; + } + // std::cout << "Sectors : " << iSector << " " << zside << " " << sector << std::endl; + + // First frame empty for alignment + ap_uint<64> packetHeader = 0; + packetHeader(63,48) = 0xabc0; + packetHeader(31,24) = iSector; + for ( unsigned iLink = 0; iLink<4; ++iLink ) { + packetHeader(23,16) = iLink; + output[iLink].push_back( packetHeader ); + } + + // Tower data for this sector + // Dummy data + for ( unsigned int iTowerFrame = 0; iTowerFrame < 30; ++iTowerFrame ) { + output[0].push_back( iTowerFrame*4 + 0 ); + output[1].push_back( iTowerFrame*4 + 1 ); + output[2].push_back( iTowerFrame*4 + 2 ); + output[3].push_back( iTowerFrame*4 + 3 ); + } + + // Cluster data for this sector + unsigned int iCluster = 0; + for (auto cl3d_itr = clusters.begin(0); cl3d_itr != clusters.end(0); cl3d_itr++) { + if ( cl3d_itr->getHwZSide() != zside ) continue; + if ( cl3d_itr->getHwSector() != sector ) continue; + + ++iCluster; + if ( iCluster > 160 ) break; + // if ( sector == 0 && zside == -1 ) { + // std::cout << "Cluster pt, eta, phi, nTC, : " << sector << " " << cl3d_itr->pt() << " " << cl3d_itr->eta() << " " << cl3d_itr->phi() << " " << cl3d_itr->constituents().size() << " " << cl3d_itr->hw_sigma_e_quotient() << " " << cl3d_itr->hw_sigma_e_fraction() << std::endl; + // } + // << " " << cl3d_itr->getHwData()[0].to_string() << std::endl; + // std::cout << "Phi, eta : " << cl3d_itr->phi() << " " << cl3d_itr->eta() << " " << cl3d_itr->getHwData()[1].to_string() << std::endl; + const auto& clusterWords = cl3d_itr->getHwData(); + // std::cout << "Cluster words : " ; + // for (const auto& word : clusterWords ) std::cout << word << " "; + // std::cout << std::endl; + output[0].push_back( clusterWords[0] ); + output[1].push_back( clusterWords[1] ); + output[2].push_back( clusterWords[2] ); + output[3].push_back( clusterWords[3] ); + + // if ( sector == 0 && zside == -1 ) { + + // const auto unpacked = l1thgcfirmware::HGCalCluster_HW::unpack(cl3d_itr->getHwData()); + // if ( abs( cl3d_itr->pt() - unpacked.e*0.25 ) > 0.001 || + // abs( cl3d_itr->iPt(l1t::HGCalMulticluster::EnergyInterpretation::EM) - unpacked.e_em*0.25 ) > 0.001 || + // abs( abs(cl3d_itr->eta()) - unpacked.w_eta * M_PI/720 ) > 0.001 || + // abs( cl3d_itr->phi() - ( unpacked.w_phi * M_PI/720 + M_PI / 2 ) ) > 0.001 || + // abs( cl3d_itr->zBarycenter() - unpacked.w_z * 0.05 ) > 0.001 || + // abs( cl3d_itr->sigmaRRTot() - unpacked.sigma_roz * 0.0001920625 ) > 0.001 + // ) { + // std::cout << "---> PANIC : Comparing unpacked hw data with edm object" << std::endl; + // std::cout << cl3d_itr->pt() << " " << unpacked.e*0.25 << std::endl; + // std::cout << cl3d_itr->iPt(l1t::HGCalMulticluster::EnergyInterpretation::EM) << " " << unpacked.e_em*0.25 << std::endl; + // std::cout << abs(cl3d_itr->eta()) << " " << unpacked.w_eta * M_PI/720 << std::endl; + // std::cout << cl3d_itr->phi() << " " << unpacked.w_phi * M_PI/720 + M_PI / 2 << std::endl; + // std::cout << cl3d_itr->zBarycenter() << " " << unpacked.w_z * 0.05 << std::endl; + // std::cout << cl3d_itr->sigmaRRTot() << " " << unpacked.sigma_roz * 0.0001920625 << std::endl; + // } + // } + + } + + return output; +} + +std::array>, 8> Stage2FileWriter::encodeClusterSumRecord(const l1t::HGCalMulticlusterBxCollection& clusters, const unsigned int iSector ) { + + std::array>, 8> output; + + // Decode which zside and sector we are extracting data for + int zside = (iSector > 2) ? 1 : -1; + unsigned int sector = iSector % 3; + if ( zside == 1 ) { + if ( sector == 1 ) sector = 2; + else if ( sector == 2 ) sector = 1; + } + // std::cout << "Sectors : " << iSector << " " << zside << " " << sector << std::endl; + + ap_uint<16> eventCount = eventCounter_; + ap_uint<8> boardID = iSector; + ap_uint<8> tmIndex = 0; + + ap_uint<64> headerWord = (eventCount, boardID, tmIndex, ap_uint<32>(0)); + + unsigned int nClusterSums = 0; + + for (auto cl3d_itr = clusters.begin(0); cl3d_itr != clusters.end(0); cl3d_itr++) { + if ( cl3d_itr->getHwZSide() != zside ) continue; + if ( cl3d_itr->getHwSector() != sector ) continue; + + // ++iCluster; + // if ( iCluster > 160 ) break; + // std::cout << "Adding cluster, sector : " << iSector << " " << zside << " " << sector << " " << cl3d_itr->pt() << " " << cl3d_itr->eta() << " " << cl3d_itr->phi() << " " << cl3d_itr->size() << std::endl; + // << " " << cl3d_itr->getHwData()[0].to_string() << std::endl; + // std::cout << "Phi, eta : " << cl3d_itr->phi() << " " << cl3d_itr->eta() << " " << cl3d_itr->getHwData()[1].to_string() << std::endl; + const auto& clusterSumWords = cl3d_itr->getHwClusterSumData(); + for ( unsigned iWord = 0; iWord < 7; ++iWord ) { + // std::cout << "Cluster sum word : " << iWord << " " << clusterSumWords[iWord] << std::endl; + output[iWord].push_back( clusterSumWords[iWord] ); + } + output[7].push_back( headerWord ); + ++nClusterSums; + } + // std::cout << "Added all clusters" << std::endl; + + // Add dummy entry if there weren't any cluster sums in this sector in this event + if ( output[0].size() == 0 ) { + for ( unsigned iWord = 0; iWord < 7; ++iWord ) { + output[iWord].push_back( 0 ); + } + output[7].push_back( headerWord ); + ++nClusterSums; + } + + while ( nClusterSums < 161 ) { + // for ( unsigned iWord = 0; iWord < 7; ++iWord ) { + // output[iWord].push_back( 0 ); + // } + output[7].push_back( headerWord ); + ++nClusterSums; + } + return output; +} + + +//define this as a plug-in +DEFINE_FWK_MODULE(Stage2FileWriter); diff --git a/L1Trigger/L1THGCalUtilities/python/customNtuples.py b/L1Trigger/L1THGCalUtilities/python/customNtuples.py index 1889b0ee12da7..0ed70d416fbe6 100644 --- a/L1Trigger/L1THGCalUtilities/python/customNtuples.py +++ b/L1Trigger/L1THGCalUtilities/python/customNtuples.py @@ -26,6 +26,12 @@ def custom_ntuples_standalone_clustering(process): ntuple.NtupleName=='HGCalTriggerNtupleHGCClusters' or \ ntuple.NtupleName=='HGCalTriggerNtupleHGCMulticlusters': ntuple.Multiclusters = cms.InputTag('l1tHGCalBackEndLayer2Producer:HGCalBackendLayer2Processor3DClusteringSA') + + # Include HW cluster properties in ntupliser + for ntuple in ntuples: + if ntuple.NtupleName.value() == 'HGCalTriggerNtupleHGCMulticlusters': + ntuple.FillHWClusterProperties = True + ntuple.FillLayerInfo = True return process diff --git a/L1Trigger/L1THGCalUtilities/python/hgcalTriggerNtuples_cfi.py b/L1Trigger/L1THGCalUtilities/python/hgcalTriggerNtuples_cfi.py index efd3a8dabe3d0..10b174e0797fb 100644 --- a/L1Trigger/L1THGCalUtilities/python/hgcalTriggerNtuples_cfi.py +++ b/L1Trigger/L1THGCalUtilities/python/hgcalTriggerNtuples_cfi.py @@ -93,7 +93,8 @@ Multiclusters = cms.InputTag('l1tHGCalBackEndLayer2Producer:HGCalBackendLayer2Processor3DClustering'), EGIdentification = egamma_identification_histomax.clone(), FillLayerInfo = cms.bool(False), - FillInterpretationInfo = cms.bool(True) + FillInterpretationInfo = cms.bool(True), + FillHWClusterProperties = cms.bool(False) ) ntuple_towers = cms.PSet( diff --git a/L1Trigger/L1THGCalUtilities/python/stage2FileReader_cff.py b/L1Trigger/L1THGCalUtilities/python/stage2FileReader_cff.py new file mode 100644 index 0000000000000..ffe59df1ba2fe --- /dev/null +++ b/L1Trigger/L1THGCalUtilities/python/stage2FileReader_cff.py @@ -0,0 +1,8 @@ +import FWCore.ParameterSet.Config as cms + +Stage2FileReader = cms.EDProducer('Stage2FileReader', + files = cms.vstring("output_hgcAlgo.txt"), + format = cms.untracked.string("EMPv2"), + refClustersTag = cms.untracked.InputTag("l1tHGCalBackEndLayer2Producer", "HGCalBackendLayer2Processor3DClusteringSA"), + sector = cms.untracked.uint32(0) +) diff --git a/L1Trigger/L1THGCalUtilities/python/stage2FileWriter_cff.py b/L1Trigger/L1THGCalUtilities/python/stage2FileWriter_cff.py new file mode 100644 index 0000000000000..eab7ec3cb893c --- /dev/null +++ b/L1Trigger/L1THGCalUtilities/python/stage2FileWriter_cff.py @@ -0,0 +1,8 @@ +import FWCore.ParameterSet.Config as cms + +Stage2FileWriter = cms.EDAnalyzer('Stage2FileWriter', + clusters = cms.untracked.InputTag("l1tHGCalBackEndLayer2Producer", "HGCalBackendLayer2Processor3DClusteringSA"), + tmIndex = cms.untracked.uint32(0), + format = cms.untracked.string("EMPv2"), + fileExtension = cms.untracked.string("txt") +) diff --git a/L1Trigger/L1THGCalUtilities/src/codecs_clusters.cc b/L1Trigger/L1THGCalUtilities/src/codecs_clusters.cc new file mode 100644 index 0000000000000..9ccaac0830e47 --- /dev/null +++ b/L1Trigger/L1THGCalUtilities/src/codecs_clusters.cc @@ -0,0 +1,22 @@ +#include "L1Trigger/L1THGCalUtilities/interface/patternFiles/codecs_clusters.h" +#include + +namespace l1thgcfirmware { + std::vector decodeClusters(const std::array>, 4>& frames) { + + std::vector clusters; + unsigned nFrames = frames.at(0).size(); + for ( unsigned int iFrame=0; iFrame < nFrames; ++iFrame ) { + if ( iFrame < 31 ) continue; // Skip header and towers + + ClusterWords clusterWords; + for ( unsigned int i=0; i 0 ) clusters.emplace_back( cluster ); + } + return clusters; + } +} \ No newline at end of file diff --git a/L1Trigger/L1THGCalUtilities/test/createFirmwareInputFiles_cfg.py b/L1Trigger/L1THGCalUtilities/test/createFirmwareInputFiles_cfg.py new file mode 100644 index 0000000000000..a53aa30dfd39c --- /dev/null +++ b/L1Trigger/L1THGCalUtilities/test/createFirmwareInputFiles_cfg.py @@ -0,0 +1,72 @@ +import FWCore.ParameterSet.Config as cms +import FWCore.Utilities.FileUtils as FileUtils +import FWCore.ParameterSet.VarParsing as VarParsing + + +# PART 1 : PARSE ARGUMENTS + +options = VarParsing.VarParsing ('analysis') +options.register('tm', + -1, + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.int, + "Time slice of pattern files") +options.parseArguments() + +inputFiles = [] +for filePath in options.inputFiles: + if filePath.endswith(".root"): + inputFiles.append(filePath) + elif filePath.endswith("_cff.py"): + filePath = filePath.replace("/python/","/") + filePath = filePath.replace("/", ".") + inputFilesImport = getattr(__import__(filePath.strip(".py"),fromlist=["readFiles"]),"readFiles") + inputFiles.extend( inputFilesImport ) + else: + inputFiles += FileUtils.loadListFromFile(filePath) + +# PART 2: SETUP MAIN CMSSW PROCESS + +process = cms.Process("Stage2FileWriter") + +process.load('Configuration.Geometry.GeometryExtended2026D88Reco_cff') +process.load('Configuration.Geometry.GeometryExtended2026D88_cff') +process.load('Configuration.StandardSequences.MagneticField_cff') +process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag = GlobalTag(process.GlobalTag, 'auto:upgradePLS3', '') +process.load("FWCore.MessageLogger.MessageLogger_cfi") + +process.source = cms.Source("PoolSource", fileNames = cms.untracked.vstring(inputFiles) ) +process.maxEvents = cms.untracked.PSet( input = cms.untracked.int32(options.maxEvents) ) + +process.load('L1Trigger.L1THGCalUtilities.stage2FileWriter_cff') + +process.MessageLogger.cerr.FwkReport.reportEvery = 1 +process.Timing = cms.Service("Timing", summaryOnly = cms.untracked.bool(True)) + +process.load('FWCore.Modules.preScaler_cfi') + + +if options.tm == 0: + # Time slice 0 + process.preScaler.prescaleFactor = 3 + process.preScaler.prescaleOffset = 1 + process.Stage2FileWriter.tmIndex = 0 +elif options.tm == 6: + # #Time slice 6 + process.preScaler.prescaleFactor = 3 + process.preScaler.prescaleOffset = 2 + process.Stage2FileWriter.tmIndex = 6 +elif options.tm == 12: + # Time slice 12 + process.preScaler.prescaleFactor = 3 + process.preScaler.prescaleOffset = 0 + process.Stage2FileWriter.tmIndex = 12 +else: + print ("Producing pattern files from all time slices...") + process.preScaler.prescaleFactor = 1 + process.preScaler.prescaleOffset = 0 + process.Stage2FileWriter.tmIndex = 99 + +process.p = cms.Path(process.preScaler*process.Stage2FileWriter) diff --git a/L1Trigger/L1THGCalUtilities/test/ntuples/HGCalTriggerNtupleHGCMulticlusters.cc b/L1Trigger/L1THGCalUtilities/test/ntuples/HGCalTriggerNtupleHGCMulticlusters.cc index 34c72aa4df886..dee3807fe6e07 100644 --- a/L1Trigger/L1THGCalUtilities/test/ntuples/HGCalTriggerNtupleHGCMulticlusters.cc +++ b/L1Trigger/L1THGCalUtilities/test/ntuples/HGCalTriggerNtupleHGCMulticlusters.cc @@ -18,6 +18,7 @@ class HGCalTriggerNtupleHGCMulticlusters : public HGCalTriggerNtupleBase { bool fill_layer_info_; bool fill_interpretation_info_; + bool fill_hw_cluster_properties_; std::unique_ptr id_; @@ -55,6 +56,32 @@ class HGCalTriggerNtupleHGCMulticlusters : public HGCalTriggerNtupleBase { std::vector cl3d_quality_; std::vector> cl3d_ipt_; std::vector> cl3d_ienergy_; + + // Hardware cluster properties + std::vector cl3d_sigma_e_quotient_; + std::vector cl3d_sigma_e_fraction_; + std::vector cl3d_Mean_z_quotient_; + std::vector cl3d_Mean_z_fraction_; + std::vector cl3d_Mean_phi_quotient_; + std::vector cl3d_Mean_phi_fraction_; + std::vector cl3d_Mean_eta_quotient_; + std::vector cl3d_Mean_eta_fraction_; + std::vector cl3d_Mean_roz_quotient_; + std::vector cl3d_Mean_roz_fraction_; + std::vector cl3d_sigma_z_quotient_; + std::vector cl3d_sigma_z_fraction_; + std::vector cl3d_sigma_phi_quotient_; + std::vector cl3d_sigma_phi_fraction_; + std::vector cl3d_sigma_eta_quotient_; + std::vector cl3d_sigma_eta_fraction_; + std::vector cl3d_sigma_roz_quotient_; + std::vector cl3d_sigma_roz_fraction_; + std::vector cl3d_e_em_over_e_quotient_; + std::vector cl3d_e_em_over_e_fraction_; + std::vector cl3d_e_em_core_over_e_em_quotient_; + std::vector cl3d_e_em_core_over_e_em_fraction_; + std::vector cl3d_e_h_early_over_e_quotient_; + std::vector cl3d_e_h_early_over_e_fraction_; }; DEFINE_EDM_PLUGIN(HGCalTriggerNtupleFactory, HGCalTriggerNtupleHGCMulticlusters, "HGCalTriggerNtupleHGCMulticlusters"); @@ -62,7 +89,8 @@ DEFINE_EDM_PLUGIN(HGCalTriggerNtupleFactory, HGCalTriggerNtupleHGCMulticlusters, HGCalTriggerNtupleHGCMulticlusters::HGCalTriggerNtupleHGCMulticlusters(const edm::ParameterSet& conf) : HGCalTriggerNtupleBase(conf), fill_layer_info_(conf.getParameter("FillLayerInfo")), - fill_interpretation_info_(conf.getParameter("FillInterpretationInfo")) { + fill_interpretation_info_(conf.getParameter("FillInterpretationInfo")), + fill_hw_cluster_properties_(conf.getParameter("FillHWClusterProperties")) { accessEventSetup_ = false; } @@ -119,6 +147,32 @@ void HGCalTriggerNtupleHGCMulticlusters::initialize(TTree& tree, tree.Branch(withPrefix("ipt"), &cl3d_ipt_); tree.Branch(withPrefix("ienergy"), &cl3d_ienergy_); } + if (fill_hw_cluster_properties_) { + tree.Branch(withPrefix("meanZquotient"), &cl3d_Mean_z_quotient_); + tree.Branch(withPrefix("meanZfraction"), &cl3d_Mean_z_fraction_); + tree.Branch(withPrefix("meanPhiquotient"), &cl3d_Mean_phi_quotient_); + tree.Branch(withPrefix("meanPhifraction"), &cl3d_Mean_phi_fraction_); + tree.Branch(withPrefix("meanEtaquotient"), &cl3d_Mean_eta_quotient_); + tree.Branch(withPrefix("meanEtafraction"), &cl3d_Mean_eta_fraction_); + tree.Branch(withPrefix("meanRoZquotient"), &cl3d_Mean_roz_quotient_); + tree.Branch(withPrefix("meanRoZfraction"), &cl3d_Mean_roz_fraction_); + tree.Branch(withPrefix("sigmaEquotient"), &cl3d_sigma_e_quotient_); + tree.Branch(withPrefix("sigmaEfraction"), &cl3d_sigma_e_fraction_); + tree.Branch(withPrefix("sigmaZquotient"), &cl3d_sigma_z_quotient_); + tree.Branch(withPrefix("sigmaZfraction"), &cl3d_sigma_z_fraction_); + tree.Branch(withPrefix("sigmaPhiquotient"), &cl3d_sigma_phi_quotient_); + tree.Branch(withPrefix("sigmaPhifraction"), &cl3d_sigma_phi_fraction_); + tree.Branch(withPrefix("sigmaEtaquotient"), &cl3d_sigma_eta_quotient_); + tree.Branch(withPrefix("sigmaEtafraction"), &cl3d_sigma_eta_fraction_); + tree.Branch(withPrefix("sigmaRoZquotient"), &cl3d_sigma_roz_quotient_); + tree.Branch(withPrefix("sigmaRoZfraction"), &cl3d_sigma_roz_fraction_); + tree.Branch(withPrefix("energyEMOverEnergyquotient"), &cl3d_e_em_over_e_quotient_); + tree.Branch(withPrefix("energyEMOverEnergyfraction"), &cl3d_e_em_over_e_fraction_); + tree.Branch(withPrefix("energyEMCoreOverEnergyEMquotient"), &cl3d_e_em_core_over_e_em_quotient_); + tree.Branch(withPrefix("energyEMCoreOverEnergyEMfraction"), &cl3d_e_em_core_over_e_em_fraction_); + tree.Branch(withPrefix("energyHEarlyOverEnergyquotient"), &cl3d_e_h_early_over_e_quotient_); + tree.Branch(withPrefix("energyHEarlyOverEnergyfraction"), &cl3d_e_h_early_over_e_fraction_); + } } void HGCalTriggerNtupleHGCMulticlusters::fill(const edm::Event& e, const HGCalTriggerNtupleEventSetup& es) { @@ -187,6 +241,33 @@ void HGCalTriggerNtupleHGCMulticlusters::fill(const edm::Event& e, const HGCalTr cl3d_itr->constituents_end(), cl3d_clusters_id_.back().begin(), [](const std::pair>& id_cl) { return id_cl.second->detId(); }); + + if (fill_hw_cluster_properties_) { + cl3d_sigma_e_quotient_.emplace_back(cl3d_itr->hw_sigma_e_quotient()); + cl3d_sigma_e_fraction_.emplace_back(cl3d_itr->hw_sigma_e_fraction()); + cl3d_Mean_z_quotient_.emplace_back(cl3d_itr->hw_mean_z_quotient()); + cl3d_Mean_z_fraction_.emplace_back(cl3d_itr->hw_mean_z_fraction()); + cl3d_Mean_phi_quotient_.emplace_back(cl3d_itr->hw_mean_phi_quotient()); + cl3d_Mean_phi_fraction_.emplace_back(cl3d_itr->hw_mean_phi_fraction()); + cl3d_Mean_eta_quotient_.emplace_back(cl3d_itr->hw_mean_eta_quotient()); + cl3d_Mean_eta_fraction_.emplace_back(cl3d_itr->hw_mean_eta_fraction()); + cl3d_Mean_roz_quotient_.emplace_back(cl3d_itr->hw_mean_roz_quotient()); + cl3d_Mean_roz_fraction_.emplace_back(cl3d_itr->hw_mean_roz_fraction()); + cl3d_sigma_z_quotient_.emplace_back(cl3d_itr->hw_sigma_z_quotient()); + cl3d_sigma_z_fraction_.emplace_back(cl3d_itr->hw_sigma_z_fraction()); + cl3d_sigma_phi_quotient_.emplace_back(cl3d_itr->hw_sigma_phi_quotient()); + cl3d_sigma_phi_fraction_.emplace_back(cl3d_itr->hw_sigma_phi_fraction()); + cl3d_sigma_eta_quotient_.emplace_back(cl3d_itr->hw_sigma_eta_quotient()); + cl3d_sigma_eta_fraction_.emplace_back(cl3d_itr->hw_sigma_eta_fraction()); + cl3d_sigma_roz_quotient_.emplace_back(cl3d_itr->hw_sigma_roz_quotient()); + cl3d_sigma_roz_fraction_.emplace_back(cl3d_itr->hw_sigma_roz_fraction()); + cl3d_e_em_over_e_quotient_.emplace_back(cl3d_itr->hw_e_em_over_e_quotient()); + cl3d_e_em_over_e_fraction_.emplace_back(cl3d_itr->hw_e_em_over_e_fraction()); + cl3d_e_em_core_over_e_em_quotient_.emplace_back(cl3d_itr->hw_e_em_core_over_e_em_quotient()); + cl3d_e_em_core_over_e_em_fraction_.emplace_back(cl3d_itr->hw_e_em_core_over_e_em_fraction()); + cl3d_e_h_early_over_e_quotient_.emplace_back(cl3d_itr->hw_e_h_early_over_e_quotient()); + cl3d_e_h_early_over_e_fraction_.emplace_back(cl3d_itr->hw_e_h_early_over_e_fraction()); + } } } @@ -224,4 +305,28 @@ void HGCalTriggerNtupleHGCMulticlusters::clear() { cl3d_quality_.clear(); cl3d_ipt_.clear(); cl3d_ienergy_.clear(); + cl3d_sigma_e_quotient_.clear(); + cl3d_sigma_e_fraction_.clear(); + cl3d_Mean_z_quotient_.clear(); + cl3d_Mean_z_fraction_.clear(); + cl3d_Mean_phi_quotient_.clear(); + cl3d_Mean_phi_fraction_.clear(); + cl3d_Mean_eta_quotient_.clear(); + cl3d_Mean_eta_fraction_.clear(); + cl3d_Mean_roz_quotient_.clear(); + cl3d_Mean_roz_fraction_.clear(); + cl3d_sigma_z_quotient_.clear(); + cl3d_sigma_z_fraction_.clear(); + cl3d_sigma_phi_quotient_.clear(); + cl3d_sigma_phi_fraction_.clear(); + cl3d_sigma_eta_quotient_.clear(); + cl3d_sigma_eta_fraction_.clear(); + cl3d_sigma_roz_quotient_.clear(); + cl3d_sigma_roz_fraction_.clear(); + cl3d_e_em_over_e_quotient_.clear(); + cl3d_e_em_over_e_fraction_.clear(); + cl3d_e_em_core_over_e_em_quotient_.clear(); + cl3d_e_em_core_over_e_em_fraction_.clear(); + cl3d_e_h_early_over_e_quotient_.clear(); + cl3d_e_h_early_over_e_fraction_.clear(); } diff --git a/L1Trigger/L1THGCalUtilities/test/readFirmwareFiles_cfg.py b/L1Trigger/L1THGCalUtilities/test/readFirmwareFiles_cfg.py new file mode 100644 index 0000000000000..c0728a0838a66 --- /dev/null +++ b/L1Trigger/L1THGCalUtilities/test/readFirmwareFiles_cfg.py @@ -0,0 +1,53 @@ +import FWCore.ParameterSet.Config as cms +import FWCore.Utilities.FileUtils as FileUtils +import FWCore.ParameterSet.VarParsing as VarParsing + + +# PART 1 : PARSE ARGUMENTS + +options = VarParsing.VarParsing ('analysis') +options.parseArguments() + +inputFiles = [] +for filePath in options.inputFiles: + if filePath.endswith(".root"): + inputFiles.append(filePath) + else: + inputFiles += FileUtils.loadListFromFile(filePath) + + +# PART 2: SETUP MAIN CMSSW PROCESS + +process = cms.Process("HGCClusterValidation") + +process.load('Configuration.Geometry.GeometryExtended2026D88Reco_cff') +process.load('Configuration.Geometry.GeometryExtended2026D88_cff') +process.load('Configuration.StandardSequences.MagneticField_cff') +process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag = GlobalTag(process.GlobalTag, 'auto:upgradePLS3', '') +process.load("FWCore.MessageLogger.MessageLogger_cfi") + +process.source = cms.Source("PoolSource", fileNames = cms.untracked.vstring(inputFiles) ) +process.maxEvents = cms.untracked.PSet( input = cms.untracked.int32(options.maxEvents) ) +process.load('L1Trigger.L1THGCalUtilities.stage2FileReader_cff') + +process.MessageLogger.cerr.FwkReport.reportEvery = 3 +process.Timing = cms.Service("Timing", summaryOnly = cms.untracked.bool(True)) + +# process.Stage2FileReader.files = cms.vstring("output_hgcAlgo.txt") + +process.Stage2FileReader.files = cms.vstring( + 'output_hgcAlgo_0.txt', + 'output_hgcAlgo_1.txt', + 'output_hgcAlgo_2.txt', + 'output_hgcAlgo_3.txt', + 'output_hgcAlgo_4.txt', + 'output_hgcAlgo_5.txt' + ) + + +process.load('FWCore.Modules.preScaler_cfi') +process.preScaler.prescaleFactor = 3 +process.preScaler.prescaleOffset = 1 +process.p = cms.Path(process.preScaler*process.Stage2FileReader) diff --git a/L1Trigger/L1THGCalUtilities/test/testHGCalL1T_RelValV11_cfg.py b/L1Trigger/L1THGCalUtilities/test/testHGCalL1T_RelValV11_cfg.py index 9abd80aa3ebc7..5dfba11bb3dca 100644 --- a/L1Trigger/L1THGCalUtilities/test/testHGCalL1T_RelValV11_cfg.py +++ b/L1Trigger/L1THGCalUtilities/test/testHGCalL1T_RelValV11_cfg.py @@ -24,12 +24,12 @@ process.maxEvents = cms.untracked.PSet( - input = cms.untracked.int32(50) + input = cms.untracked.int32(1) ) # Input source process.source = cms.Source("PoolSource", - fileNames = cms.untracked.vstring('/store/mc/Phase2HLTTDRSummer20ReRECOMiniAOD/DoublePhoton_FlatPt-1To100/FEVT/PU200_111X_mcRun4_realistic_T15_v1_ext1-v2/1210000/F2E5E947-0CB4-D245-A943-17F2F05709D3.root'), + fileNames = cms.untracked.vstring('file:/hdfs/user/ec6821/HGC/LocalInputs/TTbar_200PU_V11_HLTTDR.root'), inputCommands=cms.untracked.vstring( 'keep *', 'drop l1tEMTFHit2016Extras_simEmtfDigis_CSC_HLT', diff --git a/L1Trigger/L1THGCalUtilities/test/testHGCalL1T_newProcessors_V11_cfg.py b/L1Trigger/L1THGCalUtilities/test/testHGCalL1T_newProcessors_V11_cfg.py index 072674b02cf94..4ea3731f14510 100644 --- a/L1Trigger/L1THGCalUtilities/test/testHGCalL1T_newProcessors_V11_cfg.py +++ b/L1Trigger/L1THGCalUtilities/test/testHGCalL1T_newProcessors_V11_cfg.py @@ -24,12 +24,16 @@ process.maxEvents = cms.untracked.PSet( - input = cms.untracked.int32(50) + input = cms.untracked.int32(1) ) # Input source process.source = cms.Source("PoolSource", - fileNames = cms.untracked.vstring('/store/mc/Phase2HLTTDRWinter20DIGI/SingleElectron_PT2to200/GEN-SIM-DIGI-RAW/PU200_110X_mcRun4_realistic_v3_ext2-v2/40000/00582F93-5A2A-5847-8162-D81EE503500F.root'), + fileNames = cms.untracked.vstring( + # '/store/mc/Phase2HLTTDRWinter20DIGI/SingleElectron_PT2to200/GEN-SIM-DIGI-RAW/PU200_110X_mcRun4_realistic_v3_ext2-v2/40000/00582F93-5A2A-5847-8162-D81EE503500F.root' + 'file:/hdfs/user/ec6821/HGC/LocalInputs/TTbar_200PU_V11_HLTTDR.root' + # 'root://cms-xrd-global.cern.ch//store/mc/Phase2HLTTDRSummer20ReRECOMiniAOD/DoubleElectron_FlatPt-1To100/GEN-SIM-DIGI-RAW-MINIAOD/PU200_111X_mcRun4_realistic_T15_v1-v2/280000/003B8BCB-93B0-4040-854A-04C77E4BD066.root' + ), inputCommands=cms.untracked.vstring( 'keep *', 'drop l1tEMTFHit2016Extras_simEmtfDigis_CSC_HLT', @@ -42,7 +46,8 @@ 'drop MTDTrackingRecHitedmNewDetSetVector_mtdTrackingRecHits__RECO', 'drop BTLDetIdBTLSampleFTLDataFrameTsSorted_mix_FTLBarrel_HLT', 'drop ETLDetIdETLSampleFTLDataFrameTsSorted_mix_FTLEndcap_HLT', - ) + ), + # skipEvents=cms.untracked.uint32(37) ) process.options = cms.untracked.PSet( @@ -76,6 +81,9 @@ process.hgcl1tpg_step = cms.Path(process.L1THGCalTriggerPrimitives) +# Change to custom geometry +from L1Trigger.L1THGCal.customTriggerGeometry import custom_geometry_V11_Imp3 +process = custom_geometry_V11_Imp3(process) # load ntuplizer process.load('L1Trigger.L1THGCalUtilities.hgcalTriggerNtuples_cff') @@ -84,8 +92,30 @@ process = custom_ntuples_standalone_tower(process) process.ntuple_step = cms.Path(process.L1THGCalTriggerNtuples) +process.FEVTDEBUGoutput = cms.OutputModule("PoolOutputModule", + splitLevel = cms.untracked.int32(0), + eventAutoFlushCompressedSize = cms.untracked.int32(5242880), + outputCommands = process.FEVTDEBUGHLTEventContent.outputCommands, + fileName = cms.untracked.string('output_withEmuHGCalClusters.root'), + dataset = cms.untracked.PSet( + filterName = cms.untracked.string(''), + dataTier = cms.untracked.string('GEN-SIM-DIGI-RAW') + ), +) +process.FEVTDEBUGoutput.outputCommands.append( 'drop *') +process.FEVTDEBUGoutput.outputCommands.append( 'keep *_hgcalBackEndLayer2Producer_*_*') + +process.FEVTDEBUGoutput.outputCommands.append( 'drop TrackingParticles_mix_MergedTrackTruth_*') +process.FEVTDEBUGoutput.outputCommands.append( 'drop PixelDigiSimLinkedmDetSetVector_simSiPixelDigis_Tracker_*') +process.FEVTDEBUGoutput.outputCommands.append( 'drop PixelDigiSimLinkedmDetSetVector_simSiPixelDigis_Pixel_*') +process.FEVTDEBUGoutput.outputCommands.append( 'drop SimClusters_mix_MergedCaloTruth_*') +process.FEVTDEBUGoutput.outputCommands.append( 'drop TrackingVertexs_mix_MergedTrackTruth_*') +process.FEVTDEBUGoutput.outputCommands.append( 'drop PixelDigiedmDetSetVector_simSiPixelDigis_Pixel_*') +process.FEVTDEBUGoutput.outputCommands.append( 'drop PCaloHits_g4SimHits_EcalHitsEB_*') +process.endjob_step = cms.EndPath(process.FEVTDEBUGoutput) + # Schedule definition -process.schedule = cms.Schedule(process.hgcl1tpg_step, process.ntuple_step) +process.schedule = cms.Schedule(process.hgcl1tpg_step, process.ntuple_step, process.endjob_step ) # Add early deletion of temporary data products to reduce peak memory need from Configuration.StandardSequences.earlyDeleteSettings_cff import customiseEarlyDelete diff --git a/L1Trigger/L1THGCalUtilities/test/testHGCalL1T_newProcessors_V16_cfg.py b/L1Trigger/L1THGCalUtilities/test/testHGCalL1T_newProcessors_V16_cfg.py new file mode 100644 index 0000000000000..3db70a8f517f3 --- /dev/null +++ b/L1Trigger/L1THGCalUtilities/test/testHGCalL1T_newProcessors_V16_cfg.py @@ -0,0 +1,115 @@ +import FWCore.ParameterSet.Config as cms + +from Configuration.Eras.Era_Phase2C17I13M9_cff import Phase2C17I13M9 +process = cms.Process('DIGI',Phase2C17I13M9) + +# import of standard configurations +process.load('Configuration.StandardSequences.Services_cff') +process.load('SimGeneral.HepPDTESSource.pythiapdt_cfi') +process.load('FWCore.MessageService.MessageLogger_cfi') +process.load('Configuration.EventContent.EventContent_cff') +process.load('SimGeneral.MixingModule.mixNoPU_cfi') +process.load('Configuration.Geometry.GeometryExtended2026D88Reco_cff') +process.load('Configuration.Geometry.GeometryExtended2026D88_cff') +process.load('Configuration.StandardSequences.MagneticField_cff') +process.load('Configuration.StandardSequences.Generator_cff') +process.load('IOMC.EventVertexGenerators.VtxSmearedHLLHC14TeV_cfi') +process.load('GeneratorInterface.Core.genFilterSummary_cff') +process.load('Configuration.StandardSequences.SimIdeal_cff') +process.load('Configuration.StandardSequences.Digi_cff') +process.load('Configuration.StandardSequences.SimL1Emulator_cff') +process.load('Configuration.StandardSequences.DigiToRaw_cff') +process.load('Configuration.StandardSequences.EndOfProcess_cff') +process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') + + +process.maxEvents = cms.untracked.PSet( + input = cms.untracked.int32(100) +) + +# Input source +process.source = cms.Source("PoolSource", + fileNames = cms.untracked.vstring( + 'file:/hdfs/user/ec6821/L1TJets/LocalInputs/TTbar_200PU_Fall22_000c5e5f-78f7-44ee-95fe-7b2f2c2e2312.root' + # 'file:/hdfs/user/ec6821/HGC/LocalInputs/TTbar_0PU_V16_D88.root' + ), + inputCommands=cms.untracked.vstring( + 'keep *', + 'drop l1tPFJets_*_*_*', + 'drop l1tPFTaus_*_*_*', + 'drop l1tTrackerMuons_*_*_*' + ) + ) + +process.options = cms.untracked.PSet( + +) + +# Production Info +process.configurationMetadata = cms.untracked.PSet( + version = cms.untracked.string('$Revision: 1.20 $'), + annotation = cms.untracked.string('SingleElectronPt10_cfi nevts:10'), + name = cms.untracked.string('Applications') +) + +# Output definition +# process.TFileService = cms.Service( +# "TFileService", +# fileName = cms.string("ntuple.root") +# ) + +# Other statements +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag = GlobalTag(process.GlobalTag, 'auto:phase2_realistic_T21', '') + +# load HGCAL TPG simulation +process.load('L1Trigger.L1THGCal.hgcalTriggerPrimitives_cff') + +# Use new processors and standalone algorithms +from L1Trigger.L1THGCal.customNewProcessors import custom_clustering_standalone, custom_tower_standalone +process = custom_clustering_standalone(process) +process = custom_tower_standalone(process) + +process.hgcl1tpg_step = cms.Path(process.L1THGCalTriggerPrimitives) + +# Change to custom geometry +from L1Trigger.L1THGCal.customTriggerGeometry import custom_geometry_V11_Imp3 +process = custom_geometry_V11_Imp3(process) + +# load ntuplizer +# process.load('L1Trigger.L1THGCalUtilities.hgcalTriggerNtuples_cff') +# from L1Trigger.L1THGCalUtilities.customNtuples import custom_ntuples_standalone_clustering, custom_ntuples_standalone_tower +# process = custom_ntuples_standalone_clustering(process) +# process = custom_ntuples_standalone_tower(process) +# process.ntuple_step = cms.Path(process.L1THGCalTriggerNtuples) + +process.FEVTDEBUGoutput = cms.OutputModule("PoolOutputModule", + splitLevel = cms.untracked.int32(0), + eventAutoFlushCompressedSize = cms.untracked.int32(5242880), + outputCommands = process.FEVTDEBUGHLTEventContent.outputCommands, + fileName = cms.untracked.string('output_withEmuHGCalClusters.root'), + dataset = cms.untracked.PSet( + filterName = cms.untracked.string(''), + dataTier = cms.untracked.string('GEN-SIM-DIGI-RAW') + ), +) +# process.FEVTDEBUGoutput.outputCommands.append( 'drop *') +process.FEVTDEBUGoutput.outputCommands.append( 'keep *_hgcalBackEndLayer2Producer_*_*') +process.FEVTDEBUGoutput.outputCommands.append( 'drop TrackingParticles_mix_MergedTrackTruth_*') +process.FEVTDEBUGoutput.outputCommands.append( 'drop PixelDigiSimLinkedmDetSetVector_simSiPixelDigis_Tracker_*') +process.FEVTDEBUGoutput.outputCommands.append( 'drop PixelDigiSimLinkedmDetSetVector_simSiPixelDigis_Pixel_*') +process.FEVTDEBUGoutput.outputCommands.append( 'drop SimClusters_mix_MergedCaloTruth_*') +process.FEVTDEBUGoutput.outputCommands.append( 'drop TrackingVertexs_mix_MergedTrackTruth_*') +process.FEVTDEBUGoutput.outputCommands.append( 'drop PixelDigiedmDetSetVector_simSiPixelDigis_Pixel_*') +process.FEVTDEBUGoutput.outputCommands.append( 'drop PCaloHits_g4SimHits_EcalHitsEB_*') +process.FEVTDEBUGoutput.outputCommands.append( 'drop l1tHGCalTriggerCellBXVector_l1tHGCalVFEProducer_HGCalVFEProcessorSums_*') +process.endjob_step = cms.EndPath(process.FEVTDEBUGoutput) + +# Schedule definition +process.schedule = cms.Schedule(process.hgcl1tpg_step, process.endjob_step) + +# Add early deletion of temporary data products to reduce peak memory need +from Configuration.StandardSequences.earlyDeleteSettings_cff import customiseEarlyDelete +process = customiseEarlyDelete(process) +# End adding early deletion + diff --git a/L1Trigger/Phase2L1GMT/plugins/Phase2L1TGMTFilter.cc b/L1Trigger/Phase2L1GMT/plugins/Phase2L1TGMTFilter.cc new file mode 100644 index 0000000000000..88f2557788058 --- /dev/null +++ b/L1Trigger/Phase2L1GMT/plugins/Phase2L1TGMTFilter.cc @@ -0,0 +1,104 @@ +#include +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/stream/EDProducer.h" + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/StreamID.h" +#include "DataFormats/L1TMuonPhase2/interface/TrackerMuon.h" +#include "DataFormats/L1TMuonPhase2/interface/SAMuon.h" +#include "Node.h" + +// +// class declaration +// +using namespace Phase2L1GMT; +using namespace l1t; + +class Phase2L1TGMTFilter : public edm::stream::EDProducer<> { +public: + explicit Phase2L1TGMTFilter(const edm::ParameterSet&); + ~Phase2L1TGMTFilter() override; + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + +private: + void beginStream(edm::StreamID) override; + void produce(edm::Event&, const edm::EventSetup&) override; + void endStream() override; + edm::EDGetTokenT > srcMuons_; + bool applyLowPtFilter_; + int ptBarrelMin_; + int ptEndcapMin_; + double etaBE_; +}; + +Phase2L1TGMTFilter::Phase2L1TGMTFilter(const edm::ParameterSet& iConfig) + : srcMuons_(consumes >(iConfig.getParameter("srcMuons"))), + applyLowPtFilter_(iConfig.getParameter("applyLowPtFilter")), + ptBarrelMin_(iConfig.getParameter("ptBarrelMin")), + ptEndcapMin_(iConfig.getParameter("ptEndcapMin")), + etaBE_(iConfig.getParameter("etaBE")) { + produces >("l1tTkMuonsGmtLowPtFix").setBranchAlias("tkMuLowPtFix"); +} + +Phase2L1TGMTFilter::~Phase2L1TGMTFilter() { + // do anything here that needs to be done at destruction time + // (e.g. close files, deallocate resources etc.) +} + +// +// member functions +// + +// ------------ method called to produce the data ------------ +void Phase2L1TGMTFilter::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) { + using namespace edm; + Handle > muonHandle; + iEvent.getByToken(srcMuons_, muonHandle); + + std::vector out; + + for (uint i = 0; i < muonHandle->size(); ++i) { + auto mu = muonHandle->at(i); + bool noSAMatch = true; + if (applyLowPtFilter_) { + if ((fabs(mu.phEta()) < etaBE_ && mu.phPt() < ptBarrelMin_) || + (fabs(mu.phEta()) > etaBE_ && mu.phPt() < ptEndcapMin_)) { + // if quality is already set to 0 don't continue the loop. + for (const auto& r : mu.muonRef()) { + if (r.isNonnull()) { + noSAMatch = false; + break; + } + } + if (noSAMatch) + mu.setHwQual(0); + } + } + out.push_back(mu); // store all muons otherwise + } + + // store results + std::unique_ptr > out1 = std::make_unique >(out); + iEvent.put(std::move(out1)); +} + +// ------------ method called once each stream before processing any runs, lumis or events ------------ +void Phase2L1TGMTFilter::beginStream(edm::StreamID) {} + +// ------------ method called once each stream after processing all runs, lumis and events ------------ +void Phase2L1TGMTFilter::endStream() {} + +void Phase2L1TGMTFilter::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + //The following says we do not know what parameters are allowed so do no validation + // Please change this to state exactly what you do use, even if it is no parameters + edm::ParameterSetDescription desc; + desc.setUnknown(); + descriptions.addDefault(desc); +} + +//define this as a plug-in +DEFINE_FWK_MODULE(Phase2L1TGMTFilter); diff --git a/L1Trigger/Phase2L1GMT/python/gmt_cfi.py b/L1Trigger/Phase2L1GMT/python/gmt_cfi.py index e5d24cf7bd955..af95f691ec255 100644 --- a/L1Trigger/Phase2L1GMT/python/gmt_cfi.py +++ b/L1Trigger/Phase2L1GMT/python/gmt_cfi.py @@ -76,6 +76,17 @@ ) + +l1tGMTFilteredMuons = cms.EDProducer('Phase2L1TGMTFilter', + srcMuons = cms.InputTag("l1tTkMuonsGmt",""), + applyLowPtFilter = cms.bool(True), + ptBarrelMin = cms.int32(8), + ptEndcapMin = cms.int32(8), + etaBE = cms.double(0.9) + +) + + l1tStandaloneMuons = cms.EDProducer('Phase2L1TGMTSAMuonProducer', muonToken = cms.InputTag('simGmtStage2Digis'), Nprompt = cms.uint32(12), diff --git a/L1Trigger/Phase2L1ParticleFlow/interface/egamma/pftkegalgo_ref.h b/L1Trigger/Phase2L1ParticleFlow/interface/egamma/pftkegalgo_ref.h index 560325e46cb0c..c1a6a690a4d38 100644 --- a/L1Trigger/Phase2L1ParticleFlow/interface/egamma/pftkegalgo_ref.h +++ b/L1Trigger/Phase2L1ParticleFlow/interface/egamma/pftkegalgo_ref.h @@ -62,8 +62,8 @@ namespace l1ct { 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 id_score_t bdtScore_loose_wp; // Conifer score/4 + const id_score_t bdtScore_tight_wp; // Conifer score/4 const std::string conifer_model; }; @@ -169,7 +169,7 @@ namespace l1ct { const std::vector &emcalo, const std::vector &track, std::vector &emCalo2tk, - std::vector &emCaloTkBdtScore) const; + std::vector &emCaloTkBdtScore) const; struct CompositeCandidate { unsigned int cluster_idx; @@ -177,10 +177,10 @@ namespace l1ct { double dpt; // For sorting }; - float compute_composite_score(CompositeCandidate &cand, - const std::vector &emcalo, - const std::vector &track, - const PFTkEGAlgoEmuConfig::CompIDParameters ¶ms) const; + id_score_t 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; @@ -194,7 +194,7 @@ namespace l1ct { const std::vector &track, const std::vector &emCalo2emCalo, const std::vector &emCalo2tk, - const std::vector &emCaloTkBdtScore, + const std::vector &emCaloTkBdtScore, std::vector &egstas, std::vector &egobjs, std::vector &egeleobjs) const; @@ -208,7 +208,7 @@ namespace l1ct { const unsigned int hwQual, const pt_t ptCorr, const int tk_idx, - const float bdtScore, + const id_score_t bdtScore, const std::vector &components = {}) const; EGObjEmu &addEGStaToPF(std::vector &egobjs, @@ -227,7 +227,7 @@ namespace l1ct { const TkObjEmu &track, const unsigned int hwQual, const pt_t ptCorr, - const float bdtScore) const; + const id_score_t bdtScore) const; // FIXME: reimplemented from PFAlgoEmulatorBase template diff --git a/L1Trigger/Phase2L1ParticleFlow/interface/l1-converters/hgcalinput_ref.h b/L1Trigger/Phase2L1ParticleFlow/interface/l1-converters/hgcalinput_ref.h index 5fd80ba3954d7..6c32530428cd6 100644 --- a/L1Trigger/Phase2L1ParticleFlow/interface/l1-converters/hgcalinput_ref.h +++ b/L1Trigger/Phase2L1ParticleFlow/interface/l1-converters/hgcalinput_ref.h @@ -16,7 +16,7 @@ namespace l1ct { HgcalClusterDecoderEmulator(const edm::ParameterSet &pset); ~HgcalClusterDecoderEmulator(); - l1ct::HadCaloObjEmu decode(const ap_uint<256> &in) const; + l1ct::HadCaloObjEmu decode(const l1ct::PFRegionEmu §or, const ap_uint<256> &in) const; }; } // namespace l1ct diff --git a/L1Trigger/Phase2L1ParticleFlow/plugins/L1CTJetFileWriter.cc b/L1Trigger/Phase2L1ParticleFlow/plugins/L1CTJetFileWriter.cc index f3d21a7c85e1f..82957e57178e1 100644 --- a/L1Trigger/Phase2L1ParticleFlow/plugins/L1CTJetFileWriter.cc +++ b/L1Trigger/Phase2L1ParticleFlow/plugins/L1CTJetFileWriter.cc @@ -55,6 +55,7 @@ L1CTJetFileWriter::L1CTJetFileWriter(const edm::ParameterSet& iConfig) jetsToken_(consumes>(iConfig.getParameter("jets"))), fileWriterOutputToGT_(l1t::demo::parseFileFormat(iConfig.getParameter("format")), iConfig.getParameter("outputFilename"), + iConfig.getParameter("outputFileExtension"), nFramesPerBX_, ctl2BoardTMUX_, maxLinesPerFile_, @@ -108,11 +109,12 @@ void L1CTJetFileWriter::fillDescriptions(edm::ConfigurationDescriptions& descrip edm::ParameterSetDescription desc; desc.add("jets"); desc.add("outputFilename"); + desc.add("outputFileExtension", "txt"); desc.add("nJets", 12); desc.add("nFramesPerBX", 9); desc.add("TMUX", 6); desc.add("maxLinesPerFile", 1024); - desc.add("format", "EMP"); + desc.add("format", "EMPv2"); descriptions.addDefault(desc); } diff --git a/L1Trigger/Phase2L1ParticleFlow/plugins/L1SeedConePFJetProducer.cc b/L1Trigger/Phase2L1ParticleFlow/plugins/L1SeedConePFJetProducer.cc index 5cf255385f433..450269d466a7e 100644 --- a/L1Trigger/Phase2L1ParticleFlow/plugins/L1SeedConePFJetProducer.cc +++ b/L1Trigger/Phase2L1ParticleFlow/plugins/L1SeedConePFJetProducer.cc @@ -8,6 +8,8 @@ #include "FWCore/Framework/interface/Event.h" #include "FWCore/Utilities/interface/InputTag.h" #include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" #include "DataFormats/L1TParticleFlow/interface/PFCandidate.h" #include "DataFormats/L1TParticleFlow/interface/PFJet.h" @@ -23,6 +25,8 @@ class L1SeedConePFJetProducer : public edm::global::EDProducer<> { explicit L1SeedConePFJetProducer(const edm::ParameterSet&); ~L1SeedConePFJetProducer() override; + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + private: /// ///////////////// /// /// MANDATORY METHODS /// @@ -213,5 +217,18 @@ std::vector L1SeedConePFJetProducer::convertHWToEDM( return edmJets; } +void L1SeedConePFJetProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.add("L1PFObjects", edm::InputTag("l1tLayer1", "Puppi")); + desc.add("nJets", 16); + desc.add("coneSize", 0.4); + desc.add("HW", false); + desc.add("debug", false); + desc.add("doCorrections", false); + desc.add("correctorFile", ""); + desc.add("correctorDir", ""); + descriptions.add("l1tSeedConePFJetProducer", desc); +} + #include "FWCore/Framework/interface/MakerMacros.h" DEFINE_FWK_MODULE(L1SeedConePFJetProducer); diff --git a/L1Trigger/Phase2L1ParticleFlow/plugins/L1TCorrelatorLayer1Producer.cc b/L1Trigger/Phase2L1ParticleFlow/plugins/L1TCorrelatorLayer1Producer.cc index d6bd40e646190..28371ad75a63f 100644 --- a/L1Trigger/Phase2L1ParticleFlow/plugins/L1TCorrelatorLayer1Producer.cc +++ b/L1Trigger/Phase2L1ParticleFlow/plugins/L1TCorrelatorLayer1Producer.cc @@ -41,6 +41,8 @@ #include "DataFormats/L1TCorrelator/interface/TkEm.h" #include "DataFormats/L1TCorrelator/interface/TkEmFwd.h" +#include "DataFormats/L1THGCal/interface/HGCalMulticluster.h" +#include "DataFormats/L1THGCal/interface/HGCalCluster_HW.h" //-------------------------------------------------------------------------------------------------- class L1TCorrelatorLayer1Producer : public edm::stream::EDProducer<> { public: @@ -82,6 +84,9 @@ class L1TCorrelatorLayer1Producer : public edm::stream::EDProducer<> { const std::vector patternWriterConfigs_; std::vector> patternWriters_; + // hgcal unpacked debugging + mutable unsigned int debugHGC_; + // region of interest debugging float debugEta_, debugPhi_, debugR_; @@ -106,41 +111,110 @@ class L1TCorrelatorLayer1Producer : public edm::stream::EDProducer<> { // add objects in already-decoded format void addDecodedTrack(l1ct::DetectorSector &sec, const l1t::PFTrack &t); void addDecodedMuon(l1ct::DetectorSector &sec, const l1t::SAMuon &t); - void addDecodedHadCalo(l1ct::DetectorSector &sec, const l1t::PFCluster &t); + void addDecodedHadCalo(l1ct::DetectorSector &sec, + const l1t::PFCluster &t, + const ap_uint<256> rawCaloWord = 0); void addDecodedEmCalo(l1ct::DetectorSector &sec, const l1t::PFCluster &t); - void addRawHgcalCluster(l1ct::DetectorSector> &sec, const l1t::PFCluster &c); + ap_uint<256> addRawHgcalCluster(l1ct::DetectorSector> &sec, const l1t::PFCluster &c); template void rawHgcalClusterEncode(ap_uint<256> &cwrd, const l1ct::DetectorSector &sec, const l1t::PFCluster &c) const { + const l1t::HGCalMulticluster *hgcCluster = + dynamic_cast(c.constituentsAndFractions().front().first.get()); + l1t::HGCalMulticluster::ClusterWords hgcsa = hgcCluster->getHwData(); + l1thgcfirmware::HGCalCluster_HW hgcsaHLS = l1thgcfirmware::HGCalCluster_HW::unpack(hgcsa); + cwrd = 0; ap_ufixed<14, 12, AP_RND_CONV, AP_SAT> w_pt = c.pt(); + ap_uint<14> w_intpt = w_pt.range(); 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_uint<10> w_abseta = round(std::abs(c.eta()) / ETAPHI_LSB); ap_int<9> w_phi = round(sec.region.localPhi(c.phi()) / ETAPHI_LSB); + if (c.eta() > 0) + w_phi = -w_phi; ap_uint<10> w_qual = c.hwQual(); + float f_emf = c.pt() ? c.emEt() / c.pt() : 0; + ap_uint<8> w_emf = std::min(round(256 * std::max(0.f, f_emf)), 255); + ap_uint<8> w_emf_raw = hgcsaHLS.fractionInCE_E; // 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()); + constexpr float HGCAL_SRRTOT_LSB = 0.024584 / (1 << 7); + ap_uint<7> w_srrtot = round(c.sigmaRR() / HGCAL_SRRTOT_LSB); + // depending on the emulator used, absZBarycenter may be defined in absolute coordinates (starts form 320 cm) or relative (starts from 0). + // since the two are disjoint, I can do this ugly thing and support both + ap_uint<12> w_meanz = + round((c.absZBarycenter() > 300 ? std::max(0.f, c.absZBarycenter() - 320) : c.absZBarycenter()) / 0.05); // 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(); + ap_ufixed<10, 5, AP_RND_CONV, AP_SAT> w_hoe_fromRawEmf = 0; + w_hoe_fromRawEmf = 256.0 / (w_emf_raw.to_int() + 0.5) - 1; 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; + cwrd(73, 64) = w_abseta; + cwrd(82, 74) = w_phi; + cwrd(31, 28) = w_qual(3, 0); + cwrd(39, 32) = w_emf; // 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(191, 185) = w_srrtot; cwrd(94, 83) = w_meanz; - cwrd(127, 116) = w_hoe.range(); + //cwrd(127, 116) = w_hoe.range(); + if (debugHGC_ && c.pt() > 0) { + l1t::HGCalMulticluster::ClusterWords me; + for (int w = 0; w < 4; ++w) + me[w] = ap_uint<64>(cwrd(64 * w + 63, 64 * w)).to_uint64(); + printf( + "Packing cluster of pt %8.2f eta %+6.3f phi %+6.3f, emet %8.2f.in sector at eta %+6.3f phi %+6.3f (hwSector " + "%u, hwZSide %d)\n", + c.pt(), + c.eta(), + c.phi(), + c.emEt(), + sec.region.floatEtaCenter(), + sec.region.floatPhiCenter(), + hgcCluster->getHwSector(), + hgcCluster->getHwZSide()); + printf(" CTL1 %016lx.%016lx.%016lx.%016lx\n", me[0], me[1], me[2], me[3]); + printf(" HGCSA %016lx.%016lx.%016lx.%016lx\n", hgcsa[0], hgcsa[1], hgcsa[2], hgcsa[3]); + printf(" match %016lx.%016lx.%016lx.%016lx\n", + ~(me[0] ^ hgcsa[0]), + ~(me[1] ^ hgcsa[1]), + ~(me[2] ^ hgcsa[2]), + ~(me[3] ^ hgcsa[3])); + printf(" pt %5llu %5d\n", w_pt.bits_to_uint64(), hgcsaHLS.e.to_int()); + printf(" empt %5d %5d\n", w_empt.to_int(), hgcsaHLS.e_em.to_int()); + printf(" ieta %5d %5d\n", w_abseta.to_int(), hgcsaHLS.w_eta.to_int()); + printf(" iphi %+5d %+5d (fid: b42 %d, b48 %d, byhand %d)\n", + w_phi.to_int(), + hgcsaHLS.w_phi.to_int(), + int(hgcsaHLS.qualFlags[0]), + int(hgcsaHLS.qualFlags[6]), + int(std::abs(hgcsaHLS.w_phi.to_int()) < sec.region.hwPhiHalfWidth.to_int())); + printf(" zeta %5d %5d (float: %.2f)\n", w_meanz.to_int(), hgcsaHLS.w_z.to_int(), c.absZBarycenter()); + printf(" sRR %5d %5d (float: %.6f)\n", w_srrtot.to_int(), hgcsaHLS.sigma_roz.to_int(), c.sigmaRR()); + printf(" qual %5s %5s \n", + std::bitset<5>(w_qual.to_int()).to_string().c_str(), + std::bitset<5>(hgcsaHLS.gctBits.to_int()).to_string().c_str()); + printf(" EMF %5d %5d (float: %.6f)\n", w_emf.to_int(), hgcsaHLS.fractionInCE_E.to_int(), f_emf); + printf(" H/E %5llu %5llu (float: %.6f, %.6f vs %.6f, diff %.6f)\n", + w_hoe.bits_to_uint64(), + w_hoe_fromRawEmf.bits_to_uint64(), + c.hOverE(), + w_hoe.to_float(), + w_hoe_fromRawEmf.to_float(), + w_hoe.to_float() - w_hoe_fromRawEmf.to_float()); + debugHGC_--; + } + // in the end, we write out the HGCal word since that's the nominal value + for (int w = 0; w < 4; ++w) + cwrd(64 * w + 63, 64 * w) = ap_uint<64>(hgcsa[w]); } // fetching outputs @@ -197,6 +271,7 @@ L1TCorrelatorLayer1Producer::L1TCorrelatorLayer1Producer(const edm::ParameterSet writeRawHgcalCluster_(iConfig.getUntrackedParameter("writeRawHgcalCluster", false)), patternWriterConfigs_(iConfig.getUntrackedParameter>( "patternWriters", std::vector())), + debugHGC_(iConfig.getUntrackedParameter("debugHGC", 0)), debugEta_(iConfig.getUntrackedParameter("debugEta", 0)), debugPhi_(iConfig.getUntrackedParameter("debugPhi", 0)), debugR_(iConfig.getUntrackedParameter("debugR", -1)) { @@ -647,14 +722,36 @@ void L1TCorrelatorLayer1Producer::addMuon(const l1t::SAMuon &mu, l1t::PFCandidat muonRefMap_[&mu] = ref; } void L1TCorrelatorLayer1Producer::addHadCalo(const l1t::PFCluster &c, l1t::PFClusterRef ref) { - int sidx = 0; - for (auto &sec : event_.decoded.hadcalo) { - if (sec.region.contains(c.eta(), c.phi())) { - addDecodedHadCalo(sec, c); - if (writeRawHgcalCluster_) - addRawHgcalCluster(event_.raw.hgcalcluster[sidx], c); + if (writeRawHgcalCluster_) { + const l1t::HGCalMulticluster *hgcCluster = + dynamic_cast(c.constituentsAndFractions().front().first.get()); + unsigned int hw_sidx = hgcCluster->getHwSector(); + int hw_ieta = hgcCluster->getHwZSide(); + // convert to CMSSW sector numbering (increasing in phi for both endcaps) + unsigned int sidx_cmssw = hw_ieta > 0 ? (3 + (hw_sidx > 0 ? 3 - hw_sidx : hw_sidx)) : hw_sidx; + auto &sec = event_.decoded.hadcalo[sidx_cmssw]; + addDecodedHadCalo(sec, c, addRawHgcalCluster(event_.raw.hgcalcluster[sidx_cmssw], c)); + if (debugHGC_ || !sec.region.contains(c.eta(), c.phi())) { + printf( + "Cluster of pt %8.2f eta %+6.3f phi %+6.3f, emet %8.2f.in sector %u at eta %+6.3f phi %+6.3f (hwSector %u, " + "hwZSide %d) %s\n", + c.pt(), + c.eta(), + c.phi(), + c.emEt(), + sidx_cmssw, + sec.region.floatEtaCenter(), + sec.region.floatPhiCenter(), + hw_sidx, + hw_ieta, + sec.region.contains(c.eta(), c.phi()) ? "ok" : " OUTSIDE FIDUCIAL"); + } + } else { + for (auto &sec : event_.decoded.hadcalo) { + if (sec.region.contains(c.eta(), c.phi())) { + addDecodedHadCalo(sec, c); + } } - sidx++; } clusterRefMap_[&c] = ref; } @@ -723,12 +820,50 @@ void L1TCorrelatorLayer1Producer::addDecodedMuon(l1ct::DetectorSector &sec, - const l1t::PFCluster &c) { + const l1t::PFCluster &c, + const ap_uint<256> word) { l1ct::HadCaloObjEmu calo; - ap_uint<256> word = 0; - rawHgcalClusterEncode(word, sec, c); if (hgcalInput_) { - calo = hgcalInput_->decode(word); + calo = hgcalInput_->decode(sec.region, word); + if (debugHGC_ && c.pt() > 0) { + printf("Unpacking cluster of pt %8.2f eta %+6.3f phi %+6.3f, emet %8.2f in sector at eta %+6.3f phi %+6.3f\n", + c.pt(), + c.eta(), + c.phi(), + c.emEt(), + sec.region.floatEtaCenter(), + sec.region.floatPhiCenter()); + printf(" pt %8.2f %8.2f %+8.2f\n", calo.floatPt(), c.pt(), calo.floatPt() - c.pt()); + printf(" empt %8.2f %8.2f %+8.2f\n", calo.floatEmPt(), c.emEt(), calo.floatEmPt() - c.emEt()); + printf(" eta %+8.4f %+8.4f %+8.4f [hw %+8d]\n", + calo.floatEta(), + sec.region.localEta(c.eta()), + calo.floatEta() - sec.region.localEta(c.eta()), + calo.intEta()); + printf(" phi %+8.4f %+8.4f %+8.4f [hw %+8d]\n", + calo.floatPhi(), + sec.region.localPhi(c.phi()), + calo.floatPhi() - sec.region.localPhi(c.phi()), + calo.intPhi()); + printf(" zeta %8.2f %8.2f %+8.2f [hw %8llu]\n", + calo.floatMeanZ(), + c.absZBarycenter(), + calo.floatMeanZ() - c.absZBarycenter(), + calo.hwMeanZ.to_uint64()); + printf(" sRR %8.5f %8.5f %+8.5f [hw %8llu] \n", + calo.floatSrrTot(), + c.sigmaRR(), + calo.floatSrrTot() - c.sigmaRR(), + calo.hwSrrTot.bits_to_uint64()); + printf(" H/E %8.4f %8.4f %+8.4f [hw %8llu]\n", + calo.floatHoe(), + c.hOverE(), + calo.floatHoe() - c.hOverE(), + calo.hwHoe.bits_to_uint64()); + printf(" qual %8s %8s \n", + std::bitset<6>(calo.hwEmID.to_int()).to_string().c_str(), + std::bitset<6>(c.hwEmID()).to_string().c_str()); + } } else { calo.hwPt = l1ct::Scales::makePtFromFloat(c.pt()); calo.hwEta = l1ct::Scales::makeGlbEta(c.eta()) - @@ -744,10 +879,12 @@ void L1TCorrelatorLayer1Producer::addDecodedHadCalo(l1ct::DetectorSector> &sec, const l1t::PFCluster &c) { +ap_uint<256> L1TCorrelatorLayer1Producer::addRawHgcalCluster(l1ct::DetectorSector> &sec, + const l1t::PFCluster &c) { ap_uint<256> cwrd = 0; rawHgcalClusterEncode(cwrd, sec, c); sec.obj.push_back(cwrd); + return cwrd; } void L1TCorrelatorLayer1Producer::addDecodedEmCalo(l1ct::DetectorSector &sec, @@ -1128,7 +1265,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); + tkele.setIdScore(egele.floatIDScore()); 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 54399d8a497a3..a55f6fea5dd12 100644 --- a/L1Trigger/Phase2L1ParticleFlow/plugins/L1TCtL2EgProducer.cc +++ b/L1Trigger/Phase2L1ParticleFlow/plugins/L1TCtL2EgProducer.cc @@ -97,6 +97,7 @@ class L1TCtL2EgProducer : public edm::global::EDProducer<> { dataWriter_ = std::make_unique( l1t::demo::parseFileFormat(conf.getParameter("format")), conf.getParameter("outputFilename"), + conf.getParameter("outputFileExtension"), nFramesPerBX, conf.getParameter("TMUX"), conf.getParameter("maxLinesPerFile"), @@ -351,8 +352,6 @@ 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); } @@ -422,7 +421,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); + tkele.setIdScore(egele.floatIDScore()); return tkele; } diff --git a/L1Trigger/Phase2L1ParticleFlow/python/l1TkEgAlgoEmulator_cfi.py b/L1Trigger/Phase2L1ParticleFlow/python/l1TkEgAlgoEmulator_cfi.py index 4b267ff987db1..9fc1873294725 100644 --- a/L1Trigger/Phase2L1ParticleFlow/python/l1TkEgAlgoEmulator_cfi.py +++ b/L1Trigger/Phase2L1ParticleFlow/python/l1TkEgAlgoEmulator_cfi.py @@ -1,6 +1,7 @@ import FWCore.ParameterSet.Config as cms tkEgAlgoParameters = cms.PSet( + # debug=cms.untracked.uint32(4), nTRACK=cms.uint32(50), # very large numbers for first test nTRACK_EGIN=cms.uint32(50), # very large numbers for first test nEMCALO_EGIN=cms.uint32(50), # very large numbers for first test @@ -53,9 +54,11 @@ 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), + # NOTE: conifer BDT score is log(p/1-p) + # the working points are cuts on BDT output logits [log(p/1-p)]/4 (range -1 to 1 to match the FW dataformat) + # loose_wp=cms.double(-0.181641), + loose_wp=cms.double(-1.), # FIXME: we relax the loose WP for HGC tests + tight_wp=cms.double(0.0527344), model=cms.string("L1Trigger/Phase2L1ParticleFlow/data/compositeID.json") ), ) diff --git a/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer1_cff.py b/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer1_cff.py index 4a0774bdfc3b0..c9c24812e6902 100644 --- a/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer1_cff.py +++ b/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer1_cff.py @@ -326,17 +326,31 @@ hgcalInputConversionParameters = cms.PSet( slim = cms.bool(True) ), - regionizerAlgo = cms.string("Ideal"), - pfAlgo = cms.string("PFAlgoDummy"), - puAlgo = cms.string("LinearizedPuppi"), + regionizerAlgo = cms.string("Multififo"), regionizerAlgoParameters = cms.PSet( useAlsoVtxCoords = cms.bool(True), - ), + nEndcaps = cms.uint32(2), + nClocks = cms.uint32(54), + nTkLinks = cms.uint32(0), + nCaloLinks = cms.uint32(3), + nTrack = cms.uint32(0), + nCalo = cms.uint32(12), + nEmCalo = cms.uint32(12), + nMu = cms.uint32(4), + egInterceptMode = cms.PSet( + afterFifo = cms.bool(True), + emIDMask = cms.uint32(0x1E), + nHADCALO_IN = cms.uint32(12), + nEMCALO_OUT = cms.uint32(12), + ) + ), + pfAlgo = cms.string("PFAlgoDummy"), pfAlgoParameters = cms.PSet( nCalo = cms.uint32(12), nMu = cms.uint32(4), # unused debug = cms.untracked.bool(False) ), + puAlgo = cms.string("LinearizedPuppi"), puAlgoParameters = cms.PSet( nTrack = cms.uint32(0), # unused nIn = cms.uint32(12), diff --git a/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer1_patternWriters_cff.py b/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer1_patternWriters_cff.py index e79e4bae5f6c8..823302c8f1103 100644 --- a/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer1_patternWriters_cff.py +++ b/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer1_patternWriters_cff.py @@ -1,178 +1,217 @@ import FWCore.ParameterSet.Config as cms -eventsPerFile_ = 12 -gttLatency_ = 156+120 -gttNumberOfPVs_ = 10 +_eventsPerFile = 12 +_gttLatency = 156+120 +_gttNumberOfPVs = 10 ##################################################################################################################### ## Barrel configurations: 54 regions, 6 puppi output links, only write out the layer 1 outputs for now -barrelWriterOutputOnly_ = cms.PSet( +_barrelWriterOutputOnly = cms.PSet( partition = cms.string("Barrel"), outputLinksPuppi = cms.vuint32(*range(6)), outputLinkEgamma = cms.int32(6), nEgammaObjectsOut = cms.uint32(16), + nInputFramesPerBX = cms.uint32(9), nOutputFramesPerBX = cms.uint32(9), - fileFormat = cms.string("EMP"), + fileFormat = cms.string("EMPv2"), + inputFileExtension = cms.string("txt.gz"), + outputFileExtension = cms.string("txt.gz"), + maxLinesPerInputFile = cms.uint32(1024), maxLinesPerOutputFile = cms.uint32(1024), - eventsPerFile = cms.uint32(eventsPerFile_), + eventsPerFile = cms.uint32(_eventsPerFile), ) -## Barrel (54) split in 3 eta slices -barrelWriterOutputOnlyEtaConfigs = [ - barrelWriterOutputOnly_.clone( - outputRegions = cms.vuint32(*[18*ie+i for i in range(18)]), - outputFileName = cms.string("l1BarrelEta%d-outputs-ideal" % (ie+1)), - outputBoard = cms.int32(-1), ## can't output e/gamma in eta split regions - outputLinkEgamma = cms.int32(-1), ## since the boards are defined in phi regions - ) for ie in range(3) -] ## Barrel (54) split in 3 phi slices barrelWriterOutputOnlyPhiConfigs = [ - barrelWriterOutputOnly_.clone( + _barrelWriterOutputOnly.clone( outputRegions = cms.vuint32(*[3*ip+9*ie+i for ie in range(6) for i in range(3) ]), outputBoard = cms.int32(ip), - outputFileName = cms.string("l1BarrelPhi%d-outputs-ideal" % (ip+1)) - ) for ip in range(3) -] -## Barrel9 (27) split in phi eta slices -barrel9WriterOutputOnlyPhiConfigs = [ - barrelWriterOutputOnly_.clone( - outputRegions = cms.vuint32(*[3*ip+9*ie+i for ie in range(3) for i in range(3) ]), - outputBoard = cms.int32(ip), - outputFileName = cms.string("l1Barrel9Phi%d-outputs-ideal" % (ip+1)) + outputFileName = cms.string("l1BarrelPhi%d-outputs" % (ip+1)) ) for ip in range(3) ] -barrelWriterConfigs = barrelWriterOutputOnlyPhiConfigs # + barrelWriterOutputOnlyEtaConfigs -barrel9WriterConfigs = [] #barrel9WriterOutputOnlyPhiConfigs +barrelSerenityPhi1Config = barrelWriterOutputOnlyPhiConfigs[0].clone( + tfTimeSlices = cms.VPSet(*[cms.PSet(tfSectors = cms.VPSet(*[ cms.PSet(tfLink = cms.int32(-1)) for s in range(18) ])) for t in range(3)]), + gctSectors = cms.VPSet(*[cms.PSet( + gctLinksHad = cms.vint32(-1,-1), + gctLinksEcal = cms.vint32(-1), + ) for s in range(3)]), + gmtTimeSlices = cms.VPSet(*[cms.PSet(gmtLink = cms.int32(4*17+t)) for t in range(3)]), + gmtNumberOfMuons = cms.uint32(12), + gttLatency = cms.uint32(156+10), + gttNumberOfPVs = cms.uint32(_gttNumberOfPVs), + inputFileName = cms.string("l1BarrelPhi1Serenity-inputs-vu9p"), + outputFileName = cms.string("l1BarrelPhi1Serenity-outputs") +) +barrelSerenityVU9PPhi1Config = barrelSerenityPhi1Config.clone( + gttLink = cms.int32(4*28+3), + inputFileName = cms.string("l1BarrelPhi1Serenity-inputs-vu9p"), + outputFileName = cms.string("l1BarrelPhi1Serenity-outputs") +) +barrelSerenityVU13PPhi1Config = barrelSerenityPhi1Config.clone( + gttLink = cms.int32(4*31+3), + inputFileName = cms.string("l1BarrelPhi1Serenity-inputs-vu13p"), +) +for t in range(3): + for ie in range(2): + for i,s in enumerate([8, 0, 1, 2, 3]): + loglink = 3*(i+5*ie)+t + physlink = loglink+4*1 if loglink < 15 else (loglink-15)+4*25 + barrelSerenityVU9PPhi1Config.tfTimeSlices[t].tfSectors[s+9*ie].tfLink = physlink + physlink = loglink+4*0 if loglink < 15 else (loglink-15)+4*28 + barrelSerenityVU13PPhi1Config.tfTimeSlices[t].tfSectors[s+9*ie].tfLink = physlink +for i,s in enumerate([0,1]): + barrelSerenityVU9PPhi1Config.gctSectors[s].gctLinksHad = [3*i+4*18, 3*i+4*18+1] + barrelSerenityVU9PPhi1Config.gctSectors[s].gctLinksEcal = [3*i+4*18+2] + barrelSerenityVU13PPhi1Config.gctSectors[s].gctLinksHad = [3*i+4*18, 3*i+4*18+1] + barrelSerenityVU13PPhi1Config.gctSectors[s].gctLinksEcal = [3*i+4*18+2] + +barrelWriterConfigs = barrelWriterOutputOnlyPhiConfigs ##################################################################################################################### ## HGcal configuration: write out both inputs and outputs -hgcalWriterConfig_ = cms.PSet( +_hgcalWriterConfig = cms.PSet( partition = cms.string("HGCal"), - outputRegions = cms.vuint32(*[i+9 for i in range(9)]), - outputBoard = cms.int32(1), nEgammaObjectsOut = cms.uint32(16), nInputFramesPerBX = cms.uint32(9), nOutputFramesPerBX = cms.uint32(9), - fileFormat = cms.string("EMP"), + fileFormat = cms.string("EMPv2"), + inputFileExtension = cms.string("txt.gz"), + outputFileExtension = cms.string("txt.gz"), maxLinesPerInputFile = cms.uint32(1024), maxLinesPerOutputFile = cms.uint32(1024), - eventsPerFile = cms.uint32(eventsPerFile_), + eventsPerFile = cms.uint32(_eventsPerFile), tfTimeSlices = cms.VPSet(*[cms.PSet(tfSectors = cms.VPSet()) for i in range(3)]), hgcTimeSlices = cms.VPSet(*[cms.PSet(hgcSectors = cms.VPSet()) for i in range(3)]), gmtTimeSlices = cms.VPSet(cms.PSet(),cms.PSet(),cms.PSet()), gmtNumberOfMuons = cms.uint32(12), gttLink = cms.int32(-1), - gttLatency = cms.uint32(gttLatency_), - gttNumberOfPVs = cms.uint32(gttNumberOfPVs_) + gttLatency = cms.uint32(_gttLatency), + gttNumberOfPVs = cms.uint32(_gttNumberOfPVs), + outputLinksPuppi = cms.vuint32(*range(3)), + outputLinkEgamma = cms.int32(3), ) ## Ideal configuration: 27 input links from tf, 36 from hgc, 3 from gmt, 1 from gtt, in this order; output 3 puppi + 1 e/gamma -hgcalPosIdealWriterConfig = hgcalWriterConfig_.clone() -for t in range(3): - hgcalPosIdealWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(-1)) for i in range(9) ] # neg - hgcalPosIdealWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(3*i+t)) for i in range(9) ] # pos - hgcalPosIdealWriterConfig.hgcTimeSlices[t].hgcSectors += [ cms.PSet(hgcLinks = cms.vint32(-1,-1,-1,-1)) for i in range(3) ] # neg - hgcalPosIdealWriterConfig.hgcTimeSlices[t].hgcSectors += [ cms.PSet(hgcLinks = cms.vint32(*[27+12*i+4*t+j for j in range(4)])) for i in range(3) ] # pos - hgcalPosIdealWriterConfig.gmtTimeSlices[t].gmtLink = cms.int32(27+36+t) -hgcalPosIdealWriterConfig.gttLink = 27+36+3 -hgcalPosIdealWriterConfig.outputLinksPuppi = cms.vuint32(0,1,2) -hgcalPosIdealWriterConfig.outputLinkEgamma = cms.int32(5) -hgcalPosIdealWriterConfig.inputFileName = cms.string("l1HGCalPos-inputs-ideal") -hgcalPosIdealWriterConfig.outputFileName = cms.string("l1HGCalPos-outputs-ideal") -hgcalNegIdealWriterConfig = hgcalPosIdealWriterConfig.clone( - inputFileName = "", - outputFileName = "l1HGCalNeg-outputs-ideal", +_hgcalPosWriterConfig = _hgcalWriterConfig.clone( + outputRegions = cms.vuint32(*[i+9 for i in range(9)]), + outputBoard = cms.int32(1), +) +_hgcalNegWriterConfig = _hgcalPosWriterConfig.clone( outputRegions = [i for i in range(9)], outputBoard = 0, ) -## Current configuration for VU9P at B904 for layer1 - layer2 tests with puppi and e/gamma outputs on links 56-59 -hgcalPosVU9PB904egWriterConfig = hgcalWriterConfig_.clone() +hgcalPosOutputWriterConfig = _hgcalPosWriterConfig.clone( + outputFileName = cms.string("l1HGCalPos-outputs") +) +hgcalNegOutputWriterConfig = _hgcalNegWriterConfig.clone( + outputFileName = cms.string("l1HGCalNeg-outputs") +) +## Current configurations for VU9P +hgcalPosVU9PWriterConfig = _hgcalPosWriterConfig.clone() +hgcalNegVU9PWriterConfig = _hgcalNegWriterConfig.clone() for t in range(3): - hgcalPosVU9PB904egWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(-1)) for i in range(9) ] # neg - hgcalPosVU9PB904egWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(3*i+t+4*2)) for i in range(4) ] # pos, left quads - hgcalPosVU9PB904egWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(3*i+t+4*25)) for i in range(5) ] # pos, right quads - hgcalPosVU9PB904egWriterConfig.hgcTimeSlices[t].hgcSectors += [ cms.PSet(hgcLinks = cms.vint32(-1,-1,-1,-1)) for i in range(3) ] # neg - hgcalPosVU9PB904egWriterConfig.hgcTimeSlices[t].hgcSectors += [ cms.PSet(hgcLinks = cms.vint32(*[4*11+12*i+4*t+j for j in range(4)])) for i in range(3) ] # pos - hgcalPosVU9PB904egWriterConfig.gmtTimeSlices[t].gmtLink = cms.int32(4+t) -hgcalPosVU9PB904egWriterConfig.gttLink = 4+3 -hgcalPosVU9PB904egWriterConfig.outputLinksPuppi = cms.vuint32(56,57,58) -hgcalPosVU9PB904egWriterConfig.outputLinkEgamma = cms.int32(59) -hgcalPosVU9PB904egWriterConfig.inputFileName = cms.string("l1HGCalPos-inputs-vu9p_B904eg") -hgcalPosVU9PB904egWriterConfig.outputFileName = cms.string("l1HGCalPos-outputs-vu9p_B904eg") -## Current configuration for VU13P -hgcalPosVU13PWriterConfig = hgcalWriterConfig_.clone() + hgcalPosVU9PWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(-1)) for i in range(9) ] # neg + hgcalPosVU9PWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(3*i+t+4*2)) for i in range(4) ] # pos, left quads + hgcalPosVU9PWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(3*i+t+4*25)) for i in range(5) ] # pos, right quads + hgcalNegVU9PWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(3*i+t+4*2)) for i in range(4) ] # neg, left quads + hgcalNegVU9PWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(3*i+t+4*25)) for i in range(5) ] # neg, right quads + hgcalNegVU9PWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(-1)) for i in range(9) ] # pos + hgcalPosVU9PWriterConfig.hgcTimeSlices[t].hgcSectors += [ cms.PSet(hgcLinks = cms.vint32(-1,-1,-1,-1)) for i in range(3) ] # neg + hgcalPosVU9PWriterConfig.hgcTimeSlices[t].hgcSectors += [ cms.PSet(hgcLinks = cms.vint32(*[4*11+12*i+4*t+j for j in range(4)])) for i in range(3) ] # pos + hgcalNegVU9PWriterConfig.hgcTimeSlices[t].hgcSectors += [ cms.PSet(hgcLinks = cms.vint32(*[4*11+12*i+4*t+j for j in range(4)])) for i in range(3) ] # neg + hgcalNegVU9PWriterConfig.hgcTimeSlices[t].hgcSectors += [ cms.PSet(hgcLinks = cms.vint32(-1,-1,-1,-1)) for i in range(3) ] # pos + hgcalPosVU9PWriterConfig.gmtTimeSlices[t].gmtLink = cms.int32(4+t) + hgcalNegVU9PWriterConfig.gmtTimeSlices[t].gmtLink = cms.int32(4+t) +hgcalPosVU9PWriterConfig.gttLink = 4+3 +hgcalNegVU9PWriterConfig.gttLink = 4+3 +hgcalPosVU9PWriterConfig.inputFileName = cms.string("l1HGCalPos-inputs-vu9p") +hgcalNegVU9PWriterConfig.inputFileName = cms.string("l1HGCalNeg-inputs-vu9p") +## Current configurations for VU13P +hgcalPosVU13PWriterConfig = _hgcalPosWriterConfig.clone() +hgcalNegVU13PWriterConfig = _hgcalNegWriterConfig.clone() for t in range(3): - hgcalPosVU13PWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(-1)) for i in range(9) ] # neg - hgcalPosVU13PWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(3*i+t+4*0)) for i in range(5) ] # pos, left quads + hgcalPosVU13PWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(-1)) for i in range(9) ] # neg + hgcalPosVU13PWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(3*i+t+4*0)) for i in range(5) ] # pos, left quads hgcalPosVU13PWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(3*i+t+4*28)) for i in range(4) ] # pos, right quads + hgcalNegVU13PWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(3*i+t+4*0)) for i in range(5) ] # neg, left quads + hgcalNegVU13PWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(3*i+t+4*28)) for i in range(4) ] # neg, right quads + hgcalNegVU13PWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(-1)) for i in range(9) ] # pos hgcalPosVU13PWriterConfig.hgcTimeSlices[t].hgcSectors += [ cms.PSet(hgcLinks = cms.vint32(-1,-1,-1,-1)) for i in range(3) ] # neg for isec,q0 in (0,12),(1,17),(2,20): hgcalPosVU13PWriterConfig.hgcTimeSlices[t].hgcSectors += [ cms.PSet(hgcLinks = cms.vint32(*[4*q0+4*t+j for j in range(4)])) ] # pos - hgcalPosVU13PWriterConfig.gmtTimeSlices[t].gmtLink = cms.int32(4*27+t) -hgcalPosVU13PWriterConfig.gttLink = 4*27+3 -hgcalPosVU13PWriterConfig.outputLinksPuppi = cms.vuint32(0,1,2) -hgcalPosVU13PWriterConfig.outputLinkEgamma = cms.int32(3) -hgcalPosVU13PWriterConfig.inputFileName = cms.string("l1HGCalPos-inputs-vu13p") -hgcalPosVU13PWriterConfig.outputFileName = cms.string("l1HGCalPos-outputs-vu13p") -hgcalNegVU13PWriterConfig = hgcalWriterConfig_.clone() -for t in range(3): - hgcalNegVU13PWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(3*i+t+4*0)) for i in range(5) ] # neg, left quads - hgcalNegVU13PWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(3*i+t+4*28)) for i in range(4) ] # neg, right quads - hgcalNegVU13PWriterConfig.tfTimeSlices[t].tfSectors += [ cms.PSet(tfLink = cms.int32(-1)) for i in range(9) ] # pos - for isec,q0 in (0,12),(1,17),(2,20): hgcalNegVU13PWriterConfig.hgcTimeSlices[t].hgcSectors += [ cms.PSet(hgcLinks = cms.vint32(*[4*q0+4*t+j for j in range(4)])) ] # neg hgcalNegVU13PWriterConfig.hgcTimeSlices[t].hgcSectors += [ cms.PSet(hgcLinks = cms.vint32(-1,-1,-1,-1)) for i in range(3) ] # pos + hgcalPosVU13PWriterConfig.gmtTimeSlices[t].gmtLink = cms.int32(4*27+t) hgcalNegVU13PWriterConfig.gmtTimeSlices[t].gmtLink = cms.int32(4*27+t) +hgcalPosVU13PWriterConfig.gttLink = 4*27+3 hgcalNegVU13PWriterConfig.gttLink = 4*27+3 -hgcalNegVU13PWriterConfig.outputLinksPuppi = cms.vuint32(0,1,2) -hgcalNegVU13PWriterConfig.outputLinkEgamma = cms.int32(3) +hgcalPosVU13PWriterConfig.inputFileName = cms.string("l1HGCalPos-inputs-vu13p") hgcalNegVU13PWriterConfig.inputFileName = cms.string("l1HGCalNeg-inputs-vu13p") -hgcalNegVU13PWriterConfig.outputFileName = cms.string("l1HGCalNeg-outputs-vu13p") - -## Enable both +## Enable outputs and both boards hgcalWriterConfigs = [ - hgcalPosIdealWriterConfig, - hgcalNegIdealWriterConfig, - hgcalPosVU9PB904egWriterConfig, + hgcalPosOutputWriterConfig, + hgcalNegOutputWriterConfig, + hgcalPosVU9PWriterConfig, + hgcalNegVU9PWriterConfig, hgcalPosVU13PWriterConfig, hgcalNegVU13PWriterConfig ] ##################################################################################################################### ## Forward HGCal configuration: only outputs for now, 18 regions, 12 candidates x region, 4 output fibers -hgcalNoTKWriterOutputOnlyConfig = cms.PSet( +_hgcalNoTKWriterConfig = cms.PSet( partition = cms.string("HGCalNoTk"), outputRegions = cms.vuint32(*range(18)), + nInputFramesPerBX = cms.uint32(9), nOutputFramesPerBX = cms.uint32(9), - fileFormat = cms.string("EMP"), + fileFormat = cms.string("EMPv2"), + inputFileExtension = cms.string("txt.gz"), + outputFileExtension = cms.string("txt.gz"), + maxLinesPerInputFile = cms.uint32(1024), maxLinesPerOutputFile = cms.uint32(1024), - eventsPerFile = cms.uint32(eventsPerFile_), - outputLinksPuppi = cms.vuint32(0,1,2,4), - outputFileName = cms.string("l1HGCalNoTk-outputs-ideal") + eventsPerFile = cms.uint32(_eventsPerFile), +) +hgcalNoTKOutputWriterConfig = _hgcalNoTKWriterConfig.clone( + outputLinksPuppi = cms.vuint32(*range(4)), + outputFileName = cms.string("l1HGCalNoTK-outputs") ) +hgcalNoTKVU13PWriterConfig = _hgcalNoTKWriterConfig.clone( + hgcTimeSlices = cms.VPSet(*[cms.PSet(hgcSectors = cms.VPSet()) for i in range(3)]), + gmtTimeSlices = cms.VPSet(*[cms.PSet(gmtLink = cms.int32(-1)) for i in range(3)]), + gmtNumberOfMuons = cms.uint32(12), + gttLink = cms.int32(-1), + gttLatency = cms.uint32(_gttLatency), + gttNumberOfPVs = cms.uint32(_gttNumberOfPVs), +) +for t in range(3): + for isec in range(6): + q0 = 3*isec + 6 + hgcalNoTKVU13PWriterConfig.hgcTimeSlices[t].hgcSectors += [ cms.PSet(hgcLinks = cms.vint32(*[4*q0+4*t+j for j in range(4)])) ] # pos +hgcalNoTKVU13PWriterConfig.inputFileName = cms.string("l1HGCalNoTK-inputs-vu13p") # vu9p uses the same cabling for now hgcalNoTKWriterConfigs = [ - hgcalNoTKWriterOutputOnlyConfig + hgcalNoTKOutputWriterConfig, + hgcalNoTKVU13PWriterConfig ] ##################################################################################################################### -## HF configuration: not enabled for the moment +## HF configuration (to be better defined later) ##################################################################################################################### ## HF configuration not realistic, 3 links per endcap, write out the layer 1 outputs for now -hfWriterOutputOnly_ = cms.PSet( +_hfWriterOutputOnly = cms.PSet( partition = cms.string("HF"), outputLinksPuppi = cms.vuint32(*range(3)), nOutputFramesPerBX = cms.uint32(9), - fileFormat = cms.string("EMP"), + fileFormat = cms.string("EMPv2"), + outputFileExtension = cms.string("txt.gz"), maxLinesPerOutputFile = cms.uint32(1024), - eventsPerFile = cms.uint32(eventsPerFile_), + eventsPerFile = cms.uint32(_eventsPerFile), ) hfWriterConfigs = [ - hfWriterOutputOnly_.clone( + _hfWriterOutputOnly.clone( outputRegions = cms.vuint32(*[9*ie+i for i in range(9)]), - outputFileName = cms.string("l1HF%s-outputs-ideal" % ("Pos" if ie else "Neg")), + outputFileName = cms.string("l1HF%s-outputs" % ("Pos" if ie else "Neg")), ) for ie in range(2) ] diff --git a/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer2EG_cff.py b/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer2EG_cff.py index e42be9d3b8211..18e28d46752f0 100644 --- a/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer2EG_cff.py +++ b/L1Trigger/Phase2L1ParticleFlow/python/l1ctLayer2EG_cff.py @@ -72,8 +72,9 @@ writeOutPattern=cms.bool(False), inPatternFile=cms.PSet( nFramesPerBX=cms.uint32(9), # 360 MHz clock or 25 Gb/s link - format=cms.string("EMP"), + format=cms.string("EMPv2"), outputFilename=cms.string("L1TCTL2EG_InPattern"), + outputFileExtension=cms.string("txt.gz"), TMUX=cms.uint32(6), maxLinesPerFile=cms.uint32(1024), channels=cms.VPSet( @@ -117,14 +118,15 @@ ), outPatternFile=cms.PSet( nFramesPerBX=cms.uint32(9), # 360 MHz clock or 25 Gb/s link - format=cms.string("EMP"), + format=cms.string("EMPv2"), outputFilename=cms.string("L1TCTL2EG_OutPattern"), + outputFileExtension=cms.string("txt.gz"), TMUX=cms.uint32(6), maxLinesPerFile=cms.uint32(1024), channels=cms.VPSet( cms.PSet( TMUX=cms.uint32(6), - nWords=cms.uint32(36), # 36 = 12*3/2words ele + 12*3/2words phhotons + nWords=cms.uint32(36), # 36 = 12*3/2words ele + 12*3/2words photons interface=cms.string("eglayer2"), id=cms.uint32(0), channels=cms.vuint32(0) @@ -134,8 +136,9 @@ # NOTE: to write out the GT input from 6TS # outPatternFile=cms.PSet( # nFramesPerBX=cms.uint32(9), # 360 MHz clock or 25 Gb/s link - # format=cms.string("EMP"), + # format=cms.string("EMPv2"), # outputFilename=cms.string("L1TCTL2EG_ToGTPattern"), + # outputFileExtension=cms.string("txt.gz"), # TMUX=cms.uint32(1), # maxLinesPerFile=cms.uint32(1024), # channels=cms.VPSet( diff --git a/L1Trigger/Phase2L1ParticleFlow/python/l1pfJetMet_cff.py b/L1Trigger/Phase2L1ParticleFlow/python/l1pfJetMet_cff.py index 60d58d2ac23dd..a2a34b149513a 100644 --- a/L1Trigger/Phase2L1ParticleFlow/python/l1pfJetMet_cff.py +++ b/L1Trigger/Phase2L1ParticleFlow/python/l1pfJetMet_cff.py @@ -1,6 +1,7 @@ import FWCore.ParameterSet.Config as cms -from L1Trigger.Phase2L1ParticleFlow.l1tSeedConePFJetProducer_cfi import l1tSeedConePFJetProducer, l1tSeedConePFJetEmulatorProducer +from L1Trigger.Phase2L1ParticleFlow.l1tSeedConePFJetProducer_cfi import l1tSeedConePFJetProducer +from L1Trigger.Phase2L1ParticleFlow.l1tSeedConePFJetEmulatorProducer_cfi import l1tSeedConePFJetEmulatorProducer from L1Trigger.Phase2L1ParticleFlow.l1tDeregionizerProducer_cfi import l1tDeregionizerProducer as l1tLayer2Deregionizer, l1tDeregionizerProducerExtended as l1tLayer2DeregionizerExtended l1tSCPFL1PF = l1tSeedConePFJetProducer.clone(L1PFObjects = 'l1tLayer1:PF') l1tSCPFL1Puppi = l1tSeedConePFJetProducer.clone() diff --git a/L1Trigger/Phase2L1ParticleFlow/python/l1tJetFileWriter_cfi.py b/L1Trigger/Phase2L1ParticleFlow/python/l1tJetFileWriter_cfi.py index 6dd9b1f64370e..a53db5cb667fe 100644 --- a/L1Trigger/Phase2L1ParticleFlow/python/l1tJetFileWriter_cfi.py +++ b/L1Trigger/Phase2L1ParticleFlow/python/l1tJetFileWriter_cfi.py @@ -7,5 +7,6 @@ TMUX = cms.uint32(6), maxLinesPerFile = cms.uint32(1024), outputFilename = cms.string("L1CTSCJetsPatterns"), - format = cms.string("EMP") + format = cms.string("EMPv2"), + outputFileExtension = cms.string("txt.gz") ) diff --git a/L1Trigger/Phase2L1ParticleFlow/python/l1tSeedConePFJetEmulatorProducer_cfi.py b/L1Trigger/Phase2L1ParticleFlow/python/l1tSeedConePFJetEmulatorProducer_cfi.py new file mode 100644 index 0000000000000..2c859e0a97af7 --- /dev/null +++ b/L1Trigger/Phase2L1ParticleFlow/python/l1tSeedConePFJetEmulatorProducer_cfi.py @@ -0,0 +1,2 @@ +from L1Trigger.Phase2L1ParticleFlow.l1tSeedConePFJetProducer_cfi import l1tSeedConePFJetProducer as _l1tSeedConePFJetProducer +l1tSeedConePFJetEmulatorProducer = _l1tSeedConePFJetProducer.clone(HW = True) \ No newline at end of file diff --git a/L1Trigger/Phase2L1ParticleFlow/python/l1tSeedConePFJetProducer_cfi.py b/L1Trigger/Phase2L1ParticleFlow/python/l1tSeedConePFJetProducer_cfi.py deleted file mode 100644 index eb7fd2fd1e081..0000000000000 --- a/L1Trigger/Phase2L1ParticleFlow/python/l1tSeedConePFJetProducer_cfi.py +++ /dev/null @@ -1,15 +0,0 @@ -import FWCore.ParameterSet.Config as cms - -l1tSeedConePFJetProducer = cms.EDProducer("L1SeedConePFJetProducer", - L1PFObjects = cms.InputTag("l1tLayer1","Puppi"), - nJets = cms.uint32(16), - coneSize = cms.double(0.4), - HW = cms.bool(False), - debug = cms.bool(False), - doCorrections = cms.bool(False), - correctorFile = cms.string(""), - correctorDir = cms.string("") - ) - -l1tSeedConePFJetEmulatorProducer = l1tSeedConePFJetProducer.clone(HW = True) - diff --git a/L1Trigger/Phase2L1ParticleFlow/src/L1TCorrelatorLayer1PatternFileWriter.cc b/L1Trigger/Phase2L1ParticleFlow/src/L1TCorrelatorLayer1PatternFileWriter.cc index 018f156978ca0..6c6043241f5d9 100644 --- a/L1Trigger/Phase2L1ParticleFlow/src/L1TCorrelatorLayer1PatternFileWriter.cc +++ b/L1Trigger/Phase2L1ParticleFlow/src/L1TCorrelatorLayer1PatternFileWriter.cc @@ -61,6 +61,7 @@ L1TCorrelatorLayer1PatternFileWriter::L1TCorrelatorLayer1PatternFileWriter(const inputFileWriter_ = std::make_unique(l1t::demo::parseFileFormat(fileFormat_), iConfig.getParameter("inputFileName"), + iConfig.getParameter("inputFileExtension"), nInputFramesPerBX_, tmuxFactor_, iConfig.getParameter("maxLinesPerInputFile"), @@ -93,6 +94,7 @@ L1TCorrelatorLayer1PatternFileWriter::L1TCorrelatorLayer1PatternFileWriter(const outputFileWriter_ = std::make_unique(l1t::demo::parseFileFormat(fileFormat_), iConfig.getParameter("outputFileName"), + iConfig.getParameter("outputFileExtension"), nOutputFramesPerBX_, tmuxFactor_, iConfig.getParameter("maxLinesPerOutputFile"), diff --git a/L1Trigger/Phase2L1ParticleFlow/src/egamma/pftkegalgo_ref.cpp b/L1Trigger/Phase2L1ParticleFlow/src/egamma/pftkegalgo_ref.cpp index da9baff109831..eca1752e98a21 100644 --- a/L1Trigger/Phase2L1ParticleFlow/src/egamma/pftkegalgo_ref.cpp +++ b/L1Trigger/Phase2L1ParticleFlow/src/egamma/pftkegalgo_ref.cpp @@ -181,7 +181,7 @@ void PFTkEGAlgoEmulator::link_emCalo2tk_composite(const PFRegionEmu &r, const std::vector &emcalo, const std::vector &track, std::vector &emCalo2tk, - std::vector &emCaloTkBdtScore) const { + 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]; @@ -214,12 +214,12 @@ void PFTkEGAlgoEmulator::link_emCalo2tk_composite(const PFRegionEmu &r, if (nCandPerCluster == 0) continue; - float maxScore = -999; + id_score_t maxScore = -pow(2, l1ct::id_score_t::iwidth - 1); 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); + id_score_t score = compute_composite_score(cand, emcalo_sel, track, cfg.compIDparams); if ((score > cfg.compIDparams.bdtScore_loose_wp) && (score > maxScore)) { maxScore = score; ibest = icand; @@ -232,10 +232,10 @@ void PFTkEGAlgoEmulator::link_emCalo2tk_composite(const PFRegionEmu &r, } } -float PFTkEGAlgoEmulator::compute_composite_score(CompositeCandidate &cand, - const std::vector &emcalo, - const std::vector &track, - const PFTkEGAlgoEmuConfig::CompIDParameters ¶ms) const { +id_score_t 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]; @@ -258,7 +258,7 @@ float PFTkEGAlgoEmulator::compute_composite_score(CompositeCandidate &cand, 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]; + return bdt_score[0] / 4; } void PFTkEGAlgoEmulator::sel_emCalo(unsigned int nmax_sel, @@ -297,7 +297,7 @@ void PFTkEGAlgoEmulator::run(const PFInputRegion &in, OutputRegion &out) const { link_emCalo2emCalo(emcalo_sel, emCalo2emCalo); std::vector emCalo2tk(emcalo_sel.size(), -1); - std::vector emCaloTkBdtScore(emcalo_sel.size(), -999); + std::vector emCaloTkBdtScore(emcalo_sel.size(), -1); if (cfg.doCompositeTkEle) { link_emCalo2tk_composite(in.region, emcalo_sel, in.track, emCalo2tk, emCaloTkBdtScore); @@ -325,7 +325,7 @@ void PFTkEGAlgoEmulator::eg_algo(const PFRegionEmu ®ion, const std::vector &track, const std::vector &emCalo2emCalo, const std::vector &emCalo2tk, - const std::vector &emCaloTkBdtScore, + const std::vector &emCaloTkBdtScore, std::vector &egstas, std::vector &egobjs, std::vector &egeleobjs) const { @@ -341,7 +341,7 @@ void PFTkEGAlgoEmulator::eg_algo(const PFRegionEmu ®ion, << " phi " << calo.hwPhi << std::endl; int itk = emCalo2tk[ic]; - float bdt = emCaloTkBdtScore[ic]; + id_score_t bdt = emCaloTkBdtScore[ic]; // check if brem recovery is on if (!cfg.doBremRecovery || cfg.writeBeforeBremRecovery) { @@ -432,7 +432,7 @@ EGIsoEleObjEmu &PFTkEGAlgoEmulator::addEGIsoEleToPF(std::vector const TkObjEmu &track, const unsigned int hwQual, const pt_t ptCorr, - const float bdtScore) const { + const id_score_t bdtScore) const { EGIsoEleObjEmu egiso; egiso.clear(); egiso.hwPt = ptCorr; @@ -456,7 +456,7 @@ EGIsoEleObjEmu &PFTkEGAlgoEmulator::addEGIsoEleToPF(std::vector egiso.hwCharge = track.hwCharge; egiso.srcCluster = calo.src; egiso.srcTrack = track.src; - egiso.idScore = bdtScore; + egiso.hwIDScore = bdtScore; egobjs.push_back(egiso); if (debug_ > 2) @@ -475,7 +475,7 @@ void PFTkEGAlgoEmulator::addEgObjsToPF(std::vector &egstas, const unsigned int hwQual, const pt_t ptCorr, const int tk_idx, - const float bdtScore, + const id_score_t bdtScore, const std::vector &components) const { int sta_idx = -1; if (writeEgSta()) { diff --git a/L1Trigger/Phase2L1ParticleFlow/src/l1-converters/hgcalinputt_ref.cpp b/L1Trigger/Phase2L1ParticleFlow/src/l1-converters/hgcalinputt_ref.cpp index e4713944edf02..96a61ef4392f2 100644 --- a/L1Trigger/Phase2L1ParticleFlow/src/l1-converters/hgcalinputt_ref.cpp +++ b/L1Trigger/Phase2L1ParticleFlow/src/l1-converters/hgcalinputt_ref.cpp @@ -9,29 +9,48 @@ l1ct::HgcalClusterDecoderEmulator::HgcalClusterDecoderEmulator(const edm::Parame l1ct::HgcalClusterDecoderEmulator::~HgcalClusterDecoderEmulator() {} -l1ct::HadCaloObjEmu l1ct::HgcalClusterDecoderEmulator::decode(const ap_uint<256> &in) const { +l1ct::HadCaloObjEmu l1ct::HgcalClusterDecoderEmulator::decode(const l1ct::PFRegionEmu §or, + const ap_uint<256> &in) const { ap_uint<14> w_pt = in(13, 0); ap_uint<14> w_empt = in(27, 14); - 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<10> w_abseta = in(73, 64); + ap_int<9> w_eta = l1ct::glbeta_t(w_abseta.to_int() * (sector.floatEtaCenter() > 0 ? +1 : -1)) - sector.hwEtaCenter; + ap_int<9> w_phi = in(82, 74); + if (sector.floatEtaCenter() > 0) + w_phi = -w_phi; + ap_uint<4> w_gctqual = in(31, 28); // GCT quality + ap_uint<7> w_srrtot = in(191, 185); ap_uint<12> w_meanz = in(94, 83); + ap_uint<8> w_emf = in(39, 32); // 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); + //ap_uint<12> w_hoe = in(127, 116); + // Compute an H/E value: 1/emf - 1 + ap_ufixed<10, 5, AP_RND_CONV, AP_SAT> w_hoe = 256.0 / (w_emf.to_int() + 0.5) - 1; l1ct::HadCaloObjEmu out; out.clear(); + if (w_pt == 0 || w_phi > sector.hwPhiHalfWidth || w_phi <= -sector.hwPhiHalfWidth) + return out; out.hwPt = w_pt * l1ct::pt_t(l1ct::Scales::INTPT_LSB); out.hwEta = w_eta; out.hwPhi = w_phi; // relative to the region center, at calo out.hwEmPt = w_empt * l1ct::pt_t(l1ct::Scales::INTPT_LSB); - out.hwEmID = w_qual; + + out.hwEmID = 0; + out.hwEmID[0] = (out.floatEmPt() > 1.0) && w_emf > int(0.5 * 256); // PF ID + out.hwEmID[2] = (out.floatEmPt() > 3.0) && w_emf > int(0.7 * 256); // LOOSE ID + out.hwEmID[1] = (out.floatEmPt() > 5.0) && w_emf > int(0.8 * 256); // TIGHT ID if (!slim_) { - 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); + constexpr float HGCAL_SRRTOT_LSB = 0.024584 / (1 << 7); + // -- integer version --- + //float SRRTOT_FACTOR_FLT = HGCAL_SRRTOT_LSB*l1ct::Scales::SRRTOT_SCALE/l1ct::Scales::SRRTOT_LSB; + //ap_uint<10> our_srrtot_raw = (w_srrtot.to_int() * int(round(SRRTOT_FACTOR_FLT*(1<<4))))>>4;; + //out.hwSrrTot(9,0) = our_srrtot_raw(9,0); + // --- ap_fixed version (note that our LSB doesn't appear) --- + const ap_ufixed<8, -6> SRRTOT_FACTOR = HGCAL_SRRTOT_LSB * l1ct::Scales::SRRTOT_SCALE; + out.hwSrrTot = w_srrtot * SRRTOT_FACTOR; + out.hwMeanZ = l1ct::meanz_t(std::min(w_meanz.to_int() + 4, (1 << 12) - 1) >> 3); + out.hwHoe = w_hoe; } return out; } diff --git a/L1Trigger/Phase2L1ParticleFlow/src/puppi/linpuppi_ref.cpp b/L1Trigger/Phase2L1ParticleFlow/src/puppi/linpuppi_ref.cpp index 8ef2679747d0d..6ba07ebf6f7ff 100644 --- a/L1Trigger/Phase2L1ParticleFlow/src/puppi/linpuppi_ref.cpp +++ b/L1Trigger/Phase2L1ParticleFlow/src/puppi/linpuppi_ref.cpp @@ -638,5 +638,14 @@ void l1ct::LinPuppiEmulator::run(const PFInputRegion &in, } else { // forward std::vector outallne_nocut, outallne; fwdlinpuppi_ref(in.region, in.hadcalo, outallne_nocut, outallne, out.puppi); + unsigned int nne = outallne.size(); + outallne.resize(nOut_); + for (unsigned int j = nne + 1; j < nOut_; ++j) + outallne[j].clear(); + puppisort_and_crop_ref(nFinalSort_, outallne, out.puppi, finalSortAlgo_); + // trim if needed + while (!out.puppi.empty() && out.puppi.back().hwPt == 0) + out.puppi.pop_back(); + out.puppi.shrink_to_fit(); } } diff --git a/L1Trigger/Phase2L1ParticleFlow/test/.gitignore b/L1Trigger/Phase2L1ParticleFlow/test/.gitignore index 26f0a8dafc043..61181e36e734f 100644 --- a/L1Trigger/Phase2L1ParticleFlow/test/.gitignore +++ b/L1Trigger/Phase2L1ParticleFlow/test/.gitignore @@ -1,2 +1,4 @@ *.txt +*.txt.gz +*.txt.xz *.dump diff --git a/L1Trigger/Phase2L1ParticleFlow/test/make_l1ct_binaryFiles_HGCTest_cfg.py b/L1Trigger/Phase2L1ParticleFlow/test/make_l1ct_binaryFiles_HGCTest_cfg.py new file mode 100644 index 0000000000000..1eba552cb859c --- /dev/null +++ b/L1Trigger/Phase2L1ParticleFlow/test/make_l1ct_binaryFiles_HGCTest_cfg.py @@ -0,0 +1,138 @@ +import argparse +import sys + +# example: cmsRun L1Trigger/Phase2L1ParticleFlow/test/make_l1ct_patternFiles_cfg.py -- --patternFilesOFF +# example: cmsRun L1Trigger/Phase2L1ParticleFlow/test/make_l1ct_patternFiles_cfg.py -- --dumpFilesOFF --serenity + +parser = argparse.ArgumentParser(prog=sys.argv[0], description='Optional parameters') + +parser.add_argument("--dumpFilesOFF", help="switch on dump file production", action="store_true", default=False) +parser.add_argument("--patternFilesOFF", help="switch on Layer-1 pattern file production", action="store_true", default=False) +parser.add_argument("--serenity", help="use Serenity settigns as default everwhere, i.e. also for barrel", action="store_true", default=False) + +argv = sys.argv[:] +if '--' in argv: + argv.remove("--") +args, unknown = parser.parse_known_args(argv) + +if args.dumpFilesOFF: + print(f'Switching off dump file creation: dumpFilesOFF is {args.dumpFilesOFF}') +if args.patternFilesOFF: + print(f'Switching off pattern file creation: patternFilesOFF is {args.patternFilesOFF}') + + +import FWCore.ParameterSet.Config as cms +from Configuration.StandardSequences.Eras import eras + +process = cms.Process("RESP", eras.Phase2C17I13M9) + +process.load('Configuration.StandardSequences.Services_cff') +process.load("SimGeneral.HepPDTESSource.pythiapdt_cfi") +process.load("FWCore.MessageLogger.MessageLogger_cfi") +process.options = cms.untracked.PSet( wantSummary = cms.untracked.bool(True), allowUnscheduled = cms.untracked.bool(False) ) +process.maxEvents = cms.untracked.PSet( input = cms.untracked.int32(480)) +process.MessageLogger.cerr.FwkReport.reportEvery = 1 + +process.source = cms.Source("PoolSource", + fileNames = cms.untracked.vstring('file:inputs110X.root'), + inputCommands = cms.untracked.vstring("keep *", + "drop l1tPFClusters_*_*_*", + "drop l1tPFTracks_*_*_*", + "drop l1tPFCandidates_*_*_*", + "drop l1tTkPrimaryVertexs_*_*_*") +) + +process.load('Configuration.Geometry.GeometryExtended2026D88Reco_cff') +process.load('Configuration.Geometry.GeometryExtended2026D88_cff') +process.load('Configuration.StandardSequences.MagneticField_cff') +process.load('SimCalorimetry.HcalTrigPrimProducers.hcaltpdigi_cff') # needed to read HCal TPs +process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') + +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag = GlobalTag(process.GlobalTag, '125X_mcRun4_realistic_v2', '') + +process.load('L1Trigger.Phase2L1ParticleFlow.l1ctLayer1_cff') +process.load('L1Trigger.Phase2L1ParticleFlow.l1ctLayer2EG_cff') +process.load('L1Trigger.L1TTrackMatch.l1tGTTInputProducer_cfi') +process.load('L1Trigger.VertexFinder.l1tVertexProducer_cfi') +process.l1tVertexFinderEmulator = process.l1tVertexProducer.clone() +process.l1tVertexFinderEmulator.VertexReconstruction.Algorithm = "fastHistoEmulation" +process.l1tVertexFinderEmulator.l1TracksInputTag = cms.InputTag("l1tGTTInputProducer", "Level1TTTracksConverted") +from L1Trigger.Phase2L1GMT.gmt_cfi import l1tStandaloneMuons +process.l1tSAMuonsGmt = l1tStandaloneMuons.clone() + +from L1Trigger.Phase2L1ParticleFlow.l1tSeedConePFJetEmulatorProducer_cfi import l1tSeedConePFJetEmulatorProducer +from L1Trigger.Phase2L1ParticleFlow.l1tDeregionizerProducer_cfi import l1tDeregionizerProducer +from L1Trigger.Phase2L1ParticleFlow.l1tJetFileWriter_cfi import l1tSeededConeJetFileWriter +process.l1tLayer2Deregionizer = l1tDeregionizerProducer.clone() +process.l1tLayer2SeedConeJetsCorrected = l1tSeedConePFJetEmulatorProducer.clone(L1PFObjects = cms.InputTag('l1tLayer2Deregionizer', 'Puppi'), + doCorrections = cms.bool(True), + correctorFile = cms.string("L1Trigger/Phase2L1ParticleFlow/data/jecs/jecs_20220308.root"), + correctorDir = cms.string('L1PuppiSC4EmuJets')) + +process.runPF = cms.Path( + process.l1tSAMuonsGmt + + process.l1tGTTInputProducer + + process.l1tVertexFinderEmulator + + process.l1tLayer1Barrel + + process.l1tLayer1HGCal + + process.l1tLayer1HGCalElliptic + + process.l1tLayer1HGCalNoTK + + process.l1tLayer1HF + + process.l1tLayer1 + + process.l1tLayer2Deregionizer + + process.l1tLayer2SeedConeJetsCorrected + + # process.l1tLayer2SeedConeJetWriter + + process.l1tLayer2EG + ) +process.runPF.associate(process.L1TLayer1TaskInputsTask) + +##################################################################################################################### +## HGCal TPs +process.load('L1Trigger.L1THGCalUtilities.stage2FileWriter_cff') +process.Stage2FileWriter.fileExtension = "txt.gz" +from FWCore.Modules.preScaler_cfi import preScaler +for tmSlice, psOffset in (0,1), (6,2), (12,0): + setattr(process, f"preTM{tmSlice}", preScaler.clone(prescaleFactor = 3, prescaleOffset = psOffset)) + setattr(process, f"writerTM{tmSlice}", process.Stage2FileWriter.clone(tmIndex = tmSlice)) + setattr(process, f"Write_TM{tmSlice}", cms.Path(getattr(process, f"preTM{tmSlice}")+getattr(process, f"writerTM{tmSlice}"))) + +# make also TM18 version. +process.Stage2FileWriter.tmIndex = 18 # a bit of a hack +process.Write_TM18 = cms.Path(process.Stage2FileWriter) + +##################################################################################################################### +## Layer 1 +from L1Trigger.Phase2L1ParticleFlow.l1ctLayer1_patternWriters_cff import * +from L1Trigger.Phase2L1ParticleFlow.l1ctLayer1_patternWriters_cff import _eventsPerFile +process.l1tLayer1Barrel.patternWriters = cms.untracked.VPSet(*barrelWriterConfigs) +process.l1tLayer1HGCal.patternWriters = cms.untracked.VPSet(*hgcalWriterConfigs) +process.l1tLayer1HGCalNoTK.patternWriters = cms.untracked.VPSet(*hgcalNoTKWriterConfigs) +process.l1tLayer1HF.patternWriters = cms.untracked.VPSet(*hfWriterConfigs) + +for det in "HGCal", "HGCalNoTK": + l1pf = getattr(process, 'l1tLayer1'+det) + l1pf.dumpFileName = cms.untracked.string("TTbar_PU200_"+det+".dump") + +##################################################################################################################### +## Layer 2 e/gamma +process.l1tLayer2EG.writeInPattern = True +process.l1tLayer2EG.writeOutPattern = True +process.l1tLayer2EG.inPatternFile.maxLinesPerFile = _eventsPerFile*54 +process.l1tLayer2EG.outPatternFile.maxLinesPerFile = _eventsPerFile*54 + +##################################################################################################################### +## Layer 2 seeded-cone jets +process.l1tLayer2SeedConeJetWriter = l1tSeededConeJetFileWriter.clone(jets = "l1tLayer2SeedConeJetsCorrected") +process.runPF.insert(process.runPF.index(process.l1tLayer2SeedConeJetsCorrected)+1, process.l1tLayer2SeedConeJetWriter) +process.l1tLayer2SeedConeJetWriter.maxLinesPerFile = _eventsPerFile*54 + +process.source.fileNames = [ 'file:/afs/cern.ch/work/e/ejclemen/public/ForHGCalL1T/output_withEmuHGCalClusters.root' ] +process.l1tPFClustersFromHGC3DClusters.src = cms.InputTag("l1tHGCalBackEndLayer2Producer","HGCalBackendLayer2Processor3DClusteringSA") +process.l1tPFClustersFromCombinedCaloHF.hcalCandidates = [ cms.InputTag("l1tHGCalBackEndLayer2Producer","HGCalBackendLayer2Processor3DClusteringSA")] +process.l1tPFClustersFromHGC3DClusters.corrector = "" +process.l1tPFClustersFromHGC3DClusters.emVsPUID.wp = "-99" +process.l1tPFClustersFromHGC3DClusters.useEMInterpretation = "allKeepTot" +#process.l1tLayer1HGCal.debugHGC = cms.untracked.uint32(999999) +#process.l1tLayer1HGCal.pfAlgoParameters.debug = True +#process.l1tLayer1HGCal.puAlgoParameters.debug = True diff --git a/L1Trigger/Phase2L1ParticleFlow/test/make_l1ct_binaryFiles_cfg.py b/L1Trigger/Phase2L1ParticleFlow/test/make_l1ct_binaryFiles_cfg.py index 21d6d105095f9..30cdcb18ef6a5 100644 --- a/L1Trigger/Phase2L1ParticleFlow/test/make_l1ct_binaryFiles_cfg.py +++ b/L1Trigger/Phase2L1ParticleFlow/test/make_l1ct_binaryFiles_cfg.py @@ -1,13 +1,14 @@ import argparse import sys -# example: cmsRun L1Trigger/Phase2L1ParticleFlow/test/make_l1ct_patternFiles_cfg.py -- --dumpFilesOFF -# example: cmsRun L1Trigger/Phase2L1ParticleFlow/test/make_l1ct_patternFiles_cfg.py -- --dumpFilesOFF +# example: cmsRun L1Trigger/Phase2L1ParticleFlow/test/make_l1ct_patternFiles_cfg.py -- --patternFilesOFF +# example: cmsRun L1Trigger/Phase2L1ParticleFlow/test/make_l1ct_patternFiles_cfg.py -- --dumpFilesOFF --serenity parser = argparse.ArgumentParser(prog=sys.argv[0], description='Optional parameters') parser.add_argument("--dumpFilesOFF", help="switch on dump file production", action="store_true", default=False) parser.add_argument("--patternFilesOFF", help="switch on Layer-1 pattern file production", action="store_true", default=False) +parser.add_argument("--serenity", help="use Serenity settigns as default everwhere, i.e. also for barrel", action="store_true", default=False) argv = sys.argv[:] if '--' in argv: @@ -23,7 +24,7 @@ import FWCore.ParameterSet.Config as cms from Configuration.StandardSequences.Eras import eras -process = cms.Process("RESP", eras.Phase2C9) +process = cms.Process("RESP", eras.Phase2C17I13M9) process.load('Configuration.StandardSequences.Services_cff') process.load("SimGeneral.HepPDTESSource.pythiapdt_cfi") @@ -41,14 +42,14 @@ "drop l1tTkPrimaryVertexs_*_*_*") ) -process.load('Configuration.Geometry.GeometryExtended2026D49Reco_cff') -process.load('Configuration.Geometry.GeometryExtended2026D49_cff') +process.load('Configuration.Geometry.GeometryExtended2026D88Reco_cff') +process.load('Configuration.Geometry.GeometryExtended2026D88_cff') process.load('Configuration.StandardSequences.MagneticField_cff') process.load('SimCalorimetry.HcalTrigPrimProducers.hcaltpdigi_cff') # needed to read HCal TPs process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') from Configuration.AlCa.GlobalTag import GlobalTag -process.GlobalTag = GlobalTag(process.GlobalTag, '123X_mcRun4_realistic_v3', '') +process.GlobalTag = GlobalTag(process.GlobalTag, '125X_mcRun4_realistic_v2', '') process.load('L1Trigger.Phase2L1ParticleFlow.l1ctLayer1_cff') process.load('L1Trigger.Phase2L1ParticleFlow.l1ctLayer2EG_cff') @@ -60,28 +61,16 @@ from L1Trigger.Phase2L1GMT.gmt_cfi import l1tStandaloneMuons process.l1tSAMuonsGmt = l1tStandaloneMuons.clone() -from L1Trigger.Phase2L1ParticleFlow.l1tSeedConePFJetProducer_cfi import l1tSeedConePFJetEmulatorProducer +from L1Trigger.Phase2L1ParticleFlow.l1tSeedConePFJetEmulatorProducer_cfi import l1tSeedConePFJetEmulatorProducer from L1Trigger.Phase2L1ParticleFlow.l1tDeregionizerProducer_cfi import l1tDeregionizerProducer from L1Trigger.Phase2L1ParticleFlow.l1tJetFileWriter_cfi import l1tSeededConeJetFileWriter process.l1tLayer2Deregionizer = l1tDeregionizerProducer.clone() -process.l1tLayer2SeedConeJetsCorrected = l1tSeedConePFJetEmulatorProducer.clone(L1PFObject = cms.InputTag('l1tLayer2Deregionizer', 'Puppi'), +process.l1tLayer2SeedConeJetsCorrected = l1tSeedConePFJetEmulatorProducer.clone(L1PFObjects = cms.InputTag('l1tLayer2Deregionizer', 'Puppi'), doCorrections = cms.bool(True), correctorFile = cms.string("L1Trigger/Phase2L1ParticleFlow/data/jecs/jecs_20220308.root"), correctorDir = cms.string('L1PuppiSC4EmuJets')) process.l1tLayer2SeedConeJetWriter = l1tSeededConeJetFileWriter.clone(jets = "l1tLayer2SeedConeJetsCorrected") -process.l1tLayer1Barrel9 = process.l1tLayer1Barrel.clone() -process.l1tLayer1Barrel9.puAlgo.nFinalSort = 32 -process.l1tLayer1Barrel9.regions[0].etaBoundaries = [ -1.5, -0.5, 0.5, 1.5 ] -process.l1tLayer1Barrel9.boards=cms.VPSet( - cms.PSet( - regions=cms.vuint32(*[0+9*ie+i for ie in range(3) for i in range(3)])), - cms.PSet( - regions=cms.vuint32(*[3+9*ie+i for ie in range(3) for i in range(3)])), - cms.PSet( - regions=cms.vuint32(*[6+9*ie+i for ie in range(3) for i in range(3)])), - ) - process.l1tLayer1BarrelTDR = process.l1tLayer1Barrel.clone() process.l1tLayer1BarrelTDR.regionizerAlgo = cms.string("TDR") process.l1tLayer1BarrelTDR.regionizerAlgoParameters = cms.PSet( @@ -115,10 +104,16 @@ process.l1tLayer1BarrelSerenity.puAlgoParameters.nOut = 27 process.l1tLayer1BarrelSerenity.puAlgoParameters.finalSortAlgo = "FoldedHybrid" +if args.serenity: + process.l1tLayer1.pfProducers[0] = "l1tLayer1BarrelSerenity" + process.l1tLayer2EG.tkElectrons[1].pfProducer = "l1tLayer1BarrelSerenity:L1TkElePerBoard" + process.l1tLayer2EG.tkEms[2].pfProducer = "l1tLayer1BarrelSerenity:L1TkEmPerBoard" + from L1Trigger.Phase2L1ParticleFlow.l1ctLayer1_patternWriters_cff import * +from L1Trigger.Phase2L1ParticleFlow.l1ctLayer1_patternWriters_cff import _eventsPerFile if not args.patternFilesOFF: process.l1tLayer1Barrel.patternWriters = cms.untracked.VPSet(*barrelWriterConfigs) - # process.l1tLayer1Barrel9.patternWriters = cms.untracked.VPSet(*barrel9WriterConfigs) # not enabled for now + process.l1tLayer1BarrelSerenity.patternWriters = cms.untracked.VPSet(barrelSerenityVU9PPhi1Config,barrelSerenityVU13PPhi1Config) process.l1tLayer1HGCal.patternWriters = cms.untracked.VPSet(*hgcalWriterConfigs) process.l1tLayer1HGCalNoTK.patternWriters = cms.untracked.VPSet(*hgcalNoTKWriterConfigs) process.l1tLayer1HF.patternWriters = cms.untracked.VPSet(*hfWriterConfigs) @@ -130,7 +125,6 @@ process.l1tLayer1Barrel + process.l1tLayer1BarrelTDR + process.l1tLayer1BarrelSerenity + - process.l1tLayer1Barrel9 + process.l1tLayer1HGCal + process.l1tLayer1HGCalElliptic + process.l1tLayer1HGCalNoTK + @@ -150,26 +144,24 @@ if not args.patternFilesOFF: process.l1tLayer2EG.writeInPattern = True process.l1tLayer2EG.writeOutPattern = True - process.l1tLayer2EG.inPatternFile.maxLinesPerFile = eventsPerFile_*54 - process.l1tLayer2EG.outPatternFile.maxLinesPerFile = eventsPerFile_*54 + process.l1tLayer2EG.inPatternFile.maxLinesPerFile = _eventsPerFile*54 + process.l1tLayer2EG.outPatternFile.maxLinesPerFile = _eventsPerFile*54 ##################################################################################################################### ## Layer 2 seeded-cone jets if not args.patternFilesOFF: process.runPF.insert(process.runPF.index(process.l1tLayer2SeedConeJetsCorrected)+1, process.l1tLayer2SeedConeJetWriter) - process.l1tLayer2SeedConeJetWriter.maxLinesPerFile = eventsPerFile_*54 + process.l1tLayer2SeedConeJetWriter.maxLinesPerFile = _eventsPerFile*54 if not args.dumpFilesOFF: - for det in "Barrel", "BarrelTDR", "BarrelSerenity", "Barrel9", "HGCal", "HGCalElliptic", "HGCalNoTK", "HF": + for det in "Barrel", "BarrelTDR", "BarrelSerenity", "HGCal", "HGCalElliptic", "HGCalNoTK", "HF": l1pf = getattr(process, 'l1tLayer1'+det) l1pf.dumpFileName = cms.untracked.string("TTbar_PU200_"+det+".dump") -process.source.fileNames = [ '/store/cmst3/group/l1tr/gpetrucc/11_1_0/NewInputs110X/110121.done/TTbar_PU200/inputs110X_%d.root' % i for i in (1,3,7,8,9) ] -process.l1tPFClustersFromL1EGClusters.src = cms.InputTag("L1EGammaClusterEmuProducer",) -process.l1tPFClustersFromCombinedCaloHCal.phase2barrelCaloTowers = [cms.InputTag("L1EGammaClusterEmuProducer",)] -process.l1tPFClustersFromHGC3DClusters.src = cms.InputTag("hgcalBackEndLayer2Producer","HGCalBackendLayer2Processor3DClustering") -process.l1tPFClustersFromCombinedCaloHF.hcalCandidates = [ cms.InputTag("hgcalBackEndLayer2Producer","HGCalBackendLayer2Processor3DClustering")] -process.l1tPFTracksFromL1Tracks.L1TrackTag = cms.InputTag("TTTracksFromTrackletEmulation","Level1TTTracks") -process.l1tGTTInputProducer.l1TracksInputTag = cms.InputTag("TTTracksFromTrackletEmulation","Level1TTTracks") - +process.source.fileNames = [ 'file:/afs/cern.ch/work/e/ejclemen/public/ForHGCalL1T/output_withEmuHGCalClusters.root' ] +process.l1tPFClustersFromHGC3DClusters.src = cms.InputTag("l1tHGCalBackEndLayer2Producer","HGCalBackendLayer2Processor3DClusteringSA") +process.l1tPFClustersFromCombinedCaloHF.hcalCandidates = [ cms.InputTag("l1tHGCalBackEndLayer2Producer","HGCalBackendLayer2Processor3DClusteringSA")] +process.l1tPFClustersFromHGC3DClusters.corrector = "" +process.l1tPFClustersFromHGC3DClusters.emVsPUID.wp = "-99" +process.l1tPFClustersFromHGC3DClusters.useEMInterpretation = "allKeepTot"