From 3cca89c54e31deea0ab3f842cba8fa056b552a3f Mon Sep 17 00:00:00 2001 From: Rajarshi Bhattacharya Date: Fri, 17 Mar 2023 10:14:23 +0100 Subject: [PATCH] Code for custom Muon POG NanoAOD --- .../python/relval_steps.py | 1 + .../NanoAOD/plugins/MuonSpecialVariables.cc | 120 +++++++++ .../NanoAOD/plugins/pfTracksProducer.cc | 66 +++++ .../NanoAOD/python/custom_muon_cff.py | 238 ++++++++++++++++++ 4 files changed, 425 insertions(+) create mode 100644 PhysicsTools/NanoAOD/plugins/MuonSpecialVariables.cc create mode 100644 PhysicsTools/NanoAOD/plugins/pfTracksProducer.cc create mode 100644 PhysicsTools/NanoAOD/python/custom_muon_cff.py diff --git a/Configuration/PyReleaseValidation/python/relval_steps.py b/Configuration/PyReleaseValidation/python/relval_steps.py index 08eebf619db79..54ea44341bd08 100644 --- a/Configuration/PyReleaseValidation/python/relval_steps.py +++ b/Configuration/PyReleaseValidation/python/relval_steps.py @@ -3895,6 +3895,7 @@ def gen2022HiMix(fragment,howMuch): steps['NANOUP17'] = merge([{'--conditions':'auto:phase1_2017_realistic','--era': 'Run2_2017','-n':'10' ,'--filein':'file:step3_inMINIAODSIM.root', '--geometry':'DB:Extended', '--nThreads':'2'}, stepNanoEDMMCProd]) steps['NANOUP15Had']=merge([{'--filein':'file:step4_inMINIAODSIM.root'},steps['NANOUP15']]) steps['NANOUP15MC_PU25_JME']=merge([{'--customise':'PhysicsTools/NanoAOD/custom_jme_cff.PrepJMECustomNanoAOD_MC'},steps['NANOUP15']]) +steps['NANOUP15MC_PU25_Muon']=merge([{'--customise':'PhysicsTools/NanoAOD/custom_muon_cff.PrepMuonCustomNanoAOD'},steps['NANOUP15']]) steps['NANOUP17Had']=merge([{'--filein':'file:step4_inMINIAODSIM.root'},steps['NANOUP17']]) steps['NANOUP18'] = merge([{'--conditions': 'auto:phase1_2018_realistic', '--era': 'Run2_2018','-n':'10', '--filein':'file:step3_inMINIAODSIM.root', '--nThreads':'2'}, stepNanoEDMMCProd ]) steps['NANOUP18Had']=merge([{'--filein':'file:step4_inMINIAODSIM.root'},steps['NANOUP18']]) diff --git a/PhysicsTools/NanoAOD/plugins/MuonSpecialVariables.cc b/PhysicsTools/NanoAOD/plugins/MuonSpecialVariables.cc new file mode 100644 index 0000000000000..af2e41190c806 --- /dev/null +++ b/PhysicsTools/NanoAOD/plugins/MuonSpecialVariables.cc @@ -0,0 +1,120 @@ +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "DataFormats/Common/interface/View.h" + +#include "DataFormats/PatCandidates/interface/UserData.h" +#include "PhysicsTools/PatAlgos/interface/PATUserDataMerger.h" + +#include "DataFormats/MuonReco/interface/Muon.h" +#include "DataFormats/MuonReco/interface/MuonSelectors.h" +#include "DataFormats/PatCandidates/interface/Muon.h" + +#include "DataFormats/VertexReco/interface/Vertex.h" +#include "DataFormats/VertexReco/interface/VertexFwd.h" + +#include "DataFormats/PatCandidates/interface/PackedCandidate.h" +#include "DataFormats/TrackReco/interface/Track.h" +#include "DataFormats/Math/interface/deltaR.h" +#include "DataFormats/MuonReco/interface/MuonSimInfo.h" +#include "MuonAnalysis/MuonAssociators/interface/PropagateToMuon.h" + +class MuonSpecialVariables : public edm::stream::EDProducer<> { +public: + explicit MuonSpecialVariables(const edm::ParameterSet &iConfig) + : muonSrc_(consumes>(iConfig.getParameter("muonSrc"))), + vertexSrc_(consumes>(iConfig.getParameter("vertexSrc"))), + trkSrc_(consumes(iConfig.getParameter("trkSrc"))) { + produces>(); + } + ~MuonSpecialVariables() override {} + + void setArbitratedTracker(pat::Muon &mu) const; + void setInnerTrackDxyz(pat::Muon &mu, const reco::Vertex &vtx) const; + void setTrkiso04(pat::Muon &mu, const std::vector tracks) const; + void setNSegements(pat::Muon &mu) const; + +private: + void produce(edm::Event &iEvent, const edm::EventSetup &iSetup) override; + + edm::EDGetToken muonSrc_; + edm::EDGetToken vertexSrc_; + edm::EDGetToken trkSrc_; +}; + +void MuonSpecialVariables::setArbitratedTracker(pat::Muon &mu) const { + mu.addUserInt("isArbitratedTracker", muon::isGoodMuon(mu, muon::TrackerMuonArbitrated)); +} + +void MuonSpecialVariables::setInnerTrackDxyz(pat::Muon &mu, const reco::Vertex &vtx) const { + float innerTrackDxy = + mu.innerTrack().isNonnull() ? mu.innerTrack()->dxy(reco::TrackBase::Point(vtx.x(), vtx.y(), vtx.z())) : -999.9; + float innerTrackDz = + mu.innerTrack().isNonnull() ? mu.innerTrack()->dz(reco::TrackBase::Point(vtx.x(), vtx.y(), vtx.z())) : -999.9; + mu.addUserFloat("innerTrackDxy", innerTrackDxy); + mu.addUserFloat("innerTrackDz", innerTrackDz); +} + +void MuonSpecialVariables::setTrkiso04(pat::Muon &mu, const std::vector tracks) const { + float energy = 0; + for (const auto &trk : tracks) { + if (deltaR(mu.eta(), mu.phi(), trk.eta(), trk.phi()) > 0.4) + continue; + energy += trk.pt(); + } + float Trkiso04 = (energy - mu.pt()) / mu.pt(); + float relTrkiso4 = (Trkiso04 > 0) ? Trkiso04 : 0; + mu.addUserFloat("relTrkiso4", relTrkiso4); +} + +void MuonSpecialVariables::setNSegements(pat::Muon &mu) const { + int nsegments = 0; + for (auto &chamber : mu.matches()) { + if (chamber.id.det() != DetId::Muon) + continue; + if (chamber.id.subdetId() != MuonSubdetId::DT && chamber.id.subdetId() != MuonSubdetId::CSC) + continue; + nsegments += chamber.segmentMatches.size(); + } + mu.addUserInt("nsegments", nsegments); +} + +void MuonSpecialVariables::produce(edm::Event &iEvent, const edm::EventSetup &iSetup) { + edm::Handle> muonSrc; + iEvent.getByToken(muonSrc_, muonSrc); + + edm::Handle> vertices; + iEvent.getByToken(vertexSrc_, vertices); + + edm::Handle trkCollection; + iEvent.getByToken(trkSrc_, trkCollection); + + std::unique_ptr> muonCollection(new std::vector(*muonSrc)); + + std::unique_ptr> out(new std::vector()); + + out->reserve(muonCollection->size()); + + for (unsigned int i = 0; i < muonCollection->size(); i++) { + pat::Muon &mu = (*muonCollection).at(i); + setArbitratedTracker(mu); + int good_vertex = 0; + for (auto &vtx : *vertices) { + if (vtx.isFake() || !vtx.isValid()) + continue; + setInnerTrackDxyz(mu, vtx); + good_vertex = 1; + break; + } + mu.addUserInt("isGoodVertex", good_vertex); + setTrkiso04(mu, *trkCollection); + setNSegements(mu); + out->push_back(mu); + } + + iEvent.put(std::move(out)); +} + +#include "FWCore/Framework/interface/MakerMacros.h" +DEFINE_FWK_MODULE(MuonSpecialVariables); diff --git a/PhysicsTools/NanoAOD/plugins/pfTracksProducer.cc b/PhysicsTools/NanoAOD/plugins/pfTracksProducer.cc new file mode 100644 index 0000000000000..061dcbc17197a --- /dev/null +++ b/PhysicsTools/NanoAOD/plugins/pfTracksProducer.cc @@ -0,0 +1,66 @@ +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/InputTag.h" +#include "DataFormats/Common/interface/View.h" + +#include "DataFormats/PatCandidates/interface/UserData.h" +#include "PhysicsTools/PatAlgos/interface/PATUserDataMerger.h" +#include "CommonTools/Utils/interface/StringCutObjectSelector.h" + +#include "DataFormats/VertexReco/interface/Vertex.h" +#include "DataFormats/VertexReco/interface/VertexFwd.h" + +#include "DataFormats/PatCandidates/interface/PackedCandidate.h" +#include "DataFormats/TrackReco/interface/Track.h" +#include "DataFormats/Math/interface/deltaR.h" +#include "DataFormats/MuonReco/interface/MuonSimInfo.h" +#include "MuonAnalysis/MuonAssociators/interface/PropagateToMuon.h" + +class pfTracksProducer : public edm::stream::EDProducer<> { +public: + explicit pfTracksProducer(const edm::ParameterSet& iConfig) + : PFCands_(consumes>(iConfig.getParameter("PFCands"))), + LostTracks_(consumes>(iConfig.getParameter("lostTracks"))), + trkSelection_(iConfig.getParameter("trkSelection")), + HighPurity_(iConfig.getParameter("TrkHPurity")) { + produces(); + } + ~pfTracksProducer() override {} + +private: + void produce(edm::Event& iEvent, const edm::EventSetup& iSetup) override; + + edm::EDGetToken PFCands_; + edm::EDGetToken LostTracks_; + const StringCutObjectSelector trkSelection_; + const bool HighPurity_; +}; + +void pfTracksProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) { + edm::Handle> pfcands; + iEvent.getByToken(PFCands_, pfcands); + + edm::Handle> lostTracks; + iEvent.getByToken(LostTracks_, lostTracks); + + std::unique_ptr> tracks(new std::vector()); + tracks->reserve(pfcands->size() + lostTracks->size()); + + for (const auto& container : {pfcands, lostTracks}) { + for (const pat::PackedCandidate& trk : *container) { + if (!trk.hasTrackDetails()) + continue; + if (!trkSelection_(trk)) + continue; + if (HighPurity_ && !trk.trackHighPurity()) + continue; + tracks->emplace_back(*trk.bestTrack()); + } + } + + iEvent.put(std::move(tracks)); +} + +#include "FWCore/Framework/interface/MakerMacros.h" +DEFINE_FWK_MODULE(pfTracksProducer); diff --git a/PhysicsTools/NanoAOD/python/custom_muon_cff.py b/PhysicsTools/NanoAOD/python/custom_muon_cff.py new file mode 100644 index 0000000000000..27d1ecc09cc19 --- /dev/null +++ b/PhysicsTools/NanoAOD/python/custom_muon_cff.py @@ -0,0 +1,238 @@ +import FWCore.ParameterSet.Config as cms + +from PhysicsTools.NanoAOD.nano_eras_cff import * +from PhysicsTools.NanoAOD.simpleCandidateFlatTableProducer_cfi import simpleCandidateFlatTableProducer + +from PhysicsTools.NanoAOD.common_cff import Var, P3Vars, P4Vars +from PhysicsTools.NanoAOD.muons_cff import muonTable, finalMuons + +def Custom_Muon_Task(process): + process.nanoTableTaskCommon.remove(process.electronTablesTask) + process.nanoTableTaskCommon.remove(process.lowPtElectronTablesTask) + process.nanoTableTaskCommon.remove(process.photonTablesTask) + process.nanoTableTaskCommon.remove(process.metTablesTask) + process.nanoTableTaskCommon.remove(process.tauTablesTask) + process.nanoTableTaskCommon.remove(process.boostedTauTablesTask) + process.nanoTableTaskCommon.remove(process.jetPuppiTablesTask) + process.nanoTableTaskCommon.remove(process.jetAK8TablesTask) + + process.nanoTableTaskFS.remove(process.electronMCTask) + process.nanoTableTaskFS.remove(process.lowPtElectronMCTask) + process.nanoTableTaskFS.remove(process.photonMCTask) + process.nanoTableTaskFS.remove(process.jetMCTask) + process.nanoTableTaskFS.remove(process.tauMCTask) + process.nanoTableTaskFS.remove(process.boostedTauMCTask) + process.nanoTableTaskFS.remove(process.metMCTable) + process.nanoTableTaskFS.remove(process.ttbarCatMCProducersTask) + process.nanoTableTaskFS.remove(process.ttbarCategoryTableTask) + + return process + +def AddPFTracks(proc): + pfTracks = "pfTracks" + setattr(proc, pfTracks, cms.EDProducer("pfTracksProducer", + PFCands=cms.InputTag("packedPFCandidates"), + lostTracks=cms.InputTag("lostTracks"), + TrkHPurity = cms.bool(False), + trkSelection = cms.string("bestTrack.pt()>5 && abs(bestTrack.eta())<2.4 "), + ) + ) + + pfTracksTable = "pfTracksTable" + setattr(proc, pfTracksTable, cms.EDProducer("SimpleTrackFlatTableProducer", + src = cms.InputTag("pfTracks"), + cut = cms.string("pt > 15"), # filtered already above + name = cms.string("Track"), + doc = cms.string("General tracks with pt > 15 GeV"), + singleton = cms.bool(False), # the number of entries is variable + extension = cms.bool(False), # this is the main table for the muons + variables = cms.PSet(P3Vars, + dz = Var("dz",float,doc="dz (with sign) wrt first PV, in cm",precision=10), + dxy = Var("dxy",float,doc="dxy (with sign) wrt first PV, in cm",precision=10), + charge = Var("charge", int, doc="electric charge"), + normChiSq = Var("normalizedChi2", float, precision=14, doc="Chi^2/ndof"), + numberOfValidHits = Var('numberOfValidHits()', 'int', precision=-1, doc='Number of valid hits in track'), + numberOfLostHits = Var('numberOfLostHits()', 'int', precision=-1, doc='Number of lost hits in track'), + trackAlgo = Var('algo()', 'int', precision=-1, doc='Track algo enum, check DataFormats/TrackReco/interface/TrackBase.h for details.'), + trackOriginalAlgo = Var('originalAlgo()', 'int', precision=-1, doc='Track original algo enum'), + qualityMask = Var('qualityMask()', 'int', precision=-1, doc='Quality mask of the track.'), + extraIdx = Var('extra().key()', 'int', precision=-1, doc='Index of the TrackExtra in the original collection'), + vx = Var('vx', 'float', precision=-1, doc='Track X position'), + vy = Var('vy', 'float', precision=-1, doc='Track Y position'), + vz = Var('vz', 'float', precision=-1, doc='Track Z position'), + ), + ) + ) + + pfTracksTask = "pfTracksTask" + setattr(proc,pfTracksTask, cms.Task( + getattr(proc,pfTracks) + ) + ) + + pfTracksTableTask = "pfTracksTableTask" + setattr(proc,pfTracksTableTask, cms.Task( + getattr(proc,pfTracksTable) + ) + ) + proc.nanoTableTaskCommon.add(getattr(proc,pfTracksTask)) + proc.nanoTableTaskCommon.add(getattr(proc,pfTracksTableTask)) + + return proc + + + +def AddVariablesForMuon(proc): + + muonWithVariables = "muonWithVariables" + setattr(proc, muonWithVariables, cms.EDProducer("MuonSpecialVariables", + muonSrc=cms.InputTag("slimmedMuons"), + vertexSrc=cms.InputTag("offlineSlimmedPrimaryVertices"), + trkSrc=cms.InputTag("pfTracks"), + ) + ) + getattr(proc,"muonTask").add(getattr(proc,muonWithVariables)) + + proc.slimmedMuonsUpdated.src = cms.InputTag("muonWithVariables") + #proc.muonMVATTH.src = cms.InputTag("muonWithVariables") + #proc.muonMVALowPt.src = cms.InputTag("muonWithVariables") + #proc.muonTable.src = cms.InputTag("muonWithVariables") + #proc.muonMCTable.src = cms.InputTag("muonWithVariables") + #proc.muonsMCMatchForTable.src = cms.InputTag("muonWithVariables") + + + #SandAlone Variables + proc.muonTable.variables.standalonePt = Var("? standAloneMuon().isNonnull() ? standAloneMuon().pt() : -1", float, doc = "pt of the standalone muon", precision=14) + proc.muonTable.variables.standaloneEta = Var("? standAloneMuon().isNonnull() ? standAloneMuon().eta() : -99", float, doc = "eta of the standalone muon", precision=14) + proc.muonTable.variables.standalonePhi = Var("? standAloneMuon().isNonnull() ? standAloneMuon().phi() : -99", float, doc = "phi of the standalone muon", precision=14) + proc.muonTable.variables.standaloneCharge = Var("? standAloneMuon().isNonnull() ? standAloneMuon().charge() : -99", float, doc = "phi of the standalone muon", precision=14) + + # Inner Track Algo variables + proc.muonTable.variables.innerTrackAlgo = Var('? innerTrack().isNonnull() ? innerTrack().algo() : -99', 'int', precision=-1, doc='Track algo enum, check DataFormats/TrackReco/interface/TrackBase.h for details.') + proc.muonTable.variables.innerTrackOriginalAlgo = Var('? innerTrack().isNonnull() ? innerTrack().originalAlgo() : -99', 'int', precision=-1, doc='Track original algo enum') + + #Spark Tool Iso 03 variables + proc.muonTable.variables.pfAbsIso03_neu = Var("pfIsolationR03().sumNeutralHadronEt",float,doc="PF absolute isolation dR=0.3, neutral component") + proc.muonTable.variables.pfAbsIso03_pho = Var("pfIsolationR03().sumPhotonEt",float,doc="PF absolute isolation dR=0.3, photon component") + proc.muonTable.variables.pfAbsIso03_sumPU = Var("pfIsolationR03().sumPUPt",float,doc="PF absolute isolation dR=0.3, pu component (no deltaBeta corrections)") + + # Spark Tool Iso 04 variables + proc.muonTable.variables.pfAbsIso04_chg = Var("pfIsolationR04().sumChargedHadronPt",float,doc="PF absolute isolation dR=0.4, charged component") + proc.muonTable.variables.pfAbsIso04_neu = Var("pfIsolationR04().sumNeutralHadronEt",float,doc="PF absolute isolation dR=0.4, neutral component") + proc.muonTable.variables.pfAbsIso04_pho = Var("pfIsolationR04().sumPhotonEt",float,doc="PF absolute isolation dR=0.4, photon component") + proc.muonTable.variables.pfAbsIso04_sumPU = Var("pfIsolationR04().sumPUPt",float,doc="PF absolute isolation dR=0.4, pu component (no deltaBeta corrections)") + + #Mini PF Isolation + proc.muonTable.variables.miniPFAbsIso_chg = Var("userFloat('miniIsoChg')",float,doc="mini PF absolute isolation, charged component") + proc.muonTable.variables.miniPFAbsIso_all = Var("userFloat('miniIsoAll')",float,doc="mini PF absolute isolation, total (with scaled rho*EA PU corrections)") + proc.muonTable.variables.miniPFAbsIso_neu = Var("miniPFIsolation().neutralHadronIso()",float,doc="mini PF absolute isolation, neutral component") + proc.muonTable.variables.miniPFAbsIso_pho = Var("miniPFIsolation().photonIso()", float, doc="mini PF absolute isolation, photon component") + + # Absolute Isolations for variables already present in Standard NanoAOD as Relative Isolation + proc.muonTable.variables.tkAbsIso = Var("isolationR03().sumPt",float,doc="Tracker-based absolute isolation dR=0.3 for highPt, trkIso",precision=6) + proc.muonTable.variables.pfAbsIso03_chg = Var("pfIsolationR03().sumChargedHadronPt",float,doc="PF absolute isolation dR=0.3, charged component") + proc.muonTable.variables.pfAbsIso03_all = Var("(pfIsolationR03().sumChargedHadronPt + max(pfIsolationR03().sumNeutralHadronEt + pfIsolationR03().sumPhotonEt - pfIsolationR03().sumPUPt/2,0.0))",float,doc="PF absolute isolation dR=0.3, total (deltaBeta corrections)") + proc.muonTable.variables.pfAbsIso04_all = Var("(pfIsolationR04().sumChargedHadronPt + max(pfIsolationR04().sumNeutralHadronEt + pfIsolationR04().sumPhotonEt - pfIsolationR04().sumPUPt/2,0.0))",float,doc="PF absolute isolation dR=0.4, total (deltaBeta corrections)") + proc.muonTable.variables.jetAbsIso = Var("?userCand('jetForLepJetVar').isNonnull()?(1./userFloat('ptRatio'))-1.:(pfIsolationR04().sumChargedHadronPt + max(pfIsolationR04().sumNeutralHadronEt + pfIsolationR04().sumPhotonEt - pfIsolationR04().sumPUPt/2,0.0))",float,doc="Absolute isolation in matched jet (1/ptRatio-1, pfRelIso04_all if no matched jet)",precision=8) + proc.muonTable.variables.relTrkiso4 = Var("userFloat('relTrkiso4')",float,doc="Realtive Tracker Iso with cone size 0.4") + + # Muon Quality Variables + proc.muonTable.variables.expectedMatchedStations = Var("expectedNnumberOfMatchedStations()",int,doc="Expected Number of Matched stations") + proc.muonTable.variables.RPCLayers = Var("numberOfMatchedRPCLayers()",int,doc="Number of RPC Layers") + proc.muonTable.variables.stationMask = Var("stationMask()","uint8",doc="Number of masked station") + proc.muonTable.variables.nShowers = Var("numberOfShowers()",int,doc="Number of Showers") + proc.muonTable.variables.muonHits = Var("? globalTrack().isNonnull() ? globalTrack().hitPattern().numberOfValidMuonHits() : ? innerTrack().isNonnull() && innerTrack().isAvailable() ? innerTrack().hitPattern().numberOfValidMuonHits() :-99",float,doc="Number of valid Muon Hits from either globalTrack or innerTrack") + ## For completeness I save here also the muonHits for the outer tracker also + proc.muonTable.variables.outerTrackMuonHits = Var("? outerTrack().isNonnull() ? outerTrack().hitPattern().numberOfValidMuonHits() : -99", float, doc = "Number of valid Muon Hits from OuterTrack") + ## + proc.muonTable.variables.pixelLayers = Var("? innerTrack().isNonnull() && innerTrack().isAvailable() ? innerTrack().hitPattern().pixelLayersWithMeasurement() : -99", float,doc="Number of Pixel Layers") # No of tracker layers are already saved in the standard NanoAODs + proc.muonTable.variables.validFraction = Var("? innerTrack().isNonnull() && innerTrack().isAvailable() ? innerTrack().validFraction() : -99", float, doc="Inner Track Valid Fraction") + proc.muonTable.variables.pixelHits = Var("? innerTrack().isNonnull() && innerTrack().isAvailable() ? innerTrack().hitPattern().numberOfValidPixelHits() : -99", float, doc="Numbr of valid pixel hits") + proc.muonTable.variables.muonStations = Var("? outerTrack().isNonnull() && outerTrack().isAvailable() ? outerTrack().hitPattern().muonStationsWithValidHits() : -99", float, doc="No of valid hits in muon stations") + proc.muonTable.variables.DTHits = Var("? outerTrack().isNonnull() && outerTrack().isAvailable() ? outerTrack().hitPattern().numberOfValidMuonDTHits() : -99", float, doc="No of valid hits in DT") + proc.muonTable.variables.CSCHits = Var("? outerTrack().isNonnull() && outerTrack().isAvailable() ? outerTrack().hitPattern().numberOfValidMuonCSCHits() : -99", float, doc="No of valid hits in CSC") + proc.muonTable.variables.RPCHits = Var("? outerTrack().isNonnull() && outerTrack().isAvailable() ? outerTrack().hitPattern().numberOfValidMuonRPCHits() : -99", float, doc="No of valid hits in RPC") + + + + # Chi2 related to different tracks + proc.muonTable.variables.trkChi2 = Var("? globalTrack().isNonnull() ? globalTrack().normalizedChi2() : ? innerTrack().isNonnull() && innerTrack().isAvailable() ? innerTrack().normalizedChi2() : -99",float,doc="Normalized Chi Square from either globalTrack or innerTrack ") + proc.muonTable.variables.trkChi2_outerTrack = Var("? outerTrack().isNonnull() && outerTrack().isAvailable() ? outerTrack().normalizedChi2() : -99",float,doc="Normalized Chi Square from outerTrack ") + proc.muonTable.variables.trkChi2_innerTrack = Var("? innerTrack().isNonnull() && innerTrack().isAvailable() ? innerTrack().normalizedChi2() : -99",float,doc="Normalized Chi Square from outerTrack ") + + + #pt, ptErr, eta, phi, charge for different tracks + ## ptErr in standard NanoAOD are saved from bestTrack() + ## For Spark tool it is needed from innerTrack. For completeness outerTrack + ## variables are also saved + proc.muonTable.variables.innerTrack_ptErr = Var("? innerTrack().isNonnull() && innerTrack().isAvailable() ? innerTrack().ptError()/innerTrack().pt() : -99", float, doc="InnerTrack Pt Error") + proc.muonTable.variables.outerTrack_ptErr = Var("? outerTrack().isNonnull() && outerTrack().isAvailable() ? outerTrack().ptError()/outerTrack().pt() : -99", float, doc="OuterTrack Pt Error") + proc.muonTable.variables.outerTrack_pt = Var("? outerTrack().isNonnull() && outerTrack().isAvailable() ? outerTrack().pt(): -99", float, doc="OuterTrack Pt") + proc.muonTable.variables.outerTrack_eta = Var("? outerTrack().isNonnull() && outerTrack().isAvailable() ? outerTrack().eta(): -99", float, doc="OuterTrack Eta") + proc.muonTable.variables.outerTrack_phi = Var("? outerTrack().isNonnull() && outerTrack().isAvailable() ? outerTrack().phi(): -99", float, doc="OuterTrack Phi") + proc.muonTable.variables.outerTrack_charge = Var("? outerTrack().isNonnull() && outerTrack().isAvailable() ? outerTrack().charge(): -99", float, doc="OuterTrack charge") + proc.muonTable.variables.innerTrack_charge = Var("? innerTrack().isNonnull() && innerTrack().isAvailable() ? innerTrack().charge(): -99", float, doc="OuterTrack charge") + + + # TuneP related variables + proc.muonTable.variables.tuneP_pt = Var("? tunePMuonBestTrack().isNonnull() ? tunePMuonBestTrack().pt() : -99", float, doc = "pT from tunePMuonBestTrack") + proc.muonTable.variables.tuneP_pterr = Var("? tunePMuonBestTrack().isNonnull() ? tunePMuonBestTrack().ptError() : -99", float, doc = "pTerr from tunePMuonBestTrack") + proc.muonTable.variables.tuneP_muonHits = Var("? tunePMuonBestTrack().isNonnull() ? tunePMuonBestTrack().hitPattern().numberOfValidMuonHits() : -99", int, doc="No of valid muon hists from tunePMuonBestTrack") + + + #CombinedQuality Variables + proc.muonTable.variables.positionChi2 = Var("combinedQuality().chi2LocalPosition", float, doc="chi2 Local Position") + proc.muonTable.variables.momentumChi2 = Var("combinedQuality().chi2LocalMomentum", float, doc="chi2 Local Momentum") + proc.muonTable.variables.trkKink = Var("combinedQuality().trkKink", float, doc="Track Kink") + proc.muonTable.variables.glbKink = Var("combinedQuality().glbKink", float, doc="Glb Kink") + proc.muonTable.variables.glbTrackProbability = Var("combinedQuality().glbTrackProbability", float, doc="Glb Track Probability") + proc.muonTable.variables.trkRelChi2 = Var("combinedQuality().trkRelChi2",float,doc="Track Rel Chi2") + + #timAtIpInOutErr + proc.muonTable.variables.timAtIpInOutErr = Var("time().timeAtIpInOutErr",float,doc="timAtIpInOutErr") + + #isArbitratedTracker + proc.muonTable.variables.isArbitratedTracker = Var("userInt('isArbitratedTracker')", bool, doc = "s Arbitrated Tracker") + + #ExtraidX + proc.muonTable.variables.standaloneExtraIdx = Var('? standAloneMuon().isNonnull() ? standAloneMuon().extra().key() : -99', 'int', precision=-1, doc='Index of the StandAloneTrack TrackExtra in the original collection') + proc.muonTable.variables.innerTrackExtraIdx = Var('? innerTrack().isNonnull() ? innerTrack().extra().key() : -99', 'int', precision=-1, doc='Index of the innerTrack TrackExtra in the original collection') + + #Jet Related Variables + proc.muonTable.variables.jetPtRatio = Var("?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)", float, doc="ptRatio using the LepAware JEC approach, for muon MVA") + proc.muonTable.variables.jetDF = Var("?userCand('jetForLepJetVar').isNonnull()?max(userCand('jetForLepJetVar').bDiscriminator('pfDeepFlavourJetTags:probbb')+userCand('jetForLepJetVar').bDiscriminator('pfDeepFlavourJetTags:probb')+userCand('jetForLepJetVar').bDiscriminator('pfDeepFlavourJetTags:problepb'),0.0):0.0",float,doc="b-tagging discriminator of the jet matched to the lepton, for muon MVA") + proc.muonTable.variables.jetCSVv2 = Var("?userCand('jetForLepJetVar').isNonnull()?max(userCand('jetForLepJetVar').bDiscriminator('pfCombinedSecondaryVertexV2BJetTags'),0.0):0.0",float,doc="CSVv2 b-tagging discriminator of the jet matched to the lepton, for muon MVA") + + #Dxy Dz variables as of Spark tool + proc.muonTable.variables.innerTrackDxy = Var("? userInt('isGoodVertex') ? userFloat('innerTrackDxy') : -99.9",float,doc = "dxy from Primary Vertex calculated with Inner Track") + proc.muonTable.variables.innerTrackDz = Var("? userInt('isGoodVertex') ? userFloat('innerTrackDz') : -99.9",float,doc= "dz from Primary Vertex calculated with Inner Track") + + #nSegments + proc.muonTable.variables.nsegments = Var("userInt('nsegments')", int, doc = "nsegments as of Spark-tool") + + #Sim Variables + proc.muonTable.variables.simType = Var("? simType() ? simType() : -99",int,doc="simType") + proc.muonTable.variables.simExtType = Var("? simExtType() ? simExtType() : -99",int,doc="simExtType") + proc.muonTable.variables.simFlavour = Var("? simFlavour() ? simFlavour() : -99",int,doc="simFlavour") + proc.muonTable.variables.simHeaviestMotherFlavour = Var(" ? simHeaviestMotherFlavour() ? simHeaviestMotherFlavour() : -99",int,doc="simHeaviestMotherFlavour") + proc.muonTable.variables.simPdgId = Var("? simPdgId() ? simPdgId() : -99",int,doc="simPdgId") + proc.muonTable.variables.simMotherPdgId = Var("? simMotherPdgId() ? simMotherPdgId() : -99",int,doc="simMotherPdgId") + proc.muonTable.variables.simBX = Var("? simBX() ? simBX() : -99",int,doc="simBX") + proc.muonTable.variables.simProdRho = Var("? simProdRho() ? simProdRho(): -99",float,doc="simProdRho") + proc.muonTable.variables.simProdZ = Var("? simProdZ() ? simProdZ(): -99",float,doc="simProdZ") + proc.muonTable.variables.simPt = Var("? simPt() ? simPt(): -99",float,doc="simPt") + proc.muonTable.variables.simEta = Var("? simEta() ? simEta(): -99",float,doc="simEta") + proc.muonTable.variables.simPhi = Var("? simPhi() ? simPhi(): -99",float,doc='simPhi') + + + return proc + + +def PrepMuonCustomNanoAOD(process): + + process = Custom_Muon_Task(process) + process = AddPFTracks(process) + process = AddVariablesForMuon(process) + + + return process