diff --git a/DataFormats/BTauReco/interface/DeepBoostedJetFeatures.h b/DataFormats/BTauReco/interface/DeepBoostedJetFeatures.h index fb06d9c8a6c47..a49e889805e3f 100644 --- a/DataFormats/BTauReco/interface/DeepBoostedJetFeatures.h +++ b/DataFormats/BTauReco/interface/DeepBoostedJetFeatures.h @@ -5,6 +5,7 @@ #include #include #include "FWCore/Utilities/interface/Exception.h" +#include "DataFormats/BTauReco/interface/RefMacros.h" namespace btagbtvdeep { @@ -57,6 +58,8 @@ namespace btagbtvdeep { std::unordered_map> feature_map_; }; + DECLARE_EDM_REFS(DeepBoostedJetFeatures) + } // namespace btagbtvdeep #endif // DataFormats_BTauReco_DeepBoostedJetFeatures_h diff --git a/DataFormats/BTauReco/src/classes_def.xml b/DataFormats/BTauReco/src/classes_def.xml index f5f697a7a2c98..895e486f1e144 100644 --- a/DataFormats/BTauReco/src/classes_def.xml +++ b/DataFormats/BTauReco/src/classes_def.xml @@ -489,7 +489,15 @@ + + + + + + + + diff --git a/PhysicsTools/NanoAOD/python/muons_cff.py b/PhysicsTools/NanoAOD/python/muons_cff.py index 073b8c331d6e5..5295817f0e67b 100644 --- a/PhysicsTools/NanoAOD/python/muons_cff.py +++ b/PhysicsTools/NanoAOD/python/muons_cff.py @@ -145,6 +145,73 @@ variables = _legacy_muon_BDT_variable ) +from PhysicsTools.PatAlgos.muonTagInfos_cfi import muonTagInfos as _muonTagInfos +muonPNetVariables = _muonTagInfos.clone( + src = cms.InputTag("linkedObjects","muons"), + leptonVars = cms.PSet( + MuonSelected_LepGood_pt = cms.string("pt"), + MuonSelected_LepGood_eta = cms.string("eta"), + MuonSelected_LepGood_jetNDauChargedMVASel = cms.string("?userCand('jetForLepJetVar').isNonnull()?userFloat('jetNDauChargedMVASel'):0"), + MuonSelected_LepGood_miniRelIsoCharged = cms.string("userFloat('miniIsoChg')/pt"), + MuonSelected_LepGood_miniRelIsoNeutral = cms.string("(userFloat('miniIsoAll')-userFloat('miniIsoChg'))/pt"), + MuonSelected_LepGood_jetPtRelv2 = cms.string("?userCand('jetForLepJetVar').isNonnull()?userFloat('ptRel'):0"), + MuonSelected_LepGood_jetDF = cms.string("?userCand('jetForLepJetVar').isNonnull()?max(userCand('jetForLepJetVar').bDiscriminator('pfDeepFlavourJetTags:probbb')+userCand('jetForLepJetVar').bDiscriminator('pfDeepFlavourJetTags:probb')+userCand('jetForLepJetVar').bDiscriminator('pfDeepFlavourJetTags:problepb'),0.0):0.0"), + MuonSelected_LepGood_jetPtRatio = cms.string("?userCand('jetForLepJetVar').isNonnull()?min(userFloat('ptRatio'),1.5):1.0/(1.0+(pfIsolationR04().sumChargedHadronPt + max(pfIsolationR04().sumNeutralHadronEt + pfIsolationR04().sumPhotonEt - pfIsolationR04().sumPUPt/2,0.0))/pt)"), + MuonSelected_dxy = cms.string("log(abs(dB('PV2D')))"), + MuonSelected_sip3d = cms.string("abs(dB('PV3D')/edB('PV3D'))"), + MuonSelected_dz = cms.string("log(abs(dB('PVDZ')))"), + MuonSelected_LepGood_dz = cms.string("log(abs(dB('PVDZ')))"), + MuonSelected_segmentComp = cms.string("segmentCompatibility"), + MuonSelected_global_muon = cms.string("isGlobalMuon"), + MuonSelected_validFraction = cms.string("?innerTrack.isNonnull?innerTrack().validFraction:-99"), + MuonSelected_local_chi2 = cms.string("combinedQuality().chi2LocalPosition"), + MuonSelected_kink = cms.string("combinedQuality().trkKink"), + MuonSelected_n_MatchedStations = cms.string("numberOfMatchedStations()"), + MuonSelected_Valid_pixel = cms.string("?innerTrack.isNonnull()?innerTrack().hitPattern().numberOfValidPixelHits():-99"), + MuonSelected_tracker_layers = cms.string("?innerTrack.isNonnull()?innerTrack().hitPattern().trackerLayersWithMeasurement():-99"), + MuonSelected_mvaId=cms.string("userFloat('mvaIDMuon')"), + ), + leptonVarsExt = cms.PSet( + MuonSelected_mvaTTH=cms.InputTag("muonPROMPTMVA"), + ), + pfVars = cms.PSet( + PF_pt=cms.string("pt"), + PF_charge=cms.string("charge"), + PF_isElectron=cms.string("?abs(pdgId)==11?1:0"), + PF_isMuon=cms.string("?abs(pdgId)==13?1:0"), + PF_isNeutralHadron=cms.string("?abs(pdgId)==130?1:0"), + PF_isPhoton=cms.string("?abs(pdgId)==22?1:0"), + PF_isChargedHadron=cms.string("?abs(pdgId)==211?1:0"), + PF_puppiWeightNoLep=cms.string("puppiWeightNoLep"), + PF_fromPV=cms.string("fromPV"), + PF_numberOfPixelHits=cms.string("numberOfPixelHits"), + PF_dzSig=cms.string("?hasTrackDetails?dz/max(dzError,1.e-6):0"), + PF_dxySig=cms.string("?hasTrackDetails?dxy/max(dxyError,1.e-6):0"), + PF_hcalFraction=cms.string("hcalFraction"), + PF_trackerLayersWithMeasurement=cms.string("?hasTrackDetails?bestTrack().hitPattern().trackerLayersWithMeasurement:0"), + PF_mask=cms.string("1"), + ), + svVars = cms.PSet( + SV_eta=cms.string("eta"), + SV_phi=cms.string("phi"), + SV_pt=cms.string("pt"), + SV_ndof=cms.string("vertexNdof"), + SV_chi2=cms.string("vertexChi2"), + SV_nTracks=cms.string("numberOfDaughters"), + SV_mass=cms.string("mass"), + SV_mask=cms.string("1"), + ), +) + +from PhysicsTools.PatAlgos.muonPNetTags_cfi import muonPNetTags as _muonPNetTags +muonPNetScores = _muonPNetTags.clone( + src = cms.InputTag("muonPNetVariables"), + srcLeps = cms.InputTag("linkedObjects", "muons"), + model_path = 'PhysicsTools/NanoAOD/data/PNetMuonId/model.onnx', + preprocess_json = 'PhysicsTools/NanoAOD/data/PNetMuonId/preprocess.json', + flav_names = cms.vstring(["light", "prompt", "tau", "heavy"]), +) + from TrackingTools.TransientTrack.TransientTrackBuilder_cfi import * muonBSConstrain = cms.EDProducer("MuonBeamspotConstraintValueMapProducer", src = cms.InputTag("linkedObjects","muons"), @@ -213,6 +280,10 @@ externalVariables = cms.PSet( promptMVA = ExtVar(cms.InputTag("muonPROMPTMVA"),float, doc="Prompt MVA lepton ID score. Corresponds to the previous mvaTTH",precision=14), mvaLowPt = ExtVar(cms.InputTag("muonMVALowPt"),float, doc="Low pt muon ID score",precision=14), + pnScore_prompt = ExtVar(cms.InputTag("muonPNetScores:prompt"),float, doc="PNet muon ID score for lepton from W/Z/H bosons", precision=14), + pnScore_heavy = ExtVar(cms.InputTag("muonPNetScores:heavy"),float, doc="PNet muon ID score for lepton from B or D hadrons", precision=14), + pnScore_light = ExtVar(cms.InputTag("muonPNetScores:light"),float, doc="PNet muon ID score for lepton from hadrons w/o b or c quarks OR w/o generator matching", precision=14), + pnScore_tau = ExtVar(cms.InputTag("muonPNetScores:tau"),float, doc="PNet muon ID score for decay of tau to light leptons (mu)", precision=14), fsrPhotonIdx = ExtVar(cms.InputTag("leptonFSRphotons:muFsrIndex"), "int16", doc="Index of the lowest-dR/ET2 among associated FSR photons"), bsConstrainedPt = ExtVar(cms.InputTag("muonBSConstrain:muonBSConstrainedPt"),float, doc="pT with beamspot constraint",precision=-1), bsConstrainedPtErr = ExtVar(cms.InputTag("muonBSConstrain:muonBSConstrainedPtErr"),float, doc="pT error with beamspot constraint ",precision=6), @@ -252,7 +323,6 @@ docString = cms.string("MC matching to status==1 muons"), ) -muonTask = cms.Task(slimmedMuonsUpdated,isoForMu,ptRatioRelForMu,slimmedMuonsWithUserData,finalMuons,finalLooseMuons ) +muonTask = cms.Task(slimmedMuonsUpdated,isoForMu,ptRatioRelForMu,slimmedMuonsWithUserData,finalMuons,finalLooseMuons) muonMCTask = cms.Task(muonsMCMatchForTable,muonMCTable) -muonTablesTask = cms.Task(muonPROMPTMVA,muonMVALowPt,muonBSConstrain,muonTable,muonMVAID) - +muonTablesTask = cms.Task(muonPROMPTMVA,muonMVALowPt,muonBSConstrain,muonTable,muonMVAID,muonPNetVariables,muonPNetScores) diff --git a/PhysicsTools/NanoAOD/python/nanoDQM_cfi.py b/PhysicsTools/NanoAOD/python/nanoDQM_cfi.py index 19c4d371b22ea..b15fb41f11c4d 100644 --- a/PhysicsTools/NanoAOD/python/nanoDQM_cfi.py +++ b/PhysicsTools/NanoAOD/python/nanoDQM_cfi.py @@ -593,6 +593,10 @@ Plot1D('pfRelIso03_chg', 'pfRelIso03_chg', 20, 0, 2, 'PF relative isolation dR=0.3, charged component'), Plot1D('pfRelIso04_all', 'pfRelIso04_all', 20, 0, 2, 'PF relative isolation dR=0.4, total (deltaBeta corrections)'), Plot1D('phi', 'phi', 20, -3.14159, 3.14159, 'phi'), + Plot1D('pnScore_heavy', 'pnScore_heavy', 40, -1, 1, 'PNet muon ID score for lepton from B or D hadrons'), + Plot1D('pnScore_light', 'pnScore_light', 40, -1, 1, 'PNet muon ID score for lepton from hadrons w/o b or c quarks OR w/o generator matching'), + Plot1D('pnScore_prompt', 'pnScore_prompt', 40, -1, 1, 'PNet muon ID score for lepton from W/Z/H bosons'), + Plot1D('pnScore_tau', 'pnScore_tau', 40, -1, 1, 'PNet muon ID score for decay of tau to light leptons (mu)'), Plot1D('pt', 'pt', 20, 0, 200, 'pt'), Plot1D('ptErr', 'ptErr', 20, 0, 20, 'ptError of the muon track'), Plot1D('segmentComp', 'segmentComp', 20, 0, 1, 'muon segment compatibility'), @@ -607,6 +611,7 @@ Plot1D('tkRelIso', 'tkRelIso', 100, 0, 1, 'Tracker-based relative isolation dR=0.3 for highPt, trkIso/tunePpt'), Plot1D('triggerIdLoose', 'triggerIdLoose', 2, -0.5, 1.5, 'TriggerIdLoose ID'), Plot1D('tunepRelPt', 'tunepRelPt', 200, 0, 200, 'TuneP relative pt, tunePpt/pt'), + Plot1D('tuneP_pterr', 'tuneP_pterr', 200, 0, 20, 'pTerr from tunePMuonBestTrack'), Plot1D('VXBS_Cov00', 'VXBS_Cov00', 200, -10, 10, '0, 0 element of the VXBS Covariance matrix'), Plot1D('VXBS_Cov03', 'VXBS_Cov03', 200, -10, 10, '0, 3 element of the VXBS Covariance matrix'), Plot1D('VXBS_Cov33', 'VXBS_Cov33', 200, -10, 10, '3, 3 element of the VXBS Covariance matrix'), diff --git a/PhysicsTools/PatAlgos/plugins/BuildFile.xml b/PhysicsTools/PatAlgos/plugins/BuildFile.xml index 8abcb381084a6..1eb494d19fbd3 100644 --- a/PhysicsTools/PatAlgos/plugins/BuildFile.xml +++ b/PhysicsTools/PatAlgos/plugins/BuildFile.xml @@ -35,5 +35,6 @@ + diff --git a/PhysicsTools/PatAlgos/plugins/LeptonTagInfoCollectionProducer.cc b/PhysicsTools/PatAlgos/plugins/LeptonTagInfoCollectionProducer.cc new file mode 100644 index 0000000000000..dcf1c168e9f58 --- /dev/null +++ b/PhysicsTools/PatAlgos/plugins/LeptonTagInfoCollectionProducer.cc @@ -0,0 +1,293 @@ +// -*- C++ -*- +// +// Package: PhysicsTools/PatAlgos +// Class: LeptonTagInfoCollectionProducer +// +// Original Author: Sergio Sanchez Cruz +// Created: Mon, 15 May 2023 08:32:03 GMT +// +#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/StreamID.h" +#include "FWCore/Utilities/interface/ESGetToken.h" + +#include "CommonTools/Utils/interface/StringObjectFunction.h" +#include "DataFormats/BTauReco/interface/DeepBoostedJetFeatures.h" +#include "DataFormats/Candidate/interface/VertexCompositePtrCandidate.h" +#include "DataFormats/PatCandidates/interface/PackedCandidate.h" +#include "DataFormats/PatCandidates/interface/Electron.h" +#include "DataFormats/PatCandidates/interface/Muon.h" +#include "DataFormats/PatCandidates/interface/Jet.h" +#include "DataFormats/VertexReco/interface/Vertex.h" +#include "DataFormats/Math/interface/deltaPhi.h" +#include "DataFormats/Math/interface/deltaR.h" + +#include "RecoVertex/VertexTools/interface/VertexDistance3D.h" +#include "RecoVertex/VertexTools/interface/VertexDistanceXY.h" +#include "RecoVertex/VertexPrimitives/interface/VertexState.h" +#include "RecoVertex/VertexPrimitives/interface/ConvertToFromReco.h" + +using namespace btagbtvdeep; + +template +class LeptonTagInfoCollectionProducer : public edm::stream::EDProducer<> { +public: + explicit LeptonTagInfoCollectionProducer(const edm::ParameterSet& iConfig); + ~LeptonTagInfoCollectionProducer() override {}; + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + +private: + using LeptonTagInfoCollection = DeepBoostedJetFeaturesCollection; + + void produce(edm::Event& iEvent, const edm::EventSetup& iSetup) override; + + void fill_lepton_features(const LeptonType&, DeepBoostedJetFeatures&); + void fill_lepton_extfeatures(const edm::RefToBase&, DeepBoostedJetFeatures&, edm::Event&); + void fill_pf_features(const LeptonType&, DeepBoostedJetFeatures&); + void fill_sv_features(const LeptonType&, DeepBoostedJetFeatures&); + + template + using VarWithName = std::pair>; + template + void parse_vars_into(const edm::ParameterSet& varsPSet, std::vector>>& vars) { + for (const std::string& vname : varsPSet.getParameterNamesForType()) { + const std::string& func = varsPSet.getParameter(vname); + vars.push_back(std::make_unique>(vname, StringObjectFunction(func))); + } + } + + template + using ExtVarWithName = std::pair>>; + template + void parse_extvars_into(const edm::ParameterSet& varsPSet, + std::vector>>& vars) { + for (const std::string& vname : varsPSet.getParameterNamesForType()) { + vars.push_back(std::make_unique>( + vname, consumes>(varsPSet.getParameter(vname)))); + } + } + + edm::EDGetTokenT> src_token_; + edm::EDGetTokenT pf_token_; + edm::EDGetTokenT sv_token_; + edm::EDGetTokenT> pv_token_; + + edm::ParameterSet lepton_varsPSet_; + edm::ParameterSet lepton_varsExtPSet_; + edm::ParameterSet pf_varsPSet_; + edm::ParameterSet sv_varsPSet_; + + std::vector>> lepton_vars_; + std::vector>> pf_vars_; + std::vector>> sv_vars_; + edm::Handle svs_; + edm::Handle pfs_; + edm::Handle> pvs_; + std::vector>> extLepton_vars_; +}; + +template +LeptonTagInfoCollectionProducer::LeptonTagInfoCollectionProducer(const edm::ParameterSet& iConfig) + : src_token_(consumes>(iConfig.getParameter("src"))), + pf_token_(consumes(iConfig.getParameter("pfCandidates"))), + sv_token_(consumes( + iConfig.getParameter("secondary_vertices"))), + pv_token_(consumes>(iConfig.getParameter("pvSrc"))), + lepton_varsPSet_(iConfig.getParameter("leptonVars")), + lepton_varsExtPSet_(iConfig.getParameter("leptonVarsExt")), + pf_varsPSet_(iConfig.getParameter("pfVars")), + sv_varsPSet_(iConfig.getParameter("svVars")) { + parse_vars_into(lepton_varsPSet_, lepton_vars_); + parse_vars_into(pf_varsPSet_, pf_vars_); + parse_vars_into(sv_varsPSet_, sv_vars_); + parse_extvars_into(lepton_varsExtPSet_, extLepton_vars_); + + produces(); +} + +template +void LeptonTagInfoCollectionProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + + desc.add("src", edm::InputTag("slimmedMuons")); + desc.add("pfCandidates", edm::InputTag("packedPFCandidates")); + desc.add("secondary_vertices", edm::InputTag("slimmedSecondaryVertices")); + desc.add("pvSrc", edm::InputTag("offlineSlimmedPrimaryVertices")); + + for (auto&& what : {"leptonVars", "pfVars", "svVars"}) { + edm::ParameterSetDescription descNested; + descNested.addWildcard("*"); + desc.add(what, descNested); + } + + for (auto&& what : {"leptonVarsExt"}) { + edm::ParameterSetDescription descNested; + descNested.addWildcard("*"); + desc.add(what, descNested); + } + + std::string modname; + if (typeid(LeptonType) == typeid(pat::Muon)) + modname += "muon"; + else if (typeid(LeptonType) == typeid(pat::Electron)) + modname += "electron"; + modname += "TagInfos"; + descriptions.add(modname, desc); +} + +template +void LeptonTagInfoCollectionProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) { + auto src = iEvent.getHandle(src_token_); + iEvent.getByToken(sv_token_, svs_); + iEvent.getByToken(pv_token_, pvs_); + iEvent.getByToken(pf_token_, pfs_); + + auto output_info = std::make_unique(); + + if (pvs_->empty()) { + // produce empty TagInfos in case no primary vertex + iEvent.put(std::move(output_info)); + return; + } + + for (size_t ilep = 0; ilep < src->size(); ilep++) { + const auto& lep = (*src)[ilep]; + edm::RefToBase lep_ref(src, ilep); + DeepBoostedJetFeatures features; + fill_lepton_features(lep, features); + fill_lepton_extfeatures(lep_ref, features, iEvent); // fixme + fill_pf_features(lep, features); + fill_sv_features(lep, features); + + output_info->emplace_back(features); + } + iEvent.put(std::move(output_info)); +} + +template +void LeptonTagInfoCollectionProducer::fill_lepton_features(const LeptonType& lep, + DeepBoostedJetFeatures& features) { + for (auto& var : lepton_vars_) { + features.add(var->first); + features.reserve(var->first, 1); + features.fill(var->first, var->second(lep)); + } +} + +template +void LeptonTagInfoCollectionProducer::fill_lepton_extfeatures(const edm::RefToBase& lep, + DeepBoostedJetFeatures& features, + edm::Event& iEvent) { + for (auto& var : extLepton_vars_) { + edm::Handle> vmap; + iEvent.getByToken(var->second, vmap); + + features.add(var->first); + features.reserve(var->first, 1); + features.fill(var->first, (*vmap)[lep]); + } +} + +template +void LeptonTagInfoCollectionProducer::fill_pf_features(const LeptonType& lep, + DeepBoostedJetFeatures& features) { + pat::PackedCandidateCollection pfcands; + for (size_t ipf = 0; ipf < pfs_->size(); ++ipf) { + if (reco::deltaR(pfs_->at(ipf), lep) < 0.4) + pfcands.push_back(pfs_->at(ipf)); + } + + for (auto& var : pf_vars_) { + features.add(var->first); + features.reserve(var->first, pfcands.size()); + for (const auto& cand : pfcands) { + features.fill(var->first, var->second(cand)); + } + } + + // afaik these need to be hardcoded because I cannot put userFloats to pat::packedCandidates + features.add("PF_phi_rel"); + features.reserve("PF_phi_rel", pfcands.size()); + features.add("PF_eta_rel"); + features.reserve("PF_eta_rel", pfcands.size()); + features.add("PF_dR_lep"); + features.reserve("PF_dR_lep", pfcands.size()); + features.add("PF_pt_rel_log"); + features.reserve("PF_pt_rel_log", pfcands.size()); + + for (const auto& cand : pfcands) { + features.fill("PF_phi_rel", reco::deltaPhi(lep.phi(), cand.phi())); + features.fill("PF_eta_rel", lep.eta() - cand.eta()); + features.fill("PF_dR_lep", reco::deltaR(lep, cand)); + features.fill("PF_pt_rel_log", log(cand.pt() / lep.pt())); + } +} + +template +void LeptonTagInfoCollectionProducer::fill_sv_features(const LeptonType& lep, + DeepBoostedJetFeatures& features) { + reco::VertexCompositePtrCandidateCollection selectedSVs; + for (size_t isv = 0; isv < svs_->size(); ++isv) { + if (reco::deltaR(lep, svs_->at(isv)) < 0.4) { + selectedSVs.push_back(svs_->at(isv)); + } + } + + for (auto& var : sv_vars_) { + features.add(var->first); + features.reserve(var->first, selectedSVs.size()); + for (auto& sv : selectedSVs) + features.fill(var->first, var->second(sv)); + } + + // afaik these need to be hardcoded + const auto& PV0 = pvs_->front(); + VertexDistance3D vdist; + VertexDistanceXY vdistXY; + + features.add("SV_dlenSig"); + features.reserve("SV_dlenSig", selectedSVs.size()); + features.add("SV_dxy"); + features.reserve("SV_dxy", selectedSVs.size()); + features.add("SV_eta_rel"); + features.reserve("SV_eta_rel", selectedSVs.size()); + features.add("SV_phi_rel"); + features.reserve("SV_phi_rel", selectedSVs.size()); + features.add("SV_dR_lep"); + features.reserve("SV_dR_lep", selectedSVs.size()); + features.add("SV_pt_rel"); + features.reserve("SV_pt_rel", selectedSVs.size()); + features.add("SV_cospAngle"); + features.reserve("SV_cospAngle", selectedSVs.size()); + features.add("SV_d3d"); + features.reserve("SV_d3d", selectedSVs.size()); + + for (auto& sv : selectedSVs) { + Measurement1D dl = + vdist.distance(PV0, VertexState(RecoVertex::convertPos(sv.position()), RecoVertex::convertError(sv.error()))); + features.fill("SV_d3d", dl.value()); + features.fill("SV_dlenSig", dl.significance()); + Measurement1D d2d = + vdistXY.distance(PV0, VertexState(RecoVertex::convertPos(sv.position()), RecoVertex::convertError(sv.error()))); + features.fill("SV_dxy", d2d.value()); + features.fill("SV_phi_rel", reco::deltaPhi(lep.phi(), sv.phi())); + features.fill("SV_eta_rel", lep.eta() - sv.eta()); + features.fill("SV_dR_lep", reco::deltaR(sv, lep)); + features.fill("SV_pt_rel", sv.pt() / lep.pt()); + double dx = (PV0.x() - sv.vx()), dy = (PV0.y() - sv.vy()), dz = (PV0.z() - sv.vz()); + double pdotv = (dx * sv.px() + dy * sv.py() + dz * sv.pz()) / sv.p() / sqrt(dx * dx + dy * dy + dz * dz); + features.fill("SV_cospAngle", pdotv); + } +} + +typedef LeptonTagInfoCollectionProducer MuonTagInfoCollectionProducer; +typedef LeptonTagInfoCollectionProducer ElectronTagInfoCollectionProducer; + +DEFINE_FWK_MODULE(MuonTagInfoCollectionProducer); +DEFINE_FWK_MODULE(ElectronTagInfoCollectionProducer); diff --git a/PhysicsTools/PatAlgos/plugins/PNETLeptonProducer.cc b/PhysicsTools/PatAlgos/plugins/PNETLeptonProducer.cc new file mode 100644 index 0000000000000..de9a466f2e2c0 --- /dev/null +++ b/PhysicsTools/PatAlgos/plugins/PNETLeptonProducer.cc @@ -0,0 +1,197 @@ +// -*- C++ -*- +// +// Package: PhysicsTools/PatAlgos +// Class: PNETLeptonProducer +// +// Original Author: Sergio Sanchez Cruz +// Created: Mon, 15 May 2023 08:32:03 GMT +// + +#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/StreamID.h" + +#include "DataFormats/BTauReco/interface/DeepBoostedJetFeatures.h" +#include "DataFormats/Common/interface/ValueMap.h" +#include "DataFormats/PatCandidates/interface/Electron.h" +#include "DataFormats/PatCandidates/interface/Muon.h" + +#include "PhysicsTools/ONNXRuntime/interface/ONNXRuntime.h" +#include "RecoBTag/FeatureTools/interface/deep_helpers.h" + +using namespace cms::Ort; +using namespace btagbtvdeep; + +template +class PNETLeptonProducer : public edm::stream::EDProducer> { +public: + explicit PNETLeptonProducer(const edm::ParameterSet &, const cms::Ort::ONNXRuntime *); + ~PNETLeptonProducer() override {} + + static void fillDescriptions(edm::ConfigurationDescriptions &descriptions); + + static std::unique_ptr initializeGlobalCache(const edm::ParameterSet &); + static void globalEndJob(const ONNXRuntime *); + +private: + using LeptonTagInfoCollection = DeepBoostedJetFeaturesCollection; + + void produce(edm::Event &, const edm::EventSetup &) override; + void make_inputs(const DeepBoostedJetFeatures &); + + edm::EDGetTokenT src_; + edm::EDGetTokenT> leps_; + std::vector flav_names_; + std::vector input_names_; // names of each input group - the ordering is important! + std::vector> input_shapes_; // shapes of each input group (-1 for dynamic axis) + std::vector input_sizes_; // total length of each input vector + std::unordered_map + prep_info_map_; // preprocessing info for each input group + + cms::Ort::FloatArrays data_; + bool debug_ = false; +}; + +template +PNETLeptonProducer::PNETLeptonProducer(const edm::ParameterSet &iConfig, const cms::Ort::ONNXRuntime *cache) + : src_(consumes(iConfig.getParameter("src"))), + leps_(consumes>(iConfig.getParameter("srcLeps"))), + flav_names_(iConfig.getParameter>("flav_names")), + debug_(iConfig.getUntrackedParameter("debugMode", false)) { + ParticleNetConstructor(iConfig, true, input_names_, prep_info_map_, input_shapes_, input_sizes_, &data_); + + if (debug_) { + for (unsigned i = 0; i < input_names_.size(); ++i) { + const auto &group_name = input_names_.at(i); + std::cout << group_name << std::endl; + if (!input_shapes_.empty()) { + std::cout << group_name << "\nshapes: "; + for (const auto &x : input_shapes_.at(i)) { + std::cout << x << ", "; + } + } + std::cout << "\nvariables: "; + for (const auto &x : prep_info_map_.at(group_name).var_names) { + std::cout << x << ", "; + } + std::cout << "\n"; + } + std::cout << "\n"; + } + + for (const auto &flav_name : flav_names_) { + produces>(flav_name); + } +} + +template +void PNETLeptonProducer::produce(edm::Event &iEvent, const edm::EventSetup &iSetup) { + edm::Handle src; + iEvent.getByToken(src_, src); + + edm::Handle> leps; + iEvent.getByToken(leps_, leps); + + std::vector> mvaScores(flav_names_.size(), std::vector(leps->size(), -1)); + + // tagInfo src could be empty if the event has no PV + if (!src->empty()) { + assert(src->size() == leps->size()); + for (size_t ilep = 0; ilep < src->size(); ilep++) { + const auto &taginfo = (*src)[ilep]; + make_inputs(taginfo); + auto outputs = globalCache()->run(input_names_, data_, input_shapes_)[0]; + // std::cout<<"outputs.size(): "<> pnScore(new edm::ValueMap()); + edm::ValueMap::Filler filler(*pnScore); + filler.insert(leps, mvaScores[iflav].begin(), mvaScores[iflav].end()); + filler.fill(); + iEvent.put(std::move(pnScore), flav_names_[iflav]); + } +} + +template +std::unique_ptr PNETLeptonProducer::initializeGlobalCache( + const edm::ParameterSet &cfg) { + return std::make_unique(cfg.getParameter("model_path").fullPath()); +} + +template +void PNETLeptonProducer::globalEndJob(const cms::Ort::ONNXRuntime *cache) {} + +template +void PNETLeptonProducer::fillDescriptions(edm::ConfigurationDescriptions &descriptions) { + edm::ParameterSetDescription desc; + desc.add("src")->setComment("input variables"); + desc.add("srcLeps")->setComment("input physics object collection. src and srcLeps must be in synch"); + desc.add>("flav_names")->setComment("Names of the oputput classes"); + desc.add("preprocess_json", "PhysicsTools/NanoAOD/data/PNetMuonId/preprocess.json"); + desc.add("model_path", edm::FileInPath("PhysicsTools/NanoAOD/data/PNetMuonId/model.onnx")); + desc.addOptionalUntracked("debugMode", false); + + std::string modname; + if (typeid(LeptonType) == typeid(pat::Muon)) + modname += "muon"; + else if (typeid(LeptonType) == typeid(pat::Electron)) + modname += "electron"; + modname += "PNetTags"; + descriptions.add(modname, desc); +} + +template +void PNETLeptonProducer::make_inputs(const DeepBoostedJetFeatures &taginfo) { + for (unsigned igroup = 0; igroup < input_names_.size(); ++igroup) { + const auto &group_name = input_names_[igroup]; + const auto &prep_params = prep_info_map_.at(group_name); + auto &group_values = data_[igroup]; + group_values.resize(input_sizes_[igroup]); + + // first reset group_values to 0 + std::fill(group_values.begin(), group_values.end(), 0); + unsigned curr_pos = 0; + + // transform/pad + for (unsigned i = 0; i < prep_params.var_names.size(); ++i) { + const auto &varname = prep_params.var_names[i]; + const auto &raw_value = taginfo.get(varname); + const auto &info = prep_params.info(varname); + int insize = btagbtvdeep::center_norm_pad(raw_value, + info.center, + info.norm_factor, + prep_params.min_length, + prep_params.max_length, + group_values, + curr_pos, + info.pad, + info.replace_inf_value, + info.lower_bound, + info.upper_bound); + curr_pos += insize; + if (i == 0 && (!input_shapes_.empty())) { + input_shapes_[igroup][2] = insize; + } + } + group_values.resize(curr_pos); + } +} + +typedef PNETLeptonProducer MuonPNETProducer; +typedef PNETLeptonProducer ElectronPNETProducer; + +//define this as a plug-in +DEFINE_FWK_MODULE(MuonPNETProducer); +DEFINE_FWK_MODULE(ElectronPNETProducer); diff --git a/RecoBTag/FeatureTools/src/deep_helpers.cc b/RecoBTag/FeatureTools/src/deep_helpers.cc index 0c149d59df562..d8e4d9321f2b5 100644 --- a/RecoBTag/FeatureTools/src/deep_helpers.cc +++ b/RecoBTag/FeatureTools/src/deep_helpers.cc @@ -279,6 +279,7 @@ namespace btagbtvdeep { if (group_pset.contains("var_length")) { prep_params.min_length = group_pset.at("var_length"); prep_params.max_length = prep_params.min_length; + input_shapes_.push_back({1, (int64_t)prep_params.var_names.size(), prep_params.max_length}); } else { prep_params.min_length = group_pset.at("min_length"); prep_params.max_length = group_pset.at("max_length");