diff --git a/DataFormats/L1Trigger/interface/P2GTAlgoBlock.h b/DataFormats/L1Trigger/interface/P2GTAlgoBlock.h new file mode 100644 index 0000000000000..0e57ae027c12b --- /dev/null +++ b/DataFormats/L1Trigger/interface/P2GTAlgoBlock.h @@ -0,0 +1,50 @@ +#ifndef DataFormats_L1Trigger_P2GTAlgoBlock_h +#define DataFormats_L1Trigger_P2GTAlgoBlock_h + +#include "P2GTCandidate.h" + +#include +#include +#include + +namespace l1t { + + class P2GTAlgoBlock; + typedef std::vector P2GTAlgoBlockCollection; + + class P2GTAlgoBlock { + public: + P2GTAlgoBlock() + : algoName_(""), + decisionBeforeBxMaskAndPrescale_(false), + decisionBeforePrescale_(false), + decisionFinal_(false), + trigObjects_() {} + P2GTAlgoBlock(std::string name, + bool decisionBeforeBxMaskAndPrescale, + bool decisionBeforePrescale, + bool decisionFinal, + P2GTCandidateVectorRef trigObjects) + : algoName_(std::move(name)), + decisionBeforeBxMaskAndPrescale_(decisionBeforeBxMaskAndPrescale), + decisionBeforePrescale_(decisionBeforePrescale), + decisionFinal_(decisionFinal), + trigObjects_(std::move(trigObjects)) {} + + const std::string& algoName() const { return algoName_; } + bool decisionBeforeBxMaskAndPrescale() const { return decisionBeforeBxMaskAndPrescale_; } + bool decisionBeforePrescale() const { return decisionBeforePrescale_; } + bool decisionFinal() const { return decisionFinal_; } + const P2GTCandidateVectorRef& trigObjects() const { return trigObjects_; } + + private: + const std::string algoName_; + const bool decisionBeforeBxMaskAndPrescale_; + const bool decisionBeforePrescale_; + const bool decisionFinal_; + const P2GTCandidateVectorRef trigObjects_; + }; + +} // namespace l1t + +#endif // DataFormats_L1Trigger_P2GTAlgoBlock_h diff --git a/DataFormats/L1Trigger/interface/P2GTCandidate.h b/DataFormats/L1Trigger/interface/P2GTCandidate.h new file mode 100644 index 0000000000000..9fdae587d3c41 --- /dev/null +++ b/DataFormats/L1Trigger/interface/P2GTCandidate.h @@ -0,0 +1,309 @@ +#ifndef DataFormats_L1Trigger_P2GTCandidate_h +#define DataFormats_L1Trigger_P2GTCandidate_h + +#include +#include +#include + +#include "DataFormats/Common/interface/Ref.h" +#include "DataFormats/Common/interface/RefVector.h" +#include "DataFormats/Candidate/interface/LeafCandidate.h" + +namespace l1t { + + class L1GTProducer; + + class P2GTCandidate; + typedef std::vector P2GTCandidateCollection; + typedef edm::Ref P2GTCandidateRef; + typedef edm::RefVector P2GTCandidateRefVector; + typedef std::vector P2GTCandidateVectorRef; + + class P2GTCandidate : public reco::LeafCandidate { + public: + using Base = reco::LeafCandidate; + + using Base::Base; + + friend class L1GTProducer; + + typedef ap_uint<16> hwPT_t; + typedef ap_int<13> hwPhi_t; + typedef ap_int<14> hwEta_t; + typedef ap_int<18> hwZ0_t; + typedef ap_uint<11> hwIso_t; + typedef ap_uint<8> hwQual_t; + typedef ap_uint<1> hwCharge_t; + typedef ap_int<12> hwD0_t; + typedef ap_uint<4> hwBeta_t; + typedef ap_uint<10> hwMass_t; + typedef ap_uint<16> hwIndex_t; + typedef ap_uint<10> hwSeed_pT_t; + typedef ap_int<10> hwSeed_z0_t; + typedef ap_uint<16> hwSca_sum_t; + typedef ap_uint<5> hwNumber_of_tracks_t; + typedef ap_uint<12> hwSum_pT_pv_t; + typedef ap_uint<2> hwType_t; + typedef ap_uint<8> hwNumber_of_tracks_in_pv_t; + typedef ap_uint<10> hwNumber_of_tracks_not_in_pv_t; + + // Similar to std::optional but avoids inheritance for ROOT file embedding + template + struct Optional { + Optional() : value_(0), set_(false) {} + Optional(T value) : value_(value), set_(true) {} + + operator T() const { return value_; } + operator bool() const { return set_; } + + bool operator==(bool rhs) const { return set_ == rhs; } + bool operator!=(bool rhs) const { return set_ != rhs; } + + private: + T value_; + bool set_; + }; + + enum ObjectType { + Undefined, + GCTNonIsoEg, + GCTIsoEg, + GCTJets, + GCTTaus, + GCTHtSum, + GCTEtSum, + GMTSaPromptMuons, + GMTSaDisplacedMuons, + GMTTkMuons, + GMTTopo, + GTTPromptJets, + GTTDisplacedJets, + GTTPhiCandidates, + GTTRhoCandidates, + GTTBsCandidates, + GTTHadronicTaus, + GTTPrimaryVert, + GTTPromptHtSum, + GTTDisplacedHtSum, + GTTEtSum, + CL2Jets, + CL2Taus, + CL2Electrons, + CL2Photons, + CL2HtSum, + CL2EtSum + }; + + void setHwPT(hwPT_t hwPT) { hwPT_ = hwPT.to_int(); } + void setHwPhi(hwPhi_t hwPhi) { hwPhi_ = hwPhi.to_int(); } + void setHwEta(hwEta_t hwEta) { hwEta_ = hwEta.to_int(); } + void setHwZ0(hwZ0_t hwZ0) { hwZ0_ = hwZ0.to_int(); } + void setHwIso(hwIso_t hwIso) { hwIso_ = hwIso.to_int(); } + void setHwQual(hwQual_t hwQual) { hwQual_ = hwQual.to_int(); } + void setHwCharge(hwCharge_t hwCharge) { hwCharge_ = hwCharge.to_int(); } + void setHwD0(hwD0_t hwD0) { hwD0_ = hwD0.to_int(); } + void setHwBeta(hwBeta_t hwBeta) { hwBeta_ = hwBeta.to_int(); } + void setHwMass(hwMass_t hwMass) { hwMass_ = hwMass.to_int(); } + void setHwIndex(hwIndex_t hwIndex) { hwIndex_ = hwIndex.to_int(); } + void setHwSeed_pT(hwSeed_pT_t hwSeed_pT) { hwSeed_pT_ = hwSeed_pT.to_int(); } + void setHwSeed_z0(hwSeed_z0_t hwSeed_z0) { hwSeed_z0_ = hwSeed_z0.to_int(); } + void setHwSca_sum(hwSca_sum_t hwSca_sum) { hwSca_sum_ = hwSca_sum.to_int(); } + void setHwNumber_of_tracks(hwNumber_of_tracks_t hwNumber_of_tracks) { + hwNumber_of_tracks_ = hwNumber_of_tracks.to_int(); + } + + void setHwSum_pT_pv(hwSum_pT_pv_t hwSum_pT_pv) { hwSum_pT_pv_ = hwSum_pT_pv.to_int(); } + void setHwType(hwType_t hwType) { hwType_ = hwType.to_int(); } + void setHwNumber_of_tracks_in_pv(hwNumber_of_tracks_in_pv_t hwNumber_of_tracks_in_pv) { + hwNumber_of_tracks_in_pv_ = hwNumber_of_tracks_in_pv.to_int(); + } + void setHwNumber_of_tracks_not_in_pv(hwNumber_of_tracks_not_in_pv_t hwNumber_of_tracks_not_in_pv) { + hwNumber_of_tracks_not_in_pv_ = hwNumber_of_tracks_not_in_pv.to_int(); + } + + hwPT_t hwPT() const { + if (!hwPT_) { + throw std::invalid_argument("Object doesn't have pT"); + } + return static_cast(hwPT_); + } + + hwPhi_t hwPhi() const { + if (!hwPhi_) { + throw std::invalid_argument("Object doesn't have phi"); + } + return static_cast(hwPhi_); + } + + hwEta_t hwEta() const { + if (!hwEta_) { + throw std::invalid_argument("Object doesn't have eta"); + } + return static_cast(hwEta_); + } + + hwZ0_t hwZ0() const { + if (!hwZ0_) { + throw std::invalid_argument("Object doesn't have z0"); + } + return static_cast(hwZ0_); + } + + hwIso_t hwIso() const { + if (!hwIso_) { + throw std::invalid_argument("Object doesn't have iso"); + } + return static_cast(hwIso_); + } + + hwQual_t hwQual() const { + if (!hwQual_) { + throw std::invalid_argument("Object doesn't have qual"); + } + return static_cast(hwQual_); + } + + hwCharge_t hwCharge() const { + if (!hwCharge_) { + throw std::invalid_argument("Object doesn't have charge"); + } + return static_cast(hwCharge_); + } + + hwD0_t hwD0() const { + if (!hwD0_) { + throw std::invalid_argument("Object doesn't have d0"); + } + return static_cast(hwD0_); + } + + hwBeta_t hwBeta() const { + if (!hwBeta_) { + throw std::invalid_argument("Object doesn't have beta"); + } + return static_cast(hwBeta_); + } + + hwMass_t hwMass() const { + if (!hwMass_) { + throw std::invalid_argument("Object doesn't have mass"); + } + return static_cast(hwMass_); + } + + hwIndex_t hwIndex() const { + if (!hwIndex_) { + throw std::invalid_argument("Object doesn't have index"); + } + return static_cast(hwIndex_); + } + + hwSeed_pT_t hwSeed_pT() const { + if (!hwSeed_pT_) { + throw std::invalid_argument("Object doesn't have seed_pT"); + } + return static_cast(hwSeed_pT_); + } + + hwSeed_z0_t hwSeed_z0() const { + if (!hwSeed_z0_) { + throw std::invalid_argument("Object doesn't have seed_z0"); + } + return static_cast(hwSeed_z0_); + } + + hwSca_sum_t hwSca_sum() const { + if (!hwSca_sum_) { + throw std::invalid_argument("Object doesn't have sca_sum"); + } + return static_cast(hwSca_sum_); + } + + hwNumber_of_tracks_t hwNumber_of_tracks() const { + if (!hwNumber_of_tracks_) { + throw std::invalid_argument("Object doesn't have number_of_tracks"); + } + return static_cast(hwNumber_of_tracks_); + } + + hwSum_pT_pv_t hwSum_pT_pv() const { + if (!hwSum_pT_pv_) { + throw std::invalid_argument("Object doesn't have sum_pT_pv"); + } + return static_cast(hwSum_pT_pv_); + } + + hwType_t hwType() const { + if (!hwType_) { + throw std::invalid_argument("Object doesn't have type"); + } + return static_cast(hwType_); + } + + hwNumber_of_tracks_in_pv_t hwNumber_of_tracks_in_pv() const { + if (!hwNumber_of_tracks_in_pv_) { + throw std::invalid_argument("Object doesn't have number_of_tracks_in_pv"); + } + return static_cast(hwNumber_of_tracks_in_pv_); + } + + hwNumber_of_tracks_not_in_pv_t hwNumber_of_tracks_not_in_pv() const { + if (!hwNumber_of_tracks_not_in_pv_) { + throw std::invalid_argument("Object doesn't have hwNumber_of_tracks_not_in_pv"); + } + return static_cast(hwNumber_of_tracks_not_in_pv_); + } + + ObjectType objectType() const { return objectType_; } + + bool operator==(const P2GTCandidate& rhs) const; + bool operator!=(const P2GTCandidate& rhs) const; + + bool isElectron() const override { return objectType_ == CL2Electrons; }; + + bool isMuon() const override { + return objectType_ == GMTSaPromptMuons || objectType_ == GMTSaDisplacedMuons || objectType_ == GMTTkMuons; + }; + + bool isStandAloneMuon() const override { + return objectType_ == GMTSaPromptMuons || objectType_ == GMTSaDisplacedMuons; + }; + + bool isTrackerMuon() const override { return objectType_ == GMTTkMuons; } + + bool isPhoton() const override { return objectType_ == CL2Photons; } + + bool isJet() const override { + return objectType_ == GCTJets || objectType_ == GTTPromptJets || objectType_ == GTTDisplacedJets || + objectType_ == CL2Jets; + } + + private: + Optional hwPT_; + Optional hwPhi_; + Optional hwEta_; + Optional hwZ0_; + Optional hwIso_; + Optional hwQual_; + Optional hwCharge_; + Optional hwD0_; + Optional hwBeta_; + Optional hwMass_; + Optional hwIndex_; + Optional hwSeed_pT_; + Optional hwSeed_z0_; + Optional hwSca_sum_; + Optional hwNumber_of_tracks_; + + // TODO ? + Optional hwSum_pT_pv_; + Optional hwType_; + Optional hwNumber_of_tracks_in_pv_; + Optional hwNumber_of_tracks_not_in_pv_; + + ObjectType objectType_ = Undefined; + }; + +}; // namespace l1t + +#endif // DataFormats_L1Trigger_P2GTCandidate_h diff --git a/DataFormats/L1Trigger/src/P2GTCandidate.cc b/DataFormats/L1Trigger/src/P2GTCandidate.cc new file mode 100644 index 0000000000000..42513681fcc9f --- /dev/null +++ b/DataFormats/L1Trigger/src/P2GTCandidate.cc @@ -0,0 +1,24 @@ +#include "DataFormats/L1Trigger/interface/P2GTCandidate.h" + +namespace l1t { + + bool P2GTCandidate::operator==(const P2GTCandidate& rhs) const { + return hwPT_ == rhs.hwPT_ && hwPhi_ == rhs.hwPhi_ && hwEta_ == rhs.hwEta_ && hwZ0_ == rhs.hwZ0_ && + hwIso_ == rhs.hwIso_ && hwQual_ == rhs.hwQual_ && hwCharge_ == rhs.hwCharge_ && hwD0_ == rhs.hwD0_ && + hwBeta_ == rhs.hwBeta_ && hwMass_ == rhs.hwMass_ && hwIndex_ == rhs.hwIndex_ && + hwSeed_pT_ == rhs.hwSeed_pT_ && hwSeed_z0_ == rhs.hwSeed_z0_ && hwSca_sum_ == rhs.hwSca_sum_ && + hwNumber_of_tracks_ == rhs.hwNumber_of_tracks_ && hwSum_pT_pv_ == rhs.hwSum_pT_pv_ && + hwType_ == rhs.hwType_ && hwNumber_of_tracks_in_pv_ == rhs.hwNumber_of_tracks_in_pv_ && + hwNumber_of_tracks_not_in_pv_ == rhs.hwNumber_of_tracks_not_in_pv_; + } + + bool P2GTCandidate::operator!=(const P2GTCandidate& rhs) const { + return hwPT_ != rhs.hwPT_ && hwPhi_ != rhs.hwPhi_ && hwEta_ != rhs.hwEta_ && hwZ0_ != rhs.hwZ0_ && + hwIso_ != rhs.hwIso_ && hwQual_ != rhs.hwQual_ && hwCharge_ != rhs.hwCharge_ && hwD0_ != rhs.hwD0_ && + hwBeta_ != rhs.hwBeta_ && hwMass_ != rhs.hwMass_ && hwIndex_ != rhs.hwIndex_ && + hwSeed_pT_ != rhs.hwSeed_pT_ && hwSeed_z0_ != rhs.hwSeed_z0_ && hwSca_sum_ != rhs.hwSca_sum_ && + hwNumber_of_tracks_ != rhs.hwNumber_of_tracks_ && hwSum_pT_pv_ != rhs.hwSum_pT_pv_ && + hwType_ != rhs.hwType_ && hwNumber_of_tracks_in_pv_ != rhs.hwNumber_of_tracks_in_pv_ && + hwNumber_of_tracks_not_in_pv_ != rhs.hwNumber_of_tracks_not_in_pv_; + }; +} // namespace l1t diff --git a/DataFormats/L1Trigger/src/classes.h b/DataFormats/L1Trigger/src/classes.h index af95bb2a5c7dd..4b87a0018d5f0 100644 --- a/DataFormats/L1Trigger/src/classes.h +++ b/DataFormats/L1Trigger/src/classes.h @@ -36,3 +36,5 @@ #include "DataFormats/L1Trigger/interface/VertexWord.h" #include "DataFormats/L1Trigger/interface/TkJetWord.h" #include "DataFormats/Common/interface/RefToBase.h" +#include "DataFormats/L1Trigger/interface/P2GTCandidate.h" +#include "DataFormats/L1Trigger/interface/P2GTAlgoBlock.h" diff --git a/DataFormats/L1Trigger/src/classes_def.xml b/DataFormats/L1Trigger/src/classes_def.xml index a597e588a84bc..862c23e3c742f 100644 --- a/DataFormats/L1Trigger/src/classes_def.xml +++ b/DataFormats/L1Trigger/src/classes_def.xml @@ -14,6 +14,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/L1Trigger/Configuration/python/GTemulator_cff.py b/L1Trigger/Configuration/python/GTemulator_cff.py new file mode 100644 index 0000000000000..905753f0367d5 --- /dev/null +++ b/L1Trigger/Configuration/python/GTemulator_cff.py @@ -0,0 +1,13 @@ +import FWCore.ParameterSet.Config as cms + +# Global Trigger +from L1Trigger.Phase2L1GT.l1tGTProducer_cff import * +from L1Trigger.Phase2L1GT.l1tGTAlgoBlockProducer_cff import * + +# define a core which can be extented in customizations: +GTemulatorTask = cms.Task( + l1tGTProducer, + l1tGTAlgoBlockProducer +) + +GTemulator = cms.Sequence( GTemulatorTask ) diff --git a/L1Trigger/Phase2L1GT/.gitignore b/L1Trigger/Phase2L1GT/.gitignore new file mode 100644 index 0000000000000..8ab90aafbe469 --- /dev/null +++ b/L1Trigger/Phase2L1GT/.gitignore @@ -0,0 +1,4 @@ +test/*.root +test/*.txt +test/*.mem +*.vhd \ No newline at end of file diff --git a/L1Trigger/Phase2L1GT/BuildFile.xml b/L1Trigger/Phase2L1GT/BuildFile.xml new file mode 100644 index 0000000000000..41cc8ca53f05a --- /dev/null +++ b/L1Trigger/Phase2L1GT/BuildFile.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/L1Trigger/Phase2L1GT/interface/L1GTInvariantMassError.h b/L1Trigger/Phase2L1GT/interface/L1GTInvariantMassError.h new file mode 100644 index 0000000000000..f587353ba5827 --- /dev/null +++ b/L1Trigger/Phase2L1GT/interface/L1GTInvariantMassError.h @@ -0,0 +1,16 @@ +#ifndef L1Trigger_Phase2L1GT_InvariantMassError_h +#define L1Trigger_Phase2L1GT_InvariantMassError_h + +#include + +namespace l1t { + struct InvariantMassError { + const double absoluteError_ = 0; // GeV/c^2 + const double relativeError_ = 0; // GeV/c^2 (could also be calculated) + const double invariantMass_ = 0; // GeV/c^2 (calculated without LUT) + }; + + typedef std::vector InvariantMassErrorCollection; +} // namespace l1t + +#endif // L1Trigger_Phase2L1GT_InvariantMassError_h diff --git a/L1Trigger/Phase2L1GT/interface/L1GTScales.h b/L1Trigger/Phase2L1GT/interface/L1GTScales.h new file mode 100644 index 0000000000000..f70b0dc31493d --- /dev/null +++ b/L1Trigger/Phase2L1GT/interface/L1GTScales.h @@ -0,0 +1,97 @@ +#ifndef L1Trigger_Phase2L1GT_L1GTScales_h +#define L1Trigger_Phase2L1GT_L1GTScales_h + +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +#include + +namespace l1t { + class L1GTScales { + static constexpr int RELATIVE_ISOLATION_RESOLUTION = 10; // Resolution = 1/2^RELATIVE_ISOLATION_RESOLUTION + + public: + L1GTScales(double pT_lsb, + double phi_lsb, + double eta_lsb, + double z0_lsb, + //double dD_lsb, + double isolation_lsb, + double beta_lsb, + double mass_lsb, + double seed_pT_lsb, + double seed_dZ_lsb, + double sca_sum_lsb, + double sum_pT_pv_lsb, + int pos_chg, + int neg_chg); + + L1GTScales(const edm::ParameterSet &); + + static void fillPSetDescription(edm::ParameterSetDescription &); + + int to_hw_pT(double value) const { return std::round(value / pT_lsb_); }; + int to_hw_phi(double value) const { return std::round(value / phi_lsb_); }; + int to_hw_eta(double value) const { return std::round(value / eta_lsb_); }; + int to_hw_z0(double value) const { return std::round(value / z0_lsb_); }; + // int to_hw_d0(double value) const { return std::round(value / d0_lsb_); }; + int to_hw_isolation(double value) const { + return std::round(pT_lsb_ * value * std::pow(2, isolation_shift_) / isolation_lsb_); + } + int to_hw_beta(double value) const { return std::round(value / beta_lsb_); }; + int to_hw_mass(double value) const { return std::round(value / mass_lsb_); }; + int to_hw_seed_pT(double value) const { return std::round(value / seed_pT_lsb_); }; + int to_hw_seed_z0(double value) const { return std::round(value / seed_z0_lsb_); }; + int to_hw_sca_sum(double value) const { return std::round(value / sca_sum_lsb_); }; + int to_hw_sum_pT_pv(double value) const { return std::round(value / sum_pT_pv_lsb_); }; + + int to_hw_dRSquared(double value) const { return std::round(value * value / (eta_lsb_ * eta_lsb_)); } + + double to_hw_InvMassSqrDiv2(double value) const { return value * value / (2 * pT_lsb_ * pT_lsb_); } + double to_hw_TransMassSqrDiv2(double value) const { return value * value / (2 * pT_lsb_ * pT_lsb_); } + + double to_hw_PtSquared(double value) const { return value * value / (pT_lsb_ * pT_lsb_); } + + double to_pT(int value) const { return value * pT_lsb_; }; + double to_phi(int value) const { return value * phi_lsb_; }; + double to_eta(int value) const { return value * eta_lsb_; }; + double to_z0(int value) const { return value * z0_lsb_; }; + double to_sca_sum(int value) const { return value * sca_sum_lsb_; }; + int to_chg(int value) const { return value == pos_chg_ ? +1 : value == neg_chg_ ? -1 : 0; } + + double pT_lsb() const { return pT_lsb_; } + double phi_lsb() const { return phi_lsb_; } + double eta_lsb() const { return eta_lsb_; } + double z0_lsb() const { return z0_lsb_; } + double isolation_lsb() const { return isolation_lsb_; } + //const double dD_lsb_; + double beta_lsb() const { return beta_lsb_; } + double mass_lsb() const { return mass_lsb_; } + double seed_pT_lsb() const { return seed_pT_lsb_; } + double seed_z0_lsb() const { return seed_z0_lsb_; } + double sca_sum_lsb() const { return sca_sum_lsb_; } + double sum_pT_pv_lsb() const { return sum_pT_pv_lsb_; } + int pos_chg() const { return pos_chg_; } + int neg_chg() const { return neg_chg_; } + int isolation_shift() const { return isolation_shift_; } + + private: + const double pT_lsb_; + const double phi_lsb_; + const double eta_lsb_; + const double z0_lsb_; + //const double dD_lsb_; + const double isolation_lsb_; + const double isolation_shift_; + const double beta_lsb_; + const double mass_lsb_; + const double seed_pT_lsb_; + const double seed_z0_lsb_; + const double sca_sum_lsb_; + const double sum_pT_pv_lsb_; + const int pos_chg_; + const int neg_chg_; + }; +} // namespace l1t + +#endif // L1Trigger_Phase2L1GT_L1GTScales_h diff --git a/L1Trigger/Phase2L1GT/plugins/BuildFile.xml b/L1Trigger/Phase2L1GT/plugins/BuildFile.xml new file mode 100644 index 0000000000000..f47b21c7fdd30 --- /dev/null +++ b/L1Trigger/Phase2L1GT/plugins/BuildFile.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/L1Trigger/Phase2L1GT/plugins/L1GTAlgoBlockProducer.cc b/L1Trigger/Phase2L1GT/plugins/L1GTAlgoBlockProducer.cc new file mode 100644 index 0000000000000..98991980cd140 --- /dev/null +++ b/L1Trigger/Phase2L1GT/plugins/L1GTAlgoBlockProducer.cc @@ -0,0 +1,476 @@ +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "DataFormats/Common/interface/Handle.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Framework/interface/GetterOfProducts.h" +#include "FWCore/Framework/interface/TypeMatch.h" + +#include "FWCore/Framework/interface/MakerMacros.h" +#include "DataFormats/Common/interface/View.h" + +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/stream/EDProducer.h" + +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "FWCore/Framework/interface/TriggerNamesService.h" +#include "FWCore/ParameterSet/interface/Registry.h" + +#include "DataFormats/Common/interface/PathStatus.h" +#include "FWCore/Framework/interface/ConsumesCollector.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "FWCore/Utilities/interface/Exception.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "FWCore/Utilities/interface/propagate_const.h" + +#include + +#include "DataFormats/L1Trigger/interface/P2GTCandidate.h" +#include "DataFormats/L1Trigger/interface/P2GTAlgoBlock.h" + +#include +#include +#include +#include +#include +#include +#include + +/** pathStatusExpression is borrowed from \class edm::PathStatusFilter by W. David Dagenhart */ + +namespace qi = boost::spirit::qi; +namespace ascii = boost::spirit::ascii; + +namespace pathStatusExpression { + class Evaluator { + public: + virtual ~Evaluator() {} + + enum EvaluatorType { Name, Not, And, Or, BeginParen }; + virtual EvaluatorType type() const = 0; + + virtual const char* pathName() const { return ""; } + + virtual void setLeft(std::unique_ptr&&) {} + virtual void setRight(std::unique_ptr&&) {} + + virtual void print(std::ostream& out, unsigned int indentation) const {} + virtual void init(edm::ConsumesCollector&) {} + virtual bool evaluate(edm::Event const& event) const { return true; }; + }; + + class Operand : public Evaluator { + public: + Operand(std::vector const& pathName) : pathName_(pathName.begin(), pathName.end()) {} + + EvaluatorType type() const override { return Name; } + + void print(std::ostream& out, unsigned int indentation) const override { + out << std::string(indentation, ' ') << pathName_ << "\n"; + } + + void init(edm::ConsumesCollector& iC) override { token_ = iC.consumes(edm::InputTag(pathName_)); } + + bool evaluate(edm::Event const& event) const override { return event.get(token_).accept(); } + + private: + std::string pathName_; + edm::EDGetTokenT token_; + }; + + class NotOperator : public Evaluator { + public: + EvaluatorType type() const override { return Not; } + + void setLeft(std::unique_ptr&& v) override { operand_ = std::move(v); } + + void print(std::ostream& out, unsigned int indentation) const override { + out << std::string(indentation, ' ') << "not\n"; + operand_->print(out, indentation + 4); + } + + void init(edm::ConsumesCollector& iC) override { operand_->init(iC); } + + bool evaluate(edm::Event const& event) const override { return !operand_->evaluate(event); } + + private: + edm::propagate_const> operand_; + }; + + template + class BinaryOperator : public Evaluator { + public: + EvaluatorType type() const override; + + void setLeft(std::unique_ptr&& v) override { left_ = std::move(v); } + void setRight(std::unique_ptr&& v) override { right_ = std::move(v); } + + void print(std::ostream& out, unsigned int indentation) const override; + + void init(edm::ConsumesCollector& iC) override { + left_->init(iC); + right_->init(iC); + } + + bool evaluate(edm::Event const& event) const override { + T op; + return op(left_->evaluate(event), right_->evaluate(event)); + } + + private: + edm::propagate_const> left_; + edm::propagate_const> right_; + }; + + template <> + inline Evaluator::EvaluatorType BinaryOperator>::type() const { + return And; + } + + template <> + inline Evaluator::EvaluatorType BinaryOperator>::type() const { + return Or; + } + + template <> + void BinaryOperator>::print(std::ostream& out, unsigned int indentation) const { + out << std::string(indentation, ' ') << "and\n"; + left_->print(out, indentation + 4); + right_->print(out, indentation + 4); + } + template <> + void BinaryOperator>::print(std::ostream& out, unsigned int indentation) const { + out << std::string(indentation, ' ') << "or\n"; + left_->print(out, indentation + 4); + right_->print(out, indentation + 4); + } + + using AndOperator = BinaryOperator>; + using OrOperator = BinaryOperator>; + + class BeginParenthesis : public Evaluator { + public: + EvaluatorType type() const override { return BeginParen; } + }; + + // This class exists to properly handle the precedence of the + // operators and also handle the order of operations specified + // by parentheses. (search for shunting yard algorithm on the + // internet for a description of this algorithm) + class ShuntingYardAlgorithm { + public: + void addPathName(std::vector const& s) { + operandStack.push_back(std::make_unique(s)); + pathNames_.emplace_back(s.begin(), s.end()); + } + + void addOperatorNot() { + if (operatorStack.empty() || operatorStack.back()->type() != Evaluator::Not) { + operatorStack.push_back(std::make_unique()); + } else { + // Two Not operations in a row cancel and are the same as no operation at all. + operatorStack.pop_back(); + } + } + + void moveBinaryOperator() { + std::unique_ptr& backEvaluator = operatorStack.back(); + backEvaluator->setRight(std::move(operandStack.back())); + operandStack.pop_back(); + backEvaluator->setLeft(std::move(operandStack.back())); + operandStack.pop_back(); + operandStack.push_back(std::move(backEvaluator)); + operatorStack.pop_back(); + } + + void moveNotOperator() { + std::unique_ptr& backEvaluator = operatorStack.back(); + backEvaluator->setLeft(std::move(operandStack.back())); + operandStack.pop_back(); + operandStack.push_back(std::move(backEvaluator)); + operatorStack.pop_back(); + } + + void addOperatorAnd() { + while (!operatorStack.empty()) { + std::unique_ptr& backEvaluator = operatorStack.back(); + if (backEvaluator->type() == Evaluator::And) { + moveBinaryOperator(); + } else if (backEvaluator->type() == Evaluator::Not) { + moveNotOperator(); + } else { + break; + } + } + operatorStack.push_back(std::make_unique()); + } + + void addOperatorOr() { + while (!operatorStack.empty()) { + std::unique_ptr& backEvaluator = operatorStack.back(); + if (backEvaluator->type() == Evaluator::And || backEvaluator->type() == Evaluator::Or) { + moveBinaryOperator(); + } else if (backEvaluator->type() == Evaluator::Not) { + moveNotOperator(); + } else { + break; + } + } + operatorStack.push_back(std::make_unique()); + } + + void addBeginParenthesis() { operatorStack.push_back(std::make_unique()); } + + void addEndParenthesis() { + while (!operatorStack.empty()) { + std::unique_ptr& backEvaluator = operatorStack.back(); + if (backEvaluator->type() == Evaluator::BeginParen) { + operatorStack.pop_back(); + break; + } + if (backEvaluator->type() == Evaluator::And || backEvaluator->type() == Evaluator::Or) { + moveBinaryOperator(); + } else if (backEvaluator->type() == Evaluator::Not) { + moveNotOperator(); + } + } + } + + std::unique_ptr finish() { + while (!operatorStack.empty()) { + std::unique_ptr& backEvaluator = operatorStack.back(); + // Just a sanity check. The grammar defined for the boost Spirit parser + // should catch any errors of this type before we get here. + if (backEvaluator->type() == Evaluator::BeginParen) { + throw cms::Exception("LogicError") << "Should be impossible to get this error. Contact a Framework developer"; + } + if (backEvaluator->type() == Evaluator::And || backEvaluator->type() == Evaluator::Or) { + moveBinaryOperator(); + } else if (backEvaluator->type() == Evaluator::Not) { + moveNotOperator(); + } + } + // Just a sanity check. The grammar defined for the boost Spirit parser + // should catch any errors of this type before we get here. + if (!operatorStack.empty() || operandStack.size() != 1U) { + throw cms::Exception("LogicError") << "Should be impossible to get this error. Contact a Framework developer"; + } + std::unique_ptr temp = std::move(operandStack.back()); + operandStack.pop_back(); + return temp; + } + + const std::vector& pathNames() { return pathNames_; } + + private: + std::vector pathNames_; + std::vector> operandStack; + std::vector> operatorStack; + }; + + // Use boost Spirit to parse the logical expression character string + template + class Grammar : public qi::grammar { + public: + Grammar(ShuntingYardAlgorithm* algorithm) : Grammar::base_type(expression), algorithm_(algorithm) { + // setup functors that call into shunting algorithm while parsing the logical expression + auto addPathName = std::bind(&ShuntingYardAlgorithm::addPathName, algorithm_, std::placeholders::_1); + auto addOperatorNot = std::bind(&ShuntingYardAlgorithm::addOperatorNot, algorithm_); + auto addOperatorAnd = std::bind(&ShuntingYardAlgorithm::addOperatorAnd, algorithm_); + auto addOperatorOr = std::bind(&ShuntingYardAlgorithm::addOperatorOr, algorithm_); + auto addBeginParenthesis = std::bind(&ShuntingYardAlgorithm::addBeginParenthesis, algorithm_); + auto addEndParenthesis = std::bind(&ShuntingYardAlgorithm::addEndParenthesis, algorithm_); + + // Define the syntax allowed in the logical expressions + pathName = !unaryOperator >> !binaryOperatorTest >> (+qi::char_("a-zA-Z0-9_"))[addPathName]; + binaryOperand = (qi::lit('(')[addBeginParenthesis] >> expression >> qi::lit(')')[addEndParenthesis]) | + (unaryOperator[addOperatorNot] >> binaryOperand) | pathName; + afterOperator = ascii::space | &qi::lit('(') | &qi::eoi; + unaryOperator = qi::lit("not") >> afterOperator; + // The only difference in the next two is that one calls a functor and the other does not + binaryOperatorTest = (qi::lit("and") >> afterOperator) | (qi::lit("or") >> afterOperator); + binaryOperator = + (qi::lit("and") >> afterOperator)[addOperatorAnd] | (qi::lit("or") >> afterOperator)[addOperatorOr]; + expression = binaryOperand % binaryOperator; + } + + private: + qi::rule pathName; + qi::rule binaryOperand; + qi::rule afterOperator; + qi::rule unaryOperator; + qi::rule binaryOperatorTest; + qi::rule binaryOperator; + qi::rule expression; + + ShuntingYardAlgorithm* algorithm_; + }; +} // namespace pathStatusExpression + +using namespace l1t; + +class L1GTAlgoBlockProducer : public edm::stream::EDProducer<> { +public: + explicit L1GTAlgoBlockProducer(const edm::ParameterSet&); + ~L1GTAlgoBlockProducer() override = default; + + static void fillDescriptions(edm::ConfigurationDescriptions&); + + void beginRun(const edm::Run& iRun, const edm::EventSetup& iSetup) override; + +private: + struct AlgoDefinition { + edm::propagate_const> evaluator_; + std::vector pathNames_; + std::set> filtModules_; + }; + + void produce(edm::Event&, const edm::EventSetup&) override; + + edm::GetterOfProducts getterOfPassedReferences_; + std::map algoDefinitions_; +}; + +void L1GTAlgoBlockProducer::fillDescriptions(edm::ConfigurationDescriptions& description) { + edm::ParameterSetDescription algoDesc; + algoDesc.add("name", ""); + algoDesc.add("expression"); + + edm::ParameterSetDescription desc; + desc.addVPSet("algorithms", algoDesc); + + description.addWithDefaultLabel(desc); +} + +L1GTAlgoBlockProducer::L1GTAlgoBlockProducer(const edm::ParameterSet& config) + : getterOfPassedReferences_(edm::TypeMatch(), this) { + edm::ConsumesCollector iC(consumesCollector()); + + for (const auto& algoConfig : config.getParameterSetVector("algorithms")) { + const std::string logicalExpression = algoConfig.getParameter("expression"); + std::string name = algoConfig.getParameter("name"); + if (name.empty()) { + name = logicalExpression; + } + + pathStatusExpression::ShuntingYardAlgorithm shuntingYardAlgorithm; + pathStatusExpression::Grammar grammar(&shuntingYardAlgorithm); + + auto it = logicalExpression.cbegin(); + if (!qi::phrase_parse(it, logicalExpression.cend(), grammar, ascii::space) || (it != logicalExpression.cend())) { + throw cms::Exception("Configuration") << "Syntax error in logical expression. Here is an example of how\n" + << "the syntax should look:\n" + << " \"path1 and not (path2 or not path3)\"\n" + << "The expression must contain alternating appearances of operands\n" + << "which are path names and binary operators which can be \'and\'\n" + << "or \'or\', with a path name at the beginning and end. There\n" + << "must be at least one path name. In addition to the alternating\n" + << "path names and binary operators, the unary operator \'not\' can\n" + << "be inserted before a path name or a begin parenthesis.\n" + << "Parentheses are allowed. Parentheses must come in matching pairs.\n" + << "Matching begin and end parentheses must contain a complete and\n" + << "syntactically correct logical expression. There must be at least\n" + << "one space or parenthesis between operators and path names. Extra\n" + << "space is ignored and OK. Path names can only contain upper and\n" + << "lower case letters, numbers, and underscores. A path name cannot\n" + << "be the same as an operator name.\n"; + } + + AlgoDefinition definition; + + for (const std::string& pathName : shuntingYardAlgorithm.pathNames()) { + definition.pathNames_.push_back(pathName); + } + + definition.evaluator_ = shuntingYardAlgorithm.finish(); + + definition.evaluator_->init(iC); + algoDefinitions_.emplace(std::move(name), std::move(definition)); + } + + callWhenNewProductsRegistered(getterOfPassedReferences_); + produces(); +} + +void L1GTAlgoBlockProducer::beginRun(const edm::Run& iRun, const edm::EventSetup& iSetup) { + const std::string& pName = edm::Service()->getProcessName(); + + edm::ProcessConfiguration cfg; + + iRun.processHistory().getConfigurationForProcess(pName, cfg); + + const edm::ParameterSet* pset = edm::pset::Registry::instance()->getMapped(cfg.parameterSetID()); + + for (auto& [name, algoDef] : algoDefinitions_) { + for (const std::string& pathName : algoDef.pathNames_) { + if (pset->existsAs>(pathName)) { + const auto& modules = pset->getParameter>(pathName); + for (const auto& mod : modules) { + if (mod.front() != std::string("-") && pset->exists(mod)) { + const auto& modPSet = pset->getParameterSet(mod); + if (modPSet.getParameter("@module_edm_type") == "EDFilter") { + if (modPSet.getParameter("@module_type") == "L1GTSingleObjectCond") { + algoDef.filtModules_.insert({mod, modPSet.getParameter("tag").instance()}); + } else if (modPSet.getParameter("@module_type") == "L1GTDoubleObjectCond") { + algoDef.filtModules_.insert( + {mod, modPSet.getParameterSet("collection1").getParameter("tag").instance()}); + algoDef.filtModules_.insert( + {mod, modPSet.getParameterSet("collection2").getParameter("tag").instance()}); + } else if (modPSet.getParameter("@module_type") == "L1GTTripleObjectCond") { + algoDef.filtModules_.insert( + {mod, modPSet.getParameterSet("collection1").getParameter("tag").instance()}); + algoDef.filtModules_.insert( + {mod, modPSet.getParameterSet("collection2").getParameter("tag").instance()}); + algoDef.filtModules_.insert( + {mod, modPSet.getParameterSet("collection3").getParameter("tag").instance()}); + } else if (modPSet.getParameter("@module_type") == "L1GTQuadObjectCond") { + algoDef.filtModules_.insert( + {mod, modPSet.getParameterSet("collection1").getParameter("tag").instance()}); + algoDef.filtModules_.insert( + {mod, modPSet.getParameterSet("collection2").getParameter("tag").instance()}); + algoDef.filtModules_.insert( + {mod, modPSet.getParameterSet("collection3").getParameter("tag").instance()}); + algoDef.filtModules_.insert( + {mod, modPSet.getParameterSet("collection4").getParameter("tag").instance()}); + } + } + } + } + } + } + } +} + +void L1GTAlgoBlockProducer::produce(edm::Event& event, const edm::EventSetup& eventSetup) { + std::vector> handles; + getterOfPassedReferences_.fillHandles(event, handles); + + std::unique_ptr algoCollection = std::make_unique(); + algoCollection->reserve(algoDefinitions_.size()); + + for (const auto& [name, algoDef] : algoDefinitions_) { + bool initial = algoDef.evaluator_->evaluate(event); + // TODO apply prescale and bunch mask + + P2GTCandidateVectorRef trigObjects; + + if (initial) { + for (const auto& handle : handles) { + const std::string& module = handle.provenance()->moduleLabel(); + const std::string& instance = handle.provenance()->productInstanceName(); + + if (algoDef.filtModules_.count({module, instance}) > 0) { + trigObjects.insert(trigObjects.end(), handle->begin(), handle->end()); + } + } + } + + algoCollection->emplace_back(name, initial, initial, initial, std::move(trigObjects)); + } + + event.put(std::move(algoCollection)); +} + +DEFINE_FWK_MODULE(L1GTAlgoBlockProducer); diff --git a/L1Trigger/Phase2L1GT/plugins/L1GTBoardWriter.cc b/L1Trigger/Phase2L1GT/plugins/L1GTBoardWriter.cc new file mode 100644 index 0000000000000..9c5d1402fedc4 --- /dev/null +++ b/L1Trigger/Phase2L1GT/plugins/L1GTBoardWriter.cc @@ -0,0 +1,104 @@ +/** + * BoardDataWriter for validation with hardware. Currently only writing the algo bits is implemented. + **/ + +#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/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/Utilities/interface/InputTag.h" + +#include "L1Trigger/DemonstratorTools/interface/BoardDataWriter.h" +#include "L1Trigger/DemonstratorTools/interface/utilities.h" + +#include "FWCore/Utilities/interface/EDGetToken.h" + +#include "DataFormats/L1Trigger/interface/P2GTAlgoBlock.h" + +#include "ap_int.h" + +#include +#include +#include + +using namespace l1t; + +class L1GTBoardWriter : public edm::one::EDAnalyzer<> { +public: + explicit L1GTBoardWriter(const edm::ParameterSet&); + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + +private: + void analyze(const edm::Event&, const edm::EventSetup&) override; + void endJob() override; + + const std::vector channels_; + const std::vector algoBitMask_; + const edm::EDGetTokenT algoBlocksToken_; + l1t::demo::BoardDataWriter boardDataWriter_; +}; + +L1GTBoardWriter::L1GTBoardWriter(const edm::ParameterSet& config) + : channels_(config.getParameter>("channels")), + algoBitMask_(config.getParameter>("algoBitMask")), + algoBlocksToken_(consumes(config.getParameter("algoBlocksTag"))), + boardDataWriter_( + l1t::demo::parseFileFormat(config.getParameter("patternFormat")), + config.getParameter("outputFilename"), + config.getParameter("outputFileExtension"), + 9, + 1, + config.getParameter("maxLines"), + [](const std::vector& channels) { + l1t::demo::BoardDataWriter::ChannelMap_t channelMap; + for (unsigned int channel : channels) { + channelMap.insert({l1t::demo::LinkId{"Algos", channel}, {l1t::demo::ChannelSpec{1, 0, 0}, {channel}}}); + } + return channelMap; + }(channels_)) {} + +void L1GTBoardWriter::analyze(const edm::Event& event, const edm::EventSetup& iSetup) { + l1t::demo::EventData eventData; + const P2GTAlgoBlockCollection& algoBlocks = event.get(algoBlocksToken_); + + auto algoBlockIt = algoBlocks.begin(); + auto algoMaskIt = algoBitMask_.begin(); + + for (unsigned int channel : channels_) { + std::vector> bits(9, 0); + for (std::size_t word = 0; word < 9; word++) { + ap_uint<64> mask = algoMaskIt != algoBitMask_.end() ? *algoMaskIt++ : ~static_cast(0); + + for (std::size_t idx = 0; idx < 64 && algoBlockIt != algoBlocks.end(); idx++) { + bits[word].set(idx, algoBlockIt->decisionBeforeBxMaskAndPrescale() && mask.bit(idx)); + algoBlockIt++; + } + } + + eventData.add({"Algos", channel}, bits); + } + + boardDataWriter_.addEvent(eventData); +} + +void L1GTBoardWriter::endJob() { boardDataWriter_.flush(); } + +void L1GTBoardWriter::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.add("outputFilename"); + desc.add("outputFileExtension", "txt"); + desc.add("algoBlocksTag"); + desc.add>("channels"); + desc.add>("algoBitMask", {}); + desc.add("maxLines", 1024); + desc.add("patternFormat", "EMPv2"); + + descriptions.addDefault(desc); +} + +DEFINE_FWK_MODULE(L1GTBoardWriter); diff --git a/L1Trigger/Phase2L1GT/plugins/L1GTDeltaCut.h b/L1Trigger/Phase2L1GT/plugins/L1GTDeltaCut.h new file mode 100644 index 0000000000000..2683ff9398334 --- /dev/null +++ b/L1Trigger/Phase2L1GT/plugins/L1GTDeltaCut.h @@ -0,0 +1,268 @@ +#ifndef L1Trigger_Phase2L1GT_L1GTDeltaCut_h +#define L1Trigger_Phase2L1GT_L1GTDeltaCut_h + +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/L1Trigger/interface/P2GTCandidate.h" + +#include "L1Trigger/Phase2L1GT/interface/L1GTInvariantMassError.h" + +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "L1Trigger/Phase2L1GT/interface/L1GTScales.h" + +#include "L1GTSingleInOutLUT.h" +#include "L1GTOptionalParam.h" + +#include + +namespace l1t { + + class L1GTDeltaCut { + public: + static constexpr uint32_t DETA_LUT_SPLIT = 1 << 13; // hw 2pi + + L1GTDeltaCut(const edm::ParameterSet& config, + const edm::ParameterSet& lutConfig, + const L1GTScales& scales, + bool enable_sanity_checks = false, + bool inv_mass_checks = false) + : scales_(scales), + coshEtaLUT_(lutConfig.getParameterSet("cosh_eta_lut")), + coshEtaLUT2_(lutConfig.getParameterSet("cosh_eta_lut2")), + cosPhiLUT_(lutConfig.getParameterSet("cos_phi_lut")), + minDEta_(getOptionalParam( + "minDEta", config, [&scales](double value) { return scales.to_hw_eta(value); })), + maxDEta_(getOptionalParam( + "maxDEta", config, [&scales](double value) { return scales.to_hw_eta(value); })), + minDPhi_(getOptionalParam( + "minDPhi", config, [&scales](double value) { return scales.to_hw_phi(value); })), + maxDPhi_(getOptionalParam( + "maxDPhi", config, [&scales](double value) { return scales.to_hw_phi(value); })), + minDz_(getOptionalParam( + "minDz", config, [&scales](double value) { return scales.to_hw_z0(value); })), + maxDz_(getOptionalParam( + "maxDz", config, [&scales](double value) { return scales.to_hw_z0(value); })), + minDRSquared_(getOptionalParam( + "minDR", config, [&scales](double value) { return scales.to_hw_dRSquared(value); })), + maxDRSquared_(getOptionalParam( + "maxDR", config, [&scales](double value) { return scales.to_hw_dRSquared(value); })), + minInvMassSqrDiv2_(getOptionalParam( + "minInvMass", config, [&scales](double value) { return scales.to_hw_InvMassSqrDiv2(value); })), + maxInvMassSqrDiv2_(getOptionalParam( + "maxInvMass", config, [&scales](double value) { return scales.to_hw_InvMassSqrDiv2(value); })), + minTransMassSqrDiv2_(getOptionalParam( + "minTransMass", config, [&scales](double value) { return scales.to_hw_TransMassSqrDiv2(value); })), + maxTransMassSqrDiv2_(getOptionalParam( + "maxTransMass", config, [&scales](double value) { return scales.to_hw_TransMassSqrDiv2(value); })), + minPTSquared_(getOptionalParam( + "minCombPt", config, [&scales](double value) { return scales.to_hw_PtSquared(value); })), + maxPTSquared_(getOptionalParam( + "maxCombPt", config, [&scales](double value) { return scales.to_hw_PtSquared(value); })), + os_(config.getParameter("os")), + ss_(config.getParameter("ss")), + enable_sanity_checks_(enable_sanity_checks), + inv_mass_checks_(inv_mass_checks) {} + + bool checkObjects(const P2GTCandidate& obj1, + const P2GTCandidate& obj2, + InvariantMassErrorCollection& massErrors) const { + bool res = true; + + std::optional dEta; + + if (minDEta_ || maxDEta_ || minDRSquared_ || maxDRSquared_ || minInvMassSqrDiv2_ || maxInvMassSqrDiv2_) { + dEta = (obj1.hwEta() > obj2.hwEta()) ? obj1.hwEta().to_int() - obj2.hwEta().to_int() + : obj2.hwEta().to_int() - obj1.hwEta().to_int(); + res &= minDEta_ ? dEta > minDEta_ : true; + res &= maxDEta_ ? dEta < maxDEta_ : true; + } + + constexpr int HW_PI = 1 << (P2GTCandidate::hwPhi_t::width - 1); // assumes phi in [-pi, pi) + + // Ensure dPhi is always the smaller angle, i.e. always between [0, pi] + std::optional dPhi; + + if (minDPhi_ || maxDPhi_ || minDRSquared_ || maxDRSquared_ || minInvMassSqrDiv2_ || maxInvMassSqrDiv2_ || + minTransMassSqrDiv2_ || maxTransMassSqrDiv2_ || minPTSquared_ || maxPTSquared_) { + dPhi = HW_PI - abs(abs(obj1.hwPhi().to_int() - obj2.hwPhi().to_int()) - HW_PI); + } + + res &= minDPhi_ ? dPhi > minDPhi_ : true; + res &= maxDPhi_ ? dPhi < maxDPhi_ : true; + + if (minDz_ || maxDz_) { + uint32_t dZ = abs(obj1.hwZ0() - obj2.hwZ0()); + res &= minDz_ ? dZ > minDz_ : true; + res &= maxDz_ ? dZ < maxDz_ : true; + } + + if (minDRSquared_ || maxDRSquared_) { + uint32_t dRSquared = dEta.value() * dEta.value() + dPhi.value() * dPhi.value(); + res &= minDRSquared_ ? dRSquared > minDRSquared_ : true; + res &= maxDRSquared_ ? dRSquared < maxDRSquared_ : true; + } + + res &= os_ ? obj1.hwCharge() != obj2.hwCharge() : true; + res &= ss_ ? obj1.hwCharge() == obj2.hwCharge() : true; + + int32_t lutCoshDEta; + if (dEta) { + lutCoshDEta = dEta < DETA_LUT_SPLIT ? coshEtaLUT_[dEta.value()] : coshEtaLUT2_[dEta.value() - DETA_LUT_SPLIT]; + } + + // Optimization: (cos(x + pi) = -cos(x), x in [0, pi)) + int32_t lutCosDPhi; + if (dPhi) { + lutCosDPhi = dPhi >= HW_PI ? -cosPhiLUT_[dPhi.value()] : cosPhiLUT_[dPhi.value()]; + } + + if (enable_sanity_checks_ && dEta && dPhi) { + // Check whether the LUT error is smaller or equal than the expected maximum LUT error + double coshEtaLUTMax = dEta < DETA_LUT_SPLIT ? coshEtaLUT_.hwMax_error() : coshEtaLUT2_.hwMax_error(); + double etaLUTScale = dEta < DETA_LUT_SPLIT ? coshEtaLUT_.output_scale() : coshEtaLUT2_.output_scale(); + + if (std::abs(lutCoshDEta - etaLUTScale * std::cosh(dEta.value() * scales_.eta_lsb())) > coshEtaLUTMax) { + edm::LogError("COSH LUT") << "Difference larger than max LUT error: " << coshEtaLUTMax + << ", lut: " << lutCoshDEta + << ", calc: " << etaLUTScale * std::cosh(dEta.value() * scales_.eta_lsb()) + << ", dEta: " << dEta.value() << ", scale: " << etaLUTScale; + } + + if (std::abs(lutCosDPhi - cosPhiLUT_.output_scale() * std::cos(dPhi.value() * scales_.phi_lsb())) > + cosPhiLUT_.hwMax_error()) { + edm::LogError("COS LUT") << "Difference larger than max LUT error: " << cosPhiLUT_.hwMax_error() + << ", lut: " << lutCosDPhi << ", calc: " + << cosPhiLUT_.output_scale() * std::cos(dPhi.value() * scales_.phi_lsb()); + } + } + + if (minInvMassSqrDiv2_ || maxInvMassSqrDiv2_) { + int64_t invMassSqrDiv2; + if (dEta < DETA_LUT_SPLIT) { + // dEta [0, 2pi) + invMassSqrDiv2 = obj1.hwPT().to_int64() * obj2.hwPT().to_int64() * (lutCoshDEta - lutCosDPhi); + res &= minInvMassSqrDiv2_ + ? invMassSqrDiv2 > std::round(minInvMassSqrDiv2_.value() * coshEtaLUT_.output_scale()) + : true; + res &= maxInvMassSqrDiv2_ + ? invMassSqrDiv2 < std::round(maxInvMassSqrDiv2_.value() * coshEtaLUT_.output_scale()) + : true; + } else { + // dEta [2pi, 4pi), ignore cos + invMassSqrDiv2 = obj1.hwPT().to_int64() * obj2.hwPT().to_int64() * lutCoshDEta; + res &= minInvMassSqrDiv2_ + ? invMassSqrDiv2 > std::round(minInvMassSqrDiv2_.value() * coshEtaLUT2_.output_scale()) + : true; + res &= maxInvMassSqrDiv2_ + ? invMassSqrDiv2 < std::round(maxInvMassSqrDiv2_.value() * coshEtaLUT2_.output_scale()) + : true; + } + + if (inv_mass_checks_) { + double precInvMass = + scales_.pT_lsb() * + std::sqrt(2 * obj1.hwPT().to_double() * obj2.hwPT().to_double() * + (std::cosh(dEta.value() * scales_.eta_lsb()) - std::cos(dPhi.value() * scales_.phi_lsb()))); + + double lutInvMass = scales_.pT_lsb() * std::sqrt(2 * static_cast(invMassSqrDiv2) / + (dEta < DETA_LUT_SPLIT ? coshEtaLUT_.output_scale() + : coshEtaLUT2_.output_scale())); + + double error = std::abs(precInvMass - lutInvMass); + massErrors.emplace_back(InvariantMassError{error, error / precInvMass, precInvMass}); + } + } + + if (minPTSquared_ || maxPTSquared_) { + int64_t pTSquared = obj1.hwPT().to_int64() * obj1.hwPT().to_int64() * + static_cast(std::round(cosPhiLUT_.output_scale())) + + obj2.hwPT().to_int64() * obj2.hwPT().to_int64() * + static_cast(std::round(cosPhiLUT_.output_scale())) + + 2 * obj1.hwPT().to_int64() * obj2.hwPT().to_int64() * lutCosDPhi; + res &= minPTSquared_ ? pTSquared > std::round(minPTSquared_.value() * cosPhiLUT_.output_scale()) : true; + res &= maxPTSquared_ ? pTSquared < std::round(maxPTSquared_.value() * cosPhiLUT_.output_scale()) : true; + } + + if (minTransMassSqrDiv2_ || maxTransMassSqrDiv2_) { + int64_t transMassDiv2 = obj1.hwPT().to_int64() * obj2.hwPT().to_int64() * + (static_cast(coshEtaLUT_.output_scale()) - lutCosDPhi); + res &= minTransMassSqrDiv2_ + ? transMassDiv2 > std::round(minTransMassSqrDiv2_.value() * coshEtaLUT_.output_scale()) + : true; + res &= maxTransMassSqrDiv2_ + ? transMassDiv2 < std::round(maxTransMassSqrDiv2_.value() * coshEtaLUT_.output_scale()) + : true; + } + + return res; + } + + static void fillLUTDescriptions(edm::ParameterSetDescription& desc) { + edm::ParameterSetDescription coshLUTDesc; + L1GTSingleInOutLUT::fillLUTDescriptions(coshLUTDesc); + desc.add("cosh_eta_lut", coshLUTDesc); + + edm::ParameterSetDescription coshLUT2Desc; + L1GTSingleInOutLUT::fillLUTDescriptions(coshLUT2Desc); + desc.add("cosh_eta_lut2", coshLUT2Desc); + + edm::ParameterSetDescription cosLUTDesc; + L1GTSingleInOutLUT::fillLUTDescriptions(cosLUTDesc); + desc.add("cos_phi_lut", cosLUTDesc); + } + + static void fillPSetDescription(edm::ParameterSetDescription& desc) { + desc.addOptional("minDEta"); + desc.addOptional("maxDEta"); + desc.addOptional("minDPhi"); + desc.addOptional("maxDPhi"); + desc.addOptional("minDR"); + desc.addOptional("maxDR"); + desc.addOptional("minDz"); + desc.addOptional("maxDz"); + desc.addOptional("minInvMass"); + desc.addOptional("maxInvMass"); + desc.addOptional("minTransMass"); + desc.addOptional("maxTransMass"); + desc.addOptional("minCombPt"); + desc.addOptional("maxCombPt"); + desc.add("os", false); + desc.add("ss", false); + } + + private: + const L1GTScales& scales_; + + const L1GTSingleInOutLUT coshEtaLUT_; // [0, 2pi) + const L1GTSingleInOutLUT coshEtaLUT2_; // [2pi, 4pi) + const L1GTSingleInOutLUT cosPhiLUT_; + + const std::optional minDEta_; + const std::optional maxDEta_; + const std::optional minDPhi_; + const std::optional maxDPhi_; + const std::optional minDz_; + const std::optional maxDz_; + + const std::optional minDRSquared_; + const std::optional maxDRSquared_; + + const std::optional minInvMassSqrDiv2_; + const std::optional maxInvMassSqrDiv2_; + const std::optional minTransMassSqrDiv2_; + const std::optional maxTransMassSqrDiv2_; + + const std::optional minPTSquared_; + const std::optional maxPTSquared_; + + const bool os_; // Opposite sign + const bool ss_; // Same sign + + const bool enable_sanity_checks_; + const bool inv_mass_checks_; + }; + +} // namespace l1t + +#endif // L1Trigger_Phase2L1GT_L1GTDeltaCut_h diff --git a/L1Trigger/Phase2L1GT/plugins/L1GTDoubleObjectCond.cc b/L1Trigger/Phase2L1GT/plugins/L1GTDoubleObjectCond.cc new file mode 100644 index 0000000000000..249f991778171 --- /dev/null +++ b/L1Trigger/Phase2L1GT/plugins/L1GTDoubleObjectCond.cc @@ -0,0 +1,162 @@ +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/global/EDFilter.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/L1Trigger/interface/P2GTCandidate.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" + +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "DataFormats/Common/interface/Handle.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "DataFormats/Common/interface/Ref.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "L1Trigger/Phase2L1GT/interface/L1GTInvariantMassError.h" + +#include "L1Trigger/Phase2L1GT/interface/L1GTScales.h" + +#include "L1GTOptionalParam.h" +#include "L1GTSingleCollectionCut.h" +#include "L1GTDeltaCut.h" +#include "L1GTSingleInOutLUT.h" + +#include +#include +#include +#include + +#include + +using namespace l1t; + +class L1GTDoubleObjectCond : public edm::global::EDFilter<> { +public: + explicit L1GTDoubleObjectCond(const edm::ParameterSet&); + ~L1GTDoubleObjectCond() override = default; + + static void fillDescriptions(edm::ConfigurationDescriptions&); + +private: + bool filter(edm::StreamID, edm::Event&, const edm::EventSetup&) const override; + + const L1GTScales scales_; + + const L1GTSingleCollectionCut collection1Cuts_; + const L1GTSingleCollectionCut collection2Cuts_; + + const bool enable_sanity_checks_; + const bool inv_mass_checks_; + + const L1GTDeltaCut deltaCuts_; + + const edm::EDGetTokenT token1_; + const edm::EDGetTokenT token2_; +}; + +L1GTDoubleObjectCond::L1GTDoubleObjectCond(const edm::ParameterSet& config) + : scales_(config.getParameter("scales")), + collection1Cuts_(config.getParameterSet("collection1"), config, scales_), + collection2Cuts_(config.getParameterSet("collection2"), config, scales_), + enable_sanity_checks_(config.getUntrackedParameter("sanity_checks")), + inv_mass_checks_(config.getUntrackedParameter("inv_mass_checks")), + deltaCuts_(config, config, scales_, enable_sanity_checks_, inv_mass_checks_), + token1_(consumes(collection1Cuts_.tag())), + token2_(collection1Cuts_.tag() == collection2Cuts_.tag() + ? token1_ + : consumes(collection2Cuts_.tag())) { + produces(collection1Cuts_.tag().instance()); + + if (!(collection1Cuts_.tag() == collection2Cuts_.tag())) { + produces(collection2Cuts_.tag().instance()); + } + + if (inv_mass_checks_) { + produces(); + } +} + +void L1GTDoubleObjectCond::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + + edm::ParameterSetDescription collection1Desc; + L1GTSingleCollectionCut::fillPSetDescription(collection1Desc); + desc.add("collection1", collection1Desc); + + edm::ParameterSetDescription collection2Desc; + L1GTSingleCollectionCut::fillPSetDescription(collection2Desc); + desc.add("collection2", collection2Desc); + + desc.addUntracked("sanity_checks", false); + desc.addUntracked("inv_mass_checks", false); + + L1GTDeltaCut::fillPSetDescription(desc); + L1GTDeltaCut::fillLUTDescriptions(desc); + + edm::ParameterSetDescription scalesDesc; + L1GTScales::fillPSetDescription(scalesDesc); + desc.add("scales", scalesDesc); + + descriptions.addWithDefaultLabel(desc); +} + +bool L1GTDoubleObjectCond::filter(edm::StreamID, edm::Event& event, const edm::EventSetup& setup) const { + edm::Handle col1 = event.getHandle(token1_); + edm::Handle col2 = event.getHandle(token2_); + + bool condition_result = false; + + std::set triggeredIdcs1; + std::set triggeredIdcs2; + + InvariantMassErrorCollection massErrors; + + for (std::size_t idx1 = 0; idx1 < col1->size(); ++idx1) { + for (std::size_t idx2 = 0; idx2 < col2->size(); ++idx2) { + // If we're looking at the same collection then we shouldn't use the same object in one comparison. + if (col1.product() == col2.product() && idx1 == idx2) { + continue; + } + + bool pass = true; + pass &= collection1Cuts_.checkObject(col1->at(idx1)); + pass &= collection2Cuts_.checkObject(col2->at(idx2)); + pass &= deltaCuts_.checkObjects(col1->at(idx1), col2->at(idx2), massErrors); + + condition_result |= pass; + + if (pass) { + triggeredIdcs1.emplace(idx1); + if (col1.product() != col2.product()) { + triggeredIdcs2.emplace(idx2); + } else { + triggeredIdcs1.emplace(idx2); + } + } + } + } + + if (condition_result) { + std::unique_ptr triggerCol1 = std::make_unique(); + + for (std::size_t idx : triggeredIdcs1) { + triggerCol1->push_back(P2GTCandidateRef(col1, idx)); + } + event.put(std::move(triggerCol1), collection1Cuts_.tag().instance()); + + if (col1.product() != col2.product()) { + std::unique_ptr triggerCol2 = std::make_unique(); + + for (std::size_t idx : triggeredIdcs2) { + triggerCol2->push_back(P2GTCandidateRef(col2, idx)); + } + event.put(std::move(triggerCol2), collection2Cuts_.tag().instance()); + } + } + + if (inv_mass_checks_) { + event.put(std::make_unique(std::move(massErrors)), ""); + } + + return condition_result; +} + +DEFINE_FWK_MODULE(L1GTDoubleObjectCond); diff --git a/L1Trigger/Phase2L1GT/plugins/L1GTEvaluationInterface.h b/L1Trigger/Phase2L1GT/plugins/L1GTEvaluationInterface.h new file mode 100644 index 0000000000000..a79ab9a8de36e --- /dev/null +++ b/L1Trigger/Phase2L1GT/plugins/L1GTEvaluationInterface.h @@ -0,0 +1,539 @@ +#ifndef L1Trigger_Phase2L1GT_L1GTEvaluationInterface_h +#define L1Trigger_Phase2L1GT_L1GTEvaluationInterface_h + +#include "DataFormats/L1Trigger/interface/P2GTCandidate.h" + +#include + +#include +#include +#include + +/** + * Source: CMS level-1 trigger interface specification: Global trigger + **/ +namespace l1t { + + template + A l1t_pack_int(const Args&... args) { + A result = 0; + std::size_t shift = 0; + ( + [&result, &shift](const auto& arg) { + result(shift + arg.width - 1, shift) = arg; + shift += arg.width; + }(args), + ...); + + return result; + } + + template + A l1t_unpack_int(const A& packed, Args&&... args) { + A temp = packed; + ( + [&temp](auto&& arg) { + arg = temp(arg.width - 1, 0); + temp >>= arg.width; + }(std::forward(args)), + ...); + return temp; + } + + struct L1TGT_BaseInterface { + virtual std::size_t packed_width() const = 0; + virtual P2GTCandidate to_GTObject() const = 0; + virtual ~L1TGT_BaseInterface() {} + }; + + template + struct L1TGT_Interface : public L1TGT_BaseInterface { + virtual ap_uint pack() const = 0; + virtual ap_uint unpack(const ap_uint&) = 0; + + static constexpr std::size_t WIDTH = N; + + std::size_t packed_width() const override { return WIDTH; } + }; + + template + struct L1TGT_Common3Vector : public L1TGT_Interface { + ap_uint<1> valid; + ap_uint<16> pT; + ap_int<13> phi; + ap_int<14> eta; + + L1TGT_Common3Vector(int valid = 0, int pT = 0, int phi = 0, int eta = 0) + : valid(valid), pT(pT), phi(phi), eta(eta){}; + + virtual ap_uint<44> pack_common() const { return l1t_pack_int>(valid, pT, phi, eta); } + + ap_uint pack() const override { return pack_common(); } + + ap_uint unpack(const ap_uint& packed) override { return l1t_unpack_int(packed, valid, pT, phi, eta); } + + P2GTCandidate to_GTObject() const override { + P2GTCandidate gt_object; + gt_object.setHwPT(pT); + gt_object.setHwPhi(phi); + gt_object.setHwEta(eta); + + return gt_object; + } + }; + + template + struct L1TGT_CommonSum : public L1TGT_Interface { + ap_uint<1> valid; + ap_uint<16> pT; + ap_int<13> phi; + ap_uint<16> scalar_sum_pT; + + L1TGT_CommonSum(int valid = 0, int pT = 0, int phi = 0, int scalar_sum_pT = 0) + : valid(valid), pT(pT), phi{phi}, scalar_sum_pT(scalar_sum_pT) {} + + ap_uint<46> pack_common() const { return l1t_pack_int>(valid, pT, phi, scalar_sum_pT); } + + ap_uint pack() const override { return pack_common(); } + + ap_uint unpack(const ap_uint& packed) override { + return l1t_unpack_int(packed, valid, pT, phi, scalar_sum_pT); + } + + P2GTCandidate to_GTObject() const override { + P2GTCandidate gt_object; + gt_object.setHwPT(pT); + gt_object.setHwPhi(phi); + gt_object.setHwSca_sum(scalar_sum_pT); + + return gt_object; + } + }; + + // Global Calorimeter Trigger + + struct L1TGT_GCT_EgammaNonIsolated6p6 : public L1TGT_Common3Vector<64> { + using L1TGT_Common3Vector::L1TGT_Common3Vector; + }; + + struct L1TGT_GCT_EgammaIsolated6p6 : public L1TGT_Common3Vector<64> { + using L1TGT_Common3Vector::L1TGT_Common3Vector; + }; + + struct L1TGT_GCT_jet6p6 : public L1TGT_Common3Vector<64> { + using L1TGT_Common3Vector::L1TGT_Common3Vector; + }; + + struct L1TGT_GCT_tau6p6 : public L1TGT_Common3Vector<64> { + ap_uint<10> seed_pT; + + L1TGT_GCT_tau6p6(int valid = 0, int pT = 0, int phi = 0, int eta = 0, int seed_pT = 0) + : L1TGT_Common3Vector(valid, pT, phi, eta), seed_pT(seed_pT) {} + + ap_uint pack() const override { + return l1t_pack_int>(L1TGT_Common3Vector::pack_common(), seed_pT); + } + + ap_uint unpack(const ap_uint& packed) override { + return l1t_unpack_int(L1TGT_Common3Vector::unpack(packed), seed_pT); + } + + P2GTCandidate to_GTObject() const override { + P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject()); + gt_object.setHwSeed_pT(seed_pT); + + return gt_object; + } + }; + + struct L1TGT_GCT_Sum2 : public L1TGT_CommonSum<64> { + using L1TGT_CommonSum::L1TGT_CommonSum; + }; + + // Global Muon Trigger + + struct L1TGT_GMT_PromptDisplacedMuon : public L1TGT_Common3Vector<64> { + ap_uint<5> z0; + ap_int<7> d0; + ap_uint<1> charge; + ap_uint<4> qual; + + L1TGT_GMT_PromptDisplacedMuon( + int valid = 0, int pT = 0, int phi = 0, int eta = 0, int z0 = 0, int d0 = 0, int charge = 0, int qual = 0) + : L1TGT_Common3Vector(valid, pT, phi, eta), z0(z0), d0(d0), charge(charge), qual(qual) {} + + ap_uint pack() const override { + return l1t_pack_int>(L1TGT_Common3Vector::pack_common(), z0, d0, charge, qual); + } + + ap_uint unpack(const ap_uint& packed) override { + return l1t_unpack_int(L1TGT_Common3Vector::unpack(packed), z0, d0, charge, qual); + } + + P2GTCandidate to_GTObject() const override { + P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject()); + gt_object.setHwZ0(static_cast(z0) << 5); + gt_object.setHwD0(static_cast(d0) << 5); + gt_object.setHwCharge(charge); + gt_object.setHwQual(qual); + + return gt_object; + } + }; + + struct L1TGT_GMT_TrackMatchedmuon : public L1TGT_Common3Vector<96> { + ap_int<10> z0; + ap_int<10> d0; + ap_uint<1> charge; + ap_uint<8> qual; + ap_uint<4> iso; + ap_uint<4> beta; + + L1TGT_GMT_TrackMatchedmuon(int valid = 0, + int pT = 0, + int phi = 0, + int eta = 0, + int z0 = 0, + int d0 = 0, + int charge = 0, + int qual = 0, + int iso = 0, + int beta = 0) + : L1TGT_Common3Vector(valid, pT, phi, eta), z0(z0), d0(d0), charge(charge), qual(qual), iso(iso), beta(beta) {} + + ap_uint pack() const override { + return l1t_pack_int>(L1TGT_Common3Vector::pack_common(), z0, d0, charge, qual, iso, beta); + } + + ap_uint unpack(const ap_uint& packed) override { + return l1t_unpack_int(L1TGT_Common3Vector::unpack(packed), z0, d0, charge, qual, iso, beta); + } + + P2GTCandidate to_GTObject() const override { + P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject()); + gt_object.setHwZ0(z0); + gt_object.setHwD0(static_cast(d0) << 2); + gt_object.setHwCharge(charge); + gt_object.setHwQual(qual); + gt_object.setHwIso(static_cast(iso) << 7); + gt_object.setHwBeta(beta); + + return gt_object; + } + }; + + struct L1TGT_GMT_TopoObject : public L1TGT_Interface<64> { + ap_uint<1> valid; + ap_uint<8> pT; // TODO + ap_int<8> eta; + ap_int<8> phi; + ap_uint<8> mass; + ap_uint<6> qual; + // ap_uint<16> /* Index of 3 prongs */; + // ap_uint<3> /* Some other quality */; + + L1TGT_GMT_TopoObject(int valid = 0, int pT = 0, int phi = 0, int eta = 0, int mass = 0, int qual = 0) + : valid(valid), pT(pT), eta(eta), phi(phi), mass(mass), qual(qual) {} + + ap_uint pack() const override { return l1t_pack_int>(valid, pT, eta, phi, mass, qual); } + + ap_uint unpack(const ap_uint& packed) override { + return l1t_unpack_int(packed, valid, pT, eta, phi, mass, qual); + } + + P2GTCandidate to_GTObject() const override { + P2GTCandidate gt_object; + gt_object.setHwPT(static_cast(pT) * 5); // TODO + gt_object.setHwPhi(static_cast(phi) << 5); + gt_object.setHwEta(static_cast(eta) << 5); + gt_object.setHwMass(mass); + gt_object.setHwQual(qual); + + return gt_object; + } + }; + + // Global Track Trigger + + struct L1TGT_GTT_PromptJet : public L1TGT_Common3Vector<128> { + ap_int<10> z0; + ap_uint<5> number_of_tracks; + // ap_uint<5> /* unassigned */; + + L1TGT_GTT_PromptJet(int valid = 0, int pT = 0, int phi = 0, int eta = 0, int z0 = 0, int number_of_tracks = 0) + : L1TGT_Common3Vector(valid, pT, phi, eta), z0(z0), number_of_tracks(number_of_tracks) {} + + ap_uint pack() const override { + return l1t_pack_int>(L1TGT_Common3Vector::pack_common(), z0, number_of_tracks); + } + + ap_uint unpack(const ap_uint& packed) override { + return l1t_unpack_int>(L1TGT_Common3Vector::unpack(packed), z0, number_of_tracks); + } + + P2GTCandidate to_GTObject() const override { + P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject()); + gt_object.setHwZ0(z0); + gt_object.setHwNumber_of_tracks(number_of_tracks); + + return gt_object; + } + }; + + struct L1TGT_GTT_DisplacedJet : public L1TGT_Common3Vector<128> { + ap_int<10> z0; + ap_uint<5> number_of_tracks; + // ap_uint<5> /* unassigned */; + ap_int<12> d0; + + L1TGT_GTT_DisplacedJet( + int valid = 0, int pT = 0, int phi = 0, int eta = 0, int z0 = 0, int number_of_tracks = 0, int d0 = 0) + : L1TGT_Common3Vector(valid, pT, phi, eta), z0(z0), number_of_tracks(number_of_tracks), d0(d0) {} + + ap_uint pack() const override { + return l1t_pack_int>(L1TGT_Common3Vector::pack_common(), z0, number_of_tracks, ap_uint<5>(0), d0); + } + + ap_uint unpack(const ap_uint& packed) override { + return l1t_unpack_int>( + L1TGT_Common3Vector::unpack(packed), z0, number_of_tracks, ap_uint<5>(0), d0); + } + + P2GTCandidate to_GTObject() const override { + P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject()); + gt_object.setHwZ0(z0); + gt_object.setHwNumber_of_tracks(number_of_tracks); + gt_object.setHwD0(d0); + + return gt_object; + } + }; + + struct L1TGT_GTT_Sum : public L1TGT_CommonSum<64> { + using L1TGT_CommonSum::L1TGT_CommonSum; + }; + + struct L1TGT_GTT_HadronicTau : public L1TGT_Common3Vector<96> { + ap_uint<10> seed_pT; + ap_int<10> seed_z0; + ap_uint<1> charge; + ap_uint<2> type; + + L1TGT_GTT_HadronicTau(int valid = 0, + int pT = 0, + int phi = 0, + int eta = 0, + int seed_pT = 0, + int seed_z0 = 0, + int charge = 0, + int type = 0) + : L1TGT_Common3Vector(valid, pT, phi, eta), seed_pT(seed_pT), seed_z0(seed_z0), charge(charge), type(type) {} + + ap_uint pack() const override { + return l1t_pack_int>(L1TGT_Common3Vector::pack_common(), seed_pT, seed_z0, charge, type); + } + + ap_uint unpack(const ap_uint& packed) override { + return l1t_unpack_int(L1TGT_Common3Vector::unpack(packed), seed_pT, seed_z0, charge, type); + } + + P2GTCandidate to_GTObject() const override { + P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject()); + gt_object.setHwSeed_pT(seed_pT); + gt_object.setHwSeed_z0(seed_z0); + gt_object.setHwCharge(charge); + gt_object.setHwType(type); + + return gt_object; + } + }; + + struct L1TGT_GTT_LightMeson : public L1TGT_Common3Vector<96> { + ap_int<10> z0; + //ap_uint<10> /* candidate mass */; + //ap_uint<2> /* candidate type */; + //ap_uint<3> /* nbr of tracks */; + + L1TGT_GTT_LightMeson(int valid = 0, int pT = 0, int phi = 0, int eta = 0, int z0 = 0) + : L1TGT_Common3Vector(valid, pT, phi, eta), z0(z0) {} + + ap_uint pack() const override { + return l1t_pack_int>(L1TGT_Common3Vector::pack_common(), z0); + } + + ap_uint unpack(const ap_uint& packed) override { + return l1t_unpack_int(L1TGT_Common3Vector::unpack(packed), z0); + } + + P2GTCandidate to_GTObject() const override { + P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject()); + gt_object.setHwZ0(z0); + + return gt_object; + } + }; + + struct L1TGT_GTT_PrimaryVert : public L1TGT_Interface<64> { + ap_uint<1> valid; + ap_int<15> z0; + ap_uint<8> number_of_tracks_in_pv; + ap_uint<12> sum_pT_pv; + ap_uint<3> qual; + ap_uint<10> number_of_tracks_not_in_pv; + // ap_uint<15> /* unassigned */; + + L1TGT_GTT_PrimaryVert(int valid = 0, + int z0 = 0, + int number_of_tracks_in_pv = 0, + int sum_pT_pv = 0, + int qual = 0, + int number_of_tracks_not_in_pv = 0) + : valid(valid), + z0(z0), + number_of_tracks_in_pv(number_of_tracks_in_pv), + sum_pT_pv(sum_pT_pv), + qual(qual), + number_of_tracks_not_in_pv(number_of_tracks_not_in_pv) {} + + ap_uint pack() const override { + return l1t_pack_int>( + valid, z0 /*, number_of_tracks_in_pv, sum_pT_pv, qual, number_of_tracks_not_in_pv */); // TODO: Maybe later + } + + ap_uint unpack(const ap_uint& packed) override { + return l1t_unpack_int(packed, valid, z0, number_of_tracks_in_pv, sum_pT_pv, qual, number_of_tracks_not_in_pv); + } + + P2GTCandidate to_GTObject() const override { + P2GTCandidate gt_object; + gt_object.setHwZ0(z0); + gt_object.setHwNumber_of_tracks_in_pv(number_of_tracks_in_pv); + gt_object.setHwSum_pT_pv(sum_pT_pv); + gt_object.setHwQual(qual); + gt_object.setHwNumber_of_tracks_not_in_pv(number_of_tracks_not_in_pv); + + return gt_object; + } + }; + + // Correlator Layer-2 + + struct L1TGT_CL2_Jet : public L1TGT_Common3Vector<128> { + ap_int<10> z0; + + L1TGT_CL2_Jet(int valid = 0, int pT = 0, int phi = 0, int eta = 0, int z0 = 0) + : L1TGT_Common3Vector(valid, pT, phi, eta), z0(z0) {} + + ap_uint pack() const override { + return l1t_pack_int>(L1TGT_Common3Vector::pack_common(), z0); + } + + ap_uint unpack(const ap_uint& packed) override { + return l1t_unpack_int(L1TGT_Common3Vector::unpack(packed), z0); + } + + P2GTCandidate to_GTObject() const override { + P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject()); + gt_object.setHwZ0(z0); + + return gt_object; + } + }; + + struct L1TGT_CL2_Sum : public L1TGT_CommonSum<64> { + using L1TGT_CommonSum::L1TGT_CommonSum; + }; + + struct L1TGT_CL2_Tau : public L1TGT_Common3Vector<96> { + ap_uint<10> seed_pT; + ap_int<10> seed_z0; + ap_uint<1> charge; + ap_uint<2> type; + //ap_uint<10> /* MVA Id / Isol */; + //ap_uint<2> /* Id vs Mu */; + //ap_uint<2> /* Id vs Mu */; + + L1TGT_CL2_Tau(int valid = 0, + int pT = 0, + int phi = 0, + int eta = 0, + int seed_pT = 0, + int seed_z0 = 0, + int charge = 0, + int type = 0) + : L1TGT_Common3Vector(valid, pT, phi, eta), seed_pT(seed_pT), seed_z0(seed_z0), charge(charge), type(type) {} + + ap_uint pack() const override { + return l1t_pack_int>(L1TGT_Common3Vector::pack_common(), seed_pT, seed_z0, charge, type); + } + + ap_uint unpack(const ap_uint& packed) override { + return l1t_unpack_int(L1TGT_Common3Vector::unpack(packed), seed_pT, seed_z0, charge, type); + } + + P2GTCandidate to_GTObject() const override { + P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject()); + gt_object.setHwSeed_pT(seed_pT); + gt_object.setHwSeed_z0(seed_z0); + gt_object.setHwCharge(charge); + gt_object.setHwType(type); + + return gt_object; + } + }; + + struct L1TGT_CL2_Electron : public L1TGT_Common3Vector<96> { + ap_uint<4> qual; + ap_uint<11> iso; + ap_uint<1> charge; + ap_int<10> z0; + + L1TGT_CL2_Electron( + int valid = 0, int pT = 0, int phi = 0, int eta = 0, int qual = 0, int iso = 0, int charge = 0, int z0 = 0) + : L1TGT_Common3Vector(valid, pT, phi, eta), qual(qual), iso(iso), charge(charge), z0(z0) {} + + ap_uint pack() const override { + return l1t_pack_int>(L1TGT_Common3Vector::pack_common(), qual, iso, charge, z0); + } + + ap_uint unpack(const ap_uint& packed) override { + return l1t_unpack_int(L1TGT_Common3Vector::unpack(packed), qual, iso, charge, z0); + } + + P2GTCandidate to_GTObject() const override { + P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject()); + gt_object.setHwQual(qual); + gt_object.setHwIso(iso); + gt_object.setHwCharge(charge); + gt_object.setHwZ0(z0); + + return gt_object; + } + }; + + struct L1TGT_CL2_Photon : public L1TGT_Common3Vector<96> { + ap_uint<4> qual; + ap_uint<11> iso; + + L1TGT_CL2_Photon(int valid = 0, int pT = 0, int phi = 0, int eta = 0, int qual = 0, int iso = 0) + : L1TGT_Common3Vector(valid, pT, phi, eta), qual(qual), iso(iso) {} + + ap_uint pack() const override { + return l1t_pack_int>(L1TGT_Common3Vector::pack_common(), qual, iso); + } + + ap_uint unpack(const ap_uint& packed) override { + return l1t_unpack_int(L1TGT_Common3Vector::unpack(packed), qual, iso); + } + + P2GTCandidate to_GTObject() const override { + P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject()); + gt_object.setHwQual(qual); + gt_object.setHwIso(iso); + + return gt_object; + } + }; +} // namespace l1t + +#endif // L1Trigger_Phase2L1GT_L1GTEvaluationInterface_h diff --git a/L1Trigger/Phase2L1GT/plugins/L1GTEvaluationProducer.cc b/L1Trigger/Phase2L1GT/plugins/L1GTEvaluationProducer.cc new file mode 100644 index 0000000000000..723b679014382 --- /dev/null +++ b/L1Trigger/Phase2L1GT/plugins/L1GTEvaluationProducer.cc @@ -0,0 +1,325 @@ +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/ParameterSet/interface/allowedValues.h" +#include "DataFormats/Common/interface/Handle.h" + +#include "FWCore/Framework/interface/MakerMacros.h" +#include "DataFormats/Common/interface/View.h" + +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/one/EDProducer.h" + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/L1Trigger/interface/P2GTCandidate.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" + +#include "L1Trigger/DemonstratorTools/interface/BoardDataWriter.h" +#include "L1Trigger/DemonstratorTools/interface/utilities.h" + +#include "L1GTEvaluationInterface.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace l1t; + +class L1GTEvaluationProducer : public edm::one::EDProducer<> { +public: + explicit L1GTEvaluationProducer(const edm::ParameterSet &); + ~L1GTEvaluationProducer() override = default; + + static void fillDescriptions(edm::ConfigurationDescriptions &); + +private: + void produce(edm::Event &, const edm::EventSetup &) override; + int nextValue(int mean = 1000, bool sign = false, int max = std::numeric_limits::max()); + + int nextPt() { + return std::max(0, + nextValue(300, false, (1 << P2GTCandidate::hwPT_t::width) - 1) + + std::normal_distribution(0, 500)(randomGenerator_)); + } + int nextEta() { + return std::uniform_int_distribution(-(1 << (P2GTCandidate::hwEta_t::width - 1)), + (1 << (P2GTCandidate::hwEta_t::width - 1)) - 1)(randomGenerator_); + } + int nextPhi() { + return std::uniform_int_distribution(-(1 << (P2GTCandidate::hwPhi_t::width - 1)), + (1 << (P2GTCandidate::hwPhi_t::width - 1)) - 1)(randomGenerator_); + } + + void writeInputPatterns( + const std::unordered_map>> &inputObjects); + + void endJob() override; + + std::mt19937 randomGenerator_; + l1t::demo::BoardDataWriter boardDataWriter_; +}; + +template +static constexpr std::array arange() { + std::array array; + T value = low; + for (T &el : array) { + el = value; + value += incr; + } + return array; +} + +template +static std::vector vrange() { + std::array arr(arange()); + return std::vector(std::begin(arr), std::end(arr)); +} + +static const l1t::demo::BoardDataWriter::ChannelMap_t CHANNEL_MAP_VU9P{ + {{"GTT", 0}, {{6, 0}, vrange()}}, + {{"GTT", 1}, {{6, 0}, vrange()}}, + {{"CL2", 0}, {{6, 0}, vrange()}}, + {{"CL2", 1}, {{6, 0}, vrange()}}, + {{"GCT", 0}, {{6, 0}, vrange()}}, + {{"GMT", 0}, {{18, 0}, vrange()}}, + {{"CL2", 2}, {{6, 0}, vrange()}}, + {{"GTT", 2}, {{6, 0}, vrange()}}, + {{"GTT", 3}, {{6, 0}, vrange()}}}; + +static const l1t::demo::BoardDataWriter::ChannelMap_t CHANNEL_MAP_VU13P{ + {{"GTT", 0}, {{6, 0}, vrange()}}, + {{"GTT", 1}, {{6, 0}, vrange()}}, + {{"GCT", 0}, {{6, 0}, vrange()}}, + {{"CL2", 0}, {{6, 0}, vrange()}}, + {{"CL2", 1}, {{6, 0}, vrange()}}, + {{"GMT", 0}, {{18, 0}, {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 68, 69, 70, 71, 72, 73}}}, + {{"CL2", 2}, {{6, 0}, vrange()}}, + {{"GTT", 2}, {{6, 0}, vrange()}}, + {{"GTT", 3}, {{6, 0}, vrange()}}}; + +L1GTEvaluationProducer::L1GTEvaluationProducer(const edm::ParameterSet &config) + : randomGenerator_(config.exists("random_seed") ? config.getParameter("random_seed") + : std::random_device()()), + boardDataWriter_(l1t::demo::parseFileFormat(config.getParameter("patternFormat")), + config.getParameter("outputFilename"), + config.getParameter("outputFileExtension"), + 9, + 1, + config.getParameter("maxLines"), + config.getParameter("platform") == "VU13P" ? CHANNEL_MAP_VU13P : CHANNEL_MAP_VU9P) { + produces("GCTNonIsoEg"); + produces("GCTIsoEg"); + produces("GCTJets"); + produces("GCTTaus"); + produces("GCTHtSum"); + produces("GCTEtSum"); + produces("GMTSaPromptMuons"); + produces("GMTSaDisplacedMuons"); + produces("GMTTkMuons"); + produces("GMTTopo"); + produces("GTTPromptJets"); + produces("GTTDisplacedJets"); + produces("GTTPhiCandidates"); + produces("GTTRhoCandidates"); + produces("GTTBsCandidates"); + produces("GTTHadronicTaus"); + produces("GTTPrimaryVert"); + produces("GTTPromptHtSum"); + produces("GTTDisplacedHtSum"); + produces("GTTEtSum"); + produces("CL2Jets"); + produces("CL2Taus"); + produces("CL2Electrons"); + produces("CL2Photons"); + produces("CL2HtSum"); + produces("CL2EtSum"); +} + +void L1GTEvaluationProducer::fillDescriptions(edm::ConfigurationDescriptions &description) { + edm::ParameterSetDescription desc; + desc.addOptional("random_seed"); + desc.add("maxLines", 1024); + desc.add("outputFilename"); + desc.add("outputFileExtension", "txt"); + desc.add("patternFormat", "EMPv2"); + desc.ifValue(edm::ParameterDescription("platform", "VU9P", true), + edm::allowedValues("VU9P", "VU13P")); + description.addWithDefaultLabel(desc); +} + +int L1GTEvaluationProducer::nextValue(int mean, bool sign, int max) { + bool positive = sign ? std::bernoulli_distribution(0.5)(randomGenerator_) : true; + + int result; + do { + result = std::poisson_distribution(mean)(randomGenerator_); + } while (result > max); + + return positive ? result : -result; +} + +template +static std::vector> vpack(const Args &...vobjects) { + std::vector> vpacked; + + ( + [&vpacked](const std::vector> &objects) { + std::optional> next_packed; + for (const auto &object : objects) { + if (object->packed_width() == 64) { + const l1t::L1TGT_Interface<64> &interface_obj = dynamic_cast &>(*object); + vpacked.emplace_back(interface_obj.pack()); + } else if (object->packed_width() == 96) { + const l1t::L1TGT_Interface<96> &interface_obj = dynamic_cast &>(*object); + ap_uint<96> packed = interface_obj.pack(); + if (next_packed.has_value()) { + vpacked.emplace_back(packed(95, 64) << 32 | next_packed.value()); + next_packed.reset(); + } else { + next_packed = packed(95, 64); + } + + vpacked.emplace_back(packed(63, 0)); + + } else if (object->packed_width() == 128) { + const l1t::L1TGT_Interface<128> &interface_obj = dynamic_cast &>(*object); + ap_uint<128> packed = interface_obj.pack(); + vpacked.emplace_back(packed(63, 0)); + vpacked.emplace_back(packed(127, 64)); + } + } + }(vobjects), + ...); + + return vpacked; +} + +void L1GTEvaluationProducer::writeInputPatterns( + const std::unordered_map>> &inputObjects) { + boardDataWriter_.addEvent(l1t::demo::EventData{ + {{{"GTT", 0}, + vpack(inputObjects.at("GTTPromptJets"), + inputObjects.at("GTTDisplacedJets"), + inputObjects.at("GTTPromptHtSum"), + inputObjects.at("GTTDisplacedHtSum"), + inputObjects.at("GTTEtSum"))}, + {{"GTT", 1}, vpack(inputObjects.at("GTTHadronicTaus"))}, + {{"CL2", 0}, vpack(inputObjects.at("CL2Jets"), inputObjects.at("CL2HtSum"), inputObjects.at("CL2EtSum"))}, + {{"CL2", 1}, vpack(inputObjects.at("CL2Taus"))}, + {{"GCT", 0}, + vpack(inputObjects.at("GCTNonIsoEg"), + inputObjects.at("GCTIsoEg"), + inputObjects.at("GCTJets"), + inputObjects.at("GCTTaus"), + inputObjects.at("GCTHtSum"), + inputObjects.at("GCTEtSum"))}, + {{"GMT", 0}, + vpack(inputObjects.at("GMTSaPromptMuons"), + inputObjects.at("GMTSaDisplacedMuons"), + inputObjects.at("GMTTkMuons"), + inputObjects.at("GMTTopo"))}, + {{"CL2", 2}, vpack(inputObjects.at("CL2Electrons"), inputObjects.at("CL2Photons"))}, + {{"GTT", 2}, + vpack(inputObjects.at("GTTPhiCandidates"), + inputObjects.at("GTTRhoCandidates"), + inputObjects.at("GTTBsCandidates"))}, + {{"GTT", 3}, vpack(inputObjects.at("GTTPrimaryVert"))}}}); +} + +void L1GTEvaluationProducer::produce(edm::Event &event, const edm::EventSetup &setup) { + // Generate random input objects + std::unordered_map>> inputObjects; + for (std::size_t i = 0; i < 12; ++i) { + // Global Muon Trigger + inputObjects["GMTSaPromptMuons"].emplace_back(std::make_unique( + true, nextPt(), nextEta(), nextPhi(), nextValue(), nextValue(), nextValue(), nextValue())); + + inputObjects["GMTSaDisplacedMuons"].emplace_back(std::make_unique( + true, nextPt(), nextEta(), nextPhi(), nextValue(), nextValue(), nextValue(), nextValue())); + inputObjects["GMTTkMuons"].emplace_back(std::make_unique(true, + nextPt(), + nextEta(), + nextPhi(), + nextValue(), + nextValue(), + nextValue(), + nextValue(), + nextValue(), + nextValue())); + inputObjects["GMTTopo"].emplace_back( + std::make_unique(true, nextPt(), nextEta(), nextPhi(), nextValue(), nextValue())); + + // Global Calorimeter Trigger + inputObjects["GCTNonIsoEg"].emplace_back( + std::make_unique(true, nextPt(), nextEta(), nextPhi())); + inputObjects["GCTIsoEg"].emplace_back( + std::make_unique(true, nextPt(), nextEta(), nextPhi())); + inputObjects["GCTJets"].emplace_back(std::make_unique(true, nextPt(), nextEta(), nextPhi())); + inputObjects["GCTTaus"].emplace_back( + std::make_unique(true, nextPt(), nextEta(), nextPhi(), nextValue())); + + // Global Track Trigger + inputObjects["GTTPrimaryVert"].emplace_back( + std::make_unique(true, nextPt(), nextEta(), nextPhi(), nextValue(), nextValue())); + inputObjects["GTTPromptJets"].emplace_back( + std::make_unique(true, nextPt(), nextEta(), nextPhi(), nextValue(), nextValue())); + inputObjects["GTTDisplacedJets"].emplace_back(std::make_unique( + true, nextPt(), nextEta(), nextPhi(), nextValue(), nextValue(), nextValue())); + inputObjects["GTTHadronicTaus"].emplace_back(std::make_unique( + true, nextPt(), nextEta(), nextPhi(), nextValue(), nextValue(), nextValue(), nextValue())); + inputObjects["GTTPhiCandidates"].emplace_back( + std::make_unique(true, nextPt(), nextEta(), nextPhi(), nextValue())); + inputObjects["GTTRhoCandidates"].emplace_back( + std::make_unique(true, nextPt(), nextEta(), nextPhi(), nextValue())); + inputObjects["GTTBsCandidates"].emplace_back( + std::make_unique(true, nextPt(), nextEta(), nextPhi(), nextValue())); + + // Correlator Layer-2 + inputObjects["CL2Jets"].emplace_back( + std::make_unique(true, nextPt(), nextEta(), nextPhi(), nextValue())); + inputObjects["CL2Electrons"].emplace_back(std::make_unique( + true, nextPt(), nextEta(), nextPhi(), nextValue(), nextValue(), nextValue(), nextValue())); + inputObjects["CL2Photons"].emplace_back( + std::make_unique(true, nextPt(), nextEta(), nextPhi(), nextValue(), nextValue())); + inputObjects["CL2Taus"].emplace_back(std::make_unique( + true, nextPt(), nextEta(), nextPhi(), nextValue(), nextValue(), nextValue(), nextValue())); + } + + inputObjects["CL2HtSum"].emplace_back( + std::make_unique(true, nextValue(), nextValue(), nextValue())); + inputObjects["CL2EtSum"].emplace_back( + std::make_unique(true, nextValue(), nextValue(), nextValue())); + inputObjects["GCTHtSum"].emplace_back( + std::make_unique(true, nextValue(), nextValue(), nextValue())); + inputObjects["GCTEtSum"].emplace_back( + std::make_unique(true, nextValue(), nextValue(), nextValue())); + + inputObjects["GTTPromptHtSum"].emplace_back( + std::make_unique(true, nextValue(), nextValue(), nextValue())); + inputObjects["GTTDisplacedHtSum"].emplace_back( + std::make_unique(true, nextValue(), nextValue(), nextValue())); + inputObjects["GTTEtSum"].emplace_back( + std::make_unique(true, nextValue(), nextValue(), nextValue())); + + // Write them to a pattern file + writeInputPatterns(inputObjects); + + for (const auto &[key, inputCollection] : inputObjects) { + std::unique_ptr gtCollection = std::make_unique(); + for (const auto &object : inputCollection) { + gtCollection->emplace_back(object->to_GTObject()); + } + + event.put(std::move(gtCollection), key); + } +} + +void L1GTEvaluationProducer::endJob() { boardDataWriter_.flush(); } + +DEFINE_FWK_MODULE(L1GTEvaluationProducer); diff --git a/L1Trigger/Phase2L1GT/plugins/L1GTNTupleProducer.cc b/L1Trigger/Phase2L1GT/plugins/L1GTNTupleProducer.cc new file mode 100644 index 0000000000000..1028b2c64769c --- /dev/null +++ b/L1Trigger/Phase2L1GT/plugins/L1GTNTupleProducer.cc @@ -0,0 +1,163 @@ +#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/MessageLogger/interface/MessageLogger.h" + +#include "FWCore/ServiceRegistry/interface/Service.h" +#include "CommonTools/UtilAlgos/interface/TFileService.h" +#include "TTree.h" + +#include "DataFormats/L1Trigger/interface/P2GTCandidate.h" + +#include +#include +#include +#include + +using namespace l1t; + +class L1GTNTupleProducer : public edm::one::EDAnalyzer<> { +public: + explicit L1GTNTupleProducer(const edm::ParameterSet&); + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + +private: + //void beginJob(void) override; + void analyze(const edm::Event&, const edm::EventSetup&) override; + //void endJob() override; + +private: + void fillData(const l1t::P2GTCandidateCollection& collection, const std::string& instanceName); + + const std::string producerName_; + const unsigned maxNTuples_; + + const edm::EDGetTokenT gttPromptJetToken_; + const edm::EDGetTokenT gttDisplacedJetToken_; + const edm::EDGetTokenT gttPrimaryVertexToken_; + + const edm::EDGetTokenT gmtSaPromptMuonToken_; + const edm::EDGetTokenT gmtSaDisplacedMuonToken_; + const edm::EDGetTokenT gmtTkMuonToken_; + + const edm::EDGetTokenT cl2JetToken_; + const edm::EDGetTokenT cl2PhotonToken_; + const edm::EDGetTokenT cl2ElectronToken_; + const edm::EDGetTokenT cl2EtSumToken_; + const edm::EDGetTokenT cl2HtSumToken_; + + const edm::Service fs_; + TTree* tree_; + + std::unordered_map> data_; +}; + +static const std::map> NTUPLE_VARIABLES = { + {"GTTPromptJet", {"Pt", "Eta", "Phi"}}, + {"GTTDisplacedJet", {"Pt", "Eta", "Phi"}}, + {"GTTPrimaryVertex", {"Z0"}}, + {"GMTSaPromptMuon", {"Pt", "Eta", "Phi", "Z0"}}, + {"GMTSaDisplacedMuon", {"Pt", "Eta", "Phi", "Z0"}}, + {"GMTTkMuon", {"Pt", "Eta", "Phi", "Z0"}}, + {"CL2Jet", {"Pt", "Eta", "Phi", "Z0"}}, + {"CL2Photon", {"Pt", "Eta", "Phi"}}, + {"CL2Electron", {"Pt", "Eta", "Phi", "Z0"}}, + {"CL2EtSum", {"Pt", "Phi", "ScaSumPt"}}, + {"CL2HtSum", {"Pt", "Phi", "ScaSumPt"}}}; + +L1GTNTupleProducer::L1GTNTupleProducer(const edm::ParameterSet& config) + : producerName_(config.getParameter("producerName")), + maxNTuples_(config.getParameter("maxNTuples")), + gttPromptJetToken_(consumes(edm::InputTag(producerName_, "GTTPromptJets"))), + gttDisplacedJetToken_(consumes(edm::InputTag(producerName_, "GTTDisplacedJets"))), + gttPrimaryVertexToken_(consumes(edm::InputTag(producerName_, "GTTPrimaryVert"))), + gmtSaPromptMuonToken_(consumes(edm::InputTag(producerName_, "GMTSaPromptMuons"))), + gmtSaDisplacedMuonToken_(consumes(edm::InputTag(producerName_, "GMTSaDisplacedMuons"))), + gmtTkMuonToken_(consumes(edm::InputTag(producerName_, "GMTTkMuons"))), + cl2JetToken_(consumes(edm::InputTag(producerName_, "CL2Jets"))), + cl2PhotonToken_(consumes(edm::InputTag(producerName_, "CL2Photons"))), + cl2ElectronToken_(consumes(edm::InputTag(producerName_, "CL2Electrons"))), + cl2EtSumToken_(consumes(edm::InputTag(producerName_, "CL2EtSum"))), + cl2HtSumToken_(consumes(edm::InputTag(producerName_, "CL2HtSum"))), + tree_(fs_->make("L1PhaseIITree", "L1PhaseIITree")) { + for (const auto& [collec, variables] : NTUPLE_VARIABLES) { + for (const std::string& var : variables) { + std::string name = collec + var; + tree_->Branch(name.c_str(), &data_[name], 8000, 1); + } + } +} + +void L1GTNTupleProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.add("producerName"); + desc.add("maxNTuples"); + + descriptions.addDefault(desc); +} + +void L1GTNTupleProducer::fillData(const l1t::P2GTCandidateCollection& collection, const std::string& instanceName) { + for (const P2GTCandidate& object : collection) { + for (const std::string& var : NTUPLE_VARIABLES.at(instanceName)) { + std::string name = instanceName + var; + if (var == "Pt") + data_.at(name).push_back(object.hwPT()); + else if (var == "Eta") + data_.at(name).push_back(object.hwEta()); + else if (var == "Phi") + data_.at(name).push_back(object.hwPhi()); + else if (var == "Z0") + data_.at(name).push_back(object.hwZ0()); + else if (var == "D0") + data_.at(name).push_back(object.hwD0()); + else if (var == "ScaSumPt") + data_.at(name).push_back(object.hwSca_sum()); + } + } +} + +void L1GTNTupleProducer::analyze(const edm::Event& event, const edm::EventSetup& setup) { + const l1t::P2GTCandidateCollection& gttPromptJets = event.get(gttPromptJetToken_); + fillData(gttPromptJets, "GTTPromptJet"); + + const l1t::P2GTCandidateCollection& gttDisplacedJets = event.get(gttDisplacedJetToken_); + fillData(gttDisplacedJets, "GTTDisplacedJet"); + + const l1t::P2GTCandidateCollection& gttPrimaryVertices = event.get(gttPrimaryVertexToken_); + fillData(gttPrimaryVertices, "GTTPrimaryVertex"); + + const l1t::P2GTCandidateCollection& gmtSaPromptMuons = event.get(gmtSaPromptMuonToken_); + fillData(gmtSaPromptMuons, "GMTSaPromptMuon"); + + const l1t::P2GTCandidateCollection& gmtSaDisplacedMuons = event.get(gmtSaDisplacedMuonToken_); + fillData(gmtSaDisplacedMuons, "GMTSaDisplacedMuon"); + + const l1t::P2GTCandidateCollection& gmtTkMuons = event.get(gmtTkMuonToken_); + fillData(gmtTkMuons, "GMTTkMuon"); + + const l1t::P2GTCandidateCollection& cl2Jets = event.get(cl2JetToken_); + fillData(cl2Jets, "CL2Jet"); + + const l1t::P2GTCandidateCollection& cl2Photons = event.get(cl2PhotonToken_); + fillData(cl2Photons, "CL2Photon"); + + const l1t::P2GTCandidateCollection& cl2Electrons = event.get(cl2ElectronToken_); + fillData(cl2Electrons, "CL2Electron"); + + const l1t::P2GTCandidateCollection& cl2EtSum = event.get(cl2EtSumToken_); + fillData(cl2EtSum, "CL2EtSum"); + + const l1t::P2GTCandidateCollection& cl2HtSum = event.get(cl2HtSumToken_); + fillData(cl2HtSum, "CL2HtSum"); + + tree_->Fill(); + + for (auto& [key, vector] : data_) { + vector.clear(); + } +} + +DEFINE_FWK_MODULE(L1GTNTupleProducer); diff --git a/L1Trigger/Phase2L1GT/plugins/L1GTOptionalParam.h b/L1Trigger/Phase2L1GT/plugins/L1GTOptionalParam.h new file mode 100644 index 0000000000000..f3a959888255d --- /dev/null +++ b/L1Trigger/Phase2L1GT/plugins/L1GTOptionalParam.h @@ -0,0 +1,31 @@ +#ifndef L1Trigger_Phase2L1GT_L1GTOptionalParam_h +#define L1Trigger_Phase2L1GT_L1GTOptionalParam_h + +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +#include +#include +#include + +namespace l1t { + + template + inline std::optional getOptionalParam(const std::string& name, + const edm::ParameterSet& config, + std::function conv) { + if (config.exists(name)) { + return std::optional(conv(config.getParameter(name))); + } + return std::optional(); + } + + template + inline std::optional getOptionalParam(const std::string& name, const edm::ParameterSet& config) { + if (config.exists(name)) { + return std::optional(config.getParameter(name)); + } + return std::optional(); + } +} // namespace l1t + +#endif // L1Trigger_Phase2L1GT_L1GTOptionalParam_h diff --git a/L1Trigger/Phase2L1GT/plugins/L1GTProducer.cc b/L1Trigger/Phase2L1GT/plugins/L1GTProducer.cc new file mode 100644 index 0000000000000..4e1cf7d93ecc9 --- /dev/null +++ b/L1Trigger/Phase2L1GT/plugins/L1GTProducer.cc @@ -0,0 +1,438 @@ +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "DataFormats/Common/interface/Handle.h" +#include "FWCore/Utilities/interface/EDGetToken.h" + +#include "FWCore/Framework/interface/MakerMacros.h" +#include "DataFormats/Common/interface/View.h" + +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/global/EDProducer.h" + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/L1Trigger/interface/P2GTCandidate.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "L1Trigger/Phase2L1GT/interface/L1GTScales.h" + +#include "DataFormats/L1Trigger/interface/TkJetWord.h" +#include "DataFormats/L1Trigger/interface/VertexWord.h" + +#include "DataFormats/L1TMuonPhase2/interface/SAMuon.h" +#include "DataFormats/L1TMuonPhase2/interface/TrackerMuon.h" + +#include "DataFormats/L1TParticleFlow/interface/PFJet.h" +#include "DataFormats/L1TCorrelator/interface/TkEmFwd.h" +#include "DataFormats/L1TCorrelator/interface/TkEm.h" +#include "DataFormats/L1TCorrelator/interface/TkElectronFwd.h" +#include "DataFormats/L1TCorrelator/interface/TkElectron.h" +#include "DataFormats/L1TParticleFlow/interface/PFTau.h" +#include "DataFormats/L1TParticleFlow/interface/gt_datatypes.h" + +#include "DataFormats/L1Trigger/interface/EtSum.h" + +#include +#include +#include +#include + +namespace l1t { + + class L1GTProducer : public edm::global::EDProducer<> { + public: + explicit L1GTProducer(const edm::ParameterSet &); + ~L1GTProducer() override = default; + + static void fillDescriptions(edm::ConfigurationDescriptions &); + + private: + void produceGTTPromptJets(edm::Event &event) const; + void produceGTTDisplacedJets(edm::Event &event) const; + void produceGTTPrimaryVert(edm::Event &event) const; + + void produceGMTSaPromptMuons(edm::Event &event) const; + void produceGMTSaDisplacedMuons(edm::Event &event) const; + void produceGMTTkMuons(edm::Event &event) const; + + void produceCL2Jets(edm::Event &event) const; + void produceCL2Photons(edm::Event &event) const; + void produceCL2Electrons(edm::Event &event) const; + void produceCL2Taus(edm::Event &event) const; + void produceCL2EtSum(edm::Event &event) const; + void produceCl2HtSum(edm::Event &event) const; + + void produce(edm::StreamID, edm::Event &, const edm::EventSetup &) const override; + + const L1GTScales scales_; + + const edm::EDGetTokenT gttPromptJetToken_; + const edm::EDGetTokenT gttDisplacedJetToken_; + const edm::EDGetTokenT gttPrimaryVertexToken_; + + const edm::EDGetTokenT gmtSaPromptMuonToken_; + const edm::EDGetTokenT gmtSaDisplacedMuonToken_; + const edm::EDGetTokenT gmtTkMuonToken_; + + const edm::EDGetTokenT cl2JetToken_; + const edm::EDGetTokenT cl2PhotonToken_; + const edm::EDGetTokenT cl2ElectronToken_; + const edm::EDGetTokenT cl2TauToken_; + const edm::EDGetTokenT> cl2EtSumToken_; + const edm::EDGetTokenT> cl2HtSumToken_; + }; + + L1GTProducer::L1GTProducer(const edm::ParameterSet &config) + : scales_(config.getParameter("scales")), + gttPromptJetToken_(consumes(config.getParameter("GTTPromptJets"))), + gttDisplacedJetToken_(consumes(config.getParameter("GTTDisplacedJets"))), + gttPrimaryVertexToken_(consumes(config.getParameter("GTTPrimaryVert"))), + gmtSaPromptMuonToken_(consumes(config.getParameter("GMTSaPromptMuons"))), + gmtSaDisplacedMuonToken_(consumes(config.getParameter("GMTSaDisplacedMuons"))), + gmtTkMuonToken_(consumes(config.getParameter("GMTTkMuons"))), + cl2JetToken_(consumes(config.getParameter("CL2Jets"))), + cl2PhotonToken_(consumes(config.getParameter("CL2Photons"))), + cl2ElectronToken_(consumes(config.getParameter("CL2Electrons"))), + cl2TauToken_(consumes(config.getParameter("CL2Taus"))), + cl2EtSumToken_(consumes>(config.getParameter("CL2EtSum"))), + cl2HtSumToken_(consumes>(config.getParameter("CL2HtSum"))) { + produces("GTTPromptJets"); + produces("GTTDisplacedJets"); + produces("GTTPrimaryVert"); + + produces("GMTSaPromptMuons"); + produces("GMTSaDisplacedMuons"); + produces("GMTTkMuons"); + + produces("CL2Jets"); + produces("CL2Photons"); + produces("CL2Electrons"); + produces("CL2Taus"); + produces("CL2EtSum"); + produces("CL2HtSum"); + } + + void L1GTProducer::fillDescriptions(edm::ConfigurationDescriptions &description) { + edm::ParameterSetDescription desc; + + edm::ParameterSetDescription scalesDesc; + L1GTScales::fillPSetDescription(scalesDesc); + desc.add("scales", scalesDesc); + + desc.add("GTTPromptJets"); + desc.add("GTTDisplacedJets"); + desc.add("GTTPrimaryVert"); + + desc.add("GMTSaPromptMuons"); + desc.add("GMTSaDisplacedMuons"); + desc.add("GMTTkMuons"); + + desc.add("CL2Jets"); + desc.add("CL2Photons"); + desc.add("CL2Electrons"); + desc.add("CL2Taus"); + desc.add("CL2EtSum"); + desc.add("CL2HtSum"); + + description.addWithDefaultLabel(desc); + } + + void L1GTProducer::produceGTTPrimaryVert(edm::Event &event) const { + std::unique_ptr outputCollection = std::make_unique(); + const VertexWordCollection &collection = event.get(gttPrimaryVertexToken_); + for (std::size_t i = 0; i < collection.size() && i < 10; i++) { + const VertexWord &obj = collection[i]; + int hwZ0 = obj.z0Word().V.to_int() * 5; + P2GTCandidate gtObj( + 0, reco::ParticleState::PolarLorentzVector(), reco::ParticleState::Point(0, 0, scales_.to_z0(hwZ0))); + gtObj.hwZ0_ = hwZ0; + gtObj.hwQual_ = obj.qualityWord().V.to_int(); + gtObj.hwSum_pT_pv_ = obj.multiplicityWord().V.to_int(); + gtObj.hwNumber_of_tracks_in_pv_ = obj.multiplicityWord().V.to_int(); + gtObj.hwNumber_of_tracks_not_in_pv_ = obj.inverseMultiplicityWord().V.to_int(); + gtObj.objectType_ = P2GTCandidate::GTTPrimaryVert; + + outputCollection->push_back(gtObj); + } + event.put(std::move(outputCollection), "GTTPrimaryVert"); + } + + void L1GTProducer::produceGTTPromptJets(edm::Event &event) const { + std::unique_ptr outputCollection = std::make_unique(); + const TkJetWordCollection &collection = event.get(gttPromptJetToken_); + for (std::size_t i = 0; i < collection.size() && i < 12; i++) { + const TkJetWord &obj = collection[i]; + int hwZ0 = obj.z0Word().V.to_int() << 7; + P2GTCandidate gtObj(0, + reco::ParticleState::PolarLorentzVector(scales_.to_pT(obj.ptWord().V.to_int()), + scales_.to_eta(obj.glbEtaWord().V.to_int()), + scales_.to_phi(obj.glbPhiWord().V.to_int()), + 0), + reco::ParticleState::Point(0, 0, scales_.to_z0(hwZ0))); + gtObj.hwPT_ = obj.ptWord().V.to_int(); + gtObj.hwPhi_ = obj.glbPhiWord().V.to_int(); + gtObj.hwEta_ = obj.glbEtaWord().V.to_int(); + gtObj.hwZ0_ = hwZ0; + gtObj.hwNumber_of_tracks_ = obj.ntWord().V.to_int(); + gtObj.objectType_ = P2GTCandidate::GTTPromptJets; + + outputCollection->push_back(gtObj); + } + event.put(std::move(outputCollection), "GTTPromptJets"); + } + + void L1GTProducer::produceGTTDisplacedJets(edm::Event &event) const { + std::unique_ptr outputCollection = std::make_unique(); + const TkJetWordCollection &collection = event.get(gttDisplacedJetToken_); + for (std::size_t i = 0; i < collection.size() && i < 12; i++) { + const TkJetWord &obj = collection[i]; + int hwZ0 = obj.z0Word().V.to_int() << 7; + P2GTCandidate gtObj(0, + reco::ParticleState::PolarLorentzVector(scales_.to_pT(obj.ptWord().V.to_int()), + scales_.to_eta(obj.glbEtaWord().V.to_int()), + scales_.to_phi(obj.glbPhiWord().V.to_int()), + 0), + reco::ParticleState::Point(0, 0, scales_.to_z0(hwZ0))); + gtObj.hwPT_ = obj.ptWord().V.to_int(); + gtObj.hwPhi_ = obj.glbPhiWord().V.to_int(); + gtObj.hwEta_ = obj.glbEtaWord().V.to_int(); + gtObj.hwZ0_ = hwZ0; + gtObj.hwNumber_of_tracks_ = obj.ntWord().V.to_int(); + gtObj.objectType_ = P2GTCandidate::GTTDisplacedJets; + + outputCollection->push_back(gtObj); + } + event.put(std::move(outputCollection), "GTTDisplacedJets"); + } + + void L1GTProducer::produceGMTSaPromptMuons(edm::Event &event) const { + std::unique_ptr outputCollection = std::make_unique(); + const SAMuonCollection &collection = event.get(gmtSaPromptMuonToken_); + for (size_t i = 0; i < collection.size() && i < 12; i++) { + const SAMuon &obj = collection[i]; + int hwZ0 = obj.apZ0().to_int() << 12; + P2GTCandidate gtObj(scales_.to_chg(obj.apCharge().to_int()), + reco::ParticleState::PolarLorentzVector(scales_.to_pT(obj.apPt().to_int()), + scales_.to_eta(obj.apEta().to_int()), + scales_.to_phi(obj.apPhi().to_int()), + 0), + reco::ParticleState::Point(0, 0, scales_.to_z0(hwZ0))); + gtObj.hwPT_ = obj.apPt().to_int(); + gtObj.hwPhi_ = obj.apPhi().to_int(); + gtObj.hwEta_ = obj.apEta().to_int(); + gtObj.hwZ0_ = hwZ0; + gtObj.hwQual_ = obj.apQual().to_int(); + gtObj.hwCharge_ = obj.apCharge().to_int(); + gtObj.hwD0_ = obj.apD0().to_int(); + gtObj.objectType_ = P2GTCandidate::GMTSaPromptMuons; + + outputCollection->push_back(gtObj); + } + event.put(std::move(outputCollection), "GMTSaPromptMuons"); + } + + void L1GTProducer::produceGMTSaDisplacedMuons(edm::Event &event) const { + std::unique_ptr outputCollection = std::make_unique(); + const SAMuonCollection &collection = event.get(gmtSaDisplacedMuonToken_); + for (size_t i = 0; i < collection.size() && i < 12; i++) { + const SAMuon &obj = collection[i]; + int hwZ0 = obj.apZ0().to_int() << 12; + P2GTCandidate gtObj(scales_.to_chg(obj.apCharge().to_int()), + reco::ParticleState::PolarLorentzVector(scales_.to_pT(obj.apPt().to_int()), + scales_.to_eta(obj.apEta().to_int()), + scales_.to_phi(obj.apPhi().to_int()), + 0), + reco::ParticleState::Point(0, 0, scales_.to_z0(hwZ0))); + gtObj.hwPT_ = obj.apPt().to_int(); + gtObj.hwPhi_ = obj.apPhi().to_int(); + gtObj.hwEta_ = obj.apEta().to_int(); + gtObj.hwZ0_ = hwZ0; + gtObj.hwQual_ = obj.apQual().to_int(); + gtObj.hwCharge_ = obj.apCharge().to_int(); + gtObj.hwD0_ = obj.apD0().to_int(); + gtObj.objectType_ = P2GTCandidate::GMTSaDisplacedMuons; + + outputCollection->push_back(gtObj); + } + event.put(std::move(outputCollection), "GMTSaDisplacedMuons"); + } + + void L1GTProducer::produceGMTTkMuons(edm::Event &event) const { + std::unique_ptr outputCollection = std::make_unique(); + const TrackerMuonCollection &collection = event.get(gmtTkMuonToken_); + for (size_t i = 0; i < collection.size() && i < 12; i++) { + const TrackerMuon &obj = collection[i]; + int hwZ0 = obj.apZ0().to_int() << 7; + P2GTCandidate gtObj(scales_.to_chg(obj.apCharge().to_int()), + reco::ParticleState::PolarLorentzVector(scales_.to_pT(obj.apPt().to_int()), + scales_.to_eta(obj.apEta().to_int()), + scales_.to_phi(obj.apPhi().to_int()), + 0), + reco::ParticleState::Point(0, 0, scales_.to_z0(hwZ0))); + gtObj.hwPT_ = obj.apPt().to_int(); + gtObj.hwPhi_ = obj.apPhi().to_int(); + gtObj.hwEta_ = obj.apEta().to_int(); + gtObj.hwZ0_ = hwZ0; + gtObj.hwIso_ = obj.apIso().to_int(); + gtObj.hwQual_ = obj.apQual().to_int(); + gtObj.hwCharge_ = obj.apCharge().to_int(); + gtObj.hwD0_ = obj.apD0().to_int(); + gtObj.hwBeta_ = obj.apBeta().to_int(); + gtObj.objectType_ = P2GTCandidate::GMTTkMuons; + + outputCollection->push_back(gtObj); + } + event.put(std::move(outputCollection), "GMTTkMuons"); + } + + void L1GTProducer::produceCL2Jets(edm::Event &event) const { + std::unique_ptr outputCollection = std::make_unique(); + const PFJetCollection &collection = event.get(cl2JetToken_); + for (size_t i = 0; i < collection.size() && i < 12; i++) { + l1gt::Jet gtJet = l1gt::Jet::unpack(collection[i].getHWJetGT()); + int hwZ0 = gtJet.z0.V.to_int() << 7; + P2GTCandidate gtObj(0, + reco::ParticleState::PolarLorentzVector(scales_.to_pT(gtJet.v3.pt.V.to_int()), + scales_.to_eta(gtJet.v3.eta.V.to_int()), + scales_.to_phi(gtJet.v3.phi.V.to_int()), + 0), + reco::ParticleState::Point(0, 0, scales_.to_z0(hwZ0))); + gtObj.hwPT_ = gtJet.v3.pt.V.to_int(); + gtObj.hwPhi_ = gtJet.v3.phi.V.to_int(); + gtObj.hwEta_ = gtJet.v3.eta.V.to_int(); + gtObj.hwZ0_ = hwZ0; + gtObj.objectType_ = P2GTCandidate::CL2Jets; + + outputCollection->push_back(gtObj); + } + event.put(std::move(outputCollection), "CL2Jets"); + } + + void L1GTProducer::produceCL2Photons(edm::Event &event) const { + std::unique_ptr outputCollection = std::make_unique(); + const TkEmCollection &collection = event.get(cl2PhotonToken_); + for (size_t i = 0; i < collection.size() && i < 12; i++) { + l1gt::Photon gtPhoton = l1gt::Photon::unpack_ap(const_cast(collection[i]).egBinaryWord<96>()); + P2GTCandidate gtObj(0, + reco::ParticleState::PolarLorentzVector(scales_.to_pT(gtPhoton.v3.pt.V.to_int()), + scales_.to_eta(gtPhoton.v3.eta.V.to_int()), + scales_.to_phi(gtPhoton.v3.phi.V.to_int()), + 0)); + gtObj.hwPT_ = gtPhoton.v3.pt.V.to_int(); + gtObj.hwPhi_ = gtPhoton.v3.phi.V.to_int(); + gtObj.hwEta_ = gtPhoton.v3.eta.V.to_int(); + gtObj.hwIso_ = gtPhoton.isolation.V.to_int(); + gtObj.hwQual_ = gtPhoton.quality.V.to_int(); + gtObj.objectType_ = P2GTCandidate::CL2Photons; + + outputCollection->push_back(gtObj); + } + event.put(std::move(outputCollection), "CL2Photons"); + } + + void L1GTProducer::produceCL2Electrons(edm::Event &event) const { + std::unique_ptr outputCollection = std::make_unique(); + const TkElectronCollection &collection = event.get(cl2ElectronToken_); + for (size_t i = 0; i < collection.size() && i < 12; i++) { + l1gt::Electron gtElectron = l1gt::Electron::unpack_ap(const_cast(collection[i]).egBinaryWord<96>()); + int hwZ0 = gtElectron.z0.V.to_int() << 7; + P2GTCandidate gtObj(scales_.to_chg(gtElectron.charge.V.to_int()), + reco::ParticleState::PolarLorentzVector(scales_.to_pT(gtElectron.v3.pt.V.to_int()), + scales_.to_eta(gtElectron.v3.eta.V.to_int()), + scales_.to_phi(gtElectron.v3.phi.V.to_int()), + 0), + reco::ParticleState::Point(0, 0, scales_.to_z0(hwZ0))); + gtObj.hwPT_ = gtElectron.v3.pt.V.to_int(); + gtObj.hwPhi_ = gtElectron.v3.phi.V.to_int(); + gtObj.hwEta_ = gtElectron.v3.eta.V.to_int(); + gtObj.hwZ0_ = hwZ0; + gtObj.hwIso_ = gtElectron.isolation.V.to_int(); + gtObj.hwQual_ = gtElectron.quality.V.to_int(); + gtObj.hwCharge_ = gtElectron.charge.V.to_int(); + gtObj.objectType_ = P2GTCandidate::CL2Electrons; + + outputCollection->push_back(gtObj); + } + event.put(std::move(outputCollection), "CL2Electrons"); + } + + void L1GTProducer::produceCL2Taus(edm::Event &event) const { + std::unique_ptr outputCollection = std::make_unique(); + const PFTauCollection &collection = event.get(cl2TauToken_); + for (size_t i = 0; i < collection.size() && i < 12; i++) { + l1gt::Tau gtTau = collection[i].getHWTauGT(); + P2GTCandidate gtObj(scales_.to_chg(gtTau.charge.V.to_int()), + reco::ParticleState::PolarLorentzVector(scales_.to_pT(gtTau.v3.pt.V.to_int()), + scales_.to_eta(gtTau.v3.eta.V.to_int()), + scales_.to_phi(gtTau.v3.phi.V.to_int()), + 0)); + gtObj.hwPT_ = gtTau.v3.pt.V.to_int(); + gtObj.hwPhi_ = gtTau.v3.phi.V.to_int(); + gtObj.hwEta_ = gtTau.v3.eta.V.to_int(); + gtObj.hwSeed_pT_ = gtTau.seed_pt.V.to_int(); + gtObj.hwSeed_z0_ = gtTau.seed_z0.V.to_int(); + gtObj.hwCharge_ = gtTau.charge.V.to_int(); + gtObj.hwType_ = gtTau.type.V.to_int(); + gtObj.hwIso_ = gtTau.isolation.V.to_int(); + gtObj.objectType_ = P2GTCandidate::CL2Taus; + + outputCollection->push_back(gtObj); + } + event.put(std::move(outputCollection), "CL2Taus"); + } + + void L1GTProducer::produceCL2EtSum(edm::Event &event) const { + std::unique_ptr outputCollection = std::make_unique(); + const std::vector &collection = event.get(cl2EtSumToken_); + const EtSum &met = collection[0]; + + l1gt::Sum sum{true /* valid */, met.pt(), met.phi() / l1gt::Scales::ETAPHI_LSB, 0 /* scalar sum */}; + + P2GTCandidate gtObj(0, + reco::ParticleState::PolarLorentzVector( + scales_.to_pT(sum.vector_pt.V.to_int()), 0, scales_.to_phi(sum.vector_phi.V.to_int()), 0)); + gtObj.hwPT_ = sum.vector_pt.V.to_int(); + gtObj.hwPhi_ = sum.vector_phi.V.to_int(); + gtObj.hwSca_sum_ = sum.scalar_pt.V.to_int(); + gtObj.objectType_ = P2GTCandidate::CL2EtSum; + + outputCollection->push_back(gtObj); + event.put(std::move(outputCollection), "CL2EtSum"); + } + + void L1GTProducer::produceCl2HtSum(edm::Event &event) const { + std::unique_ptr outputCollection = std::make_unique(); + const std::vector &collection = event.get(cl2HtSumToken_); + const EtSum &ht = collection[0]; + const EtSum &mht = collection[1]; + + P2GTCandidate gtObj( + 0, reco::ParticleState::PolarLorentzVector(scales_.to_pT(mht.hwPt()), 0, scales_.to_phi(mht.hwPhi()), 0)); + gtObj.hwPT_ = mht.hwPt(); + gtObj.hwPhi_ = mht.hwPhi(); + gtObj.hwSca_sum_ = ht.hwPt(); + gtObj.objectType_ = P2GTCandidate::CL2HtSum; + + outputCollection->push_back(gtObj); + event.put(std::move(outputCollection), "CL2HtSum"); + } + + void L1GTProducer::produce(edm::StreamID, edm::Event &event, const edm::EventSetup &setup) const { + produceGTTPromptJets(event); + produceGTTDisplacedJets(event); + produceGTTPrimaryVert(event); + + produceGMTSaPromptMuons(event); + produceGMTSaDisplacedMuons(event); + produceGMTTkMuons(event); + + produceCL2Jets(event); + produceCL2Photons(event); + produceCL2Electrons(event); + produceCL2Taus(event); + produceCL2EtSum(event); + produceCl2HtSum(event); + } +} // namespace l1t + +using namespace l1t; + +DEFINE_FWK_MODULE(L1GTProducer); diff --git a/L1Trigger/Phase2L1GT/plugins/L1GTQuadObjectCond.cc b/L1Trigger/Phase2L1GT/plugins/L1GTQuadObjectCond.cc new file mode 100644 index 0000000000000..994507dac101b --- /dev/null +++ b/L1Trigger/Phase2L1GT/plugins/L1GTQuadObjectCond.cc @@ -0,0 +1,304 @@ +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/global/EDFilter.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/L1Trigger/interface/P2GTCandidate.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" + +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "DataFormats/Common/interface/Handle.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "DataFormats/Common/interface/Ref.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "L1Trigger/Phase2L1GT/interface/L1GTScales.h" +#include "L1GTSingleCollectionCut.h" +#include "L1GTDeltaCut.h" +#include "L1GTSingleInOutLUT.h" + +#include +#include +#include +#include + +#include + +using namespace l1t; + +class L1GTQuadObjectCond : public edm::global::EDFilter<> { +public: + explicit L1GTQuadObjectCond(const edm::ParameterSet&); + ~L1GTQuadObjectCond() override = default; + + static void fillDescriptions(edm::ConfigurationDescriptions&); + +private: + bool filter(edm::StreamID, edm::Event&, edm::EventSetup const&) const override; + + const L1GTScales scales_; + + const L1GTSingleCollectionCut collection1Cuts_; + const L1GTSingleCollectionCut collection2Cuts_; + const L1GTSingleCollectionCut collection3Cuts_; + const L1GTSingleCollectionCut collection4Cuts_; + + const bool enable_sanity_checks_; + const bool inv_mass_checks_; + + const L1GTDeltaCut delta12Cuts_; + const L1GTDeltaCut delta13Cuts_; + const L1GTDeltaCut delta23Cuts_; + const L1GTDeltaCut delta14Cuts_; + const L1GTDeltaCut delta24Cuts_; + const L1GTDeltaCut delta34Cuts_; + + const edm::EDGetTokenT token1_; + const edm::EDGetTokenT token2_; + const edm::EDGetTokenT token3_; + const edm::EDGetTokenT token4_; +}; + +L1GTQuadObjectCond::L1GTQuadObjectCond(const edm::ParameterSet& config) + : scales_(config.getParameter("scales")), + collection1Cuts_(config.getParameter("collection1"), config, scales_), + collection2Cuts_(config.getParameter("collection2"), config, scales_), + collection3Cuts_(config.getParameter("collection3"), config, scales_), + collection4Cuts_(config.getParameter("collection4"), config, scales_), + enable_sanity_checks_(config.getUntrackedParameter("sanity_checks")), + inv_mass_checks_(config.getUntrackedParameter("inv_mass_checks")), + delta12Cuts_( + config.getParameter("delta12"), config, scales_, enable_sanity_checks_, inv_mass_checks_), + delta13Cuts_( + config.getParameter("delta13"), config, scales_, enable_sanity_checks_, inv_mass_checks_), + delta23Cuts_( + config.getParameter("delta23"), config, scales_, enable_sanity_checks_, inv_mass_checks_), + delta14Cuts_( + config.getParameter("delta14"), config, scales_, enable_sanity_checks_, inv_mass_checks_), + delta24Cuts_( + config.getParameter("delta24"), config, scales_, enable_sanity_checks_, inv_mass_checks_), + delta34Cuts_( + config.getParameter("delta34"), config, scales_, enable_sanity_checks_, inv_mass_checks_), + token1_(consumes(collection1Cuts_.tag())), + token2_(collection1Cuts_.tag() == collection2Cuts_.tag() + ? token1_ + : consumes(collection2Cuts_.tag())), + token3_(collection1Cuts_.tag() == collection3Cuts_.tag() + ? token1_ + : (collection2Cuts_.tag() == collection3Cuts_.tag() + ? token2_ + : consumes(collection3Cuts_.tag()))), + token4_(collection1Cuts_.tag() == collection4Cuts_.tag() + ? token1_ + : (collection2Cuts_.tag() == collection4Cuts_.tag() + ? token2_ + : (collection3Cuts_.tag() == collection4Cuts_.tag() + ? token3_ + : consumes(collection4Cuts_.tag())))) { + produces(collection1Cuts_.tag().instance()); + + if (!(collection1Cuts_.tag() == collection2Cuts_.tag())) { + produces(collection2Cuts_.tag().instance()); + } + + if (!(collection1Cuts_.tag() == collection3Cuts_.tag()) && !(collection2Cuts_.tag() == collection3Cuts_.tag())) { + produces(collection3Cuts_.tag().instance()); + } + + if (!(collection1Cuts_.tag() == collection4Cuts_.tag()) && !(collection2Cuts_.tag() == collection4Cuts_.tag()) && + !(collection3Cuts_.tag() == collection4Cuts_.tag())) { + produces(collection4Cuts_.tag().instance()); + } + + if (inv_mass_checks_) { + produces(); + } +} + +void L1GTQuadObjectCond::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + + edm::ParameterSetDescription collection1Desc; + L1GTSingleCollectionCut::fillPSetDescription(collection1Desc); + desc.add("collection1", collection1Desc); + + edm::ParameterSetDescription collection2Desc; + L1GTSingleCollectionCut::fillPSetDescription(collection2Desc); + desc.add("collection2", collection2Desc); + + edm::ParameterSetDescription collection3Desc; + L1GTSingleCollectionCut::fillPSetDescription(collection3Desc); + desc.add("collection3", collection3Desc); + + edm::ParameterSetDescription collection4Desc; + L1GTSingleCollectionCut::fillPSetDescription(collection4Desc); + desc.add("collection4", collection4Desc); + + edm::ParameterSetDescription scalesDesc; + L1GTScales::fillPSetDescription(scalesDesc); + desc.add("scales", scalesDesc); + + desc.addUntracked("sanity_checks", false); + desc.addUntracked("inv_mass_checks", false); + + edm::ParameterSetDescription delta12Desc; + L1GTDeltaCut::fillPSetDescription(delta12Desc); + desc.add("delta12", delta12Desc); + + edm::ParameterSetDescription delta13Desc; + L1GTDeltaCut::fillPSetDescription(delta13Desc); + desc.add("delta13", delta13Desc); + + edm::ParameterSetDescription delta23Desc; + L1GTDeltaCut::fillPSetDescription(delta23Desc); + desc.add("delta23", delta23Desc); + + edm::ParameterSetDescription delta14Desc; + L1GTDeltaCut::fillPSetDescription(delta14Desc); + desc.add("delta14", delta14Desc); + + edm::ParameterSetDescription delta24Desc; + L1GTDeltaCut::fillPSetDescription(delta24Desc); + desc.add("delta24", delta24Desc); + + edm::ParameterSetDescription delta34Desc; + L1GTDeltaCut::fillPSetDescription(delta34Desc); + desc.add("delta34", delta34Desc); + + L1GTDeltaCut::fillLUTDescriptions(desc); + + descriptions.addWithDefaultLabel(desc); +} + +bool L1GTQuadObjectCond::filter(edm::StreamID, edm::Event& event, const edm::EventSetup& setup) const { + edm::Handle col1 = event.getHandle(token1_); + edm::Handle col2 = event.getHandle(token2_); + edm::Handle col3 = event.getHandle(token3_); + edm::Handle col4 = event.getHandle(token4_); + + bool condition_result = false; + + std::set triggeredIdcs1; + std::set triggeredIdcs2; + std::set triggeredIdcs3; + std::set triggeredIdcs4; + + InvariantMassErrorCollection massErrors; + + for (std::size_t idx1 = 0; idx1 < col1->size(); ++idx1) { + for (std::size_t idx2 = 0; idx2 < col2->size(); ++idx2) { + for (std::size_t idx3 = 0; idx3 < col3->size(); ++idx3) { + for (std::size_t idx4 = 0; idx4 < col4->size(); ++idx4) { + // If we're looking at the same collection then we shouldn't use the same object in one comparison. + if (col1.product() == col2.product() && idx1 == idx2) { + continue; + } + + if (col2.product() == col3.product() && idx2 == idx3) { + continue; + } + + if (col1.product() == col3.product() && idx1 == idx3) { + continue; + } + + if (col1.product() == col4.product() && idx1 == idx4) { + continue; + } + + if (col2.product() == col4.product() && idx2 == idx4) { + continue; + } + + if (col3.product() == col4.product() && idx3 == idx4) { + continue; + } + + bool pass = true; + pass &= collection1Cuts_.checkObject(col1->at(idx1)); + pass &= collection2Cuts_.checkObject(col2->at(idx2)); + pass &= collection3Cuts_.checkObject(col3->at(idx3)); + pass &= collection4Cuts_.checkObject(col4->at(idx4)); + pass &= delta12Cuts_.checkObjects(col1->at(idx1), col2->at(idx2), massErrors); + pass &= delta13Cuts_.checkObjects(col1->at(idx1), col3->at(idx3), massErrors); + pass &= delta23Cuts_.checkObjects(col2->at(idx2), col3->at(idx3), massErrors); + pass &= delta14Cuts_.checkObjects(col1->at(idx1), col4->at(idx4), massErrors); + pass &= delta24Cuts_.checkObjects(col2->at(idx2), col4->at(idx4), massErrors); + pass &= delta34Cuts_.checkObjects(col3->at(idx3), col4->at(idx4), massErrors); + condition_result |= pass; + + if (pass) { + triggeredIdcs1.emplace(idx1); + + if (col1.product() != col2.product()) { + triggeredIdcs2.emplace(idx2); + } else { + triggeredIdcs1.emplace(idx2); + } + + if (col1.product() != col3.product() && col2.product() != col3.product()) { + triggeredIdcs3.emplace(idx3); + } else if (col1.product() == col3.product()) { + triggeredIdcs1.emplace(idx3); + } else { + triggeredIdcs2.emplace(idx3); + } + + if (col1.product() != col4.product() && col2.product() != col4.product() && + col3.product() != col4.product()) { + triggeredIdcs4.emplace(idx4); + } else if (col1.product() == col4.product()) { + triggeredIdcs1.emplace(idx4); + } else if (col2.product() == col4.product()) { + triggeredIdcs2.emplace(idx4); + } else { + triggeredIdcs3.emplace(idx4); + } + } + } + } + } + } + + if (condition_result) { + std::unique_ptr triggerCol1 = std::make_unique(); + + for (std::size_t idx : triggeredIdcs1) { + triggerCol1->push_back(P2GTCandidateRef(col1, idx)); + } + event.put(std::move(triggerCol1), collection1Cuts_.tag().instance()); + + if (col1.product() != col2.product()) { + std::unique_ptr triggerCol2 = std::make_unique(); + + for (std::size_t idx : triggeredIdcs2) { + triggerCol2->push_back(P2GTCandidateRef(col2, idx)); + } + event.put(std::move(triggerCol2), collection2Cuts_.tag().instance()); + } + + if (col1.product() != col3.product() && col2.product() != col3.product()) { + std::unique_ptr triggerCol3 = std::make_unique(); + + for (std::size_t idx : triggeredIdcs3) { + triggerCol3->push_back(P2GTCandidateRef(col3, idx)); + } + event.put(std::move(triggerCol3), collection3Cuts_.tag().instance()); + } + + if (col1.product() != col4.product() && col2.product() != col4.product() && col3.product() != col4.product()) { + std::unique_ptr triggerCol4 = std::make_unique(); + + for (std::size_t idx : triggeredIdcs4) { + triggerCol4->push_back(P2GTCandidateRef(col4, idx)); + } + event.put(std::move(triggerCol4), collection4Cuts_.tag().instance()); + } + } + + if (inv_mass_checks_) { + event.put(std::make_unique(std::move(massErrors)), ""); + } + + return condition_result; +} + +DEFINE_FWK_MODULE(L1GTQuadObjectCond); diff --git a/L1Trigger/Phase2L1GT/plugins/L1GTSingleCollectionCut.h b/L1Trigger/Phase2L1GT/plugins/L1GTSingleCollectionCut.h new file mode 100644 index 0000000000000..04663436434c1 --- /dev/null +++ b/L1Trigger/Phase2L1GT/plugins/L1GTSingleCollectionCut.h @@ -0,0 +1,178 @@ +#ifndef L1Trigger_Phase2L1GT_L1GTSingleCollectionCut_h +#define L1Trigger_Phase2L1GT_L1GTSingleCollectionCut_h + +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/L1Trigger/interface/P2GTCandidate.h" + +#include "L1Trigger/Phase2L1GT/interface/L1GTScales.h" + +#include "L1GTOptionalParam.h" + +#include +#include + +namespace l1t { + + template + inline std::vector getParamVector(const std::string& name, + const edm::ParameterSet& config, + std::function conv) { + const std::vector& values = config.getParameter>(name); + std::vector convertedValues(values.size()); + for (std::size_t i = 0; i < values.size(); i++) { + convertedValues[i] = conv(values[i]); + } + return convertedValues; + } + + class L1GTSingleCollectionCut { + public: + L1GTSingleCollectionCut(const edm::ParameterSet& config, + const edm::ParameterSet& lutConfig, + const L1GTScales& scales) + : scales_(scales), + tag_(config.getParameter("tag")), + minPt_(getOptionalParam( + "minPt", config, [&scales](double value) { return scales.to_hw_pT(value); })), + maxPt_(getOptionalParam( + "maxPt", config, [&scales](double value) { return scales.to_hw_pT(value); })), + minEta_(getOptionalParam( + "minEta", config, [&scales](double value) { return scales.to_hw_eta(value); })), + maxEta_(getOptionalParam( + "maxEta", config, [&scales](double value) { return scales.to_hw_eta(value); })), + minPhi_(getOptionalParam( + "minPhi", config, [&scales](double value) { return scales.to_hw_phi(value); })), + maxPhi_(getOptionalParam( + "maxPhi", config, [&scales](double value) { return scales.to_hw_phi(value); })), + minZ0_(getOptionalParam( + "minZ0", config, [&scales](double value) { return scales.to_hw_z0(value); })), + maxZ0_(getOptionalParam( + "maxZ0", config, [&scales](double value) { return scales.to_hw_z0(value); })), + minScalarSumPt_(getOptionalParam( + "minScalarSumPt", config, [&scales](double value) { return scales.to_hw_pT(value); })), + maxScalarSumPt_(getOptionalParam( + "maxScalarSumPt", config, [&scales](double value) { return scales.to_hw_pT(value); })), + qual_(config.getParameter>("qual")), + minAbsEta_(getOptionalParam( + "minAbsEta", config, [&scales](double value) { return scales.to_hw_eta(value); })), + maxAbsEta_(getOptionalParam( + "maxAbsEta", config, [&scales](double value) { return scales.to_hw_eta(value); })), + maxIso_(getOptionalParam( + "maxIso", config, [&scales](double value) { return scales.to_hw_isolation(value); })), + minHwIso_(getOptionalParam("minHwIso", config)), + regionsAbsEtaLowerBounds_(getParamVector( + "regionsAbsEtaLowerBounds", config, [&scales](double value) { return scales.to_hw_eta(value); })), + regionsMinPt_(getParamVector( + "regionsMinPt", config, [&scales](double value) { return scales.to_hw_pT(value); })), + regionsMaxIso_(getParamVector( + "regionsMaxIso", config, [&scales](double value) { return scales.to_hw_isolation(value); })), + regionsQual_(config.getParameter>("regionsQual")) {} + + bool checkEtadependentcuts(const P2GTCandidate& obj) const { + bool res = true; + + unsigned int index; + index = atIndex(obj.hwEta()); + res &= regionsMinPt_.empty() ? true : obj.hwPT() > regionsMinPt_[index]; + res &= regionsMaxIso_.empty() + ? true + : obj.hwIso().to_int() << scales_.isolation_shift() < regionsMaxIso_[index] * obj.hwPT().to_int(); + res &= regionsQual_.empty() ? true : (obj.hwQual().to_uint() & regionsQual_[index]) == regionsQual_[index]; + return res; + } + + unsigned int atIndex(int objeta) const { + // Function that checks at which index the eta of the object is + // If object abs(eta) < regionsAbsEtaLowerBounds_[0] the function returns the last index, + // Might be undesired behaviour + for (unsigned int i = 0; i < regionsAbsEtaLowerBounds_.size() - 1; i++) { + if (std::abs(objeta) >= regionsAbsEtaLowerBounds_[i] && std::abs(objeta) < regionsAbsEtaLowerBounds_[i + 1]) { + return i; + } + } + return regionsAbsEtaLowerBounds_.size() - 1; + } + + bool checkObject(const P2GTCandidate& obj) const { + bool result = true; + + result &= minPt_ ? (obj.hwPT() > minPt_) : true; + result &= maxPt_ ? (obj.hwPT() < maxPt_) : true; + + result &= minEta_ ? (obj.hwEta() > minEta_) : true; + result &= maxEta_ ? (obj.hwEta() < maxEta_) : true; + + result &= minPhi_ ? (obj.hwPhi() > minPhi_) : true; + result &= maxPhi_ ? (obj.hwPhi() < maxPhi_) : true; + + result &= minZ0_ ? (obj.hwZ0() > minZ0_) : true; + result &= maxZ0_ ? (obj.hwZ0() < maxZ0_) : true; + + result &= minAbsEta_ ? (abs(obj.hwEta()) > minAbsEta_) : true; + result &= maxAbsEta_ ? (abs(obj.hwEta()) < maxAbsEta_) : true; + + result &= minScalarSumPt_ ? (obj.hwSca_sum() > minScalarSumPt_) : true; + result &= maxScalarSumPt_ ? (obj.hwSca_sum() < minScalarSumPt_) : true; + + result &= qual_.empty() ? true : std::find(qual_.begin(), qual_.end(), obj.hwQual().to_uint()) != qual_.end(); + result &= + maxIso_ ? obj.hwIso().to_int() << scales_.isolation_shift() < maxIso_.value() * obj.hwPT().to_int() : true; + + result &= minHwIso_ ? (obj.hwIso() > minHwIso_) : true; + result &= regionsAbsEtaLowerBounds_.empty() ? true : checkEtadependentcuts(obj); + return result; + } + + static void fillPSetDescription(edm::ParameterSetDescription& desc) { + desc.add("tag"); + desc.addOptional("minPt"); + desc.addOptional("maxPt"); + desc.addOptional("minEta"); + desc.addOptional("maxEta"); + desc.addOptional("minPhi"); + desc.addOptional("maxPhi"); + desc.addOptional("minZ0"); + desc.addOptional("maxZ0"); + desc.addOptional("minScalarSumPt"); + desc.addOptional("maxScalarSumPt"); + desc.add>("qual", {}); + desc.addOptional("minAbsEta"); + desc.addOptional("maxAbsEta"); + desc.addOptional("maxIso"); + desc.addOptional("minHwIso"); + desc.add>("regionsAbsEtaLowerBounds", {}); + desc.add>("regionsMinPt", {}); + desc.add>("regionsMaxIso", {}); + desc.add>("regionsQual", {}); + } + + const edm::InputTag& tag() const { return tag_; } + + private: + const L1GTScales scales_; + const edm::InputTag tag_; + const std::optional minPt_; + const std::optional maxPt_; + const std::optional minEta_; + const std::optional maxEta_; + const std::optional minPhi_; + const std::optional maxPhi_; + const std::optional minZ0_; + const std::optional maxZ0_; + const std::optional minScalarSumPt_; + const std::optional maxScalarSumPt_; + const std::vector qual_; + const std::optional minAbsEta_; + const std::optional maxAbsEta_; + const std::optional maxIso_; + const std::optional minHwIso_; + const std::vector regionsAbsEtaLowerBounds_; + const std::vector regionsMinPt_; + const std::vector regionsMaxIso_; + const std::vector regionsQual_; + }; + +} // namespace l1t + +#endif // L1Trigger_Phase2L1GT_L1GTSingleCollectionCut_h diff --git a/L1Trigger/Phase2L1GT/plugins/L1GTSingleInOutLUT.h b/L1Trigger/Phase2L1GT/plugins/L1GTSingleInOutLUT.h new file mode 100644 index 0000000000000..e972e736f17cb --- /dev/null +++ b/L1Trigger/Phase2L1GT/plugins/L1GTSingleInOutLUT.h @@ -0,0 +1,41 @@ +#ifndef L1Trigger_Phase2L1GT_L1GTSingleInOutLUT_h +#define L1Trigger_Phase2L1GT_L1GTSingleInOutLUT_h + +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +#include +#include +#include + +namespace l1t { + + class L1GTSingleInOutLUT { + public: + L1GTSingleInOutLUT(const edm::ParameterSet& lutConfig) + : data_(lutConfig.getParameter>("lut")), + unused_lsbs_(lutConfig.getParameter("unused_lsbs")), + output_scale_(lutConfig.getParameter("output_scale_factor")), + // I guess ceil is required due to small differences in C++ and python's cos/cosh implementation. + hwMax_error_(std::ceil(lutConfig.getParameter("max_error") * output_scale_)) {} + + int32_t operator[](uint32_t i) const { return data_[(i >> unused_lsbs_) % data_.size()]; } + double hwMax_error() const { return hwMax_error_; } + double output_scale() const { return output_scale_; } + + static void fillLUTDescriptions(edm::ParameterSetDescription& desc) { + desc.add>("lut"); + desc.add("output_scale_factor"); + desc.add("unused_lsbs"); + desc.add("max_error"); + } + + private: + const std::vector data_; + const uint32_t unused_lsbs_; + const double output_scale_; + const double hwMax_error_; // Sanity check + }; +} // namespace l1t + +#endif // L1Trigger_Phase2L1GT_L1GTSingleInOutLUT_h \ No newline at end of file diff --git a/L1Trigger/Phase2L1GT/plugins/L1GTSingleObjectCond.cc b/L1Trigger/Phase2L1GT/plugins/L1GTSingleObjectCond.cc new file mode 100644 index 0000000000000..a89c6af56e65c --- /dev/null +++ b/L1Trigger/Phase2L1GT/plugins/L1GTSingleObjectCond.cc @@ -0,0 +1,80 @@ +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/global/EDFilter.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/L1Trigger/interface/P2GTCandidate.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" + +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "DataFormats/Common/interface/Handle.h" +#include "FWCore/Utilities/interface/EDGetToken.h" +#include "DataFormats/Common/interface/Ref.h" + +#include "L1Trigger/Phase2L1GT/interface/L1GTScales.h" +#include "L1GTSingleCollectionCut.h" + +#include +#include + +#include + +using namespace l1t; + +class L1GTSingleObjectCond : public edm::global::EDFilter<> { +public: + explicit L1GTSingleObjectCond(const edm::ParameterSet&); + ~L1GTSingleObjectCond() override = default; + + static void fillDescriptions(edm::ConfigurationDescriptions&); + +private: + bool filter(edm::StreamID, edm::Event&, edm::EventSetup const&) const override; + + const L1GTScales scales_; + const L1GTSingleCollectionCut collection; + + const edm::EDGetTokenT token_; +}; + +L1GTSingleObjectCond::L1GTSingleObjectCond(const edm::ParameterSet& config) + : scales_(config.getParameter("scales")), + collection(config, config, scales_), + token_(consumes(collection.tag())) { + produces(collection.tag().instance()); +} + +void L1GTSingleObjectCond::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + L1GTSingleCollectionCut::fillPSetDescription(desc); + + edm::ParameterSetDescription scalesDesc; + L1GTScales::fillPSetDescription(scalesDesc); + desc.add("scales", scalesDesc); + + descriptions.addWithDefaultLabel(desc); +} + +bool L1GTSingleObjectCond::filter(edm::StreamID, edm::Event& event, const edm::EventSetup& setup) const { + edm::Handle col = event.getHandle(token_); + + bool condition_result = false; + + std::unique_ptr triggerCol = std::make_unique(); + + for (std::size_t idx = 0; idx < col->size(); ++idx) { + bool pass{collection.checkObject(col->at(idx))}; + condition_result |= pass; + + if (pass) { + triggerCol->push_back(P2GTCandidateRef(col, idx)); + } + } + + if (condition_result) { + event.put(std::move(triggerCol), collection.tag().instance()); + } + + return condition_result; +} + +DEFINE_FWK_MODULE(L1GTSingleObjectCond); diff --git a/L1Trigger/Phase2L1GT/plugins/L1GTTripleObjectCond.cc b/L1Trigger/Phase2L1GT/plugins/L1GTTripleObjectCond.cc new file mode 100644 index 0000000000000..1e36748272e42 --- /dev/null +++ b/L1Trigger/Phase2L1GT/plugins/L1GTTripleObjectCond.cc @@ -0,0 +1,223 @@ +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/global/EDFilter.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "DataFormats/L1Trigger/interface/P2GTCandidate.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" + +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "DataFormats/Common/interface/Handle.h" +#include "DataFormats/Common/interface/Ref.h" +#include "FWCore/Utilities/interface/EDGetToken.h" + +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "L1Trigger/Phase2L1GT/interface/L1GTScales.h" +#include "L1GTSingleCollectionCut.h" +#include "L1GTDeltaCut.h" +#include "L1GTSingleInOutLUT.h" + +#include + +#include + +using namespace l1t; + +class L1GTTripleObjectCond : public edm::global::EDFilter<> { +public: + explicit L1GTTripleObjectCond(const edm::ParameterSet&); + ~L1GTTripleObjectCond() override = default; + + static void fillDescriptions(edm::ConfigurationDescriptions&); + +private: + bool filter(edm::StreamID, edm::Event&, edm::EventSetup const&) const override; + + const L1GTScales scales_; + + const L1GTSingleCollectionCut collection1Cuts_; + const L1GTSingleCollectionCut collection2Cuts_; + const L1GTSingleCollectionCut collection3Cuts_; + + const bool enable_sanity_checks_; + const bool inv_mass_checks_; + + const L1GTDeltaCut delta12Cuts_; + const L1GTDeltaCut delta13Cuts_; + const L1GTDeltaCut delta23Cuts_; + + const edm::EDGetTokenT token1_; + const edm::EDGetTokenT token2_; + const edm::EDGetTokenT token3_; +}; + +L1GTTripleObjectCond::L1GTTripleObjectCond(const edm::ParameterSet& config) + : scales_(config.getParameter("scales")), + collection1Cuts_(config.getParameter("collection1"), config, scales_), + collection2Cuts_(config.getParameter("collection2"), config, scales_), + collection3Cuts_(config.getParameter("collection3"), config, scales_), + enable_sanity_checks_(config.getUntrackedParameter("sanity_checks")), + inv_mass_checks_(config.getUntrackedParameter("inv_mass_checks")), + delta12Cuts_( + config.getParameter("delta12"), config, scales_, enable_sanity_checks_, inv_mass_checks_), + delta13Cuts_( + config.getParameter("delta13"), config, scales_, enable_sanity_checks_, inv_mass_checks_), + delta23Cuts_( + config.getParameter("delta23"), config, scales_, enable_sanity_checks_, inv_mass_checks_), + token1_(consumes(collection1Cuts_.tag())), + token2_(collection1Cuts_.tag() == collection2Cuts_.tag() + ? token1_ + : consumes(collection2Cuts_.tag())), + token3_(collection1Cuts_.tag() == collection3Cuts_.tag() + ? token1_ + : (collection2Cuts_.tag() == collection3Cuts_.tag() + ? token2_ + : consumes(collection3Cuts_.tag()))) { + produces(collection1Cuts_.tag().instance()); + + if (!(collection1Cuts_.tag() == collection2Cuts_.tag())) { + produces(collection2Cuts_.tag().instance()); + } + + if (!(collection1Cuts_.tag() == collection3Cuts_.tag()) && !(collection2Cuts_.tag() == collection3Cuts_.tag())) { + produces(collection3Cuts_.tag().instance()); + } + + if (inv_mass_checks_) { + produces(); + } +} + +void L1GTTripleObjectCond::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + + edm::ParameterSetDescription collection1Desc; + L1GTSingleCollectionCut::fillPSetDescription(collection1Desc); + desc.add("collection1", collection1Desc); + + edm::ParameterSetDescription collection2Desc; + L1GTSingleCollectionCut::fillPSetDescription(collection2Desc); + desc.add("collection2", collection2Desc); + + edm::ParameterSetDescription collection3Desc; + L1GTSingleCollectionCut::fillPSetDescription(collection3Desc); + desc.add("collection3", collection3Desc); + + edm::ParameterSetDescription scalesDesc; + L1GTScales::fillPSetDescription(scalesDesc); + desc.add("scales", scalesDesc); + + desc.addUntracked("sanity_checks", false); + desc.addUntracked("inv_mass_checks", false); + + edm::ParameterSetDescription delta12Desc; + L1GTDeltaCut::fillPSetDescription(delta12Desc); + desc.add("delta12", delta12Desc); + + edm::ParameterSetDescription delta13Desc; + L1GTDeltaCut::fillPSetDescription(delta13Desc); + desc.add("delta13", delta13Desc); + + edm::ParameterSetDescription delta23Desc; + L1GTDeltaCut::fillPSetDescription(delta23Desc); + desc.add("delta23", delta23Desc); + + L1GTDeltaCut::fillLUTDescriptions(desc); + + descriptions.addWithDefaultLabel(desc); +} + +bool L1GTTripleObjectCond::filter(edm::StreamID, edm::Event& event, const edm::EventSetup& setup) const { + edm::Handle col1 = event.getHandle(token1_); + edm::Handle col2 = event.getHandle(token2_); + edm::Handle col3 = event.getHandle(token3_); + + bool condition_result = false; + + std::set triggeredIdcs1; + std::set triggeredIdcs2; + std::set triggeredIdcs3; + + InvariantMassErrorCollection massErrors; + + for (std::size_t idx1 = 0; idx1 < col1->size(); ++idx1) { + for (std::size_t idx2 = 0; idx2 < col2->size(); ++idx2) { + for (std::size_t idx3 = 0; idx3 < col3->size(); ++idx3) { + // If we're looking at the same collection then we shouldn't use the same object in one comparison. + if (col1.product() == col2.product() && idx1 == idx2) { + continue; + } + + if (col1.product() == col3.product() && idx1 == idx3) { + continue; + } + + if (col2.product() == col3.product() && idx2 == idx3) { + continue; + } + + bool pass = true; + pass &= collection1Cuts_.checkObject(col1->at(idx1)); + pass &= collection2Cuts_.checkObject(col2->at(idx2)); + pass &= collection3Cuts_.checkObject(col3->at(idx3)); + pass &= delta12Cuts_.checkObjects(col1->at(idx1), col2->at(idx2), massErrors); + pass &= delta13Cuts_.checkObjects(col1->at(idx1), col3->at(idx3), massErrors); + pass &= delta23Cuts_.checkObjects(col2->at(idx2), col3->at(idx3), massErrors); + + condition_result |= pass; + + if (pass) { + triggeredIdcs1.emplace(idx1); + + if (col1.product() != col2.product()) { + triggeredIdcs2.emplace(idx2); + } else { + triggeredIdcs1.emplace(idx2); + } + + if (col1.product() != col3.product() && col2.product() != col3.product()) { + triggeredIdcs3.emplace(idx3); + } else if (col1.product() == col3.product()) { + triggeredIdcs1.emplace(idx3); + } else { + triggeredIdcs2.emplace(idx3); + } + } + } + } + } + + if (condition_result) { + std::unique_ptr triggerCol1 = std::make_unique(); + + for (std::size_t idx : triggeredIdcs1) { + triggerCol1->push_back(P2GTCandidateRef(col1, idx)); + } + event.put(std::move(triggerCol1), collection1Cuts_.tag().instance()); + + if (col1.product() != col2.product()) { + std::unique_ptr triggerCol2 = std::make_unique(); + + for (std::size_t idx : triggeredIdcs2) { + triggerCol2->push_back(P2GTCandidateRef(col2, idx)); + } + event.put(std::move(triggerCol2), collection2Cuts_.tag().instance()); + } + + if (col1.product() != col3.product() && col2.product() != col3.product()) { + std::unique_ptr triggerCol3 = std::make_unique(); + + for (std::size_t idx : triggeredIdcs3) { + triggerCol3->push_back(P2GTCandidateRef(col3, idx)); + } + event.put(std::move(triggerCol3), collection3Cuts_.tag().instance()); + } + } + + if (inv_mass_checks_) { + event.put(std::make_unique(std::move(massErrors)), ""); + } + + return condition_result; +} + +DEFINE_FWK_MODULE(L1GTTripleObjectCond); diff --git a/L1Trigger/Phase2L1GT/python/l1tGTAlgoBlockProducer_cff.py b/L1Trigger/Phase2L1GT/python/l1tGTAlgoBlockProducer_cff.py new file mode 100644 index 0000000000000..df8bbb732ec16 --- /dev/null +++ b/L1Trigger/Phase2L1GT/python/l1tGTAlgoBlockProducer_cff.py @@ -0,0 +1,23 @@ +import FWCore.ParameterSet.Config as cms +import re + +algorithms = cms.VPSet() + +l1tGTAlgoBlockProducer = cms.EDProducer( + "L1GTAlgoBlockProducer", + algorithms = algorithms +) + +def collectAlgorithmPaths(process) -> "tuple[cms.Path]": + str_paths = set() + for algorithm in algorithms: + algo_paths = re.sub(r'[()]'," " , algorithm.expression.value()).split() + for algo in algo_paths: + if algo in process.pathNames() : + str_paths.add(algo) + paths = set() + + for str_path in str_paths: + paths.add(getattr(process, str_path)) + + return tuple(paths) diff --git a/L1Trigger/Phase2L1GT/python/l1tGTDoubleObjectCond_cfi.py b/L1Trigger/Phase2L1GT/python/l1tGTDoubleObjectCond_cfi.py new file mode 100644 index 0000000000000..2179f23b761e3 --- /dev/null +++ b/L1Trigger/Phase2L1GT/python/l1tGTDoubleObjectCond_cfi.py @@ -0,0 +1,13 @@ +import FWCore.ParameterSet.Config as cms +from L1Trigger.Phase2L1GT.l1tGTSingleInOutLUT import COS_PHI_LUT, COSH_ETA_LUT, COSH_ETA_LUT_2 +from L1Trigger.Phase2L1GT.l1tGTScales import scale_parameter + +l1tGTDoubleObjectCond = cms.EDFilter( + "L1GTDoubleObjectCond", + scales=scale_parameter, + cosh_eta_lut=COSH_ETA_LUT.config(), + cosh_eta_lut2=COSH_ETA_LUT_2.config(), + cos_phi_lut=COS_PHI_LUT.config(), + sanity_checks=cms.untracked.bool(False), + inv_mass_checks=cms.untracked.bool(False) +) diff --git a/L1Trigger/Phase2L1GT/python/l1tGTMenu_cff.py b/L1Trigger/Phase2L1GT/python/l1tGTMenu_cff.py new file mode 100644 index 0000000000000..5838fa557a12f --- /dev/null +++ b/L1Trigger/Phase2L1GT/python/l1tGTMenu_cff.py @@ -0,0 +1,10 @@ +import FWCore.ParameterSet.Config as cms + +############################################################ +# L1 Global Trigger Menu +############################################################ + +from L1Trigger.Phase2L1GT.l1tGTMenu_lepSeeds_cff import * + +from L1Trigger.Phase2L1GT.l1tGTMenu_hadr_metSeeds_cff import * + diff --git a/L1Trigger/Phase2L1GT/python/l1tGTMenu_hadr_metSeeds_cff.py b/L1Trigger/Phase2L1GT/python/l1tGTMenu_hadr_metSeeds_cff.py new file mode 100644 index 0000000000000..a0b645aba3695 --- /dev/null +++ b/L1Trigger/Phase2L1GT/python/l1tGTMenu_hadr_metSeeds_cff.py @@ -0,0 +1,92 @@ +import FWCore.ParameterSet.Config as cms + +############################################################ +# L1 Global Trigger Emulation +############################################################ + +# Conditions + +from L1Trigger.Phase2L1GT.l1tGTProducer_cff import l1tGTProducer + +from L1Trigger.Phase2L1GT.l1tGTSingleObjectCond_cfi import l1tGTSingleObjectCond +from L1Trigger.Phase2L1GT.l1tGTDoubleObjectCond_cfi import l1tGTDoubleObjectCond +from L1Trigger.Phase2L1GT.l1tGTTripleObjectCond_cfi import l1tGTTripleObjectCond +from L1Trigger.Phase2L1GT.l1tGTQuadObjectCond_cfi import l1tGTQuadObjectCond + +from L1Trigger.Phase2L1GT.l1tGTAlgoBlockProducer_cff import algorithms + +####### JET, MET, HT ########### + +SinglePuppiJet230 = l1tGTSingleObjectCond.clone( + tag = cms.InputTag("l1tGTProducer", "CL2Jets"), + #minPt = cms.double(164.9), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.5), + regionsMinPt=cms.vdouble(160.5,108.3) +) +pSinglePuppiJet230 = cms.Path(SinglePuppiJet230) +algorithms.append(cms.PSet(expression = cms.string("pSinglePuppiJet230"))) + +PuppiHT450 = l1tGTSingleObjectCond.clone( + tag = cms.InputTag("l1tGTProducer", "CL2HtSum"), + minScalarSumPt = cms.double(372.9) +) +pPuppiHT450 = cms.Path(PuppiHT450) +algorithms.append(cms.PSet(expression = cms.string("pPuppiHT450"))) + + +PuppiMET200 = l1tGTSingleObjectCond.clone( + tag = cms.InputTag("l1tGTProducer", "CL2EtSum"), + minPt = cms.double(93.1) +) +pPuppiMET200 = cms.Path(PuppiMET200) +algorithms.append(cms.PSet(expression = cms.string("pPuppiMET200"))) + +QuadJet70554040 = l1tGTQuadObjectCond.clone( + collection1 = cms.PSet( + tag = cms.InputTag("l1tGTProducer", "CL2Jets"), + #minPt = cms.double(41.9), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.5), + regionsMinPt=cms.vdouble(42.0,32.7) + ), + collection2 = cms.PSet( + tag = cms.InputTag("l1tGTProducer", "CL2Jets"), + #minPt = cms.double(30.3), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.5), + regionsMinPt=cms.vdouble(26.7,25.0) + ), + collection3 = cms.PSet( + tag = cms.InputTag("l1tGTProducer", "CL2Jets"), + #minPt = cms.double(18.8), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.5), + regionsMinPt=cms.vdouble(25.0,25.0) + ), + collection4 = cms.PSet( + tag = cms.InputTag("l1tGTProducer", "CL2Jets"), + #minPt = cms.double(18.8), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.5), + regionsMinPt=cms.vdouble(25.0,25.0) + ), + +) +pQuadJet70_55_40_40 = cms.Path(QuadJet70554040) + +PuppiHT400 = l1tGTSingleObjectCond.clone( + tag = cms.InputTag("l1tGTProducer", "CL2HtSum"), + minScalarSumPt = cms.double(326.9) +) +pPuppiHT400 = cms.Path(PuppiHT400) + + +algorithms.append(cms.PSet(name=cms.string("pPuppiHT400_pQuadJet70_55_40_40"), + expression=cms.string("pPuppiHT400 and pQuadJet70_55_40_40"))) + diff --git a/L1Trigger/Phase2L1GT/python/l1tGTMenu_lepSeeds_cff.py b/L1Trigger/Phase2L1GT/python/l1tGTMenu_lepSeeds_cff.py new file mode 100644 index 0000000000000..18f1f1a8658ce --- /dev/null +++ b/L1Trigger/Phase2L1GT/python/l1tGTMenu_lepSeeds_cff.py @@ -0,0 +1,409 @@ +import FWCore.ParameterSet.Config as cms + +############################################################ +# L1 Global Trigger Emulation +############################################################ + +# Conditions + +from L1Trigger.Phase2L1GT.l1tGTProducer_cff import l1tGTProducer + +from L1Trigger.Phase2L1GT.l1tGTSingleObjectCond_cfi import l1tGTSingleObjectCond +from L1Trigger.Phase2L1GT.l1tGTDoubleObjectCond_cfi import l1tGTDoubleObjectCond +from L1Trigger.Phase2L1GT.l1tGTTripleObjectCond_cfi import l1tGTTripleObjectCond +from L1Trigger.Phase2L1GT.l1tGTQuadObjectCond_cfi import l1tGTQuadObjectCond + +from L1Trigger.Phase2L1GT.l1tGTAlgoBlockProducer_cff import algorithms + +####### MUON SEEDS ########### + +# regionsAbsEtaLowerBounds=cms.vdouble(0,1.2,3), +# regionsMinPt=cms.vdouble(12,14,15) + + +SingleTkMuon22 = l1tGTSingleObjectCond.clone( + tag = cms.InputTag("l1tGTProducer", "GMTTkMuons"), + #minPt = cms.double(20.3), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,0.83,1.24), + regionsMinPt=cms.vdouble(20.0,19.9,20.1) +) +pSingleTkMuon22 = cms.Path(SingleTkMuon22) +algorithms.append(cms.PSet(expression = cms.string("pSingleTkMuon22"))) + +DoubleTkMuon157 = l1tGTDoubleObjectCond.clone( + collection1 = cms.PSet( + tag = cms.InputTag("l1tGTProducer", "GMTTkMuons"), + #minPt = cms.double(13.6), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,0.83,1.24), + regionsMinPt=cms.vdouble(13.4,13.2,13.5) + + ), + collection2 = cms.PSet( + tag = cms.InputTag("l1tGTProducer", "GMTTkMuons"), + #minPt = cms.double(5.9), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,0.83,1.24), + regionsMinPt=cms.vdouble(7,7,7) + ), + maxDz = cms.double(1), +) +pDoubleTkMuon15_7 = cms.Path(DoubleTkMuon157) +algorithms.append(cms.PSet(expression = cms.string("pDoubleTkMuon15_7"))) + +TripleTkMuon533 = l1tGTTripleObjectCond.clone( + collection1 = cms.PSet( + tag = cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt = cms.double(5), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + qual = cms.vuint32(0b00000001, 0b00000010, 0b00000011, 0b00000100, 0b00000101, 0b00000110, 0b00000111, 0b00001000, 0b00001001, 0b00001010, 0b00001011, 0b00001100, 0b00001101, 0b00001110, 0b00001111, 0b00010000, 0b00010001, 0b00010010, 0b00010011, 0b00010100, 0b00010101, 0b00010110, 0b00010111, 0b00011000, 0b00011001, 0b00011010, 0b00011011, 0b00011100, 0b00011101, 0b00011110, 0b00011111, 0b00100000, 0b00100001, 0b00100010, 0b00100011, 0b00100100, 0b00100101, 0b00100110, 0b00100111, 0b00101000, 0b00101001, 0b00101010, 0b00101011, 0b00101100, 0b00101101, 0b00101110, 0b00101111, 0b00110000, 0b00110001, 0b00110010, 0b00110011, 0b00110100, 0b00110101, 0b00110110, 0b00110111, 0b00111000, 0b00111001, 0b00111010, 0b00111011, 0b00111100, 0b00111101, 0b00111110, 0b00111111, 0b01000000, 0b01000001, 0b01000010, 0b01000011, 0b01000100, 0b01000101, 0b01000110, 0b01000111, 0b01001000, 0b01001001, 0b01001010, 0b01001011, 0b01001100, 0b01001101, 0b01001110, 0b01001111, 0b01010000, 0b01010001, 0b01010010, 0b01010011, 0b01010100, 0b01010101, 0b01010110, 0b01010111, 0b01011000, 0b01011001, 0b01011010, 0b01011011, 0b01011100, 0b01011101, 0b01011110, 0b01011111, 0b01100000, 0b01100001, 0b01100010, 0b01100011, 0b01100100, 0b01100101, 0b01100110, 0b01100111, 0b01101000, 0b01101001, 0b01101010, 0b01101011, 0b01101100, 0b01101101, 0b01101110, 0b01101111, 0b01110000, 0b01110001, 0b01110010, 0b01110011, 0b01110100, 0b01110101, 0b01110110, 0b01110111, 0b01111000, 0b01111001, 0b01111010, 0b01111011, 0b01111100, 0b01111101, 0b01111110, 0b01111111, 0b10000000, 0b10000001, 0b10000010, 0b10000011, 0b10000100, 0b10000101, 0b10000110, 0b10000111, 0b10001000, 0b10001001, 0b10001010, 0b10001011, 0b10001100, 0b10001101, 0b10001110, 0b10001111, 0b10010000, 0b10010001, 0b10010010, 0b10010011, 0b10010100, 0b10010101, 0b10010110, 0b10010111, 0b10011000, 0b10011001, 0b10011010, 0b10011011, 0b10011100, 0b10011101, 0b10011110, 0b10011111, 0b10100000, 0b10100001, 0b10100010, 0b10100011, 0b10100100, 0b10100101, 0b10100110, 0b10100111, 0b10101000, 0b10101001, 0b10101010, 0b10101011, 0b10101100, 0b10101101, 0b10101110, 0b10101111, 0b10110000, 0b10110001, 0b10110010, 0b10110011, 0b10110100, 0b10110101, 0b10110110, 0b10110111, 0b10111000, 0b10111001, 0b10111010, 0b10111011, 0b10111100, 0b10111101, 0b10111110, 0b10111111, 0b11000000, 0b11000001, 0b11000010, 0b11000011, 0b11000100, 0b11000101, 0b11000110, 0b11000111, 0b11001000, 0b11001001, 0b11001010, 0b11001011, 0b11001100, 0b11001101, 0b11001110, 0b11001111, 0b11010000, 0b11010001, 0b11010010, 0b11010011, 0b11010100, 0b11010101, 0b11010110, 0b11010111, 0b11011000, 0b11011001, 0b11011010, 0b11011011, 0b11011100, 0b11011101, 0b11011110, 0b11011111, 0b11100000, 0b11100001, 0b11100010, 0b11100011, 0b11100100, 0b11100101, 0b11100110, 0b11100111, 0b11101000, 0b11101001, 0b11101010, 0b11101011, 0b11101100, 0b11101101, 0b11101110, 0b11101111, 0b11110000, 0b11110001, 0b11110010, 0b11110011, 0b11110100, 0b11110101, 0b11110110, 0b11110111, 0b11111000, 0b11111001, 0b11111010, 0b11111011, 0b11111100, 0b11111101, 0b11111110, 0b11111111) + #regionsAbsEtaLowerBounds=cms.vdouble(0,0.83,1.24), + #regionsMinPt=cms.vdouble(3.9,3.9,4.0) + ), + collection2 = cms.PSet( + tag = cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt = cms.double(3), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + qual = cms.vuint32(0b00000001, 0b00000010, 0b00000011, 0b00000100, 0b00000101, 0b00000110, 0b00000111, 0b00001000, 0b00001001, 0b00001010, 0b00001011, 0b00001100, 0b00001101, 0b00001110, 0b00001111, 0b00010000, 0b00010001, 0b00010010, 0b00010011, 0b00010100, 0b00010101, 0b00010110, 0b00010111, 0b00011000, 0b00011001, 0b00011010, 0b00011011, 0b00011100, 0b00011101, 0b00011110, 0b00011111, 0b00100000, 0b00100001, 0b00100010, 0b00100011, 0b00100100, 0b00100101, 0b00100110, 0b00100111, 0b00101000, 0b00101001, 0b00101010, 0b00101011, 0b00101100, 0b00101101, 0b00101110, 0b00101111, 0b00110000, 0b00110001, 0b00110010, 0b00110011, 0b00110100, 0b00110101, 0b00110110, 0b00110111, 0b00111000, 0b00111001, 0b00111010, 0b00111011, 0b00111100, 0b00111101, 0b00111110, 0b00111111, 0b01000000, 0b01000001, 0b01000010, 0b01000011, 0b01000100, 0b01000101, 0b01000110, 0b01000111, 0b01001000, 0b01001001, 0b01001010, 0b01001011, 0b01001100, 0b01001101, 0b01001110, 0b01001111, 0b01010000, 0b01010001, 0b01010010, 0b01010011, 0b01010100, 0b01010101, 0b01010110, 0b01010111, 0b01011000, 0b01011001, 0b01011010, 0b01011011, 0b01011100, 0b01011101, 0b01011110, 0b01011111, 0b01100000, 0b01100001, 0b01100010, 0b01100011, 0b01100100, 0b01100101, 0b01100110, 0b01100111, 0b01101000, 0b01101001, 0b01101010, 0b01101011, 0b01101100, 0b01101101, 0b01101110, 0b01101111, 0b01110000, 0b01110001, 0b01110010, 0b01110011, 0b01110100, 0b01110101, 0b01110110, 0b01110111, 0b01111000, 0b01111001, 0b01111010, 0b01111011, 0b01111100, 0b01111101, 0b01111110, 0b01111111, 0b10000000, 0b10000001, 0b10000010, 0b10000011, 0b10000100, 0b10000101, 0b10000110, 0b10000111, 0b10001000, 0b10001001, 0b10001010, 0b10001011, 0b10001100, 0b10001101, 0b10001110, 0b10001111, 0b10010000, 0b10010001, 0b10010010, 0b10010011, 0b10010100, 0b10010101, 0b10010110, 0b10010111, 0b10011000, 0b10011001, 0b10011010, 0b10011011, 0b10011100, 0b10011101, 0b10011110, 0b10011111, 0b10100000, 0b10100001, 0b10100010, 0b10100011, 0b10100100, 0b10100101, 0b10100110, 0b10100111, 0b10101000, 0b10101001, 0b10101010, 0b10101011, 0b10101100, 0b10101101, 0b10101110, 0b10101111, 0b10110000, 0b10110001, 0b10110010, 0b10110011, 0b10110100, 0b10110101, 0b10110110, 0b10110111, 0b10111000, 0b10111001, 0b10111010, 0b10111011, 0b10111100, 0b10111101, 0b10111110, 0b10111111, 0b11000000, 0b11000001, 0b11000010, 0b11000011, 0b11000100, 0b11000101, 0b11000110, 0b11000111, 0b11001000, 0b11001001, 0b11001010, 0b11001011, 0b11001100, 0b11001101, 0b11001110, 0b11001111, 0b11010000, 0b11010001, 0b11010010, 0b11010011, 0b11010100, 0b11010101, 0b11010110, 0b11010111, 0b11011000, 0b11011001, 0b11011010, 0b11011011, 0b11011100, 0b11011101, 0b11011110, 0b11011111, 0b11100000, 0b11100001, 0b11100010, 0b11100011, 0b11100100, 0b11100101, 0b11100110, 0b11100111, 0b11101000, 0b11101001, 0b11101010, 0b11101011, 0b11101100, 0b11101101, 0b11101110, 0b11101111, 0b11110000, 0b11110001, 0b11110010, 0b11110011, 0b11110100, 0b11110101, 0b11110110, 0b11110111, 0b11111000, 0b11111001, 0b11111010, 0b11111011, 0b11111100, 0b11111101, 0b11111110, 0b11111111) + #regionsAbsEtaLowerBounds=cms.vdouble(0,0.83,1.24), + #regionsMinPt=cms.vdouble(2.0,2.0,2.1) + ), + collection3 = cms.PSet( + tag = cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt = cms.double(3), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + qual = cms.vuint32(0b00000001, 0b00000010, 0b00000011, 0b00000100, 0b00000101, 0b00000110, 0b00000111, 0b00001000, 0b00001001, 0b00001010, 0b00001011, 0b00001100, 0b00001101, 0b00001110, 0b00001111, 0b00010000, 0b00010001, 0b00010010, 0b00010011, 0b00010100, 0b00010101, 0b00010110, 0b00010111, 0b00011000, 0b00011001, 0b00011010, 0b00011011, 0b00011100, 0b00011101, 0b00011110, 0b00011111, 0b00100000, 0b00100001, 0b00100010, 0b00100011, 0b00100100, 0b00100101, 0b00100110, 0b00100111, 0b00101000, 0b00101001, 0b00101010, 0b00101011, 0b00101100, 0b00101101, 0b00101110, 0b00101111, 0b00110000, 0b00110001, 0b00110010, 0b00110011, 0b00110100, 0b00110101, 0b00110110, 0b00110111, 0b00111000, 0b00111001, 0b00111010, 0b00111011, 0b00111100, 0b00111101, 0b00111110, 0b00111111, 0b01000000, 0b01000001, 0b01000010, 0b01000011, 0b01000100, 0b01000101, 0b01000110, 0b01000111, 0b01001000, 0b01001001, 0b01001010, 0b01001011, 0b01001100, 0b01001101, 0b01001110, 0b01001111, 0b01010000, 0b01010001, 0b01010010, 0b01010011, 0b01010100, 0b01010101, 0b01010110, 0b01010111, 0b01011000, 0b01011001, 0b01011010, 0b01011011, 0b01011100, 0b01011101, 0b01011110, 0b01011111, 0b01100000, 0b01100001, 0b01100010, 0b01100011, 0b01100100, 0b01100101, 0b01100110, 0b01100111, 0b01101000, 0b01101001, 0b01101010, 0b01101011, 0b01101100, 0b01101101, 0b01101110, 0b01101111, 0b01110000, 0b01110001, 0b01110010, 0b01110011, 0b01110100, 0b01110101, 0b01110110, 0b01110111, 0b01111000, 0b01111001, 0b01111010, 0b01111011, 0b01111100, 0b01111101, 0b01111110, 0b01111111, 0b10000000, 0b10000001, 0b10000010, 0b10000011, 0b10000100, 0b10000101, 0b10000110, 0b10000111, 0b10001000, 0b10001001, 0b10001010, 0b10001011, 0b10001100, 0b10001101, 0b10001110, 0b10001111, 0b10010000, 0b10010001, 0b10010010, 0b10010011, 0b10010100, 0b10010101, 0b10010110, 0b10010111, 0b10011000, 0b10011001, 0b10011010, 0b10011011, 0b10011100, 0b10011101, 0b10011110, 0b10011111, 0b10100000, 0b10100001, 0b10100010, 0b10100011, 0b10100100, 0b10100101, 0b10100110, 0b10100111, 0b10101000, 0b10101001, 0b10101010, 0b10101011, 0b10101100, 0b10101101, 0b10101110, 0b10101111, 0b10110000, 0b10110001, 0b10110010, 0b10110011, 0b10110100, 0b10110101, 0b10110110, 0b10110111, 0b10111000, 0b10111001, 0b10111010, 0b10111011, 0b10111100, 0b10111101, 0b10111110, 0b10111111, 0b11000000, 0b11000001, 0b11000010, 0b11000011, 0b11000100, 0b11000101, 0b11000110, 0b11000111, 0b11001000, 0b11001001, 0b11001010, 0b11001011, 0b11001100, 0b11001101, 0b11001110, 0b11001111, 0b11010000, 0b11010001, 0b11010010, 0b11010011, 0b11010100, 0b11010101, 0b11010110, 0b11010111, 0b11011000, 0b11011001, 0b11011010, 0b11011011, 0b11011100, 0b11011101, 0b11011110, 0b11011111, 0b11100000, 0b11100001, 0b11100010, 0b11100011, 0b11100100, 0b11100101, 0b11100110, 0b11100111, 0b11101000, 0b11101001, 0b11101010, 0b11101011, 0b11101100, 0b11101101, 0b11101110, 0b11101111, 0b11110000, 0b11110001, 0b11110010, 0b11110011, 0b11110100, 0b11110101, 0b11110110, 0b11110111, 0b11111000, 0b11111001, 0b11111010, 0b11111011, 0b11111100, 0b11111101, 0b11111110, 0b11111111) + #regionsAbsEtaLowerBounds=cms.vdouble(0,0.83,1.24), + #regionsMinPt=cms.vdouble(2.0,2.0,2.1) + ), + delta12 = cms.PSet( + maxDz = cms.double(1) + ), + delta13 = cms.PSet( + maxDz = cms.double(1) + ), + #delta23 = cms.PSet( + # maxDz = cms.double(1) + #) +) +pTripleTkMuon5_3_3 = cms.Path(TripleTkMuon533) +algorithms.append(cms.PSet(expression = cms.string("pTripleTkMuon5_3_3"))) + +####### EG and PHO seeds ########### + +SingleEGEle51 = l1tGTSingleObjectCond.clone( + tag = cms.InputTag("l1tGTProducer", "CL2Photons"), + #minPt = cms.double(29.9), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.479), + regionsMinPt=cms.vdouble(40.7,39.6), + regionsQual=cms.vuint32(0b0010,0b0100), + #qual = cms.vuint32(0b0010) +) +pSingleEGEle51 = cms.Path(SingleEGEle51) +algorithms.append(cms.PSet(expression = cms.string("pSingleEGEle51"))) + +DoubleEGEle3724 = l1tGTDoubleObjectCond.clone( + collection1 = cms.PSet( + tag = cms.InputTag("l1tGTProducer", "CL2Photons"), + #minPt = cms.double(20.6), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.479), + regionsMinPt=cms.vdouble(28.9,28.4), + regionsQual=cms.vuint32(0b0010,0b0100), + #qual = cms.vuint32(0b0010) + ), + collection2 = cms.PSet( + tag = cms.InputTag("l1tGTProducer", "CL2Photons"), + #minPt = cms.double(9.6), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.479), + regionsMinPt=cms.vdouble(17.9,18.0), + regionsQual=cms.vuint32(0b0010,0b0100), + #qual = cms.vuint32(0b0010) + ), + minDR = cms.double(0.1), +) +pDoubleEGEle37_24 = cms.Path(DoubleEGEle3724) +algorithms.append(cms.PSet(expression = cms.string("pDoubleEGEle37_24"))) + +IsoTkEleEGEle2212 = l1tGTDoubleObjectCond.clone( + collection1 = cms.PSet( + tag = cms.InputTag("l1tGTProducer", "CL2Electrons"), + #minPt = cms.double(20.6), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.479), + regionsMinPt=cms.vdouble(17.8,17.1), + #regionsQual=cms.vuint32(0b0000,0b0010), + regionsMaxIso = cms.vdouble(0.13,0.28) + #qual = cms.vuint32(0b0010) + ), + collection2 = cms.PSet( + tag = cms.InputTag("l1tGTProducer", "CL2Photons"), + #minPt = cms.double(9.6), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.479), + regionsMinPt=cms.vdouble(7.8,8.3), + regionsQual=cms.vuint32(0b0010,0b0100) + #qual = cms.vuint32(0b0010) + ), + minDR = cms.double(0.1), +) +pIsoTkEleEGEle22_12 = cms.Path(IsoTkEleEGEle2212) +algorithms.append(cms.PSet(expression = cms.string("pIsoTkEleEGEle22_12"))) + +SingleTkEle36 = l1tGTSingleObjectCond.clone( + tag = cms.InputTag("l1tGTProducer", "CL2Electrons"), + #minPt = cms.double(29.9), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.479), + regionsMinPt=cms.vdouble(29.8,28.5), + regionsQual=cms.vuint32(0b0010,0b0010) + #qual = cms.vuint32(0b0010) +) +pSingleTkEle36 = cms.Path(SingleTkEle36) +algorithms.append(cms.PSet(expression = cms.string("pSingleTkEle36"))) + +SingleIsoTkEle28 = l1tGTSingleObjectCond.clone( + tag = cms.InputTag("l1tGTProducer", "CL2Electrons"), + #minPt = cms.double(29.9), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.479), + regionsMinPt=cms.vdouble(23,22.1), + #regionsQual=cms.vuint32(0b0000,0b0010), + regionsMaxIso = cms.vdouble(0.13,0.28) + #qual = cms.vuint32(0b0010) +) +pSingleIsoTkEle28 = cms.Path(SingleIsoTkEle28) +algorithms.append(cms.PSet(expression = cms.string("pSingleIsoTkEle28"))) + +#SingleIsoTkEle28Barrel = l1tGTSingleObjectCond.clone( +# tag = cms.InputTag("l1tGTProducer", "CL2Electrons"), +# minPt = cms.double(23), +# minEta = cms.double(-1.479), +# maxEta = cms.double(1.479), + #maxIso = cms.double(0.13), +#) +#pSingleIsoTkEle28Barrel = cms.Path(SingleIsoTkEle28Barrel) +#algorithms.append(cms.PSet(expression = cms.string("pSingleIsoTkEle28Barrel"))) + +#SingleIsoTkEle28BarrelQual = l1tGTSingleObjectCond.clone( +# tag = cms.InputTag("l1tGTProducer", "CL2Electrons"), +# minPt = cms.double(23), +# minEta = cms.double(-1.479), +# maxEta = cms.double(1.479), +# qual = cms.vuint32(0b0000), + #maxIso = cms.double(0.13), +#) +#pSingleIsoTkEle28BarrelQual = cms.Path(SingleIsoTkEle28BarrelQual) +#algorithms.append(cms.PSet(expression = cms.string("pSingleIsoTkEle28BarrelQual"))) + +#SingleIsoTkEle28Endcap = l1tGTSingleObjectCond.clone( +# tag = cms.InputTag("l1tGTProducer", "CL2Electrons"), +# minPt = cms.double(21.9), +# minEtaAbs = cms.double(1.479), +# maxEtaAbs = cms.double(2.4), +# qual = cms.vuint32(0b0010,0b0011,0b0110,0b1010,0b0111,0b1011,0b1110,0b1111), + #maxIso = cms.double(0.28) +#) +#pSingleIsoTkEle28Endcap = cms.Path(SingleIsoTkEle28Endcap) +#algorithms.append(cms.PSet(expression = cms.string("pSingleIsoTkEle28Endcap"))) + +#algorithms.append(cms.PSet(name=cms.string("pSingleIsoTkEle28OLD"), +# expression=cms.string("pSingleIsoTkEle28Barrel or pSingleIsoTkEle28Endcap"))) + + +SingleIsoTkPho36 = l1tGTSingleObjectCond.clone( + tag = cms.InputTag("l1tGTProducer", "CL2Photons"), + #minPt = cms.double(30.8), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.479), + regionsMinPt=cms.vdouble(30.4,29.0), + regionsQual=cms.vuint32(0b0010,0b0100), + regionsMaxIso = cms.vdouble(0.25,0.205) + #qual = cms.vuint32(0b0100), + #maxIso = cms.double(0.205) +) +pSingleIsoTkPho36 = cms.Path(SingleIsoTkPho36) + +algorithms.append(cms.PSet(expression=cms.string("pSingleIsoTkPho36"))) + +#SingleIsoTkPho36Barrel = l1tGTSingleObjectCond.clone( +# tag = cms.InputTag("l1tGTProducer", "CL2Photons"), +# minPt = cms.double(30.8), +# minEta = cms.double(-1.479), +# maxEta = cms.double(1.479), +# qual = cms.vuint32(0b0010), +# maxIso = cms.double(0.25) +#) +#pSingleIsoTkPho36Barrel = cms.Path(SingleIsoTkPho36Barrel) + +#SingleIsoTkPho36Endcap = l1tGTSingleObjectCond.clone( +# tag = cms.InputTag("l1tGTProducer", "CL2Photons"), +# minPt = cms.double(30.8), +# minEtaAbs = cms.double(1.479), +# maxEtaAbs = cms.double(2.4), +# qual = cms.vuint32(0b0100), +# maxIso = cms.double(0.205) +#) +#pSingleIsoTkPho36Endcap = cms.Path(SingleIsoTkPho36Endcap) +# +#algorithms.append(cms.PSet(name=cms.string("pSingleIsoTkPho36"), +# expression=cms.string("pSingleIsoTkPho36Barrel or pSingleIsoTkPho36Endcap"))) + +DoubleTkEle2512 = l1tGTDoubleObjectCond.clone( + collection1 = cms.PSet( + tag = cms.InputTag("l1tGTProducer", "CL2Electrons"), + #minPt = cms.double(20.6), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.479), + regionsMinPt=cms.vdouble(20.3,19.5), + regionsQual=cms.vuint32(0b0010,0b0000) + #qual = cms.vuint32(0b0010) + ), + collection2 = cms.PSet( + tag = cms.InputTag("l1tGTProducer", "CL2Electrons"), + #minPt = cms.double(9.6), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.479), + regionsMinPt=cms.vdouble(9.1,8.8), + regionsQual=cms.vuint32(0b0010,0b0000) + #qual = cms.vuint32(0b0010) + ), + maxDz = cms.double(1), +) +pDoubleTkEle25_12 = cms.Path(DoubleTkEle2512) +algorithms.append(cms.PSet(expression = cms.string("pDoubleTkEle25_12"))) + +DoubleIsoTkPho2212 = l1tGTDoubleObjectCond.clone( + collection1 = cms.PSet( + tag = cms.InputTag("l1tGTProducer", "CL2Photons"), + #minPt = cms.double(20.6), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.479), + regionsMinPt=cms.vdouble(17.6,15.9), + regionsQual=cms.vuint32(0b0010,0b0100), + regionsMaxIso = cms.vdouble(0.25,0.205) + #qual = cms.vuint32(0b0010) + ), + collection2 = cms.PSet( + tag = cms.InputTag("l1tGTProducer", "CL2Photons"), + #minPt = cms.double(9.6), + minEta = cms.double(-2.4), + maxEta = cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.479), + regionsMinPt=cms.vdouble(8.5,6.0), + regionsQual=cms.vuint32(0b0010,0b0100), + regionsMaxIso = cms.vdouble(0.25,0.205) + #qual = cms.vuint32(0b0010) + ), +) +pDoubleIsoTkPho22_12 = cms.Path(DoubleIsoTkPho2212) +algorithms.append(cms.PSet(expression = cms.string("pDoubleIsoTkPho22_12"))) + + + +#SingleIsoTkPho36 = l1tGTSingleObjectCond.clone( +# tag = cms.InputTag("l1tGTProducer", "CL2Photons"), +# #minPt = cms.double(30.8), +# minEta = cms.double(-2.4), +# maxEta = cms.double(2.4), +# regionsAbsEtaLowerBounds=cms.vdouble(0,1.479), +# regionsMinPt=cms.vdouble(30.8,29.2), +# regionsQual=cms.vuint32(0b0010,0b0100) + #qual = cms.vuint32(0b0100), + #maxIso = cms.double(0.205) +#) +#pSingleIsoTkPho36 = cms.Path(SingleIsoTkPho36) + +#algorithms.append(cms.PSet(expression=cms.string("pSingleIsoTkPho36"))) + + + + + +#SingleIsoTkPho22Barrel = l1tGTSingleObjectCond.clone( +# tag = cms.InputTag("l1tGTProducer", "CL2Photons"), +# minPt = cms.double(17.1), +# minEta = cms.double(-1.479), +# maxEta = cms.double(1.479), +# qual = cms.vuint32(0b0010), +# maxIso = cms.double(0.25) +#) +#pSingleIsoTkPho22Barrel = cms.Path(SingleIsoTkPho22Barrel) + +#SingleIsoTkPho22Endcap = l1tGTSingleObjectCond.clone( +# tag = cms.InputTag("l1tGTProducer", "CL2Photons"), +# minPt = cms.double(17.1), +# minEtaAbs = cms.double(1.479), +# maxEtaAbs = cms.double(2.4), +# qual = cms.vuint32(0b0100), +# maxIso = cms.double(0.205) +#) +#pSingleIsoTkPho22Endcap = cms.Path(SingleIsoTkPho22Endcap) + +#SingleIsoTkPho12Barrel = l1tGTSingleObjectCond.clone( +# tag = cms.InputTag("l1tGTProducer", "CL2Photons"), +# minPt = cms.double(8.8), +# minEta = cms.double(-1.479), +# maxEta = cms.double(1.479), +# qual = cms.vuint32(0b0010), +# maxIso = cms.double(0.25) +#) +#pSingleIsoTkPho12Barrel = cms.Path(SingleIsoTkPho12Barrel) + +#SingleIsoTkPho12EndcapPos = l1tGTSingleObjectCond.clone( +# tag = cms.InputTag("l1tGTProducer", "CL2Photons"), +# minPt = cms.double(8.8), +# minEtaAbs = cms.double(1.479), +# maxEtaAbs = cms.double(2.4), +# qual = cms.vuint32(0b0100), +# maxIso = cms.double(0.205) +#) +#pSingleIsoTkPho12EndcapPos = cms.Path(SingleIsoTkPho12EndcapPos) + +#algorithms.append(cms.PSet(name=cms.string("pDoubleTkIsoPho22_12"), +# expression=cms.string("(pSingleIsoTkPho22Barrel or pSingleIsoTkPho22EndcapPos or pSingleIsoTkPho22EndcapNeg) and (pSingleIsoTkPho12Barrel or pSingleIsoTkPho12EndcapPos or pSingleIsoTkPho12EndcapNeg)"))) + + + +DoublePuppiTau5252 = l1tGTDoubleObjectCond.clone( + collection1 = cms.PSet( + tag = cms.InputTag("l1tGTProducer", "CL2Taus"), + minEta = cms.double(-2.172), + maxEta = cms.double(2.172), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.5), + regionsMinPt=cms.vdouble(28.6,19.6), + minHwIso = cms.int32(286), + ), + collection2 = cms.PSet( + tag = cms.InputTag("l1tGTProducer", "CL2Taus"), + minEta = cms.double(-2.172), + maxEta = cms.double(2.172), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.5), + regionsMinPt=cms.vdouble(28.6,19.6), + minHwIso = cms.int32(286), + ), + minDR = cms.double(0.5), +) +pDoublePuppiTau52_52 = cms.Path(DoublePuppiTau5252) +algorithms.append(cms.PSet(expression = cms.string("pDoublePuppiTau52_52"))) + diff --git a/L1Trigger/Phase2L1GT/python/l1tGTProducer_cff.py b/L1Trigger/Phase2L1GT/python/l1tGTProducer_cff.py new file mode 100644 index 0000000000000..e0ce27cc0fbc9 --- /dev/null +++ b/L1Trigger/Phase2L1GT/python/l1tGTProducer_cff.py @@ -0,0 +1,19 @@ +import FWCore.ParameterSet.Config as cms +from L1Trigger.Phase2L1GT.l1tGTScales import scale_parameter + +l1tGTProducer = cms.EDProducer( + "L1GTProducer", + scales=scale_parameter, + GTTPromptJets = cms.InputTag("l1tTrackJetsEmulation", "L1TrackJets"), + GTTDisplacedJets = cms.InputTag("l1tTrackJetsExtendedEmulation", "L1TrackJetsExtended"), + GTTPrimaryVert = cms.InputTag("l1tVertexFinderEmulator", "l1verticesEmulation"), + GMTSaPromptMuons = cms.InputTag("l1tSAMuonsGmt", "promptSAMuons"), + GMTSaDisplacedMuons = cms.InputTag("l1tSAMuonsGmt", "displacedSAMuons"), + GMTTkMuons = cms.InputTag("l1tTkMuonsGmtLowPtFix", ""), #cms.InputTag("l1tTkMuonsGmt", ""), + CL2Jets = cms.InputTag("l1tSCPFL1PuppiCorrectedEmulator"), + CL2Electrons = cms.InputTag("l1tLayer2EG", "L1CtTkElectron"), + CL2Photons = cms.InputTag("l1tLayer2EG", "L1CtTkEm"), + CL2Taus = cms.InputTag("l1tNNTauProducerPuppi", "L1PFTausNN"), + CL2EtSum = cms.InputTag("l1tMETPFProducer"), + CL2HtSum = cms.InputTag("l1tSCPFL1PuppiCorrectedEmulatorMHT") +) diff --git a/L1Trigger/Phase2L1GT/python/l1tGTQuadObjectCond_cfi.py b/L1Trigger/Phase2L1GT/python/l1tGTQuadObjectCond_cfi.py new file mode 100644 index 0000000000000..d6a1539634dba --- /dev/null +++ b/L1Trigger/Phase2L1GT/python/l1tGTQuadObjectCond_cfi.py @@ -0,0 +1,13 @@ +import FWCore.ParameterSet.Config as cms +from L1Trigger.Phase2L1GT.l1tGTSingleInOutLUT import COS_PHI_LUT, COSH_ETA_LUT, COSH_ETA_LUT_2 +from L1Trigger.Phase2L1GT.l1tGTScales import scale_parameter + +l1tGTQuadObjectCond = cms.EDFilter( + "L1GTQuadObjectCond", + scales=scale_parameter, + cosh_eta_lut=COSH_ETA_LUT.config(), + cosh_eta_lut2=COSH_ETA_LUT_2.config(), + cos_phi_lut=COS_PHI_LUT.config(), + sanity_checks=cms.untracked.bool(False), + inv_mass_checks=cms.untracked.bool(False) +) diff --git a/L1Trigger/Phase2L1GT/python/l1tGTScales.py b/L1Trigger/Phase2L1GT/python/l1tGTScales.py new file mode 100644 index 0000000000000..350e71ce2476d --- /dev/null +++ b/L1Trigger/Phase2L1GT/python/l1tGTScales.py @@ -0,0 +1,22 @@ +from libL1TriggerPhase2L1GT import L1GTScales as CppScales +import FWCore.ParameterSet.Config as cms +import math + +scale_parameter = cms.PSet( + pT_lsb=cms.double(0.03125), # GeV + phi_lsb=cms.double(math.pi / 2**12), # radiants + eta_lsb=cms.double(math.pi / 2**12), # radiants + z0_lsb=cms.double(1/(5*2**9)), # cm + # d0_lsb = cms.double(...), TODO input scales far apart + isolation_lsb=cms.double(0.25), # GeV + beta_lsb=cms.double(1. / 2**4), # [0, 1] + mass_lsb=cms.double(0.25), # GeV^2 + seed_pT_lsb=cms.double(0.25), # GeV + seed_z0_lsb=cms.double(30. / 2**9), # ? cm + sca_sum_lsb=cms.double(0.03125), # GeV + sum_pT_pv_lsb=cms.double(0.25), # GeV + pos_chg=cms.int32(1), + neg_chg=cms.int32(0) +) + +l1tGTScales = CppScales(*[param.value() for param in scale_parameter.parameters_().values()]) diff --git a/L1Trigger/Phase2L1GT/python/l1tGTSingleInOutLUT.py b/L1Trigger/Phase2L1GT/python/l1tGTSingleInOutLUT.py new file mode 100644 index 0000000000000..67e97e01991ab --- /dev/null +++ b/L1Trigger/Phase2L1GT/python/l1tGTSingleInOutLUT.py @@ -0,0 +1,105 @@ +""" +This computes the most optimal COS_PHI_LUT and COSH_ETA_LUT. Call +:func:`~l1tGTSingleInOutLUT.SingleInOutLUT.export` to export the +generated LUT. +""" + +import FWCore.ParameterSet.Config as cms +from L1Trigger.Phase2L1GT.l1tGTScales import scale_parameter +from statistics import mean, median, stdev +import math + + +class SingleInOutLUT: + + def __init__(self, width_in, unused_lsbs, lsb, output_scale_factor, operation, start_value=0, label=""): + self.debug_txt = "" + input_scale_factor = 2**unused_lsbs * lsb + self.unused_lsbs = unused_lsbs + self.lsb = lsb + signed_output = min([operation(input_scale_factor * (i + 0.5) + start_value) + for i in range(2**width_in)]) < 0 + + self.width_out = math.ceil(math.log2(output_scale_factor * + max([abs(operation(input_scale_factor * (i + 0.5) + start_value)) for i in range(2**width_in - 1)] + + [abs(operation(input_scale_factor * (2**width_in - 1) + start_value))]))) + + if signed_output: + self.width_out += 1 + + self.debug_info( + "***************************** {} LUT {} *****************************".format(operation.__name__, label)) + self.debug_info("Depth: {} x {} (addr x data)".format(width_in, self.width_out)) + self.debug_info("Scale: {}".format(output_scale_factor)) + + self.width_in = width_in + self.output_scale_factor = output_scale_factor + self.input_scale_factor = input_scale_factor + self.operation = operation + self.start_value = start_value + self.lut = cms.vint32( + * ([round(output_scale_factor * operation(input_scale_factor * (i + 0.5) + start_value)) for i in range(2**width_in - 1)] + + [round(output_scale_factor * operation(input_scale_factor * (2 ** width_in - 1) + start_value))])) + + self.print_error() + + def debug_info(self, msg): + self.debug_txt += msg + "\n" + + def config(self): + return cms.PSet( + output_scale_factor=cms.double(self.output_scale_factor), + unused_lsbs=cms.uint32(self.unused_lsbs), + lut=self.lut, + max_error=cms.double(self.max_error) + ) + + def export(self, filename: str): + print(self.debug_txt) + with open(filename, "w") as file: + for value in self.lut: + file.write("{:X}".format(int(value) & ((1 << self.width_out) - 1) + ).rjust(math.ceil(self.width_out/4), '0') + "\n") + + @ staticmethod + def optimal_scale_factor(width_in, max_width_out, unused_lsbs, lsb, operation, start_value=0): + input_scale_factor = 2**unused_lsbs * lsb + scale_factor = (2**max_width_out - 1) / max([abs(operation(input_scale_factor * (i + 0.5) + start_value)) + for i in range(2**width_in)]) + return scale_factor + + def print_error(self): + errors = [abs(self.lut[int(i/(2**self.unused_lsbs))]/self.output_scale_factor - + self.operation(i * self.lsb + self.start_value)) for i in range(2**(self.width_in + self.unused_lsbs))] + + self.max_error = max(errors) + + self.debug_info("Error: {:.5f} +/- {:.5f}, max: {:.5f}, total: {:.5f}, median: {:.5f}".format( + mean(errors), stdev(errors), self.max_error, sum(errors), median(errors))) + + # mass_errors = [errors[i]/(2*self.operation(i * self.lsb + self.start_value)) for i in range(2**(self.width_in + self.unused_lsbs)) ] + # self.debug_info("inv mass error: {:.5f} +/- {:.5f}, max: {:.5f}, total: {:.5f}, median: {:.5f}".format( + # mean(mass_errors), stdev(mass_errors), max(mass_errors), sum(mass_errors), median(mass_errors))) + + +COS_PHI_IN_WIDTH = 10 # not using 2 lsb and 1 msb (cos(x + pi) = -cos(x), x in [0, pi)) +COSH_ETA_IN_WIDTH = 11 # not using 2 lsb and 1 msb (splitted LUT) +ISOLATION_WIDTH = 11 + +# Since we calculate cosh(dEta) - cos(dPhi); both must be on the same scale the difference should fit into 17 bits for the DSP +optimal_scale_factor = math.floor( + (2**17 - 1) / (math.cosh((2**(COSH_ETA_IN_WIDTH + 2) - 1)*scale_parameter.eta_lsb.value()) + 1)) + +COS_PHI_LUT = SingleInOutLUT( + COS_PHI_IN_WIDTH, 2, scale_parameter.phi_lsb.value(), optimal_scale_factor, math.cos) + +# eta in [0, 2pi) +COSH_ETA_LUT = SingleInOutLUT( + COSH_ETA_IN_WIDTH, 2, scale_parameter.eta_lsb.value(), optimal_scale_factor, math.cosh, 0, "[0, 2pi)") + +# eta in [2pi, 4pi) +COSH_ETA_LUT_2 = SingleInOutLUT( + COSH_ETA_IN_WIDTH, 2, scale_parameter.eta_lsb.value(), + SingleInOutLUT.optimal_scale_factor( + COSH_ETA_IN_WIDTH, 17, 2, scale_parameter.eta_lsb.value(), math.cosh, 2**13 * scale_parameter.eta_lsb.value()), + math.cosh, 2**13 * scale_parameter.eta_lsb.value(), "[2pi, 4pi)") diff --git a/L1Trigger/Phase2L1GT/python/l1tGTSingleObjectCond_cfi.py b/L1Trigger/Phase2L1GT/python/l1tGTSingleObjectCond_cfi.py new file mode 100644 index 0000000000000..783e7aafb309f --- /dev/null +++ b/L1Trigger/Phase2L1GT/python/l1tGTSingleObjectCond_cfi.py @@ -0,0 +1,7 @@ +import FWCore.ParameterSet.Config as cms +from L1Trigger.Phase2L1GT.l1tGTScales import scale_parameter + +l1tGTSingleObjectCond = cms.EDFilter( + "L1GTSingleObjectCond", + scales=scale_parameter +) diff --git a/L1Trigger/Phase2L1GT/python/l1tGTTripleObjectCond_cfi.py b/L1Trigger/Phase2L1GT/python/l1tGTTripleObjectCond_cfi.py new file mode 100644 index 0000000000000..19dce9c0ad63b --- /dev/null +++ b/L1Trigger/Phase2L1GT/python/l1tGTTripleObjectCond_cfi.py @@ -0,0 +1,13 @@ +import FWCore.ParameterSet.Config as cms +from L1Trigger.Phase2L1GT.l1tGTSingleInOutLUT import COS_PHI_LUT, COSH_ETA_LUT, COSH_ETA_LUT_2 +from L1Trigger.Phase2L1GT.l1tGTScales import scale_parameter + +l1tGTTripleObjectCond = cms.EDFilter( + "L1GTTripleObjectCond", + scales=scale_parameter, + cosh_eta_lut=COSH_ETA_LUT.config(), + cosh_eta_lut2=COSH_ETA_LUT_2.config(), + cos_phi_lut=COS_PHI_LUT.config(), + sanity_checks=cms.untracked.bool(False), + inv_mass_checks=cms.untracked.bool(False) +) diff --git a/L1Trigger/Phase2L1GT/src/L1GTScales.cc b/L1Trigger/Phase2L1GT/src/L1GTScales.cc new file mode 100644 index 0000000000000..1c9050fa4c083 --- /dev/null +++ b/L1Trigger/Phase2L1GT/src/L1GTScales.cc @@ -0,0 +1,107 @@ +#include "L1Trigger/Phase2L1GT/interface/L1GTScales.h" + +#include + +namespace py = pybind11; + +namespace l1t { + L1GTScales::L1GTScales(double pT_lsb, + double phi_lsb, + double eta_lsb, + double z0_lsb, + //double d0_lsb, + double isolation_lsb, + double beta_lsb, + double mass_lsb, + double seed_pT_lsb, + double seed_z0_lsb, + double sca_sum_lsb, + double sum_pT_pv_lsb, + int pos_chg, + int neg_chg) + : pT_lsb_(pT_lsb), + phi_lsb_(phi_lsb), + eta_lsb_(eta_lsb), + z0_lsb_(z0_lsb), + //d0_lsb_(d0_lsb), + isolation_lsb_(isolation_lsb), + isolation_shift_(RELATIVE_ISOLATION_RESOLUTION + std::log2(isolation_lsb_ / pT_lsb_)), + beta_lsb_(beta_lsb), + mass_lsb_(mass_lsb), + seed_pT_lsb_(seed_pT_lsb), + seed_z0_lsb_(seed_z0_lsb), + sca_sum_lsb_(sca_sum_lsb), + sum_pT_pv_lsb_(sum_pT_pv_lsb), + pos_chg_(pos_chg), + neg_chg_(neg_chg) {} + + L1GTScales::L1GTScales(const edm::ParameterSet& config) + : pT_lsb_(config.getParameter("pT_lsb")), + phi_lsb_(config.getParameter("phi_lsb")), + eta_lsb_(config.getParameter("eta_lsb")), + z0_lsb_(config.getParameter("z0_lsb")), + //d0_lsb_(config.getParameter("d0_lsb")), + isolation_lsb_(config.getParameter("isolation_lsb")), + isolation_shift_(RELATIVE_ISOLATION_RESOLUTION + std::log2(isolation_lsb_ / pT_lsb_)), + beta_lsb_(config.getParameter("beta_lsb")), + mass_lsb_(config.getParameter("mass_lsb")), + seed_pT_lsb_(config.getParameter("seed_pT_lsb")), + seed_z0_lsb_(config.getParameter("seed_z0_lsb")), + sca_sum_lsb_(config.getParameter("sca_sum_lsb")), + sum_pT_pv_lsb_(config.getParameter("sum_pT_pv_lsb")), + pos_chg_(config.getParameter("pos_chg")), + neg_chg_(config.getParameter("neg_chg")) {} + + void L1GTScales::fillPSetDescription(edm::ParameterSetDescription& desc) { + desc.add("pT_lsb"); + desc.add("phi_lsb"); + desc.add("eta_lsb"); + desc.add("z0_lsb"); + //desc.add("d0_lsb"); + desc.add("isolation_lsb"); + desc.add("beta_lsb"); + desc.add("mass_lsb"); + desc.add("seed_pT_lsb"); + desc.add("seed_z0_lsb"); + desc.add("sca_sum_lsb"); + desc.add("sum_pT_pv_lsb"); + desc.add("pos_chg"); + desc.add("neg_chg"); + } + + PYBIND11_MODULE(libL1TriggerPhase2L1GT, m) { + py::class_(m, "L1GTScales") + .def(py::init()) + .def("to_hw_pT", &L1GTScales::to_hw_pT) + .def("to_hw_phi", &L1GTScales::to_hw_phi) + .def("to_hw_eta", &L1GTScales::to_hw_eta) + .def("to_hw_z0", &L1GTScales::to_hw_z0) + .def("to_hw_isolation", &L1GTScales::to_hw_isolation) + .def("isolation_shift", &L1GTScales::isolation_shift) + .def("to_hw_beta", &L1GTScales::to_hw_beta) + .def("to_hw_mass", &L1GTScales::to_hw_mass) + .def("to_hw_seed_pT", &L1GTScales::to_hw_seed_pT) + .def("to_hw_seed_z0", &L1GTScales::to_hw_seed_z0) + .def("to_hw_sca_sum", &L1GTScales::to_hw_sca_sum) + .def("to_hw_sum_pT_pv", &L1GTScales::to_hw_sum_pT_pv) + .def("to_hw_dRSquared", &L1GTScales::to_hw_dRSquared) + .def("to_hw_InvMassSqrDiv2", &L1GTScales::to_hw_InvMassSqrDiv2) + .def("to_hw_TransMassSqrDiv2", &L1GTScales::to_hw_TransMassSqrDiv2) + .def("to_hw_PtSquared", &L1GTScales::to_hw_PtSquared) + .def("neg_chg", &L1GTScales::neg_chg) + .def("pos_chg", &L1GTScales::pos_chg); + } +} // namespace l1t diff --git a/L1Trigger/Phase2L1GT/src/classes.h b/L1Trigger/Phase2L1GT/src/classes.h new file mode 100644 index 0000000000000..ac1ef2985d173 --- /dev/null +++ b/L1Trigger/Phase2L1GT/src/classes.h @@ -0,0 +1,3 @@ +#include "DataFormats/Common/interface/Wrapper.h" + +#include "L1Trigger/Phase2L1GT/interface/L1GTInvariantMassError.h" diff --git a/L1Trigger/Phase2L1GT/src/classes_def.xml b/L1Trigger/Phase2L1GT/src/classes_def.xml new file mode 100644 index 0000000000000..7b480eec42392 --- /dev/null +++ b/L1Trigger/Phase2L1GT/src/classes_def.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/L1Trigger/Phase2L1GT/test/gt_firmware_evaluation.py b/L1Trigger/Phase2L1GT/test/gt_firmware_evaluation.py new file mode 100644 index 0000000000000..9878d970a4a76 --- /dev/null +++ b/L1Trigger/Phase2L1GT/test/gt_firmware_evaluation.py @@ -0,0 +1,827 @@ +import FWCore.ParameterSet.VarParsing as VarParsing +import FWCore.ParameterSet.Config as cms + +process = cms.Process('L1Test') + +# import of standard configurations +process.load('Configuration.StandardSequences.Services_cff') + + +# Input source +process.source = cms.Source("EmptySource") +process.maxEvents = cms.untracked.PSet(input=cms.untracked.int32(72)) + +options = VarParsing.VarParsing() +options.register ("platform", + "VU9P", + VarParsing.VarParsing.multiplicity.singleton, + VarParsing.VarParsing.varType.string) +options.parseArguments() + + +process.l1tGTProducer = cms.EDProducer( + "L1GTEvaluationProducer", + outputFilename=cms.string("inputPattern"), + random_seed=cms.uint32(0), + maxLines=cms.uint32(1024), + platform=cms.string(options.platform) +) + +process.l1t_GTProducer = cms.Path(process.l1tGTProducer) + +from L1Trigger.Phase2L1GT.l1tGTSingleInOutLUT import COSH_ETA_LUT, COSH_ETA_LUT_2, COS_PHI_LUT + +COSH_ETA_LUT.export("coshEtaLUT.mem") +COSH_ETA_LUT_2.export("coshEtaLUT2.mem") +COS_PHI_LUT.export("cosPhiLUT.mem") + +from L1Trigger.Phase2L1GT.l1tGTSingleObjectCond_cfi import l1tGTSingleObjectCond +from L1Trigger.Phase2L1GT.l1tGTDoubleObjectCond_cfi import l1tGTDoubleObjectCond +from L1Trigger.Phase2L1GT.l1tGTTripleObjectCond_cfi import l1tGTTripleObjectCond +from L1Trigger.Phase2L1GT.l1tGTQuadObjectCond_cfi import l1tGTQuadObjectCond + +l1tGTDoubleObjectCond.sanity_checks = cms.untracked.bool(True) +l1tGTDoubleObjectCond.inv_mass_checks = cms.untracked.bool(True) + +l1tGTTripleObjectCond.sanity_checks = cms.untracked.bool(True) +l1tGTTripleObjectCond.inv_mass_checks = cms.untracked.bool(True) + +l1tGTQuadObjectCond.sanity_checks = cms.untracked.bool(True) +l1tGTQuadObjectCond.inv_mass_checks = cms.untracked.bool(True) + +# Conditions + +process._singleTkMu_14_er2p3 = l1tGTSingleObjectCond.clone( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(14), + minEta=cms.double(-2.3), + maxEta=cms.double(2.3), +) + +process._doubleJet_3_9_dEta_Max1p6_OS = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GCTJets"), + minPt=cms.double(3), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GCTJets"), + minPt=cms.double(9), + ), + maxDEta=cms.double(1.6), +) + +process._doubleTau_5_9_q2_4_SS = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Taus"), + minPt=cms.double(5), + # qual=cms.double(2), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Taus"), + minPt=cms.double(9), + # qual=cms.double(4), + ), + ss=cms.bool(True), +) + +process._doubleMu_11_9_q2_4 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTSaPromptMuons"), + minPt=cms.double(11), + # qual_cut=cms.double(2), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTSaPromptMuons"), + minPt=cms.double(9), + # qual_cut=cms.double(4), + ), +) + +process._doubleMuEl_11_9_q2_4_OS = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTSaPromptMuons"), + minPt=cms.double(11), + # qual_cut=cms.double(2), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Electrons"), + minPt=cms.double(9), + # qual_cut=cms.double(4), + ), + os=cms.bool(True), +) + +process._doubleMu_11_9_combPt_19 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(11), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(9), + ), + minCombPt=cms.double(19) +) + +process._doubleMuEl_11_9_SS = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(11), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Electrons"), + minPt=cms.double(9), + ), + ss=cms.bool(True), +) + +process._doubleJetGamma_11_9_pr_0p2to1p8_1to3 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GCTIsoEg"), + minPt=cms.double(11), + minPhi=cms.double(0.2), + maxPhi=cms.double(1.8), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GCTJets"), + minPt=cms.double(9), + minPhi=cms.double(1), + maxPhi=cms.double(3), + ), +) + +process._doubleMuTau_2_9_er_1to3_3to3p3 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTSaPromptMuons"), + minPt=cms.double(2), + minEta=cms.double(1), + maxEta=cms.double(3), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Taus"), + minPt=cms.double(9), + minEta=cms.double(3), + maxEta=cms.double(3.3), + ), +) + +process._doubleMuEl_2_9_dEtaMin2 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTSaPromptMuons"), + minPt=cms.double(2), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Electrons"), + minPt=cms.double(9), + ), + minDEta=cms.double(2), +) + +process._doubleElGamma_2_9_dPhiMin2 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GCTIsoEg"), + minPt=cms.double(2), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Taus"), + minPt=cms.double(9), + ), + minDPhi=cms.double(2), +) + +process._doubleMuEl_2_9_dRMin2 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTSaPromptMuons"), + minPt=cms.double(2), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Electrons"), + minPt=cms.double(9), + ), + minDR=cms.double(2), +) + +process._doubleElTau_2_9_dEta0p2to2 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GCTTaus"), + minPt=cms.double(2), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Electrons"), + minPt=cms.double(9), + ), + minDEta=cms.double(0.2), + maxDEta=cms.double(2), +) + +process._doubleMuJet_2_9_dPhi2to4 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTSaPromptMuons"), + minPt=cms.double(2), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GCTJets"), + minPt=cms.double(9), + ), + minDPhi=cms.double(2), + maxDPhi=cms.double(4), +) + +process._doubleMuEl_2_9_dR1to3 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTSaPromptMuons"), + minPt=cms.double(2), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Photons"), + minPt=cms.double(9), + ), + minDR=cms.double(1), + maxDR=cms.double(3), +) + +process._doubleMuGamma_11_9_massMax10 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTSaPromptMuons"), + minPt=cms.double(11), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Photons"), + minPt=cms.double(9), + ), + maxInvMass=cms.double(10), +) + +process._doubleElMu_11_9_mass10to600 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Electrons"), + minPt=cms.double(11), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTSaPromptMuons"), + minPt=cms.double(9), + ), + minInvMass=cms.double(10), + maxInvMass=cms.double(600), +) + +process._doubleTkMu_15_7_er2p4_dzMax1p0 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(15), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + maxZ0=cms.double(1.0), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(7), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + maxZ0=cms.double(1.0), + ), +) + +process._tkIsoEleStaEG_22_12_er2p4 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GCTIsoEg"), + minPt=cms.double(22), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GCTNonIsoEg"), + minPt=cms.double(12), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + ), +) + +process._doubleTkEle_25_12_er2p4 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GCTNonIsoEg"), + minPt=cms.double(25), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GCTNonIsoEg"), + minPt=cms.double(12), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + ), +) + +process._doubleStaEG_37_24_er2p4 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GTTBsCandidates"), + minPt=cms.double(37), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GTTBsCandidates"), + minPt=cms.double(24), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + ), +) + +process._doubleTkIsoPhoton_22_12_er2p4 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GCTIsoEg"), + minPt=cms.double(22), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GCTIsoEg"), + minPt=cms.double(12), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + ), +) + +process._doubleCaloTau_69_69_er2p1_drMin0p5 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GCTTaus"), + minPt=cms.double(69), + minEta=cms.double(-2.1), + maxEta=cms.double(2.1), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GCTTaus"), + minPt=cms.double(69), + minEta=cms.double(-2.1), + maxEta=cms.double(2.1), + ), + minDR=cms.double(0.5), +) + +process._doubleCaloTau_90_90_er2p1_drMin0p5 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GCTTaus"), + minPt=cms.double(90), + minEta=cms.double(-2.1), + maxEta=cms.double(2.1), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GCTTaus"), + minPt=cms.double(90), + minEta=cms.double(-2.1), + maxEta=cms.double(2.1), + ), + minDR=cms.double(0.5), +) + +process._doublePUPPITau_36_36_er2p1_drMin0p5 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Taus"), + minPt=cms.double(36), + minEta=cms.double(-2.1), + maxEta=cms.double(2.1), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Taus"), + minPt=cms.double(36), + minEta=cms.double(-2.1), + maxEta=cms.double(2.1), + ), + minDR=cms.double(0.5), +) + +process._doublePUPPITau_52_52_er2p1_drMin0p5 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Taus"), + minPt=cms.double(52), + minEta=cms.double(-2.1), + maxEta=cms.double(2.1), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Taus"), + minPt=cms.double(52), + minEta=cms.double(-2.1), + maxEta=cms.double(2.1), + ), + minDR=cms.double(0.5), +) + +process._doublePUPPIJet_112_112_er2p4_dEtaMax1p6 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Jets"), + minPt=cms.double(112), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Jets"), + minPt=cms.double(112), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + ), + maxDEta=cms.double(1.6), +) + +process._tkMuonTkIsoEle_7_20_er2p4_dzMax1p0 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTSaPromptMuons"), + minPt=cms.double(7), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + maxZ0=cms.double(1.0), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Electrons"), + minPt=cms.double(20), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + maxZ0=cms.double(1.0), + ), +) + +process._tkMuonTkEle_7_23_er2p4_dzMax1p0 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(7), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + maxZ0=cms.double(1.0), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Electrons"), + minPt=cms.double(23), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + maxZ0=cms.double(1.0), + ), +) + +process._tkEleTkMuon_10_20_er2p4_dzMax1p0 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Electrons"), + minPt=cms.double(10), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + maxZ0=cms.double(1.0), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(20), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + maxZ0=cms.double(1.0), + ), +) + +process._puppiTauTkMuon_27_18_er2p1_dzMax1p0 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Taus"), + minPt=cms.double(27), + minEta=cms.double(-2.1), + maxEta=cms.double(2.1), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTSaPromptMuons"), + minPt=cms.double(18), + minEta=cms.double(-2.1), + maxEta=cms.double(2.1), + minZ0=cms.double(-1.0), + maxZ0=cms.double(1.0), + ), +) + +process._puppiTauTkMuon_36_18_er2p1_dzMax1p0 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Taus"), + minPt=cms.double(36), + minEta=cms.double(-2.1), + maxEta=cms.double(2.1), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTSaPromptMuons"), + minPt=cms.double(18), + minEta=cms.double(-2.1), + maxEta=cms.double(2.1), + minZ0=cms.double(-1.0), + maxZ0=cms.double(1.0), + ), +) + +process._tkIsoElePUPPItau_22_29_er2p1_drMin0p3_dzMax1p0 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Electrons"), + minPt=cms.double(22), + minEta=cms.double(-2.1), + maxEta=cms.double(2.1), + minZ0=cms.double(-1.0), + maxZ0=cms.double(1.0), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Taus"), + minPt=cms.double(29), + minEta=cms.double(-2.1), + maxEta=cms.double(2.1), + ), + minDR=cms.double(0.3), +) + +process._tkIsoElePUPPItau_22_39_er2p1_drMin0p3_dzMax1p0 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Electrons"), + minPt=cms.double(22), + minEta=cms.double(-2.1), + maxEta=cms.double(2.1), + minZ0=cms.double(-1.0), + maxZ0=cms.double(1.0), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Taus"), + minPt=cms.double(39), + minEta=cms.double(-2.1), + maxEta=cms.double(2.1), + ), + minDR=cms.double(0.3), +) + +process._tkElePUPPIJet_28_40_er2p1_er2p4_dRmin0p3_dzMax1p0 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Electrons"), + minPt=cms.double(28), + minEta=cms.double(-2.1), + maxEta=cms.double(2.1), + maxZ0=cms.double(1.0), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GTTPromptJets"), + minPt=cms.double(40), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + maxZ0=cms.double(1.0), + ), + minDR=cms.double(0.3), +) + +process._doublePuppiJet_160_35_er5p0_massMin620 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Jets"), + minPt=cms.double(160), + minEta=cms.double(-5), + maxEta=cms.double(5), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Jets"), + minPt=cms.double(35), + minEta=cms.double(-5), + maxEta=cms.double(5), + ), + minInvMass=cms.double(620), +) + +process._doubleTkMuon_2_2_er1p5_drMax1p4_OS_dzMax1p0 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(2), + minEta=cms.double(-1.5), + maxEta=cms.double(1.5), + maxZ0=cms.double(1.0), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(2), + minEta=cms.double(-1.5), + maxEta=cms.double(1.5), + maxZ0=cms.double(1.0), + ), + maxDR=cms.double(1.4), + os=cms.bool(True), +) + +process._doubleTkMuon_4_4_er2p4_drMax1p2_OS_dzMax1p0 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(4), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + maxZ0=cms.double(1.0), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(4), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + maxZ0=cms.double(1.0), + ), + maxDR=cms.double(1.2), + os=cms.bool(True), +) + +process._doubleTkMuon_4_4_er2p0_massMin7_massMax18_OS_dzMax1p0 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(4), + minEta=cms.double(-2.0), + maxEta=cms.double(2.0), + maxZ0=cms.double(1.0), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(4), + minEta=cms.double(-2.0), + maxEta=cms.double(2.0), + maxZ0=cms.double(1.0), + ), + minInvMass=cms.double(7), + maxInvMass=cms.double(18), + os=cms.bool(True), +) + +process._doubleEG_32_32_er2p5_Mt40 = l1tGTDoubleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GCTIsoEg"), + minPt=cms.double(32), + minEta=cms.double(-2.5), + maxEta=cms.double(2.5), + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GCTIsoEg"), + minPt=cms.double(32), + minEta=cms.double(-2.5), + maxEta=cms.double(2.5), + ), + minTransMass=cms.double(40), +) + + +process._triplePuppiJet_70_50_35 = l1tGTTripleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Jets"), + minPt=cms.double(70) + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Jets"), + minPt=cms.double(50) + ), + collection3=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Jets"), + minPt=cms.double(35) + ) +) + +process._tripleTkEleTkMuPUPPIJet_30_40_25_er2p4 = l1tGTTripleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Electrons"), + minPt=cms.double(30), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4) + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(40), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4) + ), + collection3=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Jets"), + minPt=cms.double(25), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4) + ) +) + +process._tripleTkMuTkEle_7_5_5_er3p4_SS = l1tGTTripleObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(7), + minEta=cms.double(-3.4), + maxEta=cms.double(3.4) + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(5), + minEta=cms.double(-3.4), + maxEta=cms.double(3.4) + ), + collection3=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Electrons"), + minPt=cms.double(5), + minEta=cms.double(-3.4), + maxEta=cms.double(3.4) + ), + delta12=cms.PSet( + ss=cms.bool(True) + ), + delta13=cms.PSet( + ss=cms.bool(True) + ) +) + +process._quadTkMuTkEle_5_5_5_7_er3p4_SS = l1tGTQuadObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(5), + minEta=cms.double(-3.4), + maxEta=cms.double(3.4) + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(5), + minEta=cms.double(-3.4), + maxEta=cms.double(3.4) + ), + collection3=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(5), + minEta=cms.double(-3.4), + maxEta=cms.double(3.4) + ), + collection4=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Electrons"), + minPt=cms.double(7), + minEta=cms.double(-3.4), + maxEta=cms.double(3.4) + ), + delta12=cms.PSet( + ss=cms.bool(True) + ), + delta13=cms.PSet( + ss=cms.bool(True) + ), + delta14=cms.PSet( + ss=cms.bool(True) + ) +) + +process._quadTkEleTkMuPUPPIJet_30_40_25_25_er2p4 = l1tGTQuadObjectCond.clone( + collection1=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Electrons"), + minPt=cms.double(30), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4), + regionsAbsEtaLowerBounds=cms.vdouble(0,1.2,3), + regionsMinPt=cms.vdouble(12,14,15) + ), + collection2=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "GMTTkMuons"), + minPt=cms.double(40), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4) + ), + collection3=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Jets"), + minPt=cms.double(25), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4) + ), + collection4=cms.PSet( + tag=cms.InputTag("l1tGTProducer", "CL2Taus"), + minPt=cms.double(25), + minEta=cms.double(-2.4), + maxEta=cms.double(2.4) + ) +) + +algorithms = cms.VPSet() + +idx = 0 +# remove '_', since it is not allowed for module names +for filt_name in process.filters: + if filt_name[:1] != '_': + continue + new_name = filt_name.replace('_', '') + setattr(process, new_name, getattr(process, filt_name).clone()) + delattr(process, filt_name) + setattr(process, 'l1t' + filt_name, cms.Path(getattr(process, new_name))) + + algorithms.append(cms.PSet(expression = cms.string('l1t' + filt_name))) + idx += 1 + +# Algo bits +process.l1tGTAlgoBlockProducer = cms.EDProducer( + "L1GTAlgoBlockProducer", + algorithms = algorithms +) + +process.pl1tGTAlgoBlockProducer = cms.Path(process.l1tGTAlgoBlockProducer) + +if options.platform == "VU13P": + channels = cms.vuint32(46, 47) +else: + channels = cms.vuint32(32, 33) + + +process.BoardData = cms.EDAnalyzer("L1GTBoardWriter", + outputFilename = cms.string("outputPattern"), + algoBlocksTag = cms.InputTag("l1tGTAlgoBlockProducer"), + maxLines = cms.uint32(1024), + channels = channels +) + +process.l1t_BoardData = cms.EndPath(process.BoardData) + +process.output = cms.OutputModule("PoolOutputModule", + fileName = cms.untracked.string('file:test_output.root'), + outputCommands = cms.untracked.vstring('keep *'), + splitLevel = cms.untracked.int32(0) +) + +process.output_step = cms.EndPath(process.output) diff --git a/L1Trigger/Phase2L1GT/test/menu_analyzer.py b/L1Trigger/Phase2L1GT/test/menu_analyzer.py new file mode 100755 index 0000000000000..95ee25e84e5f0 --- /dev/null +++ b/L1Trigger/Phase2L1GT/test/menu_analyzer.py @@ -0,0 +1,83 @@ +import argparse +import ROOT +from DataFormats.FWLite import Events, Handle +from L1Trigger.Phase2L1GT.l1tGTScales import scale_parameter + + +def object_name(object_type): + if not hasattr(ROOT, "getObjectName"): + ROOT.gInterpreter.Declare(""" +#include "DataFormats/L1Trigger/interface/P2GTCandidate.h" +const char* getObjectName(l1t::P2GTCandidate::ObjectType objectType){ + switch(objectType) { + case l1t::P2GTCandidate::GCTNonIsoEg: return "GCTNonIsoEg"; + case l1t::P2GTCandidate::GCTIsoEg: return "GCTIsoEg"; + case l1t::P2GTCandidate::GCTJets: return "GCTJet"; + case l1t::P2GTCandidate::GCTTaus: return "GCTTau"; + case l1t::P2GTCandidate::GCTHtSum: return "GCTHtSum"; + case l1t::P2GTCandidate::GCTEtSum: return "GCTEtSum"; + case l1t::P2GTCandidate::GMTSaPromptMuons: return "GMTSaPromptMuon"; + case l1t::P2GTCandidate::GMTSaDisplacedMuons: return "GMTSaDisplacedMuon"; + case l1t::P2GTCandidate::GMTTkMuons: return "GMTTkMuon"; + case l1t::P2GTCandidate::GMTTopo: return "GMTTopo"; + case l1t::P2GTCandidate::GTTPromptJets: return "GTTPromptJet"; + case l1t::P2GTCandidate::GTTDisplacedJets: return "GTTDisplacedJet"; + case l1t::P2GTCandidate::GTTPhiCandidates: return "GTTPhiCandidate"; + case l1t::P2GTCandidate::GTTRhoCandidates: return "GTTRhoCandidate"; + case l1t::P2GTCandidate::GTTBsCandidates: return "GTTBsCandidate"; + case l1t::P2GTCandidate::GTTHadronicTaus: return "GTTHadronicTau"; + case l1t::P2GTCandidate::GTTPrimaryVert: return "GTTPrimaryVert"; + case l1t::P2GTCandidate::GTTPromptHtSum: return "GTTPromptHtSum"; + case l1t::P2GTCandidate::GTTDisplacedHtSum: return "GTTDisplacedHtSum"; + case l1t::P2GTCandidate::GTTEtSum: return "GTTEtSum"; + case l1t::P2GTCandidate::CL2Jets: return "CL2Jet"; + case l1t::P2GTCandidate::CL2Taus: return "CL2Tau"; + case l1t::P2GTCandidate::CL2Electrons: return "CL2Electron"; + case l1t::P2GTCandidate::CL2Photons: return "CL2Photon"; + case l1t::P2GTCandidate::CL2HtSum: return "CL2HtSum"; + case l1t::P2GTCandidate::CL2EtSum: return "CL2EtSum"; + default: return "Undefined"; + } +} +""") + return ROOT.getObjectName(object_type) + + +if __name__ == "__main__": + + parser = argparse.ArgumentParser(description='L1GT analyzer') + parser.add_argument('in_filename', nargs="+", help='input filename') + parser.add_argument('--prefix', '-p', default='file:', help='file prefix') + parser.add_argument('--process', '-P', default='', help='Process to analyze') + + args = parser.parse_args() + + in_filenames_with_prefix = ['{}{}'.format(args.prefix, x) for x in args.in_filename] + events = Events(in_filenames_with_prefix) + + print("number of events", events.size()) + print('*' * 80) + + for idx, event in enumerate(events): + print('Event:', idx) + + algo_blocks = Handle('l1t::P2GTAlgoBlockCollection') + event.getByLabel('l1tGTAlgoBlockProducer', '', args.process, algo_blocks) + + for algo_blk in algo_blocks.product(): + print(algo_blk.algoName(), algo_blk.decisionBeforeBxMaskAndPrescale()) + + for obj in algo_blk.trigObjects(): + if object_name(obj.objectType()) in ["CL2Electron", "CL2Photon"]: + print(" {}: pt {:3.1f} eta {:3.2f} phi {:3.2f} iso: {:3.2f} relIso: {:3.2f}".format( + object_name(obj.objectType()), obj.pt(), obj.eta(), obj.phi(), + obj.hwIso() * scale_parameter.isolation_lsb.value(), + obj.hwIso() * scale_parameter.isolation_lsb.value()/(obj.hwPT() * scale_parameter.pT_lsb.value()))) + elif "Sum" not in object_name(obj.objectType()): + print(" {}: pt {:3.1f} eta {:3.2f} phi {:3.2f}".format( + object_name(obj.objectType()), obj.pt(), obj.eta(), obj.phi())) + else: + print(" {}: pt {:3.1f} phi {:3.2f}".format( + object_name(obj.objectType()), obj.pt(), obj.phi())) + + print('*' * 80) diff --git a/L1Trigger/Phase2L1GT/test/test_GT.py b/L1Trigger/Phase2L1GT/test/test_GT.py new file mode 100644 index 0000000000000..5e6232a482fb2 --- /dev/null +++ b/L1Trigger/Phase2L1GT/test/test_GT.py @@ -0,0 +1,178 @@ +# Auto generated configuration file +# using: +# Revision: 1.19 +# Source: /local/reps/CMSSW/CMSSW/Configuration/Applications/python/ConfigBuilder.py,v +# with command line options: step1 --conditions 125X_mcRun4_realistic_v2 -n 2 --era Phase2C17I13M9 --eventcontent FEVTDEBUGHLT -s RAW2DIGI,L1TrackTrigger,L1 --datatier GEN-SIM-DIGI-RAW-MINIAOD --fileout file:test.root --customise SLHCUpgradeSimulations/Configuration/aging.customise_aging_1000,Configuration/DataProcessing/Utils.addMonitoring,L1Trigger/Configuration/customisePhase2.addHcalTriggerPrimitives,L1Trigger/Configuration/customisePhase2FEVTDEBUGHLT.customisePhase2FEVTDEBUGHLT,L1Trigger/Configuration/customisePhase2TTNoMC.customisePhase2TTNoMC --geometry Extended2026D88 --nThreads 8 --filein /store/mc/Phase2Fall22DRMiniAOD/TT_TuneCP5_14TeV-powheg-pythia8/GEN-SIM-DIGI-RAW-MINIAOD/PU200_125X_mcRun4_realistic_v2_ext1-v1/30000/000c5e5f-78f7-44ee-95fe-7b2f2c2e2312.root --mc --customise_commands=process.source.inputCommands = cms.untracked.vstring("keep *", "drop l1tPFJets_*_*_*") +import FWCore.ParameterSet.Config as cms + +from Configuration.Eras.Era_Phase2C17I13M9_cff import Phase2C17I13M9 + +process = cms.Process('L1TEmulation',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.StandardSequences.MagneticField_cff') +process.load('Configuration.StandardSequences.RawToDigi_cff') +process.load('Configuration.StandardSequences.L1TrackTrigger_cff') +process.load('Configuration.StandardSequences.SimL1Emulator_cff') +process.load('Configuration.StandardSequences.EndOfProcess_cff') +process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') + +process.source = cms.Source("PoolSource", + fileNames=cms.untracked.vstring( +'/store/mc/Phase2Fall22DRMiniAOD/TT_TuneCP5_14TeV-powheg-pythia8/GEN-SIM-DIGI-RAW-MINIAOD/PU200_125X_mcRun4_realistic_v2_ext1-v1/30001/9ac14ec7-19fe-4933-a6c6-bc873f473f67.root', +'/store/mc/Phase2Fall22DRMiniAOD/TT_TuneCP5_14TeV-powheg-pythia8/GEN-SIM-DIGI-RAW-MINIAOD/PU200_125X_mcRun4_realistic_v2_ext1-v1/30001/cf19f554-5b35-4074-b297-937986db7743.root', +'/store/mc/Phase2Fall22DRMiniAOD/TT_TuneCP5_14TeV-powheg-pythia8/GEN-SIM-DIGI-RAW-MINIAOD/PU200_125X_mcRun4_realistic_v2_ext1-v1/30001/2215647c-cacd-4c9d-a84f-646a4c11c347.root', +'/store/mc/Phase2Fall22DRMiniAOD/TT_TuneCP5_14TeV-powheg-pythia8/GEN-SIM-DIGI-RAW-MINIAOD/PU200_125X_mcRun4_realistic_v2_ext1-v1/30000/bec8fe62-c75f-459d-ba69-366fff94d3e5.root', +'/store/mc/Phase2Fall22DRMiniAOD/TT_TuneCP5_14TeV-powheg-pythia8/GEN-SIM-DIGI-RAW-MINIAOD/PU200_125X_mcRun4_realistic_v2_ext1-v1/30001/0d870582-78fd-4c25-b476-2ccd2129edc7.root', +'/store/mc/Phase2Fall22DRMiniAOD/TT_TuneCP5_14TeV-powheg-pythia8/GEN-SIM-DIGI-RAW-MINIAOD/PU200_125X_mcRun4_realistic_v2_ext1-v1/30001/b7256d6c-d4b1-4ca4-bbf1-bf0853220641.root', +'/store/mc/Phase2Fall22DRMiniAOD/TT_TuneCP5_14TeV-powheg-pythia8/GEN-SIM-DIGI-RAW-MINIAOD/PU200_125X_mcRun4_realistic_v2_ext1-v1/30000/3eaace9c-7465-4f52-94e8-b07e3b2630e8.root', +'/store/mc/Phase2Fall22DRMiniAOD/TT_TuneCP5_14TeV-powheg-pythia8/GEN-SIM-DIGI-RAW-MINIAOD/PU200_125X_mcRun4_realistic_v2_ext1-v1/30000/0f2c534d-5292-4bd3-9948-e8003583d2f6.root', +'/store/mc/Phase2Fall22DRMiniAOD/TT_TuneCP5_14TeV-powheg-pythia8/GEN-SIM-DIGI-RAW-MINIAOD/PU200_125X_mcRun4_realistic_v2_ext1-v1/30001/70c30283-78fd-44b4-8a30-60db56b3c0f9.root', +'/store/mc/Phase2Fall22DRMiniAOD/TT_TuneCP5_14TeV-powheg-pythia8/GEN-SIM-DIGI-RAW-MINIAOD/PU200_125X_mcRun4_realistic_v2_ext1-v1/30001/90196109-a57c-4df8-931d-7b42bc7b6a3e.root', + ), +) + +process.maxEvents = cms.untracked.PSet(input=cms.untracked.int32(500)) + + +process.options = cms.untracked.PSet( + FailPath = cms.untracked.vstring(), + IgnoreCompletely = cms.untracked.vstring(), + Rethrow = cms.untracked.vstring(), + SkipEvent = cms.untracked.vstring(), + accelerators = cms.untracked.vstring('*'), + allowUnscheduled = cms.obsolete.untracked.bool, + canDeleteEarly = cms.untracked.vstring(), + deleteNonConsumedUnscheduledModules = cms.untracked.bool(True), + dumpOptions = cms.untracked.bool(False), + emptyRunLumiMode = cms.obsolete.untracked.string, + eventSetup = cms.untracked.PSet( + forceNumberOfConcurrentIOVs = cms.untracked.PSet( + allowAnyLabel_=cms.required.untracked.uint32 + ), + numberOfConcurrentIOVs = cms.untracked.uint32(0) + ), + fileMode = cms.untracked.string('FULLMERGE'), + forceEventSetupCacheClearOnNewRun = cms.untracked.bool(False), + makeTriggerResults = cms.obsolete.untracked.bool, + numberOfConcurrentLuminosityBlocks = cms.untracked.uint32(0), + numberOfConcurrentRuns = cms.untracked.uint32(1), + numberOfStreams = cms.untracked.uint32(0), + numberOfThreads = cms.untracked.uint32(1), + printDependencies = cms.untracked.bool(False), + sizeOfStackForThreadsInKB = cms.optional.untracked.uint32, + throwIfIllegalParameter = cms.untracked.bool(True), + wantSummary = cms.untracked.bool(False) +) + +# Production Info +process.configurationMetadata = cms.untracked.PSet( + annotation = cms.untracked.string('step1 nevts:2'), + name = cms.untracked.string('Applications'), + version = cms.untracked.string('$Revision: 1.19 $') +) + +# Output definition + +process.FEVTDEBUGHLToutput = cms.OutputModule("PoolOutputModule", + dataset = cms.untracked.PSet( + dataTier = cms.untracked.string('GEN-SIM-DIGI-RAW-MINIAOD'), + filterName = cms.untracked.string('') + ), + fileName = cms.untracked.string('file:test.root'), + outputCommands = process.FEVTDEBUGHLTEventContent.outputCommands, + splitLevel = cms.untracked.int32(0) +) + +# Additional output definition + +# Other statements +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag = GlobalTag(process.GlobalTag, '125X_mcRun4_realistic_v2', '') + +# Path and EndPath definitions +process.raw2digi_step = cms.Path(process.RawToDigi) +process.L1TrackTrigger_step = cms.Path(process.L1TrackTrigger) +process.L1simulation_step = cms.Path(process.SimL1Emulator) +process.endjob_step = cms.EndPath(process.endOfProcess) +process.FEVTDEBUGHLToutput_step = cms.EndPath(process.FEVTDEBUGHLToutput) + + +#GT emulator +process.load('L1Trigger.Configuration.GTemulator_cff') +process.GTemulation_step = cms.Path(process.GTemulator) + +process.load('L1Trigger.Phase2L1GT.l1tGTMenu_cff') +from L1Trigger.Phase2L1GT.l1tGTAlgoBlockProducer_cff import collectAlgorithmPaths + + +process.GToutput = cms.OutputModule("PoolOutputModule", + outputCommands = cms.untracked.vstring('drop *', + #'keep *_l1ctLayer2*_*', + #'keep *_l1tLayer2EG_*_*', + #'keep *l1tLayer2EG*_*_*_L1TEmulation', + 'keep *P2GT*_*_*_L1TEmulation', + ), + fileName=cms.untracked.string("l1t_emulation.root") + ) + +process.pGToutput = cms.EndPath(process.GToutput) + + +# Schedule definition +process.schedule = cms.Schedule(process.raw2digi_step,process.L1simulation_step,process.GTemulation_step, *collectAlgorithmPaths(process), process.pGToutput, process.endjob_step) +from PhysicsTools.PatAlgos.tools.helpers import associatePatAlgosToolsTask +associatePatAlgosToolsTask(process) + +#Setup FWK for multithreaded +process.options.numberOfThreads = 8 +process.options.numberOfStreams = 0 + +# customisation of the process. + +# Automatic addition of the customisation function from SLHCUpgradeSimulations.Configuration.aging +from SLHCUpgradeSimulations.Configuration.aging import customise_aging_1000 + +#call to customisation function customise_aging_1000 imported from SLHCUpgradeSimulations.Configuration.aging +process = customise_aging_1000(process) + +# Automatic addition of the customisation function from Configuration.DataProcessing.Utils +from Configuration.DataProcessing.Utils import addMonitoring + +#call to customisation function addMonitoring imported from Configuration.DataProcessing.Utils +process = addMonitoring(process) + +# Automatic addition of the customisation function from L1Trigger.Configuration.customisePhase2 +from L1Trigger.Configuration.customisePhase2 import addHcalTriggerPrimitives + +#call to customisation function addHcalTriggerPrimitives imported from L1Trigger.Configuration.customisePhase2 +process = addHcalTriggerPrimitives(process) + +# Automatic addition of the customisation function from L1Trigger.Configuration.customisePhase2FEVTDEBUGHLT +from L1Trigger.Configuration.customisePhase2FEVTDEBUGHLT import customisePhase2FEVTDEBUGHLT + +#call to customisation function customisePhase2FEVTDEBUGHLT imported from L1Trigger.Configuration.customisePhase2FEVTDEBUGHLT +process = customisePhase2FEVTDEBUGHLT(process) + +# Automatic addition of the customisation function from L1Trigger.Configuration.customisePhase2TTNoMC +from L1Trigger.Configuration.customisePhase2TTNoMC import customisePhase2TTNoMC + +#call to customisation function customisePhase2TTNoMC imported from L1Trigger.Configuration.customisePhase2TTNoMC +process = customisePhase2TTNoMC(process) + +# End of customisation functions + + +# Customisation from command line + +process.source.inputCommands = cms.untracked.vstring("keep *", "drop l1tPFJets_*_*_*", "drop l1tTkPrimaryVertexs_L1TkPrimaryVertex_*_*") +# 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