def makeJetmultiplictyPlots(selection, jets, suffix, uname, ForBeauty=False):
    binScaling = 1
    plots = []
    plots.append(
        Plot.make1D(f"{uname}_%s_Jet_mulmtiplicity" % suffix,
                    op.rng_len(jets),
                    selection,
                    EqBin(10, 0., 10.),
                    title="Jet mulmtiplicity",
                    plotopts=utils.getOpts(uname, **{"log-y": True})))
    if ForBeauty:
        wp = suffix.split('_')[-1]
        cut = suffix.replace(wp, '')
        print(wp, cut)
        for key, sel in selection.items():
            tagger = key.replace(wp, "")
            bjets = safeget(jets, tagger, wp)
            plots.append(
                Plot.make1D(f"{uname}_%s_%s%s_Jet_mulmtiplicity" %
                            (cut, tagger, wp),
                            op.rng_len(bjets),
                            sel,
                            EqBin(10, 0., 10.),
                            title="Jet mulmtiplicity",
                            plotopts=utils.getOpts(uname, **{"log-y": True})))

    return plots
Esempio n. 2
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 = []

        verbose = False

        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))
        hasTriJet = noSel.refine("hasTriJet", cut=(op.rng_len(trijets) > 0))
        hadTop_p4 = op.defineOnFirstUse(hadTop[0].p4 + hadTop[1].p4 + hadTop[2].p4)
        plots.append(Plot.make1D("trijet_topPt",
            hadTop_p4.Pt(), hasTriJet,
            EqBin(100, 15., 40.), title="Trijet p_{T} (GeV/c)"))
        plots.append(Plot.make1D("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("njets",
                op.rng_len(tree.Jet), noSel,
                EqBin(20, 0., 20.), title="Number of jets"))
            plots.append(Plot.make1D("ntrijets",
                op.rng_len(trijets), noSel,
                EqBin(100, 0., 1000.), title="Number of 3-jet combinations"))
            plots.append(Plot.make1D("trijet_mass",
                hadTop_p4.M(), hasTriJet,
                EqBin(100, 0., 250.), title="Trijet mass (GeV/c^{2})"))

        return plots
Esempio n. 3
0
def evaluateJPA_1b0Wj(lepton, muons, electrons, ak4jets, jets, bJetsL, bJetsM, met, model, HLL):
    #invars = [op.c_float(0.)]*8
    invars = [lepton.pt,                                                              # leptonPt                                         
              bJetCorrPT(jets[0]),                                                    # bjet1_ptReg
              jets[0].btagDeepFlavB,                                                  # bjet1_btagCSV
              jets[0].qgl,                                                            # bjet1_qgDiscr
              op.abs(lepton.eta - jets[0].eta),                                       # dEta_bjet1_lep
              op.rng_len(ak4jets),                                                    # nJets
              op.rng_len(bJetsL),                                                     # nBJetLoose
              op.rng_len(bJetsM)                                                      # nBJetMedium
          ]
    return model(*invars, defineOnFirstUse=False)[0]
Esempio n. 4
0
def evaluateJPA_2b0Wj(lepton, muons, electrons, ak4jets, jets, bJetsL, bJetsM, met, model, HLL):
    #invars = [op.c_float(0.)]*9
    invars = [bJetCorrPT(jets[0]),                                                    # bjet1_ptReg
              jets[0].btagDeepFlavB,                                                  # bjet1_btagCSV
              bJetCorrPT(jets[1]),                                                    # bjet2_ptReg
              jets[1].btagDeepFlavB,                                                  # bjet2_btagCSV
              jets[1].qgl,                                                            # bjet2_qgDiscr
              op.abs(lepton.eta - jets[1].eta),                                       # dEta_bjet2_lep
              (HLL.bJetCorrP4(jets[0]) + HLL.bJetCorrP4(jets[1])).M(),                # Hbb_massReg
              op.rng_len(ak4jets),                                                    # nJets
              op.rng_len(bJetsM)                                                      # nBJetMedium
          ]
    return model(*invars, defineOnFirstUse=False)[0]
Esempio n. 5
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
Esempio n. 6
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
Esempio n. 7
0
def evaluateJPA_1b2Wj(lepton, muons, electrons, ak4jets, jets, bJetsL, bJetsM, met, model, HLL):
    #invars = [op.c_float(0.)]*12
    invars = [bJetCorrPT(jets[0]),                                                    # bjet1_ptReg
              jets[0].btagDeepFlavB,                                                  # bjet1_btagCSV
              bJetCorrPT(jets[1]),                                                    # wjet1_ptReg
              jets[1].btagDeepFlavB,                                                  # wjet1_btagCSV
              jets[2].btagDeepFlavB,                                                  # wjet2_btagCSV
              jets[2].qgl,                                                            # wjet2_qgDiscr
              HLL.Wjj_simple(jets[1].p4, jets[2].p4).M(),                             # HadW_mass
              op.deltaR(HLL.Wjj_simple(jets[1].p4, jets[2].p4), lepton.p4),           # dR_HadW_lep
              op.deltaR(jets[1].p4, jets[2].p4),                                      # dR_wjet1wjet2 
              (HLL.bJetCorrP4(jets[0]) + HLL.Wjj_simple(jets[1].p4, jets[2].p4)).M(), # mTop1 = (WhadP4 + bJet1P4).M()
              op.rng_len(ak4jets),                                                    # nJets
              op.rng_len(bJetsM)                                                      # nBJetMedium
          ]
    return model(*invars, defineOnFirstUse=False)[0]
Esempio n. 8
0
def plotNumber(contName, cont, sel, Nmax, xTitle):
    return [
        Plot.make1D(contName,
                    op.rng_len(cont),
                    sel,
                    EquidistantBinning(Nmax, 0., Nmax),
                    xTitle=xTitle)
    ]
Esempio n. 9
0
def evaluateJPA_2b1Wj(lepton, muons, electrons, ak4jets, jets, bJetsL, bJetsM, met, model, HLL):
    #invars = [op.c_float(0.)]*13
    invars = [jets[0].btagDeepFlavB,                                                  # bjet1_btagCSV
              bJetCorrPT(jets[1]),                                                    # bjet2_ptReg
              jets[1].btagDeepFlavB,                                                  # bjet2_btagCSV
              jets[1].qgl,                                                            # bjet2_qgDiscr
              op.abs(lepton.eta - jets[1].eta),                                       # dEta_bjet2_lep
              bJetCorrPT(jets[2]),                                                    # wjet1_ptReg
              jets[2].btagDeepFlavB,                                                  # wjet1_btagCSV
              jets[2].qgl,                                                            # wjet1_qgDiscr
              op.abs(lepton.eta - jets[2].eta),                                       # dEta_wjet1_lep
              op.deltaR(jets[0].p4, jets[1].p4),                                      # dR_bjet1bjet2 
              op.rng_len(ak4jets),                                                    # nJets
              op.rng_len(bJetsL),                                                     # nBJetLoose
              op.rng_len(bJetsM)                                                      # nBJetMedium
          ]
    return model(*invars, defineOnFirstUse=False)[0]
Esempio n. 10
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
Esempio n. 11
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
Esempio n. 12
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]
Esempio n. 13
0
def evaluateJPA_Hbb1Wj(lepton, muons, electrons, fatJets, jets, bJetsL, bJetsM, met, model, HLL):
    #invars = [op.c_float(0.)]*14
    invars = [op.switch(fatJets[0].subJet1.btagDeepB > fatJets[0].subJet2.btagDeepB,  # dEta_bjet1_lep 
                        op.abs(lepton.eta-fatJets[0].subJet1.eta),
                        op.abs(lepton.eta-fatJets[0].subJet2.eta)),        
              bJetCorrPT(jets[0]),                                                    # wjet1_ptReg
              jets[0].btagDeepB,                                                      # wjet1_btagCSV
              jets[0].qgl,                                                            # wjet1_qgDiscr
              op.deltaR(lepton.p4, jets[0].p4),                                       # dR_wjet1_lep
              (fatJets[0].subJet1.p4 + fatJets[0].subJet2.p4).Pt(),                   # Hbb_Pt
              op.rng_len(bJetsM)                                                      # nBJetMedium
          ]

    return model(*invars, defineOnFirstUse=False)[0]
Esempio n. 14
0
 def controlPlots_2l(self, noSel, muons, electrons):
     plots = [
         Plot.make1D("nEl", op.rng_len(electrons), noSel, EqBin(10, 0., 10.), xTitle="Number of tight electrons"),
         Plot.make1D("nMu", op.rng_len(muons), noSel, EqBin(10, 0., 10.), xTitle="Number of tight muons"),
         ]
     hasOSElEl = noSel.refine("hasOSElEl", cut=[ op.rng_len(electrons) >= 2,
         electrons[0].charge != electrons[1].charge, electrons[0].pt > 20., electrons[1].pt > 10. ])
     plots.append(Plot.make1D("massZto2e", op.invariant_mass(electrons[0].p4, electrons[1].p4),
         hasOSElEl, EqBin(120, 40., 120.), title="mass of Z to 2e",
         xTitle="Invariant Mass of Nelectrons=2 (in GeV/c^2)"))
     plots += [ 
         Plot.make1D("OSElEl_PTl1", electrons[0].pt, hasOSElEl, EqBin(50, 0., 100.)),
         Plot.make1D("OSElEl_PTl2", electrons[1].pt, hasOSElEl, EqBin(50, 0., 100.)),
         ]
     hasOSMuMu = noSel.refine("hasOSMuMu", cut=[ op.rng_len(muons) >= 2,
         muons[0].charge != muons[1].charge, muons[0].pt > 20., muons[1].pt > 10. ])
     plots.append(Plot.make1D("massZto2mu", op.invariant_mass(muons[0].p4, muons[1].p4),
         hasOSMuMu, EqBin(120, 40., 120.), title="mass of Z to 2mu",
         xTitle="Invariant Mass of Nmuons=2 (in GeV/c^2)"))
     plots += [ 
         Plot.make1D("OSMuMu_PTl1", muons[0].pt, hasOSMuMu, EqBin(50, 0., 100.)),
         Plot.make1D("OSMuMu_PTl2", muons[1].pt, hasOSMuMu, EqBin(50, 0., 100.)),
         ]
     return plots
def returnFatjetMVAInputs(self, fatjets):
    return {
        ('fatjet_E', 'Fatjet E [GeV]', (50, 0., 500.)):
        op.switch(op.rng_len(fatjets) > 0, fatjets[0].p4.E(), op.c_float(0.)),
        ('fatjet_Px', 'Fatjet P_x [GeV]', (40, -200., 200.)):
        op.switch(op.rng_len(fatjets) > 0, fatjets[0].p4.Px(), op.c_float(0.)),
        ('fatjet_Py', 'Fatjet P_y [GeV]', (40, -200., 200.)):
        op.switch(op.rng_len(fatjets) > 0, fatjets[0].p4.Py(), op.c_float(0.)),
        ('fatjet_Pz', 'Fatjet P_z [GeV]', (40, -200., 200.)):
        op.switch(op.rng_len(fatjets) > 0, fatjets[0].p4.Pz(), op.c_float(0.)),
        ('fatjet_tau1', 'Fatjet #tau_1', (50, 0., 1.)):
        op.switch(op.rng_len(fatjets) > 0, fatjets[0].tau1, op.c_float(0.)),
        ('fatjet_tau2', 'Fatjet #tau_2', (50, 0., 1.)):
        op.switch(op.rng_len(fatjets) > 0, fatjets[0].tau2, op.c_float(0.)),
        ('fatjet_tau3', 'Fatjet #tau_3', (50, 0., 1.)):
        op.switch(op.rng_len(fatjets) > 0, fatjets[0].tau3, op.c_float(0.)),
        ('fatjet_tau4', 'Fatjet #tau_4', (50, 0., 1.)):
        op.switch(op.rng_len(fatjets) > 0, fatjets[0].tau4, op.c_float(0.)),
        ('fatjet_softdrop', 'Fatjet softdrop mass [GeV]', (50, 0., 1000.)):
        op.switch(
            op.rng_len(fatjets) > 0, fatjets[0].msoftdrop, op.c_float(0.))
    }
Esempio n. 16
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
Esempio n. 17
0
def makeResolvedBJetPlots(self, sel, bjets, wp, uname):
    plots = []
    binScaling = 1
    for key in sel.keys():

        tagger = key.replace(wp, "")
        bjets_ = safeget(bjets, tagger, wp)

        plots.append(
            Plot.make1D("{0}_nBJets_{1}".format(uname, key),
                        op.rng_len(bjets_),
                        sel.get(key),
                        EqB(5, 2., 6.),
                        xTitle="Jets multiplicty {0}".format(key),
                        plotopts=utils.getOpts(uname)))
        for i in range(1):
            plots.append(
                Plot.make1D(
                    f"{uname}_bjet{i+1}_pT_{key}",
                    bjets_[i].pt,
                    sel.get(key),
                    EqB(60, 0., 800.),
                    title=
                    f"{utils.getCounter(i+1)}-highest bjet pT {key} [GeV]",
                    plotopts=utils.getOpts(uname)))

            plots.append(
                Plot.make1D(
                    f"{uname}_bjet{i+1}_eta_{key}",
                    bjets_[i].eta,
                    sel.get(key),
                    EqB(50 // binScaling, -2.4, 2.4),
                    title=f"{utils.getCounter(i+1)}-highest bjet eta {key}",
                    plotopts=utils.getOpts(uname)))

            plots.append(
                Plot.make1D(
                    f"{uname}_bjet{i+1}_eta_{key}",
                    bjets_[i].phi,
                    sel.get(key),
                    EqB(50 // binScaling, -3.1416, 3.1416),
                    title=f"{utils.getCounter(i+1)}-highest bjet phi {key}",
                    plotopts=utils.getOpts(uname)))
    return plots
Esempio n. 18
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
Esempio n. 19
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 = []

        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("dimuZ_MET",
                        tree.MET.pt,
                        hasDiMuZ,
                        EqBin(100, 0., 2000.),
                        title="MET (GeV)"))

        return plots
Esempio n. 20
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
Esempio n. 21
0
def makeJetsPlots(self, sel, jets, suffix, channel):
    """
    Make basic plots
    sel         = refine selection 
    jets        = bjet container with len(jets)>=1 (we require at least one bjet) 
    suffix      = string identifying the selecton 
    channel     = string identifying the channel of the dilepton (can be "NoChannel")
    """

    plots = []

    # bjet 1 plots (always present by selection) #
    plots.append(
        Plot.make1D("%s_leadjetPT_%s" % (channel, suffix),
                    jets[0].p4.Pt(),
                    sel,
                    EquidistantBinning(100, 0, 300.),
                    title='Transverse momentum of the leading jet',
                    xTitle="P_{T}(leading jet) [GeV]"))
    plots.append(
        Plot.make1D("%s_leadjetEta_%s" % (channel, suffix),
                    jets[0].p4.Eta(),
                    sel,
                    EquidistantBinning(20, -3., 3.),
                    title='Transverse momentum of the leading jet',
                    xTitle="#eta(leading jet) [GeV]"))
    plots.append(
        Plot.make1D("%s_leadjetPhi_%s" % (channel, suffix),
                    jets[0].p4.Phi(),
                    sel,
                    EquidistantBinning(20, -3.2, 3.2),
                    title='Azimutal angle of the leading jet',
                    xTitle="#phi(leading jet) [GeV]"))

    # bjet 2 plots (not necessarily present) #
    hasAtLeastTwoBJets = sel.refine("hasAtLeastTwoBJets_%s_%s" %
                                    (channel, suffix),
                                    cut=[op.rng_len(jets) >= 2])
    hasOnlyOneBJet = sel.refine("hasAtLeast2BJets_%s_%s" % (channel, suffix),
                                cut=[op.rng_len(jets) == 1])
    # Fill a specific bin apart so that the information is not lost

    # PT plot #
    plot_hasTwoBJets_PT = Plot.make1D(
        "%s_hasSubleadjetPT_%s" % (channel, suffix),
        jets[1].p4.Pt(),
        hasAtLeastTwoBJets,
        EquidistantBinning(100, -10., 300.),
        title='Transverse momentum of the subleading jet',
        xTitle="P_{T}(subleading jet) [GeV]")
    plot_notTwoBJets_PT = Plot.make1D(
        "%s_notSubleadjetPT_%s" % (channel, suffix),
        op.c_float(-10.),
        hasOnlyOneBJet,
        EquidistantBinning(100, -10., 300.),
        title='Transverse momentum of the subleading jet',
        xTitle="P_{T}(subleading jet) [GeV]")
    plots.append(
        SummedPlot("%s_subleadjetPT_%s" % (channel, suffix),
                   [plot_hasTwoBJets_PT, plot_notTwoBJets_PT],
                   xTitle="P_{T}(subleading jet) [GeV]"))

    # Eta plot #
    plot_hasTwoBJets_Eta = Plot.make1D(
        "%s_hasSubleadjetEta_%s" % (channel, suffix),
        jets[1].p4.Eta(),
        hasAtLeastTwoBJets,
        EquidistantBinning(20, -3., 3.),
        title='Pseudorapidity of the subleading jet',
        xTitle="#eta(subleading jet) [GeV]")
    plot_notTwoBJets_Eta = Plot.make1D(
        "%s_notSubleadjetEta_%s" % (channel, suffix),
        op.c_float(-3.),
        hasOnlyOneBJet,
        EquidistantBinning(20, -3., 3.),
        title='Pseudorapidity of the subleading jet',
        xTitle="#eta(subleading jet) [GeV]")
    plots.append(
        SummedPlot("%s_subleadjetEta_%s" % (channel, suffix),
                   [plot_hasTwoBJets_Eta, plot_notTwoBJets_Eta],
                   xTitle="#eta(subleading jet) [GeV]"))

    # Phi plot #
    plot_hasTwoBJets_Phi = Plot.make1D(
        "%s_hasSubleadjetPhi_%s" % (channel, suffix),
        jets[1].p4.Phi(),
        hasAtLeastTwoBJets,
        EquidistantBinning(20, -3.2, 3.2),
        title='Azimutal angle of the subleading jet',
        xTitle="#phi(subleading jet) [GeV]")
    plot_notTwoBJets_Phi = Plot.make1D(
        "%s_notSubleadjetPhi_%s" % (channel, suffix),
        op.c_float(-3.2),
        hasOnlyOneBJet,
        EquidistantBinning(20, -3.2, 3.2),
        title='Azimutal angle of the subleading jet',
        xTitle="#phi(subleading jet) [GeV]")
    plots.append(
        SummedPlot("%s_subleadjetPhi_%s" % (channel, suffix),
                   [plot_hasTwoBJets_Phi, plot_notTwoBJets_Phi],
                   xTitle="#phi(subleading jet) [GeV]"))

    # InvMass plot #
    plot_hasTwoBJets_invMass = Plot.make1D(
        "%s_hasTwoBJets_invMass_%s" % (channel, suffix),
        op.invariant_mass(jets[0].p4, jets[1].p4),
        hasAtLeastTwoBJets,
        EquidistantBinning(100, -10, 500.),
        title="Dijet invariant mass (channel %s)" % channel,
        xTitle="Invariant mass [GeV]")
    plot_notTwoBJets_invMass = Plot.make1D(
        "%s_notTwoBJets_invMass_%s" % (channel, suffix),
        op.c_float(-10.),
        hasAtLeastTwoBJets,
        EquidistantBinning(100, -10, 500.),
        title="Dijet invariant mass (channel %s)" % channel,
        xTitle="Invariant mass [GeV]")
    plots.append(
        SummedPlot("%s_dijetInvariantMass_%s" % (channel, suffix),
                   [plot_hasTwoBJets_invMass, plot_notTwoBJets_invMass],
                   xTitle="Invariant mass [GeV]"))

    return plots
Esempio n. 22
0
def returnHighLevelMVAInputs(self,l1,l2,met,jets,bjets,electrons,muons,channel):
    if channel == "ElEl":
        cone_l1 = self.getElectronConeP4(l1) 
        cone_l2 = self.getElectronConeP4(l2)
    elif channel == "MuMu":
        cone_l1 = self.getMuonConeP4(l1)
        cone_l2 = self.getMuonConeP4(l2)
    elif channel == "ElMu":
        cone_l1 = self.getElectronConeP4(l1)
        cone_l2 = self.getMuonConeP4(l2)
    else:
        raise RuntimeError("Wrong channel")

    dijets = op.combine(jets, N=2)

    import bamboo.treeoperations as _to
    def rng_min(rng, fun=(lambda x : x), typeName="float"):
        return op._to.Reduce.fromRngFun(rng, op.c_float(float("+inf"), typeName), ( lambda fn : (
                lambda res, elm : op.extMethod("std::min", returnType="Float_t")(res, fn(elm))
                        ) )(fun) )

    if self.args.Boosted0Btag or self.args.Boosted1Btag:
        VBFJetPairs = self.VBFJetPairsBoosted
    elif self.args.Resolved0Btag or self.args.Resolved1Btag or self.args.Resolved2Btag:
        VBFJetPairs = self.VBFJetPairsResolved
    else:
        raise RuntimeError("Wrong selection to be used by the DNN")

    return {
            ('m_bb_bregcorr',          'Di-bjet invariant mass (regcorr) [GeV]',  (100,0.,1000.))   : op.multiSwitch((op.rng_len(bjets) == 0, op.c_float(0.)),
                                                                                                                     (op.rng_len(bjets) == 1, self.HLL.getCorrBp4(bjets[0]).M()),
                                                                                                                     op.invariant_mass(self.HLL.getCorrBp4(bjets[0]),self.HLL.getCorrBp4(bjets[1]))),
            ('ht',                     'HT(jets) [GeV]',                          (100,0.,1000.))   : op.rng_sum(jets, lambda j : j.pt),
            ('min_dr_jets_lep1',       'Min(#Delta R(lead lepton,jets))',         (25,0.,5.))       : op.switch(op.rng_len(jets) > 0,
                                                                                                                op.switch(cone_l1.Pt() >= cone_l2.Pt(),
                                                                                                                          self.HLL.MinDR_part1_partCont(cone_l1,jets),
                                                                                                                          self.HLL.MinDR_part1_partCont(cone_l2,jets)),
                                                                                                                op.c_float(0.)),
            ('min_dr_jets_lep2',       'Min(#Delta R(sublead lepton,jets))',      (25,0.,5.))       : op.switch(op.rng_len(jets) > 0,
                                                                                                                op.switch(cone_l1.Pt() >= cone_l2.Pt(),
                                                                                                                          self.HLL.MinDR_part1_partCont(cone_l2,jets),
                                                                                                                          self.HLL.MinDR_part1_partCont(cone_l1,jets)),
                                                                                                                op.c_float(0.)),
            ('m_ll',                   'Dilepton invariant mass [GeV]',           (100,0.,1000.))   : op.invariant_mass(cone_l1,cone_l2),
            ('dr_ll',                  'Dilepton #Delta R',                       (25,0.,5.))       : op.deltaR(cone_l1,cone_l2),
            ('min_dr_jet',             'Min(#Delta R(jets))',                     (25,0.,5.))       : op.switch(op.rng_len(dijets) > 0,
                                                                                                                op.rng_min(dijets,lambda dijet : op.deltaR(dijet[0].p4,dijet[1].p4)),
                                                                                                                op.c_float(0.)),
            ('min_dhi_jet',            'Min(#Delta #Phi(jets))',                  (16,0.,3.2))      : op.switch(op.rng_len(dijets) > 0,
                                                                                                                rng_min(dijets,lambda dijet : op.abs(op.deltaPhi(dijet[0].p4,dijet[1].p4)),typeName='double'),
                                                                                                                op.c_float(0.)),
            ('m_hh_simplemet_bregcorr','M_{HH} (simple MET) (regcorr) [GeV]',     (100,0.,1000.))   : op.invariant_mass(op.rng_sum(bjets,
                                                                                                                                   lambda bjet : self.HLL.getCorrBp4(bjet),
                                                                                                                                   start=self.HLL.empty_p4),
                                                                                                                        cone_l1,
                                                                                                                        cone_l2,
                                                                                                                        met.p4),
            ('met_ld',                 'MET_{LD}',                                (100,0.,1000.))   : self.HLL.MET_LD_DL(met,jets,electrons,muons),
            ('dr_bb',                  'Di-bjet #Delta R',                        (25,0.,5.))       : op.switch(op.rng_len(bjets)>=2,
                                                                                                                op.deltaR(bjets[0].p4,bjets[1].p4),
                                                                                                                op.c_float(0.)),
            ('min_dr_leps_b1',         'Min(#Delta R(lead bjet,dilepton))',       (25,0.,5.))       : op.switch(op.rng_len(bjets)>=1,
                                                                                                                self.HLL.MinDR_part1_dipart(bjets[0].p4,[cone_l1,cone_l2]),
                                                                                                                op.c_float(0.)),
            ('min_dr_leps_b2',         'Min(#Delta R(sublead bjet,dilepton))',    (25,0.,5.))       : op.switch(op.rng_len(bjets)>=2,
                                                                                                                self.HLL.MinDR_part1_dipart(bjets[1].p4,[cone_l1,cone_l2]),
                                                                                                                op.c_float(0.)),
            ('lep1_conept',            'Lead lepton cone-P_T [GeV]',              (40,0.,200.))     : op.switch(cone_l1.Pt() >= cone_l2.Pt() , cone_l1.Pt() , cone_l2.Pt()),
            ('lep2_conept',            'Sublead lepton cone-P_T [GeV]',           (40,0.,200.))     : op.switch(cone_l1.Pt() >= cone_l2.Pt() , cone_l2.Pt() , cone_l1.Pt()),
            ('mww_simplemet',          'M_{WW} (simple MET) [GeV]',               (100,0.,1000.))   : op.invariant_mass(cone_l1,cone_l2,met.p4),
            ('vbf_tag',                'VBF tag',                                 (2,0.,2.))        : op.c_int(op.rng_len(VBFJetPairs)>0),
            ('boosted_tag',            'Boosted tag',                             (2,0.,2.))        : op.c_int(op.OR(op.rng_len(self.ak8BJets) > 0,           # Boosted 1B
                                                                                                                     op.AND(op.rng_len(self.ak8BJets) == 0,   # Boosted 0B
                                                                                                                            op.rng_len(self.ak8Jets) > 0,
                                                                                                                            op.rng_len(self.ak4BJets) == 0))),
            ('dphi_met_dilep',         'Dilepton-MET #Delta #Phi',                (32,-3.2,3.2))    : op.abs(op.deltaPhi(met.p4,(cone_l1+cone_l2))),
            ('dphi_met_dibjet',        'Dibjet-MET #Delta #Phi',                  (32,-3.2,3.2))    : op.multiSwitch((op.rng_len(bjets) == 0, op.c_float(0.)),
                                                                                                                     (op.rng_len(bjets) == 1, op.abs(op.deltaPhi(met.p4,bjets[0].p4))),
                                                                                                                     op.abs(op.deltaPhi(met.p4,(bjets[0].p4+bjets[1].p4)))),
            ('dr_dilep_dijet',         'Dilepton-dijet #Delta R',                 (25,0.,5.))       : op.multiSwitch((op.rng_len(jets) == 0, op.c_float(0.)),
                                                                                                                     (op.rng_len(jets) == 1, op.deltaR((cone_l1+cone_l2),jets[0].p4)),
                                                                                                                     op.deltaR((cone_l1+cone_l2),(jets[0].p4+jets[1].p4))),
            ('dr_dilep_dibjet',        'Dilepton-dibjet #Delta R',                (25,0.,5.))       : op.multiSwitch((op.rng_len(bjets) == 0, op.c_float(0.)),
                                                                                                                     (op.rng_len(bjets) == 1, op.deltaR((cone_l1+cone_l2),bjets[0].p4)),
                                                                                                                     op.deltaR((cone_l1+cone_l2),(bjets[0].p4+bjets[1].p4))),
            ('vbf_pair_mass',          'VBF pair M_{jj}',                         (100,0.,1000.))   : op.switch(op.rng_len(VBFJetPairs)>0,
                                                                                                                op.invariant_mass(VBFJetPairs[0][0].p4,VBFJetPairs[0][1].p4),
                                                                                                                op.c_float(0.)),
            ('vbf_pairs_absdeltaeta',  'VBF pair #Delta#eta',                     (25,0.,5.))       : op.switch(op.rng_len(VBFJetPairs)>0,
                                                                                                                op.abs(VBFJetPairs[0][0].eta-VBFJetPairs[0][1].eta),
                                                                                                                op.c_float(0.)),
            ('sphericity',             'None',                                    (1,0.,1.))        : op.c_float(0.),
            ('sphericity_T',           'None',                                    (1,0.,1.))        : op.c_float(0.),
            ('aplanarity',             'None',                                    (1,0.,1.))        : op.c_float(0.),
            ('eventshape_C',           'None',                                    (1,0.,1.))        : op.c_float(0.),
            ('eventshape_D',           'None',                                    (1,0.,1.))        : op.c_float(0.),
            ('eventshape_Y',           'None',                                    (1,0.,1.))        : op.c_float(0.),
            ('foxwolfram1',            'None',                                    (1,0.,1.))        : op.c_float(0.),
            ('foxwolfram2',            'None',                                    (1,0.,1.))        : op.c_float(0.),
            ('foxwolfram3',            'None',                                    (1,0.,1.))        : op.c_float(0.),
            ('foxwolfram4',            'None',                                    (1,0.,1.))        : op.c_float(0.),
            ('foxwolfram5',            'None',                                    (1,0.,1.))        : op.c_float(0.),
            ('centrality',             'None',                                    (1,0.,1.))        : op.c_float(0.),
            ('centrality_jets',        'None',                                    (1,0.,1.))        : op.c_float(0.),
            ('eigenvalue1',            'None',                                    (1,0.,1.))        : op.c_float(0.),
            ('eigenvalue2',            'None',                                    (1,0.,1.))        : op.c_float(0.),
            ('eigenvalue3',            'None',                                    (1,0.,1.))        : op.c_float(0.),
            }
Esempio n. 23
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
Esempio n. 24
0
    def definePlots(self, t, noSel, sample=None, sampleCfg=None): 
        noSel = super(PlotterNanoHHtobbWWDL,self).prepareObjects(t, noSel, sample, sampleCfg, 'DL')
        #----- Machine Learning Model -----#                
        path_model = os.path.join(os.path.abspath(os.path.dirname(__file__)),'MachineLearning','model.pb')
        if not os.path.exists(path_model):
            raise RuntimeError('Could not find model file %s'%path_model)
        try:
            LBN = op.mvaEvaluator(path_model,mvaType='Tensorflow',otherArgs=(["input_1", "input_2"], "model/output/Softmax"))
        except:
            raise RuntimeError('Could not load model %s'%path_model)

        #---- Parameters -----#

        plots = []

        cutFlowPlots = []

        era = sampleCfg['era']

        self.sample = sample
        self.sampleCfg = sampleCfg
        self.era = era

        self.yieldPlots = makeYieldPlots(self.args.Synchronization)

        #----- Ratio reweighting variables (before lepton and jet selection) -----#
        if self.args.BtagReweightingOff or self.args.BtagReweightingOn:
            plots.append(objectsNumberPlot(channel="NoChannel",suffix='NoSelection',sel=noSel,objCont=self.ak4Jets,objName='Ak4Jets',Nmax=15,xTitle='N(Ak4 jets)'))
            plots.append(CutFlowReport("BtagReweightingCutFlowReport",noSel))
            return plots

        #----- Stitching study -----#
        if self.args.DYStitchingPlots or self.args.WJetsStitchingPlots:
            if self.args.DYStitchingPlots and sampleCfg['group'] != 'DY':
                raise RuntimeError("Stitching is only done on DY MC samples")
            if self.args.WJetsStitchingPlots and sampleCfg['group'] != 'Wjets':
                raise RuntimeError("Stitching is only done on WJets MC samples")
            plots.extend(makeLHEPlots(noSel,t.LHE))
            plots.append(objectsNumberPlot(channel="NoChannel",suffix='NoSelection',sel=noSel,objCont=self.ak4Jets,objName='Ak4Jets',Nmax=15,xTitle='N(Ak4 jets)'))
            plots.append(CutFlowReport("DYStitchingCutFlowReport",noSel))
            return plots


        #----- Dileptons -----#
        selObjectDict = makeDoubleLeptonSelection(self,noSel,plot_yield=True)
        # selObjectDict : keys -> level (str)
        #                 values -> [ElEl,MuMu,ElMu] x Selection object

        # Select the jets selections that will be done depending on user input #
        jet_level = ["Ak4","Ak8","Resolved0Btag","Resolved1Btag","Resolved2Btag","Boosted"]
        jetplot_level = [arg for (arg,boolean) in self.args.__dict__.items() if arg in jet_level and boolean]
        if len(jetplot_level) == 0:  
            jetplot_level = jet_level # If nothing said, will do all
        jetsel_level = copy(jetplot_level)  # A plot level might need a previous selection that needs to be defined but not necessarily plotted
        if "Resolved0Btag" in jetsel_level or "Resolved1Btag" in jetsel_level or "Resolved2Btag" in jetsel_level:
            jetsel_level.append("Ak4") # Resolved needs the Ak4 selection
        if "Boosted" in jetsel_level:
            jetsel_level.append("Ak8") # Boosted needs the Ak8 selection

        # Loop over lepton selection and start plotting #
        for selectionType, selectionList in selObjectDict.items():
            print ("... Processing %s lepton type"%selectionType)
            #----- Select correct dilepton -----#
            if selectionType == "Preselected":  
                OSElElDilepton = self.OSElElDileptonPreSel
                OSMuMuDilepton = self.OSMuMuDileptonPreSel
                OSElMuDilepton = self.OSElMuDileptonPreSel
            elif selectionType == "Fakeable":
                OSElElDilepton = self.ElElDileptonFakeSel
                OSMuMuDilepton = self.MuMuDileptonFakeSel
                OSElMuDilepton = self.ElMuDileptonFakeSel
            elif selectionType == "Tight":
                OSElElDilepton = switch_on_index([0],op.rng_len(self.ElElDileptonTightSel)>=1,self.ElElDileptonTightSel,self.ElElDileptonFakeExtrapolationSel)
                OSMuMuDilepton = switch_on_index([0],op.rng_len(self.MuMuDileptonTightSel)>=1,self.MuMuDileptonTightSel,self.MuMuDileptonFakeExtrapolationSel)
                OSElMuDilepton = switch_on_index([0],op.rng_len(self.ElMuDileptonTightSel)>=1,self.ElMuDileptonTightSel,self.ElMuDileptonFakeExtrapolationSel)
            elif selectionType == "FakeExtrapolation":
                OSElElDilepton = self.ElElDileptonFakeExtrapolationSel
                OSMuMuDilepton = self.MuMuDileptonFakeExtrapolationSel
                OSElMuDilepton = self.ElMuDileptonFakeExtrapolationSel

            #----- Separate selections ------#
            ElElSelObjectDilepton = selectionList[0]
            MuMuSelObjectDilepton = selectionList[1]
            ElMuSelObjectDilepton = selectionList[2]

            #----- Channel and trigger plots -----#

            if not self.args.OnlyYield:
                ChannelDictList = []
                ChannelDictList.append({'channel':'ElEl','sel':ElElSelObjectDilepton.sel,'suffix':ElElSelObjectDilepton.selName})
                ChannelDictList.append({'channel':'MuMu','sel':MuMuSelObjectDilepton.sel,'suffix':MuMuSelObjectDilepton.selName})
                ChannelDictList.append({'channel':'ElMu','sel':ElMuSelObjectDilepton.sel,'suffix':ElMuSelObjectDilepton.selName})

                for channelDict in ChannelDictList:
                    #----- Trigger plots -----#
                    plots.extend(doubleLeptonTriggerPlots(**channelDict,triggerDict=self.triggersPerPrimaryDataset))
                    #----- Dilepton plots -----#
                    #plots.extend(doubleLeptonChannelPlot(**channelDict,DilepElEl=OSElElDilepton,DilepMuMu=OSMuMuDilepton,DilepElMu=OSElMuDilepton))

            LeptonKeys = ['channel','sel','dilepton','suffix','is_MC']
            JetKeys    = ['channel','sel','leadjet','subleadjet','lead_is_b','sublead_is_b','suffix','is_MC']
            commonItems = ['channel','sel','suffix']
                
            #----- Ak4 jets selection -----#
            if "Ak4" in jetsel_level:
                print ("...... Processing Ak4 jet selection")
                ElElSelObjectDileptonAk4Jets = makeAtLeastTwoAk4JetSelection(self,ElElSelObjectDilepton,copy_sel=True,plot_yield=True)
                MuMuSelObjectDileptonAk4Jets = makeAtLeastTwoAk4JetSelection(self,MuMuSelObjectDilepton,copy_sel=True,plot_yield=True)
                ElMuSelObjectDileptonAk4Jets = makeAtLeastTwoAk4JetSelection(self,ElMuSelObjectDilepton,copy_sel=True,plot_yield=True)

                # Jet and lepton plots #
                ChannelDictList = []
                if "Ak4" in jetplot_level:
                    # Cut flow report #
                    cutFlowPlots.append(CutFlowReport(ElElSelObjectDileptonAk4Jets.selName,ElElSelObjectDileptonAk4Jets.sel))
                    cutFlowPlots.append(CutFlowReport(MuMuSelObjectDileptonAk4Jets.selName,MuMuSelObjectDileptonAk4Jets.sel))
                    cutFlowPlots.append(CutFlowReport(ElMuSelObjectDileptonAk4Jets.selName,ElMuSelObjectDileptonAk4Jets.sel))
                    if not self.args.OnlyYield:
                        ChannelDictList.append({'channel':'ElEl','sel':ElElSelObjectDileptonAk4Jets.sel,'dilepton':OSElElDilepton[0],'leadjet':self.ak4Jets[0],'subleadjet':self.ak4Jets[1],'lead_is_b':False,'sublead_is_b':False,'suffix':ElElSelObjectDileptonAk4Jets.selName,'is_MC':self.is_MC})
                        ChannelDictList.append({'channel':'MuMu','sel':MuMuSelObjectDileptonAk4Jets.sel,'dilepton':OSMuMuDilepton[0],'leadjet':self.ak4Jets[0],'subleadjet':self.ak4Jets[1],'lead_is_b':False,'sublead_is_b':False,'suffix':MuMuSelObjectDileptonAk4Jets.selName,'is_MC':self.is_MC})
                        ChannelDictList.append({'channel':'ElMu','sel':ElMuSelObjectDileptonAk4Jets.sel,'dilepton':OSElMuDilepton[0],'leadjet':self.ak4Jets[0],'subleadjet':self.ak4Jets[1],'lead_is_b':False,'sublead_is_b':False,'suffix':ElMuSelObjectDileptonAk4Jets.selName,'is_MC':self.is_MC})

                JetsN = {'objName':'Ak4Jets','objCont':self.ak4Jets,'Nmax':15,'xTitle':'N(Ak4 jets)'}
                                                            
                for channelDict in ChannelDictList:
                    # Dilepton #
                    plots.extend(makeDileptonPlots(**{k:channelDict[k] for k in LeptonKeys}))
                    # Number of jets #
                    plots.append(objectsNumberPlot(**{k:channelDict[k] for k in commonItems},**JetsN))
                    # Ak4 Jets #
                    plots.extend(makeTwoAk4JetsPlots(**{k:channelDict[k] for k in JetKeys}))
                    # MET #
                    plots.extend(makeMETPlots(**{k:channelDict[k] for k in commonItems}, met=self.corrMET))

            ##### Ak8 jets selection #####
            if "Ak8" in jetsel_level:
                print ("...... Processing Ak8 jet selection")
                ElElSelObjectDileptonAk8Jets = makeAtLeastOneAk8JetSelection(self,ElElSelObjectDilepton,copy_sel=True,plot_yield=True)
                MuMuSelObjectDileptonAk8Jets = makeAtLeastOneAk8JetSelection(self,MuMuSelObjectDilepton,copy_sel=True,plot_yield=True)
                ElMuSelObjectDileptonAk8Jets = makeAtLeastOneAk8JetSelection(self,ElMuSelObjectDilepton,copy_sel=True,plot_yield=True)

                # Fatjets plots #
                ChannelDictList = []
                if "Ak8" in jetplot_level:
                    # Cut flow report #
                    cutFlowPlots.append(CutFlowReport(ElElSelObjectDileptonAk8Jets.selName,ElElSelObjectDileptonAk8Jets.sel))
                    cutFlowPlots.append(CutFlowReport(MuMuSelObjectDileptonAk8Jets.selName,MuMuSelObjectDileptonAk8Jets.sel))
                    cutFlowPlots.append(CutFlowReport(ElMuSelObjectDileptonAk8Jets.selName,ElMuSelObjectDileptonAk8Jets.sel))
                    if not self.args.OnlyYield:
                        ChannelDictList.append({'channel':'ElEl','sel':ElElSelObjectDileptonAk8Jets.sel,'dilepton':OSElElDilepton[0],'fatjet':self.ak8Jets[0],'suffix':ElElSelObjectDileptonAk8Jets.selName,'is_MC':self.is_MC})
                        ChannelDictList.append({'channel':'MuMu','sel':MuMuSelObjectDileptonAk8Jets.sel,'dilepton':OSMuMuDilepton[0],'fatjet':self.ak8Jets[0],'suffix':MuMuSelObjectDileptonAk8Jets.selName,'is_MC':self.is_MC})
                        ChannelDictList.append({'channel':'ElMu','sel':ElMuSelObjectDileptonAk8Jets.sel,'dilepton':OSElMuDilepton[0],'fatjet':self.ak8Jets[0],'suffix':ElMuSelObjectDileptonAk8Jets.selName,'is_MC':self.is_MC})

                FatJetKeys = ['channel','sel','fatjet','suffix']
                FatJetsN = {'objName':'Ak8Jets','objCont':self.ak8Jets,'Nmax':5,'xTitle':'N(Ak8 jets)'}
                
                for channelDict in ChannelDictList:
                    # Dilepton #
                    plots.extend(makeDileptonPlots(**{k:channelDict[k] for k in LeptonKeys}))
                    # Number of jets #
                    plots.append(objectsNumberPlot(**{k:channelDict[k] for k in commonItems},**FatJetsN))
                    # Ak8 Jets #
                    plots.extend(makeDoubleLeptonAk8JetsPlots(**{k:channelDict[k] for k in FatJetKeys}))
                    # MET #
                    plots.extend(makeMETPlots(**{k:channelDict[k] for k in commonItems}, met=self.corrMET))

                         
            #----- Resolved selection -----#
            if any(item in ["Resolved0Btag","Resolved1Btag","Resolved2Btag"] for item in jetsel_level): # If any of resolved category is asked
                #----- select the jets -----#
                aka4JetsByBtagScore = op.sort(self.ak4Jets, lambda jet : -jet.btagDeepFlavB)

                container0b2j = [ t.Jet[self.ak4LightJetsByBtagScore[i].idx] for i in range(2) ]
                container1b1j = [ t.Jet[op.switch(op.rng_len(self.ak4BJets) == 1, self.ak4BJets[0].idx,  aka4JetsByBtagScore[0].idx)] ,
                                  t.Jet[op.switch(op.rng_len(self.ak4BJets) == 1, self.ak4LightJetsByBtagScore[0].idx,  aka4JetsByBtagScore[1].idx)]]
                container2b0j = [ t.Jet[op.switch(op.rng_len(self.ak4BJets) >= 2, self.ak4BJets[i].idx, aka4JetsByBtagScore[i].idx)] for i in range(2) ]

                ChannelDictList = []
                #----- Resolved selection : 0 Btag -----#
                if "Resolved0Btag" in jetsel_level:
                    print ("...... Processing Resolved jet (0 btag) selection")
                    ElElSelObjectDileptonAk4JetsExclusiveResolvedNoBtag = makeExclusiveResolvedNoBtagSelection(self,ElElSelObjectDileptonAk4Jets,copy_sel=True,plot_yield=True)
                    MuMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag = makeExclusiveResolvedNoBtagSelection(self,MuMuSelObjectDileptonAk4Jets,copy_sel=True,plot_yield=True)
                    ElMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag = makeExclusiveResolvedNoBtagSelection(self,ElMuSelObjectDileptonAk4Jets,copy_sel=True,plot_yield=True)

                    if "Resolved0Btag" in jetplot_level:
                        # Cut flow report #
                        cutFlowPlots.append(CutFlowReport(ElElSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.selName,ElElSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.sel))
                        cutFlowPlots.append(CutFlowReport(MuMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.selName,MuMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.sel))
                        cutFlowPlots.append(CutFlowReport(ElMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.selName,ElMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.sel))
                        if not self.args.OnlyYield:
                            ChannelDictList.append({'channel':'ElEl','sel':ElElSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.sel,'dilepton':OSElElDilepton[0],'leadjet':container0b2j[0],'subleadjet':container0b2j[1],'lead_is_b':False,'sublead_is_b':False,'suffix':ElElSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.selName,'is_MC':self.is_MC})
                            ChannelDictList.append({'channel':'MuMu','sel':MuMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.sel,'dilepton':OSMuMuDilepton[0],'leadjet':container0b2j[0],'subleadjet':container0b2j[1],'lead_is_b':False,'sublead_is_b':False,'suffix':MuMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.selName,'is_MC':self.is_MC})
                            ChannelDictList.append({'channel':'ElMu','sel':ElMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.sel,'dilepton':OSElMuDilepton[0],'leadjet':container0b2j[0],'subleadjet':container0b2j[1],'lead_is_b':False,'sublead_is_b':False,'suffix':ElMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.selName,'is_MC':self.is_MC})
                #----  Resolved selection : 1 Btag  -----#
                if "Resolved1Btag" in jetsel_level:
                    print ("...... Processing Resolved jet (1 btag) selection")
                    ElElSelObjectDileptonAk4JetsExclusiveResolvedOneBtag = makeExclusiveResolvedOneBtagSelection(self,ElElSelObjectDileptonAk4Jets,copy_sel=True,plot_yield=True)
                    MuMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag = makeExclusiveResolvedOneBtagSelection(self,MuMuSelObjectDileptonAk4Jets,copy_sel=True,plot_yield=True)
                    ElMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag = makeExclusiveResolvedOneBtagSelection(self,ElMuSelObjectDileptonAk4Jets,copy_sel=True,plot_yield=True)

                    if "Resolved1Btag" in jetplot_level:
                        # Cut flow report #
                        cutFlowPlots.append(CutFlowReport(ElElSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.selName,ElElSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.sel))
                        cutFlowPlots.append(CutFlowReport(MuMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.selName,MuMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.sel))
                        cutFlowPlots.append(CutFlowReport(ElMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.selName,ElMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.sel))
                        if not self.args.OnlyYield:
                            ChannelDictList.append({'channel':'ElEl','sel':ElElSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.sel,'dilepton':OSElElDilepton[0],'leadjet':container1b1j[0],'subleadjet':container1b1j[1],'lead_is_b':True,'sublead_is_b':False,'suffix':ElElSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.selName,'is_MC':self.is_MC})
                            ChannelDictList.append({'channel':'MuMu','sel':MuMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.sel,'dilepton':OSMuMuDilepton[0],'leadjet':container1b1j[0],'subleadjet':container1b1j[1],'lead_is_b':True,'sublead_is_b':False,'suffix':MuMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.selName,'is_MC':self.is_MC})
                            ChannelDictList.append({'channel':'ElMu','sel':ElMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.sel,'dilepton':OSElMuDilepton[0],'leadjet':container1b1j[0],'subleadjet':container1b1j[1],'lead_is_b':True,'sublead_is_b':False,'suffix':ElMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.selName,'is_MC':self.is_MC})
                #----- Resolved selection : 2 Btags -----#
                if "Resolved2Btag" in jetsel_level:
                    print ("...... Processing Resolved jet (2 btags) selection")
                    ElElSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags = makeExclusiveResolvedTwoBtagsSelection(self,ElElSelObjectDileptonAk4Jets,copy_sel=True,plot_yield=True)
                    MuMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags = makeExclusiveResolvedTwoBtagsSelection(self,MuMuSelObjectDileptonAk4Jets,copy_sel=True,plot_yield=True)
                    ElMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags = makeExclusiveResolvedTwoBtagsSelection(self,ElMuSelObjectDileptonAk4Jets,copy_sel=True,plot_yield=True)

                    if "Resolved2Btag" in jetplot_level:
                        # Cut flow report #
                        cutFlowPlots.append(CutFlowReport(ElElSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.selName,ElElSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.sel))
                        cutFlowPlots.append(CutFlowReport(MuMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.selName,MuMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.sel))
                        cutFlowPlots.append(CutFlowReport(ElMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.selName,ElMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.sel))
                        if not self.args.OnlyYield:
                            ChannelDictList.append({'channel':'ElEl','sel':ElElSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.sel,'dilepton':OSElElDilepton[0],'leadjet':container2b0j[0],'subleadjet':container2b0j[1],'lead_is_b':True,'sublead_is_b':True,'suffix':ElElSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.selName,'is_MC':self.is_MC})
                            ChannelDictList.append({'channel':'MuMu','sel':MuMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.sel,'dilepton':OSMuMuDilepton[0],'leadjet':container2b0j[0],'subleadjet':container2b0j[1],'lead_is_b':True,'sublead_is_b':True,'suffix':MuMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.selName,'is_MC':self.is_MC})
                            ChannelDictList.append({'channel':'ElMu','sel':ElMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.sel,'dilepton':OSElMuDilepton[0],'leadjet':container2b0j[0],'subleadjet':container2b0j[1],'lead_is_b':True,'sublead_is_b':True,'suffix':ElMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.selName,'is_MC':self.is_MC})

                # Lepton + jet Plots #

                ResolvedJetsN = {'objName':'Ak4BJets','objCont':self.ak4BJets,'Nmax':5,'xTitle':'N(Ak4 Bjets)'}
        
                for channelDict in ChannelDictList:
                    # Dilepton #
                    plots.extend(makeDileptonPlots(**{k:channelDict[k] for k in LeptonKeys}))
                    # Number of jets #
                    plots.append(objectsNumberPlot(**{k:channelDict[k] for k in commonItems},**ResolvedJetsN))
                    plots.append(objectsNumberPlot(**{k:channelDict[k] for k in commonItems},**JetsN))
                    # Ak4 Jets #
                    plots.extend(makeTwoAk4JetsPlots(**{k:channelDict[k] for k in JetKeys}))
                    # MET #
                    plots.extend(makeMETPlots(**{k:channelDict[k] for k in commonItems}, met=self.corrMET))
            
            #----- Boosted selection -----#
            if "Boosted" in jetsel_level:
                print ("...... Processing Boosted jet selection")
                ElElSelObjectDileptonAk8JetsInclusiveBoosted = makeInclusiveBoostedSelection(self,ElElSelObjectDileptonAk8Jets,copy_sel=True,plot_yield=True)
                MuMuSelObjectDileptonAk8JetsInclusiveBoosted = makeInclusiveBoostedSelection(self,MuMuSelObjectDileptonAk8Jets,copy_sel=True,plot_yield=True)
                ElMuSelObjectDileptonAk8JetsInclusiveBoosted = makeInclusiveBoostedSelection(self,ElMuSelObjectDileptonAk8Jets,copy_sel=True,plot_yield=True)

                # Lepton + jet Plots #
                ChannelDictList = []
                if "Boosted" in jetplot_level:
                    # Cut flow report #
                    cutFlowPlots.append(CutFlowReport(ElElSelObjectDileptonAk8JetsInclusiveBoosted.selName,ElElSelObjectDileptonAk8JetsInclusiveBoosted.sel))
                    cutFlowPlots.append(CutFlowReport(MuMuSelObjectDileptonAk8JetsInclusiveBoosted.selName,MuMuSelObjectDileptonAk8JetsInclusiveBoosted.sel))
                    cutFlowPlots.append(CutFlowReport(ElMuSelObjectDileptonAk8JetsInclusiveBoosted.selName,ElMuSelObjectDileptonAk8JetsInclusiveBoosted.sel))
                    if not self.args.OnlyYield:
                        ChannelDictList.append({'channel':'ElEl','sel':ElElSelObjectDileptonAk8JetsInclusiveBoosted.sel,'dilepton':OSElElDilepton[0],'fatjet':self.ak8BJets[0],'suffix':ElElSelObjectDileptonAk8JetsInclusiveBoosted.selName,'is_MC':self.is_MC})
                        ChannelDictList.append({'channel':'MuMu','sel':MuMuSelObjectDileptonAk8JetsInclusiveBoosted.sel,'dilepton':OSMuMuDilepton[0],'fatjet':self.ak8BJets[0],'suffix':MuMuSelObjectDileptonAk8JetsInclusiveBoosted.selName,'is_MC':self.is_MC})
                        ChannelDictList.append({'channel':'ElMu','sel':ElMuSelObjectDileptonAk8JetsInclusiveBoosted.sel,'dilepton':OSElMuDilepton[0],'fatjet':self.ak8BJets[0],'suffix':ElMuSelObjectDileptonAk8JetsInclusiveBoosted.selName,'is_MC':self.is_MC})

                BoostedJetsN = {'objName':'Ak8BJets','objCont':self.ak8BJets,'Nmax':5,'xTitle':'N(Ak8 Bjets)'}
                
                for channelDict in ChannelDictList:
                    # Dilepton #
                    plots.extend(makeDileptonPlots(**{k:channelDict[k] for k in LeptonKeys}))
                    # Number of jets #
                    plots.append(objectsNumberPlot(**{k:channelDict[k] for k in commonItems},**BoostedJetsN))
                    plots.append(objectsNumberPlot(**{k:channelDict[k] for k in commonItems},**FatJetsN))
                    # Ak8 Jets #
                    plots.extend(makeDoubleLeptonAk8JetsPlots(**{k:channelDict[k] for k in FatJetKeys}))
                    # MET #
                    plots.extend(makeMETPlots(**{k:channelDict[k] for k in commonItems}, met=self.corrMET))
            
            #----- High-level combinations -----#
            # NOTE : very time consuming 
            ChannelDictList = []
            if not self.args.OnlyYield:
                # Resolved No Btag #
                if "Resolved0Btag" in jetplot_level:
                    ChannelDictList.append({'channel': 'ElEl','met': self.corrMET,'l1':OSElElDilepton[0][0],'l2':OSElElDilepton[0][1],'j1':container0b2j[0],'j2':container0b2j[1],'sel':ElElSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.sel,'suffix':ElElSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.selName})
                    ChannelDictList.append({'channel': 'MuMu','met': self.corrMET,'l1':OSMuMuDilepton[0][0],'l2':OSMuMuDilepton[0][1],'j1':container0b2j[0],'j2':container0b2j[1],'sel':MuMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.sel,'suffix':MuMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.selName})
                    ChannelDictList.append({'channel': 'ElMu','met': self.corrMET,'l1':OSElMuDilepton[0][0],'l2':OSElMuDilepton[0][1],'j1':container0b2j[0],'j2':container0b2j[1],'sel':ElMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.sel,'suffix':ElMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag.selName})
                # Resolved One Btag #
                if "Resolved1Btag" in jetplot_level:
                    ChannelDictList.append({'channel': 'ElEl','met': self.corrMET,'l1':OSElElDilepton[0][0],'l2':OSElElDilepton[0][1],'j1':container1b1j[0],'j2':container1b1j[1],'sel':ElElSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.sel,'suffix':ElElSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.selName})
                    ChannelDictList.append({'channel': 'MuMu','met': self.corrMET,'l1':OSMuMuDilepton[0][0],'l2':OSMuMuDilepton[0][1],'j1':container1b1j[0],'j2':container1b1j[1],'sel':MuMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.sel,'suffix':MuMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.selName})
                    ChannelDictList.append({'channel': 'ElMu','met': self.corrMET,'l1':OSElMuDilepton[0][0],'l2':OSElMuDilepton[0][1],'j1':container1b1j[0],'j2':container1b1j[1],'sel':ElMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.sel,'suffix':ElMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag.selName})
                # Resolved Two Btags  #
                if "Resolved2Btag" in jetplot_level:
                    ChannelDictList.append({'channel': 'ElEl','met': self.corrMET,'l1':OSElElDilepton[0][0],'l2':OSElElDilepton[0][1],'j1':container2b0j[0],'j2':container2b0j[1],'sel':ElElSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.sel,'suffix':ElElSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.selName})
                    ChannelDictList.append({'channel': 'MuMu','met': self.corrMET,'l1':OSMuMuDilepton[0][0],'l2':OSMuMuDilepton[0][1],'j1':container2b0j[0],'j2':container2b0j[1],'sel':MuMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.sel,'suffix':MuMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.selName})
                    ChannelDictList.append({'channel': 'ElMu','met': self.corrMET,'l1':OSElMuDilepton[0][0],'l2':OSElMuDilepton[0][1],'j1':container2b0j[0],'j2':container2b0j[1],'sel':ElMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.sel,'suffix':ElMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags.selName})
                # Boosted #
                if "Boosted" in jetplot_level:
                    ChannelDictList.append({'channel': 'ElEl','met': self.corrMET,'l1':OSElElDilepton[0][0],'l2':OSElElDilepton[0][1],'j1':self.ak8BJets[0].subJet1,'j2':self.ak8BJets[0].subJet2,'sel':ElElSelObjectDileptonAk8JetsInclusiveBoosted.sel,'suffix':ElElSelObjectDileptonAk8JetsInclusiveBoosted.selName})
                    ChannelDictList.append({'channel': 'MuMu','met': self.corrMET,'l1':OSMuMuDilepton[0][0],'l2':OSMuMuDilepton[0][1],'j1':self.ak8BJets[0].subJet1,'j2':self.ak8BJets[0].subJet2,'sel':MuMuSelObjectDileptonAk8JetsInclusiveBoosted.sel,'suffix':MuMuSelObjectDileptonAk8JetsInclusiveBoosted.selName})
                    ChannelDictList.append({'channel': 'ElMu','met': self.corrMET,'l1':OSElMuDilepton[0][0],'l2':OSElMuDilepton[0][1],'j1':self.ak8BJets[0].subJet1,'j2':self.ak8BJets[0].subJet2,'sel':ElMuSelObjectDileptonAk8JetsInclusiveBoosted.sel,'suffix':ElMuSelObjectDileptonAk8JetsInclusiveBoosted.selName})

            for channelDict in ChannelDictList:
                plots.extend(makeDoubleLeptonHighLevelQuantities(**channelDict,HLL=self.HLL))

            #----- Machine Learning plots -----#
            selObjectDictList = []
            if not self.args.OnlyYield:
                if "Ak4" in jetplot_level:
                    selObjectDictList.append({'channel':'ElEl','selObject':ElElSelObjectDileptonAk4Jets})
                    selObjectDictList.append({'channel':'MuMu','selObject':MuMuSelObjectDileptonAk4Jets})
                    selObjectDictList.append({'channel':'ElMu','selObject':ElMuSelObjectDileptonAk4Jets})
#                if "Ak8" in jetplot_level:
#                    selObjectDictList.append({'channel':'ElEl','selObject':ElElSelObjectDileptonAk8Jets})
#                    selObjectDictList.append({'channel':'MuMu','selObject':MuMuSelObjectDileptonAk8Jets})
#                    selObjectDictList.append({'channel':'ElMu','selObject':ElMuSelObjectDileptonAk8Jets})
                if "Resolved0Btag" in jetplot_level:
                    selObjectDictList.append({'channel':'ElEl','selObject':ElElSelObjectDileptonAk4JetsExclusiveResolvedNoBtag})
                    selObjectDictList.append({'channel':'MuMu','selObject':MuMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag})
                    selObjectDictList.append({'channel':'ElMu','selObject':ElMuSelObjectDileptonAk4JetsExclusiveResolvedNoBtag})
                if "Resolved1Btag" in jetplot_level:
                    selObjectDictList.append({'channel':'ElEl','selObject':ElElSelObjectDileptonAk4JetsExclusiveResolvedOneBtag})
                    selObjectDictList.append({'channel':'MuMu','selObject':MuMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag})
                    selObjectDictList.append({'channel':'ElMu','selObject':ElMuSelObjectDileptonAk4JetsExclusiveResolvedOneBtag})
                if "Resolved2Btag" in jetplot_level:
                    selObjectDictList.append({'channel':'ElEl','selObject':ElElSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags})
                    selObjectDictList.append({'channel':'MuMu','selObject':MuMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags})
                    selObjectDictList.append({'channel':'ElMu','selObject':ElMuSelObjectDileptonAk4JetsExclusiveResolvedTwoBtags})
#                if "Boosted" in jetplot_level:
#                    selObjectDictList.append({'channel':'ElEl','selObject':ElElSelObjectDileptonAk8JetsInclusiveBoosted})
#                    selObjectDictList.append({'channel':'MuMu','selObject':MuMuSelObjectDileptonAk8JetsInclusiveBoosted})
#                    selObjectDictList.append({'channel':'ElMu','selObject':ElMuSelObjectDileptonAk8JetsInclusiveBoosted})

            dileptons = {'ElEl':OSElElDilepton[0],'MuMu':OSMuMuDilepton[0],'ElMu':OSElMuDilepton[0]}
            for selObjectDict in selObjectDictList:
                dilepton = dileptons[selObjectDict['channel']]
                plots.extend(makeDoubleLeptonMachineLearningPlots(channel=selObjectDict['channel'],l1=dilepton[0],l2=dilepton[1],jets=self.ak4Jets,sel=selObjectDict['selObject'].sel,suffix=selObjectDict['selObject'].selName,model=LBN))
    
        #----- Add the Yield plots -----#
        plots.extend(self.yieldPlots.returnPlots())

        #plots.extend(cutFlowPlots)

        #----- Return -----#
        return plots
Esempio n. 25
0
def returnJetsMVAInputs(self,jets):
    return {('j1_E',        'Lead jet E [GeV]',             (50,0.,500.))        : op.switch(op.rng_len(jets)>0,jets[0].p4.E(),op.c_float(0.)),
            ('j1_Px',       'Lead jet P_x [GeV]',           (40,-200.,200.))     : op.switch(op.rng_len(jets)>0,jets[0].p4.Px(),op.c_float(0.)),
            ('j1_Py',       'Lead jet P_y [GeV]',           (40,-200.,200.))     : op.switch(op.rng_len(jets)>0,jets[0].p4.Py(),op.c_float(0.)),
            ('j1_Pz',       'Lead jet P_z [GeV]',           (40,-200.,200.))     : op.switch(op.rng_len(jets)>0,jets[0].p4.Pz(),op.c_float(0.)),
            ('j1_btag',     'Lead jet btag score',          (50,0.,1.)  )        : op.switch(op.rng_len(jets)>0,jets[0].btagDeepFlavB,op.c_float(0.)),
            ('j2_E',        'Sublead jet E [GeV]',          (50,0.,500.))        : op.switch(op.rng_len(jets)>1,jets[1].p4.E(),op.c_float(0.)),
            ('j2_Px',       'Sublead jet P_x [GeV]',        (40,-200.,200.))     : op.switch(op.rng_len(jets)>1,jets[1].p4.Px(),op.c_float(0.)),
            ('j2_Py',       'Sublead jet P_y [GeV]',        (40,-200.,200.))     : op.switch(op.rng_len(jets)>1,jets[1].p4.Py(),op.c_float(0.)),
            ('j2_Pz',       'Sublead jet P_z [GeV]',        (40,-200.,200.))     : op.switch(op.rng_len(jets)>1,jets[1].p4.Pz(),op.c_float(0.)),
            ('j2_btag',     'Sublead jet btag score',       (50,0.,1.)  )        : op.switch(op.rng_len(jets)>1,jets[1].btagDeepFlavB,op.c_float(0.)),
            ('j3_E',        'Subsublead jet E [GeV]',       (50,0.,500.))        : op.switch(op.rng_len(jets)>2,jets[2].p4.E(),op.c_float(0.)),
            ('j3_Px',       'Subsublead jet P_x [GeV]',     (40,-200.,200.))     : op.switch(op.rng_len(jets)>2,jets[2].p4.Px(),op.c_float(0.)),
            ('j3_Py',       'Subsublead jet P_y [GeV]',     (40,-200.,200.))     : op.switch(op.rng_len(jets)>2,jets[2].p4.Py(),op.c_float(0.)),
            ('j3_Pz',       'Subsublead jet P_z [GeV]',     (40,-200.,200.))     : op.switch(op.rng_len(jets)>2,jets[2].p4.Pz(),op.c_float(0.)),
            ('j3_btag',     'Subsublead jet btag score',    (50,0.,1.)  )        : op.switch(op.rng_len(jets)>2,jets[2].btagDeepFlavB,op.c_float(0.)),
            ('j4_E',        'Subsubsublead jet E [GeV]',    (50,0.,500.))        : op.switch(op.rng_len(jets)>3,jets[3].p4.E(),op.c_float(0.)),
            ('j4_Px',       'Subsubsublead jet P_x [GeV]',  (40,-200.,200.))     : op.switch(op.rng_len(jets)>3,jets[3].p4.Px(),op.c_float(0.)),
            ('j4_Py',       'Subsubsublead jet P_y [GeV]',  (40,-200.,200.))     : op.switch(op.rng_len(jets)>3,jets[3].p4.Py(),op.c_float(0.)),
            ('j4_Pz',       'Subsubsublead jet P_z [GeV]',  (40,-200.,200.))     : op.switch(op.rng_len(jets)>3,jets[3].p4.Pz(),op.c_float(0.)),
            ('j4_btag',     'Subsubsublead jet btag score', (50,0.,1.)  )        : op.switch(op.rng_len(jets)>3,jets[3].btagDeepFlavB,op.c_float(0.))}
def returnResonantMVAInputs(self, l1, l2, channel, jets, bjets, fatjets, met,
                            electrons, muons):
    if channel == "ElEl":
        l1conept = lambda l1: self.electron_conept[l1.idx]
        l2conept = lambda l2: self.electron_conept[l2.idx]
    elif channel == "MuMu":
        l1conept = lambda l1: self.muon_conept[l1.idx]
        l2conept = lambda l2: self.muon_conept[l2.idx]
    elif channel == "ElMu":
        l1conept = lambda l1: self.electron_conept[l1.idx]
        l2conept = lambda l2: self.muon_conept[l2.idx]
    else:
        raise RuntimeError("Wrong channel")

    dijets = op.combine(jets, N=2)

    import bamboo.treeoperations as _to

    def rng_min(rng, fun=(lambda x: x), typeName="float"):
        return op._to.Reduce.fromRngFun(
            rng, op.c_float(float("+inf"), typeName),
            (lambda fn:
             (lambda res, elm: op.extMethod("std::min", returnType="Float_t")
              (res, fn(elm))))(fun))

    if self.args.era is None:
        era = op.c_int(int(self.era))
    else:
        era = op.c_int(int(self.args.era))
        print(f'Using {self.args.era} as DNN input')

    return {
        ('eventnr', 'Event number', (100, 0., 1e6)):
        self.tree.event,
        ('era', 'Era', (3, 2016., 2019.)):
        era,
        ('l1_E', 'Lead lepton E [GeV]', (50, 0., 500.)):
        op.switch(l1conept(l1) >= l2conept(l2), l1.p4.E(), l2.p4.E()),
        ('l1_Px', 'Lead lepton P_x [GeV]', (40, -200., 200.)):
        op.switch(l1conept(l1) >= l2conept(l2), l1.p4.Px(), l2.p4.Px()),
        ('l1_Py', 'Lead lepton P_y [GeV]', (40, -200., 200.)):
        op.switch(l1conept(l1) >= l2conept(l2), l1.p4.Py(), l2.p4.Py()),
        ('l1_Pz', 'Lead lepton P_z [GeV]', (40, -200., 200.)):
        op.switch(l1conept(l1) >= l2conept(l2), l1.p4.Pz(), l2.p4.Pz()),
        ('l1_charge', 'Lead lepton charge', (2, 0., 2.)):
        op.switch(l1conept(l1) >= l2conept(l2), l1.charge, l2.charge),
        ('l1_pdgId', 'Lead lepton pdg ID', (45, -22., 22.)):
        op.switch(l1conept(l1) >= l2conept(l2), l1.pdgId, l2.pdgId),
        ('l2_E', 'Sublead lepton E [GeV]', (50, 0., 500.)):
        op.switch(l1conept(l1) >= l2conept(l2), l2.p4.E(), l1.p4.E()),
        ('l2_Px', 'Sublead lepton P_x [GeV]', (40, -200., 200.)):
        op.switch(l1conept(l1) >= l2conept(l2), l2.p4.Px(), l1.p4.Px()),
        ('l2_Py', 'Sublead lepton P_y [GeV]', (40, -200., 200.)):
        op.switch(l1conept(l1) >= l2conept(l2), l2.p4.Py(), l1.p4.Py()),
        ('l2_Pz', 'Sublead lepton P_z [GeV]', (40, -200., 200.)):
        op.switch(l1conept(l1) >= l2conept(l2), l2.p4.Pz(), l1.p4.Pz()),
        ('l2_charge', 'Sublead lepton charge', (2, 0., 2.)):
        op.switch(l1conept(l1) >= l2conept(l2), l2.charge, l1.charge),
        ('l2_pdgId', 'Sublead lepton pdg ID', (45, -22., 22.)):
        op.switch(l1conept(l1) >= l2conept(l2), l2.pdgId, l1.pdgId),
        ('j1_E', 'Lead jet E [GeV]', (50, 0., 500.)):
        op.switch(op.rng_len(jets) > 0, jets[0].p4.E(), op.c_float(0.)),
        ('j1_Px', 'Lead jet P_x [GeV]', (40, -200., 200.)):
        op.switch(op.rng_len(jets) > 0, jets[0].p4.Px(), op.c_float(0.)),
        ('j1_Py', 'Lead jet P_y [GeV]', (40, -200., 200.)):
        op.switch(op.rng_len(jets) > 0, jets[0].p4.Py(), op.c_float(0.)),
        ('j1_Pz', 'Lead jet P_z [GeV]', (40, -200., 200.)):
        op.switch(op.rng_len(jets) > 0, jets[0].p4.Pz(), op.c_float(0.)),
        ('j2_E', 'Sublead jet E [GeV]', (50, 0., 500.)):
        op.switch(op.rng_len(jets) > 1, jets[1].p4.E(), op.c_float(0.)),
        ('j2_Px', 'Sublead jet P_x [GeV]', (40, -200., 200.)):
        op.switch(op.rng_len(jets) > 1, jets[1].p4.Px(), op.c_float(0.)),
        ('j2_Py', 'Sublead jet P_y [GeV]', (40, -200., 200.)):
        op.switch(op.rng_len(jets) > 1, jets[1].p4.Py(), op.c_float(0.)),
        ('j2_Pz', 'Sublead jet P_z [GeV]', (40, -200., 200.)):
        op.switch(op.rng_len(jets) > 1, jets[1].p4.Pz(), op.c_float(0.)),
        ('j3_E', 'Subsublead jet E [GeV]', (50, 0., 500.)):
        op.switch(op.rng_len(jets) > 2, jets[2].p4.E(), op.c_float(0.)),
        ('j3_Px', 'Subsublead jet P_x [GeV]', (40, -200., 200.)):
        op.switch(op.rng_len(jets) > 2, jets[2].p4.Px(), op.c_float(0.)),
        ('j3_Py', 'Subsublead jet P_y [GeV]', (40, -200., 200.)):
        op.switch(op.rng_len(jets) > 2, jets[2].p4.Py(), op.c_float(0.)),
        ('j3_Pz', 'Subsublead jet P_z [GeV]', (40, -200., 200.)):
        op.switch(op.rng_len(jets) > 2, jets[2].p4.Pz(), op.c_float(0.)),
        ('j4_E', 'Subsubsublead jet E [GeV]', (50, 0., 500.)):
        op.switch(op.rng_len(jets) > 3, jets[3].p4.E(), op.c_float(0.)),
        ('j4_Px', 'Subsubsublead jet P_x [GeV]', (40, -200., 200.)):
        op.switch(op.rng_len(jets) > 3, jets[3].p4.Px(), op.c_float(0.)),
        ('j4_Py', 'Subsubsublead jet P_y [GeV]', (40, -200., 200.)):
        op.switch(op.rng_len(jets) > 3, jets[3].p4.Py(), op.c_float(0.)),
        ('j4_Pz', 'Subsubsublead jet P_z [GeV]', (40, -200., 200.)):
        op.switch(op.rng_len(jets) > 3, jets[3].p4.Pz(), op.c_float(0.)),
        ('fatjet_E', 'Fatjet E [GeV]', (50, 0., 500.)):
        op.switch(op.rng_len(fatjets) > 0, fatjets[0].p4.E(), op.c_float(0.)),
        ('fatjet_Px', 'Fatjet P_x [GeV]', (40, -200., 200.)):
        op.switch(op.rng_len(fatjets) > 0, fatjets[0].p4.Px(), op.c_float(0.)),
        ('fatjet_Py', 'Fatjet P_y [GeV]', (40, -200., 200.)):
        op.switch(op.rng_len(fatjets) > 0, fatjets[0].p4.Py(), op.c_float(0.)),
        ('fatjet_Pz', 'Fatjet P_z [GeV]', (40, -200., 200.)):
        op.switch(op.rng_len(fatjets) > 0, fatjets[0].p4.Pz(), op.c_float(0.)),
        ('fatjet_tau1', 'Fatjet #tau_1', (50, 0., 1.)):
        op.switch(op.rng_len(fatjets) > 0, fatjets[0].tau1, op.c_float(0.)),
        ('fatjet_tau2', 'Fatjet #tau_2', (50, 0., 1.)):
        op.switch(op.rng_len(fatjets) > 0, fatjets[0].tau2, op.c_float(0.)),
        ('fatjet_tau3', 'Fatjet #tau_3', (50, 0., 1.)):
        op.switch(op.rng_len(fatjets) > 0, fatjets[0].tau3, op.c_float(0.)),
        ('fatjet_tau4', 'Fatjet #tau_4', (50, 0., 1.)):
        op.switch(op.rng_len(fatjets) > 0, fatjets[0].tau4, op.c_float(0.)),
        ('fatjet_softdrop', 'Fatjet softdrop mass [GeV]', (50, 0., 1000.)):
        op.switch(
            op.rng_len(fatjets) > 0, fatjets[0].msoftdrop, op.c_float(0.)),
        ('met_E', 'MET Energy', (50, 0., 500.)):
        met.p4.E(),
        ('met_Px', 'MET P_x', (40, -200., 200.)):
        met.p4.Px(),
        ('met_Py', 'MET P_y', (40, -200., 200.)):
        met.p4.Py(),
        ('met_Pz', 'MET P_z', (40, -200., 200.)):
        met.p4.Pz(),
        ('m_bb_bregcorr', 'Di-bjet invariant mass (regcorr) [GeV]', (100, 0., 1000.)):
        op.multiSwitch(
            (op.rng_len(bjets) == 0, op.c_float(0.)),
            (op.rng_len(bjets) == 1, self.HLL.getCorrBp4(bjets[0]).M()),
            op.invariant_mass(self.HLL.getCorrBp4(bjets[0]),
                              self.HLL.getCorrBp4(bjets[1]))),
        ('ht', 'HT(jets) [GeV]', (100, 0., 1000.)):
        op.rng_sum(jets, lambda j: j.pt),
        ('min_dr_jets_lep1', 'Min(#Delta R(lead lepton,jets))', (25, 0., 5.)):
        op.switch(
            op.rng_len(jets) > 0,
            op.switch(
                l1conept(l1) >= l2conept(l2),
                self.HLL.MinDR_part1_partCont(l1.p4, jets),
                self.HLL.MinDR_part1_partCont(l2.p4, jets)), op.c_float(0.)),
        ('min_dr_jets_lep2', 'Min(#Delta R(sublead lepton,jets))', (25, 0., 5.)):
        op.switch(
            op.rng_len(jets) > 0,
            op.switch(
                l1conept(l1) >= l2conept(l2),
                self.HLL.MinDR_part1_partCont(l2.p4, jets),
                self.HLL.MinDR_part1_partCont(l1.p4, jets)), op.c_float(0.)),
        ('m_ll', 'Dilepton invariant mass [GeV]', (100, 0., 1000.)):
        op.invariant_mass(l1.p4, l2.p4),
        ('dr_ll', 'Dilepton #Delta R', (25, 0., 5.)):
        op.deltaR(l1.p4, l2.p4),
        ('min_dr_jet', 'Min(#Delta R(jets))', (25, 0., 5.)):
        op.switch(
            op.rng_len(dijets) > 0,
            op.rng_min(dijets,
                       lambda dijet: op.deltaR(dijet[0].p4, dijet[1].p4)),
            op.c_float(0.)),
        ('min_dphi_jet', 'Min(#Delta #Phi(jets))', (16, 0., 3.2)):
        op.switch(
            op.rng_len(dijets) > 0,
            rng_min(
                dijets,
                lambda dijet: op.abs(op.deltaPhi(dijet[0].p4, dijet[1].p4)),
                typeName='double'), op.c_float(0.)),
        ('m_hh_simplemet_bregcorr', 'M_{HH} (simple MET) (regcorr) [GeV]', (100, 0., 1000.)):
        op.invariant_mass(
            op.rng_sum(bjets,
                       lambda bjet: self.HLL.getCorrBp4(bjet),
                       start=self.HLL.empty_p4), l1.p4, l2.p4, met.p4),
        ('met_ld', 'MET_{LD}', (100, 0., 1000.)):
        self.HLL.MET_LD_DL(met, jets, electrons, muons),
        ('dr_bb', 'Di-bjet #Delta R', (25, 0., 5.)):
        op.switch(
            op.rng_len(bjets) >= 2, op.deltaR(bjets[0].p4, bjets[1].p4),
            op.c_float(0.)),
        ('min_dr_leps_b1', 'Min(#Delta R(lead bjet,dilepton))', (25, 0., 5.)):
        op.switch(
            op.rng_len(bjets) >= 1,
            self.HLL.MinDR_part1_dipart(bjets[0].p4, [l1.p4, l2.p4]),
            op.c_float(0.)),
        ('min_dr_leps_b2', 'Min(#Delta R(sublead bjet,dilepton))', (25, 0., 5.)):
        op.switch(
            op.rng_len(bjets) >= 2,
            self.HLL.MinDR_part1_dipart(bjets[1].p4, [l1.p4, l2.p4]),
            op.c_float(0.)),
        ('lep1_conept', 'Lead lepton cone-P_T [GeV]', (40, 0., 200.)):
        op.switch(l1conept(l1) >= l2conept(l2), l1conept(l1), l2conept(l2)),
        ('lep2_conept', 'Sublead lepton cone-P_T [GeV]', (40, 0., 200.)):
        op.switch(l1conept(l1) >= l2conept(l2), l2conept(l2), l1conept(l1)),
        ('mww_simplemet', 'M_{WW} (simple MET) [GeV]', (100, 0., 1000.)):
        op.invariant_mass(l1.p4, l2.p4, met.p4),
        ('boosted_tag', 'Boosted tag', (2, 0., 2.)):
        op.c_int(
            op.OR(
                op.rng_len(self.ak8BJets) > 0,  # Boosted 1B
                op.AND(
                    op.rng_len(self.ak8BJets) == 0,  # Boosted 0B
                    op.rng_len(self.ak8Jets) > 0,
                    op.rng_len(self.ak4BJets) == 0))),
        ('dphi_met_dilep', 'Dilepton-MET #Delta #Phi', (32, -3.2, 3.2)):
        op.abs(op.deltaPhi(met.p4, (l1.p4 + l2.p4))),
        ('dphi_met_dibjet', 'Dibjet-MET #Delta #Phi', (32, -3.2, 3.2)):
        op.multiSwitch(
            (op.rng_len(bjets) == 0, op.c_float(0.)),
            (op.rng_len(bjets) == 1, op.abs(op.deltaPhi(met.p4, bjets[0].p4))),
            op.abs(op.deltaPhi(met.p4, (bjets[0].p4 + bjets[1].p4)))),
        ('dr_dilep_dijet', 'Dilepton-dijet #Delta R', (25, 0., 5.)):
        op.multiSwitch(
            (op.rng_len(jets) == 0, op.c_float(0.)),
            (op.rng_len(jets) == 1, op.deltaR((l1.p4 + l2.p4), jets[0].p4)),
            op.deltaR((l1.p4 + l2.p4), (jets[0].p4 + jets[1].p4))),
        ('dr_dilep_dibjet', 'Dilepton-dibjet #Delta R', (25, 0., 5.)):
        op.multiSwitch(
            (op.rng_len(bjets) == 0, op.c_float(0.)),
            (op.rng_len(bjets) == 1, op.deltaR((l1.p4 + l2.p4), bjets[0].p4)),
            op.deltaR((l1.p4 + l2.p4), (bjets[0].p4 + bjets[1].p4))),
        ('m_T', 'Transverse mass', (100, 0., 1000.)):
        op.sqrt(2 * (l1.p4 + l2.p4).Pt() * met.p4.E() *
                (1 - op.cos((l1.p4 + l2.p4).Phi() - met.p4.Phi()))),
        ('cosThetaS_Hbb', 'Helicity angle between Hbb and bjet', (20, 0., 1.)):
        op.switch(
            op.rng_len(bjets) == 2,
            op.extMethod("HHbbWWJPA::cosThetaS",
                         returnType="float")(bjets[0].p4, bjets[1].p4),
            op.c_float(0.)),
        ('LBN_inputs', 'LBN inputs', None): [
            op.switch(l1conept(l1) >= l2conept(l2), l1.p4.E(), l2.p4.E()),
            op.switch(l1conept(l1) >= l2conept(l2), l1.p4.Px(), l2.p4.Px()),
            op.switch(l1conept(l1) >= l2conept(l2), l1.p4.Py(), l2.p4.Py()),
            op.switch(l1conept(l1) >= l2conept(l2), l1.p4.Pz(), l2.p4.Pz()),
            op.switch(l1conept(l1) >= l2conept(l2), l2.p4.E(), l1.p4.E()),
            op.switch(l1conept(l1) >= l2conept(l2), l2.p4.Px(), l1.p4.Px()),
            op.switch(l1conept(l1) >= l2conept(l2), l2.p4.Py(), l1.p4.Py()),
            op.switch(l1conept(l1) >= l2conept(l2), l2.p4.Pz(), l1.p4.Pz()),
            op.switch(op.rng_len(jets) > 0, jets[0].p4.E(), op.c_float(0.)),
            op.switch(op.rng_len(jets) > 0, jets[0].p4.Px(), op.c_float(0.)),
            op.switch(op.rng_len(jets) > 0, jets[0].p4.Py(), op.c_float(0.)),
            op.switch(op.rng_len(jets) > 0, jets[0].p4.Pz(), op.c_float(0.)),
            op.switch(op.rng_len(jets) > 1, jets[1].p4.E(), op.c_float(0.)),
            op.switch(op.rng_len(jets) > 1, jets[1].p4.Px(), op.c_float(0.)),
            op.switch(op.rng_len(jets) > 1, jets[1].p4.Py(), op.c_float(0.)),
            op.switch(op.rng_len(jets) > 1, jets[1].p4.Pz(), op.c_float(0.)),
            op.switch(op.rng_len(jets) > 2, jets[2].p4.E(), op.c_float(0.)),
            op.switch(op.rng_len(jets) > 2, jets[2].p4.Px(), op.c_float(0.)),
            op.switch(op.rng_len(jets) > 2, jets[2].p4.Py(), op.c_float(0.)),
            op.switch(op.rng_len(jets) > 2, jets[2].p4.Pz(), op.c_float(0.)),
            op.switch(op.rng_len(jets) > 3, jets[3].p4.E(), op.c_float(0.)),
            op.switch(op.rng_len(jets) > 3, jets[3].p4.Px(), op.c_float(0.)),
            op.switch(op.rng_len(jets) > 3, jets[3].p4.Py(), op.c_float(0.)),
            op.switch(op.rng_len(jets) > 3, jets[3].p4.Pz(), op.c_float(0.)),
            op.switch(
                op.rng_len(fatjets) > 0, fatjets[0].p4.E(), op.c_float(0.)),
            op.switch(
                op.rng_len(fatjets) > 0, fatjets[0].p4.Px(), op.c_float(0.)),
            op.switch(
                op.rng_len(fatjets) > 0, fatjets[0].p4.Py(), op.c_float(0.)),
            op.switch(
                op.rng_len(fatjets) > 0, fatjets[0].p4.Pz(), op.c_float(0.))
        ]
    }
Esempio n. 27
0
    def defineSkimSelection(self, t, noSel, sample=None, sampleCfg=None):
        noSel, PUWeight, corrMET, muons, electrons, AK4jets, AK8jets, bjets_resolved, bjets_boosted, categories, TwoLeptonsTwoJets_Resolved, TwoLeptonsTwoJets_Boosted, TwoLeptonsTwoBjets_Res, TwoLeptonsTwoBjets_Boo, TwoLeptonsTwoBjets_NoMETCut_Res, TwoLeptonsTwoBjets_NoMETCut_Boo, WorkingPoints = self.defineObjects(
            t, noSel, sample, sampleCfg)

        era = sampleCfg["era"]
        isMC = self.isMC(sample)

        if self.SetSel not in ["noSel", "catSel", "2Lep2Jets", "2Lep2bJets"]:
            print('[Skimedtree_NanoHtoZA]: %s Unkown selection ' % self.SetSel)
            sys.exit(0)

        if self.SetRegion not in ["boosted", "resolved"]:
            print(' Region of studies should be : boosted or resolved ! ')
            sys.exit(0)

        if self.SetRegion == "boosted":
            self.SetTagger = "DeepCSV"  # FIXME add later DeepDoubleB
        else:
            if self.SetTagger not in ["DeepFlavour", "DeepCSV"]:
                print(
                    '[Skimedtree_NanoHtoZA]: %s Unknown tagger for resolved region'
                    % self.SetTagger)
                sys.exit(0)

        if self.SetCat not in categories.keys():
            print('[Skimedtree_NanoHtoZA] channel %s not found in categories' %
                  self.SetCat)
            print('Available channel are :')
            print(categories.keys())
            sys.exit(0)

        if self.SetWP is None:
            print(
                '[Skimedtree_NanoHtoZA]: WP is MANDATORY, this is the working point as defined in the ZAtollbb_PreSelection.py'
            )
            sys.exit(0)

        if self.SetWP not in WorkingPoints:
            print(
                '[Skimedtree_NanoHtoZA] WP %s not found in working points definitions'
                % self.SetWP)
            print('  --> define in settings first')
            print('  In settings I found WPs: ')
            print(WorkingPoints)
            sys.exit(1)

        key = self.SetTagger + self.SetWP
        if self.SetRegion == "resolved":
            jets = AK4jets
            bjets = bjets_resolved
            suffix = "AK4Jets"
        elif self.SetRegion == "boosted":
            jets = AK8jets
            bjets = bjets_boosted
            suffix = "AK8Jets"
        else:
            raise RuntimeError('ERROR : %s Unkown args' % self.SetRegion)

        #variables to keep from the input tree
        varsToKeep = {"run": None, "luminosityBlock": None, "event": None}

        if isMC:
            varsToKeep["MC_weight"] = t.genWeight
            varsToKeep["PU_weight"] = PUWeight

        if self.SetSel == "noSel":
            FinalSel = noSel
            # Muons && Electrons selections
            for obj, flav in zip([muons, electrons], ["Muons", "Electrons"]):
                varsToKeep["n%s" % flav] = op.static_cast(
                    "UInt_t", op.rng_len(obj))
                varsToKeep["%s_pt" % flav] = op.map(obj, lambda lep: lep.pt)
                varsToKeep["%s_eta" % flav] = op.map(obj, lambda lep: lep.eta)
                varsToKeep["%s_phi" % flav] = op.map(obj, lambda lep: lep.phi)

            # resolved or boosted
            ### Jets selections
            varsToKeep["%s_pt" % suffix] = op.map(jets, lambda j: j.pt)
            varsToKeep["%s_eta" % suffix] = op.map(jets, lambda j: j.eta)
            varsToKeep["%s_phi" % suffix] = op.map(jets, lambda j: j.phi)
            varsToKeep["n%s" % suffix] = op.static_cast(
                "UInt_t", op.rng_len(jets))

            # MET selections
            varsToKeep["CorrMET_pt"] = corrMET.pt
            varsToKeep["CorrMET_phi"] = corrMET.phi

        for channel, (dilepton, catSel) in categories.items():

            ### Opposite sign leptons , Same Flavour  selection
            if self.SetSel == "catSel":
                FinalSel = catSel
                for i in range(2):
                    varsToKeep["lep{0}_pt_{1}".format(
                        i, self.SetCat)] = dilepton[i].p4.pt
                    varsToKeep["lep{0}_eta_{1}".format(
                        i, self.SetCat)] = dilepton[i].p4.eta
                    varsToKeep["lep{0}_phi_{1}".format(
                        i, self.SetCat)] = dilepton[i].p4.phi
                ll_M = op.invariant_mass(dilepton[0].p4, dilepton[1].p4)
                varsToKeep["ll_M_{0}".format(channel)] = ll_M

            # boosted or resolved
            ### Two OS SF Leptons _ Two Jets  selection
            elif self.SetSel == "2Lep2Jets":
                if self.SetRegion == "resolved":
                    FinalSel = TwoLeptonsTwoJets_Resolved.get(key)
                elif self.SetRegion == "boosted":
                    FinaSel = TwoLeptonsTwoJets_Boosted.get(key)

                lljj_M = (dilepton[0].p4 + dilepton[1].p4 + jets[0].p4 +
                          jets[1].p4).M()
                jj_M = op.invariant_mass(jets[0].p4, jets[1].p4)
                varsToKeep["lljj_M_{0}_{1}{2}_{3}".format(
                    self.SetRegion, self.SetTagger, self.SetWP,
                    self.SetCat)] = lljj_M
                varsToKeep["jj_M_{0}_{1}{2}_{3}".format(
                    self.SetRegion, self.SetTagger, self.SetWP,
                    self.SetCat)] = jj_M

                varsToKeep["nB_{0}_{1}{2}_{3}".format(
                    suffix, self.SetTagger, self.SetWP,
                    self.SetCat)] = op.static_cast("UInt_t", op.rng_len(bJets))

                ### Two OS SF Leptons _ Two bJets  selection +MET cut (xy corr applied too )
            elif self.SetSel == "2Lep2bJets":
                bJets = safeget(bjets, self.SetTagger, self.SetWP)
                if self.SetRegion == "resolved":
                    FinalSel = TwoLeptonsTwoBjets_Res.get(key)
                elif self.SetRegion == "boosted":
                    FinalSel = TwoLeptonsTwoBjets_Boo.get(key)

                llbb_M = (dilepton[0].p4 + dilepton[1].p4 + bJets[0].p4 +
                          bJets[1].p4).M()
                bb_M = op.invariant_mass(bJets[0].p4 + bJets[1].p4)
                varsToKeep["llbb_M_{0}_{1}{2}_{3}".format(
                    self.SetRegion, self.SetTagger, self.SetWP,
                    self.SetCat)] = llbb_M
                varsToKeep["bb_M_{0}_{1}{2}_{3}".format(
                    self.SetRegion, self.SetTagger, self.SetWP,
                    self.SetCat)] = bb_M

                varsToKeep["nB_{0}_{1}{2}_{3}".format(
                    suffix, self.SetTagger, self.SetWP,
                    self.SetCat)] = op.static_cast("UInt_t", op.rng_len(bJets))
            else:
                raise RuntimeError('ERROR : %s  in selection args' %
                                   self.SetSel)

            #sample_weight=
            #event_weight=
            #total_weight=
            #cross_section=

        return FinalSel, varsToKeep
Esempio n. 28
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
Esempio n. 29
0
    def defineSkimSelection(self, t, noSel, sample=None, sampleCfg=None):
        noSel = super(SkimmerNanoHHtobbWWSL,
                      self).prepareObjects(t,
                                           noSel,
                                           sample,
                                           sampleCfg,
                                           "SL",
                                           forSkimmer=True)
        # For the Skimmer, SF must not use defineOnFirstUse -> segmentation fault

        era = sampleCfg['era']

        # Initialize varsToKeep dict #
        varsToKeep = dict()

        #---------------------------------------------------------------------------------------#
        #                                     Selections                                        #
        #---------------------------------------------------------------------------------------#
        # keep the exact same order of nodes as mentioned in respective JPA model xml files
        ResolvedJPANodeList = [
            '2b2Wj', '2b1Wj', '1b2Wj', '2b0Wj', '1b1Wj', '1b0Wj', '0b'
        ]
        BoostedJPANodeList = ['Hbb2Wj', 'Hbb1Wj', 'Hbb0Wj']

        # JPA Models
        basepath = os.path.join(os.path.abspath(os.path.dirname(__file__)),
                                'MachineLearning', 'ml-models',
                                'JPA_Loose_ttH')
        resolvedModelDict = getResolvedJpaModelDict(basepath,
                                                    ResolvedJPANodeList, era)
        boostedModelDict = getBoostedJpaModelDict(basepath, BoostedJPANodeList,
                                                  era)

        if not self.inclusive_sel:
            #----- Check arguments -----#
            jet_level = [
                "Ak4", "Ak8", "Res2b2Wj", "Res2b1Wj", "Res2b0Wj", "Res1b2Wj",
                "Res1b1Wj", "Res1b0Wj", "Res0b", "Hbb2Wj", "Hbb1Wj", "Hbb0Wj"
            ]

            if [
                    boolean for (level, boolean) in self.args.__dict__.items()
                    if level in jet_level
            ].count(True) != 1:
                raise RuntimeError(
                    "Only one of the jet arguments must be used, check --help")

            if self.args.Channel not in ["El", "Mu"]:
                raise RuntimeError("Channel must be either 'El' or 'Mu'")

            #----- Lepton selection -----#
            ElSelObj, MuSelObj = makeSingleLeptonSelection(
                self, noSel, use_dd=False, fake_selection=self.args.FakeCR)

            if self.args.Channel is None:
                raise RuntimeError("You need to specify --Channel")
            if self.args.Channel == "El":
                selObj = ElSelObj
                lep = self.electronsTightSel[0]
            if self.args.Channel == "Mu":
                selObj = MuSelObj
                lep = self.muonsTightSel[0]

            #----- Apply jet corrections -----#
            ElSelObject.sel = self.beforeJetselection(ElSelObj.sel, 'El')
            MuSelObject.sel = self.beforeJetselection(MuSelObj.sel, 'Mu')

            #----- Jet selection -----#
            if any([
                    self.args.__dict__[item] for item in [
                        "Ak4", "Res2b2Wj", "Res2b1Wj", "Res2b0Wj", "Res1b2Wj",
                        "Res1b1Wj", "Res1b0Wj", "Res0b"
                    ]
            ]):
                makeResolvedSelection(self, selObj)
                if self.args.Channel == "El":
                    print('... Resolved :: El Channel')
                    L1out, L2out, selObjAndJetsPerJpaCatDict = findJPACategoryResolved(
                        self,
                        selObj,
                        lep,
                        self.muonsPreSel,
                        self.electronsPreSel,
                        self.ak4Jets,
                        self.ak4BJetsLoose,
                        self.ak4BJets,
                        self.corrMET,
                        resolvedModelDict,
                        t.event,
                        self.HLL,
                        ResolvedJPANodeList,
                        plot_yield=False)

                if self.args.Channel == "Mu":
                    print('... Resolved :: Mu Channel')
                    L1out, L2out, selObjAndJetsPerJpaCatDict = findJPACategoryResolved(
                        self,
                        selObj,
                        lep,
                        self.muonsPreSel,
                        self.electronsPreSel,
                        self.ak4Jets,
                        self.ak4BJetsLoose,
                        self.ak4BJets,
                        self.corrMET,
                        resolvedModelDict,
                        t.event,
                        self.HLL,
                        ResolvedJPANodeList,
                        plot_yield=False)

            if any([
                    self.args.__dict__[item]
                    for item in ["Ak8", "Hbb2Wj", "Hbb1Wj", "Hbb0Wj"]
            ]):
                makeBoostedSelection(self, selObj)
                if self.args.Channel == "El":
                    print('... Boosted :: El Channel')
                    L1out, L2out, selObjAndJetsPerJpaCatDict = findJPACategoryBoosted(
                        self,
                        selObj,
                        lep,
                        self.muonsPreSel,
                        self.electronsPreSel,
                        self.ak8BJets,
                        self.ak4JetsCleanedFromAk8b,
                        self.ak4BJetsLoose,
                        self.ak4BJets,
                        self.corrMET,
                        boostedModelDict,
                        t.event,
                        self.HLL,
                        BoostedJPANodeList,
                        plot_yield=False)

                if self.args.Channel == "Mu":
                    print('... Boosted :: Mu Channel')
                    L1out, L2out, selObjAndJetsPerJpaCatDict = findJPACategoryBoosted(
                        self,
                        selObj,
                        lep,
                        self.muonsPreSel,
                        self.electronsPreSel,
                        self.ak8BJets,
                        self.ak4JetsCleanedFromAk8b,
                        self.ak4BJetsLoose,
                        self.ak4BJets,
                        self.corrMET,
                        boostedModelDict,
                        t.event,
                        self.HLL,
                        BoostedJPANodeList,
                        plot_yield=False)

            if self.args.Res2b2Wj:
                print("...... 2b2Wj")
                selObj = selObjAndJetsPerJpaCatDict.get('2b2Wj')[0]
                jpaJets = selObjAndJetsPerJpaCatDict.get('2b2Wj')[1]
                jpaarg = "Res2b2Wj"

            if self.args.Res2b1Wj:
                print("...... 2b1Wj")
                selObj = selObjAndJetsPerJpaCatDict.get('2b1Wj')[0]
                jpaJets = selObjAndJetsPerJpaCatDict.get('2b1Wj')[1]
                jpaarg = "Res2b1Wj"

            if self.args.Res1b2Wj:
                print("...... 1b2Wj")
                selObj = selObjAndJetsPerJpaCatDict.get('1b2Wj')[0]
                jpaJets = selObjAndJetsPerJpaCatDict.get('1b2Wj')[1]
                jpaarg = "Res1b2Wj"

            if self.args.Res2b0Wj:
                print("...... 2b0Wj")
                selObj = selObjAndJetsPerJpaCatDict.get('2b0Wj')[0]
                jpaJets = selObjAndJetsPerJpaCatDict.get('2b0Wj')[1]
                jpaarg = "Res2b0Wj"

            if self.args.Res1b1Wj:
                print("...... 1b1Wj")
                selObj = selObjAndJetsPerJpaCatDict.get('1b1Wj')[0]
                jpaJets = selObjAndJetsPerJpaCatDict.get('1b1Wj')[1]
                jpaarg = "Res1b1Wj"

            if self.args.Res1b0Wj:
                print("...... 1b0Wj")
                selObj = selObjAndJetsPerJpaCatDict.get('1b0Wj')[0]
                jpaJets = selObjAndJetsPerJpaCatDict.get('1b0Wj')[1]
                jpaarg = "Res1b0Wj"

            if self.args.Res0b:
                print("...... 0b")
                selObj = selObjAndJetsPerJpaCatDict.get('0b')[0]
                jpaJets = None
                jpaarg = "Res0b"

            #######################################
            # Hbb2Wj : jet1 jet2   jet3   jet4
            # Hbb1Wj : jet1 jet2   jet3   jet4=0
            # Hbb0Wj : jet1 jet2   jet3=0 jet4=0
            #######################################
            if self.args.Hbb2Wj:
                print("...... Hbb2Wj")
                selObj = selObjAndJetsPerJpaCatDict.get('Hbb2Wj')[0]
                jpaJets = selObjAndJetsPerJpaCatDict.get('Hbb2Wj')[1]
                jpaarg = "Hbb2Wj"

            if self.args.Hbb1Wj:
                print("...... Hbb1Wj")
                selObj = selObjAndJetsPerJpaCatDict.get('Hbb1Wj')[0]
                jpaJets = selObjAndJetsPerJpaCatDict.get('Hbb1Wj')[1]
                jpaarg = "Hbb1Wj"

            if self.args.Hbb0Wj:
                print("...... Hbb0Wj")
                selObj = selObjAndJetsPerJpaCatDict.get('Hbb0Wj')[0]
                jpaJets = None
                jpaarg = "Hbb0Wj"

        else:
            noSel = self.beforeJetselection(noSel)

        #---------------------------------------------------------------------------------------#
        #                                 Synchronization tree                                  #
        #---------------------------------------------------------------------------------------#
        if self.args.Synchronization:
            # Event variables #
            varsToKeep["event"] = None  # Already in tree
            varsToKeep["run"] = None  # Already in tree
            varsToKeep["ls"] = t.luminosityBlock
            varsToKeep["n_presel_mu"] = op.static_cast(
                "UInt_t", op.rng_len(self.muonsPreSel))
            varsToKeep["n_fakeablesel_mu"] = op.static_cast(
                "UInt_t", op.rng_len(self.muonsFakeSel))
            varsToKeep["n_mvasel_mu"] = op.static_cast(
                "UInt_t", op.rng_len(self.muonsTightSel))
            varsToKeep["n_presel_ele"] = op.static_cast(
                "UInt_t", op.rng_len(self.electronsPreSel))
            varsToKeep["n_fakeablesel_ele"] = op.static_cast(
                "UInt_t", op.rng_len(self.electronsFakeSel))
            varsToKeep["n_mvasel_ele"] = op.static_cast(
                "UInt_t", op.rng_len(self.electronsTightSel))
            varsToKeep["n_presel_ak4Jet"] = op.static_cast(
                "UInt_t", op.rng_len(self.ak4Jets))
            varsToKeep["n_presel_ak8Jet"] = op.static_cast(
                "UInt_t", op.rng_len(self.ak8Jets))
            varsToKeep["n_presel_ak8BJet"] = op.static_cast(
                "UInt_t", op.rng_len(self.ak8BJets))
            varsToKeep["n_loose_ak4BJet"] = op.static_cast(
                "UInt_t", op.rng_len(self.ak4BJetsLoose))
            varsToKeep["n_medium_ak4BJet"] = op.static_cast(
                "UInt_t", op.rng_len(self.ak4BJets))
            varsToKeep["n_ak4JetsCleanAk8b"] = op.static_cast(
                "UInt_t", op.rng_len(self.ak4JetsCleanedFromAk8b))
            varsToKeep["n_presel_ak4JetVBF"] = op.static_cast(
                "UInt_t", op.rng_len(self.VBFJetsPreSel))

            varsToKeep["is_SR"] = op.static_cast(
                "UInt_t",
                op.OR(
                    op.rng_len(self.electronsTightSel) == 1,
                    op.rng_len(self.muonsTightSel) == 1))

            varsToKeep["is_e"] = op.c_float(
                True) if self.args.Channel == 'El' else op.c_float(False)
            varsToKeep["is_m"] = op.c_float(
                False) if self.args.Channel == 'El' else op.c_float(True)

            varsToKeep["is_resolved"] = op.switch(
                op.AND(
                    op.rng_len(self.ak4Jets) >= 3,
                    op.rng_len(self.ak4BJets) >= 1,
                    op.rng_len(self.ak8BJets) == 0), op.c_bool(True),
                op.c_bool(False))
            varsToKeep["is_boosted"] = op.switch(
                op.AND(
                    op.rng_len(self.ak8BJets) >= 1,
                    op.rng_len(self.ak4JetsCleanedFromAk8b) >= 1),
                op.c_bool(True), op.c_bool(False))

            varsToKeep["n_tau"] = op.static_cast("UInt_t",
                                                 op.rng_len(self.tauCleanSel))

            varsToKeep['resolved_tag'] = op.static_cast(
                "UInt_t",
                op.AND(
                    op.rng_len(self.ak4Jets) >= 3,
                    op.rng_len(self.ak4BJets) >= 1,
                    op.rng_len(self.ak8BJets) == 0))
            varsToKeep['boosted_tag'] = op.static_cast(
                "UInt_t",
                op.AND(
                    op.rng_len(self.ak8BJets) >= 1,
                    op.rng_len(self.ak4JetsCleanedFromAk8b) >= 1))

            # Triggers #
            '''
            varsToKeep["triggers"]                  = self.triggers
            varsToKeep["triggers_SingleElectron"]   = op.OR(*self.triggersPerPrimaryDataset['SingleElectron'])
            varsToKeep["triggers_SingleMuon"]       = op.OR(*self.triggersPerPrimaryDataset['SingleMuon'])
            varsToKeep["triggers_DoubleElectron"]   = op.OR(*self.triggersPerPrimaryDataset['DoubleEGamma'])
            varsToKeep["triggers_DoubleMuon"]       = op.OR(*self.triggersPerPrimaryDataset['DoubleMuon'])
            varsToKeep["triggers_MuonElectron"]     = op.OR(*self.triggersPerPrimaryDataset['MuonEG'])
            '''
            # Muons #

            for i in range(1, 3):  # 2 leading muons
                varsToKeep["mu{}_pt".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].pt, op.c_float(-9999., "float"))
                varsToKeep["mu{}_eta".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].eta, op.c_float(-9999.))
                varsToKeep["mu{}_phi".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].phi, op.c_float(-9999.))
                varsToKeep["mu{}_E".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].p4.E(),
                    op.c_float(-9999., "float"))
                varsToKeep["mu{}_charge".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].charge, op.c_int(-9999.))
                varsToKeep["mu{}_conept".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muon_conept[self.muonsPreSel[i - 1].idx],
                    op.c_float(-9999.))
                varsToKeep["mu{}_miniRelIso".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].miniPFRelIso_all,
                    op.c_float(-9999.))
                varsToKeep["mu{}_PFRelIso04".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].pfRelIso04_all, op.c_float(-9999.))
                varsToKeep["mu{}_jetNDauChargedMVASel".format(i)] = op.c_float(
                    -9999.)
                varsToKeep["mu{}_jetPtRel".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].jetPtRelv2, op.c_float(-9999.))
                varsToKeep["mu{}_jetRelIso".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].jetRelIso, op.c_float(-9999.))
                varsToKeep["mu{}_jetDeepJet".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].jet.btagDeepFlavB,
                    op.c_float(-9999.))
                varsToKeep["mu{}_sip3D".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].sip3d, op.c_float(-9999.))
                varsToKeep["mu{}_dxy".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].dxy, op.c_float(-9999.))
                varsToKeep["mu{}_dxyAbs".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    op.abs(self.muonsPreSel[i - 1].dxy), op.c_float(-9999.))
                varsToKeep["mu{}_dz".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].dz, op.c_float(-9999.))
                varsToKeep["mu{}_segmentCompatibility".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].segmentComp, op.c_float(-9999.))
                varsToKeep["mu{}_leptonMVA".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].mvaTTH, op.c_float(-9999.))
                varsToKeep["mu{}_mediumID".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].mediumId,
                    op.c_float(-9999., "Bool_t"))
                varsToKeep["mu{}_dpt_div_pt".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].tunepRelPt,
                    op.c_float(-9999.))  # Not sure
                varsToKeep["mu{}_isfakeablesel".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    op.switch(self.lambda_muonFakeSel(self.muonsPreSel[i - 1]),
                              op.c_int(1), op.c_int(0)), op.c_int(-9999))
                varsToKeep["mu{}_ismvasel".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    op.switch(
                        op.AND(
                            self.lambda_muonTightSel(self.muonsPreSel[i - 1]),
                            self.lambda_muonFakeSel(self.muonsPreSel[i - 1])),
                        op.c_int(1), op.c_int(0)),
                    op.c_int(-9999))  # mvasel encompasses fakeablesel
                varsToKeep["mu{}_isGenMatched".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    op.switch(self.lambda_is_matched(self.muonsPreSel[i - 1]),
                              op.c_int(1), op.c_int(0)), op.c_int(-9999))
                varsToKeep["mu{}_genPartFlav".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.muonsPreSel[i - 1].genPartFlav, op.c_int(-9999))
                varsToKeep["mu{}_FR".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.lambda_FR_mu(self.muonsPreSel[i - 1]),
                    op.c_int(-9999))
                varsToKeep["mu{}_FRcorr".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.lambda_FRcorr_mu(self.muonsPreSel[i - 1]),
                    op.c_int(-9999))
                varsToKeep["mu{}_FF".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.lambda_FF_mu(self.muonsPreSel[i - 1]),
                    op.c_int(-9999))
                varsToKeep["mu{}_looseSF".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    reduce(mul,
                           self.lambda_MuonLooseSF(self.muonsPreSel[i - 1])),
                    op.c_int(-9999))
                varsToKeep["mu{}_tightSF".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    reduce(mul,
                           self.lambda_MuonTightSF(self.muonsPreSel[i - 1])),
                    op.c_int(-9999))

            # Electrons #
            for i in range(1, 3):  # 2 leading electrons
                varsToKeep["ele{}_pt".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].pt, op.c_float(-9999.))
                varsToKeep["ele{}_eta".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].eta, op.c_float(-9999.))
                varsToKeep["ele{}_phi".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].phi, op.c_float(-9999.))
                varsToKeep["ele{}_E".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].p4.E(), op.c_float(-9999., ))
                varsToKeep["ele{}_charge".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].charge, op.c_int(-9999.))
                varsToKeep["ele{}_conept".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electron_conept[self.electronsPreSel[i - 1].idx],
                    op.c_float(-9999.))
                varsToKeep["ele{}_miniRelIso".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].miniPFRelIso_all,
                    op.c_float(-9999.))
                varsToKeep["ele{}_PFRelIso03".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].pfRelIso03_all,
                    op.c_float(-9999.))  # Iso03, Iso04 not in NanoAOD
                varsToKeep["ele{}_jetNDauChargedMVASel".format(
                    i)] = op.c_float(-9999.)
                varsToKeep["ele{}_jetPtRel".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].jetPtRelv2, op.c_float(-9999.))
                varsToKeep["ele{}_jetRelIso".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].jetRelIso, op.c_float(-9999.))
                varsToKeep["ele{}_jetDeepJet".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].jet.btagDeepFlavB,
                    op.c_float(-9999.))
                varsToKeep["ele{}_sip3D".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].sip3d, op.c_float(-9999.))

                varsToKeep["ele{}_dxy".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].dxy, op.c_float(-9999.))
                varsToKeep["ele{}_dxyAbs".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    op.abs(self.electronsPreSel[i - 1].dxy),
                    op.c_float(-9999.))
                varsToKeep["ele{}_dz".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].dz, op.c_float(-9999.))
                varsToKeep["ele{}_ntMVAeleID".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].mvaFall17V2noIso,
                    op.c_float(-9999.))
                varsToKeep["ele{}_leptonMVA".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].mvaTTH, op.c_float(-9999.))
                varsToKeep["ele{}_passesConversionVeto".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].convVeto,
                    op.c_float(-9999., "Bool_t"))
                varsToKeep["ele{}_nMissingHits".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].lostHits,
                    op.c_float(-9999., "UChar_t"))
                varsToKeep["ele{}_sigmaEtaEta".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].sieie, op.c_float(-9999.))
                varsToKeep["ele{}_HoE".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].hoe, op.c_float(-9999.))
                varsToKeep["ele{}_OoEminusOoP".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].eInvMinusPInv,
                    op.c_float(-9999.))
                varsToKeep["ele{}_isfakeablesel".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    op.switch(
                        self.lambda_electronFakeSel(self.electronsPreSel[i -
                                                                         1]),
                        op.c_int(1), op.c_int(0)), op.c_int(-9999))
                varsToKeep["ele{}_ismvasel".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    op.switch(
                        op.AND(
                            self.lambda_electronTightSel(
                                self.electronsPreSel[i - 1]),
                            self.lambda_electronFakeSel(
                                self.electronsPreSel[i - 1])), op.c_int(1),
                        op.c_int(0)),
                    op.c_int(-9999))  # mvasel encompasses fakeablesel
                varsToKeep["ele{}_isGenMatched".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    op.switch(
                        self.lambda_is_matched(self.electronsPreSel[i - 1]),
                        op.c_int(1), op.c_int(0)), op.c_int(-9999))
                varsToKeep["ele{}_genPartFlav".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].genPartFlav, op.c_int(-9999))
                varsToKeep["ele{}_deltaEtaSC".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.electronsPreSel[i - 1].deltaEtaSC, op.c_int(-9999))
                varsToKeep["ele{}_FR".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.lambda_FR_el(self.electronsPreSel[i - 1]),
                    op.c_int(-9999))
                varsToKeep["ele{}_FRcorr".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.lambda_FRcorr_el(self.electronsPreSel[i - 1]),
                    op.c_int(-9999))
                varsToKeep["ele{}_FF".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    self.lambda_FF_el(self.electronsPreSel[i - 1]),
                    op.c_int(-9999))
                varsToKeep["ele{}_looseSF".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    reduce(
                        mul,
                        self.lambda_ElectronLooseSF(self.electronsPreSel[i -
                                                                         1])),
                    op.c_int(-9999))
                varsToKeep["ele{}_tightSF".format(i)] = op.switch(
                    op.rng_len(self.electronsPreSel) >= i,
                    reduce(
                        mul,
                        self.lambda_ElectronTightSF(self.electronsPreSel[i -
                                                                         1])),
                    op.c_int(-9999))

            # AK4 Jets #
            for i in range(1, 5):  # 4 leading jets
                varsToKeep["ak4Jet{}_pt".format(i)] = op.switch(
                    op.rng_len(self.ak4Jets) >= i, self.ak4Jets[i - 1].pt,
                    op.c_float(-9999.))
                varsToKeep["ak4Jet{}_eta".format(i)] = op.switch(
                    op.rng_len(self.ak4Jets) >= i, self.ak4Jets[i - 1].eta,
                    op.c_float(-9999.))
                varsToKeep["ak4Jet{}_phi".format(i)] = op.switch(
                    op.rng_len(self.ak4Jets) >= i, self.ak4Jets[i - 1].phi,
                    op.c_float(-9999.))
                varsToKeep["ak4Jet{}_E".format(i)] = op.switch(
                    op.rng_len(self.ak4Jets) >= i, self.ak4Jets[i - 1].p4.E(),
                    op.c_float(-9999.))
                varsToKeep["ak4Jet{}_CSV".format(i)] = op.switch(
                    op.rng_len(self.ak4Jets) >= i,
                    self.ak4Jets[i - 1].btagDeepFlavB, op.c_float(-9999.))
                varsToKeep["ak4Jet{}_hadronFlavour".format(i)] = op.switch(
                    op.rng_len(self.ak4Jets) >= i,
                    self.ak4Jets[i - 1].hadronFlavour, op.c_float(-9999.))
                varsToKeep["ak4Jet{}_btagSF".format(i)] = op.switch(
                    op.rng_len(self.ak4Jets) >= i,
                    self.DeepJetDiscReshapingSF(self.ak4Jets[i - 1]),
                    op.c_float(-9999.))
                varsToKeep["ak4Jet{}_puid_eff".format(i)] = op.switch(
                    op.rng_len(self.ak4Jets) >= i,
                    self.jetpuid_mc_eff(self.ak4Jets[i - 1]),
                    op.c_float(-9999.))
                varsToKeep["ak4Jet{}_puid_sfeff".format(i)] = op.switch(
                    op.rng_len(self.ak4Jets) >= i,
                    self.jetpuid_sf_eff(self.ak4Jets[i - 1]),
                    op.c_float(-9999.))
                varsToKeep["ak4Jet{}_puid_mis".format(i)] = op.switch(
                    op.rng_len(self.ak4Jets) >= i,
                    self.jetpuid_mc_mis(self.ak4Jets[i - 1]),
                    op.c_float(-9999.))
                varsToKeep["ak4Jet{}_puid_sfmis".format(i)] = op.switch(
                    op.rng_len(self.ak4Jets) >= i,
                    self.jetpuid_sf_mis(self.ak4Jets[i - 1]),
                    op.c_float(-9999.))

            # VBF Jets #
            for i in range(1, 6):  # 5 leading jets
                varsToKeep["ak4JetVBF{}_pt".format(i)] = op.switch(
                    op.rng_len(self.VBFJetsPreSel) >= i,
                    self.VBFJetsPreSel[i - 1].pt, op.c_float(-9999.))
                varsToKeep["ak4JetVBF{}_eta".format(i)] = op.switch(
                    op.rng_len(self.VBFJetsPreSel) >= i,
                    self.VBFJetsPreSel[i - 1].eta, op.c_float(-9999.))
                varsToKeep["ak4JetVBF{}_phi".format(i)] = op.switch(
                    op.rng_len(self.VBFJetsPreSel) >= i,
                    self.VBFJetsPreSel[i - 1].phi, op.c_float(-9999.))
                varsToKeep["ak4JetVBF{}_E".format(i)] = op.switch(
                    op.rng_len(self.VBFJetsPreSel) >= i,
                    self.VBFJetsPreSel[i - 1].p4.E(), op.c_float(-9999.))
                varsToKeep["ak4JetVBF{}_CSV".format(i)] = op.switch(
                    op.rng_len(self.VBFJetsPreSel) >= i,
                    self.VBFJetsPreSel[i - 1].btagDeepFlavB,
                    op.c_float(-9999.))
                varsToKeep["ak4JetVBF{}_btagSF".format(i)] = op.switch(
                    op.rng_len(self.VBFJetsPreSel) >= i,
                    self.DeepJetDiscReshapingSF(self.VBFJetsPreSel[i - 1]),
                    op.c_float(-9999.))

            if not self.inclusive_sel:
                if not any([self.args.Res0b, self.args.Ak4, self.args.Ak8]):
                    varsToKeep["ak4JetVBFPair1_pt"] = op.switch(
                        op.rng_len(VBFJetPairsJPA) >= 1,
                        VBFJetPairsJPA[0][0].pt, op.c_float(-9999.))
                    varsToKeep["ak4JetVBFPair1_eta"] = op.switch(
                        op.rng_len(VBFJetPairsJPA) >= 1,
                        VBFJetPairsJPA[0][0].eta, op.c_float(-9999.))
                    varsToKeep["ak4JetVBFPair1_phi"] = op.switch(
                        op.rng_len(VBFJetPairsJPA) >= 1,
                        VBFJetPairsJPA[0][0].phi, op.c_float(-9999.))
                    varsToKeep["ak4JetVBFPair1_E"] = op.switch(
                        op.rng_len(VBFJetPairsJPA) >= 1,
                        VBFJetPairsJPA[0][0].p4.E(), op.c_float(-9999.))
                    varsToKeep["ak4JetVBFPair1_CSV"] = op.switch(
                        op.rng_len(VBFJetPairsJPA) >= 1,
                        VBFJetPairsJPA[0][0].btagDeepFlavB, op.c_float(-9999.))
                    varsToKeep["ak4JetVBFPair1_btagSF"] = op.switch(
                        op.rng_len(VBFJetPairsJPA) >= 1,
                        self.DeepJetDiscReshapingSF(VBFJetPairsJPA[0][0]),
                        op.c_float(-9999.))
                    varsToKeep["ak4JetVBFPair2_pt"] = op.switch(
                        op.rng_len(VBFJetPairsJPA) >= 1,
                        VBFJetPairsJPA[0][1].pt, op.c_float(-9999.))
                    varsToKeep["ak4JetVBFPair2_eta"] = op.switch(
                        op.rng_len(VBFJetPairsJPA) >= 1,
                        VBFJetPairsJPA[0][1].eta, op.c_float(-9999.))
                    varsToKeep["ak4JetVBFPair2_phi"] = op.switch(
                        op.rng_len(VBFJetPairsJPA) >= 1,
                        VBFJetPairsJPA[0][1].phi, op.c_float(-9999.))
                    varsToKeep["ak4JetVBFPair2_E"] = op.switch(
                        op.rng_len(VBFJetPairsJPA) >= 1,
                        VBFJetPairsJPA[0][1].p4.E(), op.c_float(-9999.))
                    varsToKeep["ak4JetVBFPair2_CSV"] = op.switch(
                        op.rng_len(VBFJetPairsJPA) >= 1,
                        VBFJetPairsJPA[0][1].btagDeepFlavB, op.c_float(-9999.))
                    varsToKeep["ak4JetVBFPair2_btagSF"] = op.switch(
                        op.rng_len(VBFJetPairsJPA) >= 1,
                        self.DeepJetDiscReshapingSF(VBFJetPairsJPA[0][1]),
                        op.c_float(-9999.))
                else:
                    varsToKeep["ak4JetVBFPair1_pt"] = op.c_float(-9999.)
                    varsToKeep["ak4JetVBFPair1_eta"] = op.c_float(-9999.)
                    varsToKeep["ak4JetVBFPair1_phi"] = op.c_float(-9999.)
                    varsToKeep["ak4JetVBFPair1_E"] = op.c_float(-9999.)
                    varsToKeep["ak4JetVBFPair1_CSV"] = op.c_float(-9999.)
                    varsToKeep["ak4JetVBFPair1_btagSF"] = op.c_float(-9999.)
                    varsToKeep["ak4JetVBFPair2_pt"] = op.c_float(-9999.)
                    varsToKeep["ak4JetVBFPair2_eta"] = op.c_float(-9999.)
                    varsToKeep["ak4JetVBFPair2_phi"] = op.c_float(-9999.)
                    varsToKeep["ak4JetVBFPair2_E"] = op.c_float(-9999.)
                    varsToKeep["ak4JetVBFPair2_CSV"] = op.c_float(-9999.)
                    varsToKeep["ak4JetVBFPair2_btagSF"] = op.c_float(-9999.)

            # AK8 Jets #
            for i in range(1, 3):  # 2 leading fatjets
                varsToKeep["ak8Jet{}_pt".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i, self.ak8BJets[i - 1].pt,
                    op.c_float(-9999.))
                varsToKeep["ak8Jet{}_eta".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i, self.ak8BJets[i - 1].eta,
                    op.c_float(-9999.))
                varsToKeep["ak8Jet{}_phi".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i, self.ak8BJets[i - 1].phi,
                    op.c_float(-9999.))
                varsToKeep["ak8Jet{}_E".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].p4.E(), op.c_float(-9999.))
                varsToKeep["ak8Jet{}_msoftdrop".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].msoftdrop, op.c_float(-9999.))
                varsToKeep["ak8Jet{}_tau1".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i, self.ak8BJets[i - 1].tau1,
                    op.c_float(-9999.))
                varsToKeep["ak8Jet{}_tau2".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i, self.ak8BJets[i - 1].tau2,
                    op.c_float(-9999.))
                varsToKeep["ak8Jet{}_subjet0_pt".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].subJet1.pt, op.c_float(-9999.))
                varsToKeep["ak8Jet{}_subjet0_eta".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].subJet1.eta, op.c_float(-9999.))
                varsToKeep["ak8Jet{}_subjet0_phi".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].subJet1.phi, op.c_float(-9999.))
                varsToKeep["ak8Jet{}_subjet0_CSV".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].subJet1.btagDeepB, op.c_float(-9999.))
                varsToKeep["ak8Jet{}_subjet1_pt".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].subJet2.pt, op.c_float(-9999.))
                varsToKeep["ak8Jet{}_subjet1_eta".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].subJet2.eta, op.c_float(-9999.))
                varsToKeep["ak8Jet{}_subjet1_phi".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].subJet2.phi, op.c_float(-9999.))
                varsToKeep["ak8Jet{}_subjet1_CSV".format(i)] = op.switch(
                    op.rng_len(self.ak8BJets) >= i,
                    self.ak8BJets[i - 1].subJet2.btagDeepB, op.c_float(-9999.))

            varsToKeep["PFMET"] = self.corrMET.pt
            varsToKeep["PFMETphi"] = self.corrMET.phi
            varsToKeep["met1_E"] = self.corrMET.p4.E()
            varsToKeep["met1_pt"] = self.corrMET.pt
            varsToKeep["met1_eta"] = self.corrMET.eta
            varsToKeep["met1_phi"] = self.corrMET.phi

            # SF #
            electronMuon_cont = op.combine(
                (self.electronsFakeSel, self.muonsFakeSel))

            varsToKeep["trigger_SF"] = op.multiSwitch(
                (op.AND(
                    op.rng_len(self.electronsTightSel) == 1,
                    op.rng_len(self.muonsTightSel) == 0),
                 self.ttH_singleElectron_trigSF(self.electronsTightSel[0])),
                (op.AND(
                    op.rng_len(self.electronsTightSel) == 0,
                    op.rng_len(self.muonsTightSel)
                    == 1), self.ttH_singleMuon_trigSF(self.muonsTightSel[0])),
                (op.AND(
                    op.rng_len(self.electronsTightSel) >= 2,
                    op.rng_len(self.muonsTightSel) == 0),
                 self.lambda_ttH_doubleElectron_trigSF(
                     self.electronsTightSel)),
                (op.AND(
                    op.rng_len(self.electronsTightSel) == 0,
                    op.rng_len(self.muonsTightSel) >= 2),
                 self.lambda_ttH_doubleMuon_trigSF(self.muonsTightSel)),
                (op.AND(
                    op.rng_len(self.electronsTightSel) >= 1,
                    op.rng_len(self.muonsTightSel) >= 1),
                 self.lambda_ttH_electronMuon_trigSF(electronMuon_cont[0])),
                op.c_float(1.))

            if not self.inclusive_sel:
                varsToKeep["weight_trigger_el_sf"] = op.switch(
                    op.rng_len(self.electronsTightSel) > 0,
                    self.ttH_singleElectron_trigSF(lep), op.c_float(1.))
                varsToKeep["weight_trigger_mu_sf"] = op.switch(
                    op.rng_len(self.muonsTightSel) > 0,
                    self.ttH_singleMuon_trigSF(lep), op.c_float(1.))

                varsToKeep["lepton_IDSF"] = op.rng_product(self.electronsFakeSel, lambda el : reduce(mul,self.lambda_ElectronLooseSF(el)+self.lambda_ElectronTightSF(el))) * \
                                            op.rng_product(self.muonsFakeSel, lambda mu : reduce(mul,self.lambda_MuonLooseSF(mu)+self.lambda_MuonTightSF(mu)))

                varsToKeep["lepton_IDSF_recoToLoose"]  = op.rng_product(self.electronsFakeSel, lambda el : reduce(mul,self.lambda_ElectronLooseSF(el))) * \
                                                        op.rng_product(self.muonsFakeSel, lambda mu : reduce(mul,self.lambda_MuonLooseSF(mu)))
                varsToKeep["lepton_IDSF_looseToTight"] = op.rng_product(self.electronsFakeSel, lambda el : reduce(mul,self.lambda_ElectronTightSF(el))) * \
                                                         op.rng_product(self.muonsFakeSel, lambda mu : reduce(mul,self.lambda_MuonTightSF(mu)))
                if era == "2016" or era == "2017":
                    if self.args.Channel == "El":
                        varsToKeep["weight_electron_reco_low"] = op.switch(
                            op.AND(self.lambda_is_matched(lep), lep.pt <= 20.),
                            self.elLooseRecoPtLt20(lep), op.c_float(1.))
                        varsToKeep["weight_electron_reco_high"] = op.switch(
                            op.AND(self.lambda_is_matched(lep), lep.pt > 20.),
                            self.elLooseRecoPtGt20(lep), op.c_float(1.))
                        varsToKeep["weight_muon_idiso_loose"] = op.c_float(1.)
                        varsToKeep["weight_electron_id_loose_01"] = op.switch(
                            self.lambda_is_matched(lep), self.elLooseEff(lep),
                            op.c_float(1.))
                        varsToKeep["weight_electron_id_loose_02"] = op.switch(
                            self.lambda_is_matched(lep), self.elLooseId(lep),
                            op.c_float(1.))
                        varsToKeep[
                            "weight_electron_tth_loose"] = self.lambda_ElectronTightSF(
                                lep)[0]
                        varsToKeep["weight_muon_tth_loose"] = op.c_float(1.)

                    if self.args.Channel == "Mu":
                        varsToKeep["weight_muon_idiso_loose"] = op.switch(
                            self.lambda_is_matched(lep), self.muLooseId(lep),
                            op.c_float(1.))
                        varsToKeep["weight_electron_reco_low"] = op.c_float(1.)
                        varsToKeep["weight_electron_reco_high"] = op.c_float(
                            1.)
                        varsToKeep["weight_electron_id_loose_01"] = op.c_float(
                            1.)
                        varsToKeep["weight_electron_id_loose_02"] = op.c_float(
                            1.)
                        varsToKeep["weight_electron_tth_loose"] = op.c_float(
                            1.)
                        varsToKeep[
                            "weight_muon_tth_loose"] = self.lambda_MuonTightSF(
                                lep)[0]
                else:
                    raise NotImplementedError

            # L1 Prefire #
            if era in ["2016", "2017"]:
                varsToKeep["L1prefire"] = self.L1Prefiring
                varsToKeep["weight_l1_ecal_prefiring"] = self.L1Prefiring
            else:
                varsToKeep["L1prefire"] = op.c_float(-9999.)
                varsToKeep["weight_l1_ecal_prefiring"] = op.c_float(-9999.)

            # Fake rate #
            if self.args.Channel == "El":
                varsToKeep["fakeRate"] = op.switch(
                    self.lambda_electronTightSel(self.electronsFakeSel[0]),
                    self.ElFakeFactor(self.electronsFakeSel[0]),
                    op.c_float(1.))
                varsToKeep["weight_fake_electrons"] = op.switch(
                    self.lambda_electronTightSel(self.electronsFakeSel[0]),
                    op.abs(self.ElFakeFactor(self.electronsFakeSel[0])),
                    op.c_float(1.))
                varsToKeep["weight_fake_muons"] = op.c_float(1.)
                varsToKeep["weight_fake_two_non_tight"] = op.c_float(999.0)
            if self.args.Channel == "Mu":
                varsToKeep["fakeRate"] = op.switch(
                    self.lambda_muonTightSel(self.muonsFakeSel[0]),
                    self.MuFakeFactor(self.muonsFakeSel[0]), op.c_float(1.))
                varsToKeep["weight_fake_electrons"] = op.c_float(1.)
                varsToKeep["weight_fake_muons"] = op.switch(
                    self.lambda_muonTightSel(self.muonsFakeSel[0]),
                    op.abs(self.MuFakeFactor(self.muonsFakeSel[0])),
                    op.c_float(1.))
                varsToKeep["weight_fake_two_non_tight"] = op.c_float(999.0)

            if self.is_MC:
                varsToKeep["weight_fake_is_mc"] = op.c_float(-1.)
            else:
                varsToKeep["weight_fake_is_mc"] = op.c_float(1.)

            # PU ID SF #
            varsToKeep["PU_jetID_SF"] = self.puid_reweighting
            varsToKeep[
                "weight_jet_PUid_efficiency"] = self.puid_reweighting_efficiency
            varsToKeep["weight_jet_PUid_mistag"] = self.puid_reweighting_mistag

            # Btagging SF #
            varsToKeep["btag_SF"] = self.btagAk4SF
            varsToKeep["weight_btagWeight"] = self.btagAk4SF
            if "BtagRatioWeight" in self.__dict__.keys():
                varsToKeep["btag_ratio_SF"] = self.BtagRatioWeight
                varsToKeep["weight_btagNorm"] = self.BtagRatioWeight

            # PS weights #
            varsToKeep["weight_PSWeight_ISR"] = self.psISRSyst
            varsToKeep["weight_PSWeight_FSR"] = self.psFSRSyst

            # ttbar PT reweighting #
            if "group" in sampleCfg and sampleCfg["group"] == 'ttbar':
                varsToKeep["topPt_wgt"] = self.ttbar_weight(
                    self.genTop[0], self.genAntitop[0])

        # Event Weight #
            if self.is_MC:
                varsToKeep["MC_weight"] = t.genWeight
                puWeightsFile = os.path.join(os.path.dirname(__file__), "data",
                                             "pileup",
                                             sample + '_%s.json' % era)
                #puWeightsFile = os.path.join(os.path.dirname(__file__), "data" , "pileup", sampleCfg["pufile"])
                varsToKeep["PU_weight"] = makePileupWeight(
                    puWeightsFile,
                    t.Pileup_nTrueInt,
                    nameHint=f"puweightFromFile{sample}".replace('-', '_'))
                varsToKeep[
                    "eventWeight"] = noSel.weight if self.inclusive_sel else selObj.sel.weight

            if self.inclusive_sel:
                return noSel, varsToKeep
            else:
                return selObj.sel, varsToKeep

        #---------------------------------------------------------------------------------------#
        #                                    Selection tree                                     #
        #---------------------------------------------------------------------------------------#
        #----- EVT variables -----#
        varsToKeep["event"] = None  # Already in tree
        varsToKeep["run"] = None  # Already in tree
        varsToKeep["ls"] = t.luminosityBlock

        genVarsList = self.HLL.comp_cosThetaSbetBeamAndHiggs(t.GenPart)
        varsToKeep['mHH_gen'] = genVarsList[0]
        varsToKeep['consTheta1_gen'] = genVarsList[1]
        varsToKeep['consTheta2_gen'] = genVarsList[2]

        if any([
                self.args.__dict__[item] for item in [
                    "Ak4", "Res2b2Wj", "Res2b1Wj", "Res2b0Wj", "Res1b2Wj",
                    "Res1b1Wj", "Res1b0Wj", "Res0b"
                ]
        ]):
            commonInputs_Resolved = returnCommonInputs_Resolved(self=self)
            classicInputs_Resolved = returnClassicInputs_Resolved(
                self=self,
                lepton=lep,
                jpaSelectedJets=jpaJets,
                L1out=L1out,
                L2out=L2out,
                jpaArg=jpaarg)
            inputs_resolved = {
                **commonInputs_Resolved,
                **classicInputs_Resolved
            }

            for (varname, _, _), var in inputs_resolved.items():
                varsToKeep[varname] = var

        #----- Fatjet variables -----#
        if any([
                self.args.__dict__[item]
                for item in ["Ak8", "Hbb2Wj", "Hbb1Wj", "Hbb0Wj"]
        ]):
            commonInputs_Boosted = returnCommonInputs_Boosted(self=self)
            classicInputs_Boosted = returnClassicInputs_Boosted(
                self=self,
                lepton=lep,
                jpaSelectedJets=jpaJets,
                L1out=L1out,
                L2out=L2out,
                jpaArg=jpaarg)
            inputs_boosted = {**commonInputs_Boosted, **classicInputs_Boosted}

            for (varname, _, _), var in inputs_boosted.items():
                varsToKeep[varname] = var

        #----- Additional variables -----#
        varsToKeep["MC_weight"] = t.genWeight
        varsToKeep['total_weight'] = selObj.sel.weight

        #return leptonSel.sel, varsToKeep
        return selObj.sel, varsToKeep
    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