def get_scalefactor(objType, key, periods=None, combine=None, additionalVariables=dict(), getFlavour=None, systName=None): return scalefactors.get_scalefactor(objType, key, periods=periods, combine=combine, additionalVariables=additionalVariables, sfLib=all_scalefactors, paramDefs=binningVariables, getFlavour=getFlavour, systName=systName)
def get_scalefactor(self, objType, key, periods=None, combine=None, additionalVariables=dict(), systName=None, defineOnFirstUse=True): paramDefs = self.binningVariables if additionalVariables is not None: paramDefs.update(additionalVariables) return scalefactors.get_scalefactor( objType=objType, key=key, periods=periods, combine=combine, sfLib=self.all_scalefactors, paramDefs=paramDefs, getFlavour=(lambda j: j.hadronFlavour), systName=systName, defineOnFirstUse=defineOnFirstUse)
def definePlots(self, t, noSel, sample=None, sampleCfg=None): if 'type' not in sampleCfg.keys() or sampleCfg["type"] != "signal": raise RuntimeError("Sample needs to be HH signal LO GGF sample") era = sampleCfg.get("era") if sampleCfg else None # Select gen level Higgs # genh = op.select( t.GenPart, lambda g: op.AND(g.pdgId == 25, g.statusFlags & (0x1 << 13))) HH_p4 = genh[0].p4 + genh[1].p4 cm = HH_p4.BoostToCM() boosted_h = op.extMethod("ROOT::Math::VectorUtil::boost", returnType=genh[0].p4._typeName)(genh[0].p4, cm) mHH = op.invariant_mass(genh[0].p4, genh[1].p4) cosHH = op.abs(boosted_h.Pz() / boosted_h.P()) # Apply reweighting # benchmarks = [ 'BenchmarkSM', 'Benchmark1', 'Benchmark2', 'Benchmark3', 'Benchmark4', 'Benchmark5', 'Benchmark6', 'Benchmark7', 'Benchmark8', 'Benchmark8a', 'Benchmark9', 'Benchmark10', 'Benchmark11', 'Benchmark12', 'BenchmarkcHHH0', 'BenchmarkcHHH1', 'BenchmarkcHHH2p45', 'BenchmarkcHHH5', 'Benchmarkcluster1', 'Benchmarkcluster2', 'Benchmarkcluster3', 'Benchmarkcluster4', 'Benchmarkcluster5', 'Benchmarkcluster6', 'Benchmarkcluster7', ] selections = {'': noSel} reweights = {} if self.args.reweighting: for benchmark in benchmarks: json_file = os.path.join( os.path.abspath(os.path.dirname(__file__)), 'data', 'ScaleFactors_GGF_LO', '{}_to_{}_{}.json'.format(sample, benchmark, era)) if os.path.exists(json_file): print("Found file {}".format(json_file)) reweightLO = get_scalefactor("lepton", json_file, paramDefs={ 'Eta': lambda x: mHH, 'Pt': lambda x: cosHH }) selections[benchmark] = SelectionWithDataDriven.create( parent=noSel, name='noSel' + benchmark, ddSuffix=benchmark, cut=op.c_bool(True), ddCut=op.c_bool(True), weight=op.c_float(1.), ddWeight=reweightLO(op.c_float(1.)), enable=True) reweights[benchmark] = reweightLO(op.c_float(1.)) else: print("Could not find file {}".format(json_file)) # Plots # plots = [] for name, reweight in reweights.items(): plots.append( Plot.make1D("weight_{}".format(name), reweight, noSel, EquidistantBinning(100, 0, 5.), xTitle='weight')) for selName, sel in selections.items(): plots.append( Plot.make2D( f"mHHvsCosThetaStar{selName}", [mHH, cosHH], sel, [ VariableBinning([ 250., 270., 290., 310., 330., 350., 370., 390., 410., 430., 450., 470., 490., 510., 530., 550., 570., 590., 610., 630., 650., 670., 700., 750., 800., 850., 900., 950., 1000., 1100., 1200., 1300., 1400., 1500., 1750., 2000., 5000. ]), VariableBinning([0.0, 0.4, 0.6, 0.8, 1.0]) ], xTitle='m_{HH}', yTitle='cos(#theta^{*})')) plots.append( Plot.make1D(f"mHH{selName}", mHH, sel, VariableBinning([ 250., 270., 290., 310., 330., 350., 370., 390., 410., 430., 450., 470., 490., 510., 530., 550., 570., 590., 610., 630., 650., 670., 700., 750., 800., 850., 900., 950., 1000., 1100., 1200., 1300., 1400., 1500., 1750., 2000., 5000. ]), xTitle='m_{HH}')) plots.append( Plot.make1D(f"cosThetaStar{selName}", cosHH, sel, VariableBinning([0.0, 0.4, 0.6, 0.8, 1.0]), xTitle='cos(#theta^{*})')) return plots
def definePlots(self, t, noSel, sample=None, sampleCfg=None): from bamboo.plots import Plot, CutFlowReport, SummedPlot from bamboo.plots import EquidistantBinning as EqB from bamboo import treefunctions as op isMC = self.isMC(sample) trigCut, trigWeight = None, None if isMC: noSel = noSel.refine("mcWeight", weight=[ t.genWeight, t.puWeight, t.PrefireWeight ]) trigCut = op.OR(t.HLT.HIEle20_Ele12_CaloIdL_TrackIdL_IsoVL_DZ, t.HLT.HIL3DoubleMu0, t.HLT.HIL3Mu20, t.HLT.HIEle20_WPLoose_Gsf) ## TODO add a correction for prescaled triggers else: ## suggested trigger order: dielectron, dimuon or single muon, single electron (to minimise loss due to prescales). Electron triggered-events should be taken from the HighEGJet primary datasets, muon-triggered events from the SingleMuon primary datset pd = sample.split("_")[0] if pd == "SingleMuon": ## TODO fill trigger cut elif pd == "HighEGJet": ## TODO fill trigger cut noSel = noSel.refine("trig", cut=trigCut, weight=trigWeight) plots = [] goodLeptons = { "el" : op.select(t.Electron, partial(isGoodElectron, ptCut=15.)), "mu" : op.select(t.Muon, partial(isGoodMuon, ptCut=15.)) } plots += [ Plot.make1D("trig_nLeptons15", op.rng_len(goodLeptons["el"])+op.rng_len(goodLeptons["mu"]), noSel, EqB(15, 0., 15.)), Plot.make1D("trig_nEl15", op.rng_len(goodLeptons["el"]), noSel, EqB(15, 0., 15.)), Plot.make1D("trig_nMu15", op.rng_len(goodLeptons["mu"]), noSel, EqB(15, 0., 15.)) ] from bamboo.scalefactors import get_scalefactor sf_loose = { "mu": get_scalefactor("lepton", "Muon_RecoToLoose", sfLib=scalefactors_lepMVA, paramDefs=binningVariables_nano_noScaleSyst, systName="muLoose"), "el": get_scalefactor("lepton", "Electron_RecoToLoose", sfLib=scalefactors_lepMVA, paramDefs=binningVariables_nano_noScaleSyst, systName="elLoose") } sf_tight = { "mu": get_scalefactor("lepton", "Muon_LooseToTight", sfLib=scalefactors_lepMVA, paramDefs=binningVariables_nano_noScaleSyst, systName="muTight"), "el": get_scalefactor("lepton", "Electron_LooseToTight", sfLib=scalefactors_lepMVA, paramDefs=binningVariables_nano_noScaleSyst, systName="elTight") } nGoodLeptons = op.rng_len(goodLeptons["el"])+op.rng_len(goodLeptons["mu"]) hasTwoGoodLeptons = noSel.refine("has2Lep", cut=(nGoodLeptons > 1)) # avoid overlap with 1l jets = op.sort(op.select(t.Jet, lambda j : op.AND( j.pt > 25., ## you decide... op.abs(j.eta) < 2.4, j.jetId & 0x2, ## tight JetID op.AND( ## lepton-jet cross-cleaning op.NOT(op.rng_any(goodLeptons["el"], lambda l : op.deltaR(l.p4, j.p4) < 0.4)), op.NOT(op.rng_any(goodLeptons["mu"], lambda l : op.deltaR(l.p4, j.p4) < 0.4))) )), lambda j : -j.pt) for fl1,fl2 in product(*repeat(goodLeptons.keys(), 2)): dilepSel = lambda l1,l2 : op.AND( l1.charge != l2.charge, (l1.p4+l2.p4).M() > 12. ) if fl1 == fl2: lGood = op.sort(goodLeptons[fl1], lambda l : -l.pt) dilep = op.combine(lGood, N=2, pred=dilepSel) else: l1Good = op.sort(goodLeptons[fl1], lambda l : -l.pt) l2Good = op.sort(goodLeptons[fl2], lambda l : -l.pt) dilep = op.combine((l1Good, l2Good), pred=dilepSel) ll = dilep[0] hasDilep = hasTwoGoodLeptons.refine(f"hasDilep{fl1}{fl2}", cut=(op.rng_len(dilep) > 0, ll[0].pt > 25.), weight=([ sf_loose[fl1](ll[0]), sf_loose[fl2](ll[1]), sf_tight[fl1](ll[0]), sf_tight[fl2](ll[1]) ] if isMC else None)) plots += [ Plot.make1D(f"dilepton_{fl1}{fl2}_Mll", (ll[0].p4+ll[1].p4).M(), hasDilep, EqB(50, 70, 120.), title="Dilepton mass"), ] for il,ifl in enumerate((fl1, fl2)): plots += [ Plot.make1D(f"dilepton_{fl1}{fl2}_L{il:d}PT", ll[il].pt, hasDilep, EqB(50, 0., 100.), title=f"Lepton {il:d} PT"), Plot.make1D(f"dilepton_{fl1}{fl2}_L{il:d}ETA", ll[il].eta, hasDilep, EqB(50, -2.5, 2.5), title=f"Lepton {il:d} ETA"), ] plots += [ Plot.make1D(f"dilepton_{fl1}{fl2}_nJets", op.rng_len(jets), hasDilep, EqB(15, 0, 15.), title="Jet multiplicity"), ] return plots
def definePlots(self, t, noSel, sample=None, sampleCfg=None): from bamboo.plots import Plot, CutFlowReport, SummedPlot from bamboo.plots import EquidistantBinning as EqB from bamboo import treefunctions as op isMC = self.isMC(sample) if sampleCfg.get("alt-syst"): noSel = noSel.refine("withoutsyst", autoSyst=False) plots = [] trigCut, trigWeight = None, None if isMC: muR = op.systematic(op.c_float(1.), name="muR", up=t.PSWeight[2], down=t.PSWeight[0]) muF = op.systematic(op.c_float(1.), name="muF", up=t.PSWeight[3], down=t.PSWeight[1]) noSel = noSel.refine( "mcWeight", weight=[t.genWeight, t.puWeight, t.PrefireWeight, muR, muF]) trigCut = op.OR(t.HLT.HIEle20_Ele12_CaloIdL_TrackIdL_IsoVL_DZ, t.HLT.HIL3DoubleMu0, t.HLT.HIL3Mu20, t.HLT.HIEle20_WPLoose_Gsf) trigWeight = op.switch( op.OR(t.HLT.HIEle20_Ele12_CaloIdL_TrackIdL_IsoVL_DZ, t.HLT.HIL3DoubleMu0), op.c_float(1.), op.switch(t.HLT.HIL3Mu20, op.c_float(306.913 / 308.545), op.c_float(264.410 / 308.545)) ) ## FIXME these are wrong - you will get the final values from team A else: ## trigger order: dielectron, dimuon or single muon, single electron pd = sample.split("_")[0] if pd == "SingleMuon": trigCut = op.AND( op.NOT(t.HLT.HIEle20_Ele12_CaloIdL_TrackIdL_IsoVL_DZ), op.OR(t.HLT.HIL3DoubleMu0, t.HLT.HIL3Mu20)) elif pd == "HighEGJet": trigCut = op.OR( t.HLT.HIEle20_Ele12_CaloIdL_TrackIdL_IsoVL_DZ, op.AND(op.NOT(op.OR(t.HLT.HIL3DoubleMu0, t.HLT.HIL3Mu20)), t.HLT.HIEle20_WPLoose_Gsf)) noSel = noSel.refine("trig", cut=trigCut, weight=trigWeight) #plots += [Plot.make1D("nTotalEvents", op.rng_len([1]), noSel , EqB(1, 0, 1.), title="nTotalEvents")] plots.append( Plot.make1D("nTotalJets", op.rng_len(t.Jet), noSel, EqB(15, 0, 15.), title="Initial Jet multiplicity")) #noSel = noSel.refine("trig", cut=op.OR(t.HLT.HIL3DoubleMu0, t.HLT.HIEle20_Ele12_CaloIdL_TrackIdL_IsoVL_DZ)) # plots = [] goodLeptons = { "el": op.select( t.Electron, lambda el: op.AND(el.pt > 15., op.abs(el.p4.Eta()) < 2.5) ), # op.select(t.Electron, partial(isGoodElectron, ptCut=15.)), "mu": op.select(t.Muon, lambda mu: mu.pt > 20. ) # op.select(t.Muon, partial(isGoodMuon, ptCut=15.)) } plots += [ Plot.make1D( "trig_nLeptons15", op.rng_len(goodLeptons["el"]) + op.rng_len(goodLeptons["mu"]), noSel, EqB(15, 0., 15.)), Plot.make1D("trig_nEl15", op.rng_len(goodLeptons["el"]), noSel, EqB(15, 0., 15.)), Plot.make1D("trig_nMu15", op.rng_len(goodLeptons["mu"]), noSel, EqB(15, 0., 15.)) ] from bamboo.scalefactors import get_scalefactor sf_loose = { "mu": get_scalefactor("lepton", "Muon_RecoToLoose", sfLib=scalefactors_lepMVA, paramDefs=binningVariables_nano_noScaleSyst, systName="muLoose"), "el": get_scalefactor("lepton", "Electron_RecoToLoose", sfLib=scalefactors_lepMVA, paramDefs=binningVariables_nano_noScaleSyst, systName="elLoose") } sf_tight = { "mu": get_scalefactor("lepton", "Muon_LooseToTight", sfLib=scalefactors_lepMVA, paramDefs=binningVariables_nano_noScaleSyst, systName="muTight"), "el": get_scalefactor("lepton", "Electron_LooseToTight", sfLib=scalefactors_lepMVA, paramDefs=binningVariables_nano_noScaleSyst, systName="elTight") } nGoodLeptons = op.rng_len(goodLeptons["el"]) + op.rng_len( goodLeptons["mu"]) hasTwoGoodLeptons = noSel.refine( "has2Lep", cut=(nGoodLeptons > 1)) # avoid overlap with 1l jets = op.sort( op.select( t.Jet, lambda j: op.AND( j.pt > 25., op.abs(j.eta) < 2.4, j.jetId & 0x2, op.AND( op.NOT( op.rng_any(goodLeptons["el"], lambda l: op.deltaR( l.p4, j.p4) < 0.4)), op.NOT( op.rng_any(goodLeptons["mu"], lambda l: op.deltaR( l.p4, j.p4) < 0.4))))), lambda j: -j.pt) ## WP: see https://twiki.cern.ch/twiki/bin/viewauth/CMS/BtagRecommendation94X loosebjets = op.select(jets, lambda j: j.btagDeepB > 0.1522) mediumbjets = op.select(jets, lambda j: j.btagDeepB > 0.4941) for fl1, fl2 in product(*repeat(goodLeptons.keys(), 2)): dilepSel = lambda l1, l2: op.AND(l1.charge != l2.charge, (l1.p4 + l2.p4).M() > 12.) if fl1 == fl2: lGood = op.sort(goodLeptons[fl1], lambda l: -l.pt) dilep = op.combine(lGood, N=2, pred=dilepSel) else: l1Good = op.sort(goodLeptons[fl1], lambda l: -l.pt) l2Good = op.sort(goodLeptons[fl2], lambda l: -l.pt) dilep = op.combine((l1Good, l2Good), pred=dilepSel) ll = dilep[0] hasDilep = hasTwoGoodLeptons.refine( f"hasDilep{fl1}{fl2}", cut=(op.rng_len(dilep) > 0, ll[0].pt > 25.), weight=([ sf_loose[fl1](ll[0]), sf_loose[fl2](ll[1]), sf_tight[fl1]( ll[0]), sf_tight[fl2](ll[1]) ] if isMC else None)) plots += [ Plot.make1D(f"dilepton_{fl1}{fl2}_Mll", (ll[0].p4 + ll[1].p4).M(), hasDilep, EqB(50, 70, 120.), title="Dilepton mass"), ] for il, ifl in enumerate((fl1, fl2)): plots += [ Plot.make1D(f"dilepton_{fl1}{fl2}_L{il:d}PT", ll[il].pt, hasDilep, EqB(50, 0., 100.), title=f"Lepton {il:d} PT"), Plot.make1D(f"dilepton_{fl1}{fl2}_L{il:d}ETA", ll[il].eta, hasDilep, EqB(50, -2.5, 2.5), title=f"Lepton {il:d} ETA"), ] plots += [ Plot.make1D(f"dilepton_{fl1}{fl2}_nJets", op.rng_len(jets), hasDilep, EqB(15, 0, 15.), title="Jet multiplicity"), Plot.make1D(f"dilepton_{fl1}{fl2}_nLooseBJets", op.rng_len(loosebjets), hasDilep, EqB(15, 0, 15.), title="Loose b-jet multiplicity"), Plot.make1D(f"dilepton_{fl1}{fl2}_nMediumBJets", op.rng_len(mediumbjets), hasDilep, EqB(15, 0, 15.), title="Medium b-jet multiplicity"), #Plot.make1D(f"dilepton_{fl1}{fl2}_nSelectedEvents", 1, hasDilep, EqB(1, 0, 1.), title="nSelectedEvents") ] #muons = op.select(t.Muon, lambda mu : mu.pt > 20.) #twoMuSel = noSel.refine("twoMuons", cut=[ op.rng_len(muons) > 1 ]) #electrons = op.select(t.Electron, lambda el : op.AND(el.pt > 15. , op.abs(el.p4.Eta()) < 2.5)) #twoElSel = noSel.refine("twoElectrons", cut=[ op.rng_len(electrons) > 1 ]) #oselmu = op.combine((electrons, muons)) #leptons = oselmu[0] #twoLepSel = noSel.refine("twoLeptons", cut=[ op.rng_len(electrons) == 1 , op.rng_len(muons) == 1 ]) #jets = op.select(t.Jet, lambda j : j.pt > 30.) #bjets = op.select(jets, lambda j : j.btagDeepFlavB > 0.2217) #plots.append(Plot.make1D("dimu_M", # op.invariant_mass(muons[0].p4, muons[1].p4), twoMuSel, EqB(100, 20., 120.), # title="Dimuon invariant mass", plotopts={"show-overflow":False, # "legend-position": [0.2, 0.6, 0.5, 0.9]})) #plots.append(Plot.make1D("diel_M", # op.invariant_mass(electrons[0].p4, electrons[1].p4), twoElSel, EqB(100, 20., 120.), # title="Dielectron invariant mass", plotopts={"show-overflow":False, # "legend-position": [0.2, 0.6, 0.5, 0.9]})) #plots.append(Plot.make1D("dilep_M", # op.invariant_mass(leptons[0].p4, leptons[1].p4) , twoLepSel, EqB(100, 20., 120.), # title="Dimuon invariant mass", plotopts={"show-overflow":False, # "legend-position": [0.2, 0.6, 0.5, 0.9]})) #plots.append(SummedPlot("Mjj", plots, title="m(jj)")) #plots.append(Plot.make1D("nJets_dimu",op.rng_len(jets), twoMuSel, EqB(10, -0.5, 9.5), # title="Jet multiplicity", plotopts={"show-overflow":False, # "legend-position": [0.2, 0.6, 0.5, 0.9]})) #plots.append(Plot.make1D("nBJets_dimu",op.rng_len(bjets), twoMuSel, EqB(10, -0.5, 9.5), # title="Jet multiplicity", plotopts={"show-overflow":False, # "legend-position": [0.2, 0.6, 0.5, 0.9]})) #plots.append(Plot.make1D("nJets_diel",op.rng_len(jets), twoElSel, EqB(10, -0.5, 9.5), # title="Jet multiplicity", plotopts={"show-overflow":False, # "legend-position": [0.2, 0.6, 0.5, 0.9]})) #plots.append(Plot.make1D("nBJets_diel",op.rng_len(bjets), twoElSel, EqB(10, -0.5, 9.5), # title="Jet multiplicity", plotopts={"show-overflow":False, # "legend-position": [0.2, 0.6, 0.5, 0.9]})) #plots.append(Plot.make1D("nJets_elmu",op.rng_len(jets), twoLepSel, EqB(10, -0.5, 9.5), # title="Jet multiplicity", plotopts={"show-overflow":False, # "legend-position": [0.2, 0.6, 0.5, 0.9]})) #plots.append(Plot.make1D("nBJets_elmu",op.rng_len(bjets), twoLepSel, EqB(10, -0.5, 9.5), # title="Jet multiplicity", plotopts={"show-overflow":False, # "legend-position": [0.2, 0.6, 0.5, 0.9]})) return plots
def definePlots(self, t, noSel, sample=None, sampleCfg=None): from bamboo.plots import CutFlowReport, SummedPlot from bamboo.plots import EquidistantBinning as EqB from bamboo import treefunctions as op isMC = self.isMC(sample) trigCut, trigWeight = None, None if isMC: trigCut = op.OR(t.HLT.HIEle20_Ele12_CaloIdL_TrackIdL_IsoVL_DZ, t.HLT.HIL3DoubleMu0, t.HLT.HIL3Mu20, t.HLT.HIEle20_WPLoose_Gsf) trigWeight = op.switch(op.OR(t.HLT.HIEle20_Ele12_CaloIdL_TrackIdL_IsoVL_DZ, t.HLT.HIL3DoubleMu0), op.c_float(1.), op.switch(t.HLT.HIL3Mu20, op.c_float(306.913/308.545), op.c_float(264.410/308.545))) ## FIXME these are wrong - you will get the final values from team A else: ## trigger order: dielectron, dimuon or single muon, single electron pd = sample.split("_")[0] if pd == "SingleMuon": trigCut = op.AND(op.NOT(t.HLT.HIEle20_Ele12_CaloIdL_TrackIdL_IsoVL_DZ), op.OR(t.HLT.HIL3DoubleMu0, t.HLT.HIL3Mu20)) elif pd == "HighEGJet": trigCut = op.OR(t.HLT.HIEle20_Ele12_CaloIdL_TrackIdL_IsoVL_DZ, op.AND(op.NOT(op.OR(t.HLT.HIL3DoubleMu0, t.HLT.HIL3Mu20)), t.HLT.HIEle20_WPLoose_Gsf)) noSel = noSel.refine("trig", cut=trigCut, weight=trigWeight) plots = [] def isGoodElectron(el, ptCut=10.): return op.AND( el.pt > ptCut, op.abs(el.eta) < 2.5, el.lostHits == 0, ## do you want this? op.abs(el.sip3d) < 8., op.abs(el.dxy) < .05, op.abs(el.dz ) < .1, el.miniPFRelIso_all < 0.085, el.mvaTTH > 0.125, op.NOT(op.AND(el.jet.isValid, op.OR(el.jet.btagDeepB > .1522, el.jet.btagDeepB <= -999.))) ) def isGoodMuon(mu, ptCut=10.): return op.AND( mu.pt > ptCut, op.abs(mu.eta) < 2.4, mu.mediumPromptId, op.abs(mu.sip3d) < 8., op.abs(mu.dxy) < .05, op.abs(mu.dz ) < .1, mu.miniPFRelIso_all < 0.325, mu.mvaTTH > 0.55, op.NOT(op.AND(mu.jet.isValid, op.OR(mu.jet.btagDeepB > .1522, mu.jet.btagDeepB <= -999.))) ) goodLeptons = { "el" : op.select(t.Electron, partial(isGoodElectron, ptCut=15.)), "mu" : op.select(t.Muon, partial(isGoodMuon, ptCut=15.)) } plots += [ Plot.make1D("trig_nLeptons15", op.rng_len(goodLeptons["el"])+op.rng_len(goodLeptons["mu"]), noSel, EqB(15, 0., 15.)), Plot.make1D("trig_nEl15", op.rng_len(goodLeptons["el"]), noSel, EqB(15, 0., 15.)), Plot.make1D("trig_nMu15", op.rng_len(goodLeptons["mu"]), noSel, EqB(15, 0., 15.)) ] from bamboo.scalefactors import get_scalefactor sf_loose = { "mu": get_scalefactor("lepton", "Muon_RecoToLoose", sfLib=scalefactors_lepMVA, paramDefs=binningVariables_nano_noScaleSyst, systName="muLoose"), "el": get_scalefactor("lepton", "Electron_RecoToLoose", sfLib=scalefactors_lepMVA, paramDefs=binningVariables_nano_noScaleSyst, systName="elLoose") } sf_tight = { "mu": get_scalefactor("lepton", "Muon_LooseToTight", sfLib=scalefactors_lepMVA, paramDefs=binningVariables_nano_noScaleSyst, systName="muTight"), "el": get_scalefactor("lepton", "Electron_LooseToTight", sfLib=scalefactors_lepMVA, paramDefs=binningVariables_nano_noScaleSyst, systName="elTight") } nGoodLeptons = op.rng_len(goodLeptons["el"])+op.rng_len(goodLeptons["mu"]) hasTwoGoodLeptons = noSel.refine("has2Lep", cut=(nGoodLeptons > 1)) # avoid overlap with 1l jets = op.sort(op.select(t.Jet, lambda j : op.AND( j.pt > 25., op.abs(j.eta) < 2.4, j.jetId & 0x2, op.AND( op.NOT(op.rng_any(goodLeptons["el"], lambda l : op.deltaR(l.p4, j.p4) < 0.4)), op.NOT(op.rng_any(goodLeptons["mu"], lambda l : op.deltaR(l.p4, j.p4) < 0.4))) )), lambda j : -j.pt) ## WP: see https://twiki.cern.ch/twiki/bin/viewauth/CMS/BtagRecommendation94X loosebjets = op.select(jets, lambda j : j.btagDeepB > 0.1522) mediumbjets = op.select(jets, lambda j : j.btagDeepB > 0.4941) for fl1,fl2 in product(*repeat(goodLeptons.keys(), 2)): dilepSel = lambda l1,l2 : op.AND( l1.charge != l2.charge, (l1.p4+l2.p4).M() > 12. ) if fl1 == fl2: lGood = op.sort(goodLeptons[fl1], lambda l : -l.pt) dilep = op.combine(lGood, N=2, pred=dilepSel) else: l1Good = op.sort(goodLeptons[fl1], lambda l : -l.pt) l2Good = op.sort(goodLeptons[fl2], lambda l : -l.pt) dilep = op.combine((l1Good, l2Good), pred=dilepSel) ll = dilep[0] hasDilep = hasTwoGoodLeptons.refine(f"hasDilep{fl1}{fl2}", cut=(op.rng_len(dilep) > 0, ll[0].pt > 25.), weight=([ sf_loose[fl1](ll[0]), sf_loose[fl2](ll[1]), sf_tight[fl1](ll[0]), sf_tight[fl2](ll[1]) ] if isMC else None)) plots += [ Plot.make1D(f"dilepton_{fl1}{fl2}_Mll", (ll[0].p4+ll[1].p4).M(), hasDilep, EqB(50, 70, 120.), title="Dilepton mass"), ] # for il,ifl in enumerate((fl1, fl2)): ## plots += [ # Plot.make1D(f"dilepton_{fl1}{fl2}_L{il:d}PT", ll[il].pt, hasDilep, EqB(50, 0., 100.), title=f"Lepton {il:d} PT"), # Plot.make1D(f"dilepton_{fl1}{fl2}_L{il:d}ETA", ll[il].eta, hasDilep, EqB(50, -2.5, 2.5), title=f"Lepton {il:d} ETA"), # ] # plots += [ # Plot.make1D(f"dilepton_{fl1}{fl2}_nJets", op.rng_len(jets), hasDilep, EqB(15, 0, 15.), title="Jet multiplicity"), # Plot.make1D(f"dilepton_{fl1}{fl2}_nLooseBJets", op.rng_len(loosebjets), hasDilep, EqB(15, 0, 15.), title="Loose b-jet multiplicity"), # Plot.make1D(f"dilepton_{fl1}{fl2}_nMediumBJets", op.rng_len(mediumbjets), hasDilep, EqB(15, 0, 15.), title="Medium b-jet multiplicity") # ] return plots