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

Adding MVA ID to nanoAOD code #39355

Merged
merged 5 commits into from Nov 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
46 changes: 46 additions & 0 deletions PhysicsTools/NanoAOD/plugins/EvaluateMuonMVAID.cc
@@ -0,0 +1,46 @@
//
//
//
//

#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 "DataFormats/PatCandidates/interface/Muon.h"
#include "PhysicsTools/PatAlgos/interface/BaseMVAValueMapProducer.h"
#include <vector>

class EvaluateMuonMVAID : public BaseMVAValueMapProducer<pat::Muon> {
public:
explicit EvaluateMuonMVAID(const edm::ParameterSet& iConfig, const BaseMVACache* cache)
: BaseMVAValueMapProducer<pat::Muon>(iConfig, cache) {}

void fillAdditionalVariables(const pat::Muon& m) override {
float norm_chi2;
float n_Valid_hits;
if (m.globalTrack().isNonnull()) {
norm_chi2 = m.globalTrack()->normalizedChi2();
n_Valid_hits = m.globalTrack()->hitPattern().numberOfValidMuonHits();
} else if (m.innerTrack().isNonnull()) {
norm_chi2 = m.innerTrack()->normalizedChi2();
n_Valid_hits = m.innerTrack()->hitPattern().numberOfValidMuonHits();
} else {
norm_chi2 = -99;
n_Valid_hits = -99;
}

this->setValue("Muon_norm_chi2_extended", norm_chi2);
this->setValue("Muon_n_Valid_hits_extended", n_Valid_hits);
}

static void fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
edm::ParameterSetDescription desc = BaseMVAValueMapProducer<pat::Muon>::getDescription();
descriptions.add("EvaluateMuonMVAID", desc);
}
};

//define this as a plug-in
DEFINE_FWK_MODULE(EvaluateMuonMVAID);
46 changes: 44 additions & 2 deletions PhysicsTools/NanoAOD/python/muons_cff.py
Expand Up @@ -30,6 +30,32 @@
srcVtx = cms.InputTag("offlineSlimmedPrimaryVertices"),
)

muonMVAID = cms.EDProducer("EvaluateMuonMVAID",
src = cms.InputTag("slimmedMuonsUpdated"),
weightFile = cms.FileInPath("RecoMuon/MuonIdentification/data/mvaID.onnx"),
isClassifier = cms.bool(False),
backend = cms.string('ONNX'),
name = cms.string("muonMVAID"),
outputTensorName= cms.string("probabilities"),
inputTensorName= cms.string("float_input"),
outputNames = cms.vstring(["probGOOD", "wpMedium", "wpTight"]),
batch_eval =cms.bool(True),
outputFormulas = cms.vstring(["at(1)", "? at(1) > 0.14 ? 1 : 0", "? at(1) > 0.35 ? 1 : 0"]),
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Author

Choose a reason for hiding this comment

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

The finalMuons are selected using an OR of a few IDs. Are you sure you don't want to keep muon passing the medium mvaID WP? (said otherwise, is it possible to fail that cut but still pass the medium mvaID WP?)

The finalMuon selection is much looser than the medium WP of the mvaID. Also, muons selected by the mvaID wp medium have to pass looseID, hence those are finalMuons.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for clarifying that point!

variablesOrder = cms.vstring(["LepGood_global_muon","LepGood_validFraction","Muon_norm_chi2_extended","LepGood_local_chi2","LepGood_kink","LepGood_segmentComp","Muon_n_Valid_hits_extended","LepGood_n_MatchedStations","LepGood_Valid_pixel","LepGood_tracker_layers","LepGood_pt","LepGood_eta"]),
variables = cms.PSet(
LepGood_global_muon = cms.string("isGlobalMuon"),
LepGood_validFraction = cms.string("?innerTrack.isNonnull?innerTrack().validFraction:-99"),
LepGood_local_chi2 = cms.string("combinedQuality().chi2LocalPosition"),
LepGood_kink = cms.string("combinedQuality().trkKink"),
LepGood_segmentComp = cms.string("segmentCompatibility"),
LepGood_n_MatchedStations = cms.string("numberOfMatchedStations()"),
LepGood_Valid_pixel = cms.string("?innerTrack.isNonnull()?innerTrack().hitPattern().numberOfValidPixelHits():-99"),
LepGood_tracker_layers = cms.string("?innerTrack.isNonnull()?innerTrack().hitPattern().trackerLayersWithMeasurement():-99"),
LepGood_pt = cms.string("pt"),
LepGood_eta = cms.string("eta"),
)
)

slimmedMuonsWithUserData = cms.EDProducer("PATMuonUserDataEmbedder",
src = cms.InputTag("slimmedMuonsUpdated"),
userFloats = cms.PSet(
Expand All @@ -38,12 +64,18 @@
ptRatio = cms.InputTag("ptRatioRelForMu:ptRatio"),
ptRel = cms.InputTag("ptRatioRelForMu:ptRel"),
jetNDauChargedMVASel = cms.InputTag("ptRatioRelForMu:jetNDauChargedMVASel"),
mvaIDMuon_wpMedium = cms.InputTag("muonMVAID:wpMedium"),
mvaIDMuon_wpTight = cms.InputTag("muonMVAID:wpTight")
),
userCands = cms.PSet(
jetForLepJetVar = cms.InputTag("ptRatioRelForMu:jetForLepJetVar") # warning: Ptr is null if no match is found
),
)

(run2_nanoAOD_106Xv2 | run3_nanoAOD_122 ).toModify(slimmedMuonsWithUserData.userFloats,
mvaIDMuon = cms.InputTag("muonMVAID:probGOOD"))


finalMuons = cms.EDFilter("PATMuonRefSelector",
src = cms.InputTag("slimmedMuonsWithUserData"),
cut = cms.string("pt > 15 || (pt > 3 && (passed('CutBasedIdLoose') || passed('SoftCutBasedId') || passed('SoftMvaId') || passed('CutBasedIdGlobalHighPt') || passed('CutBasedIdTrkHighPt')))")
Expand Down Expand Up @@ -129,9 +161,11 @@
highPtId = Var("?passed('CutBasedIdGlobalHighPt')?2:passed('CutBasedIdTrkHighPt')","uint8",doc="high-pT cut-based ID (1 = tracker high pT, 2 = global high pT, which includes tracker high pT)"),
pfIsoId = Var("passed('PFIsoVeryLoose')+passed('PFIsoLoose')+passed('PFIsoMedium')+passed('PFIsoTight')+passed('PFIsoVeryTight')+passed('PFIsoVeryVeryTight')","uint8",doc="PFIso ID from miniAOD selector (1=PFIsoVeryLoose, 2=PFIsoLoose, 3=PFIsoMedium, 4=PFIsoTight, 5=PFIsoVeryTight, 6=PFIsoVeryVeryTight)"),
tkIsoId = Var("?passed('TkIsoTight')?2:passed('TkIsoLoose')","uint8",doc="TkIso ID (1=TkIsoLoose, 2=TkIsoTight)"),
mvaId = Var("passed('MvaLoose')+passed('MvaMedium')+passed('MvaTight')+passed('MvaVTight')+passed('MvaVVTight')","uint8",doc="Mva ID from miniAOD selector (1=MvaLoose, 2=MvaMedium, 3=MvaTight, 4=MvaVTight, 5=MvaVVTight)"),
mvaId = Var("passed('MvaLoose')+passed('MvaMedium')+passed('MvaTight')+passed('MvaVTight')+passed('MvaVVTight')","uint8",doc="Mva for ID of prompt leptons from miniAOD selector (1=MvaLoose, 2=MvaMedium, 3=MvaTight, 4=MvaVTight, 5=MvaVVTight)"),
mvaLowPtId = Var("passed('LowPtMvaLoose')+passed('LowPtMvaMedium')","uint8", doc="Low Pt Mva ID from miniAOD selector (1=LowPtMvaLoose, 2=LowPtMvaMedium)"),
miniIsoId = Var("passed('MiniIsoLoose')+passed('MiniIsoMedium')+passed('MiniIsoTight')+passed('MiniIsoVeryTight')","uint8",doc="MiniIso ID from miniAOD selector (1=MiniIsoLoose, 2=MiniIsoMedium, 3=MiniIsoTight, 4=MiniIsoVeryTight)"),
mvaMuID = Var("mvaIDValue()",float,doc="MVA-based ID score ",precision=6),
mvaMuID_WP = Var("userFloat('mvaIDMuon_wpMedium') + userFloat('mvaIDMuon_wpTight')","uint8",doc="MVA-based ID selector WPs (1=MVAIDwpMedium,2=MVAIDwpTight)"),
multiIsoId = Var("?passed('MultiIsoMedium')?2:passed('MultiIsoLoose')","uint8",doc="MultiIsoId from miniAOD selector (1=MultiIsoLoose, 2=MultiIsoMedium)"),
puppiIsoId = Var("passed('PuppiIsoLoose')+passed('PuppiIsoMedium')+passed('PuppiIsoTight')", "uint8", doc="PuppiIsoId from miniAOD selector (1=Loose, 2=Medium, 3=Tight)"),
triggerIdLoose = Var("passed('TriggerIdLoose')",bool,doc="TriggerIdLoose ID"),
Expand All @@ -146,6 +180,10 @@
)


(run2_nanoAOD_106Xv2 | run3_nanoAOD_122).toModify(muonTable.variables,mvaMuID=None).toModify(
muonTable.variables, mvaMuID = Var("userFloat('mvaIDMuon')", float, doc="MVA-based ID score",precision=6))


# Revert back to AK4 CHS jets for Run 2
run2_nanoAOD_ANY.toModify(
ptRatioRelForMu,srcJet="updatedJets"
Expand Down Expand Up @@ -175,4 +213,8 @@

muonTask = cms.Task(slimmedMuonsUpdated,isoForMu,ptRatioRelForMu,slimmedMuonsWithUserData,finalMuons,finalLooseMuons )
muonMCTask = cms.Task(muonsMCMatchForTable,muonMCTable)
muonTablesTask = cms.Task(muonMVATTH,muonMVALowPt,muonTable)
muonTablesTask = cms.Task(muonMVATTH,muonMVALowPt,muonTable,muonMVAID)




2 changes: 2 additions & 0 deletions PhysicsTools/NanoAOD/python/nanoDQM_cfi.py
Expand Up @@ -522,6 +522,8 @@
Plot1D('mvaLowPt', 'mvaLowPt', 20, -1, 1, 'Low pt muon ID score'),
Plot1D('mvaLowPtId', 'mvaLowPtId', 3, -0.5, 2.5, 'Low Pt Mva ID from miniAOD selector (1=LowPtMvaLoose, 2=LowPtMvaMedium)'),
Plot1D('mvaTTH', 'mvaTTH', 20, -1, 1, 'TTH MVA lepton ID score'),
Plot1D('mvaMuID', 'mvaMuID', 20, 0, 1, 'Score of MVA-based muon ID'),
Plot1D('mvaMuID_WP', 'mvaMuID_WP', 3, -0.5, 2.5, 'MVA-based ID selector WPs (1=MVAIDwpMedium,2=MVAIDwpTight)'),
Plot1D('nStations', 'nStations', 5, -0.5, 4.5, 'number of matched stations with default arbitration (segment & track)'),
Plot1D('nTrackerLayers', 'nTrackerLayers', 15, 2.5, 17.5, 'number of layers in the tracker'),
Plot1D('jetNDauCharged', 'jetNDauCharged', 20, -0.5, 19.5, 'number of charged daughters of the closest jet'),
Expand Down