diff --git a/L1Trigger/Configuration/python/L1Trigger_EventContent_cff.py b/L1Trigger/Configuration/python/L1Trigger_EventContent_cff.py
index b27353c8b4382..dfffaad916bdb 100644
--- a/L1Trigger/Configuration/python/L1Trigger_EventContent_cff.py
+++ b/L1Trigger/Configuration/python/L1Trigger_EventContent_cff.py
@@ -196,6 +196,8 @@ def _appendPhase2Digis(obj):
'keep *_l1PFMetCalo__*',
'keep *_l1PFMetPF__*',
'keep *_l1PFMetPuppi__*',
+ 'keep *_l1NNTauProducer__*',
+ 'keep *_l1NNTauProducerPuppi__*',
]
obj.outputCommands += l1Phase2Digis
diff --git a/L1Trigger/Configuration/python/SimL1Emulator_cff.py b/L1Trigger/Configuration/python/SimL1Emulator_cff.py
index 24fdbe4afcf8b..f696d38f45e1b 100644
--- a/L1Trigger/Configuration/python/SimL1Emulator_cff.py
+++ b/L1Trigger/Configuration/python/SimL1Emulator_cff.py
@@ -132,6 +132,18 @@
l1PFMetsTask = cms.Task(l1PFMetCalo , l1PFMetPF , l1PFMetPuppi)
_phase2_siml1emulator.add(l1PFMetsTask)
+# NNTaus
+# ########################################################################
+from L1Trigger.Phase2L1ParticleFlow.L1NNTauProducer_cff import *
+l1NNTauProducer = L1NNTauProducer.clone(
+ L1PFObjects = cms.InputTag("l1pfCandidates","PF")
+)
+l1NNTauProducerPuppi = L1NNTauProducerPuppi.clone(
+ L1PFObjects = cms.InputTag("l1pfCandidates","Puppi")
+)
+_phase2_siml1emulator.add(l1NNTauProducer)
+_phase2_siml1emulator.add(l1NNTauProducerPuppi)
+
# --> add modules
from Configuration.Eras.Modifier_phase2_trigger_cff import phase2_trigger
from Configuration.Eras.Modifier_phase2_trackerV14_cff import phase2_trackerV14
diff --git a/L1Trigger/Phase2L1ParticleFlow/BuildFile.xml b/L1Trigger/Phase2L1ParticleFlow/BuildFile.xml
index 80c5ef5582689..3d27404e3b58a 100644
--- a/L1Trigger/Phase2L1ParticleFlow/BuildFile.xml
+++ b/L1Trigger/Phase2L1ParticleFlow/BuildFile.xml
@@ -9,6 +9,8 @@
+
+
diff --git a/L1Trigger/Phase2L1ParticleFlow/interface/L1NNTauProducer.hh b/L1Trigger/Phase2L1ParticleFlow/interface/L1NNTauProducer.hh
new file mode 100644
index 0000000000000..86ba1d19edbe1
--- /dev/null
+++ b/L1Trigger/Phase2L1ParticleFlow/interface/L1NNTauProducer.hh
@@ -0,0 +1,39 @@
+#ifndef L1TRIGGER_PHASE2L1PARTICLEFLOW_L1NNTAU_H
+#define L1TRIGGER_PHASE2L1PARTICLEFLOW_L1NNTAU_H
+
+#include
+
+#include "FWCore/Framework/interface/Frameworkfwd.h"
+#include "FWCore/Framework/interface/stream/EDProducer.h"
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/MakerMacros.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+
+#include "DataFormats/L1TParticleFlow/interface/PFTau.h"
+#include "DataFormats/L1TParticleFlow/interface/PFCandidate.h"
+#include "L1Trigger/Phase2L1ParticleFlow/interface/TauNNId.h"
+
+using namespace l1t;
+
+class L1NNTauProducer : public edm::stream::EDProducer<> {
+public:
+ explicit L1NNTauProducer(const edm::ParameterSet &);
+ ~L1NNTauProducer() override;
+
+private:
+ std::unique_ptr fTauNNId_;
+ void addTau(const l1t::PFCandidate &iCand,
+ const l1t::PFCandidateCollection &iParts,
+ std::unique_ptr &outputTaus);
+ float deltaR(const l1t::PFCandidate &iPart1, const l1t::PFCandidate &iPart2);
+ void produce(edm::Event &iEvent, const edm::EventSetup &iSetup) override;
+
+ double fSeedPt_;
+ double fConeSize_;
+ double fTauSize_;
+ int fMaxTaus_;
+ int fNParticles_;
+ edm::EDGetTokenT > fL1PFToken_;
+};
+
+#endif
diff --git a/L1Trigger/Phase2L1ParticleFlow/interface/TauNNId.h b/L1Trigger/Phase2L1ParticleFlow/interface/TauNNId.h
new file mode 100644
index 0000000000000..91e81895bddcb
--- /dev/null
+++ b/L1Trigger/Phase2L1ParticleFlow/interface/TauNNId.h
@@ -0,0 +1,30 @@
+#ifndef L1TRIGGER_PHASE2L1PARTICLEFLOWS_TAUNNID_H
+#define L1TRIGGER_PHASE2L1PARTICLEFLOWS_TAUNNID_H
+
+#include
+#include "PhysicsTools/TensorFlow/interface/TensorFlow.h"
+#include "DataFormats/L1TParticleFlow/interface/PFCandidate.h"
+
+class TauNNId {
+public:
+ TauNNId();
+ ~TauNNId();
+
+ void initialize(const std::string &iName, const std::string &iWeightFile, int iNParticles);
+ void SetNNVectorVar();
+ float EvaluateNN();
+ float compute(const l1t::PFCandidate &iSeed, l1t::PFCandidateCollection &iParts);
+
+ std::string fInput_;
+ int fNParticles_;
+ unique_ptr fPt_;
+ unique_ptr fEta_;
+ unique_ptr fPhi_;
+ unique_ptr fId_;
+
+private:
+ tensorflow::Session *session_;
+ tensorflow::GraphDef *graphDef_;
+ std::vector NNvectorVar_;
+};
+#endif
diff --git a/L1Trigger/Phase2L1ParticleFlow/plugins/L1NNTauProducer.cc b/L1Trigger/Phase2L1ParticleFlow/plugins/L1NNTauProducer.cc
new file mode 100644
index 0000000000000..dfaa5b394c39d
--- /dev/null
+++ b/L1Trigger/Phase2L1ParticleFlow/plugins/L1NNTauProducer.cc
@@ -0,0 +1,112 @@
+#include "L1Trigger/Phase2L1ParticleFlow/interface/L1NNTauProducer.hh"
+#include
+#include
+
+L1NNTauProducer::L1NNTauProducer(const edm::ParameterSet& cfg)
+ : fSeedPt_(cfg.getParameter("seedpt")),
+ fConeSize_(cfg.getParameter("conesize")),
+ fTauSize_(cfg.getParameter("tausize")),
+ fMaxTaus_(cfg.getParameter("maxtaus")),
+ fNParticles_(cfg.getParameter("nparticles")),
+ fL1PFToken_(consumes >(cfg.getParameter("L1PFObjects"))) {
+ std::string lNNFile = cfg.getParameter("NNFileName"); //,"L1Trigger/Phase2L1Taus/data/tau_3layer.pb");
+ fTauNNId_ = std::make_unique();
+ if (lNNFile.find("v0") == std::string::npos)
+ fTauNNId_->initialize("input_1:0", lNNFile, fNParticles_);
+ else if (lNNFile.find("v0") != std::string::npos)
+ fTauNNId_->initialize("dense_1_input:0", lNNFile, fNParticles_);
+ produces("L1PFTausNN");
+}
+
+void L1NNTauProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
+ edm::Handle l1PFCandidates;
+ iEvent.getByToken(fL1PFToken_, l1PFCandidates);
+
+ l1t::PFCandidateCollection pfChargedHadrons;
+ l1t::PFCandidateCollection pfChargedHadrons_sort;
+ l1t::PFCandidateCollection pfChargedHadrons_seeds;
+ for (const auto& l1PFCand : *l1PFCandidates)
+ if ((l1PFCand.id() == l1t::PFCandidate::ChargedHadron || l1PFCand.id() == l1t::PFCandidate::Electron) &&
+ std::abs(l1PFCand.eta()) < 2.5)
+ pfChargedHadrons_sort.push_back(l1PFCand);
+ std::sort(pfChargedHadrons_sort.begin(), pfChargedHadrons_sort.end(), [](l1t::PFCandidate i, l1t::PFCandidate j) {
+ return (i.pt() > j.pt());
+ });
+ auto lTaus = std::make_unique();
+ if (pfChargedHadrons_sort.empty()) {
+ if (lTaus->empty()) {
+ PFTau dummy;
+ lTaus->push_back(dummy);
+ }
+ iEvent.put(std::move(lTaus), "L1PFTausNN");
+ return;
+ }
+ pfChargedHadrons_seeds.push_back(pfChargedHadrons_sort[0]);
+ for (unsigned int i0 = 1; i0 < pfChargedHadrons_sort.size(); i0++) {
+ bool pMatch = false;
+ for (unsigned int i1 = 0; i1 < pfChargedHadrons_seeds.size(); i1++) {
+ if (deltaR(pfChargedHadrons_seeds[i1], pfChargedHadrons_sort[i0]) < fConeSize_)
+ pMatch = true;
+ }
+ if (pMatch)
+ continue;
+ pfChargedHadrons_seeds.push_back(pfChargedHadrons_sort[i0]);
+ if (int(pfChargedHadrons_seeds.size()) > fMaxTaus_ - 1)
+ break;
+ }
+ for (unsigned int i0 = 0; i0 < pfChargedHadrons_seeds.size(); i0++) {
+ addTau(pfChargedHadrons_seeds[i0], (*l1PFCandidates), lTaus);
+ }
+ if (lTaus->empty()) {
+ PFTau dummy;
+ lTaus->push_back(dummy);
+ }
+ std::sort(lTaus->begin(), lTaus->end(), [](l1t::PFTau i, l1t::PFTau j) { return (i.pt() > j.pt()); });
+ iEvent.put(std::move(lTaus), "L1PFTausNN");
+}
+
+// create taus based on grid structure
+void L1NNTauProducer::addTau(const l1t::PFCandidate& iCand,
+ const l1t::PFCandidateCollection& iParts,
+ std::unique_ptr& outputTaus) {
+ l1t::PFCandidateCollection pfTauCands;
+ TLorentzVector lTot;
+ lTot.SetPtEtaPhiM(0, 0, 0, 0);
+ TLorentzVector lCand;
+ lCand.SetPtEtaPhiM(0, 0, 0, 0);
+ int lId = 0;
+ for (auto l1PFCand : iParts) {
+ if (deltaR(iCand, l1PFCand) > fConeSize_)
+ continue;
+ TLorentzVector pVec;
+ pVec.SetPtEtaPhiM(l1PFCand.pt(), l1PFCand.eta(), l1PFCand.phi(), 0);
+ lTot += pVec;
+ if (deltaR(iCand, l1PFCand) < fTauSize_ &&
+ (l1PFCand.id() == l1t::PFCandidate::Electron || l1PFCand.id() == l1t::PFCandidate::ChargedHadron ||
+ l1PFCand.id() == l1t::PFCandidate::Photon)) {
+ lId++;
+ lCand += pVec;
+ }
+ pfTauCands.push_back(l1PFCand);
+ }
+ if (lTot.Pt() < fSeedPt_)
+ return;
+ std::sort(
+ pfTauCands.begin(), pfTauCands.end(), [](l1t::PFCandidate i, l1t::PFCandidate j) { return (i.pt() > j.pt()); });
+ float NN = fTauNNId_->compute(iCand, pfTauCands);
+ math::PtEtaPhiMLorentzVector tempP4(lCand.Pt(), lCand.Eta(), lCand.Phi(), lCand.M());
+ l1t::PFTau l1PFTau(tempP4, NN, 0, lId);
+ outputTaus->push_back(l1PFTau);
+}
+float L1NNTauProducer::deltaR(const l1t::PFCandidate& iPart1, const l1t::PFCandidate& iPart2) {
+ float delta_r = 20;
+ float pDPhi = fabs(iPart1.phi() - iPart2.phi());
+ if (pDPhi > 2. * M_PI - pDPhi)
+ pDPhi = 2. * M_PI - pDPhi;
+ delta_r = sqrt((iPart1.eta() - iPart2.eta()) * (iPart1.eta() - iPart2.eta()) + pDPhi * pDPhi);
+ return delta_r;
+}
+L1NNTauProducer::~L1NNTauProducer() {}
+
+#include "FWCore/Framework/interface/MakerMacros.h"
+DEFINE_FWK_MODULE(L1NNTauProducer);
diff --git a/L1Trigger/Phase2L1ParticleFlow/python/L1NNTauProducer_cff.py b/L1Trigger/Phase2L1ParticleFlow/python/L1NNTauProducer_cff.py
new file mode 100644
index 0000000000000..b59069640aae2
--- /dev/null
+++ b/L1Trigger/Phase2L1ParticleFlow/python/L1NNTauProducer_cff.py
@@ -0,0 +1,22 @@
+import FWCore.ParameterSet.Config as cms
+
+L1NNTauProducer = cms.EDProducer("L1NNTauProducer",
+ seedpt = cms.double(20),
+ conesize = cms.double(0.4),
+ tausize = cms.double(0.1),
+ maxtaus = cms.int32(5),
+ nparticles = cms.int32(10),
+ L1PFObjects = cms.InputTag("L1PFProducer","l1pfCandidates"),
+ NNFileName = cms.string("L1Trigger/Phase2L1ParticleFlow/data/tau_3layer.pb")
+ )
+
+
+L1NNTauProducerPuppi = cms.EDProducer("L1NNTauProducer",
+ seedpt = cms.double(20),
+ conesize = cms.double(0.4),
+ tausize = cms.double(0.1),
+ maxtaus = cms.int32(5),
+ nparticles = cms.int32(10),
+ L1PFObjects = cms.InputTag("L1PFProducer","l1pfCandidates"),
+ NNFileName = cms.string("L1Trigger/Phase2L1ParticleFlow/data/tau_3layer_puppi.pb")
+ )
diff --git a/L1Trigger/Phase2L1ParticleFlow/src/TauNNId.cc b/L1Trigger/Phase2L1ParticleFlow/src/TauNNId.cc
new file mode 100644
index 0000000000000..288b426d50e9b
--- /dev/null
+++ b/L1Trigger/Phase2L1ParticleFlow/src/TauNNId.cc
@@ -0,0 +1,74 @@
+#include "L1Trigger/Phase2L1ParticleFlow/interface/TauNNId.h"
+#include "FWCore/ParameterSet/interface/FileInPath.h"
+#include
+
+TauNNId::TauNNId() { NNvectorVar_.clear(); }
+TauNNId::~TauNNId() {
+ tensorflow::closeSession(session_);
+ delete graphDef_;
+}
+void TauNNId::initialize(const std::string &iInput, const std::string &iWeightFile, int iNParticles) {
+ edm::FileInPath fp(iWeightFile);
+ graphDef_ = tensorflow::loadGraphDef(fp.fullPath());
+ session_ = tensorflow::createSession(graphDef_);
+ fNParticles_ = iNParticles;
+ fPt_ = std::make_unique(fNParticles_);
+ fEta_ = std::make_unique(fNParticles_);
+ fPhi_ = std::make_unique(fNParticles_);
+ fId_ = std::make_unique(fNParticles_);
+ fInput_ = iInput;
+}
+void TauNNId::SetNNVectorVar() {
+ NNvectorVar_.clear();
+ for (int i0 = 0; i0 < fNParticles_; i0++) {
+ NNvectorVar_.push_back(fPt_.get()[i0]); //pT
+ NNvectorVar_.push_back(fEta_.get()[i0]); //dEta from jet axis
+ NNvectorVar_.push_back(fPhi_.get()[i0]); //dPhi from jet axis
+ if (fPt_.get()[i0] == 0) {
+ for (int i1 = 0; i1 < 5; i1++)
+ NNvectorVar_.push_back(0);
+ continue;
+ }
+ NNvectorVar_.push_back(fId_.get()[i0] == l1t::PFCandidate::Photon); // Photon
+ NNvectorVar_.push_back(fId_.get()[i0] == l1t::PFCandidate::Electron); // Electron
+ NNvectorVar_.push_back(fId_.get()[i0] == l1t::PFCandidate::Muon); // Muon
+ NNvectorVar_.push_back(fId_.get()[i0] == l1t::PFCandidate::NeutralHadron); // Neutral Had
+ NNvectorVar_.push_back(fId_.get()[i0] == l1t::PFCandidate::ChargedHadron); // Charged Had
+ }
+}
+float TauNNId::EvaluateNN() {
+ tensorflow::Tensor input(tensorflow::DT_FLOAT,
+ {1, (unsigned int)NNvectorVar_.size()}); //was {1,35} but get size mismatch, CHECK
+ for (unsigned int i = 0; i < NNvectorVar_.size(); i++) {
+ input.matrix()(0, i) = float(NNvectorVar_[i]);
+ }
+ std::vector outputs;
+ tensorflow::run(session_, {{fInput_, input}}, {"dense_4/Sigmoid:0"}, &outputs);
+ float disc = outputs[0].matrix()(0, 0);
+ return disc;
+} //end EvaluateNN
+
+float TauNNId::compute(const l1t::PFCandidate &iSeed, l1t::PFCandidateCollection &iParts) {
+ for (int i0 = 0; i0 < fNParticles_; i0++) {
+ fPt_.get()[i0] = 0;
+ fEta_.get()[i0] = 0;
+ fPhi_.get()[i0] = 0;
+ fId_.get()[i0] = 0;
+ }
+ std::sort(iParts.begin(), iParts.end(), [](l1t::PFCandidate i, l1t::PFCandidate j) { return (i.pt() > j.pt()); });
+ for (unsigned int i0 = 0; i0 < iParts.size(); i0++) {
+ if (i0 > 10)
+ break;
+ fPt_.get()[i0] = iParts[i0].pt();
+ fEta_.get()[i0] = iSeed.eta() - iParts[i0].eta();
+ float lDPhi = iSeed.phi() - iParts[i0].phi();
+ if (lDPhi > M_PI)
+ lDPhi -= M_PI;
+ if (lDPhi < -M_PI)
+ lDPhi += M_PI;
+ fPhi_.get()[i0] = lDPhi;
+ fId_.get()[i0] = iParts[i0].id();
+ }
+ SetNNVectorVar();
+ return EvaluateNN();
+}