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(); +}