예제 #1
0
    def definePlots(self, tree, noSel, sample=None, sampleCfg=None):
        from bamboo.plots import Plot
        from bamboo.plots import EquidistantBinning as EqBin
        from bamboo import treefunctions as op

        plots = []

        el10 = op.select(tree.Electron, lambda el: el.pt > 10.)
        mu10 = op.select(tree.Muon, lambda mu: mu.pt > 10.)
        cleanedJets30 = op.select(
            tree.Jet, lambda j: op.AND(
                j.pt > 30.,
                op.NOT(
                    op.rng_any(el10, lambda el: op.deltaR(j.p4, el.p4) < 0.4)),
                op.NOT(
                    op.rng_any(mu10, lambda mu: op.deltaR(j.p4, mu.p4) < 0.4)))
        )
        plots.append(
            Plot.make1D("sumCleanedJetPt",
                        op.rng_sum(cleanedJets30, lambda j: j.pt),
                        noSel,
                        EqBin(100, 15., 200.),
                        title="Sum p_{T} (GeV/c)"))

        return plots
예제 #2
0
    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 isMC:
            noSel = noSel.refine("mcWeight", weight=[t.genWeight])
        noSel = noSel.refine(
            "trig",
            cut=op.OR(t.HLT.HIL3DoubleMu0,
                      t.HLT.HIEle20_Ele12_CaloIdL_TrackIdL_IsoVL_DZ))

        plots = []

        muons = op.select(t.Muon, lambda mu: mu.pt > 20.)
        twoMuSel = noSel.refine("twoMuons", cut=[op.rng_len(muons) > 1])
        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]
                        }))

        return plots
예제 #3
0
 def reco_4l(leptons, lName, baseSel):
     ## select events with four leptons, and find the best Z candidate
     ## shared between 4el and 4mu
     has4l = baseSel.refine(f"has4{lName}", cut=[
         op.rng_len(leptons) == 4,
         op.rng_sum(leptons, lambda l : l.charge) == 0,
         ])
     allZcand = op.combine(leptons, N=2, pred=lambda l1,l2 : l1.charge != l2.charge)
     bestZ = op.rng_min_element_by(allZcand, lambda ll : op.abs(op.invariant_mass(ll[0].p4, ll[1].p4)-mZ))
     otherLeptons = op.select(leptons, partial(lambda l,oz=None : op.AND(l.idx != oz[0].idx, l.idx != oz[1].idx), oz=bestZ))
     return has4l, bestZ, otherLeptons
예제 #4
0
    def definePlots(self, tree, noSel, sample=None, sampleCfg=None):
        from bamboo.plots import Plot, SummedPlot
        from bamboo.plots import EquidistantBinning as EqBin
        from bamboo import treefunctions as op

        plots = []

        # The plot is made for each of the different flavour categories (l+/- l-/+ l') and then summed,
        # because concatenation of containers is not (yet) supported.
        lepColl = {"El": tree.Electron, "Mu": tree.Muon}
        mt3lPlots = []
        for dlNm, dlCol in lepColl.items():
            dilep = op.combine(
                dlCol,
                N=2,
                pred=(lambda l1, l2: op.AND(l1.charge != l2.charge)))
            hasDiLep = noSel.refine("hasDilep{0}{0}".format(dlNm),
                                    cut=(op.rng_len(dilep) > 0))
            dilepZ = op.rng_min_element_by(
                dilep,
                fun=lambda ll: op.abs(
                    op.invariant_mass(ll[0].p4, ll[1].p4) - 91.2))
            for tlNm, tlCol in lepColl.items():
                if tlCol == dlCol:
                    hasTriLep = hasDiLep.refine("hasTrilep{0}{0}{1}".format(
                        dlNm, tlNm),
                                                cut=(op.rng_len(tlCol) > 2))
                    residLep = op.select(
                        tlCol, lambda l: op.AND(l.idx != dilepZ[0].idx, l.idx
                                                != dilepZ[1].idx))
                    l3 = op.rng_max_element_by(residLep, lambda l: l.pt)
                else:
                    hasTriLep = hasDiLep.refine("hasTriLep{0}{0}{1}".format(
                        dlNm, tlNm),
                                                cut=(op.rng_len(tlCol) > 0))
                    l3 = op.rng_max_element_by(tlCol, lambda l: l.pt)
                mtPlot = Plot.make1D(
                    "3lMT_{0}{0}{1}".format(dlNm, tlNm),
                    op.sqrt(2 * l3.pt * tree.MET.pt *
                            (1 - op.cos(l3.phi - tree.MET.phi))),
                    hasTriLep,
                    EqBin(100, 15., 250.),
                    title="M_{T} (GeV/c^2)")
                mt3lPlots.append(mtPlot)
                plots.append(mtPlot)
        plots.append(SummedPlot("3lMT", mt3lPlots))

        return plots
예제 #5
0
    def definePlots(self, tree, noSel, sample=None, sampleCfg=None):
        from bamboo.plots import Plot
        from bamboo.plots import EquidistantBinning as EqBin
        from bamboo import treefunctions as op

        plots = []

        centralJets1 = op.select(tree.Jet, lambda j: op.abs(j.eta) < 1.)
        plots.append(
            Plot.make1D("central1_jetPt",
                        op.map(centralJets1, lambda j: j.pt),
                        noSel,
                        EqBin(100, 15., 60.),
                        title="Jet p_{T} (GeV/c)"))

        return plots
예제 #6
0
    def definePlots(self, tree, noSel, sample=None, sampleCfg=None):
        from bamboo.plots import Plot
        from bamboo.plots import EquidistantBinning as EqBin
        from bamboo import treefunctions as op

        plots = []

        jets40 = op.select(tree.Jet, lambda j: j.pt > 40)
        hasTwoJets40 = noSel.refine("twoJets40", cut=(op.rng_len(jets40) >= 2))
        plots.append(
            Plot.make1D("twoJets40_MET",
                        tree.MET.pt,
                        hasTwoJets40,
                        EqBin(100, 0., 2000.),
                        title="MET (GeV)"))

        return plots
예제 #7
0
def plotRecoForGen(sel, gen, reco, lambda_match, name):
    n_reco = [
        op.select(
            reco, lambda r: op.switch(
                op.rng_len(gen) > i, lambda_match(gen[i], r), op.c_bool(False))
        ) for i in range(10)
    ]

    plots = SummedPlot("n_reco_{}_per_gen".format(name), [
        Plot.make1D("n_reco_{}_per_gen_{}".format(name, i),
                    op.rng_len(nre),
                    sel,
                    EquidistantBinning(10, 0, 10),
                    xTitle="N reco {} for gen {}".format(name, i))
        for i, nre in enumerate(n_reco)
    ],
                       xTitle="N reco {} for each gen".format(name))

    return plots
예제 #8
0
    def definePlots(self, tree, noSel, sample=None, sampleCfg=None):
        from bamboo.plots import Plot, SummedPlot
        from bamboo.plots import EquidistantBinning as EqBin
        from bamboo import treefunctions as op
        plots = []
        metSel = noSel.refine("MET", cut=(tree.met.et > 30000))
        trigSel = metSel.refine("trig", cut=op.OR(tree.trigE, tree.trigM))
        goodLeptons = op.select(
            tree.lep, lambda l: op.AND(l.isTightID, l.pt > 35000., l.ptcone30 /
                                       l.pt < 0.1, l.etcone20 / l.pt < 0.1))
        oneLepSel = trigSel.refine("1goodlep",
                                   cut=(op.rng_len(goodLeptons) == 1))
        lep = goodLeptons[0]
        signalSel = oneLepSel.refine(
            "signalRegion",
            cut=op.AND(
                op.abs(lep.z0 * op.sin(lep.p4.theta())) < 0.5,
                op.multiSwitch(
                    (lep.type == 11,
                     op.AND(
                         op.abs(lep.eta) < 2.46,
                         op.NOT(op.in_range(1.37, op.abs(lep.eta), 1.52)),
                         op.abs(lep.trackd0pvunbiased /
                                lep.tracksigd0pvunbiased) < 5)),
                    (lep.type == 13,
                     op.AND(
                         op.abs(lep.eta) < 2.5,
                         op.abs(lep.trackd0pvunbiased /
                                lep.tracksigd0pvunbiased) < 3)),
                    op.c_bool(False))))
        metp4 = makePtEtaPhiEP4(tree.met.et, op.c_float(0.), tree.met.phi,
                                tree.met.et)
        plots.append(
            Plot.make1D("mt_w", (lep.p4 + metp4).Mt() / 1000.,
                        signalSel,
                        EqBin(40, 60., 180.),
                        title="m_{T}^{W#rightarrow l#nu} (GeV)",
                        plotopts={"log-y-axis-range": [25., 2.5e8]}))

        return plots
예제 #9
0
 def comp_cosThetaSbetBeamAndHiggs(self, genColl):
     genh = op.select(
         genColl,
         lambda g: op.AND(g.pdgId == 25, g.statusFlags & (0x1 << 13)))
     HH_p4 = genh[0].p4 + genh[1].p4
     cm = HH_p4.BoostToCM()
     boosted_h1 = op.extMethod("ROOT::Math::VectorUtil::boost",
                               returnType=genh[0].p4._typeName)(genh[0].p4,
                                                                cm)
     boosted_h2 = op.extMethod("ROOT::Math::VectorUtil::boost",
                               returnType=genh[1].p4._typeName)(genh[1].p4,
                                                                cm)
     mHH = op.switch(
         op.rng_len(genh) == 2, op.invariant_mass(genh[0].p4, genh[1].p4),
         op.c_float(-9999))
     cosTheta1 = op.switch(
         op.rng_len(genh) == 2, op.abs(boosted_h1.Pz() / boosted_h1.P()),
         op.c_float(-9999))
     cosTheta2 = op.switch(
         op.rng_len(genh) == 2, op.abs(boosted_h1.Pz() / boosted_h2.P()),
         op.c_float(-9999))
     return [mHH, cosTheta1, cosTheta2]
예제 #10
0
    def definePlots(self, tree, noSel, sample=None, sampleCfg=None):
        plots = []

        muons = op.sort(op.select(tree.Muon, lambda mu : op.AND(
            mu.pt > 5,
            op.abs(mu.eta) < 2.4,
            op.abs(mu.pfRelIso04_all) < 0.40,
            op.abs(mu.dxy) < 0.5,
            op.abs(mu.dz ) < 1.,
            op.sqrt(mu.dxy**2 + mu.dz**2)/op.sqrt(mu.dxyErr**2+mu.dzErr**2) < 4, ## SIP3D
            )), lambda mu : -mu.pt)
        electrons = op.sort(op.select(tree.Electron, lambda el : op.AND(
            el.pt > 7.,
            op.abs(el.eta) < 2.5,
            op.abs(el.pfRelIso03_all) < 0.40,
            op.abs(el.dxy) < 0.5,
            op.abs(el.dz ) < 1.,
            op.sqrt(el.dxy**2 + el.dz**2)/op.sqrt(el.dxyErr**2+el.dzErr**2) < 4, ## SIP3D
            )), lambda el : -el.pt)

        plots += self.controlPlots_2l(noSel, muons, electrons)

        mZ = 91.1876

        def reco_4l(leptons, lName, baseSel):
            ## select events with four leptons, and find the best Z candidate
            ## shared between 4el and 4mu
            has4l = baseSel.refine(f"has4{lName}", cut=[
                op.rng_len(leptons) == 4,
                op.rng_sum(leptons, lambda l : l.charge) == 0,
                ])
            allZcand = op.combine(leptons, N=2, pred=lambda l1,l2 : l1.charge != l2.charge)
            bestZ = op.rng_min_element_by(allZcand, lambda ll : op.abs(op.invariant_mass(ll[0].p4, ll[1].p4)-mZ))
            otherLeptons = op.select(leptons, partial(lambda l,oz=None : op.AND(l.idx != oz[0].idx, l.idx != oz[1].idx), oz=bestZ))
            return has4l, bestZ, otherLeptons

        ## Mixed category: take leading two for each (as in the other implementations
        def cuts2lMixed(leptons):
            return [ op.rng_len(leptons) == 2,
                     leptons[0].charge != leptons[1].charge,
                     leptons[0].pt > 20.,
                     leptons[1].pt > 10.
                   ]
        has4lMixed = noSel.refine(f"has4lMixed", cut=cuts2lMixed(muons)+cuts2lMixed(electrons))
        mixed_mElEl = op.invariant_mass(electrons[0].p4, electrons[1].p4)
        mixed_mMuMu = op.invariant_mass(muons[0].p4, muons[1].p4)
        ## two categories: elel closest to Z or mumu closest to Z
        has2El2Mu = has4lMixed.refine(f"has2El2Mu", cut=(op.abs(mixed_mElEl-mZ) < op.abs(mixed_mMuMu-mZ)))
        has2Mu2El = has4lMixed.refine(f"has2Mu2El", cut=(op.abs(mixed_mElEl-mZ) > op.abs(mixed_mMuMu-mZ)))

        mH_cats = []
        for catNm, (has4l, bestZ, otherZ) in {
                "4Mu" : reco_4l(muons    , "Mu", noSel),
                "4El" : reco_4l(electrons, "El", noSel),
                "2El2Mu" : (has2El2Mu, electrons, muons),
                "2Mu2El" : (has2Mu2El, muons, electrons)
                }.items():
            bestZp4  = bestZ[0].p4  + bestZ[1].p4
            otherZp4 = otherZ[0].p4 + otherZ[1].p4
            hasZZ = has4l.refine(f"{has4l.name}ZZ", cut=[
                op.deltaR(bestZ[0].p4 , bestZ[1].p4 ) > 0.02,
                op.deltaR(otherZ[0].p4, otherZ[1].p4) > 0.02,
                op.in_range(40., bestZp4.M(), 120.),
                op.in_range(12., otherZp4.M(), 120.)
                ])
            plots += self.controlPlots_4l(hasZZ, bestZ, otherZ)
            m4l = (bestZ[0].p4+bestZ[1].p4+otherZ[0].p4+otherZ[1].p4).M()
            hasZZ_m4l70 = hasZZ.refine(f"{hasZZ.name}m4l70", cut=(m4l > 70.))
            p_mH = Plot.make1D(f"H_mass_{catNm}", m4l, hasZZ_m4l70, EqBin(36, 70., 180.),
                    plotopts={"show-overflow": False, "log-y": False, "y-axis-range": [0., 18.]})
            mH_cats.append(p_mH)
            plots.append(p_mH)
        plots.append(SummedPlot("H_mass", mH_cats))

        return plots
예제 #11
0
    def definePlots(self, t, noSel, sample=None, sampleCfg=None):
        from bamboo.plots import Plot, CutFlowReport, EquidistantBinning, VariableBinning
        from bamboo import treefunctions as op

        plots = []

        # definitions

        electrons = op.select(
            t.elec, lambda el: op.AND(el.pt > 20.,
                                      op.abs(el.eta) < 2.5))

        muons = op.select(t.muon, lambda mu: op.AND(mu.pt > 20.,
                                                    op.abs(mu.eta) < 2.5))

        cleanedElectrons = op.select(
            electrons, lambda el: op.NOT(
                op.rng_any(muons, lambda mu: op.deltaR(el.p4, mu.p4) < 0.3)))

        # we are taking the second isopass to be on which is equal to the medium working point
        isolatedElectrons = op.select(cleanedElectrons,
                                      lambda el: el.isopass & (1 << 2))

        identifiedElectrons = op.select(isolatedElectrons,
                                        lambda el: el.idpass & (1 << 2))

        cleanedMuons = op.select(
            muons, lambda mu: op.NOT(
                op.rng_any(electrons, lambda el: op.deltaR(mu.p4, el.p4) < 0.3)
            ))

        isolatedMuons = op.select(cleanedMuons,
                                  lambda mu: mu.isopass & (1 << 2))

        identifiedMuons = op.select(isolatedMuons,
                                    lambda mu: mu.idpass & (1 << 2))

        cleanedJets = op.select(
            t.jetpuppi, lambda j: op.AND(
                op.NOT(
                    op.rng_any(identifiedElectrons, lambda el: op.deltaR(
                        el.p4, j.p4) < 0.3)),
                op.NOT(
                    op.rng_any(identifiedMuons, lambda mu: op.deltaR(
                        mu.p4, j.p4) < 0.3))))

        cleanedGoodJets30_0to1_5 = op.select(
            cleanedJets, lambda j: op.AND(j.pt > 30,
                                          op.abs(j.eta) < 1.5))

        cleanedGoodJets30_1_5to3 = op.select(
            cleanedJets, lambda j: op.AND(
                j.pt > 30,
                op.NOT(op.AND(op.abs(j.eta) < 1.5,
                              op.abs(j.eta) > 3))))

        cleanedGoodJets30_3toInf = op.select(
            cleanedJets, lambda j: op.AND(j.pt > 30,
                                          op.abs(j.eta) > 3))

        cleanedGoodJets50_0to1_5 = op.select(
            cleanedJets, lambda j: op.AND(j.pt > 50,
                                          op.abs(j.eta) < 1.5))

        cleanedGoodJets50_1_5to3 = op.select(
            cleanedJets, lambda j: op.AND(
                j.pt > 50,
                op.NOT(op.AND(op.abs(j.eta) < 1.5,
                              op.abs(j.eta) > 3))))

        cleanedGoodJets50_3toInf = op.select(
            cleanedJets, lambda j: op.AND(j.pt > 50,
                                          op.abs(j.eta) > 3))

        cleanedGoodJets100_0to1_5 = op.select(
            cleanedJets, lambda j: op.AND(j.pt > 100,
                                          op.abs(j.eta) < 1.5))

        cleanedGoodJets100_1_5to3 = op.select(
            cleanedJets, lambda j: op.AND(
                j.pt > 100,
                op.NOT(op.AND(op.abs(j.eta) < 1.5,
                              op.abs(j.eta) > 3))))

        cleanedGoodJets100_3toInf = op.select(
            cleanedJets, lambda j: op.AND(j.pt > 100,
                                          op.abs(j.eta) > 3))

        cleanedGoodJets30 = op.select(cleanedJets, lambda j: j.pt > 30)

        cleanedGoodJets50 = op.select(cleanedJets, lambda j: j.pt > 50)

        cleanedGoodJets100 = op.select(cleanedJets, lambda j: j.pt > 100)

        met = op.select(t.metpuppi)

        sel1 = noSel.refine("nJet30", cut=[op.rng_len(cleanedGoodJets30) > 0])
        sel2 = noSel.refine("nJet50", cut=[op.rng_len(cleanedGoodJets50) > 0])
        sel3 = noSel.refine("nJet100",
                            cut=[op.rng_len(cleanedGoodJets100) > 0])

        sel1_1 = noSel.refine("nJet30_1",
                              cut=[op.rng_len(cleanedGoodJets30) > 0])
        sel1_1_1 = noSel.refine("nJet30_1_1",
                                cut=[op.rng_len(cleanedGoodJets30_0to1_5) > 0])
        sel1_1_2 = noSel.refine("nJet30_1_2",
                                cut=[op.rng_len(cleanedGoodJets30_1_5to3) > 0])
        sel1_1_3 = noSel.refine("nJet30_1_3",
                                cut=[op.rng_len(cleanedGoodJets30_3toInf) > 0])
        sel2_1 = noSel.refine("nJet50_1",
                              cut=[op.rng_len(cleanedGoodJets50) > 0])
        sel1_2_1 = noSel.refine("nJet50_1_1",
                                cut=[op.rng_len(cleanedGoodJets50_0to1_5) > 0])
        sel1_2_2 = noSel.refine("nJet50_1_2",
                                cut=[op.rng_len(cleanedGoodJets50_1_5to3) > 0])
        sel1_2_3 = noSel.refine("nJet50_1_3",
                                cut=[op.rng_len(cleanedGoodJets50_3toInf) > 0])
        sel3_1 = noSel.refine("nJet100_1",
                              cut=[op.rng_len(cleanedGoodJets100) > 0])
        sel1_3_1 = noSel.refine(
            "nJet100_1_1", cut=[op.rng_len(cleanedGoodJets100_0to1_5) > 0])
        sel1_3_2 = noSel.refine(
            "nJet100_1_2", cut=[op.rng_len(cleanedGoodJets100_1_5to3) > 0])
        sel1_3_3 = noSel.refine(
            "nJet100_1_3", cut=[op.rng_len(cleanedGoodJets100_3toInf) > 0])

        sel1_2 = noSel.refine("nJet30_2",
                              cut=[op.rng_len(cleanedGoodJets30) > 1])
        sel2_1_1 = noSel.refine("nJet30_2_1",
                                cut=[op.rng_len(cleanedGoodJets30_0to1_5) > 1])
        sel2_1_2 = noSel.refine("nJet30_2_2",
                                cut=[op.rng_len(cleanedGoodJets30_1_5to3) > 1])
        sel2_1_3 = noSel.refine("nJet30_2_3",
                                cut=[op.rng_len(cleanedGoodJets30_3toInf) > 1])
        sel2_2 = noSel.refine("nJet50_2",
                              cut=[op.rng_len(cleanedGoodJets50) > 1])
        sel2_2_1 = noSel.refine("nJet50_2_1",
                                cut=[op.rng_len(cleanedGoodJets50_0to1_5) > 1])
        sel2_2_2 = noSel.refine("nJet50_2_2",
                                cut=[op.rng_len(cleanedGoodJets50_1_5to3) > 1])
        sel2_2_3 = noSel.refine("nJet50_2_3",
                                cut=[op.rng_len(cleanedGoodJets50_3toInf) > 1])
        sel3_2 = noSel.refine("nJet100_2",
                              cut=[op.rng_len(cleanedGoodJets100) > 1])
        sel2_3_1 = noSel.refine(
            "nJet100_2_1", cut=[op.rng_len(cleanedGoodJets100_0to1_5) > 1])
        sel2_3_2 = noSel.refine(
            "nJet100_2_2", cut=[op.rng_len(cleanedGoodJets100_1_5to3) > 1])
        sel2_3_3 = noSel.refine(
            "nJet100_2_3", cut=[op.rng_len(cleanedGoodJets100_3toInf) > 1])

        sel1_3 = noSel.refine("nJet30_3",
                              cut=[op.rng_len(cleanedGoodJets30) > 2])
        sel3_1_1 = noSel.refine("nJet30_3_1",
                                cut=[op.rng_len(cleanedGoodJets30_0to1_5) > 2])
        sel3_1_2 = noSel.refine("nJet30_3_2",
                                cut=[op.rng_len(cleanedGoodJets30_1_5to3) > 2])
        sel3_1_3 = noSel.refine("nJet30_3_3",
                                cut=[op.rng_len(cleanedGoodJets30_3toInf) > 2])
        sel2_3 = noSel.refine("nJet50_3",
                              cut=[op.rng_len(cleanedGoodJets50) > 2])
        sel3_2_1 = noSel.refine("nJet50_3_1",
                                cut=[op.rng_len(cleanedGoodJets50_0to1_5) > 2])
        sel3_2_2 = noSel.refine("nJet50_3_2",
                                cut=[op.rng_len(cleanedGoodJets50_1_5to3) > 2])
        sel3_2_3 = noSel.refine("nJet50_3_3",
                                cut=[op.rng_len(cleanedGoodJets50_3toInf) > 2])
        sel3_3 = noSel.refine("nJet100_3",
                              cut=[op.rng_len(cleanedGoodJets100) > 2])
        sel3_3_1 = noSel.refine(
            "nJet100_3_1", cut=[op.rng_len(cleanedGoodJets100_0to1_5) > 2])
        sel3_3_2 = noSel.refine(
            "nJet100_3_2", cut=[op.rng_len(cleanedGoodJets100_1_5to3) > 2])
        sel3_3_3 = noSel.refine(
            "nJet100_3_3", cut=[op.rng_len(cleanedGoodJets100_3toInf) > 2])

        sel1_4 = noSel.refine("nJet30_4",
                              cut=[op.rng_len(cleanedGoodJets30) > 3])
        sel4_1_1 = noSel.refine("nJet30_4_1",
                                cut=[op.rng_len(cleanedGoodJets30_0to1_5) > 3])
        sel4_1_2 = noSel.refine("nJet30_4_2",
                                cut=[op.rng_len(cleanedGoodJets30_1_5to3) > 3])
        sel4_1_3 = noSel.refine("nJet30_4_3",
                                cut=[op.rng_len(cleanedGoodJets30_3toInf) > 3])
        sel2_4 = noSel.refine("nJet50_4",
                              cut=[op.rng_len(cleanedGoodJets50) > 3])
        sel4_2_1 = noSel.refine("nJet50_4_1",
                                cut=[op.rng_len(cleanedGoodJets50_0to1_5) > 3])
        sel4_2_2 = noSel.refine("nJet50_4_2",
                                cut=[op.rng_len(cleanedGoodJets50_1_5to3) > 3])
        sel4_2_3 = noSel.refine("nJet50_4_3",
                                cut=[op.rng_len(cleanedGoodJets50_3toInf) > 3])
        sel3_4 = noSel.refine("nJet100_4",
                              cut=[op.rng_len(cleanedGoodJets100) > 3])
        sel4_3_1 = noSel.refine(
            "nJet100_4_1", cut=[op.rng_len(cleanedGoodJets100_0to1_5) > 3])
        sel4_3_2 = noSel.refine(
            "nJet100_4_2", cut=[op.rng_len(cleanedGoodJets100_1_5to3) > 3])
        sel4_3_3 = noSel.refine(
            "nJet100_4_3", cut=[op.rng_len(cleanedGoodJets100_3toInf) > 3])

        # plots

        #     # ### 30 GeV

        plots.append(
            Plot.make1D("nJets_jetPT_30GeV",
                        op.rng_len(cleanedGoodJets30),
                        noSel,
                        EquidistantBinning(15, 0., 15.),
                        title="nJets (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet1_pT_jetPT_30GeV",
                        cleanedGoodJets30[0].pt,
                        sel1_1,
                        EquidistantBinning(50, 0., 4000.),
                        title="Jet1_pT (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet1_eta_jetPT_30GeV",
                        cleanedGoodJets30[0].eta,
                        sel1_1,
                        EquidistantBinning(30, -3, 3),
                        title="Jet1_eta (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet1_pT_0to1_5_jetPT_30GeV",
                        cleanedGoodJets30_0to1_5[0].pt,
                        sel1_1_1,
                        EquidistantBinning(50, 0, 4000),
                        title="Jet1_pT 0 < eta < 1.5, (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet1_pT_1_5to3_jetPT_30GeV",
                        cleanedGoodJets30_1_5to3[0].pt,
                        sel1_1_2,
                        EquidistantBinning(50, 0, 4000),
                        title="Jet1_pT 1.5 < eta < 3, (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet1_pT_3toInf_jetPT_30GeV",
                        cleanedGoodJets30_3toInf[0].pt,
                        sel1_1_3,
                        EquidistantBinning(50, 0, 1000),
                        title="Jet1_pT eta > 3, (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet2_pT_jetPT_30GeV",
                        cleanedGoodJets30[1].pt,
                        sel1_2,
                        EquidistantBinning(50, 0., 4000.),
                        title="Jet2_pT (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet2_eta_jetPT_30GeV",
                        cleanedGoodJets30[1].eta,
                        sel1_2,
                        EquidistantBinning(30, -3, 3),
                        title="Jet2_eta (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet2_pT_0to1_5_jetPT_30GeV",
                        cleanedGoodJets30_0to1_5[1].pt,
                        sel2_1_1,
                        EquidistantBinning(50, 0, 4000),
                        title="Jet2_pT 0 < eta < 1.5, (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet2_pT_1_5to3_jetPT_30GeV",
                        cleanedGoodJets30_1_5to3[1].pt,
                        sel2_1_2,
                        EquidistantBinning(50, 0, 4000),
                        title="Jet2_pT 1.5 < eta < 3, (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet2_pT_3toInf_jetPT_30GeV",
                        cleanedGoodJets30_3toInf[1].pt,
                        sel2_1_3,
                        EquidistantBinning(50, 0, 500),
                        title="Jet2_pT eta > 3, (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet3_pT_jetPT_30GeV",
                        cleanedGoodJets30[2].pt,
                        sel1_3,
                        EquidistantBinning(50, 0., 2000.),
                        title="Jet3_pT (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet3_eta_jetPT_30GeV",
                        cleanedGoodJets30[2].eta,
                        sel1_3,
                        EquidistantBinning(30, -3, 3),
                        title="Jet3_eta (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet3_pT_0to1_5_jetPT_30GeV",
                        cleanedGoodJets30_0to1_5[2].pt,
                        sel3_1_1,
                        EquidistantBinning(50, 0, 2000),
                        title="Jet3_pT 0 < eta < 1.5, (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet3_pT_1_5to3_jetPT_30GeV",
                        cleanedGoodJets30_1_5to3[2].pt,
                        sel3_1_2,
                        EquidistantBinning(50, 0, 2000),
                        title="Jet3_pT 1.5 < eta < 3, (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet3_pT_3toInf_jetPT_30GeV",
                        cleanedGoodJets30_3toInf[2].pt,
                        sel3_1_3,
                        EquidistantBinning(50, 0, 200),
                        title="Jet3_pT eta > 3, (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet4_pT_jetPT_30GeV",
                        cleanedGoodJets30[3].pt,
                        sel1_4,
                        EquidistantBinning(50, 0., 2000.),
                        title="Jet4_pT (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet4_eta_jetPT_30GeV",
                        cleanedGoodJets30[3].eta,
                        sel1_4,
                        EquidistantBinning(30, -3, 3),
                        title="Jet4_eta (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet4_pT_0to1_5_jetPT_30GeV",
                        cleanedGoodJets30_0to1_5[3].pt,
                        sel4_1_1,
                        EquidistantBinning(50, 0, 2000),
                        title="Jet4_pT 0 < eta < 1.5, (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet4_pT_1_5to3_jetPT_30GeV",
                        cleanedGoodJets30_1_5to3[3].pt,
                        sel4_1_2,
                        EquidistantBinning(50, 0, 2000),
                        title="Jet4_pT 1.5 < eta < 3, (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet4_pT_3toInf_jetPT_30GeV",
                        cleanedGoodJets30_3toInf[3].pt,
                        sel4_1_3,
                        EquidistantBinning(50, 0, 200),
                        title="Jet4_pT eta > 3, (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("MET_jetPT_30GeV",
                        met[0].pt,
                        sel1,
                        EquidistantBinning(50, 0, 1000),
                        title="MET (jet p_{T} > 30GeV)"))

        #     # ### 50 GeV

        plots.append(
            Plot.make1D("nJets_jetPT_50GeV",
                        op.rng_len(cleanedGoodJets50),
                        noSel,
                        EquidistantBinning(15, 0., 15.),
                        title="nJets (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("Jet1_pT_jetPT_50GeV",
                        cleanedGoodJets50[0].pt,
                        sel2_1,
                        EquidistantBinning(50, 0., 4000.),
                        title="Jet1_pT (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("Jet1_eta_jetPT_50GeV",
                        cleanedGoodJets50[0].eta,
                        sel2_1,
                        EquidistantBinning(30, -3, 3),
                        title="Jet1_eta (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("Jet1_pT_0to1_5_jetPT_50GeV",
                        cleanedGoodJets50_0to1_5[0].pt,
                        sel1_2_1,
                        EquidistantBinning(50, 0, 4000),
                        title="Jet1_pT 0 < eta < 1.5, (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("Jet1_pT_1_5to3_jetPT_50GeV",
                        cleanedGoodJets50_1_5to3[0].pt,
                        sel1_2_2,
                        EquidistantBinning(50, 0, 4000),
                        title="Jet1_pT 1.5 < eta < 3, (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("Jet1_pT_3toInf_jetPT_50GeV",
                        cleanedGoodJets50_3toInf[0].pt,
                        sel1_2_3,
                        EquidistantBinning(50, 0, 1000),
                        title="Jet1_pT eta > 3, (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("Jet2_pT_jetPT_50GeV",
                        cleanedGoodJets50[1].pt,
                        sel2_2,
                        EquidistantBinning(50, 0., 4000.),
                        title="Jet2_pT (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("Jet2_eta_jetPT_50GeV",
                        cleanedGoodJets50[1].eta,
                        sel2_2,
                        EquidistantBinning(30, -3, 3),
                        title="Jet2_eta (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("Jet2_pT_0to1_5_jetPT_50GeV",
                        cleanedGoodJets50_0to1_5[1].pt,
                        sel2_2_1,
                        EquidistantBinning(50, 0, 4000),
                        title="Jet2_pT 0 < eta < 1.5, (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("Jet2_pT_1_5to3_jetPT_50GeV",
                        cleanedGoodJets50_1_5to3[1].pt,
                        sel2_2_2,
                        EquidistantBinning(50, 0, 4000),
                        title="Jet2_pT 1.5 < eta < 3, (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("Jet2_pT_3toInf_jetPT_50GeV",
                        cleanedGoodJets50_3toInf[1].pt,
                        sel2_2_3,
                        EquidistantBinning(50, 0, 500),
                        title="Jet2_pT eta > 3, (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("Jet3_pT_jetPT_50GeV",
                        cleanedGoodJets50[2].pt,
                        sel2_3,
                        EquidistantBinning(50, 0., 2000.),
                        title="Jet3_pT (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("Jet3_eta_jetPT_50GeV",
                        cleanedGoodJets50[2].eta,
                        sel2_3,
                        EquidistantBinning(30, -3, 3),
                        title="Jet3_eta (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("Jet3_pT_0to1_5_jetPT_50GeV",
                        cleanedGoodJets50_0to1_5[2].pt,
                        sel3_2_1,
                        EquidistantBinning(50, 0, 2000),
                        title="Jet3_pT 0 < eta < 1.5, (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("Jet3_pT_1_5to3_jetPT_50GeV",
                        cleanedGoodJets50_1_5to3[2].pt,
                        sel3_2_2,
                        EquidistantBinning(50, 0, 2000),
                        title="Jet3_pT 1.5 < eta < 3, (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("Jet3_pT_3toInf_jetPT_50GeV",
                        cleanedGoodJets50_3toInf[2].pt,
                        sel3_2_3,
                        EquidistantBinning(50, 0, 200),
                        title="Jet3_pT eta > 3, (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("Jet4_pT_jetPT_50GeV",
                        cleanedGoodJets50[3].pt,
                        sel2_4,
                        EquidistantBinning(50, 0., 2000.),
                        title="Jet4_pT (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("Jet4_eta_jetPT_50GeV",
                        cleanedGoodJets50[3].eta,
                        sel2_4,
                        EquidistantBinning(30, -3, 3),
                        title="Jet4_eta (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("Jet4_pT_0to1_5_jetPT_50GeV",
                        cleanedGoodJets50_0to1_5[3].pt,
                        sel4_2_1,
                        EquidistantBinning(50, 0, 2000),
                        title="Jet4_pT 0 < eta < 1.5, (jet p_{T} > 30GeV)"))

        plots.append(
            Plot.make1D("Jet4_pT_1_5to3_jetPT_50GeV",
                        cleanedGoodJets50_1_5to3[3].pt,
                        sel4_2_2,
                        EquidistantBinning(50, 0, 2000),
                        title="Jet4_pT 1.5 < eta < 3, (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("Jet4_pT_3toInf_jetPT_50GeV",
                        cleanedGoodJets50_3toInf[3].pt,
                        sel4_2_3,
                        EquidistantBinning(50, 0, 200),
                        title="Jet4_pT eta > 3, (jet p_{T} > 50GeV)"))

        plots.append(
            Plot.make1D("MET_jetPT_50GeV",
                        met[0].pt,
                        sel2,
                        EquidistantBinning(50, 0, 1000),
                        title="MET (jet p_{T} > 50GeV)"))

        #  ### 100 GeV

        plots.append(
            Plot.make1D("nJets_jetPT_100GeV",
                        op.rng_len(cleanedGoodJets100),
                        noSel,
                        EquidistantBinning(15, 0., 15.),
                        title="nJets (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet1_pT_jetPT_100GeV",
                        cleanedGoodJets100[0].pt,
                        sel3_1,
                        EquidistantBinning(50, 0., 4000.),
                        title="Jet1_pT (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet1_eta_jetPT_100GeV",
                        cleanedGoodJets100[0].eta,
                        sel3_1,
                        EquidistantBinning(30, -3, 3),
                        title="Jet1_eta (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet1_pT_0to1_5_jetPT_100GeV",
                        cleanedGoodJets100_0to1_5[0].pt,
                        sel1_3_1,
                        EquidistantBinning(50, 0, 4000),
                        title="Jet1_pT 0 < eta < 1.5, (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet1_pT_1_5to3_jetPT_100GeV",
                        cleanedGoodJets100_1_5to3[0].pt,
                        sel1_3_2,
                        EquidistantBinning(50, 0, 4000),
                        title="Jet1_pT 1.5 < eta < 3, (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet1_pT_3toInf_jetPT_100GeV",
                        cleanedGoodJets100_3toInf[0].pt,
                        sel1_3_3,
                        EquidistantBinning(50, 0, 1000),
                        title="Jet1_pT eta > 3, (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet2_pT_jetPT_100GeV",
                        cleanedGoodJets100[1].pt,
                        sel3_2,
                        EquidistantBinning(50, 0., 4000.),
                        title="Jet2_pT (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet2_eta_jetPT_100GeV",
                        cleanedGoodJets100[1].eta,
                        sel3_2,
                        EquidistantBinning(30, -3, 3),
                        title="Jet2_eta (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet2_pT_0to1_5_jetPT_100GeV",
                        cleanedGoodJets100_0to1_5[1].pt,
                        sel2_3_1,
                        EquidistantBinning(50, 0, 4000),
                        title="Jet2_pT 0 < eta < 1.5, (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet2_pT_1_5to3_jetPT_100GeV",
                        cleanedGoodJets100_1_5to3[1].pt,
                        sel2_3_2,
                        EquidistantBinning(50, 0, 4000),
                        title="Jet2_pT 1.5 < eta < 3, (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet2_pT_3toInf_jetPT_100GeV",
                        cleanedGoodJets100_3toInf[1].pt,
                        sel2_3_3,
                        EquidistantBinning(50, 0, 500),
                        title="Jet2_pT eta > 3, (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet3_pT_jetPT_100GeV",
                        cleanedGoodJets100[2].pt,
                        sel3_3,
                        EquidistantBinning(50, 0., 2000.),
                        title="Jet3_pT (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet3_eta_jetPT_100GeV",
                        cleanedGoodJets100[2].eta,
                        sel3_3,
                        EquidistantBinning(30, -3, 3),
                        title="Jet3_eta (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet3_pT_0to1_5_jetPT_100GeV",
                        cleanedGoodJets100_0to1_5[2].pt,
                        sel3_3_1,
                        EquidistantBinning(50, 0, 2000),
                        title="Jet3_pT 0 < eta < 1.5, (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet3_pT_1_5to3_jetPT_100GeV",
                        cleanedGoodJets100_1_5to3[2].pt,
                        sel3_3_2,
                        EquidistantBinning(50, 0, 2000),
                        title="Jet3_pT 1.5 < eta < 3, (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet3_pT_3toInf_jetPT_100GeV",
                        cleanedGoodJets100_3toInf[2].pt,
                        sel3_3_3,
                        EquidistantBinning(50, 0, 200),
                        title="Jet3_pT eta > 3, (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet4_pT_jetPT_100GeV",
                        cleanedGoodJets100[3].pt,
                        sel3_4,
                        EquidistantBinning(50, 0., 2000.),
                        title="Jet4_pT (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet4_eta_jetPT_100GeV",
                        cleanedGoodJets100[3].eta,
                        sel3_4,
                        EquidistantBinning(30, -3, 3),
                        title="Jet4_eta (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet4_pT_0to1_5_jetPT_100GeV",
                        cleanedGoodJets100_0to1_5[3].pt,
                        sel4_3_1,
                        EquidistantBinning(50, 0, 2000),
                        title="Jet4_pT 0 < eta < 1.5, (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet4_pT_1_5to3_jetPT_100GeV",
                        cleanedGoodJets100_1_5to3[3].pt,
                        sel4_3_2,
                        EquidistantBinning(50, 0, 2000),
                        title="Jet4_pT 1.5 < eta < 3, (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("Jet4_pT_3toInf_jetPT_100GeV",
                        cleanedGoodJets100_3toInf[3].pt,
                        sel4_3_3,
                        EquidistantBinning(50, 0, 200),
                        title="Jet4_pT eta > 3, (jet p_{T} > 100GeV)"))

        plots.append(
            Plot.make1D("MET_jetPT_100GeV",
                        met[0].pt,
                        sel3,
                        EquidistantBinning(50, 0, 1000),
                        title="MET (jet p_{T} > 100GeV)"))

        # Efficiency Report on terminal and the .tex output

        cfr = CutFlowReport("yields")
        cfr.add(noSel, "None")
        cfr.add(sel1, "30GeV")
        cfr.add(sel2, "50GeV")
        cfr.add(sel3, "100GeV")

        plots.append(cfr)

        return plots
    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
예제 #13
0
    def definePlots(self, t, noSel, sample=None, sampleCfg=None):
        # Some imports #
        from bamboo.analysisutils import forceDefine

        era = sampleCfg['era']
        # Get pile-up configs #
        puWeightsFile = None
        if era == "2016":
            sfTag = "94X"
            puWeightsFile = os.path.join(os.path.dirname(__file__), "data",
                                         "puweights2016.json")
        elif era == "2017":
            sfTag = "94X"
            puWeightsFile = os.path.join(os.path.dirname(__file__), "data",
                                         "puweights2017.json")
        elif era == "2018":
            sfTag = "102X"
            puWeightsFile = os.path.join(os.path.dirname(__file__), "data",
                                         "puweights2018.json")
        if self.isMC(sample) and puWeightsFile is not None:
            from bamboo.analysisutils import makePileupWeight
            noSel = noSel.refine("puWeight",
                                 weight=makePileupWeight(puWeightsFile,
                                                         t.Pileup_nTrueInt,
                                                         systName="pileup"))
        isMC = self.isMC(sample)
        plots = []

        forceDefine(t._Muon.calcProd, noSel)

        #############################################################################
        ################################  Muons #####################################
        #############################################################################
        # Wp // 2016- 2017 -2018 : Muon_mediumId   // https://twiki.cern.ch/twiki/bin/view/CMS/SWGuideMuonIdRun2#Muon_Isolation
        muonsByPt = op.sort(t.Muon, lambda mu: -mu.p4.Pt())
        muons = op.select(
            muonsByPt, lambda mu: op.AND(mu.p4.Pt() > 10.,
                                         op.abs(mu.p4.Eta()) < 2.4, mu.tightId,
                                         mu.pfRelIso04_all < 0.15))

        # Scalefactors #
        #if era=="2016":
        #    doubleMuTrigSF = get_scalefactor("dilepton", ("doubleMuLeg_HHMoriond17_2016"), systName="mumutrig")
        #    muMediumIDSF = get_scalefactor("lepton", ("muon_{0}_{1}".format(era, sfTag), "id_medium"), combine="weight", systName="muid")
        #    muMediumISOSF = get_scalefactor("lepton", ("muon_{0}_{1}".format(era, sfTag), "iso_tight_id_medium"), combine="weight", systName="muiso")
        #    TrkIDSF = get_scalefactor("lepton", ("muon_{0}_{1}".format(era, sfTag), "highpt"), combine="weight")
        #    TrkISOSF = get_scalefactor("lepton", ("muon_{0}_{1}".format(era, sfTag), "isotrk_loose_idtrk_tightidandipcut"), combine="weight")
        #else:
        #    muMediumIDSF = get_scalefactor("lepton", ("muon_{0}_{1}".format(era, sfTag), "id_medium"), systName="muid")
        #    muMediumISOSF = get_scalefactor("lepton", ("muon_{0}_{1}".format(era, sfTag), "iso_tight_id_medium"), systName="muiso")

        #############################################################################
        #############################  Electrons  ###################################
        #############################################################################
        #Wp  // 2016: Electron_cutBased_Sum16==3  -> medium     // 2017 -2018  : Electron_cutBased ==3   --> medium ( Fall17_V2)
        # asking for electrons to be in the Barrel region with dz<1mm & dxy< 0.5mm   //   Endcap region dz<2mm & dxy< 0.5mm
        electronsByPt = op.sort(t.Electron, lambda ele: -ele.p4.Pt())
        electrons = op.select(
            electronsByPt,
            lambda ele: op.AND(ele.p4.Pt() > 15.,
                               op.abs(ele.p4.Eta()) < 2.5, ele.cutBased >= 3)
        )  # //cut-based ID Fall17 V2 the recomended one from POG for the FullRunII

        # Scalefactors #
        #elMediumIDSF = get_scalefactor("lepton", ("electron_{0}_{1}".format(era,sfTag), "id_medium"), systName="elid")
        #doubleEleTrigSF = get_scalefactor("dilepton", ("doubleEleLeg_HHMoriond17_2016"), systName="eleltrig")

        #elemuTrigSF = get_scalefactor("dilepton", ("elemuLeg_HHMoriond17_2016"), systName="elmutrig")
        #mueleTrigSF = get_scalefactor("dilepton", ("mueleLeg_HHMoriond17_2016"), systName="mueltrig")

        OsElEl = op.combine(
            electrons,
            N=2,
            pred=lambda el1, el2: op.AND(el1.charge != el2.charge,
                                         el1.p4.Pt() > 25,
                                         el2.p4.Pt() > 15))
        OsMuMu = op.combine(
            muons,
            N=2,
            pred=lambda mu1, mu2: op.AND(mu1.charge != mu2.charge,
                                         mu1.p4.Pt() > 25,
                                         mu2.p4.Pt() > 15))
        OsElMu = op.combine((electrons, muons),
                            pred=lambda el, mu: op.AND(el.charge != mu.charge,
                                                       el.p4.Pt() > 25,
                                                       mu.p4.Pt() > 15))
        OsMuEl = op.combine((electrons, muons),
                            pred=lambda el, mu: op.AND(el.charge != mu.charge,
                                                       el.p4.Pt() > 15,
                                                       mu.p4.Pt() > 25))

        hasOsElEl = noSel.refine("hasOsElEl", cut=[op.rng_len(OsElEl) >= 1])
        hasOsMuMu = noSel.refine("hasOsMuMu", cut=[op.rng_len(OsMuMu) >= 1])
        hasOsElMu = noSel.refine("hasOsElMu", cut=[op.rng_len(OsElMu) >= 1])
        hasOsMuEl = noSel.refine("hasOsMuEl", cut=[op.rng_len(OsMuEl) >= 1])

        plots.append(
            Plot.make1D("ElEl_channel",
                        op.rng_len(OsElEl),
                        noSel,
                        EquidistantBinning(10, 0, 10.),
                        title='Number of dilepton events in ElEl channel',
                        xTitle='N_{dilepton} (ElEl channel)'))
        plots.append(
            Plot.make1D("MuMu_channel",
                        op.rng_len(OsMuMu),
                        noSel,
                        EquidistantBinning(10, 0, 10.),
                        title='Number of dilepton events in MuMu channel',
                        xTitle='N_{dilepton} (MuMu channel)'))
        plots.append(
            Plot.make1D("ElMu_channel",
                        op.rng_len(OsElMu),
                        noSel,
                        EquidistantBinning(10, 0, 10.),
                        title='Number of dilepton events in ElMu channel',
                        xTitle='N_{dilepton} (ElMu channel)'))
        plots.append(
            Plot.make1D("MuEl_channel",
                        op.rng_len(OsMuEl),
                        noSel,
                        EquidistantBinning(10, 0, 10.),
                        title='Number of dilepton events in MuEl channel',
                        xTitle='N_{dilepton} (MuEl channel)'))

        plots += makeDileptonPlots(self,
                                   sel=hasOsElEl,
                                   dilepton=OsElEl[0],
                                   suffix='hasOsdilep',
                                   channel='ElEl')
        plots += makeDileptonPlots(self,
                                   sel=hasOsMuMu,
                                   dilepton=OsMuMu[0],
                                   suffix='hasOsdilep',
                                   channel='MuMu')
        plots += makeDileptonPlots(self,
                                   sel=hasOsElMu,
                                   dilepton=OsElMu[0],
                                   suffix='hasOsdilep',
                                   channel='ElMu')
        plots += makeDileptonPlots(self,
                                   sel=hasOsMuEl,
                                   dilepton=OsMuEl[0],
                                   suffix='hasOsdilep',
                                   channel='MuEl')

        # Dilepton Z peak exclusion (charge already done in previous selection) #
        lambda_mllLowerband = lambda dilep: op.in_range(
            12., op.invariant_mass(dilep[0].p4, dilep[1].p4), 80.)
        lambda_mllUpperband = lambda dilep: op.invariant_mass(
            dilep[0].p4, dilep[1].p4) > 100.
        lambda_mllCut = lambda dilep: op.OR(lambda_mllLowerband(dilep),
                                            lambda_mllUpperband(dilep))

        hasOsElElOutZ = hasOsElEl.refine("hasOsElElOutZ",
                                         cut=[lambda_mllCut(OsElEl[0])])
        hasOsMuMuOutZ = hasOsMuMu.refine("hasOsMuMuOutZ",
                                         cut=[lambda_mllCut(OsMuMu[0])])
        hasOsElMuOutZ = hasOsElMu.refine("hasOsElMuOutZ",
                                         cut=[lambda_mllCut(OsElMu[0])])
        hasOsMuElOutZ = hasOsMuEl.refine("hasOsMuElOutZ",
                                         cut=[lambda_mllCut(OsMuEl[0])])

        plots += makeDileptonPlots(self,
                                   sel=hasOsElElOutZ,
                                   dilepton=OsElEl[0],
                                   suffix='hasOsdilep_OutZ',
                                   channel='ElEl')
        plots += makeDileptonPlots(self,
                                   sel=hasOsMuMuOutZ,
                                   dilepton=OsMuMu[0],
                                   suffix='hasOsdilep_OutZ',
                                   channel='MuMu')
        plots += makeDileptonPlots(self,
                                   sel=hasOsElMuOutZ,
                                   dilepton=OsElMu[0],
                                   suffix='hasOsdilep_OutZ',
                                   channel='ElMu')
        plots += makeDileptonPlots(self,
                                   sel=hasOsMuElOutZ,
                                   dilepton=OsMuEl[0],
                                   suffix='hasOsdilep_OutZ',
                                   channel='MuEl')

        #############################################################################
        ################################  Jets  #####################################
        #############################################################################
        # select jets   // 2016 - 2017 - 2018   ( j.jetId &2) ->      tight jet ID
        jetsByPt = op.sort(t.Jet, lambda jet: -jet.p4.Pt())
        jetsSel = op.select(jetsByPt,
                            lambda j: op.AND(j.p4.Pt() > 20.,
                                             op.abs(j.p4.Eta()) < 2.4,
                                             (j.jetId & 2)))  # Jets = AK4 jets
        fatjetsByPt = op.sort(t.FatJet, lambda fatjet: -fatjet.p4.Pt())
        fatjetsSel = op.select(
            fatjetsByPt, lambda j: op.AND(j.p4.Pt() > 20.,
                                          op.abs(j.p4.Eta()) < 2.4,
                                          (j.jetId & 2)))  # FatJets = AK8 jets
        # exclude from the jetsSel any jet that happens to include within its reconstruction cone a muon or an electron.
        jets = op.select(
            jetsSel, lambda j: op.AND(
                op.NOT(
                    op.rng_any(electrons, lambda ele: op.deltaR(j.p4, ele.p4) <
                               0.3)),
                op.NOT(
                    op.rng_any(muons, lambda mu: op.deltaR(j.p4, mu.p4) < 0.3))
            ))
        fatjets = op.select(
            fatjetsSel, lambda j: op.AND(
                op.NOT(
                    op.rng_any(electrons, lambda ele: op.deltaR(j.p4, ele.p4) <
                               0.3)),
                op.NOT(
                    op.rng_any(muons, lambda mu: op.deltaR(j.p4, mu.p4) < 0.3))
            ))
        # Boosted and resolved jets categories #
        if era == "2016":  # Must check that subJet exists before looking at the btag
            lambda_boosted = lambda fatjet: op.OR(
                op.AND(fatjet.subJet1._idx.result != -1, fatjet.subJet1.
                       btagDeepB > 0.6321),
                op.AND(fatjet.subJet2._idx.result != -1, fatjet.subJet2.
                       btagDeepB > 0.6321))
            lambda_resolved = lambda jet: jet.btagDeepB > 0.6321
        elif era == "2017":
            lambda_boosted = lambda fatjet: op.OR(
                op.AND(fatjet.subJet1._idx.result != -1, fatjet.subJet1.
                       btagDeepB > 0.4941),
                op.AND(fatjet.subJet2._idx.result != -1, fatjet.subJet2.
                       btagDeepB > 0.4941))
            lambda_resolved = lambda jet: jet.btagDeepB > 0.4941
        elif era == "2018":
            lambda_boosted = lambda fatjet: op.OR(
                op.AND(fatjet.subJet1._idx.result != -1, fatjet.subJet1.
                       btagDeepB > 0.4184),
                op.AND(fatjet.subJet2._idx.result != -1, fatjet.subJet2.
                       btagDeepB > 0.4184))
            lambda_resolved = lambda jet: jet.btagDeepB > 0.4184

        # Select the bjets we want #
        bjetsResolved = op.select(jets, lambda_resolved)
        bjetsBoosted = op.select(fatjets, lambda_boosted)

        # Define the boosted and Resolved (+exclusive) selections #
        hasBoostedJets = noSel.refine("hasBoostedJets",
                                      cut=[op.rng_len(bjetsBoosted) >= 1])
        hasNotBoostedJets = noSel.refine("hasNotBoostedJets",
                                         cut=[op.rng_len(bjetsBoosted) == 0])
        hasResolvedJets = noSel.refine(
            "hasResolvedJets",
            cut=[op.rng_len(jets) >= 2,
                 op.rng_len(bjetsResolved) >= 1])
        hasNotResolvedJets = noSel.refine(
            "hasNotResolvedJets",
            cut=[op.OR(op.rng_len(jets) <= 1,
                       op.rng_len(bjetsResolved) == 0)])
        hasBoostedAndResolvedJets = noSel.refine(
            "hasBoostedAndResolvedJets",
            cut=[
                op.rng_len(bjetsBoosted) >= 1,
                op.rng_len(jets) >= 2,
                op.rng_len(bjetsResolved) >= 1
            ])
        hasNotBoostedAndResolvedJets = noSel.refine(
            "hasNotBoostedAndResolvedJets",
            cut=[
                op.OR(
                    op.rng_len(bjetsBoosted) == 0,
                    op.rng_len(jets) <= 1,
                    op.rng_len(bjetsResolved) == 0)
            ])
        hasExlusiveResolvedJets = noSel.refine(
            "hasExlusiveResolved",
            cut=[
                op.rng_len(jets) >= 2,
                op.rng_len(bjetsResolved) >= 1,
                op.rng_len(bjetsBoosted) == 0
            ])
        hasNotExlusiveResolvedJets = noSel.refine(
            "hasNotExlusiveResolved",
            cut=[
                op.OR(
                    op.OR(
                        op.rng_len(jets) <= 1,
                        op.rng_len(bjetsResolved) == 0),
                    op.AND(
                        op.rng_len(bjetsBoosted) >= 1,
                        op.rng_len(jets) >= 2,
                        op.rng_len(bjetsResolved) >= 1))
            ])
        hasExlusiveBoostedJets = noSel.refine(
            "hasExlusiveBoostedJets",
            cut=[
                op.rng_len(bjetsBoosted) >= 1,
                op.OR(op.rng_len(jets) <= 1,
                      op.rng_len(bjetsResolved) == 0)
            ])
        hasNotExlusiveBoostedJets = noSel.refine(
            "hasNotExlusiveBoostedJets",
            cut=[
                op.OR(
                    op.rng_len(bjetsBoosted) == 0,
                    op.AND(
                        op.rng_len(jets) >= 2,
                        op.rng_len(bjetsResolved) >= 1))
            ])

        # Counting events from different selections for debugging #
        # Passing Boosted selection #
        PassedBoosted = Plot.make1D("PassedBoosted",
                                    op.c_int(1),
                                    hasBoostedJets,
                                    EquidistantBinning(2, 0., 2.),
                                    title='Passed Boosted',
                                    xTitle='Passed Boosted')
        FailedBoosted = Plot.make1D("FailedBoosted",
                                    op.c_int(0),
                                    hasNotBoostedJets,
                                    EquidistantBinning(2, 0., 2.),
                                    title='Failed Boosted',
                                    xTitle='Failed Boosted')
        plots.append(
            SummedPlot("BoostedCase", [FailedBoosted, PassedBoosted],
                       xTitle="Boosted selection"))

        # Passing Resolved selection #
        PassedResolved = Plot.make1D("PassedResolved",
                                     op.c_int(1),
                                     hasResolvedJets,
                                     EquidistantBinning(2, 0., 2.),
                                     title='Passed Resolved',
                                     xTitle='Passed Resolved')
        FailedResolved = Plot.make1D("FailedResolved",
                                     op.c_int(0),
                                     hasNotResolvedJets,
                                     EquidistantBinning(2, 0., 2.),
                                     title='Failed Resolved',
                                     xTitle='Failed Resolved')
        plots.append(
            SummedPlot("ResolvedCase", [FailedResolved, PassedResolved],
                       xTitle="Resolved selection"))

        # Passing Exclusive Resolved (Resolved AND NOT Boosted) #
        PassedExclusiveResolved = Plot.make1D(
            "PassedExclusiveResolved",
            op.c_int(1),
            hasExlusiveResolvedJets,
            EquidistantBinning(2, 0., 2.),
            title='Passed Exclusive Resolved',
            xTitle='Passed Exclusive Resolved')
        FailedExclusiveResolved = Plot.make1D(
            "FailedExclusiveResolved",
            op.c_int(0),
            hasNotExlusiveResolvedJets,
            EquidistantBinning(2, 0., 2.),
            title='Failed Exclusive Resolved',
            xTitle='Failed Exclusive Resolved')
        plots.append(
            SummedPlot("ExclusiveResolvedCase",
                       [FailedExclusiveResolved, PassedExclusiveResolved],
                       xTitle="Exclusive Resolved selection"))

        # Passing Exclusive Boosted (Boosted AND NOT Resolved) #
        PassedExclusiveBoosted = Plot.make1D("PassedExclusiveBoosted",
                                             op.c_int(1),
                                             hasExlusiveBoostedJets,
                                             EquidistantBinning(2, 0., 2.),
                                             title='Passed Exclusive Boosted',
                                             xTitle='Passed Exclusive Boosted')
        FailedExclusiveBoosted = Plot.make1D("FailedExclusiveBoosted",
                                             op.c_int(0),
                                             hasNotExlusiveBoostedJets,
                                             EquidistantBinning(2, 0., 2.),
                                             title='Failed Exclusive Boosted',
                                             xTitle='Failed Exclusive Boosted')
        plots.append(
            SummedPlot("ExclusiveBoostedCase",
                       [FailedExclusiveBoosted, PassedExclusiveBoosted],
                       xTitle="Exclusive Boosted selection"))

        # Passing Boosted AND Resolved #
        PassedBoth = Plot.make1D("PassedBoth",
                                 op.c_int(1),
                                 hasBoostedAndResolvedJets,
                                 EquidistantBinning(2, 0., 2.),
                                 title='Passed Both Boosted and Resolved',
                                 xTitle='Passed Boosted and Resolved')
        FailedBoth = Plot.make1D(
            "FailedBoth",  # Means failed the (Boosted AND Resolved) = either one or the other 
            op.c_int(0),
            hasNotBoostedAndResolvedJets,
            EquidistantBinning(2, 0., 2.),
            title='Failed combination Boosted and Resolved',
            xTitle='Failed combination')
        plots.append(
            SummedPlot("BoostedAndResolvedCase", [FailedBoth, PassedBoth],
                       xTitle="Boosted and Resolved selection"))

        # Count number of boosted and resolved jets #
        plots.append(
            Plot.make1D("NBoostedJets",
                        op.rng_len(bjetsBoosted),
                        hasBoostedJets,
                        EquidistantBinning(5, 0., 5.),
                        title='Number of boosted jets in boosted case',
                        xTitle='N boosted bjets'))
        plots.append(
            Plot.make1D(
                "NResolvedJets",
                op.rng_len(bjetsResolved),
                hasExlusiveResolvedJets,
                EquidistantBinning(5, 0., 5.),
                title='Number of resolved jets in exclusive resolved case',
                xTitle='N resolved bjets'))

        # Plot number of subjets in the boosted fatjets #
        lambda_noSubjet = lambda fatjet: op.AND(
            fatjet.subJet1._idx.result == -1,
            op.AND(fatjet.subJet2._idx.result == -1))
        lambda_oneSubjet = lambda fatjet: op.AND(
            fatjet.subJet1._idx.result != -1,
            op.AND(fatjet.subJet2._idx.result == -1))
        lambda_twoSubjet = lambda fatjet: op.AND(
            fatjet.subJet1._idx.result != -1,
            op.AND(fatjet.subJet2._idx.result != -1))

        hasNoSubjet = hasBoostedJets.refine(
            "hasNoSubjet", cut=[lambda_noSubjet(bjetsBoosted[0])])
        hasOneSubjet = hasBoostedJets.refine(
            "hasOneSubjet", cut=[lambda_oneSubjet(bjetsBoosted[0])])
        hasTwoSubjet = hasBoostedJets.refine(
            "hasTwoSubjet", cut=[lambda_twoSubjet(bjetsBoosted[0])])

        plot_hasNoSubjet = Plot.make1D(
            "plot_hasNoSubjet",  # Fill bin 0
            op.c_int(0),
            hasNoSubjet,
            EquidistantBinning(3, 0., 3.),
            title='Boosted jet without subjet')
        plot_hasOneSubjet = Plot.make1D(
            "plot_hasOneSubjet",  # Fill bin 1
            op.c_int(1),
            hasOneSubjet,
            EquidistantBinning(3, 0., 3.),
            title='Boosted jet with one subjet')
        plot_hasTwoSubjet = Plot.make1D(
            "plot_hasTwoSubjet",  # Fill bin 2
            op.c_int(2),
            hasTwoSubjet,
            EquidistantBinning(3, 0., 3.),
            title='Boosted jet with two subjets')
        plots.append(
            SummedPlot(
                "NumberOfSubjets",
                [plot_hasNoSubjet, plot_hasOneSubjet, plot_hasTwoSubjet],
                xTitle="Number of subjets in boosted jet"))

        # Plot jets quantities without the dilepton selections #
        plots += makeFatJetPlots(self,
                                 sel=hasBoostedJets,
                                 fatjet=bjetsBoosted[0],
                                 suffix="BoostedJets",
                                 channel="NoChannel")
        plots += makeJetsPlots(self,
                               sel=hasResolvedJets,
                               jets=bjetsResolved,
                               suffix="ResolvedJets",
                               channel="NoChannel")

        #############################################################################
        ##################### Jets + Dilepton combination ###########################
        #############################################################################
        # Combine dilepton and Resolved (Exclusive = NOT Boosted) selections #
        hasOsElElOutZResolvedJets = hasOsElElOutZ.refine(
            "hasOsElElOutZResolvedJets",
            cut=[
                op.rng_len(jets) >= 2,
                op.rng_len(bjetsResolved) >= 1,
                op.rng_len(bjetsBoosted) == 0
            ])
        hasOsMuMuOutZResolvedJets = hasOsMuMuOutZ.refine(
            "hasOsMuMuOutZResolvedJets",
            cut=[
                op.rng_len(jets) >= 2,
                op.rng_len(bjetsResolved) >= 1,
                op.rng_len(bjetsBoosted) == 0
            ])
        hasOsElMuOutZResolvedJets = hasOsElMuOutZ.refine(
            "hasOsElMuOutZResolvedJets",
            cut=[
                op.rng_len(jets) >= 2,
                op.rng_len(bjetsResolved) >= 1,
                op.rng_len(bjetsBoosted) == 0
            ])
        hasOsMuElOutZResolvedJets = hasOsMuElOutZ.refine(
            "hasOsMuElOutZResolvedJets",
            cut=[
                op.rng_len(jets) >= 2,
                op.rng_len(bjetsResolved) >= 1,
                op.rng_len(bjetsBoosted) == 0
            ])

        # Combine dilepton and Boosted selections #
        hasOsElElOutZBoostedJets = hasOsElElOutZ.refine(
            "hasOsElElOutZBoostedJets", cut=[op.rng_len(bjetsBoosted) >= 1])
        hasOsMuMuOutZBoostedJets = hasOsMuMuOutZ.refine(
            "hasOsMuMuOutZBoostedJets", cut=[op.rng_len(bjetsBoosted) >= 1])
        hasOsElMuOutZBoostedJets = hasOsElMuOutZ.refine(
            "hasOsElMuOutZBoostedJets", cut=[op.rng_len(bjetsBoosted) >= 1])
        hasOsMuElOutZBoostedJets = hasOsMuElOutZ.refine(
            "hasOsMuElOutZBoostedJets", cut=[op.rng_len(bjetsBoosted) >= 1])

        # Plot dilepton with OS, Z peak and Resolved jets selections #
        plots += makeDileptonPlots(self,
                                   sel=hasOsElElOutZResolvedJets,
                                   dilepton=OsElEl[0],
                                   suffix='hasOsdilep_OutZ_ResolvedJets',
                                   channel='ElEl')
        plots += makeDileptonPlots(self,
                                   sel=hasOsMuMuOutZResolvedJets,
                                   dilepton=OsMuMu[0],
                                   suffix='hasOsdilep_OutZ_ResolvedJets',
                                   channel='MuMu')
        plots += makeDileptonPlots(self,
                                   sel=hasOsElMuOutZResolvedJets,
                                   dilepton=OsElMu[0],
                                   suffix='hasOsdilep_OutZ_ResolvedJets',
                                   channel='ElMu')
        plots += makeDileptonPlots(self,
                                   sel=hasOsMuElOutZResolvedJets,
                                   dilepton=OsMuEl[0],
                                   suffix='hasOsdilep_OutZ_ResolvedJets',
                                   channel='MuEl')

        # Plot dilepton with OS dilepton, Z peak and Boosted jets selections #
        plots += makeDileptonPlots(self,
                                   sel=hasOsElElOutZBoostedJets,
                                   dilepton=OsElEl[0],
                                   suffix='hasOsdilep_OutZ_BoostedJets',
                                   channel='ElEl')
        plots += makeDileptonPlots(self,
                                   sel=hasOsMuMuOutZBoostedJets,
                                   dilepton=OsMuMu[0],
                                   suffix='hasOsdilep_OutZ_BoostedJets',
                                   channel='MuMu')
        plots += makeDileptonPlots(self,
                                   sel=hasOsElMuOutZBoostedJets,
                                   dilepton=OsElMu[0],
                                   suffix='hasOsdilep_OutZ_BoostedJets',
                                   channel='ElMu')
        plots += makeDileptonPlots(self,
                                   sel=hasOsMuElOutZBoostedJets,
                                   dilepton=OsMuEl[0],
                                   suffix='hasOsdilep_OutZ_BoostedJets',
                                   channel='MuEl')

        # Plotting the fatjet for OS dilepton, Z peak and Boosted jets selections #
        plots += makeFatJetPlots(self,
                                 sel=hasOsElElOutZBoostedJets,
                                 fatjet=bjetsBoosted[0],
                                 suffix="hasOsdilep_OutZ_BoostedJets",
                                 channel="ElEl")
        plots += makeFatJetPlots(self,
                                 sel=hasOsMuMuOutZBoostedJets,
                                 fatjet=bjetsBoosted[0],
                                 suffix="hasOsdilep_OutZ_BoostedJets",
                                 channel="MuMu")
        plots += makeFatJetPlots(self,
                                 sel=hasOsElMuOutZBoostedJets,
                                 fatjet=bjetsBoosted[0],
                                 suffix="hasOsdilep_OutZ_BoostedJets",
                                 channel="ElMu")
        plots += makeFatJetPlots(self,
                                 sel=hasOsMuElOutZBoostedJets,
                                 fatjet=bjetsBoosted[0],
                                 suffix="hasOsdilep_OutZ_BoostedJets",
                                 channel="MuEl")

        # Plotting the jets for OS dilepton, Z peak and Resolved jets selections #
        plots += makeJetsPlots(self,
                               sel=hasOsElElOutZResolvedJets,
                               jets=bjetsResolved,
                               suffix="hasOsdilep_OutZ_ResolvedJets",
                               channel="ElEl")
        plots += makeJetsPlots(self,
                               sel=hasOsMuMuOutZResolvedJets,
                               jets=bjetsResolved,
                               suffix="hasOsdilep_OutZ_ResolvedJets",
                               channel="MuMu")
        plots += makeJetsPlots(self,
                               sel=hasOsElMuOutZResolvedJets,
                               jets=bjetsResolved,
                               suffix="hasOsdilep_OutZ_ResolvedJets",
                               channel="ElMu")
        plots += makeJetsPlots(self,
                               sel=hasOsMuElOutZResolvedJets,
                               jets=bjetsResolved,
                               suffix="hasOsdilep_OutZ_ResolvedJets",
                               channel="MuEl")

        ## helper selection (OR) to make sure jet calculations are only done once
        #hasOSLL = noSel.refine("hasOSLL", cut=op.OR(*( hasOSLL_cmbRng(rng) for rng in osLLRng.values())))
        #forceDefine(t._Jet.calcProd, hasOSLL)
        #for varNm in t._Jet.available:
        #    forceDefine(t._Jet[varNm], hasOSLL)
        return plots
예제 #14
0
    def createHistos(self):
    ''' Create all the histos for the analysis '''

        ### Analysis histos
        for key_chan in channel:
        ichan = channnel[key_chan]

        # Event
        self.NewHisto('HT',   ichan, 80, 0, 400)
        self.NewHisto('MET',  ichan, 30, 0, 150)
        self.NewHisto('NJets',ichan, 8 ,-0.5, 7.5)
        self.NewHisto('Btags',ichan, 4 ,-0.5, 3.5)
        self.NewHisto('Vtx',  ichan, 10, -0.5, 9.5)
        self.NewHisto('NBtagNJets', ichan, 7, -0.5, 6.5)
        self.NewHisto('NBtagNJets_3bins', ichan, 3, -0.5, 2.5)
        # Leptons
        self.NewHisto('Lep0Pt', ichan, 20, 20, 120)
        self.NewHisto('Lep1Pt', ichan, 16, 10, 90)
        self.NewHisto('Lep0Eta', ichan, 50, -2.5, 2.5)
        self.NewHisto('Lep1Eta', ichan, 50, -2.5, 2.5)
        self.NewHisto('Lep0Phi', ichan, 20, -1, 1)
        self.NewHisto('Lep1Phi', ichan, 20, -1, 1)
        self.NewHisto('DilepPt', ichan, 40, 0, 200)
        self.NewHisto('InvMass', ichan, 60, 0, 300)
        self.NewHisto('DYMass',  ichan, 200, 70, 110)
        self.NewHisto('DYMassBB',  ichan, 200, 70, 110)
        self.NewHisto('DYMassBE',  ichan, 200, 70, 110)
        self.NewHisto('DYMassEB',  ichan, 200, 70, 110)
        self.NewHisto('DYMassEE',  ichan, 200, 70, 110)
        self.NewHisto('DeltaPhi',  ichan, 20, 0, 1)
        if ichan == chan[ch.ElMu]:
           self.NewHisto('ElecEta', 'ElMu', 50, -2.5, 2.5)
           self.NewHisto('MuonEta', 'ElMu', 50, -2.5, 2.5)
           self.NewHisto('ElecPt', 'ElMu', 20, 10, 110)
           self.NewHisto('MuonPt', 'ElMu', 20, 10, 110)
           self.NewHisto('ElecPhi', 'ElMu', 20, -1, 1)
           self.NewHisto('MuonPhi', 'ElMu', 20, -1, 1)

    def FillHistograms(self, leptons, jets, pmet, ich, ilev, isys):
    ''' Fill all the histograms. Take the inputs from lepton list, jet list, pmet '''
        if self.SS: return               # Do not fill histograms for same-sign events
        if not len(leptons) >= 2: return # Just in case
    
        # Re-calculate the observables
        lep0  = leptons[0]; lep1 = leptons[1]
        l0pt  = lep0.Pt();  l1pt  = lep1.Pt()
        l0eta = lep0.Eta(); l1eta = lep1.Eta()
        l0phi = lep0.Phi(); l1phi = lep1.Phi()
        dphi  = DeltaPhi(lep0, lep1)
        mll   = InvMass(lep0, lep1)
        dipt  = DiPt(lep0, lep1)
        mupt  = 0; elpt  = 0
        mueta = 0; eleta = 0
        muphi = 0; elphi = 0
        if ich == channel.ElMu:
           if lep0.IsMuon():
           mu = lep0
           el = lep1
        else:
           mu = lep1
           el = lep0
        elpt  = el.Pt();  mupt  = mu.Pt()
        eleta = el.Eta(); mueta = mu.Eta()
        elphi = el.Phi(); muphi = mu.Phi()
          
        met = pmet.Pt()
        ht = 0; 
   
    
        ### Fill the histograms
        #if ich == ch.ElMu and ilev == lev.dilepton: print 'Syst = ', isys, ', weight = ', self.weight
        self.GetHisto('HT',   ich).Fill(ht)
        self.GetHisto('MET',  ich).Fill(met)
        self.GetHisto('NJets',ich).Fill(njet)
        self.GetHisto('Btags',ich).Fill(nbtag)
        self.GetHisto('Vtx',  ich).Fill(self.nvtx)
        self.GetHisto("InvMass", ich, ).Fill(mll)

    
       # Leptons
       self.GetHisto('Lep0Pt', ich).Fill(l0pt)
       self.GetHisto('Lep1Pt', ich).Fill(l1pt)
       self.GetHisto('Lep0Eta', ich).Fill(l0eta)
       self.GetHisto('Lep1Eta', ich).Fill(l1eta)
       self.GetHisto('Lep0Phi', ich).Fill(l0phi/3.141592)
       self.GetHisto('Lep1Phi', ich).Fill(l1phi/3.141592)
       self.GetHisto('DilepPt', ich).Fill(dipt, self.weight)
       self.GetHisto('DeltaPhi',  ich).Fill(dphi/3.141592)
       self.GetHisto('InvMass', ich).Fill(mll, self.weight)
       if mll > 70 and mll < 110: 
          self.GetHisto('DYMass',  ich).Fill(mll)
       l0eta = abs(l0eta); l1eta = abs(l1eta)
       if ich == chan.ElEl:
          if   l0eta <= 1.479 and l1eta <= 1.479: self.GetHisto('DYMassBB',  ich).Fill(mll)
          elif l0eta <= 1.479 and l1eta  > 1.479: self.GetHisto('DYMassBE',  ich).Fill(mll)
          elif l0eta  > 1.479 and l1eta <= 1.479: self.GetHisto('DYMassEB',  ich).Fill(mll)
          elif l0eta  > 1.479 and l1eta  > 1.479: self.GetHisto('DYMassEE',  ich).Fill(mll)
      if ich == chan.ElMu:
         self.GetHisto('ElecEta', ich).Fill(eleta)
         self.GetHisto('ElecPt',  ich).Fill(elpt)
         self.GetHisto('ElecPhi', ich).Fill(elphi)
         self.GetHisto('MuonEta', ich).Fill(mueta)
         self.GetHisto('MuonPt',  ich).Fill(mupt)
         self.GetHisto('MuonPhi', ich).Fill(muphi)


        muons = op.select(t.Muon, lambda mu : mu.pt > 20.)
        twoMuSel = noSel.refine("twoMuons", cut=[ op.rng_len(muons) > 1 ])
        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]}))

        electrons = op.select(t.Electron, lambda el : el.pt > 22.)
        twoElSel = noSel.refine("twoElectrons", cut=[ op.rng_len(electrons) > 1 ])
        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]}))



        return plots
예제 #15
0
    def definePlots(self, t, noSel, sample=None, sampleCfg=None):
        noSel = super(BtagEffAndMistagNano,
                      self).prepareObjects(t,
                                           noSel,
                                           sample,
                                           sampleCfg,
                                           channel='DL',
                                           forSkimmer=True)

        era = sampleCfg['era']
        plots = []

        forceDefine(self.tree._Jet.calcProd, noSel)  # Jets for configureJets
        forceDefine(self.tree._FatJet.calcProd,
                    noSel)  # FatJets for configureJets
        forceDefine(
            getattr(
                self.tree, "_{0}".format(
                    "MET" if self.era != "2017" else "METFixEE2017")).calcProd,
            noSel)  # MET for configureMET

        # protection against data #
        if not self.is_MC:
            return []

        #############################################################################
        #                                   AK4                                     #
        #############################################################################
        ak4_truth_lightjets = op.select(self.ak4Jets,
                                        lambda j: j.hadronFlavour == 0)
        ak4_truth_cjets = op.select(self.ak4Jets,
                                    lambda j: j.hadronFlavour == 4)
        ak4_truth_bjets = op.select(self.ak4Jets,
                                    lambda j: j.hadronFlavour == 5)

        N_ak4_truth_lightjets = Plot.make3D(
            'N_ak4_truth_lightjets', [
                op.map(ak4_truth_lightjets, lambda j: op.abs(j.eta)),
                op.map(ak4_truth_lightjets, lambda j: j.pt),
                op.map(ak4_truth_lightjets, lambda j: j.btagDeepFlavB)
            ],
            noSel, [
                EquidistantBinning(100, 0., 2.5),
                EquidistantBinning(100, 0., 1000),
                EquidistantBinning(100, 0., 1.)
            ],
            xTitle='lightjet #eta',
            yTitle='lightjet P_{T}',
            zTitle='lightjet Btagging score')

        N_ak4_truth_cjets = Plot.make3D('N_ak4_truth_cjets', [
            op.map(ak4_truth_cjets, lambda j: op.abs(j.eta)),
            op.map(ak4_truth_cjets, lambda j: j.pt),
            op.map(ak4_truth_cjets, lambda j: j.btagDeepFlavB)
        ],
                                        noSel, [
                                            EquidistantBinning(100, 0., 2.5),
                                            EquidistantBinning(100, 0., 1000),
                                            EquidistantBinning(100, 0., 1.)
                                        ],
                                        xTitle='cjet #eta',
                                        yTitle='cjet P_{T}',
                                        zTitle='cjet Btagging score')

        N_ak4_truth_bjets = Plot.make3D('N_ak4_truth_bjets', [
            op.map(ak4_truth_bjets, lambda j: op.abs(j.eta)),
            op.map(ak4_truth_bjets, lambda j: j.pt),
            op.map(ak4_truth_bjets, lambda j: j.btagDeepFlavB)
        ],
                                        noSel, [
                                            EquidistantBinning(100, 0., 2.5),
                                            EquidistantBinning(100, 0., 1000),
                                            EquidistantBinning(100, 0., 1.)
                                        ],
                                        xTitle='bjet #eta',
                                        yTitle='bjet P_{T}',
                                        zTitle='bjet Btagging score')

        plots.extend(
            [N_ak4_truth_lightjets, N_ak4_truth_cjets, N_ak4_truth_bjets])

        ak4_btagged_lightjets = op.select(ak4_truth_lightjets,
                                          self.lambda_ak4Btag)
        ak4_btagged_cjets = op.select(ak4_truth_cjets, self.lambda_ak4Btag)
        ak4_btagged_bjets = op.select(ak4_truth_bjets, self.lambda_ak4Btag)

        N_ak4_btagged_lightjets = Plot.make3D(
            'N_ak4_btagged_lightjets', [
                op.map(ak4_btagged_lightjets, lambda j: op.abs(j.eta)),
                op.map(ak4_btagged_lightjets, lambda j: j.pt),
                op.map(ak4_btagged_lightjets, lambda j: j.btagDeepFlavB)
            ],
            noSel, [
                EquidistantBinning(100, 0., 2.5),
                EquidistantBinning(100, 0., 1000),
                EquidistantBinning(100, 0., 1.)
            ],
            xTitle='lightjet #eta',
            yTitle='lightjet P_{T}',
            zTitle='lightjet Btagging score')

        N_ak4_btagged_cjets = Plot.make3D(
            'N_ak4_btagged_cjets', [
                op.map(ak4_btagged_cjets, lambda j: op.abs(j.eta)),
                op.map(ak4_btagged_cjets, lambda j: j.pt),
                op.map(ak4_btagged_cjets, lambda j: j.btagDeepFlavB)
            ],
            noSel, [
                EquidistantBinning(100, 0., 2.5),
                EquidistantBinning(100, 0., 1000),
                EquidistantBinning(100, 0., 1.)
            ],
            xTitle='cjet #eta',
            yTitle='cjet P_{T}',
            zTitle='cjet Btagging score')

        N_ak4_btagged_bjets = Plot.make3D(
            'N_ak4_btagged_bjets', [
                op.map(ak4_btagged_bjets, lambda j: op.abs(j.eta)),
                op.map(ak4_btagged_bjets, lambda j: j.pt),
                op.map(ak4_btagged_bjets, lambda j: j.btagDeepFlavB)
            ],
            noSel, [
                EquidistantBinning(100, 0., 2.5),
                EquidistantBinning(100, 0., 1000),
                EquidistantBinning(100, 0., 1.)
            ],
            xTitle='bjet #eta',
            yTitle='bjet P_{T}',
            zTitle='bjet Btagging score')

        plots.extend([
            N_ak4_btagged_lightjets, N_ak4_btagged_cjets, N_ak4_btagged_bjets
        ])

        #############################################################################
        #                                   AK8                                     #
        #############################################################################

        # Truth MC object hadron flavour #
        # subjet.nBHadrons>0 : bjet
        # subjet.nCHadrons>0 : cjet
        # else               : lightjet
        ak8subJet1_truth_lightjets = op.select(
            self.ak8Jets, lambda j: op.AND(j.subJet1.nBHadrons == 0, j.subJet1.
                                           nCHadrons == 0))
        ak8subJet2_truth_lightjets = op.select(
            self.ak8Jets, lambda j: op.AND(j.subJet2.nBHadrons == 0, j.subJet2.
                                           nCHadrons == 0))
        ak8subJet1_truth_cjets = op.select(self.ak8Jets,
                                           lambda j: j.subJet1.nCHadrons > 0)
        ak8subJet2_truth_cjets = op.select(self.ak8Jets,
                                           lambda j: j.subJet2.nCHadrons > 0)
        ak8subJet1_truth_bjets = op.select(self.ak8Jets,
                                           lambda j: j.subJet1.nBHadrons > 0)
        ak8subJet2_truth_bjets = op.select(self.ak8Jets,
                                           lambda j: j.subJet2.nBHadrons > 0)

        N_ak8_truth_subJet1_lightjets = Plot.make3D(
            'N_ak8_truth_subJet1_lightjets', [
                op.map(ak8subJet1_truth_lightjets,
                       lambda j: op.abs(j.subJet1.eta)),
                op.map(ak8subJet1_truth_lightjets, lambda j: j.subJet1.pt),
                op.map(ak8subJet1_truth_lightjets,
                       lambda j: j.subJet1.btagDeepB)
            ],
            noSel, [
                EquidistantBinning(100, 0., 2.5),
                EquidistantBinning(100, 0., 1000),
                EquidistantBinning(100, 0., 1.)
            ],
            xTitle='lightjet subJet1 #eta',
            yTitle='lightjet subJet1 P_{T}',
            zTitle='lightjet subJet1 Btagging score')
        N_ak8_truth_subJet2_lightjets = Plot.make3D(
            'N_ak8_truth_subJet2_lightjets', [
                op.map(ak8subJet2_truth_lightjets,
                       lambda j: op.abs(j.subJet2.eta)),
                op.map(ak8subJet2_truth_lightjets, lambda j: j.subJet2.pt),
                op.map(ak8subJet2_truth_lightjets,
                       lambda j: j.subJet2.btagDeepB)
            ],
            noSel, [
                EquidistantBinning(100, 0., 2.5),
                EquidistantBinning(100, 0., 1000),
                EquidistantBinning(100, 0., 1.)
            ],
            xTitle='lightjet subJet2 #eta',
            yTitle='lightjet subJet2 P_{T}',
            zTitle='lightjet subJet2 Btagging score')
        N_ak8_truth_subJet1_cjets = Plot.make3D(
            'N_ak8_truth_subJet1_cjets', [
                op.map(ak8subJet1_truth_cjets,
                       lambda j: op.abs(j.subJet1.eta)),
                op.map(ak8subJet1_truth_cjets, lambda j: j.subJet1.pt),
                op.map(ak8subJet1_truth_cjets, lambda j: j.subJet1.btagDeepB)
            ],
            noSel, [
                EquidistantBinning(100, 0., 2.5),
                EquidistantBinning(100, 0., 1000),
                EquidistantBinning(100, 0., 1.)
            ],
            xTitle='cjet subJet1 #eta',
            yTitle='cjet subJet1 P_{T}',
            zTitle='cjet subJet1 Btagging score')
        N_ak8_truth_subJet2_cjets = Plot.make3D(
            'N_ak8_truth_subJet2_cjets', [
                op.map(ak8subJet2_truth_cjets,
                       lambda j: op.abs(j.subJet2.eta)),
                op.map(ak8subJet2_truth_cjets, lambda j: j.subJet2.pt),
                op.map(ak8subJet2_truth_cjets, lambda j: j.subJet2.btagDeepB)
            ],
            noSel, [
                EquidistantBinning(100, 0., 2.5),
                EquidistantBinning(100, 0., 1000),
                EquidistantBinning(100, 0., 1.)
            ],
            xTitle='cjet subJet2 #eta',
            yTitle='cjet subJet2 P_{T}',
            zTitle='cjet subJet2 Btagging score')
        N_ak8_truth_subJet1_bjets = Plot.make3D(
            'N_ak8_truth_subJet1_bjets', [
                op.map(ak8subJet1_truth_bjets,
                       lambda j: op.abs(j.subJet1.eta)),
                op.map(ak8subJet1_truth_bjets, lambda j: j.subJet1.pt),
                op.map(ak8subJet1_truth_bjets, lambda j: j.subJet1.btagDeepB)
            ],
            noSel, [
                EquidistantBinning(100, 0., 2.5),
                EquidistantBinning(100, 0., 1000),
                EquidistantBinning(100, 0., 1.)
            ],
            xTitle='bjet subJet1 #eta',
            yTitle='bjet subJet1 P_{T}',
            zTitle='bjet subJet1 Btagging score')
        N_ak8_truth_subJet2_bjets = Plot.make3D(
            'N_ak8_truth_subJet2_bjets', [
                op.map(ak8subJet2_truth_bjets,
                       lambda j: op.abs(j.subJet2.eta)),
                op.map(ak8subJet2_truth_bjets, lambda j: j.subJet2.pt),
                op.map(ak8subJet2_truth_bjets, lambda j: j.subJet2.btagDeepB)
            ],
            noSel, [
                EquidistantBinning(100, 0., 2.5),
                EquidistantBinning(100, 0., 1000),
                EquidistantBinning(100, 0., 1.)
            ],
            xTitle='bjet subJet2 #eta',
            yTitle='bjet subJet2 P_{T}',
            zTitle='bjet subJet2 Btagging score')

        plots.extend([
            N_ak8_truth_subJet1_lightjets, N_ak8_truth_subJet2_lightjets,
            N_ak8_truth_subJet1_cjets, N_ak8_truth_subJet2_cjets,
            N_ak8_truth_subJet1_bjets, N_ak8_truth_subJet2_bjets
        ])
        plots.append(
            SummedPlot(
                'N_ak8_truth_lightjets',
                [N_ak8_truth_subJet1_lightjets, N_ak8_truth_subJet2_lightjets],
                xTitle='lightjet #eta',
                yTitle='lightjet P_{T}',
                zTitle='lightjet Btagging score'))
        plots.append(
            SummedPlot('N_ak8_truth_cjets',
                       [N_ak8_truth_subJet1_cjets, N_ak8_truth_subJet2_cjets],
                       xTitle='cjet #eta',
                       yTitle='cjet P_{T}',
                       zTitle='cjet Btagging score'))
        plots.append(
            SummedPlot('N_ak8_truth_bjets',
                       [N_ak8_truth_subJet1_bjets, N_ak8_truth_subJet2_bjets],
                       xTitle='bjet #eta',
                       yTitle='bjet P_{T}',
                       zTitle='bjet Btagging score'))

        # Btagged objects per flavour #
        ak8subJet1_btagged_lightjets = op.select(
            ak8subJet1_truth_lightjets,
            lambda j: self.lambda_subjetBtag(j.subJet1))
        ak8subJet2_btagged_lightjets = op.select(
            ak8subJet2_truth_lightjets,
            lambda j: self.lambda_subjetBtag(j.subJet2))
        ak8subJet1_btagged_cjets = op.select(
            ak8subJet1_truth_cjets,
            lambda j: self.lambda_subjetBtag(j.subJet1))
        ak8subJet2_btagged_cjets = op.select(
            ak8subJet2_truth_cjets,
            lambda j: self.lambda_subjetBtag(j.subJet2))
        ak8subJet1_btagged_bjets = op.select(
            ak8subJet1_truth_bjets,
            lambda j: self.lambda_subjetBtag(j.subJet1))
        ak8subJet2_btagged_bjets = op.select(
            ak8subJet2_truth_bjets,
            lambda j: self.lambda_subjetBtag(j.subJet2))

        N_ak8_btagged_subJet1_lightjets = Plot.make3D(
            'N_ak8_btagged_subJet1_lightjets', [
                op.map(ak8subJet1_btagged_lightjets,
                       lambda j: op.abs(j.subJet1.eta)),
                op.map(ak8subJet1_btagged_lightjets, lambda j: j.subJet1.pt),
                op.map(ak8subJet1_btagged_lightjets,
                       lambda j: j.subJet1.btagDeepB)
            ],
            noSel, [
                EquidistantBinning(100, 0., 2.5),
                EquidistantBinning(100, 0., 1000),
                EquidistantBinning(100, 0., 1.)
            ],
            xTitle='lightjet subJet1 #eta',
            yTitle='lightjet subJet1 P_{T}',
            zTitle='lightjet subJet1 Btagging score')
        N_ak8_btagged_subJet2_lightjets = Plot.make3D(
            'N_ak8_btagged_subJet2_lightjets', [
                op.map(ak8subJet2_btagged_lightjets,
                       lambda j: op.abs(j.subJet2.eta)),
                op.map(ak8subJet2_btagged_lightjets, lambda j: j.subJet2.pt),
                op.map(ak8subJet2_btagged_lightjets,
                       lambda j: j.subJet2.btagDeepB)
            ],
            noSel, [
                EquidistantBinning(100, 0., 2.5),
                EquidistantBinning(100, 0., 1000),
                EquidistantBinning(100, 0., 1.)
            ],
            xTitle='lightjet subJet2 #eta',
            yTitle='lightjet subJet2 P_{T}',
            zTitle='lightjet subJet2 Btagging score')
        N_ak8_btagged_subJet1_cjets = Plot.make3D(
            'N_ak8_btagged_subJet1_cjets', [
                op.map(ak8subJet1_btagged_cjets,
                       lambda j: op.abs(j.subJet1.eta)),
                op.map(ak8subJet1_btagged_cjets, lambda j: j.subJet1.pt),
                op.map(ak8subJet1_btagged_cjets, lambda j: j.subJet1.btagDeepB)
            ],
            noSel, [
                EquidistantBinning(100, 0., 2.5),
                EquidistantBinning(100, 0., 1000),
                EquidistantBinning(100, 0., 1.)
            ],
            xTitle='cjet subJet1 #eta',
            yTitle='cjet subJet1 P_{T}',
            zTitle='cjet subJet1 Btagging score')
        N_ak8_btagged_subJet2_cjets = Plot.make3D(
            'N_ak8_btagged_subJet2_cjets', [
                op.map(ak8subJet2_btagged_cjets,
                       lambda j: op.abs(j.subJet2.eta)),
                op.map(ak8subJet2_btagged_cjets, lambda j: j.subJet2.pt),
                op.map(ak8subJet2_btagged_cjets, lambda j: j.subJet2.btagDeepB)
            ],
            noSel, [
                EquidistantBinning(100, 0., 2.5),
                EquidistantBinning(100, 0., 1000),
                EquidistantBinning(100, 0., 1.)
            ],
            xTitle='cjet subJet2 #eta',
            yTitle='cjet subJet2 P_{T}',
            zTitle='cjet subJet2 Btagging score')
        N_ak8_btagged_subJet1_bjets = Plot.make3D(
            'N_ak8_btagged_subJet1_bjets', [
                op.map(ak8subJet1_btagged_bjets,
                       lambda j: op.abs(j.subJet1.eta)),
                op.map(ak8subJet1_btagged_bjets, lambda j: j.subJet1.pt),
                op.map(ak8subJet1_btagged_bjets, lambda j: j.subJet1.btagDeepB)
            ],
            noSel, [
                EquidistantBinning(100, 0., 2.5),
                EquidistantBinning(100, 0., 1000),
                EquidistantBinning(100, 0., 1.)
            ],
            xTitle='bjet subJet1 #eta',
            yTitle='bjet subJet1 P_{T}',
            zTitle='bjet subJet1 Btagging score')
        N_ak8_btagged_subJet2_bjets = Plot.make3D(
            'N_ak8_btagged_subJet2_bjets', [
                op.map(ak8subJet2_btagged_bjets,
                       lambda j: op.abs(j.subJet2.eta)),
                op.map(ak8subJet2_btagged_bjets, lambda j: j.subJet2.pt),
                op.map(ak8subJet2_btagged_bjets, lambda j: j.subJet2.btagDeepB)
            ],
            noSel, [
                EquidistantBinning(100, 0., 2.5),
                EquidistantBinning(100, 0., 1000),
                EquidistantBinning(100, 0., 1.)
            ],
            xTitle='bjet subJet2 #eta',
            yTitle='bjet subJet2 P_{T}',
            zTitle='bjet subJet2 Btagging score')

        plots.extend([
            N_ak8_btagged_subJet1_lightjets, N_ak8_btagged_subJet2_lightjets,
            N_ak8_btagged_subJet1_cjets, N_ak8_btagged_subJet2_cjets,
            N_ak8_btagged_subJet1_bjets, N_ak8_btagged_subJet2_bjets
        ])
        plots.append(
            SummedPlot('N_ak8_btagged_lightjets', [
                N_ak8_btagged_subJet1_lightjets,
                N_ak8_btagged_subJet2_lightjets
            ],
                       xTitle='lightjet #eta',
                       yTitle='lightjet P_{T}',
                       zTitle='lightjet Btagging score'))
        plots.append(
            SummedPlot(
                'N_ak8_btagged_cjets',
                [N_ak8_btagged_subJet1_cjets, N_ak8_btagged_subJet2_cjets],
                xTitle='cjet #eta',
                yTitle='cjet P_{T}',
                zTitle='cjet Btagging score'))
        plots.append(
            SummedPlot(
                'N_ak8_btagged_bjets',
                [N_ak8_btagged_subJet1_bjets, N_ak8_btagged_subJet2_bjets],
                xTitle='bjet #eta',
                yTitle='bjet P_{T}',
                zTitle='bjet Btagging score'))

        return plots
예제 #16
0
    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
    def definePlots(self, tree, noSel, sample=None, sampleCfg=None):
        from bamboo.plots import Plot, SummedPlot
        from bamboo.plots import EquidistantBinning as EqBin
        from bamboo import treefunctions as op

        if self.args.examples == "all":
            examples = list(i+1 for i in range(self.nExamples)) # 1-4 are fine, so is 7
        else:
            examples = list(set(int(tk) for tk in self.args.examples.split(",")))
        logger.info("Running the following examples: {0}".format(",".join(str(i) for i in examples)))
                
        plots = []
        if 1 in examples:
            ## Example 1: Plot the missing ET of all events.
            plots.append(Plot.make1D("Ex1_MET",
                tree.MET.pt, noSel,
                EqBin(100, 0., 2000.), title="MET (GeV)"))

        if 2 in examples:
            ## Example 2: Plot pT of all jets in all events.
            plots.append(Plot.make1D("Ex2_jetPt",
                op.map(tree.Jet, lambda j : j.pt), noSel,
                EqBin(100, 15., 60.), title="Jet p_{T} (GeV/c)"))

        if 3 in examples:
            ## Example 3: Plot pT of jets with |η| < 1.
            centralJets1 = op.select(tree.Jet, lambda j : op.abs(j.eta) < 1.)
            plots.append(Plot.make1D("Ex3_central1_jetPt",
                op.map(centralJets1, lambda j : j.pt), noSel,
                EqBin(100, 15., 60.), title="Jet p_{T} (GeV/c)"))

        if 4 in examples:
            ## Example 4: Plot the missing ET of events that have at least two jets with pT > 40 GeV.
            jets40 = op.select(tree.Jet, lambda j : j.pt > 40)
            hasTwoJets40 = noSel.refine("twoJets40", cut=(op.rng_len(jets40) >= 2))
            plots.append(Plot.make1D("Ex4_twoJets40_MET",
                tree.MET.pt, hasTwoJets40,
                EqBin(100, 0., 2000.), title="MET (GeV)"))

        if 5 in examples:
            ## Example 5: Plot the missing ET of events that have an opposite-sign muon pair with an invariant mass between 60 and 120 GeV.
            dimu_Z = op.combine(tree.Muon, N=2, pred=(lambda mu1, mu2 : op.AND(
                mu1.charge != mu2.charge,
                op.in_range(60., op.invariant_mass(mu1.p4, mu2.p4), 120.)
                )))
            hasDiMuZ = noSel.refine("hasDiMuZ", cut=(op.rng_len(dimu_Z) > 0))
            plots.append(Plot.make1D("Ex5_dimuZ_MET",
                tree.MET.pt, hasDiMuZ,
                EqBin(100, 0., 2000.), title="MET (GeV)"))

        if 6 in examples:
            ## Example 6: Plot pT of the trijet system with the mass closest to 172.5 GeV in each event and plot the maximum b-tagging discriminant value among the jets in the triplet.
            trijets = op.combine(tree.Jet, N=3)
            hadTop = op.rng_min_element_by(trijets,
                fun=lambda comb: op.abs((comb[0].p4+comb[1].p4+comb[2].p4).M()-172.5))
            hadTop_p4 = (hadTop[0].p4 + hadTop[1].p4 + hadTop[2].p4)
            hasTriJet = noSel.refine("hasTriJet", cut=(op.rng_len(trijets) > 0))
            plots.append(Plot.make1D("Ex6_trijet_topPt",
                hadTop_p4.Pt(), hasTriJet,
                EqBin(100, 15., 40.), title="Trijet p_{T} (GeV/c)"))
            plots.append(Plot.make1D("Ex6_trijet_maxbtag",
                op.max(op.max(hadTop[0].btag, hadTop[1].btag), hadTop[2].btag), hasTriJet,
                EqBin(100, 0., 1.), title="Trijet maximum b-tag"))
            if verbose:
                plots.append(Plot.make1D("Ex6_njets",
                    op.rng_len(tree.Jet), noSel,
                    EqBin(20, 0., 20.), title="Number of jets"))
                plots.append(Plot.make1D("Ex6_ntrijets",
                    op.rng_len(trijets), noSel,
                    EqBin(100, 0., 1000.), title="Number of 3-jet combinations"))
                plots.append(Plot.make1D("Ex6_trijet_mass",
                    hadTop_p4.M(), hasTriJet,
                    EqBin(100, 0., 250.), title="Trijet mass (GeV/c^{2})"))

        if 7 in examples:
            ## Example 7: Plot the sum of pT of jets with pT > 30 GeV that are not within 0.4 in ΔR of any lepton with pT > 10 GeV.
            el10  = op.select(tree.Electron, lambda el : el.pt > 10.)
            mu10  = op.select(tree.Muon    , lambda mu : mu.pt > 10.)
            cleanedJets30 = op.select(tree.Jet, lambda j : op.AND(
                j.pt > 30.,
                op.NOT(op.rng_any(el10, lambda el : op.deltaR(j.p4, el.p4) < 0.4 )),
                op.NOT(op.rng_any(mu10, lambda mu : op.deltaR(j.p4, mu.p4) < 0.4 ))
                ))
            plots.append(Plot.make1D("Ex7_sumCleanedJetPt",
                op.rng_sum(cleanedJets30, lambda j : j.pt), noSel,
                EqBin(100, 15., 200.), title="Sum p_{T} (GeV/c)"))

        if 8 in examples:
            ## Example 8: For events with at least three leptons and a same-flavor opposite-sign lepton pair, find the same-flavor opposite-sign lepton pair with the mass closest to 91.2 GeV and plot the transverse mass of the missing energy and the leading other lepton.
            # The plot is made for each of the different flavour categories (l+/- l-/+ l') and then summed,
            # because concatenation of containers is not (yet) supported.
            lepColl = { "El" : tree.Electron, "Mu" : tree.Muon }
            mt3lPlots = []
            for dlNm,dlCol in lepColl.items():
                dilep = op.combine(dlCol, N=2, pred=(lambda l1,l2 : op.AND(l1.charge != l2.charge)))
                hasDiLep = noSel.refine("hasDilep{0}{0}".format(dlNm), cut=(op.rng_len(dilep) > 0))
                dilepZ = op.rng_min_element_by(dilep, fun=lambda ll : op.abs(op.invariant_mass(ll[0].p4, ll[1].p4)-91.2))
                for tlNm,tlCol in lepColl.items():
                    if tlCol == dlCol:
                        hasTriLep = hasDiLep.refine("hasTrilep{0}{0}{1}".format(dlNm,tlNm),
                            cut=(op.rng_len(tlCol) > 2))
                        residLep = op.select(tlCol, lambda l : op.AND(l.idx != dilepZ[0].idx, l.idx != dilepZ[1].idx))
                        l3 = op.rng_max_element_by(residLep, lambda l : l.pt)
                    else:
                        hasTriLep = hasDiLep.refine("hasTriLep{0}{0}{1}".format(dlNm,tlNm),
                            cut=(op.rng_len(tlCol) > 0))
                        l3 = op.rng_max_element_by(tlCol, lambda l : l.pt)
                    mtPlot = Plot.make1D("Ex8_3lMT_{0}{0}{1}".format(dlNm,tlNm),
                        op.sqrt(2*l3.pt*tree.MET.pt*(1-op.cos(l3.phi-tree.MET.phi))), hasTriLep,
                        EqBin(100, 15., 250.), title="M_{T} (GeV/c^2)")
                    mt3lPlots.append(mtPlot)
                    plots.append(mtPlot)
            plots.append(SummedPlot("Ex8_3lMT", mt3lPlots))

        return plots
예제 #18
0
    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
예제 #19
0
    def definePlots(self, t, noSel, sample=None, sampleCfg=None):    
        from bamboo.analysisutils import forceDefine
        from bamboo.plots import Plot
        from bamboo.plots import EquidistantBinning as EqB
        from bamboo import treefunctions as op

        era = sampleCfg.get("era") if sampleCfg else None
        noSel = noSel.refine("passMETFlags", cut=METFilter(t.Flag, era) )
        puWeightsFile = None
        
        if era == "2016":
            sfTag="94X"
            puWeightsFile = os.path.join(os.path.dirname(__file__), "data/PileupFullRunII", "puweights2016.json")
        
        elif era == "2017":
            sfTag="94X"     
            puWeightsFile = os.path.join(os.path.dirname(__file__), "data/PileupFullRunII", "puweights2017.json")
        
        elif era == "2018":
            sfTag="102X"
            puWeightsFile = os.path.join(os.path.dirname(__file__), "data/PileupFullRunII", "puweights2018.json")
        
        if self.isMC(sample) and puWeightsFile is not None:
            from bamboo.analysisutils import makePileupWeight
            noSel = noSel.refine("puWeight", weight=makePileupWeight(puWeightsFile, t.Pileup_nTrueInt, systName="pileup"))
        
        isMC = self.isMC(sample)
        plots = []
        forceDefine(t._Muon.calcProd, noSel)

        # Wp // 2016- 2017 -2018 : Muon_mediumId   // https://twiki.cern.ch/twiki/bin/view/CMS/SWGuideMuonIdRun2#Muon_Isolation
        #To suppress nonprompt lep-tons, the impact parameter in three dimensions of the lepton track, with respect to the primaryvertex, is required to be less than 4 times its uncertainty (|SIP3D|<4)
        sorted_muons = op.sort(t.Muon, lambda mu : -mu.pt)
        muons = op.select(sorted_muons, lambda mu : op.AND(mu.pt > 10., op.abs(mu.eta) < 2.4, mu.mediumId, mu.pfRelIso04_all<0.15, op.abs(mu.sip3d < 4.)))
      
        # i pass 2016 seprate from 2017 &2018  because SFs need to be combined for BCDEF and GH eras !
        if era=="2016":
            doubleMuTrigSF = get_scalefactor("dilepton", ("doubleMuLeg_HHMoriond17_2016"), systName="mumutrig")    
            muMediumIDSF = get_scalefactor("lepton", ("muon_{0}_{1}".format(era, sfTag), "id_medium"), combine="weight", systName="muid")
            muMediumISOSF = get_scalefactor("lepton", ("muon_{0}_{1}".format(era, sfTag), "iso_tight_id_medium"), combine="weight", systName="muiso")
        else:
            doubleMuTrigSF = get_scalefactor("dilepton", ("doubleMuLeg_HHMoriond17_2016"), systName="mumutrig")    
            muMediumIDSF = get_scalefactor("lepton", ("muon_{0}_{1}".format(era, sfTag), "id_medium"), systName="muid")
            muMediumISOSF = get_scalefactor("lepton", ("muon_{0}_{1}".format(era, sfTag), "iso_tight_id_medium"), systName="muiso") 
        
        #Wp  // 2016: Electron_cutBased_Sum16==3  -> medium     // 2017 -2018  : Electron_cutBased ==3   --> medium ( Fall17_V2)
        # asking for electrons to be in the Barrel region with dz<1mm & dxy< 0.5mm   //   Endcap region dz<2mm & dxy< 0.5mm 
        # cut-based ID Fall17 V2 the recomended one from POG for the FullRunII
        sorted_electrons = op.sort(t.Electron, lambda ele : -ele.pt)
        electrons = op.select(sorted_electrons, lambda ele : op.AND(ele.pt > 15., op.abs(ele.eta) < 2.5 , ele.cutBased>=3, op.abs(ele.sip3d)< 4., op.OR(op.AND(op.abs(ele.dxy) < 0.05, op.abs(ele.dz) < 0.1), op.AND(op.abs(ele.dxy) < 0.05, op.abs(ele.dz) < 0.2) ))) 

        elMediumIDSF = get_scalefactor("lepton", ("electron_{0}_{1}".format(era,sfTag), "id_medium"), systName="elid")
        doubleEleTrigSF = get_scalefactor("dilepton", ("doubleEleLeg_HHMoriond17_2016"), systName="eleltrig")     

        elemuTrigSF = get_scalefactor("dilepton", ("elemuLeg_HHMoriond17_2016"), systName="elmutrig")
        mueleTrigSF = get_scalefactor("dilepton", ("mueleLeg_HHMoriond17_2016"), systName="mueltrig")
        

        MET = t.MET if era != "2017" else t.METFixEE2017
        corrMET=METcorrection(MET,t.PV,sample,era,self.isMC(sample))
        
        
        #######  select jets  
        ##################################
        #// 2016 - 2017 - 2018   ( j.jetId &2) ->      tight jet ID
        # For 2017 data, there is the option of "Tight" or "TightLepVeto", depending on how much you want to veto jets that overlap with/are faked by leptons
        sorted_AK4jets=op.sort(t.Jet, lambda j : -j.pt)
        AK4jetsSel = op.select(sorted_AK4jets, lambda j : op.AND(j.pt > 20., op.abs(j.eta)< 2.4, (j.jetId &2)))#   j.jetId == 6))# oldcut: (j.jetId &2)))        
        # exclude from the jetsSel any jet that happens to include within its reconstruction cone a muon or an electron.
        AK4jets= op.select(AK4jetsSel, lambda j : op.AND(op.NOT(op.rng_any(electrons, lambda ele : op.deltaR(j.p4, ele.p4) < 0.3 )), op.NOT(op.rng_any(muons, lambda mu : op.deltaR(j.p4, mu.p4) < 0.3 ))))
        
        # order jets by *decreasing* deepFlavour
        cleaned_AK4JetsByDeepFlav = op.sort(AK4jets, lambda j: -j.btagDeepFlavB)
        cleaned_AK4JetsByDeepB = op.sort(AK4jets, lambda j: -j.btagDeepB)

        # Boosted Region
        sorted_AK8jets=op.sort(t.FatJet, lambda j : -j.pt)
        AK8jetsSel = op.select(sorted_AK8jets, lambda j : op.AND(j.pt > 200., op.abs(j.eta)< 2.4, (j.jetId &2), j.subJet1._idx.result != -1, j.subJet2._idx.result != -1))

        AK8jets= op.select(AK8jetsSel, lambda j : op.AND(op.NOT(op.rng_any(electrons, lambda ele : op.deltaR(j.p4, ele.p4) < 0.3 )), op.NOT(op.rng_any(muons, lambda mu : op.deltaR(j.p4, mu.p4) < 0.3 ))))
        
        cleaned_AK8JetsByDeepB = op.sort(AK8jets, lambda j: -j.btagDeepB)
        
        # Now,  let's ask for the jets to be a b-jets 
        # DeepCSV or deepJet Medium b-tag working point
        btagging = {
                "DeepCSV":{ # era: (loose, medium, tight)
                            "2016":(0.2217, 0.6321, 0.8953), 
                            "2017":(0.1522, 0.4941, 0.8001), 
                            "2018":(0.1241, 0.4184, 0.7527) 
                          },
                "DeepFlavour":{
                            "2016":(0.0614, 0.3093, 0.7221), 
                            "2017":(0.0521, 0.3033, 0.7489), 
                            "2018":(0.0494, 0.2770, 0.7264) 
                          }
                   }
        
        # bjets ={ "DeepFlavour": {"L": jets pass loose  , "M":  jets pass medium  , "T":jets pass tight    }     
        #           "DeepCSV":    {"L":    ---           , "M":         ---        , "T":   ----            }
        #        }
        # FIXME 
        bjets_boosted = {}
        bjets_resolved = {}
        
        #WorkingPoints = ["L", "M", "T"]
        WorkingPoints = ["M"]
        for tagger  in btagging.keys():
            
            bJets_AK4_deepflavour ={}
            bJets_AK4_deepcsv ={}
            bJets_AK8_deepcsv ={}
            # FIXME idx is not propagated properly when i pass only one or two wp !! 
            for wp in sorted(WorkingPoints):
                
                suffix = ("loose" if wp=='L' else ("medium" if wp=='M' else "tight"))
                idx = ( 0 if wp=="L" else ( 1 if wp=="M" else 2))
                if tagger=="DeepFlavour":
                    
                    print ("Btagging: Era= {0}, Tagger={1}, Pass_{2}_working_point={3}".format(era, tagger, suffix, btagging[tagger][era][idx] ))
                    print ("***********************************************", idx, wp)
                    print ("btag_{0}_94X".format(era).replace("94X", "102X" if era=="2018" else "94X"), "{0}_{1}".format('DeepJet', suffix))
                    
                    bJets_AK4_deepflavour[wp] = op.select(cleaned_AK4JetsByDeepFlav, lambda j : j.btagDeepFlavB >= btagging[tagger][era][idx] )
                    Jet_DeepFlavourBDisc = { "BTagDiscri": lambda j : j.btagDeepFlavB }
                    deepBFlavScaleFactor = get_scalefactor("jet", ("btag_{0}_94X".format(era).replace("94X", "102X" if era=="2018" else "94X"), "{0}_{1}".format('DeepJet', suffix)),
                                                        additionalVariables=Jet_DeepFlavourBDisc, 
                                                        getFlavour=(lambda j : j.hadronFlavour),
                                                        systName="btagging{0}".format(era))  
                    
                    bjets_resolved[tagger]=bJets_AK4_deepflavour
                    
                else:
                    print ("Btagging: Era= {0}, Tagger={1}, Pass_{2}_working_point={3}".format(era, tagger, suffix, btagging[tagger][era][idx] ))
                    print ("***********************************************", idx, wp)
                    print ("btag_{0}_94X".format(era).replace("94X", "102X" if era=="2018" else "94X"), "{0}_{1}".format('DeepCSV', suffix))
                    
                    bJets_AK4_deepcsv[wp] = op.select(cleaned_AK4JetsByDeepB, lambda j : j.btagDeepB >= btagging[tagger][era][idx] )   
                    bJets_AK8_deepcsv[wp] = op.select(cleaned_AK8JetsByDeepB, lambda j : op.AND(j.subJet1.btagDeepB >= btagging[tagger][era][idx] , j.subJet2.btagDeepB >= btagging[tagger][era][idx]))   
                    Jet_DeepCSVBDis = { "BTagDiscri": lambda j : j.btagDeepB }
                    subJet_DeepCSVBDis = { "BTagDiscri": lambda j : op.AND(j.subJet1.btagDeepB, j.subJet2.btagDeepB) }
                    
                    # FIXME for boosted and resolved i will use # tagger need to pass jsons files to scale factors above ! 
                    deepB_AK4ScaleFactor = get_scalefactor("jet", ("btag_{0}_94X".format(era).replace("94X", "102X" if era=="2018" else "94X"), "{0}_{1}".format('DeepCSV', suffix)), 
                                                additionalVariables=Jet_DeepCSVBDis,
                                                getFlavour=(lambda j : j.hadronFlavour),
                                                systName="btagging{0}".format(era))  
                    # FIXME
                    #deepB_AK8ScaleFactor = get_scalefactor("jet", ("btag_{0}_94X".format(era).replace("94X", "102X" if era=="2018" else "94X"), "subjet_{0}_{1}".format('DeepCSV', suffix)), 
                                                #additionalVariables=Jet_DeepCSVBDis,
                                                #getFlavour=(lambda j : j.subJet1.hadronFlavour),
                                                #systName="btagging{0}".format(era))  
                    
                    bjets_resolved[tagger]=bJets_AK4_deepcsv
                    bjets_boosted[tagger]=bJets_AK8_deepcsv
        
        bestDeepFlavourPair={}
        bestDeepCSVPair={}
        bestJetPairs= {}
        bjets = {}
        # For the Resolved only 
        class GetBestJetPair(object):
            JetsPair={}
            def __init__(self, JetsPair, tagger, wp):
                def ReturnHighestDiscriminatorJet(tagger, wp):
                    if tagger=="DeepCSV":
                        return op.sort(safeget(bjets_resolved, tagger, wp), lambda j: - j.btagDeepB)
                    elif tagger=="DeepFlavour":
                        return op.sort(safeget(bjets_resolved, tagger, wp), lambda j: - j.btagDeepFlavB)
                    else:
                        raise RuntimeError("Something went wrong in returning {0} discriminator !".format(tagger))
               
                firstBest=ReturnHighestDiscriminatorJet(tagger, wp)[0]
                JetsPair[0]=firstBest
                secondBest=ReturnHighestDiscriminatorJet(tagger, wp)[1]
                JetsPair[1]=secondBest
        #  bestJetPairs= { "DeepFlavour": bestDeepFlavourPair,
        #                  "DeepCSV":     bestDeepCSVPair    
        #                }
        
        #######  Zmass reconstruction : Opposite Sign , Same Flavour leptons
        ########################################################
        # supress quaronika resonances and jets misidentified as leptons
        LowMass_cut = lambda dilep: op.invariant_mass(dilep[0].p4, dilep[1].p4)>12.
        ## Dilepton selection: opposite sign leptons in range 70.<mll<120. GeV 
        osdilep_Z = lambda l1,l2 : op.AND(l1.charge != l2.charge, op.in_range(70., op.invariant_mass(l1.p4, l2.p4), 120.))

        osLLRng = {
                "MuMu" : op.combine(muons, N=2, pred= osdilep_Z),
                "ElEl" : op.combine(electrons, N=2, pred=osdilep_Z),
                #"ElMu" : op.combine((electrons, muons), pred=lambda ele,mu : op.AND(osdilep_Z(ele,mu), ele.pt > mu.pt )),
                #"MuEl" : op.combine((muons, electrons), pred=lambda mu,ele : op.AND(osdilep_Z(mu,ele), mu.pt > ele.pt))
                }

        hasOSLL_cmbRng = lambda cmbRng : op.AND(op.rng_len(cmbRng) > 0, cmbRng[0][0].pt > 25.) # TODO The leading pT for the µµ channel should be above 20 Gev !

        
        ## helper selection (OR) to make sure jet calculations are only done once
        hasOSLL = noSel.refine("hasOSLL", cut=op.OR(*( hasOSLL_cmbRng(rng) for rng in osLLRng.values())))
        forceDefine(t._Jet.calcProd, hasOSLL)
        forceDefine(getattr(t, "_{0}".format("MET" if era != "2017" else "METFixEE2017")).calcProd, hasOSLL)
        
        llSFs = {
            "MuMu" : (lambda ll : [ muMediumIDSF(ll[0]), muMediumIDSF(ll[1]), muMediumISOSF(ll[0]), muMediumISOSF(ll[1]), doubleMuTrigSF(ll) ]),
            "ElMu" : (lambda ll : [ elMediumIDSF(ll[0]), muMediumIDSF(ll[1]), muMediumISOSF(ll[1]), elemuTrigSF(ll) ]),
            "MuEl" : (lambda ll : [ muMediumIDSF(ll[0]), muMediumISOSF(ll[0]), elMediumIDSF(ll[1]), mueleTrigSF(ll) ]),
            "ElEl" : (lambda ll : [ elMediumIDSF(ll[0]), elMediumIDSF(ll[1]), doubleEleTrigSF(ll) ])
            }
        
        categories = dict((channel, (catLLRng[0], hasOSLL.refine("hasOS{0}".format(channel), cut=hasOSLL_cmbRng(catLLRng), weight=(llSFs[channel](catLLRng[0]) if isMC else None)) )) for channel, catLLRng in osLLRng.items())

        ## btagging efficiencies plots
        #plots.extend(MakeBtagEfficienciesPlots(self, jets, bjets, categories))
        
        for channel, (dilepton, catSel) in categories.items():
            #----  Zmass (2Lepton OS && SF ) --------
            #plots.extend(MakeControlPlotsForZpic(self, catSel, dilepton, channel))
            
            #----  add Jets selection 
            TwoLeptonsTwoJets_Resolved = catSel.refine("TwoJet_{0}Sel_resolved".format(channel), cut=[ op.rng_len(AK4jets) > 1 ])
            TwoLeptonsTwoJets_Boosted = catSel.refine("OneJet_{0}Sel_boosted".format(channel), cut=[ op.rng_len(AK8jets) > 0 ])
            #plots.extend(makeJetPlots(self, TwoLeptonsTwoJets_Resolved, AK4jets, channel))
            #plots.extend(makeBoostedJetPLots(self, TwoLeptonsTwoJets_Boosted, AK8jets, channel))
            
            # ----- plots : mll, mlljj, mjj, nVX, pT, eta  : basic selection plots ------
            #plots.extend(MakeControlPlotsForBasicSel(self, TwoLeptonsTwoJets_Resolved, AK4jets, dilepton, channel))
            #plots.extend(MakeControlPlotsForBasicSel(self, TwoLeptonsTwoJets_boosted, AK8jets, dilepton, channel))

            
            for wp in WorkingPoints: 
                # Get the best AK4 JETS 
                GetBestJetPair(bestDeepCSVPair,"DeepCSV", wp)
                GetBestJetPair(bestDeepFlavourPair,"DeepFlavour", wp)
                bestJetPairs["DeepCSV"]=bestDeepCSVPair
                bestJetPairs["DeepFlavour"]=bestDeepFlavourPair
                print ("bestJetPairs AK4--->", bestJetPairs, wp)
                print ("bestJetPairs_deepcsv  AK4--->", bestJetPairs["DeepCSV"][0], bestJetPairs["DeepCSV"][1], wp)
                print ("bestJetPairs_deepflavour  AK4 --->", bestJetPairs["DeepFlavour"][0],bestJetPairs["DeepFlavour"][1], wp)
                # resolved 
                bJets_resolved_PassdeepflavourWP=safeget(bjets_resolved, "DeepFlavour", wp)
                bJets_resolved_PassdeepcsvWP=safeget(bjets_resolved, "DeepCSV", wp)
                # boosted
                bJets_boosted_PassdeepcsvWP=safeget(bjets_boosted, "DeepCSV", wp)

                TwoLeptonsTwoBjets_NoMETCut_Res = {
                    "DeepFlavour{0}".format(wp) :  TwoLeptonsTwoJets_Resolved.refine("TwoLeptonsTwoBjets_NoMETcut_DeepFlavour{0}_{1}_Resolved".format(wp, channel),
                                                                        cut=[ op.rng_len(bJets_resolved_PassdeepflavourWP) > 1 ],
                                                                        weight=([ deepBFlavScaleFactor(bJets_resolved_PassdeepflavourWP[0]), deepBFlavScaleFactor(bJets_resolved_PassdeepflavourWP[1]) ]if isMC else None)),
                    "DeepCSV{0}".format(wp)     :  TwoLeptonsTwoJets_Resolved.refine("TwoLeptonsTwoBjets_NoMETcut_DeepCSV{0}_{1}_Resolved".format(wp, channel), 
                                                                        cut=[ op.rng_len(bJets_resolved_PassdeepcsvWP) > 1 ],
                                                                        weight=([ deepB_AK4ScaleFactor(bJets_resolved_PassdeepcsvWP[0]), deepB_AK4ScaleFactor(bJets_resolved_PassdeepcsvWP[1]) ]if isMC else None))
                                                }


                TwoLeptonsTwoBjets_NoMETCut_Boo = {
                    "DeepCSV{0}".format(wp)     :  TwoLeptonsTwoJets_Boosted.refine("TwoLeptonsTwoBjets_NoMETcut_DeepCSV{0}_{1}_Boosted".format(wp, channel), 
                                                                        cut=[ op.rng_len(bJets_boosted_PassdeepcsvWP) > 1 ]), 
                                                                        # FIXME ! can't pass boosted jets SFs with current version ---> move to v7  
                                                                        #weight=([ deepB_AK8ScaleFactor(bJets_boosted_PassdeepcsvWP[0]), deepB_AK8ScaleFactor(bJets_boosted_PassdeepcsvWP[1]) ]if isMC else None))
                                                }
                
                ## needed to optimize the MET cut 
                # FIXME  Rerun again  &&& pass signal and bkg  
                # The MET cut is passed to TwoLeptonsTwoBjets selection for the # tagger and for the # wp 
                plots.extend(MakeMETPlots(self, TwoLeptonsTwoBjets_NoMETCut_Res, corrMET, MET, channel, "resolved"))
                plots.extend(MakeMETPlots(self, TwoLeptonsTwoBjets_NoMETCut_Boo, corrMET, MET, channel, "boosted"))
                plots.extend(MakeExtraMETPlots(self, TwoLeptonsTwoBjets_NoMETCut_Res, dilepton, MET, channel, "resolved"))
                plots.extend(MakeExtraMETPlots(self, TwoLeptonsTwoBjets_NoMETCut_Boo, dilepton, MET, channel, "boosted"))

                TwoLeptonsTwoBjets_Res = dict((key, selNoMET.refine("TwoLeptonsTwoBjets_{0}_{1}_Resolved".format(key, channel), cut=[ corrMET.pt < 80. ])) for key, selNoMET in TwoLeptonsTwoBjets_NoMETCut_Res.items())
                TwoLeptonsTwoBjets_Boo = dict((key, selNoMET.refine("TwoLeptonsTwoBjets_{0}_{1}_Boosted".format(key, channel), cut=[ corrMET.pt < 80. ])) for key, selNoMET in TwoLeptonsTwoBjets_NoMETCut_Boo.items())
                #plots.extend(MakeDiscriminatorPlots(self, TwoLeptonsTwoBjets_Res, bjets_resolved, wp, channel, "resolved"))
                #plots.extend(MakeDiscriminatorPlots(self, TwoLeptonsTwoBjets_Boo, bjets_boosted, wp, channel, "boosted"))
                
                #plots.extend(makeResolvedBJetPlots(self, TwoLeptonsTwoBjets_Res, bjets_resolved, dilepton, wp, channel))
                #plots.extend(makeBoostedBJetPlots(self, TwoLeptonsTwoBjets_NoMETCut_Boo, bjets_boosted, dilepton, wp, channel))

                # --- to get the Ellipses plots  
                plots.extend(MakeEllipsesPLots(self, TwoLeptonsTwoBjets_Res, bjets_resolved, dilepton, wp, channel, "resolved"))
                plots.extend(MakeEllipsesPLots(self, TwoLeptonsTwoBjets_Boo, bjets_boosted, dilepton, wp, channel, "boosted"))
        
        return plots
예제 #20
0
    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
예제 #21
0
    def definePlots(self, t, noSel, sample=None, sampleCfg=None):
        noSel = super(TransferFunction,
                      self).prepareObjects(t, noSel, sample, sampleCfg, 'DL')
        noSel = self.beforeJetselection(noSel)
        era = sampleCfg['era']
        plots = []

        if not self.is_MC:
            return plots

        lambda_is_matched = lambda lep: op.OR(
            lep.genPartFlav == 1,  # Prompt muon or electron
            lep.genPartFlav == 15)  # From tau decay
        #lep.genPartFlav==22) # From photon conversion (only available for electrons)

        plots.append(
            Plot.make1D("totalWeight",
                        noSel.weight,
                        noSel,
                        EquidistantBinning(100, -int(10**5), int(10**5)),
                        xTitle="total weight"))
        plots.append(
            Plot.make1D("genWeight",
                        t.genWeight,
                        noSel,
                        EquidistantBinning(100, -int(10**5), int(10**5)),
                        xTitle="gen weight"))

        ##########################################################
        #                       Leptons                          #
        ##########################################################
        #----- Gen particles -----#
        gen_e = op.select(
            t.GenPart, lambda g: op.AND(
                op.abs(g.pdgId) == 11, g.statusFlags & (0x1 << 13), g.pt >= 10,
                op.abs(g.eta) < 2.5))
        gen_m = op.select(
            t.GenPart, lambda g: op.AND(
                op.abs(g.pdgId) == 13, g.statusFlags & (0x1 << 13), g.pt >= 10,
                op.abs(g.eta) < 2.4))

        #----- Reco particles -----#
        lambda_reco_e = lambda el: op.AND(
            op.abs(el.pdgId) == 11, el.pt >= 10,
            op.abs(el.eta) < 2.5, lambda_is_matched(el))
        lambda_reco_m = lambda mu: op.AND(
            op.abs(mu.pdgId) == 13, mu.pt >= 10,
            op.abs(mu.eta) < 2.4, lambda_is_matched(mu))

        reco_e = op.select(self.electronsFakeSel, lambda_reco_e)
        reco_m = op.select(self.muonsFakeSel, lambda_reco_m)

        #---- Matching -----#
        lambda_lepton_match = lambda gen, reco: op.AND(
            op.deltaR(gen.p4, reco.p4) < 0.1, (op.abs(gen.pt - reco.pt) /
                                               (gen.pt + reco.pt)) < 0.2)

        #        reco_e_matched = op.select(reco_e, lambda re : op.rng_any(gen_e, lambda ge: lambda_lepton_match(ge,re)))
        #        reco_m_matched = op.select(reco_m, lambda rm : op.rng_any(gen_m, lambda gm: lambda_lepton_match(gm,rm)))

        #match_e = op.combine((gen_e,reco_e), pred = lambda ge,re : re.idx == op.rng_min_element_by(reco_e_matched,lambda re_matched : op.deltaR(ge.p4,re_matched.p4)).idx)
        #match_m = op.combine((gen_m,reco_m), pred = lambda gm,rm : rm.idx == op.rng_min_element_by(reco_m_matched,lambda rm_matched : op.deltaR(gm.p4,rm_matched.p4)).idx)

        match_e = op.combine((gen_e, reco_e), pred=lambda_lepton_match)
        match_m = op.combine((gen_m, reco_m), pred=lambda_lepton_match)

        plots.extend(plotMatching("e", match_e, noSel, "e^{#pm}"))
        plots.extend(plotMatching("m", match_m, noSel, "#mu^{#pm}"))

        #        plots.append(plotRecoForGen(noSel,gen_e,tight_e,lambda_lepton_match,"e_tight"))
        #        plots.append(plotRecoForGen(noSel,gen_e,tight_m,lambda_lepton_match,"m_tight"))

        ##########################################################
        #                       Ak4 B jets                       #
        ##########################################################
        #----- RecoJets -----#
        recoJet_b = op.select(
            t.Jet, lambda j: op.AND(
                op.abs(j.partonFlavour) == 5, j.pt >= 20,
                op.abs(j.eta) < 2.4, j.genJet.isValid))
        #----- Parton -----#
        gen_b = op.select(
            t.GenPart, lambda g: op.AND(
                op.abs(g.pdgId) == 5, g.statusFlags & (0x1 << 13), g.pt >= 20,
                op.abs(g.eta) < 2.4))
        #----- Matching -----#
        lambda_jet_match = lambda gen, reco: op.AND(
            op.deltaR(gen.p4, reco.p4) < 0.2)
        reco_b_matched = op.select(
            recoJet_b, lambda jetb: op.rng_any(
                gen_b, lambda gb: lambda_jet_match(gb, jetb)))
        match_b = op.combine(
            (gen_b, recoJet_b),
            pred=lambda gb, jetb: jetb.idx == op.rng_min_element_by(
                reco_b_matched, lambda rb_matched: op.deltaR(
                    gb.p4, rb_matched.p4)).idx)
        plots.extend(plotMatching("ak4b", match_b, noSel, "b"))

        ##########################################################
        #                       Ak4 C jets                       #
        ##########################################################
        #----- RecoJets -----#
        recoJet_c = op.select(
            t.Jet, lambda j: op.AND(
                op.abs(j.partonFlavour) == 4, j.pt >= 20,
                op.abs(j.eta) < 2.4, j.genJet.isValid))
        #----- Parton -----#
        gen_c = op.select(
            t.GenPart, lambda g: op.AND(
                op.abs(g.pdgId) == 4, g.statusFlags & (0x1 << 13), g.pt >= 20,
                op.abs(g.eta) < 2.4))
        #----- Matching -----#
        reco_c_matched = op.select(
            recoJet_c, lambda jetc: op.rng_any(
                gen_c, lambda gc: lambda_jet_match(gc, jetc)))
        match_c = op.combine(
            (gen_c, recoJet_c),
            pred=lambda gc, jetc: jetc.idx == op.rng_min_element_by(
                reco_c_matched, lambda rc_matched: op.deltaR(
                    gc.p4, rc_matched.p4)).idx)
        plots.extend(plotMatching("ak4c", match_c, noSel, "c"))

        ##########################################################
        #                     Ak4 lightjets                      #
        ##########################################################
        #----- RecoJets -----#
        recoJet_l = op.select(
            t.Jet, lambda j: op.AND(
                op.OR(
                    op.abs(j.partonFlavour) == 1,
                    op.abs(j.partonFlavour) == 2,
                    op.abs(j.partonFlavour) == 3), j.pt >= 20,
                op.abs(j.eta) < 2.4, j.genJet.isValid))
        #----- Parton -----#
        gen_l = op.select(
            t.GenPart, lambda g: op.AND(
                op.OR(
                    op.abs(g.pdgId) == 1,
                    op.abs(g.pdgId) == 2,
                    op.abs(g.pdgId) == 3), g.statusFlags &
                (0x1 << 13), g.pt >= 20,
                op.abs(g.eta) < 2.4))
        #----- Matching -----#
        reco_l_matched = op.select(
            recoJet_l, lambda jetl: op.rng_any(
                gen_l, lambda gl: lambda_jet_match(gl, jetl)))
        match_l = op.combine(
            (gen_l, recoJet_l),
            pred=lambda gl, jetl: jetl.idx == op.rng_min_element_by(
                reco_l_matched, lambda rl_matched: op.deltaR(
                    gl.p4, rl_matched.p4)).idx)
        plots.extend(plotMatching("ak4l", match_l, noSel, "l"))

        ##########################################################
        #                        Ak8 jets                        #
        ##########################################################
        #----- RecoJets -----#
        recoFatJet = op.select(
            t.FatJet, lambda j: op.AND(
                j.pt >= 100,
                op.abs(j.eta) < 2.4,
                op.AND(j.subJet1.isValid, j.subJet1.pt >= 20.,
                       op.abs(j.subJet1.eta) <= 2.4, j.subJet2.isValid, j.
                       subJet2.pt >= 20.,
                       op.abs(j.subJet2.eta) <= 2.4),
                op.AND(j.msoftdrop >= 30, j.msoftdrop <= 210), j.tau2 / j.tau1
                <= 0.75))

        #plots.extend(fatjetPlots(noSel,recoFatJet,"fatjet"))

        reco_subJet1_b_matched = op.select(
            recoFatJet, lambda fat: op.rng_any(
                gen_b, lambda gb: lambda_jet_match(gb, fat.subJet1)))
        reco_subJet2_b_matched = op.select(
            recoFatJet, lambda fat: op.rng_any(
                gen_b, lambda gb: lambda_jet_match(gb, fat.subJet2)))
        reco_subJet1_c_matched = op.select(
            recoFatJet, lambda fat: op.rng_any(
                gen_c, lambda gc: lambda_jet_match(gc, fat.subJet1)))
        reco_subJet2_c_matched = op.select(
            recoFatJet, lambda fat: op.rng_any(
                gen_c, lambda gc: lambda_jet_match(gc, fat.subJet2)))
        reco_subJet1_l_matched = op.select(
            recoFatJet, lambda fat: op.rng_any(
                gen_l, lambda gl: lambda_jet_match(gl, fat.subJet1)))
        reco_subJet2_l_matched = op.select(
            recoFatJet, lambda fat: op.rng_any(
                gen_l, lambda gl: lambda_jet_match(gl, fat.subJet2)))

        def makeFatjetMatch(gen1, gen2, recoFatJet):
            return op.combine(
                (gen1, gen2, recoFatJet),
                pred=lambda g1, g2, fat: op.AND(
                    fat.subJet1.idx == op.rng_min_element_by(
                        reco_subJet1_b_matched, lambda sub1_matched: op.deltaR(
                            g1.p4, sub1_matched.p4)).idx, fat.subJet2.idx == op
                    .rng_min_element_by(
                        reco_subJet2_b_matched, lambda sub2_matched: op.deltaR(
                            g2.p4, sub2_matched.p4)).idx))

        match_fat_bb = makeFatjetMatch(gen_b, gen_b, recoFatJet)
        match_fat_bc = makeFatjetMatch(gen_b, gen_c, recoFatJet)
        match_fat_bl = makeFatjetMatch(gen_b, gen_l, recoFatJet)
        match_fat_cb = makeFatjetMatch(gen_c, gen_b, recoFatJet)
        match_fat_cc = makeFatjetMatch(gen_c, gen_c, recoFatJet)
        match_fat_cl = makeFatjetMatch(gen_c, gen_l, recoFatJet)
        match_fat_lb = makeFatjetMatch(gen_l, gen_b, recoFatJet)
        match_fat_lc = makeFatjetMatch(gen_l, gen_c, recoFatJet)
        match_fat_ll = makeFatjetMatch(gen_l, gen_l, recoFatJet)
        #        match_fat_bb = op.combine((gen_b,gen_b,recoFatJet), pred = lambda g1,g2,fat : op.AND(
        #                                                fat.subJet1.idx == op.rng_min_element_by(reco_subJet1_b_matched,
        #                                                                                         lambda sub1_matched : op.deltaR(gb1.p4,sub1_matched.p4)).idx,
        #                                                fat.subJet2.idx == op.rng_min_element_by(reco_subJet2_b_matched,
        #                                                                                         lambda sub2_matched : op.deltaR(gb2.p4,sub2_matched.p4)).idx))
        #        match_fat_bc = op.combine((gen_b,gen_b,recoFatJet), pred = lambda gb1,gb2,fat : op.AND(
        #                                                fat.subJet1.idx == op.rng_min_element_by(reco_subJet1_b_matched,
        #                                                                                         lambda sub1_matched : op.deltaR(gb1.p4,sub1_matched.p4)).idx,
        #                                                fat.subJet2.idx == op.rng_min_element_by(reco_subJet2_b_matched,
        #                                                                                         lambda sub2_matched : op.deltaR(gb2.p4,sub2_matched.p4)).idx))

        plots.extend(plotFatjetMatching(match_fat_bb, noSel, 'b', 'b'))
        plots.extend(plotFatjetMatching(match_fat_bc, noSel, 'b', 'c'))
        plots.extend(plotFatjetMatching(match_fat_bl, noSel, 'b', 'l'))
        plots.extend(plotFatjetMatching(match_fat_cb, noSel, 'c', 'b'))
        plots.extend(plotFatjetMatching(match_fat_cc, noSel, 'c', 'c'))
        plots.extend(plotFatjetMatching(match_fat_cl, noSel, 'c', 'l'))
        plots.extend(plotFatjetMatching(match_fat_bb, noSel, 'l', 'b'))
        plots.extend(plotFatjetMatching(match_fat_bc, noSel, 'l', 'c'))
        plots.extend(plotFatjetMatching(match_fat_bl, noSel, 'l', 'l'))

        return plots
예제 #22
0
    def definePlots(self, t, noSel, sample=None, sampleCfg=None):
        era = sampleCfg['era']
        plots = []

        ##########################################################
        #                       Leptons                          #
        ##########################################################
        #----- Gen particles -----#
        gen_e_minus = op.select(
            t.GenPart, lambda g: op.AND(g.pdgId == 11, g.statusFlags &
                                        (0x1 << 13), g.pt > 10,
                                        op.abs(g.eta) < 2.5))
        gen_e_plus = op.select(
            t.GenPart, lambda g: op.AND(g.pdgId == -11, g.statusFlags &
                                        (0x1 << 13), g.pt > 10,
                                        op.abs(g.eta) < 2.5))
        gen_mu_minus = op.select(
            t.GenPart, lambda g: op.AND(g.pdgId == 13, g.statusFlags &
                                        (0x1 << 13), g.pt > 10,
                                        op.abs(g.eta) < 2.4))
        gen_mu_plus = op.select(
            t.GenPart, lambda g: op.AND(g.pdgId == -13, g.statusFlags &
                                        (0x1 << 13), g.pt > 10,
                                        op.abs(g.eta) < 2.4))

        plots.extend(
            plotNumber("N_e_minus_gen", gen_e_minus, noSel, 10,
                       "N(e^{-}) gen level"))
        plots.extend(
            plotNumber("N_e_plus_gen", gen_e_plus, noSel, 10,
                       "N(e^{+}) gen level"))
        plots.extend(
            plotNumber("N_mu_minus_gen", gen_mu_minus, noSel, 10,
                       "N(\mu^{-}) gen level"))
        plots.extend(
            plotNumber("N_mu_plus_gen", gen_mu_plus, noSel, 10,
                       "N(\mu^{+}) gen level"))

        #----- Reco particles -----#
        reco_e_minus = op.select(
            t.Electron, lambda ele: op.AND(
                ele.charge == -1, ele.pdgId == 11, ele.pt > 10,
                op.abs(ele.eta) < 2.5,
                op.OR(ele.genPartFlav == 1, ele.genPartFlav == 15, ele.
                      genPartFlav == 22)))
        reco_e_plus = op.select(
            t.Electron, lambda ele: op.AND(
                ele.charge == +1, ele.pdgId == -11, ele.pt > 10,
                op.abs(ele.eta) < 2.5,
                op.OR(ele.genPartFlav == 1, ele.genPartFlav == 15, ele.
                      genPartFlav == 22)))
        reco_mu_minus = op.select(
            t.Muon, lambda mu: op.AND(
                mu.charge == -1, mu.pdgId == 13, mu.pt > 10,
                op.abs(mu.eta) < 2.4,
                op.OR(mu.genPartFlav == 1, mu.genPartFlav == 15)))
        reco_mu_plus = op.select(
            t.Muon, lambda mu: op.AND(
                mu.charge == +1, mu.pdgId == -13, mu.pt > 10,
                op.abs(mu.eta) < 2.4,
                op.OR(mu.genPartFlav == 1, mu.genPartFlav == 15)))

        plots.extend(
            plotNumber("N_e_minus_reco", reco_e_minus, noSel, 10,
                       "N(e^{-}) reco level"))
        plots.extend(
            plotNumber("N_e_plus_reco", reco_e_plus, noSel, 10,
                       "N(e^{+}) reco level"))
        plots.extend(
            plotNumber("N_mu_minus_reco", reco_mu_minus, noSel, 10,
                       "N(\mu^{-}) reco level"))
        plots.extend(
            plotNumber("N_mu_plus_reco", reco_mu_plus, noSel, 10,
                       "N(\mu^{+}) reco level"))

        #---- Matching -----#
        lambda_lepton_match = lambda l_gen, l_reco: op.AND(
            op.deltaR(l_gen.p4, l_reco.p4) < 0.1,
            op.abs(l_gen.pt - l_reco.pt) / l_gen.pt < 0.2)

        match_e_minus = op.combine((gen_e_minus, reco_e_minus),
                                   pred=lambda_lepton_match)
        match_e_plus = op.combine((gen_e_plus, reco_e_plus),
                                  pred=lambda_lepton_match)
        match_mu_minus = op.combine((gen_mu_minus, reco_mu_minus),
                                    pred=lambda_lepton_match)
        match_mu_plus = op.combine((gen_mu_plus, reco_mu_plus),
                                   pred=lambda_lepton_match)

        SelEMinusMatch = noSel.refine("SelEMinusMatch",
                                      cut=[op.rng_len(match_e_minus) >= 1])
        SelEPlusMatch = noSel.refine("SelEPlusMatch",
                                     cut=[op.rng_len(match_e_plus) >= 1])
        SelMuMinusMatch = noSel.refine("SelMuMinusMatch",
                                       cut=[op.rng_len(match_mu_minus) >= 1])
        SelMuPlusMatch = noSel.refine("SelMuPlusMatch",
                                      cut=[op.rng_len(match_mu_plus) >= 1])

        plots.extend(
            plotNumber("N_e_minus_match", match_e_minus, noSel, 10,
                       "N(e^{-}) match level"))
        plots.extend(
            plotNumber("N_e_plus_match", match_e_plus, noSel, 10,
                       "N(e^{+}) match level"))
        plots.extend(
            plotNumber("N_mu_minus_match", match_mu_minus, noSel, 10,
                       "N(\mu^{-}) match level"))
        plots.extend(
            plotNumber("N_mu_plus_match", match_mu_plus, noSel, 10,
                       "N(\mu^{+}) match level"))

        plots.extend(
            plotMatching("e", [match_e_minus, match_e_plus],
                         [SelEMinusMatch, SelEPlusMatch], "e^{#pm}"))
        plots.extend(
            plotMatching("mu", [match_mu_minus, match_mu_plus],
                         [SelMuMinusMatch, SelMuPlusMatch], "#mu^{#pm}"))

        ##########################################################
        #                       B jets                           #
        ##########################################################
        #----- RecoJets -----#
        #recoJet_b = op.select(t.Jet, lambda j : op.AND(j.partonFlavour == 5, j.pt>10, op.abs(j.eta)<2.4 ,(op.abs(j.pt-j.genJet.pt)/j.genJet.pt)<1 ))
        #recoJet_bbar = op.select(t.Jet, lambda j : op.AND(j.partonFlavour == -5, j.pt>10, op.abs(j.eta)<2.4 ,(op.abs(j.pt-j.genJet.pt)/j.genJet.pt)<1  ))
        recoJet_b = op.select(
            t.Jet, lambda j: op.AND(j.partonFlavour == 5, j.pt > 10,
                                    op.abs(j.eta) < 2.4, j.genJet.isValid))
        recoJet_bbar = op.select(
            t.Jet, lambda j: op.AND(j.partonFlavour == -5, j.pt > 10,
                                    op.abs(j.eta) < 2.4, j.genJet.isValid))
        plots.extend(
            plotNumber("N_jetb_reco", recoJet_b, noSel, 5, "N(b) reco jet"))
        plots.extend(
            plotNumber("N_jetbbar_reco", recoJet_bbar, noSel, 5,
                       "N(#bar{b}) reco jet"))

        SelBReco = noSel.refine("SelBReco", cut=[op.rng_len(recoJet_b) >= 1])
        SelBBarReco = noSel.refine("SelBBarReco",
                                   cut=[op.rng_len(recoJet_bbar) >= 1])

        #        plots.extend(plotJetReco("bjet",recoJet_b,SelBReco,"b jet"))
        #        plots.extend(plotJetReco("bbarjet",recoJet_bbar,SelBBarReco,"#bar{b} jet"))
        #
        #
        #       #----- Parton -----#
        #        gen_b = op.select(t.GenPart,lambda g : op.AND( g.pdgId==5 , g.statusFlags & ( 0x1 << 13) , g.pt>10, op.abs(g.eta)<2.4))
        #        gen_bbar = op.select(t.GenPart,lambda g : op.AND( g.pdgId==-5 , g.statusFlags & ( 0x1 << 13) , g.pt>10, op.abs(g.eta)<2.4))
        #        plots.extend(plotNumber("N_b_gen",gen_b,noSel,5,"N(b) gen quark"))
        #        plots.extend(plotNumber("N_bbar_gen",gen_bbar,noSel,5,"N(#bar{b}) gen quark"))
        #
        #        #----- Matching -----#
        #        lambda_bjet_match = lambda b_gen,b_jet : op.deltaR(b_gen.p4,b_jet.genJet.p4)<0.2
        #
        #        match_b = op.combine((gen_b,recoJet_b),pred=lambda_bjet_match)
        #        match_bbar = op.combine((gen_bbar,recoJet_bbar),pred=lambda_bjet_match)
        #
        #        plots.extend(plotNumber("N_b_match",match_b,noSel,5,"N(b) match level"))
        #        plots.extend(plotNumber("N_bbar_match",match_bbar,noSel,5,"N(#bar{b}) match level"))
        #
        #        SelBMatch = noSel.refine("SelBMatch",cut=[op.rng_len(match_b)>=1])
        #        SelBBarMatch = noSel.refine("SelBBarMatch",cut=[op.rng_len(match_bbar)>=1])
        #
        #        plots.extend(plotMatching("b",[match_b,match_bbar],[SelBMatch,SelBBarMatch],"b"))

        return plots
    def definePlots(self, t, noSel, sample=None, sampleCfg=None):
        from bamboo.plots import Plot, CutFlowReport
        from bamboo.plots import EquidistantBinning as EqB
        from bamboo import treefunctions as op

        plots = []

        #definitions

        electrons = op.select(t.elec, lambda el : op.AND(
        el.pt > 20., op.abs(el.eta) < 2.5
        ))
        
        muons = op.select(t.muon, lambda mu : op.AND(
        mu.pt > 20., op.abs(mu.eta) < 2.5
        ))
        
        cleanedElectrons = op.select(electrons, lambda el : op.NOT(
        op.rng_any(muons, lambda mu : op.deltaR(el.p4, mu.p4) < 0.3 )
        ))

        # we are taking the second isopass to be on which is equal to the medium working point
        isolatedElectrons = op.select(cleanedElectrons, lambda el : el.isopass & (1<<2) )
        
        identifiedElectrons = op.select(isolatedElectrons, lambda el : el.idpass & (1<<2) )
        
        cleanedMuons = op.select(muons, lambda mu : op.NOT(
        op.rng_any(electrons, lambda el : op.deltaR(mu.p4, el.p4) < 0.3 )
        ))
        
        isolatedMuons = op.select(cleanedMuons, lambda mu : mu.isopass & (1<<2) )
        
        identifiedMuons = op.select(isolatedMuons, lambda mu : mu.idpass & (1<<2) )
        
        InvMassMuMU = op.invariant_mass(identifiedMuons[0].p4, identifiedMuons[1].p4 )
        
        cleanedJets = op.select(t.jetpuppi, lambda j : op.AND(
        op.NOT(op.rng_any(identifiedElectrons, lambda el : op.deltaR(el.p4, j.p4) < 0.3) ),
        op.NOT(op.rng_any(identifiedMuons, lambda mu : op.deltaR(mu.p4, j.p4) < 0.3) )
        ))

        cleanedGoodJets = op.select(cleanedJets, lambda j : op.AND(
        j.pt > 30, op.abs(j.eta) < 2.5
        ))

        btaggedJets = op.select(cleanedGoodJets, lambda j : j.btag & (1<<2))

        met = op.select(t.metpuppi)

        #selections

        #selection1 : Oppositely charged MuMu selection
        sel1 = noSel.refine("nmumu", cut = [op.AND(
            (op.rng_len(identifiedMuons) > 1), (op.product(identifiedMuons[0].charge, identifiedMuons[1].charge) < 0 ))]) 

        #selection2 : Invariant mass selection
        sel2 = sel1.refine("InvM", cut = [op.NOT(op.in_range(76, InvMassMuMU, 106))])

        #selection3 : two jets selection
        sel3 = sel2.refine("njet", cut = [op.rng_len(cleanedGoodJets) > 1])
    
        #selection4 : at least 1 among two leading jets is b-tagged
        sel4 = sel3.refine("btag", cut = [op.OR(
            cleanedGoodJets[0].btag & (1<<2), cleanedGoodJets[1].btag & (1<<2))])

        #selection5 : MET > 40 GeV
        sel5 = sel4.refine("MET", cut = [met[0].pt > 40])

        #plots
            
            #noSel
        plots.append(Plot.make1D("nJetsNoSel", op.rng_len(cleanedGoodJets), noSel, EqB(10, 0., 10.), title="nJets"))

        plots.append(Plot.make1D("nbtaggedJetsNoSel", op.rng_len(btaggedJets), noSel, EqB(10, 0., 10.), title="nbtaggedJets"))
  
        plots.append(Plot.make1D("nMuNoSel", op.rng_len(identifiedMuons), noSel, EqB(15, 0., 15.), title="nMuons"))
        
        plots.append(Plot.make1D("METptNoSel", met[0].pt, noSel, EqB(50, 0., 250), title="MET_PT"))
        
            #sel1
        
        plots.append(Plot.make1D("nJetsSel1", op.rng_len(cleanedGoodJets), sel1, EqB(10, 0., 10.), title="nJets"))

        plots.append(Plot.make1D("nbtaggedJetsSel1", op.rng_len(btaggedJets), sel1, EqB(10, 0., 10.), title="nbtaggedJets"))

        plots.append(Plot.make1D("nMuSel1", op.rng_len(identifiedMuons), sel1, EqB(10, 0., 10.), title="nMuons"))

        plots.append(Plot.make1D("InvMassTwoMuonsSel1", InvMassMuMU, sel1, EqB(30, 0, 300), title="m(ll)"))
                  
        plots.append(Plot.make1D("LeadingMuonPTSel1", muons[0].pt, sel1, EqB(30, 0., 250.), title=" Leading Muon PT"))
            
        plots.append(Plot.make1D("SubLeadingMuonPTSel1", muons[1].pt, sel1, EqB(30, 0., 250.), title="SubLeading Muon PT"))

        plots.append(Plot.make1D("LeadingMuonEtaSel1", muons[0].eta, sel1, EqB(30, -3, 3), title=" Leading Muon eta"))
            
        plots.append(Plot.make1D("SubLeadingMuonEtaSel1", muons[1].eta, sel1, EqB(30, -3, 3), title="SubLeading Muon eta"))
        
        plots.append(Plot.make1D("METptSel1", met[0].pt, sel1, EqB(50, 0., 250), title="MET_PT"))
                            
            #sel2

        plots.append(Plot.make1D("nJetsSel2", op.rng_len(cleanedGoodJets), sel2, EqB(10, 0., 10.), title="nJets"))

        plots.append(Plot.make1D("nbtaggedJetsSel2", op.rng_len(btaggedJets), sel2, EqB(10, 0., 10.), title="nbtaggedJets"))

        plots.append(Plot.make1D("nMuSel2", op.rng_len(identifiedMuons), sel2, EqB(10, 0., 10.), title="nMuons"))

        plots.append(Plot.make1D("InvMassTwoMuonsSel2", InvMassMuMU, sel2, EqB(20, 20., 300.), title="m(ll)"))
        
        plots.append(Plot.make1D("LeadingMuonPTSel2", muons[0].pt, sel2, EqB(30, 0., 250.), title=" Leading Muon PT"))

        plots.append(Plot.make1D("SubLeadingMuonPTSel2", muons[1].pt, sel2, EqB(30, 0., 200.), title=" SubLeading Muon PT"))

        plots.append(Plot.make1D("LeadingMuonEtaSel2", muons[0].eta, sel2, EqB(30, -3, 3), title=" Leading Muon Eta"))
            
        plots.append(Plot.make1D("SubLeadingMuonEtaSel2", muons[1].eta, sel2, EqB(30, -3, 3), title=" SubLeading Muon Eta"))

        plots.append(Plot.make1D("METptSel2", met[0].pt, sel2, EqB(50, 0., 250), title="MET_PT"))
                        
            #sel3
            
        plots.append(Plot.make1D("nJetsSel3", op.rng_len(cleanedGoodJets), sel3, EqB(10, 0., 10.), title="nJets"))

        plots.append(Plot.make1D("nbtaggedJetsSel3", op.rng_len(btaggedJets), sel3, EqB(10, 0., 10.), title="nbtaggedJets"))

        plots.append(Plot.make1D("LeadingJetPTSel3", cleanedGoodJets[0].pt, sel3, EqB(50, 0., 350.), title="Leading jet PT"))
            
        plots.append(Plot.make1D("SubLeadingJetPTSel3", cleanedGoodJets[1].pt, sel3, EqB(50, 0., 350.), title="SubLeading jet PT"))
            
        plots.append(Plot.make1D("LeadingJetEtaSel3", cleanedGoodJets[0].eta, sel3, EqB(30, -3, 3), title="Leading jet Eta"))
            
        plots.append(Plot.make1D("SubLeadingJetEtaSel3", cleanedGoodJets[1].eta, sel3, EqB(30, -3, 3), title="SubLeading jet Eta"))

        plots.append(Plot.make1D("nMuSel3", op.rng_len(identifiedMuons), sel3, EqB(10, 0., 10.), title="nMuons"))
        
        plots.append(Plot.make1D("LeadingMuonPTSel3", muons[0].pt, sel3, EqB(30, 0., 250.), title=" Leading Muon PT"))
            
        plots.append(Plot.make1D("SubLeadingMuonPTSel3", muons[1].pt, sel3, EqB(30, 0., 200.), title=" SubLeading Muon PT"))

        plots.append(Plot.make1D("LeadingMuonEtaSel3", muons[0].eta, sel3, EqB(30, -3, 3), title=" Leading Muon Eta"))
            
        plots.append(Plot.make1D("SubLeadingMuonEtaSel3", muons[1].eta, sel3, EqB(30, -3, 3), title=" SubLeading Muon Eta"))
                
        plots.append(Plot.make1D("InvMassTwoMuonsSel3", InvMassMuMU, sel3, EqB(30, 0, 300), title="m(ll)"))
        
        plots.append(Plot.make1D("METptSel3", met[0].pt, sel3, EqB(50, 0., 250), title="MET_PT"))
        
            #sel4
             
        plots.append(Plot.make1D("nJetsSel4", op.rng_len(cleanedGoodJets), sel4, EqB(10, 0, 10), title="nJets"))

        plots.append(Plot.make1D("nbtaggedJetsSel4", op.rng_len(btaggedJets), sel4, EqB(10, 0., 10.), title="nbtaggedJets"))

        plots.append(Plot.make1D("LeadingJetPTSel4", cleanedGoodJets[0].pt, sel4, EqB(50, 0., 250.), title="Leading jet PT"))
            
        plots.append(Plot.make1D("SubLeadingJetPTSel4", cleanedGoodJets[1].pt, sel4, EqB(50, 0., 250.), title="SubLeading jet PT"))
            
        plots.append(Plot.make1D("LeadingJetEtaSel4", cleanedGoodJets[0].eta, sel4, EqB(30, -3, 3.), title="Leading jet Eta"))
            
        plots.append(Plot.make1D("SubLeadingJetEtaSel4", cleanedGoodJets[1].eta, sel4, EqB(30, -3, 3.), title="SubLeading jet Eta"))
        
        plots.append(Plot.make1D("nMuSel4", op.rng_len(identifiedMuons), sel4, EqB(10, 0., 10.), title="nMuons"))
                
        plots.append(Plot.make1D("LeadingMuonPTSel4", muons[0].pt, sel4, EqB(30, 0., 250.), title=" Leading Muon PT"))
        
        plots.append(Plot.make1D("SubLeadingMuonPTSel4", muons[1].pt, sel4, EqB(30, 0., 200.), title=" SubLeading Muon PT"))
        
        plots.append(Plot.make1D("LeadingMuonEtaSel4", muons[0].eta, sel4, EqB(30, -3, 3), title=" Leading Muon Eta"))
        
        plots.append(Plot.make1D("SubLeadingMuonEtaSel4", muons[1].eta, sel4, EqB(30, -3, 3), title=" SubLeading Muon Eta"))

        plots.append(Plot.make1D("InvMassTwoMuonsSel4", InvMassMuMU, sel4, EqB(30, 0, 300), title="m(ll)"))
        
        plots.append(Plot.make1D("METptSel4", met[0].pt, sel4, EqB(50, 0., 250), title="MET_PT"))

            #sel5
                
        plots.append(Plot.make1D("nJetsSel5", op.rng_len(cleanedGoodJets), sel5, EqB(10, 0, 10), title="nJets"))

        plots.append(Plot.make1D("nbtaggedJetsSel5", op.rng_len(btaggedJets), sel5, EqB(10, 0., 10.), title="nbtaggedJets"))

        plots.append(Plot.make1D("LeadingJetPTSel5", cleanedGoodJets[0].pt, sel5, EqB(50, 0., 250.), title="Leading jet PT"))
            
        plots.append(Plot.make1D("SubLeadingJetPTSel5", cleanedGoodJets[1].pt, sel5, EqB(50, 0., 250.), title="SubLeading jet PT"))
            
        plots.append(Plot.make1D("LeadingJetEtaSel5", cleanedGoodJets[0].eta, sel5, EqB(30, -3, 3.), title="Leading jet Eta"))
            
        plots.append(Plot.make1D("SubLeadingJetEtaSel5", cleanedGoodJets[1].eta, sel5, EqB(30, -3, 3.), title="SubLeading jet Eta"))
        
        plots.append(Plot.make1D("nMuSel5", op.rng_len(identifiedMuons), sel5, EqB(10, 0., 10.), title="nMuons"))
                
        plots.append(Plot.make1D("LeadingMuonPTSel5", muons[0].pt, sel5, EqB(30, 0., 250.), title=" Leading Muon PT"))
        
        plots.append(Plot.make1D("SubLeadingMuonPTSel5", muons[1].pt, sel5, EqB(30, 0., 200.), title=" SubLeading Muon PT"))
        
        plots.append(Plot.make1D("LeadingMuonEtaSel5", muons[0].eta, sel5, EqB(30, -3, 3), title=" Leading Muon Eta"))
        
        plots.append(Plot.make1D("SubLeadingMuonEtaSel5", muons[1].eta, sel5, EqB(30, -3, 3), title=" SubLeading Muon Eta"))

        plots.append(Plot.make1D("InvMassTwoMuonsSel5", InvMassMuMU, sel5, EqB(30, 0, 300), title="m(ll)"))

        plots.append(Plot.make1D("METptSel5", met[0].pt, sel5, EqB(50, 0., 250), title="MET_PT > 40"))

        # Efficiency Report on terminal and the .tex output

        cfr = CutFlowReport("yields")
        cfr.add(noSel, "Sel0: No selection")
        cfr.add(sel1, "Sel1: nMuMu >= 2")
        cfr.add(sel2, "Sel2: InvM")
        cfr.add(sel3, "Sel3: nJet >= 2")
        cfr.add(sel4, "Sel4: btag")
        cfr.add(sel5, "Sel5: MET")

        plots.append(cfr)
                            
        return plots
예제 #24
0
    def definePlots(self, t, noSel, sample=None, sampleCfg=None):
        noSel = super(BtagEffAndMistagNano,
                      self).prepareObjects(t, noSel, sample, sampleCfg)

        era = sampleCfg['era']
        plots = []

        # protection against data #
        if not self.is_MC:
            return []

        # Get ScaleFactor binning #
        instance = ScaleFactorsbbWW()
        all_SF = instance.all_scalefactors

        tuple_medium_DeepJet_json = all_SF['btag_' + era]['DeepJet_medium']
        variables = []
        binning = []
        index = ['x', 'y', 'z']
        for json_file in tuple_medium_DeepJet_json:
            with open(json_file, 'r') as handle:
                content = json.load(handle)
            var = content['variables']
            bins = content['binning']
            variables.append(var)
            binning.append(bins)

            print('Variables in file %s' % json_file)
            for var, bin_name in zip(var, index):
                print(('... Variable : %s' % var).ljust(30, ' ') +
                      'Binning (index %s) :' % bin_name, bins[bin_name])

        # Find best binning (finest)  #
        opt_binning = {}
        for var, bins in zip(variables, binning):
            for v, bn in zip(var, index):
                if v == 'AbsEta':
                    continue
                b = bins[bn]
                if not v in opt_binning.keys():
                    opt_binning[v] = b
                else:
                    opt_binning[v].extend(
                        [a for a in b if a not in opt_binning[v]])

        # Sort #
        for var, bins in opt_binning.items():
            opt_binning[var] = sorted(opt_binning[var])

        print("Optimal Binning chosen")
        for var, bins in opt_binning.items():
            print(('... Variable : %s' % var).ljust(30, ' ') + 'Binning :',
                  bins)

        # Truth MC object hadron flavour #
        ak4_truth_lightjets = op.select(self.ak4Jets,
                                        lambda j: op.abs(j.hadronFlavour) == 0)
        ak4_truth_cjets = op.select(self.ak4Jets,
                                    lambda j: op.abs(j.hadronFlavour) == 4)
        ak4_truth_bjets = op.select(self.ak4Jets,
                                    lambda j: op.abs(j.hadronFlavour) == 5)

        plots.append(
            Plot.make3D('N_total_lightjets', [
                op.map(ak4_truth_lightjets, lambda j: j.eta),
                op.map(ak4_truth_lightjets, lambda j: j.pt),
                op.map(ak4_truth_lightjets, lambda j: j.btagDeepFlavB)
            ],
                        noSel, [
                            VariableBinning(opt_binning['Eta']),
                            VariableBinning(opt_binning['Pt']),
                            VariableBinning(opt_binning['BTagDiscri'])
                        ],
                        xTitle='lightjet #eta',
                        yTitle='lightjet P_{T}',
                        zTitle='lightjet Btagging score'))
        plots.append(
            Plot.make3D('N_total_cjets', [
                op.map(ak4_truth_cjets, lambda j: j.eta),
                op.map(ak4_truth_cjets, lambda j: j.pt),
                op.map(ak4_truth_cjets, lambda j: j.btagDeepFlavB)
            ],
                        noSel, [
                            VariableBinning(opt_binning['Eta']),
                            VariableBinning(opt_binning['Pt']),
                            VariableBinning(opt_binning['BTagDiscri'])
                        ],
                        xTitle='cjet #eta',
                        yTitle='cjet P_{T}',
                        zTitle='cjet Btagging score'))
        plots.append(
            Plot.make3D('N_total_bjets', [
                op.map(ak4_truth_bjets, lambda j: j.eta),
                op.map(ak4_truth_bjets, lambda j: j.pt),
                op.map(ak4_truth_bjets, lambda j: j.btagDeepFlavB)
            ],
                        noSel, [
                            VariableBinning(opt_binning['Eta']),
                            VariableBinning(opt_binning['Pt']),
                            VariableBinning(opt_binning['BTagDiscri'])
                        ],
                        xTitle='bjet #eta',
                        yTitle='bjet P_{T}',
                        zTitle='bjet Btagging score'))

        # Btagged objects per flavour #
        ak4_btagged_lightjets = op.select(ak4_truth_lightjets,
                                          self.lambda_ak4Btag)
        ak4_btagged_cjets = op.select(ak4_truth_cjets, self.lambda_ak4Btag)
        ak4_btagged_bjets = op.select(ak4_truth_bjets, self.lambda_ak4Btag)

        plots.append(
            Plot.make3D('N_btagged_lightjets', [
                op.map(ak4_btagged_lightjets, lambda j: j.eta),
                op.map(ak4_btagged_lightjets, lambda j: j.pt),
                op.map(ak4_btagged_lightjets, lambda j: j.btagDeepFlavB)
            ],
                        noSel, [
                            VariableBinning(opt_binning['Eta']),
                            VariableBinning(opt_binning['Pt']),
                            VariableBinning(opt_binning['BTagDiscri'])
                        ],
                        xTitle='lightjet #eta',
                        yTitle='lightjet P_{T}',
                        zTitle='lightjet Btagging score'))
        plots.append(
            Plot.make3D('N_btagged_cjets', [
                op.map(ak4_btagged_cjets, lambda j: j.eta),
                op.map(ak4_btagged_cjets, lambda j: j.pt),
                op.map(ak4_btagged_cjets, lambda j: j.btagDeepFlavB)
            ],
                        noSel, [
                            VariableBinning(opt_binning['Eta']),
                            VariableBinning(opt_binning['Pt']),
                            VariableBinning(opt_binning['BTagDiscri'])
                        ],
                        xTitle='cjet #eta',
                        yTitle='cjet P_{T}',
                        zTitle='cjet Btagging score'))
        plots.append(
            Plot.make3D('N_btagged_bjets', [
                op.map(ak4_btagged_bjets, lambda j: j.eta),
                op.map(ak4_btagged_bjets, lambda j: j.pt),
                op.map(ak4_btagged_bjets, lambda j: j.btagDeepFlavB)
            ],
                        noSel, [
                            VariableBinning(opt_binning['Eta']),
                            VariableBinning(opt_binning['Pt']),
                            VariableBinning(opt_binning['BTagDiscri'])
                        ],
                        xTitle='bjet #eta',
                        yTitle='bjet P_{T}',
                        zTitle='bjet Btagging score'))

        return plots