diff --git a/L1Trigger/Configuration/python/L1Trigger_EventContent_cff.py b/L1Trigger/Configuration/python/L1Trigger_EventContent_cff.py
index 17ee0b32aa165..bd302c7951555 100644
--- a/L1Trigger/Configuration/python/L1Trigger_EventContent_cff.py
+++ b/L1Trigger/Configuration/python/L1Trigger_EventContent_cff.py
@@ -227,6 +227,8 @@ def _appendPhase2Digis(obj):
'keep *_l1tHPSPFTauProducer_*_*',
'keep *_l1tBJetProducerPuppi_*_*',
'keep *_l1tBJetProducerPuppiCorrectedEmulator_*_*',
+ 'keep *_l1tTOoLLiPProducer_*_*',
+ 'keep *_l1tTOoLLiPProducerCorrectedEmulator_*_*',
'keep *_TTStubsFromPhase2TrackerDigis_*_*',
'keep *_TTClustersFromPhase2TrackerDigis_*_*',
'keep *_l1tTTTracksFromExtendedTrackletEmulation_*_*',
diff --git a/L1Trigger/Configuration/python/SimL1Emulator_cff.py b/L1Trigger/Configuration/python/SimL1Emulator_cff.py
index 91bd0ba2e181a..6136c3cc49919 100644
--- a/L1Trigger/Configuration/python/SimL1Emulator_cff.py
+++ b/L1Trigger/Configuration/python/SimL1Emulator_cff.py
@@ -244,6 +244,10 @@
from L1Trigger.Phase2L1ParticleFlow.L1BJetProducer_cff import *
_phase2_siml1emulator.add(L1TBJetsTask)
+# LLPJets
+# ########################################################################
+from L1Trigger.Phase2L1ParticleFlow.TOoLLiPProducer_cff import *
+_phase2_siml1emulator.add(L1TTOoLLiPTask)
# --> add modules
from Configuration.Eras.Modifier_phase2_trigger_cff import phase2_trigger
diff --git a/L1Trigger/Phase2L1ParticleFlow/BuildFile.xml b/L1Trigger/Phase2L1ParticleFlow/BuildFile.xml
index 9c3b1442767df..e45b710a713f9 100644
--- a/L1Trigger/Phase2L1ParticleFlow/BuildFile.xml
+++ b/L1Trigger/Phase2L1ParticleFlow/BuildFile.xml
@@ -13,8 +13,9 @@
-
+
+
diff --git a/L1Trigger/Phase2L1ParticleFlow/interface/BJetId.h b/L1Trigger/Phase2L1ParticleFlow/interface/JetId.h
similarity index 60%
rename from L1Trigger/Phase2L1ParticleFlow/interface/BJetId.h
rename to L1Trigger/Phase2L1ParticleFlow/interface/JetId.h
index cffbafce13e9c..8dd4d14a7afcf 100644
--- a/L1Trigger/Phase2L1ParticleFlow/interface/BJetId.h
+++ b/L1Trigger/Phase2L1ParticleFlow/interface/JetId.h
@@ -1,11 +1,16 @@
-#ifndef L1TRIGGER_PHASE2L1PARTICLEFLOWS_BJETID_H
-#define L1TRIGGER_PHASE2L1PARTICLEFLOWS_BJETID_H
+#ifndef L1TRIGGER_PHASE2L1PARTICLEFLOWS_JETID_H
+#define L1TRIGGER_PHASE2L1PARTICLEFLOWS_JETID_H
#include
#include "PhysicsTools/TensorFlow/interface/TensorFlow.h"
#include "DataFormats/L1TParticleFlow/interface/PFCandidate.h"
#include "DataFormats/L1TParticleFlow/interface/PFJet.h"
+//HLS4ML compiled emulator modeling
+#include
+#include "ap_fixed.h"
+#include "hls4ml/emulator.h"
+
struct BJetTFCache {
BJetTFCache(const std::string &graphPath) : graphDef(tensorflow::loadGraphDef(graphPath)) {
session = tensorflow::createSession(graphDef.get());
@@ -15,14 +20,20 @@ struct BJetTFCache {
tensorflow::Session *session;
};
-class BJetId {
+class JetId {
public:
- BJetId(const std::string &iInput, const std::string &iOutput, const BJetTFCache *cache, int iNParticles);
- ~BJetId();
+ JetId(const std::string &iInput,
+ const std::string &iOutput,
+ const std::shared_ptr model,
+ int iNParticles);
+ JetId(const std::string &iInput, const std::string &iOutput, const BJetTFCache *cache, int iNParticles);
+ ~JetId() = default;
void setNNVectorVar();
float EvaluateNN();
+ ap_fixed<16, 6> EvaluateNNFixed();
float compute(const l1t::PFJet &iJet, float vz, bool useRawPt);
+ ap_fixed<16, 6> computeFixed(const l1t::PFJet &iJet, float vz, bool useRawPt);
private:
std::vector NNvectorVar_;
@@ -38,5 +49,6 @@ class BJetId {
unique_ptr fDX_;
unique_ptr fDY_;
tensorflow::Session *sessionRef_;
+ std::shared_ptr modelRef_;
};
#endif
diff --git a/L1Trigger/Phase2L1ParticleFlow/plugins/L1BJetProducer.cc b/L1Trigger/Phase2L1ParticleFlow/plugins/L1BJetProducer.cc
index 3db89a84a276e..f3a160a36a769 100644
--- a/L1Trigger/Phase2L1ParticleFlow/plugins/L1BJetProducer.cc
+++ b/L1Trigger/Phase2L1ParticleFlow/plugins/L1BJetProducer.cc
@@ -8,7 +8,7 @@
#include "DataFormats/L1TParticleFlow/interface/PFJet.h"
#include "DataFormats/JetReco/interface/Jet.h"
#include "DataFormats/L1TParticleFlow/interface/PFCandidate.h"
-#include "L1Trigger/Phase2L1ParticleFlow/interface/BJetId.h"
+#include "L1Trigger/Phase2L1ParticleFlow/interface/JetId.h"
#include "DataFormats/Common/interface/ValueMap.h"
#include "DataFormats/L1Trigger/interface/VertexWord.h"
@@ -28,7 +28,7 @@ class L1BJetProducer : public edm::stream::EDProducer fBJetId_;
+ std::unique_ptr fBJetId_;
void produce(edm::Event& iEvent, const edm::EventSetup& iSetup) override;
edm::EDGetTokenT> const jets_;
@@ -48,7 +48,7 @@ L1BJetProducer::L1BJetProducer(const edm::ParameterSet& cfg, const BJetTFCache*
fMaxJets_(cfg.getParameter("maxJets")),
fNParticles_(cfg.getParameter("nParticles")),
fVtxEmu_(consumes>(cfg.getParameter("vtx"))) {
- fBJetId_ = std::make_unique(
+ fBJetId_ = std::make_unique(
cfg.getParameter("NNInput"), cfg.getParameter("NNOutput"), cache, fNParticles_);
produces>("L1PFBJets");
}
diff --git a/L1Trigger/Phase2L1ParticleFlow/plugins/TOoLLiPProducer.cc b/L1Trigger/Phase2L1ParticleFlow/plugins/TOoLLiPProducer.cc
new file mode 100644
index 0000000000000..e33ff7040865a
--- /dev/null
+++ b/L1Trigger/Phase2L1ParticleFlow/plugins/TOoLLiPProducer.cc
@@ -0,0 +1,112 @@
+#include "FWCore/Framework/interface/Frameworkfwd.h"
+#include "FWCore/Framework/interface/stream/EDProducer.h"
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/MakerMacros.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/Utilities/interface/InputTag.h"
+
+#include "DataFormats/L1TParticleFlow/interface/PFJet.h"
+#include "DataFormats/JetReco/interface/Jet.h"
+#include "DataFormats/L1TParticleFlow/interface/PFCandidate.h"
+#include "L1Trigger/Phase2L1ParticleFlow/interface/JetId.h"
+#include "DataFormats/Common/interface/ValueMap.h"
+
+#include "DataFormats/L1Trigger/interface/VertexWord.h"
+
+#include
+#include
+
+#include
+#include "ap_fixed.h"
+#include "hls4ml/emulator.h"
+
+using namespace l1t;
+
+class TOoLLiPProducer : public edm::stream::EDProducer<> {
+public:
+ explicit TOoLLiPProducer(const edm::ParameterSet&);
+ ~TOoLLiPProducer() override = default;
+
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
+
+private:
+ std::unique_ptr fJetId_;
+ void produce(edm::Event& iEvent, const edm::EventSetup& iSetup) override;
+
+ edm::EDGetTokenT> const jets_;
+ bool const fUseRawPt_;
+ double const fMinPt_;
+ double const fMaxEta_;
+ unsigned int const fMaxJets_;
+ int const fNParticles_;
+ edm::EDGetTokenT> const fVtxEmu_;
+
+ hls4mlEmulator::ModelLoader loader;
+ std::shared_ptr model;
+};
+
+TOoLLiPProducer::TOoLLiPProducer(const edm::ParameterSet& cfg)
+ : jets_(consumes>(cfg.getParameter("jets"))),
+ fUseRawPt_(cfg.getParameter("useRawPt")),
+ fMinPt_(cfg.getParameter("minPt")),
+ fMaxEta_(cfg.getParameter("maxEta")),
+ fMaxJets_(cfg.getParameter("maxJets")),
+ fNParticles_(cfg.getParameter("nParticles")),
+ fVtxEmu_(consumes>(cfg.getParameter("vtx"))),
+ loader(hls4mlEmulator::ModelLoader(cfg.getParameter("TOoLLiPVersion"))) {
+ model = loader.load_model();
+ fJetId_ = std::make_unique(
+ cfg.getParameter("NNInput"), cfg.getParameter("NNOutput"), model, fNParticles_);
+ produces>("L1PFLLPJets");
+}
+
+void TOoLLiPProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
+ edm::Handle> jets;
+ iEvent.getByToken(jets_, jets);
+ float vz = 0.;
+ double ptsum = 0;
+ edm::Handle> vtxEmuHandle;
+ iEvent.getByToken(fVtxEmu_, vtxEmuHandle);
+ for (const auto& vtx : *vtxEmuHandle) {
+ if (ptsum == 0 || vtx.pt() > ptsum) {
+ ptsum = vtx.pt();
+ vz = vtx.z0();
+ }
+ }
+
+ std::vector LLPScores;
+ for (const auto& srcjet : *jets) {
+ if (((fUseRawPt_ ? srcjet.rawPt() : srcjet.pt()) < fMinPt_) || std::abs(srcjet.eta()) > fMaxEta_ ||
+ LLPScores.size() >= fMaxJets_) {
+ LLPScores.push_back(-1.);
+ continue;
+ }
+ ap_fixed<16, 6> LLPScore = fJetId_->computeFixed(srcjet, vz, fUseRawPt_);
+ LLPScores.push_back(LLPScore);
+ }
+
+ auto outT = std::make_unique>();
+ edm::ValueMap::Filler fillerT(*outT);
+ fillerT.insert(jets, LLPScores.begin(), LLPScores.end());
+ fillerT.fill();
+
+ iEvent.put(std::move(outT), "L1PFLLPJets");
+}
+
+void TOoLLiPProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ edm::ParameterSetDescription desc;
+ desc.add("jets", edm::InputTag("scPFL1Puppi"));
+ desc.add("useRawPt", true);
+ desc.add("TOoLLiPVersion", std::string("TOoLLiP_v1"));
+ desc.add("NNInput", "input:0");
+ desc.add("NNOutput", "sequential/dense_2/Sigmoid");
+ desc.add("maxJets", 10);
+ desc.add("nParticles", 10);
+ desc.add("minPt", 20);
+ desc.add("maxEta", 2.4);
+ desc.add("vtx", edm::InputTag("L1VertexFinderEmulator", "L1VerticesEmulation"));
+ descriptions.add("TOoLLiPProducer", desc);
+}
+
+#include "FWCore/Framework/interface/MakerMacros.h"
+DEFINE_FWK_MODULE(TOoLLiPProducer);
diff --git a/L1Trigger/Phase2L1ParticleFlow/python/TOoLLiPProducer_cff.py b/L1Trigger/Phase2L1ParticleFlow/python/TOoLLiPProducer_cff.py
new file mode 100644
index 0000000000000..9eb1c774a8243
--- /dev/null
+++ b/L1Trigger/Phase2L1ParticleFlow/python/TOoLLiPProducer_cff.py
@@ -0,0 +1,20 @@
+import FWCore.ParameterSet.Config as cms
+
+from L1Trigger.Phase2L1ParticleFlow.l1pfJetMet_cff import L1TPFJetsExtendedTask
+
+from L1Trigger.Phase2L1ParticleFlow.TOoLLiPProducer_cfi import TOoLLiPProducer
+l1tTOoLLiPProducer = TOoLLiPProducer.clone(
+ jets = ("l1tSC4PFL1PuppiExtended", ""),
+ maxJets = 6,
+ minPt = 10,
+ vtx = ("l1tVertexFinderEmulator","L1VerticesEmulation")
+)
+
+
+l1tTOoLLiPProducerCorrectedEmulator = l1tTOoLLiPProducer.clone(
+ jets = ("l1tSC4PFL1PuppiExtendedCorrectedEmulator", "")
+)
+
+L1TTOoLLiPTask = cms.Task(
+ L1TPFJetsExtendedTask, l1tTOoLLiPProducer, l1tTOoLLiPProducerCorrectedEmulator
+)
diff --git a/L1Trigger/Phase2L1ParticleFlow/src/BJetId.cc b/L1Trigger/Phase2L1ParticleFlow/src/JetId.cc
similarity index 58%
rename from L1Trigger/Phase2L1ParticleFlow/src/BJetId.cc
rename to L1Trigger/Phase2L1ParticleFlow/src/JetId.cc
index eaf8087bf85e6..3692ad912c6d0 100644
--- a/L1Trigger/Phase2L1ParticleFlow/src/BJetId.cc
+++ b/L1Trigger/Phase2L1ParticleFlow/src/JetId.cc
@@ -1,8 +1,29 @@
-#include "L1Trigger/Phase2L1ParticleFlow/interface/BJetId.h"
+#include "L1Trigger/Phase2L1ParticleFlow/interface/JetId.h"
#include "DataFormats/Math/interface/deltaPhi.h"
#include
-BJetId::BJetId(const std::string &iInput, const std::string &iOutput, const BJetTFCache *cache, int iNParticles)
+JetId::JetId(const std::string &iInput,
+ const std::string &iOutput,
+ const std::shared_ptr model,
+ int iNParticles)
+ : modelRef_(model) {
+ NNvectorVar_.clear();
+ fNParticles_ = iNParticles;
+
+ fPt_ = std::make_unique(fNParticles_);
+ fEta_ = std::make_unique(fNParticles_);
+ fPhi_ = std::make_unique(fNParticles_);
+ fId_ = std::make_unique(fNParticles_);
+ fCharge_ = std::make_unique(fNParticles_);
+ fDZ_ = std::make_unique(fNParticles_);
+ fDX_ = std::make_unique(fNParticles_);
+ fDY_ = std::make_unique(fNParticles_);
+ fInput_ = iInput;
+ fOutput_ = iOutput;
+}
+
+//--BJet algo specific constructor
+JetId::JetId(const std::string &iInput, const std::string &iOutput, const BJetTFCache *cache, int iNParticles)
: sessionRef_(cache->session) {
NNvectorVar_.clear();
fNParticles_ = iNParticles;
@@ -19,8 +40,7 @@ BJetId::BJetId(const std::string &iInput, const std::string &iOutput, const BJet
fOutput_ = iOutput;
}
-BJetId::~BJetId() {}
-void BJetId::setNNVectorVar() {
+void JetId::setNNVectorVar() {
NNvectorVar_.clear();
for (int i0 = 0; i0 < fNParticles_; i0++) {
if (fPt_.get()[i0] == 0) {
@@ -43,7 +63,7 @@ void BJetId::setNNVectorVar() {
NNvectorVar_.push_back(fPhi_.get()[i0]); //dPhi from jet axis
}
}
-float BJetId::EvaluateNN() {
+float JetId::EvaluateNN() {
tensorflow::Tensor input(tensorflow::DT_FLOAT, {1, (unsigned int)NNvectorVar_.size(), 1});
for (unsigned int i = 0; i < NNvectorVar_.size(); i++) {
input.tensor()(0, i, 0) = float(NNvectorVar_[i]);
@@ -53,7 +73,21 @@ float BJetId::EvaluateNN() {
return outputs[0].matrix()(0, 0);
} //end EvaluateNN
-float BJetId::compute(const l1t::PFJet &iJet, float vz, bool useRawPt) {
+ap_fixed<16, 6> JetId::EvaluateNNFixed() {
+ ap_fixed<16, 6> modelInput[140] = {};
+ for (unsigned int i = 0; i < NNvectorVar_.size(); i++) {
+ modelInput[i] = NNvectorVar_[i];
+ }
+ ap_fixed<16, 6> modelResult[1] = {-1};
+
+ modelRef_->prepare_input(modelInput);
+ modelRef_->predict();
+ modelRef_->read_result(modelResult);
+ ap_fixed<16, 6> modelResult_ = modelResult[0];
+ return modelResult_;
+} //end EvaluateNNFixed
+
+float JetId::compute(const l1t::PFJet &iJet, float vz, bool useRawPt) {
for (int i0 = 0; i0 < fNParticles_; i0++) {
fPt_.get()[i0] = 0;
fEta_.get()[i0] = 0;
@@ -86,3 +120,37 @@ float BJetId::compute(const l1t::PFJet &iJet, float vz, bool useRawPt) {
setNNVectorVar();
return EvaluateNN();
}
+
+ap_fixed<16, 6> JetId::computeFixed(const l1t::PFJet &iJet, float vz, bool useRawPt) {
+ for (int i0 = 0; i0 < fNParticles_; i0++) {
+ fPt_.get()[i0] = 0;
+ fEta_.get()[i0] = 0;
+ fPhi_.get()[i0] = 0;
+ fId_.get()[i0] = 0;
+ fCharge_.get()[i0] = 0;
+ fDZ_.get()[i0] = 0;
+ fDX_.get()[i0] = 0;
+ fDY_.get()[i0] = 0;
+ }
+ auto iParts = iJet.constituents();
+ std::sort(iParts.begin(), iParts.end(), [](edm::Ptr i, edm::Ptr j) {
+ return (i->pt() > j->pt());
+ });
+ float jetpt = useRawPt ? iJet.rawPt() : iJet.pt();
+ for (unsigned int i0 = 0; i0 < iParts.size(); i0++) {
+ if (i0 >= (unsigned int)fNParticles_)
+ break;
+ fPt_.get()[i0] = iParts[i0]->pt() / jetpt;
+ fEta_.get()[i0] = iParts[i0]->eta() - iJet.eta();
+ fPhi_.get()[i0] = deltaPhi(iParts[i0]->phi(), iJet.phi());
+ fId_.get()[i0] = iParts[i0]->id();
+ fCharge_.get()[i0] = iParts[i0]->charge();
+ if (iParts[i0]->pfTrack().isNonnull()) {
+ fDX_.get()[i0] = iParts[i0]->pfTrack()->vx();
+ fDY_.get()[i0] = iParts[i0]->pfTrack()->vy();
+ fDZ_.get()[i0] = iParts[i0]->pfTrack()->vz() - vz;
+ }
+ }
+ setNNVectorVar();
+ return EvaluateNNFixed();
+}