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

Phase2 L1 NN Tau #30505

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -196,6 +196,8 @@ def _appendPhase2Digis(obj):
'keep *_l1PFMetCalo__*',
'keep *_l1PFMetPF__*',
'keep *_l1PFMetPuppi__*',
'keep *_l1NNTauProducer__*',
'keep *_l1NNTauProducerPuppi__*',
]
obj.outputCommands += l1Phase2Digis

Expand Down
12 changes: 12 additions & 0 deletions L1Trigger/Configuration/python/SimL1Emulator_cff.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions L1Trigger/Phase2L1ParticleFlow/BuildFile.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
<use name="L1Trigger/L1THGCal"/>
<use name="CommonTools/Utils"/>
<use name="CommonTools/MVAUtils"/>
<use name="PhysicsTools/TensorFlow"/>
<use name="tensorflow"/>
<use name="roottmva"/>
<use name="hls"/>
<export>
Expand Down
39 changes: 39 additions & 0 deletions L1Trigger/Phase2L1ParticleFlow/interface/L1NNTauProducer.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#ifndef L1TRIGGER_PHASE2L1PARTICLEFLOW_L1NNTAU_H
#define L1TRIGGER_PHASE2L1PARTICLEFLOW_L1NNTAU_H

#include <vector>

#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<TauNNId> fTauNNId_;
void addTau(const l1t::PFCandidate &iCand,
const l1t::PFCandidateCollection &iParts,
std::unique_ptr<PFTauCollection> &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<vector<l1t::PFCandidate> > fL1PFToken_;
};

#endif
30 changes: 30 additions & 0 deletions L1Trigger/Phase2L1ParticleFlow/interface/TauNNId.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef L1TRIGGER_PHASE2L1PARTICLEFLOWS_TAUNNID_H
#define L1TRIGGER_PHASE2L1PARTICLEFLOWS_TAUNNID_H

#include <string>
#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<float> fPt_;
unique_ptr<float> fEta_;
unique_ptr<float> fPhi_;
unique_ptr<float> fId_;

private:
tensorflow::Session *session_;
tensorflow::GraphDef *graphDef_;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How big is the graph? I think we've typically shared the graph across the stream modules in an edm::GlobalCache.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, a smart pointer could be used (though it seems like that isn't common practice for CMSSW TF code at the moment, something to be improved globally)

std::vector<float> NNvectorVar_;
};
#endif
112 changes: 112 additions & 0 deletions L1Trigger/Phase2L1ParticleFlow/plugins/L1NNTauProducer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#include "L1Trigger/Phase2L1ParticleFlow/interface/L1NNTauProducer.hh"
#include <TLorentzVector.h>
#include <cmath>

L1NNTauProducer::L1NNTauProducer(const edm::ParameterSet& cfg)
: fSeedPt_(cfg.getParameter<double>("seedpt")),
fConeSize_(cfg.getParameter<double>("conesize")),
fTauSize_(cfg.getParameter<double>("tausize")),
fMaxTaus_(cfg.getParameter<int>("maxtaus")),
fNParticles_(cfg.getParameter<int>("nparticles")),
fL1PFToken_(consumes<vector<l1t::PFCandidate> >(cfg.getParameter<edm::InputTag>("L1PFObjects"))) {
std::string lNNFile = cfg.getParameter<std::string>("NNFileName"); //,"L1Trigger/Phase2L1Taus/data/tau_3layer.pb");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete commented-out code

fTauNNId_ = std::make_unique<TauNNId>();
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<l1t::PFTauCollection>("L1PFTausNN");
}

void L1NNTauProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
edm::Handle<l1t::PFCandidateCollection> 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<l1t::PFTauCollection>();
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++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be range-based loop

bool pMatch = false;
for (unsigned int i1 = 0; i1 < pfChargedHadrons_seeds.size(); i1++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be range-based loop

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++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be range-based loop

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<l1t::PFTauCollection>& 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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const auto&

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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
22 changes: 22 additions & 0 deletions L1Trigger/Phase2L1ParticleFlow/python/L1NNTauProducer_cff.py
Original file line number Diff line number Diff line change
@@ -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")
)
74 changes: 74 additions & 0 deletions L1Trigger/Phase2L1ParticleFlow/src/TauNNId.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include "L1Trigger/Phase2L1ParticleFlow/interface/TauNNId.h"
#include "FWCore/ParameterSet/interface/FileInPath.h"
#include <cmath>

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<float>(fNParticles_);
fEta_ = std::make_unique<float>(fNParticles_);
fPhi_ = std::make_unique<float>(fNParticles_);
fId_ = std::make_unique<float>(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<float>()(0, i) = float(NNvectorVar_[i]);
}
std::vector<tensorflow::Tensor> outputs;
tensorflow::run(session_, {{fInput_, input}}, {"dense_4/Sigmoid:0"}, &outputs);
float disc = outputs[0].matrix<float>()(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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this hardcoded? is it the same as the "nparticles" python parameter? if so, just use that...
(also, just make the loop condition i0 < std::min(iParts.size(),fNparticles_))

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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lDPhi -= M_PI;
if (lDPhi < -M_PI)
lDPhi += M_PI;
fPhi_.get()[i0] = lDPhi;
fId_.get()[i0] = iParts[i0].id();
}
SetNNVectorVar();
return EvaluateNN();
}