Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-06-20 01:53:32

0001 #ifndef PFTKEGALGO_REF_H
0002 #define PFTKEGALGO_REF_H
0003 
0004 #include "DataFormats/L1TParticleFlow/interface/layer1_emulator.h"
0005 #include "DataFormats/L1TParticleFlow/interface/egamma.h"
0006 #include "DataFormats/L1TParticleFlow/interface/pf.h"
0007 #include "L1Trigger/Phase2L1ParticleFlow/interface/common/inversion.h"
0008 
0009 #include "conifer.h"
0010 
0011 namespace edm {
0012   class ParameterSet;
0013   class ParameterSetDescription;
0014 }  // namespace edm
0015 
0016 namespace l1ct {
0017 
0018   struct PFTkEGAlgoEmuConfig {
0019     unsigned int nTRACK;
0020     unsigned int nTRACK_EGIN;
0021     unsigned int nEMCALO_EGIN;
0022     unsigned int nEM_EGOUT;
0023 
0024     bool filterHwQuality;
0025     bool doBremRecovery;
0026     bool writeBeforeBremRecovery;
0027     int caloHwQual;
0028     bool doEndcapHwQual;
0029     float emClusterPtMin;  // GeV
0030     float dEtaMaxBrem;
0031     float dPhiMaxBrem;
0032 
0033     std::vector<double> absEtaBoundaries;
0034     std::vector<double> dEtaValues;
0035     std::vector<double> dPhiValues;
0036     float trkQualityPtMin;  // GeV
0037 
0038     enum Algo {
0039       undefined = -1,
0040       elliptic = 0,
0041       compositeEE_v0 = 1,
0042       compositeEB_v0 = 2,
0043       compositeEE_v1 = 3,
0044       compositeEB_v1 = 4
0045     };
0046 
0047     Algo algorithm;
0048     unsigned int nCompCandPerCluster;
0049     bool writeEgSta;
0050 
0051     struct IsoParameters {
0052       IsoParameters(const edm::ParameterSet &);
0053       IsoParameters(float tkQualityPtMin, float dZ, float dRMin, float dRMax)
0054           : tkQualityPtMin(Scales::makePtFromFloat(tkQualityPtMin)),
0055             dZ(Scales::makeZ0(dZ)),
0056             dRMin2(Scales::makeDR2FromFloatDR(dRMin)),
0057             dRMax2(Scales::makeDR2FromFloatDR(dRMax)) {}
0058       pt_t tkQualityPtMin;
0059       ap_int<z0_t::width + 1> dZ;
0060       int dRMin2;
0061       int dRMax2;
0062       static edm::ParameterSetDescription getParameterSetDescription();
0063     };
0064 
0065     IsoParameters tkIsoParams_tkEle;
0066     IsoParameters tkIsoParams_tkEm;
0067     IsoParameters pfIsoParams_tkEle;
0068     IsoParameters pfIsoParams_tkEm;
0069     bool doTkIso;
0070     bool doPfIso;
0071     EGIsoEleObjEmu::IsoType hwIsoTypeTkEle;
0072     EGIsoObjEmu::IsoType hwIsoTypeTkEm;
0073 
0074     struct CompIDParameters {
0075       CompIDParameters(const edm::ParameterSet &);
0076       CompIDParameters(const std::vector<double> &loose_wp_bins,
0077                        const std::vector<double> &loose_wp,
0078                        const std::vector<double> &tight_wp_bins,
0079                        const std::vector<double> &tight_wp,
0080                        const std::string &model,
0081                        double dphi_max,
0082                        double deta_max);
0083 
0084       std::vector<double> loose_wp_bins_;
0085       std::vector<double> loose_wp_;
0086       std::vector<double> tight_wp_bins_;
0087       std::vector<double> tight_wp_;
0088       std::string conifer_model_;
0089       double dPhi_max_;
0090       double dEta_max_;
0091 
0092       static edm::ParameterSetDescription getParameterSetDescription();
0093     };
0094 
0095     CompIDParameters compIDparams;
0096 
0097     int debug = 0;
0098 
0099     PFTkEGAlgoEmuConfig(const edm::ParameterSet &iConfig);
0100     PFTkEGAlgoEmuConfig(
0101         unsigned int nTrack,                                       // Number of tracks to consider
0102         unsigned int nTrack_in,                                    // Number of tracks for EG input
0103         unsigned int nEmCalo_in,                                   // Number of EM calos for EG input
0104         unsigned int nEmOut,                                       // Number of EM objects at EG output
0105         bool filterHwQuality,                                      // Enable hardware quality filtering
0106         bool doBremRecovery,                                       // Enable brem recovery
0107         bool writeBeforeBremRecovery = false,                      // Write objects before brem recovery
0108         int caloHwQual = 4,                                        // Calo hardware quality threshold (default: 4)
0109         bool doEndcapHwQual = false,                               // Use endcap hardware quality
0110         float emClusterPtMin = 2.,                                 // Minimum EM cluster pt [GeV]
0111         float dEtaMaxBrem = 0.02,                                  // Max delta-eta for brem recovery
0112         float dPhiMaxBrem = 0.1,                                   // Max delta-phi for brem recovery
0113         const std::vector<double> &absEtaBoundaries = {0.0, 1.5},  // Eta region boundaries
0114         const std::vector<double> &dEtaValues = {0.015, 0.01},     // Delta-eta cuts per region
0115         const std::vector<double> &dPhiValues = {0.07, 0.07},      // Delta-phi cuts per region
0116         float trkQualityPtMin = 10.,                               // Minimum track pt for quality [GeV]
0117         unsigned int algo = 0,                                     // Algorithm selector (see enum Algo)
0118         unsigned int nCompCandPerCluster = 4,                      // Max composite candidates per cluster
0119         bool writeEgSta = false,                                   // Write EG standalone objects
0120         // Track isolation params for tkEle: min-pt, dZ, dRMin, dRMax
0121         const IsoParameters &tkIsoParams_tkEle = {2., 0.6, 0.03, 0.2},
0122         // Track isolation params for tkEm: min-pt, dZ, dRMin, dRMax
0123         const IsoParameters &tkIsoParams_tkEm = {2., 0.6, 0.07, 0.3},
0124         // PF isolation params for tkEle: min-pt, dZ, dRMin, dRMax
0125         const IsoParameters &pfIsoParams_tkEle = {1., 0.6, 0.03, 0.2},
0126         // PF isolation params for tkEm: min-pt, dZ, dRMin, dRMax
0127         const IsoParameters &pfIsoParams_tkEm = {1., 0.6, 0.07, 0.3},
0128         bool doTkIso = true,                                                      // Enable track isolation
0129         bool doPfIso = false,                                                     // Enable PF isolation
0130         EGIsoEleObjEmu::IsoType hwIsoTypeTkEle = EGIsoEleObjEmu::IsoType::TkIso,  // Isolation type for tkEle
0131         EGIsoObjEmu::IsoType hwIsoTypeTkEm = EGIsoObjEmu::IsoType::TkIsoPV,       // Isolation type for tkEm
0132         // Composite ID params: pt-bins, loose-WP, pt-bins tight-WP, model, dPhi_max, dEta_max
0133         const CompIDParameters &compIDparams = {{0.}, {-4}, {0.}, {0.214844}, "compositeID.json", 0.2, 0.2},
0134         int debug = 0)  // Debug level
0135         : nTRACK(nTrack),
0136           nTRACK_EGIN(nTrack_in),
0137           nEMCALO_EGIN(nEmCalo_in),
0138           nEM_EGOUT(nEmOut),
0139           filterHwQuality(filterHwQuality),
0140           doBremRecovery(doBremRecovery),
0141           writeBeforeBremRecovery(writeBeforeBremRecovery),
0142           caloHwQual(caloHwQual),
0143           doEndcapHwQual(doEndcapHwQual),
0144           emClusterPtMin(emClusterPtMin),
0145           dEtaMaxBrem(dEtaMaxBrem),
0146           dPhiMaxBrem(dPhiMaxBrem),
0147           absEtaBoundaries(absEtaBoundaries),
0148           dEtaValues(dEtaValues),
0149           dPhiValues(dPhiValues),
0150           trkQualityPtMin(trkQualityPtMin),
0151           algorithm(Algo::undefined),
0152           nCompCandPerCluster(nCompCandPerCluster),
0153           writeEgSta(writeEgSta),
0154           tkIsoParams_tkEle(tkIsoParams_tkEle),
0155           tkIsoParams_tkEm(tkIsoParams_tkEm),
0156           pfIsoParams_tkEle(pfIsoParams_tkEle),
0157           pfIsoParams_tkEm(pfIsoParams_tkEm),
0158           doTkIso(doTkIso),
0159           doPfIso(doPfIso),
0160           hwIsoTypeTkEle(hwIsoTypeTkEle),
0161           hwIsoTypeTkEm(hwIsoTypeTkEm),
0162           compIDparams(compIDparams),
0163           debug(debug) {
0164       if (algo == 0)
0165         algorithm = Algo::elliptic;
0166       else if (algo == 1)
0167         algorithm = Algo::compositeEE_v0;
0168       else if (algo == 2)
0169         algorithm = Algo::compositeEB_v0;
0170       else if (algo == 3)
0171         algorithm = Algo::compositeEE_v1;
0172       else if (algo == 4)
0173         algorithm = Algo::compositeEB_v1;
0174       else
0175         throw std::invalid_argument("[PFTkEGAlgoEmuConfig]: Unknown algorithm type: " + std::to_string(algo));
0176     }
0177 
0178     static edm::ParameterSetDescription getParameterSetDescription();
0179   };
0180 
0181   struct CompositeCandidate {
0182     unsigned int cluster_idx;
0183     unsigned int track_idx;
0184     double dpt;  // For sorting
0185   };
0186 
0187   class TkEGEleAssociationModel {
0188   public:
0189     TkEGEleAssociationModel(const l1ct::PFTkEGAlgoEmuConfig::CompIDParameters &params, int debug);
0190     virtual ~TkEGEleAssociationModel() = default;
0191 
0192     virtual id_score_t compute_score(const CompositeCandidate &cand,
0193                                      const std::vector<EmCaloObjEmu> &emcalo,
0194                                      const std::vector<TkObjEmu> &track,
0195                                      const std::vector<float> additional_vars) const = 0;
0196 
0197     bool geometric_match(const EmCaloObjEmu &emcalo, const TkObjEmu &track) const;
0198 
0199     class WP {
0200     public:
0201       enum cut_type { score_cut = 0, pt_binned_cut = 1 };
0202 
0203       cut_type getWPtype() const { return wp_type; }
0204       virtual ~WP() = default;
0205 
0206       virtual bool apply(const id_score_t &score, const float &var) const = 0;
0207 
0208     protected:
0209       WP(cut_type wp_type) : wp_type(wp_type) {}
0210       cut_type wp_type;
0211     };
0212 
0213     class SimpleWP : public WP {
0214     public:
0215       id_score_t wp_value_;
0216       SimpleWP(id_score_t wp_value) : WP(cut_type::score_cut), wp_value_(wp_value) {}
0217       bool apply(const id_score_t &score, const float &var) const override { return score >= wp_value_; }
0218     };
0219 
0220     class BinnedWP1D : public WP {
0221       std::vector<double> bin_low_edges_;
0222       std::vector<id_score_t> wp_values_;
0223 
0224     public:
0225       BinnedWP1D(const std::vector<double> &bin_low_edges, const std::vector<id_score_t> &wp_values)
0226           : WP(cut_type::pt_binned_cut), bin_low_edges_(bin_low_edges), wp_values_(wp_values) {}
0227 
0228       bool apply(const id_score_t &score, const float &var) const override {
0229         auto it = std::upper_bound(bin_low_edges_.begin(), bin_low_edges_.end(), var);
0230         unsigned int bin_index = it - bin_low_edges_.begin() - 1;
0231         return (score > id_score_t(wp_values_[bin_index]));
0232       };
0233     };
0234 
0235     static std::unique_ptr<WP> createWP(const std::vector<double> &bin_low_edges,
0236                                         const std::vector<double> &wp_values) {
0237       assert(bin_low_edges.size() == wp_values.size() && "The size of bin_low_edges must match the size of wp_values.");
0238       assert(!wp_values.empty() && "The size of bin_low_edges must not be 0.");
0239 
0240       std::vector<id_score_t> wp_values_apf;
0241       wp_values_apf.reserve(wp_values.size());
0242       std::transform(wp_values.begin(), wp_values.end(), std::back_inserter(wp_values_apf), [](const double &val) {
0243         return id_score_t(val);
0244       });
0245       if (bin_low_edges.size() == 1) {
0246         return std::make_unique<SimpleWP>(id_score_t(wp_values_apf[0]));
0247       }
0248       return std::make_unique<BinnedWP1D>(bin_low_edges, wp_values_apf);
0249     }
0250 
0251     bool apply_wp_loose(float score, float var) const { return loose_wp_->apply(score, var); }
0252 
0253     bool apply_wp_tight(float score, float var) const { return tight_wp_->apply(score, var); }
0254 
0255     WP::cut_type loose_wp_type() const { return loose_wp_->getWPtype(); }
0256 
0257     WP::cut_type tight_wp_type() const { return tight_wp_->getWPtype(); }
0258 
0259   private:
0260     std::unique_ptr<WP> loose_wp_;
0261     std::unique_ptr<WP> tight_wp_;
0262     float dphi2_max_;
0263     float deta2_max_;
0264 
0265   protected:
0266     int debug_;
0267   };
0268 
0269   class TkEgCID_EE_v0 : public TkEGEleAssociationModel {
0270   public:
0271     TkEgCID_EE_v0(const l1ct::PFTkEGAlgoEmuConfig::CompIDParameters &params, int debug);
0272 
0273     id_score_t compute_score(const CompositeCandidate &cand,
0274                              const std::vector<EmCaloObjEmu> &emcalo,
0275                              const std::vector<TkObjEmu> &track,
0276                              const std::vector<float> additional_vars) const override;
0277 
0278     typedef ap_fixed<21, 12, AP_RND_CONV, AP_SAT> bdt_feature_t;
0279     typedef ap_fixed<12, 3, AP_RND_CONV, AP_SAT> bdt_score_t;
0280 
0281   private:
0282     std::unique_ptr<conifer::BDT<bdt_feature_t, bdt_score_t, false>> model_;
0283   };
0284 
0285   class TkEgCID_EE_v1 : public TkEGEleAssociationModel {
0286   public:
0287     TkEgCID_EE_v1(const l1ct::PFTkEGAlgoEmuConfig::CompIDParameters &params, int debug);
0288 
0289     id_score_t compute_score(const CompositeCandidate &cand,
0290                              const std::vector<EmCaloObjEmu> &emcalo,
0291                              const std::vector<TkObjEmu> &track,
0292                              const std::vector<float> additional_vars) const override;
0293 
0294     typedef ap_fixed<30, 20, AP_RND_CONV, AP_SAT> bdt_feature_t;
0295     typedef ap_fixed<30, 20, AP_RND_CONV, AP_SAT> bdt_score_t;
0296 
0297   private:
0298     std::unique_ptr<conifer::BDT<bdt_feature_t, bdt_score_t, false>> model_;
0299   };
0300 
0301   class TkEgCID_EB_v0 : public TkEGEleAssociationModel {
0302   public:
0303     TkEgCID_EB_v0(const l1ct::PFTkEGAlgoEmuConfig::CompIDParameters &params, int debug);
0304 
0305     id_score_t compute_score(const CompositeCandidate &cand,
0306                              const std::vector<EmCaloObjEmu> &emcalo,
0307                              const std::vector<TkObjEmu> &track,
0308                              const std::vector<float> additional_vars) const override;
0309 
0310     typedef ap_fixed<24, 9, AP_RND_CONV, AP_SAT> bdt_feature_t;
0311     typedef ap_fixed<12, 4, AP_RND_CONV, AP_SAT> bdt_score_t;
0312 
0313   private:
0314     std::unique_ptr<conifer::BDT<bdt_feature_t, bdt_score_t, false>> model_;
0315   };
0316 
0317   class TkEgCID_EB_v1 : public TkEGEleAssociationModel {
0318   public:
0319     TkEgCID_EB_v1(const l1ct::PFTkEGAlgoEmuConfig::CompIDParameters &params, int debug);
0320 
0321     id_score_t compute_score(const CompositeCandidate &cand,
0322                              const std::vector<EmCaloObjEmu> &emcalo,
0323                              const std::vector<TkObjEmu> &track,
0324                              const std::vector<float> additional_vars) const override;
0325 
0326     typedef ap_fixed<8, 1, AP_RND_CONV, AP_SAT> bdt_feature_t;
0327     typedef ap_fixed<11, 4, AP_RND_CONV, AP_SAT> bdt_score_t;
0328 
0329   private:
0330     float scale(const float &x, const float &min_x, const int &bitshift, float inf = -1) const {
0331       return inf + (x - min_x) / pow(2, bitshift);
0332     }
0333 
0334     std::unique_ptr<conifer::BDT<bdt_feature_t, bdt_score_t, false>> model_;
0335   };
0336 
0337   class PFTkEGAlgoEmulator {
0338   public:
0339     PFTkEGAlgoEmulator(const PFTkEGAlgoEmuConfig &config);
0340 
0341     virtual ~PFTkEGAlgoEmulator() {}
0342 
0343     void toFirmware(const PFInputRegion &in, PFRegion &region, EmCaloObj calo[/*nCALO*/], TkObj track[/*nTRACK*/]) const;
0344     void toFirmware(const OutputRegion &out, EGIsoObj out_egphs[], EGIsoEleObj out_egeles[]) const;
0345     void toFirmware(const PFInputRegion &in,
0346                     const l1ct::PVObjEmu &pvin,
0347                     PFRegion &region,
0348                     TkObj track[/*nTRACK*/],
0349                     PVObj &pv) const;
0350 
0351     void run(const PFInputRegion &in, OutputRegion &out) const;
0352     void runIso(const PFInputRegion &in, const std::vector<l1ct::PVObjEmu> &pvs, OutputRegion &out) const;
0353 
0354     void setDebug(int verbose) { debug_ = verbose; }
0355 
0356     bool writeEgSta() const { return cfg.writeEgSta; }
0357 
0358     static float deltaPhi(float phi1, float phi2);
0359 
0360   private:
0361     void link_emCalo2emCalo(const std::vector<EmCaloObjEmu> &emcalo, std::vector<int> &emCalo2emCalo) const;
0362 
0363     void link_emCalo2tk_elliptic(const PFRegionEmu &r,
0364                                  const std::vector<EmCaloObjEmu> &emcalo,
0365                                  const std::vector<TkObjEmu> &track,
0366                                  std::vector<int> &emCalo2tk) const;
0367 
0368     void link_emCalo2tk_composite_eb_ee(const PFRegionEmu &r,
0369                                         const std::vector<EmCaloObjEmu> &emcalo,
0370                                         const std::vector<TkObjEmu> &track,
0371                                         std::vector<int> &emCalo2tk,
0372                                         std::vector<id_score_t> &emCaloTkBdtScore) const;
0373 
0374     void sel_emCalo(unsigned int nmax_sel,
0375                     const std::vector<EmCaloObjEmu> &emcalo,
0376                     std::vector<EmCaloObjEmu> &emcalo_sel) const;
0377 
0378     void eg_algo(const PFRegionEmu &region,
0379                  const std::vector<EmCaloObjEmu> &emcalo,
0380                  const std::vector<TkObjEmu> &track,
0381                  const std::vector<int> &emCalo2emCalo,
0382                  const std::vector<int> &emCalo2tk,
0383                  const std::vector<id_score_t> &emCaloTkBdtScore,
0384                  std::vector<EGObjEmu> &egstas,
0385                  std::vector<EGIsoObjEmu> &egobjs,
0386                  std::vector<EGIsoEleObjEmu> &egeleobjs) const;
0387 
0388     void addEgObjsToPF(std::vector<EGObjEmu> &egstas,
0389                        std::vector<EGIsoObjEmu> &egobjs,
0390                        std::vector<EGIsoEleObjEmu> &egeleobjs,
0391                        const std::vector<EmCaloObjEmu> &emcalo,
0392                        const std::vector<TkObjEmu> &track,
0393                        const int calo_idx,
0394                        const unsigned int hwQual,
0395                        const pt_t ptCorr,
0396                        const int tk_idx,
0397                        const id_score_t bdtScore,
0398                        const std::vector<unsigned int> &components = {}) const;
0399 
0400     EGObjEmu &addEGStaToPF(std::vector<EGObjEmu> &egobjs,
0401                            const EmCaloObjEmu &calo,
0402                            const unsigned int hwQual,
0403                            const pt_t ptCorr,
0404                            const std::vector<unsigned int> &components) const;
0405 
0406     EGIsoObjEmu &addEGIsoToPF(std::vector<EGIsoObjEmu> &egobjs,
0407                               const EmCaloObjEmu &calo,
0408                               const unsigned int hwQual,
0409                               const pt_t ptCorr) const;
0410 
0411     EGIsoEleObjEmu &addEGIsoEleToPF(std::vector<EGIsoEleObjEmu> &egobjs,
0412                                     const EmCaloObjEmu &calo,
0413                                     const TkObjEmu &track,
0414                                     const unsigned int hwQual,
0415                                     const pt_t ptCorr,
0416                                     const id_score_t bdtScore) const;
0417 
0418     template <typename T>
0419     void ptsort_ref(int nIn, int nOut, const std::vector<T> &in, std::vector<T> &out) const {
0420       out.resize(nOut);
0421       for (int iout = 0; iout < nOut; ++iout) {
0422         out[iout].clear();
0423       }
0424       for (int it = 0; it < nIn; ++it) {
0425         for (int iout = 0; iout < nOut; ++iout) {
0426           if (in[it].hwPt >= out[iout].hwPt) {
0427             for (int i2 = nOut - 1; i2 > iout; --i2) {
0428               out[i2] = out[i2 - 1];
0429             }
0430             out[iout] = in[it];
0431             break;
0432           }
0433         }
0434       }
0435     }
0436 
0437     template <typename T>
0438     int deltaR2(const T &charged, const EGIsoObjEmu &egphoton) const {
0439       // NOTE: we compare Tk at vertex against the calo variable...
0440       return dr2_int(charged.hwVtxEta(), charged.hwVtxPhi(), egphoton.hwEta, egphoton.hwPhi);
0441     }
0442 
0443     template <typename T>
0444     int deltaR2(const T &charged, const EGIsoEleObjEmu &egele) const {
0445       return dr2_int(charged.hwVtxEta(), charged.hwVtxPhi(), egele.hwVtxEta(), egele.hwVtxPhi());
0446     }
0447 
0448     int deltaR2(const PFNeutralObjEmu &neutral, const EGIsoObjEmu &egphoton) const {
0449       return dr2_int(neutral.hwEta, neutral.hwPhi, egphoton.hwEta, egphoton.hwPhi);
0450     }
0451 
0452     int deltaR2(const PFNeutralObjEmu &neutral, const EGIsoEleObjEmu &egele) const {
0453       // NOTE: we compare Tk at vertex against the calo variable...
0454       return dr2_int(neutral.hwEta, neutral.hwPhi, egele.hwVtxEta(), egele.hwVtxPhi());
0455     }
0456 
0457     template <typename T>
0458     ap_int<z0_t::width + 1> deltaZ0(const T &charged, const EGIsoObjEmu &egphoton, z0_t z0) const {
0459       ap_int<z0_t::width + 1> delta = charged.hwZ0 - z0;
0460       if (delta < 0)
0461         delta = -delta;
0462       return delta;
0463     }
0464 
0465     template <typename T>
0466     ap_int<z0_t::width + 1> deltaZ0(const T &charged, const EGIsoEleObjEmu &egele, z0_t z0) const {
0467       ap_int<z0_t::width + 1> delta = charged.hwZ0 - egele.hwZ0;
0468       if (delta < 0)
0469         delta = -delta;
0470       return delta;
0471     }
0472 
0473     template <typename TCH, typename TEG>
0474     void compute_sumPt(iso_t &sumPt,
0475                        iso_t &sumPtPV,
0476                        const std::vector<TCH> &objects,
0477                        unsigned int nMaxObj,
0478                        const TEG &egobj,
0479                        const PFTkEGAlgoEmuConfig::IsoParameters &params,
0480                        z0_t z0) const {
0481       for (unsigned int itk = 0; itk < std::min<unsigned>(objects.size(), nMaxObj); ++itk) {
0482         const auto &obj = objects[itk];
0483 
0484         if (obj.hwPt < params.tkQualityPtMin)
0485           continue;
0486 
0487         int dR2 = deltaR2(obj, egobj);
0488 
0489         if (dR2 > params.dRMin2 && dR2 < params.dRMax2) {
0490           sumPt += obj.hwPt;
0491           if (deltaZ0(obj, egobj, z0) < params.dZ) {
0492             sumPtPV += obj.hwPt;
0493           }
0494         }
0495       }
0496     }
0497 
0498     template <typename TEG>
0499     void compute_sumPt(iso_t &sumPt,
0500                        iso_t &sumPtPV,
0501                        const std::vector<PFNeutralObjEmu> &objects,
0502                        unsigned int nMaxObj,
0503                        const TEG &egobj,
0504                        const PFTkEGAlgoEmuConfig::IsoParameters &params,
0505                        z0_t z0) const {
0506       for (unsigned int itk = 0; itk < std::min<unsigned>(objects.size(), nMaxObj); ++itk) {
0507         const auto &obj = objects[itk];
0508 
0509         if (obj.hwPt < params.tkQualityPtMin)
0510           continue;
0511 
0512         int dR2 = deltaR2(obj, egobj);
0513 
0514         if (dR2 > params.dRMin2 && dR2 < params.dRMax2) {
0515           sumPt += obj.hwPt;
0516           // PF neutrals are not constrained by PV (since their Z0 is 0 by design)
0517           sumPtPV += obj.hwPt;
0518         }
0519       }
0520     }
0521 
0522     void compute_isolation(std::vector<EGIsoObjEmu> &egobjs,
0523                            const std::vector<TkObjEmu> &objects,
0524                            const PFTkEGAlgoEmuConfig::IsoParameters &params,
0525                            z0_t z0) const;
0526     void compute_isolation(std::vector<EGIsoEleObjEmu> &egobjs,
0527                            const std::vector<TkObjEmu> &objects,
0528                            const PFTkEGAlgoEmuConfig::IsoParameters &params,
0529                            z0_t z0) const;
0530     void compute_isolation(std::vector<EGIsoObjEmu> &egobjs,
0531                            const std::vector<PFChargedObjEmu> &charged,
0532                            const std::vector<PFNeutralObjEmu> &neutrals,
0533                            const PFTkEGAlgoEmuConfig::IsoParameters &params,
0534                            z0_t z0) const;
0535     void compute_isolation(std::vector<EGIsoEleObjEmu> &egobjs,
0536                            const std::vector<PFChargedObjEmu> &charged,
0537                            const std::vector<PFNeutralObjEmu> &neutrals,
0538                            const PFTkEGAlgoEmuConfig::IsoParameters &params,
0539                            z0_t z0) const;
0540 
0541     PFTkEGAlgoEmuConfig cfg;
0542     // Could use a std::variant
0543     std::unique_ptr<TkEGEleAssociationModel> tkEleModel_;
0544 
0545     int debug_;
0546   };
0547 }  // namespace l1ct
0548 
0549 #endif