Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TOoLLiP integration #43638

Merged
merged 13 commits into from
Mar 12, 2024
2 changes: 2 additions & 0 deletions L1Trigger/Configuration/python/L1Trigger_EventContent_cff.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ def _appendPhase2Digis(obj):
'keep *_l1tHPSPFTauProducer_*_*',
'keep *_l1tBJetProducerPuppi_*_*',
'keep *_l1tBJetProducerPuppiCorrectedEmulator_*_*',
'keep *_l1tTOoLLiPProducer_*_*',
'keep *_l1tTOoLLiPProducerCorrectedEmulator_*_*',
'keep *_TTStubsFromPhase2TrackerDigis_*_*',
'keep *_TTClustersFromPhase2TrackerDigis_*_*',
'keep *_l1tTTTracksFromExtendedTrackletEmulation_*_*',
Expand Down
4 changes: 4 additions & 0 deletions L1Trigger/Configuration/python/SimL1Emulator_cff.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion L1Trigger/Phase2L1ParticleFlow/BuildFile.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
<use name="tensorflow"/>
<use name="roottmva"/>
<use name="hls"/>
<use name="hls4mlEmulatorExtras"/>
<use name="L1METML"/>
<use name="hls4mLEmulatorExtras"/>
<use name="TOoLLiP"/>
<export>
<lib name="1"/>
</export>
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <string>
#include "PhysicsTools/TensorFlow/interface/TensorFlow.h"
#include "DataFormats/L1TParticleFlow/interface/PFCandidate.h"
#include "DataFormats/L1TParticleFlow/interface/PFJet.h"

//HLS4ML compiled emulator modeling
#include <string>
#include "ap_fixed.h"
#include "hls4ml/emulator.h"

struct BJetTFCache {
BJetTFCache(const std::string &graphPath) : graphDef(tensorflow::loadGraphDef(graphPath)) {
session = tensorflow::createSession(graphDef.get());
Expand All @@ -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<hls4mlEmulator::Model> 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<float> NNvectorVar_;
Expand All @@ -38,5 +49,6 @@ class BJetId {
unique_ptr<float[]> fDX_;
unique_ptr<float[]> fDY_;
tensorflow::Session *sessionRef_;
std::shared_ptr<hls4mlEmulator::Model> modelRef_;
};
#endif
6 changes: 3 additions & 3 deletions L1Trigger/Phase2L1ParticleFlow/plugins/L1BJetProducer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -28,7 +28,7 @@ class L1BJetProducer : public edm::stream::EDProducer<edm::GlobalCache<BJetTFCac
static void globalEndJob(const BJetTFCache*);

private:
std::unique_ptr<BJetId> fBJetId_;
std::unique_ptr<JetId> fBJetId_;
void produce(edm::Event& iEvent, const edm::EventSetup& iSetup) override;

edm::EDGetTokenT<edm::View<l1t::PFJet>> const jets_;
Expand All @@ -48,7 +48,7 @@ L1BJetProducer::L1BJetProducer(const edm::ParameterSet& cfg, const BJetTFCache*
fMaxJets_(cfg.getParameter<int>("maxJets")),
fNParticles_(cfg.getParameter<int>("nParticles")),
fVtxEmu_(consumes<std::vector<l1t::VertexWord>>(cfg.getParameter<edm::InputTag>("vtx"))) {
fBJetId_ = std::make_unique<BJetId>(
fBJetId_ = std::make_unique<JetId>(
cfg.getParameter<std::string>("NNInput"), cfg.getParameter<std::string>("NNOutput"), cache, fNParticles_);
produces<edm::ValueMap<float>>("L1PFBJets");
}
Expand Down
112 changes: 112 additions & 0 deletions L1Trigger/Phase2L1ParticleFlow/plugins/TOoLLiPProducer.cc
Original file line number Diff line number Diff line change
@@ -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 <cmath>
#include <vector>

#include <string>
#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<JetId> fJetId_;
void produce(edm::Event& iEvent, const edm::EventSetup& iSetup) override;

edm::EDGetTokenT<edm::View<l1t::PFJet>> const jets_;
bool const fUseRawPt_;
double const fMinPt_;
double const fMaxEta_;
unsigned int const fMaxJets_;
int const fNParticles_;
edm::EDGetTokenT<std::vector<l1t::VertexWord>> const fVtxEmu_;

hls4mlEmulator::ModelLoader loader;
std::shared_ptr<hls4mlEmulator::Model> model;
};

TOoLLiPProducer::TOoLLiPProducer(const edm::ParameterSet& cfg)
: jets_(consumes<edm::View<l1t::PFJet>>(cfg.getParameter<edm::InputTag>("jets"))),
fUseRawPt_(cfg.getParameter<bool>("useRawPt")),
fMinPt_(cfg.getParameter<double>("minPt")),
fMaxEta_(cfg.getParameter<double>("maxEta")),
fMaxJets_(cfg.getParameter<int>("maxJets")),
fNParticles_(cfg.getParameter<int>("nParticles")),
fVtxEmu_(consumes<std::vector<l1t::VertexWord>>(cfg.getParameter<edm::InputTag>("vtx"))),
loader(hls4mlEmulator::ModelLoader(cfg.getParameter<string>("TOoLLiPVersion"))) {
model = loader.load_model();
fJetId_ = std::make_unique<JetId>(
cfg.getParameter<std::string>("NNInput"), cfg.getParameter<std::string>("NNOutput"), model, fNParticles_);
produces<edm::ValueMap<float>>("L1PFLLPJets");
}

void TOoLLiPProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
edm::Handle<edm::View<l1t::PFJet>> jets;
iEvent.getByToken(jets_, jets);
float vz = 0.;
double ptsum = 0;
edm::Handle<std::vector<l1t::VertexWord>> vtxEmuHandle;
iEvent.getByToken(fVtxEmu_, vtxEmuHandle);
for (const auto& vtx : *vtxEmuHandle) {
if (ptsum == 0 || vtx.pt() > ptsum) {
ptsum = vtx.pt();
vz = vtx.z0();
}
}

std::vector<float> 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<float>>();
edm::ValueMap<float>::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<edm::InputTag>("jets", edm::InputTag("scPFL1Puppi"));
desc.add<bool>("useRawPt", true);
desc.add<std::string>("TOoLLiPVersion", std::string("TOoLLiP_v1"));
desc.add<std::string>("NNInput", "input:0");
desc.add<std::string>("NNOutput", "sequential/dense_2/Sigmoid");
desc.add<int>("maxJets", 10);
desc.add<int>("nParticles", 10);
desc.add<double>("minPt", 20);
desc.add<double>("maxEta", 2.4);
desc.add<edm::InputTag>("vtx", edm::InputTag("L1VertexFinderEmulator", "L1VerticesEmulation"));
descriptions.add("TOoLLiPProducer", desc);
}

#include "FWCore/Framework/interface/MakerMacros.h"
DEFINE_FWK_MODULE(TOoLLiPProducer);
20 changes: 20 additions & 0 deletions L1Trigger/Phase2L1ParticleFlow/python/TOoLLiPProducer_cff.py
Original file line number Diff line number Diff line change
@@ -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
)
Original file line number Diff line number Diff line change
@@ -1,8 +1,29 @@
#include "L1Trigger/Phase2L1ParticleFlow/interface/BJetId.h"
#include "L1Trigger/Phase2L1ParticleFlow/interface/JetId.h"
#include "DataFormats/Math/interface/deltaPhi.h"
#include <cmath>

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<hls4mlEmulator::Model> model,
int iNParticles)
: modelRef_(model) {
NNvectorVar_.clear();
fNParticles_ = iNParticles;

fPt_ = std::make_unique<float[]>(fNParticles_);
fEta_ = std::make_unique<float[]>(fNParticles_);
fPhi_ = std::make_unique<float[]>(fNParticles_);
fId_ = std::make_unique<float[]>(fNParticles_);
fCharge_ = std::make_unique<int[]>(fNParticles_);
fDZ_ = std::make_unique<float[]>(fNParticles_);
fDX_ = std::make_unique<float[]>(fNParticles_);
fDY_ = std::make_unique<float[]>(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;
Expand All @@ -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) {
Expand All @@ -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<float, 3>()(0, i, 0) = float(NNvectorVar_[i]);
Expand All @@ -53,7 +73,21 @@ float BJetId::EvaluateNN() {
return outputs[0].matrix<float>()(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;
Expand Down Expand Up @@ -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<l1t::PFCandidate> i, edm::Ptr<l1t::PFCandidate> 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();
}