Ejemplo n.º 1
0
def MakeEllipsesPLots(self, sel, bjets, lepton, wp, uname, suffix):
    plots = []
    binScaling = 1
    for key in sel.keys():

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

        plots.append(
            Plot.make1D(
                "jj_M_{0}_{1}_hZA_lljj_{2}_mll_and_met_cut".format(
                    suffix, uname, key),
                op.invariant_mass(bjets_[0].p4, bjets_[1].p4),
                sel.get(key),
                EqB(60 // binScaling, 0., 1000.),
                title="invariant mass of two b-tagged jets wrt {0} Discriminator"
                .format(suffix, key),
                xTitle="mjj {0} {1} [GeV]".format(suffix, key),
                plotopts=utils.getOpts(uname, **{"log-y": False})))

        plots.append(
            Plot.make1D(
                "lljj_M_{0}_{1}_hZA_lljj_{2}_mll_and_met_cut".format(
                    suffix, uname, key), (lepton[0].p4 + lepton[1].p4 +
                                          bjets_[0].p4 + bjets_[1].p4).M(),
                sel.get(key),
                EqB(60 // binScaling, 0., 1000.),
                title=
                "invariant mass of 2 leptons two b-tagged jets wrt {0} Discriminator"
                .format(suffix, key),
                xTitle="mlljj {0} {1} [GeV]".format(suffix, key),
                plotopts=utils.getOpts(uname, **{"log-y": False})))

        plots.append(
            Plot.make2D(
                "Mjj_vs_Mlljj_{0}_{1}_hZA_lljj_{2}_mll_and_met_cut".format(
                    suffix, uname,
                    key), (op.invariant_mass(bjets_[0].p4, bjets_[1].p4),
                           (lepton[0].p4 + lepton[1].p4 + bjets_[0].p4 +
                            bjets_[1].p4).M()),
                sel.get(key), (EqB(60 // binScaling, 0.,
                                   1000.), EqB(60 // binScaling, 0., 1000.)),
                title="mlljj vs mjj invariant mass {0} wrt {1} Discriminator".
                format(suffix, key),
                plotopts=utils.getOpts(uname, **{"log-y": False})))

        plots.append(
            Plot.make1D(
                "ll_M_{0}_{1}_hZA_lljj_{2}_mll_and_met_cut".format(
                    suffix, uname, key),
                op.invariant_mass(lepton[0].p4, lepton[1].p4),
                sel.get(key),
                EqB(60 // binScaling, 70., 110.),
                title=" dilepton invariant mass {0} wrt {1} Discriminator".
                format(suffix, key),
                xTitle="mll {0} {1} [GeV]".format(suffix, key),
                plotopts=utils.getOpts(uname)))
    return plots
Ejemplo n.º 2
0
    def definePlots(self, t, noSel, sample=None, sampleCfg=None):
        from bamboo.plots import Plot, CutFlowReport, SummedPlot
        from bamboo.plots import EquidistantBinning as EqB
        from bamboo import treefunctions as op

        isMC = self.isMC(sample)
        if isMC:
            noSel = noSel.refine("mcWeight", weight=[t.genWeight])
        noSel = noSel.refine(
            "trig",
            cut=op.OR(t.HLT.HIL3DoubleMu0,
                      t.HLT.HIEle20_Ele12_CaloIdL_TrackIdL_IsoVL_DZ))

        plots = []

        muons = op.select(t.Muon, lambda mu: mu.pt > 20.)
        twoMuSel = noSel.refine("twoMuons", cut=[op.rng_len(muons) > 1])
        plots.append(
            Plot.make1D("dimu_M",
                        op.invariant_mass(muons[0].p4, muons[1].p4),
                        twoMuSel,
                        EqB(100, 20., 120.),
                        title="Dimuon invariant mass",
                        plotopts={
                            "show-overflow": False,
                            "legend-position": [0.2, 0.6, 0.5, 0.9]
                        }))

        return plots
Ejemplo n.º 3
0
def makeControlPlotsForZpic(self, sel, lepton, uname):
    plots = []
    for i in range(2):
        if "mu" in uname:
            flav = "Muon"
        if "el" in uname:
            flav = "Electron"

        plots.append(
            Plot.make1D(f"{uname}_lep{i+1}_pt",
                        lepton[i].pt,
                        sel,
                        EqB(60 // binScaling, 30., 530.),
                        title="%s p_{T} [GeV]" % flav,
                        plotopts=utils.getOpts(uname)))
        plots.append(
            Plot.make1D(f"{uname}_lep{i+1}_eta",
                        lepton[i].eta,
                        sel,
                        EqB(50 // binScaling, -2.4, 2.4),
                        title="%s eta" % flav,
                        plotopts=utils.getOpts(uname, **{"log-y": False})))
        plots.append(
            Plot.make1D(f"{uname}_lep{i+1}_phi",
                        lepton[i].phi,
                        sel,
                        EqB(50 // binScaling, -3.1416, 3.1416),
                        title="%s phi" % flav,
                        plotopts=utils.getOpts(uname, **{"log-y": False})))

        plots.append(
            Plot.make1D("{0}_mll".format(uname),
                        op.invariant_mass(lepton[0].p4, lepton[1].p4),
                        sel,
                        EqB(60, 70., 110.),
                        title="mll [GeV]",
                        plotopts=utils.getOpts(uname)))
        plots.append(
            Plot.make1D("{0}_llpT".format(uname),
                        (dilepton[0].p4 + dilepton[1].p4).Pt(),
                        sel,
                        EqB(60, 0., 450.),
                        title="dilepton P_{T} [GeV]",
                        plotopts=utils.getOpts(uname)))
    # FIXME
    #plots.append(Plot.make1D("{0}_nVX".format(uname),
    #            t.PV.npvs, sel,
    #            EqB(10, 0., 60.),
    #            title="Distrubtion of the number of the reconstructed vertices",
    #            xTitle="number of reconstructed vertices "))
    #plots.append(Plot.make2D("{0}_Electron_dzdxy".format(uname),
    #            (lepton[0].dz ,lepton[0].dxy), sel,
    #            (EqB(10, 0., 2.),
    #            EqB(10, 0., 2.)) ,
    #            title="Electron in Barrel/EndCAP region" ))
    return plots
Ejemplo n.º 4
0
def makeControlPlotsForFinalSel(self, sel, bjets, dilepton, uname):
    plots = []
    binScaling = 1
    for key in sel.keys():

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

        plots.append(
            Plot.make1D("{0}_TwoBtaggedJets_pT_{1}".format(uname, key),
                        (bjets_[0].p4 + bjets_[1].p4).Pt(),
                        sel.get(key),
                        EqB(60, 170., 800.),
                        title="di-bjet P_{T} [GeV]",
                        plotopts=utils.getOpts(uname)))

        plots.append(
            Plot.make1D("{0}_mlljj_btagged_{1}".format(uname, key),
                        (lepton[0].p4 + lepton[1].p4 + bjets_[0].p4 +
                         bjets_[1].p4).M(),
                        sel.get(key),
                        EqB(60, 170., 1000.),
                        title="mlljj [GeV]",
                        plotopts=utils.getOpts(uname)))

        plots.append(
            Plot.make1D("{0}_mjj_btagged_{1}".format(uname, key),
                        op.invariant_mass(bjets_[0].p4 + bjets_[1].p4),
                        sel.get(key),
                        EqB(60, 170., 800.),
                        title="mjj [GeV]",
                        plotopts=utils.getOpts(uname)))

        plots.append(
            Plot.make2D("{0}_mlljjvsmjj_btagged_{1}".format(uname, key),
                        (op.invariant_mass(bjets_[0].p4 + bjets_[1].p4),
                         (lepton[0].p4 + lepton[1].p4 + bjets_[0].p4 +
                          bjets_[1].p4).M()),
                        sel.get(key),
                        (EqB(60, 170., 1000.), EqB(60, 170., 1000.)),
                        title="mlljj vs mjj invariant mass [GeV]",
                        plotopts=utils.getOpts(uname)))
    return plots
Ejemplo n.º 5
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
def makehistosforTTbarEstimation(selections, ll, bjets, wp, met, suffix,
                                 uname):
    plots = []
    for key, sel in selections.items():
        tagger = key.replace(wp, "")
        bjets_ = safeget(bjets, tagger, wp)
        bb = bjets[key.replace(wp, "")][wp]
        plots += [
            Plot.make1D(
                f"{nm}_{uname}_{suffix}_jets_{tagger}_btag{wp}_mll_and_{met}",
                llbbVar,
                sel,
                binning,
                title=title,
                plotopts=utils.getOpts(uname))
            for nm, (llbbVar, binning, title) in {
                "jj_M": (op.invariant_mass(bb[0].p4 + bb[1].p4),
                         EqBin(40, 10., 1000.), "Mjj [GeV]"),
                "lljj_M": ((ll[0].p4 + ll[1].p4 + bb[0].p4 + bb[1].p4).M(),
                           EqBin(50, 100., 1500.), "Mlljj [GeV]"),
                "ll_M": (op.invariant_mass(ll[0].p4 + ll[1].p4),
                         EqBin(60, 70., 120.), "Mll [GeV]"),
                "jj_DR": (op.deltaR(bb[0].p4, bb[1].p4), EqBin(50, 0., 6.),
                          "jj deltaR"),
                "jj_pt": ((bjets_[0].p4 + bjets_[1].p4).Pt(),
                          EqBin(50, 0., 450.), "dijets p_{T} [GeV]"),
                "jet1_pt": (bb[0].pt, EqBin(50, 20., 500.),
                            "jet1 p_{T} [GeV]"),
                "jet2_pt": (bb[1].pt, EqBin(50, 20., 300.),
                            "jet2 p_{T} [GeV]"),
                "lep1_pt": (ll[0].pt, EqBin(50, 20., 400.),
                            "Leading Lepton p_{T} [GeV]"),
                "lep2_pt": (ll[1].pt, EqBin(50, 10., 200.),
                            "Sub-leading Lepton p_{T} [GeV]"),
            }.items()
        ]
    return plots
Ejemplo n.º 7
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
Ejemplo n.º 8
0
    def definePlots(self, tree, noSel, sample=None, sampleCfg=None):
        from bamboo.plots import Plot, SummedPlot
        from bamboo.plots import EquidistantBinning as EqBin
        from bamboo import treefunctions as op

        plots = []

        # 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
Ejemplo n.º 9
0
def makeResolvedJetPlots(self, sel, jets, uname):
    maxJet = 2
    binScaling = 1
    plots = []
    for i in range(maxJet):
        plots.append(
            Plot.make1D(f"{uname}_jet{i+1}_pt",
                        jets[i].pt,
                        sel,
                        EqB(60 // binScaling, 30., 730. - max(4, i) * 100),
                        title=f"{utils.getCounter(i+1)} jet p_{{T}} [GeV]",
                        plotopts=utils.getOpts(uname)))
        plots.append(
            Plot.make1D(f"{uname}_jet{i+1}_eta",
                        jets[i].eta,
                        sel,
                        EqB(50 // binScaling, -2.4, 2.4),
                        title=f"{utils.getCounter(i+1)} jet eta",
                        plotopts=utils.getOpts(uname, **{"log-y": False})))
        plots.append(
            Plot.make1D(f"{uname}_jet{i+1}_phi",
                        jets[i].phi,
                        sel,
                        EqB(50 // binScaling, -3.1416, 3.1416),
                        title=f"{utils.getCounter(i+1)} jet phi",
                        plotopts=utils.getOpts(uname, **{"log-y": False})))

    plots.append(
        Plot.make1D(f"{uname}_jet_DR",
                    op.deltaR(jets[0].p4, jets[1].p4),
                    sel,
                    EqB(50, 0.3, 3.),
                    title="Jets DR",
                    plotopts=utils.getOpts(uname, **{"log-y": False})))
    plots.append(
        Plot.make1D(f"{uname}_jet_M",
                    op.invariant_mass(jets[0].p4, jets[1].p4),
                    sel,
                    EqB(60, 0., 400.),
                    title="dijets invariant mass [GeV]",
                    plotopts=utils.getOpts(uname)))
    plots.append(
        Plot.make1D(f"{uname}_jet_pT", (jets[0].p4 + jets[1].p4).Pt(),
                    sel,
                    EqB(60, 0., 600.),
                    title=" dijets p_{T} [GeV]",
                    plotopts=utils.getOpts(uname)))
    return plots
Ejemplo n.º 10
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
Ejemplo n.º 11
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]
Ejemplo n.º 12
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
Ejemplo n.º 13
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
    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
Ejemplo n.º 15
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.))
        ]
    }
Ejemplo n.º 16
0
    def defineSkimSelection(self, t, noSel, sample=None, sampleCfg=None):
        noSel = super(SkimmerNanoHHtobbWWDL,
                      self).prepareObjects(t,
                                           noSel,
                                           sample,
                                           sampleCfg,
                                           "DL",
                                           forSkimmer=True)
        # For the Skimmer, SF must not use defineOnFirstUse -> segmentation fault

        era = sampleCfg['era']

        #self.datadrivenContributions = {} # Avoid all data-driven estimates

        # Initialize varsToKeep dict #
        varsToKeep = dict()

        #---------------------------------------------------------------------------------------#
        #                                     Selections                                        #
        #---------------------------------------------------------------------------------------#
        if not self.inclusive_sel:
            #----- Check arguments -----#
            lepton_level = [
                "Preselected", "Fakeable", "Tight", "FakeExtrapolation"
            ]  # Only one must be in args
            jet_level = [
                "Ak4", "Ak8", "Resolved0Btag", "Resolved1Btag",
                "Resolved2Btag", "Boosted"
            ]  # Only one must be in args

            if [
                    boolean for (level, boolean) in self.args.__dict__.items()
                    if level in lepton_level
            ].count(True) != 1:
                raise RuntimeError(
                    "Only one of the lepton arguments must be used, check --help"
                )
            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 ["ElEl", "MuMu", "ElMu"]:
                raise RuntimeError(
                    "Channel must be either 'ElEl', 'MuMu' or 'ElMu'")

            #----- Lepton selection -----#
            # Args are passed within the self #
            selLeptonDict = makeDoubleLeptonSelection(self,
                                                      noSel,
                                                      use_dd=False)
            # makeDoubleLeptonSelection returns dict -> value is list of three selections for 3 channels
            # [0] -> we take the first and only key and value because restricted to one lepton selection
            selLeptonList = list(selLeptonDict.values())[0]
            if self.args.Channel == "ElEl":
                selObj = selLeptonList[
                    0]  # First item of list is ElEl selection
            if self.args.Channel == "MuMu":
                selObj = selLeptonList[
                    1]  # Second item of list is MuMu selection
            if self.args.Channel == "ElMu":
                selObj = selLeptonList[
                    2]  # Third item of list is ElMu selection

            #----- Jet selection -----#
            # Since the selections in one line, we can use the non copy option of the selection to modify the selection object internally
            if any([
                    self.args.__dict__[item] for item in
                ["Ak4", "Resolved0Btag", "Resolved1Btag", "Resolved2Btag"]
            ]):
                makeAtLeastTwoAk4JetSelection(self, selObj, use_dd=False)
            if any([self.args.__dict__[item] for item in ["Ak8", "Boosted"]]):
                makeAtLeastOneAk8JetSelection(self, selObj, use_dd=False)
            if self.args.Resolved0Btag:
                makeExclusiveResolvedNoBtagSelection(self,
                                                     selObj,
                                                     use_dd=False)
            if self.args.Resolved1Btag:
                makeExclusiveResolvedOneBtagSelection(self,
                                                      selObj,
                                                      use_dd=False)
            if self.args.Resolved2Btag:
                makeExclusiveResolvedTwoBtagsSelection(self,
                                                       selObj,
                                                       use_dd=False)
            if self.args.Boosted:
                makeInclusiveBoostedSelection(self, selObj, use_dd=False)

        #---------------------------------------------------------------------------------------#
        #                                 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.ak8BJets))
            varsToKeep["n_medium_ak4BJet"] = op.static_cast(
                "UInt_t", op.rng_len(self.ak4BJets))
            varsToKeep["is_SR"] = op.static_cast(
                "UInt_t",
                op.OR(
                    op.rng_len(self.ElElDileptonTightSel) >= 1,
                    op.rng_len(self.MuMuDileptonTightSel) >= 1,
                    op.rng_len(self.ElMuDileptonTightSel) >= 1))
            varsToKeep["is_CR"] = op.static_cast(
                "UInt_t",
                op.OR(
                    op.rng_len(self.ElElDileptonFakeExtrapolationSel) >= 1,
                    op.rng_len(self.MuMuDileptonFakeExtrapolationSel) >= 1,
                    op.rng_len(self.ElMuDileptonFakeExtrapolationSel) >= 1))
            varsToKeep["is_ee"] = op.static_cast(
                "UInt_t",
                op.OR(
                    op.rng_len(self.ElElDileptonTightSel) >= 1,
                    op.rng_len(self.ElElDileptonFakeExtrapolationSel) >= 1))
            varsToKeep["is_mm"] = op.static_cast(
                "UInt_t",
                op.OR(
                    op.rng_len(self.MuMuDileptonTightSel) >= 1,
                    op.rng_len(self.MuMuDileptonFakeExtrapolationSel) >= 1))
            varsToKeep["is_em"] = op.static_cast(
                "UInt_t",
                op.OR(
                    op.rng_len(self.ElMuDileptonTightSel) >= 1,
                    op.rng_len(self.ElMuDileptonFakeExtrapolationSel) >= 1))
            varsToKeep["is_resolved"] = op.switch(
                op.AND(
                    op.rng_len(self.ak4Jets) >= 2,
                    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.rng_len(self.ak8BJets) >= 1, op.c_bool(True),
                op.c_bool(False))

            # Triggers #
            varsToKeep['n_leadfakeableSel_ele'] = op.static_cast(
                "UInt_t", op.rng_len(self.leadElectronsFakeSel))
            varsToKeep['n_leadfakeableSel_mu'] = op.static_cast(
                "UInt_t", op.rng_len(self.leadMuonsFakeSel))
            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.muonFR(self.muonsPreSel[i - 1]), op.c_int(-9999))
                varsToKeep["mu{}_FRCorr".format(i)] = op.switch(
                    op.rng_len(self.muonsPreSel) >= i,
                    self.lambda_FF_mu(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., "float"))
                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.electronFR(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))

            # 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., "float"))
                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., "float"))
                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.))

            # 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., "float"))
                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.))

            # MET #

            varsToKeep["PFMET"] = self.corrMET.pt
            varsToKeep["PFMETphi"] = self.corrMET.phi

            # HME #

            # SF #
            from operator import mul
            from functools import reduce

            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.))

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

            varsToKeep["lepton_IDSF_recoToLoose"] = op.rng_product(self.electronsTightSel, lambda el : reduce(mul,self.lambda_ElectronLooseSF(el))) * \
                                                    op.rng_product(self.muonsTightSel, lambda mu : reduce(mul,self.lambda_MuonLooseSF(mu)))
            varsToKeep["lepton_IDSF_looseToTight"] = op.rng_product(self.electronsTightSel, lambda el : reduce(mul,self.lambda_ElectronTightSF(el))) * \
                                                     op.rng_product(self.muonsTightSel, lambda mu : reduce(mul,self.lambda_MuonTightSF(mu)))

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

            # Fake rate #
            if self.args.FakeExtrapolation:
                varsToKeep["fakeRate"] = op.multiSwitch(
                    (op.rng_len(self.ElElDileptonFakeExtrapolationSel) >= 1,
                     self.ElElFakeFactor(
                         self.ElElDileptonFakeExtrapolationSel[0])),
                    (op.rng_len(self.MuMuDileptonFakeExtrapolationSel) >= 1,
                     self.MuMuFakeFactor(
                         self.MuMuDileptonFakeExtrapolationSel[0])),
                    (op.rng_len(self.ElMuDileptonFakeExtrapolationSel) >= 1,
                     self.ElMuFakeFactor(
                         self.ElMuDileptonFakeExtrapolationSel[0])),
                    op.c_float(0.))
            else:
                varsToKeep["fakeRate"] = op.c_float(-9999.)

            # Btagging SF #
            varsToKeep["btag_SF"] = self.btagSF
            if "BtagRatioWeight" in self.__dict__.keys():
                varsToKeep["btag_reweighting"] = self.BtagRatioWeight
                varsToKeep[
                    "btag_reweighting_SF"] = self.btagSF * self.BtagRatioWeight

            # 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"] = op.sign(t.genWeight)
                varsToKeep["MC_weight"] = t.genWeight
                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                                     #
        #---------------------------------------------------------------------------------------#

        #----- MET variables -----#
        MET = self.corrMET

        varsToKeep['MET_pt'] = MET.pt
        varsToKeep['MET_phi'] = MET.phi

        #----- Lepton variables -----#
        if self.args.Channel is None:
            raise RuntimeError("You need to specify --Channel")
        dilepton = None
        if self.args.Preselected:
            if self.args.Channel == "ElEl":
                dilepton = self.ElElDileptonPreSel[0]
            if self.args.Channel == "MuMu":
                dilepton = self.MuMuDileptonPreSel[0]
            if self.args.Channel == "ElMu":
                dilepton = self.ElMuDileptonPreSel[0]
        if self.args.Fakeable:
            if self.args.Channel == "ElEl":
                dilepton = self.ElElDileptonFakeSel[0]
            if self.args.Channel == "MuMu":
                dilepton = self.MuMuDileptonFakeSel[0]
            if self.args.Channel == "ElMu":
                dilepton = self.ElMuDileptonFakeSel[0]
        if self.args.Tight:
            if self.args.Channel == "ElEl":
                dilepton = self.ElElDileptonTightSel[0]
            if self.args.Channel == "MuMu":
                dilepton = self.MuMuDileptonTightSel[0]
            if self.args.Channel == "ElMu":
                dilepton = self.ElMuDileptonTightSel[0]
        if self.args.FakeExtrapolation:
            if self.args.Channel == "ElEl":
                dilepton = self.ElElDileptonFakeExtrapolationSel[0]
            if self.args.Channel == "MuMu":
                dilepton = self.MuMuDileptonFakeExtrapolationSel[0]
            if self.args.Channel == "ElMu":
                dilepton = self.ElMuDileptonFakeExtrapolationSel[0]

        varsToKeep['l1_Px'] = dilepton[0].p4.Px()
        varsToKeep['l1_Py'] = dilepton[0].p4.Py()
        varsToKeep['l1_Pz'] = dilepton[0].p4.Pz()
        varsToKeep['l1_E'] = dilepton[0].p4.E()
        varsToKeep['l1_pt'] = dilepton[0].pt
        varsToKeep['l1_eta'] = dilepton[0].eta
        varsToKeep['l1_phi'] = dilepton[0].phi

        varsToKeep['l2_Px'] = dilepton[1].p4.Px()
        varsToKeep['l2_Py'] = dilepton[1].p4.Py()
        varsToKeep['l2_Pz'] = dilepton[1].p4.Pz()
        varsToKeep['l2_E'] = dilepton[1].p4.E()
        varsToKeep['l2_pt'] = dilepton[1].pt
        varsToKeep['l2_eta'] = dilepton[1].eta
        varsToKeep['l2_phi'] = dilepton[1].phi

        varsToKeep['ll_pt'] = (dilepton[0].p4 + dilepton[1].p4).Pt()
        varsToKeep['ll_DR'] = op.deltaR(dilepton[0].p4, dilepton[1].p4)
        varsToKeep['ll_DPhi'] = op.deltaPhi(dilepton[0].p4,
                                            dilepton[1].p4)  # Might need abs

        varsToKeep['llmet_DPhi'] = self.HLL.DilepMET_deltaPhi(
            dilepton[0], dilepton[1], MET)
        varsToKeep['llmet_pt'] = self.HLL.DilepMET_Pt(dilepton[0], dilepton[1],
                                                      MET)

        varsToKeep['ll_M'] = op.invariant_mass(dilepton[0].p4, dilepton[1].p4)
        varsToKeep['ll_MT'] = self.HLL.MT_ll(dilepton[0], dilepton[1], MET)

        #----- Jet variables -----#
        if any([
                self.args.__dict__[item] for item in
            ["Ak4", "Resolved0Btag", "Resolved1Btag", "Resolved2Btag"]
        ]):
            if self.args.Ak4:
                leadjet = self.ak4Jets[0]
                subleadjet = self.ak4Jets[1]
            if self.args.Resolved0Btag:
                leadjet = self.ak4LightJetsByBtagScore[0]
                subleadjet = self.ak4LightJetsByBtagScore[0]
            if self.args.Resolved1Btag:
                leadjet = self.ak4BJets[0]
                subleadjet = self.ak4LightJetsByBtagScore[0]
            if self.args.Resolved2Btag:
                leadjet = self.ak4BJets[0]
                subleadjet = self.ak4BJets[1]

            varsToKeep['j1_Px'] = leadjet.p4.Px()
            varsToKeep['j1_Py'] = leadjet.p4.Py()
            varsToKeep['j1_Pz'] = leadjet.p4.Pz()
            varsToKeep['j1_E'] = leadjet.p4.E()
            varsToKeep['j1_pt'] = leadjet.pt
            varsToKeep['j1_eta'] = leadjet.eta
            varsToKeep['j1_phi'] = leadjet.phi

            varsToKeep['j2_Px'] = subleadjet.p4.Px()
            varsToKeep['j2_Py'] = subleadjet.p4.Py()
            varsToKeep['j2_Pz'] = subleadjet.p4.Pz()
            varsToKeep['j2_E'] = subleadjet.p4.E()
            varsToKeep['j2_pt'] = subleadjet.pt
            varsToKeep['j2_eta'] = subleadjet.eta
            varsToKeep['j2_phi'] = subleadjet.phi

            varsToKeep['jj_pt'] = (leadjet.p4 + subleadjet.p4).Pt()
            varsToKeep['jj_DR'] = op.deltaR(leadjet.p4, subleadjet.p4)
            varsToKeep['jj_DPhi'] = op.deltaPhi(
                leadjet.p4, subleadjet.p4)  # Might need abs
            varsToKeep['jj_M'] = op.invariant_mass(leadjet.p4, subleadjet.p4)

            varsToKeep['lljj_M'] = self.HLL.M_lljj(dilepton[0], dilepton[1],
                                                   leadjet, subleadjet)
            varsToKeep['lljj_MT'] = self.HLL.MT_lljj(dilepton[0], dilepton[1],
                                                     leadjet, subleadjet, MET)
            varsToKeep['lj_MinDR'] = self.HLL.MinDR_lj(dilepton[0],
                                                       dilepton[1], leadjet,
                                                       subleadjet)
            varsToKeep['HT2'] = self.HLL.HT2(dilepton[0], dilepton[1], leadjet,
                                             subleadjet, MET)
            varsToKeep['HT2R'] = self.HLL.HT2R(dilepton[0], dilepton[1],
                                               leadjet, subleadjet, MET)

        #----- Fatjet variables -----#
        if any([self.args.__dict__[item] for item in ["Ak8", "Boosted"]]):
            if self.args.Ak8:
                fatjet = self.ak8Jets[0]
            if self.args.Boosted:
                fatjet = self.ak8BJets[0]

            varsToKeep['fatjet_Px'] = fatjet.p4.Px()
            varsToKeep['fatjet_Py'] = fatjet.p4.Py()
            varsToKeep['fatjet_Pz'] = fatjet.p4.Pz()
            varsToKeep['fatjet_E'] = fatjet.p4.E()
            varsToKeep['fatjet_pt'] = fatjet.pt
            varsToKeep['fatjet_eta'] = fatjet.eta
            varsToKeep['fatjet_phi'] = fatjet.phi
            varsToKeep['fatjet_softdropMass'] = fatjet.msoftdrop

            varsToKeep['lljj_M'] = self.HLL.M_lljj(dilepton[0], dilepton[1],
                                                   fatjet.subJet1,
                                                   fatjet.subJet2)
            varsToKeep['lljj_MT'] = self.HLL.MT_lljj(dilepton[0], dilepton[1],
                                                     fatjet.subJet1,
                                                     fatjet.subJet2, MET)
            varsToKeep['lj_MinDR'] = self.HLL.MinDR_lj(dilepton[0],
                                                       dilepton[1],
                                                       fatjet.subJet1,
                                                       fatjet.subJet2)
            varsToKeep['HT2'] = self.HLL.HT2(dilepton[0], dilepton[1],
                                             fatjet.subJet1, fatjet.subJet2,
                                             MET)
            varsToKeep['HT2R'] = self.HLL.HT2R(dilepton[0], dilepton[1],
                                               fatjet.subJet1, fatjet.subJet2,
                                               MET)

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

        #return leptonSel.sel, varsToKeep
        return selObj.sel, varsToKeep
Ejemplo n.º 17
0
    def definePlots(self, tree, noSel, sample=None, sampleCfg=None):
        plots = []

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

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

        mZ = 91.1876

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

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

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

        return plots
Ejemplo n.º 18
0
def makeDileptonPlots(self, sel, dilepton, suffix, channel):
    """
    Make dilepton basic plots
    sel         = refine selection 
    dilepton    = dilepton object (ElEl, MuEl, ElMu, MuMu)
    suffix      = string identifying the selecton 
    channel     = string identifying the channel of the dilepton (can be "NoChannel")
    """
    plots = []
    # PT plot #
    plots.append(
        Plot.make1D(
            "%s_leadleptonPT_%s" % (channel, suffix),
            dilepton[0].p4.Pt(),
            sel,
            EquidistantBinning(100, 0., 150.),
            title="Transverse momentum of the leading lepton (channel %s)" %
            channel,
            xTitle="P_{T}(leading lepton) [GeV]"))
    plots.append(
        Plot.make1D(
            "%s_subleadleptonPT_%s" % (channel, suffix),
            dilepton[1].p4.Pt(),
            sel,
            EquidistantBinning(100, 0., 150.),
            title="Transverse momentum of the subleading lepton (channel %s)" %
            channel,
            xTitle="P_{T}(leading lepton) [GeV]"))

    # Eta plot #
    plots.append(
        Plot.make1D("%s_leadleptonEta_%s" % (channel, suffix),
                    dilepton[0].p4.Eta(),
                    sel,
                    EquidistantBinning(20, -3., 3.),
                    title="Pseudorapidity of the leading lepton (channel %s)" %
                    channel,
                    xTitle="#eta (leading lepton) [GeV]"))
    plots.append(
        Plot.make1D(
            "%s_subleadleptonEta_%s" % (channel, suffix),
            dilepton[1].p4.Eta(),
            sel,
            EquidistantBinning(20, -3., 3.),
            title="Pseudorapidity of the subleading lepton (channel %s)" %
            channel,
            xTitle="#eta (subleading sublepton) [GeV]"))

    # Phi plot #
    plots.append(
        Plot.make1D("%s_leadleptonPhi_%s" % (channel, suffix),
                    dilepton[0].p4.Phi(),
                    sel,
                    EquidistantBinning(20, -3.2, 3.2),
                    title="Azimutal angle of the leading lepton (channel %s)" %
                    channel,
                    xTitle="#phi (leading lepton) [GeV]"))
    plots.append(
        Plot.make1D(
            "%s_subleadleptonPhi_%s" % (channel, suffix),
            dilepton[1].p4.Phi(),
            sel,
            EquidistantBinning(20, -3.2, 3.2),
            title="Azimutal angle of the subleading lepton (channel %s)" %
            channel,
            xTitle="#phi (subleading lepton) [GeV]"))

    # InvMass plot #
    plots.append(
        Plot.make1D("%s_leptonInvariantMass_%s" % (channel, suffix),
                    op.invariant_mass(dilepton[0].p4, dilepton[1].p4),
                    sel,
                    EquidistantBinning(100, 0., 500.),
                    title="Dilepton invariant mass (channel %s)" % channel,
                    xTitle="Invariant mass [GeV]"))

    return plots
Ejemplo n.º 19
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
    def definePlots(self, t, noSel, sample=None, sampleCfg=None):
        if 'type' not in sampleCfg.keys() or sampleCfg["type"] != "signal":
            raise RuntimeError("Sample needs to be HH signal LO GGF sample")

        era = sampleCfg.get("era") if sampleCfg else None

        # Select gen level Higgs #
        genh = op.select(
            t.GenPart,
            lambda g: op.AND(g.pdgId == 25, g.statusFlags & (0x1 << 13)))
        HH_p4 = genh[0].p4 + genh[1].p4
        cm = HH_p4.BoostToCM()
        boosted_h = op.extMethod("ROOT::Math::VectorUtil::boost",
                                 returnType=genh[0].p4._typeName)(genh[0].p4,
                                                                  cm)
        mHH = op.invariant_mass(genh[0].p4, genh[1].p4)
        cosHH = op.abs(boosted_h.Pz() / boosted_h.P())

        # Apply reweighting #

        benchmarks = [
            'BenchmarkSM',
            'Benchmark1',
            'Benchmark2',
            'Benchmark3',
            'Benchmark4',
            'Benchmark5',
            'Benchmark6',
            'Benchmark7',
            'Benchmark8',
            'Benchmark8a',
            'Benchmark9',
            'Benchmark10',
            'Benchmark11',
            'Benchmark12',
            'BenchmarkcHHH0',
            'BenchmarkcHHH1',
            'BenchmarkcHHH2p45',
            'BenchmarkcHHH5',
            'Benchmarkcluster1',
            'Benchmarkcluster2',
            'Benchmarkcluster3',
            'Benchmarkcluster4',
            'Benchmarkcluster5',
            'Benchmarkcluster6',
            'Benchmarkcluster7',
        ]
        selections = {'': noSel}
        reweights = {}
        if self.args.reweighting:
            for benchmark in benchmarks:
                json_file = os.path.join(
                    os.path.abspath(os.path.dirname(__file__)), 'data',
                    'ScaleFactors_GGF_LO',
                    '{}_to_{}_{}.json'.format(sample, benchmark, era))
                if os.path.exists(json_file):
                    print("Found file {}".format(json_file))
                    reweightLO = get_scalefactor("lepton",
                                                 json_file,
                                                 paramDefs={
                                                     'Eta': lambda x: mHH,
                                                     'Pt': lambda x: cosHH
                                                 })
                    selections[benchmark] = SelectionWithDataDriven.create(
                        parent=noSel,
                        name='noSel' + benchmark,
                        ddSuffix=benchmark,
                        cut=op.c_bool(True),
                        ddCut=op.c_bool(True),
                        weight=op.c_float(1.),
                        ddWeight=reweightLO(op.c_float(1.)),
                        enable=True)
                    reweights[benchmark] = reweightLO(op.c_float(1.))
                else:
                    print("Could not find file {}".format(json_file))

        # Plots #
        plots = []

        for name, reweight in reweights.items():
            plots.append(
                Plot.make1D("weight_{}".format(name),
                            reweight,
                            noSel,
                            EquidistantBinning(100, 0, 5.),
                            xTitle='weight'))

        for selName, sel in selections.items():
            plots.append(
                Plot.make2D(
                    f"mHHvsCosThetaStar{selName}", [mHH, cosHH],
                    sel, [
                        VariableBinning([
                            250., 270., 290., 310., 330., 350., 370., 390.,
                            410., 430., 450., 470., 490., 510., 530., 550.,
                            570., 590., 610., 630., 650., 670., 700., 750.,
                            800., 850., 900., 950., 1000., 1100., 1200., 1300.,
                            1400., 1500., 1750., 2000., 5000.
                        ]),
                        VariableBinning([0.0, 0.4, 0.6, 0.8, 1.0])
                    ],
                    xTitle='m_{HH}',
                    yTitle='cos(#theta^{*})'))
            plots.append(
                Plot.make1D(f"mHH{selName}",
                            mHH,
                            sel,
                            VariableBinning([
                                250., 270., 290., 310., 330., 350., 370., 390.,
                                410., 430., 450., 470., 490., 510., 530., 550.,
                                570., 590., 610., 630., 650., 670., 700., 750.,
                                800., 850., 900., 950., 1000., 1100., 1200.,
                                1300., 1400., 1500., 1750., 2000., 5000.
                            ]),
                            xTitle='m_{HH}'))
            plots.append(
                Plot.make1D(f"cosThetaStar{selName}",
                            cosHH,
                            sel,
                            VariableBinning([0.0, 0.4, 0.6, 0.8, 1.0]),
                            xTitle='cos(#theta^{*})'))

        return plots
Ejemplo n.º 21
0
    def __init__(self, HHself):
        # All the attributes of the BaseHH are contained in HHself object
        # All the lambdas will be saved in the highlevelLambdas object to avoid confusions of all the attributes of HH base object

        # conept #
        self.conept = lambda lep: op.switch(
            op.abs(lep.pdgId) == 11, HHself.electron_conept[lep.idx], HHself.
            muon_conept[lep.idx])

        self.electron_conept = lambda ele: HHself.electron_conept[ele.idx]
        self.muon_conept = lambda mu: HHself.muon_conept[mu.idx]

        # 4-Momentum association #
        self.ll_p4 = lambda l1, l2: l1.p4 + l2.p4
        self.lljj_p4 = lambda l1, l2, j1, j2: l1.p4 + l2.p4 + j1.p4 + j2.p4
        self.lep1j_p4 = lambda lep, j1: lep.p4 + j1.p4
        self.lep2j_p4 = lambda lep, j1, j2: lep.p4 + j1.p4 + j2.p4
        self.lep3j_p4 = lambda lep, j1, j2, j3: lep.p4 + j1.p4 + j2.p4 + j3.p4
        self.lep4j_p4 = lambda lep, j1, j2, j3, j4: lep.p4 + j1.p4 + j2.p4 + j3.p4 + j4.p4

        # bReg corr 4 momenta of ak4-bTagged jet #
        self.bJetCorrP4 = lambda j: op._to.Construct(
            "ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<float> >",
            (j.pt * j.bRegCorr, j.eta, j.phi, j.mass * j.bRegCorr)).result

        # Dilep-Met variables #
        self.DilepMET_deltaPhi = lambda l1, l2, met: self.ll_p4(l1, l2).Phi(
        ) - met.phi
        self.DilepMET_Pt = lambda l1, l2, met: op.sqrt(
            op.pow(met.pt * op.cos(met.phi) + self.ll_p4(l1, l2).Px(), 2) + op.
            pow(met.pt * op.sin(met.phi) + self.ll_p4(l1, l2).Py(), 2))
        # SingleLep-Met variables
        #self.SinglepMet_Pt = lambda lep,met : op.sqrt(op.pow(met.pt*op.cos(met.phi)+lep.p4.Px(),2)+op.pow(met.pt*op.sin(met.phi)+lep.p4.Py(),2))
        self.SinglepMet_Pt = lambda lep, met: (lep.p4 + met.p4).Pt()
        #self.SinglepMet_dPhi = lambda lep, met : lep.p4.Phi()-met.phi
        self.SinglepMet_dPhi = lambda lep, met: op.deltaPhi(lep.p4, met.p4)

        # Transverse mass #
        self.MT_ll = lambda l1, l2, met: op.sqrt(2 * self.ll_p4(l1, l2).Pt(
        ) * met.pt * (1 - op.cos(self.ll_p4(l1, l2).Phi() - met.phi)))
        self.MT_lljj = lambda l1, l2, j1, j2, met: op.sqrt(
            2 * self.lljj_p4(l1, l2, j1, j2).Pt() * met.pt *
            (1 - op.cos(self.lljj_p4(l1, l2, j1, j2).Phi() - met.phi)))
        self.MT = lambda lep, met: op.sqrt(2 * lep.p4.Pt() * met.pt * (
            1 - op.cos(lep.p4.Phi() - met.phi)))
        self.MT_W1W2_ljj = lambda lep, j1, j2, met: op.sqrt(
            2 * self.lep2j_p4(lep, j1, j2).Pt() * met.pt *
            (1 - op.cos(self.lep2j_p4(lep, j1, j2).Phi() - met.phi)))
        self.MT_W1W2_lj = lambda lep, j1, met: op.sqrt(
            2 * self.lep1j_p4(lep, j1).Pt() * met.pt *
            (1 - op.cos(self.lep1j_p4(lep, j1).Phi() - met.phi)))
        # TODO : clean different versions (eg MT)

        # dilep + dijet #
        self.M_lljj = lambda l1, l2, j1, j2: op.invariant_mass(
            self.lljj_p4(l1, l2, j1, j2))
        self.M_HH = lambda l1, l2, j1, j2, met: op.invariant_mass(
            l1.p4, l2.p4, j1.p4, j2.p4, met.p4)
        self.MinDR_lj = lambda l1, l2, j1, j2: op.min(
            op.min(op.deltaR(l1.p4, j1.p4), op.deltaR(l1.p4, j2.p4)),
            op.min(op.deltaR(l2.p4, j1.p4), op.deltaR(l2.p4, j2.p4)))
        self.MinDR_part1_partCont = lambda part1, partCont: op.rng_min(
            partCont, lambda part2: op.deltaR(part1.p4, part2.p4))
        self.MinDEta_part1_partCont = lambda part1, partCont: op.rng_min(
            partCont, lambda part2: op.abs(part1.eta - part2.eta))
        self.MinDPhi_part1_partCont = lambda part1, partCont: op.rng_min(
            partCont, lambda part2: op.abs(op.deltaPhi(part1.p4, part2.p4)))

        self.MinDR_part1_dipart = lambda part1, dipart: op.min(*(
            op.deltaR(part1.p4, dipart[i2].p4) for i2 in range(2)))

        self.JetsMinDR = lambda l, j1, j2: op.min(op.deltaR(l.p4, j1.p4),
                                                  op.deltaR(l.p4, j2.p4))
        self.LepsMinDR = lambda j, l1, l2: op.min(op.deltaR(j.p4, l1.p4),
                                                  op.deltaR(j.p4, l2.p4))

        self.MinDR_lep3j = lambda lep, j1, j2, j3: op.min(
            op.min(op.deltaR(lep.p4, j1.p4), op.deltaR(lep.p4, j2.p4)),
            op.deltaR(lep.p4, j3.p4))

        self.MinDR_lj = lambda l1, l2, j1, j2: op.min(
            op.min(op.deltaR(l1.p4, j1.p4), op.deltaR(l1.p4, j2.p4)),
            op.min(op.deltaR(l2.p4, j1.p4), op.deltaR(l2.p4, j2.p4)))

        self.MinDR_lep2j = lambda lep, j1, j2: op.min(op.deltaR(lep.p4, j1.p4),
                                                      op.deltaR(lep.p4, j2.p4))
        self.MinDR_lep3j = lambda lep, j1, j2, j3: op.min(
            op.min(op.deltaR(lep.p4, j1.p4), op.deltaR(lep.p4, j2.p4)),
            op.deltaR(lep.p4, j3.p4))
        self.MinDR_lep4j = lambda lep, j1, j2, j3, j4: op.min(
            op.min(op.min(op.deltaR(lep.p4, j1.p4), op.deltaR(lep.p4, j2.p4)),
                   op.deltaR(lep.p4, j3.p4)), op.deltaR(lep.p4, j4.p4))
        self.MinDPhi_lep2j = lambda lep, j1, j2: op.min(
            op.abs(op.deltaPhi(lep.p4, j1.p4)),
            op.abs(op.deltaPhi(lep.p4, j2.p4)))
        self.MinDPhi_lep3j = lambda lep, j1, j2, j3: op.min(
            op.min(op.abs(op.deltaPhi(lep.p4, j1.p4)),
                   op.abs(op.deltaPhi(lep.p4, j2.p4))),
            op.abs(op.deltaPhi(lep.p4, j3.p4)))
        self.MinDPhi_lep4j = lambda lep, j1, j2, j3, j4: op.min(
            op.min(
                op.min(op.abs(op.deltaPhi(lep.p4, j1.p4)),
                       op.abs(op.deltaPhi(lep.p4, j2.p4))),
                op.abs(op.deltaPhi(lep.p4, j3.p4))),
            op.abs(op.deltaPhi(lep.p4, j4.p4)))
        self.MinDEta_lep2j = lambda lep, j1, j2: op.min(
            op.abs(lep.eta - j1.eta), op.abs(lep.eta - j2.eta))
        self.MinDEta_lep3j = lambda lep, j1, j2, j3: op.min(
            op.min(op.abs(lep.eta - j1.eta), op.abs(lep.eta - j2.eta)),
            op.abs(lep.eta - j3.eta))
        self.MinDEta_lep4j = lambda lep, j1, j2, j3, j4: op.min(
            op.min(op.min(op.abs(lep.eta - j1.eta), op.abs(lep.eta - j2.eta)),
                   op.abs(lep.eta - j3.eta)), op.abs(lep.eta - j4.eta))

        self.MaxDR_lep2j = lambda lep, j1, j2: op.max(op.deltaR(lep.p4, j1.p4),
                                                      op.deltaR(lep.p4, j2.p4))
        self.MaxDR_lep3j = lambda lep, j1, j2, j3: op.max(
            op.max(op.deltaR(lep.p4, j1.p4), op.deltaR(lep.p4, j2.p4)),
            op.deltaR(lep.p4, j3.p4))
        self.MaxDR_lep4j = lambda lep, j1, j2, j3, j4: op.max(
            op.max(op.max(op.deltaR(lep.p4, j1.p4), op.deltaR(lep.p4, j2.p4)),
                   op.deltaR(lep.p4, j3.p4)), op.deltaR(lep.p4, j4.p4))
        self.MaxDPhi_lep2j = lambda lep, j1, j2: op.max(
            op.abs(op.deltaPhi(lep.p4, j1.p4)),
            op.abs(op.deltaPhi(lep.p4, j2.p4)))
        self.MaxDPhi_lep3j = lambda lep, j1, j2, j3: op.max(
            op.max(op.abs(op.deltaPhi(lep.p4, j1.p4)),
                   op.abs(op.deltaPhi(lep.p4, j2.p4))),
            op.abs(op.deltaPhi(lep.p4, j3.p4)))
        self.MaxDPhi_lep4j = lambda lep, j1, j2, j3, j4: op.max(
            op.max(
                op.max(op.abs(op.deltaPhi(lep.p4, j1.p4)),
                       op.abs(op.deltaPhi(lep.p4, j2.p4))),
                op.abs(op.deltaPhi(lep.p4, j3.p4))),
            op.abs(op.deltaPhi(lep.p4, j4.p4)))
        self.MaxDEta_lep2j = lambda lep, j1, j2: op.max(
            op.abs(lep.eta - j1.eta), op.abs(lep.eta - j2.eta))
        self.MaxDEta_lep3j = lambda lep, j1, j2, j3: op.max(
            op.max(op.abs(lep.eta - j1.eta), op.abs(lep.eta - j2.eta)),
            op.abs(lep.eta - j3.eta))
        self.MaxDEta_lep4j = lambda lep, j1, j2, j3, j4: op.max(
            op.max(op.max(op.abs(lep.eta - j1.eta), op.abs(lep.eta - j2.eta)),
                   op.abs(lep.eta - j3.eta)), op.abs(lep.eta - j4.eta))

        # Higgs related variables #
        #self.HT2 = lambda l1,l2,j1,j2,met : op.sqrt(op.pow(met.pt*op.cos(met.phi)+l1.p4.Px()+l2.p4.Px(),2)+op.pow(met.pt*op.sin(met.phi)+l1.p4.Py()+l2.p4.Py(),2)) + op.abs((j1.p4+j2.p4).Pt())
        #self.HT2R = lambda l1,l2,j1,j2,met : self.HT2(met,l1,l2,j1,j2)/(met.pt+l1.p4.Pt()+l2.p4.Pt()+j1.p4.Pt()+j2.p4.Pt())
        #self.HT2_l1jmet  = lambda l,j1,met : op.sqrt(op.pow(met.pt*op.cos(met.phi)+l.p4.Px(),2)+op.pow(met.pt*op.sin(met.phi)+l.p4.Py(),2)) + op.abs(j1.p4.Pt())
        #self.HT2R_l1jmet = lambda l,j1,met : self.HT2_l1jmet(l,j1,met)/(met.pt+l.p4.Pt()+j1.p4.Pt())
        #self.HT2_l2jmet  = lambda l,j1,j2,met : op.sqrt(op.pow(met.pt*op.cos(met.phi)+l.p4.Px(),2)+op.pow(met.pt*op.sin(met.phi)+l.p4.Py(),2)) + op.abs((j1.p4+j2.p4).Pt())
        #self.HT2R_l2jmet = lambda l,j1,j2,met : self.HT2_l2jmet(l,j1,j2,met)/(met.pt+l.p4.Pt()+j1.p4.Pt()+j2.p4.Pt())
        #self.HT2_l3jmet  = lambda l,j1,j2,j3,met : op.sqrt(op.pow(met.pt*op.cos(met.phi)+l.p4.Px(),2)+op.pow(met.pt*op.sin(met.phi)+l.p4.Py(),2)) + op.abs((j1.p4+j2.p4+j3.p4).Pt())

        self.HT_SL = lambda jets: op.rng_sum(jets, lambda j: j.pt)
        # 0b
        self.HT2_0b = lambda l, met: op.abs((met.p4 + l.p4).Pt())
        self.HT2R_0b = lambda l, met: self.HT2_0b(l, met) / (met.pt + l.pt)

        # 1b0Wj
        self.HT2_1b0Wj = lambda l, j1, met: op.abs(
            (met.p4 + l.p4).Pt()) + j1.pt
        self.HT2R_1b0Wj = lambda l, j1, met: self.HT2_1b0Wj(l, j1, met) / (
            met.pt + l.pt + j1.pt)

        # 1b1Wj
        self.HT2_1b1Wj = lambda l, j1, j3, met: op.abs(
            (met.p4 + l.p4 + j3.p4).Pt()) + j1.pt
        self.HT2R_1b1Wj = lambda l, j1, j3, met: self.HT2_1b1Wj(
            l, j1, j3, met) / (met.pt + l.pt + j1.pt + j3.pt)

        #2b0Wj
        self.HT2_2b0Wj = lambda l, j1, j2, met: op.abs(
            (met.p4 + l.p4).Pt()) + op.abs((j1.p4 + j2.p4).Pt())
        self.HT2R_2b0Wj = lambda l, j1, j2, met: self.HT2_2b0Wj(
            l, j1, j2, met) / (met.pt + l.pt + j1.pt + j2.pt)

        # 1b2Wj
        self.HT2_1b2Wj = lambda l, j1, j3, j4, met: op.abs(
            (met.p4 + l.p4 + j3.p4 + j4.p4).Pt()) + j1.pt
        self.HT2R_1b2Wj = lambda l, j1, j3, j4, met: self.HT2_1b2Wj(
            l, j1, j3, j4, met) / (met.pt + l.pt + j1.pt + j3.pt + j4.pt)

        # 2b1Wj
        self.HT2_2b1Wj = lambda l, j1, j2, j3, met: op.abs(
            (met.p4 + l.p4 + j3.p4).Pt()) + op.abs((j1.p4 + j2.p4).Pt())
        self.HT2R_2b1Wj = lambda l, j1, j2, j3, met: self.HT2_2b1Wj(
            l, j1, j2, j3, met) / (met.pt + l.pt + j1.pt + j2.pt + j3.pt)

        #self.HT2_l4jmet  = lambda l,j1,j2,j3,j4,met : op.sqrt(op.pow(met.pt*op.cos(met.phi)+l.p4.Px(),2)+op.pow(met.pt*op.sin(met.phi)+l.p4.Py(),2)) + op.abs((j1.p4+j2.p4+j3.p4+j4.p4).Pt())
        # 2b2Wj
        self.HT2_2b2Wj = lambda l, j1, j2, j3, j4, met: op.abs(
            (met.p4 + l.p4 + j3.p4 + j4.p4).Pt()) + op.abs(
                (j1.p4 + j2.p4).Pt())
        self.HT2R_2b2Wj = lambda l, j1, j2, j3, j4, met: self.HT2_2b2Wj(
            l, j1, j2, j3, j4, met) / (met.pt + l.pt + j1.pt + j2.pt + j3.pt +
                                       j4.pt)

        #min j1j2DR
        self.MinDiJetDRLoose = lambda j1, j2, j3: op.min(
            op.min(op.deltaR(j1.p4, j2.p4), op.deltaR(j2.p4, j3.p4)),
            op.deltaR(j1.p4, j3.p4))
        self.MinDiJetDRTight = lambda j1, j2, j3, j4: op.min(
            op.min(
                op.min(self.MinDiJetDRLoose(j1, j2, j3), op.deltaR(
                    j1.p4, j4.p4)), op.deltaR(j2.p4, j4.p4)),
            op.deltaR(j3.p4, j4.p4))
        self.MinDiJetDEtaLoose = lambda j1, j2, j3: op.min(
            op.min(op.abs(j1.eta - j2.eta), op.abs(j2.eta - j3.eta)),
            op.abs(j1.eta - j3.eta))
        self.MinDiJetDEtaTight = lambda j1, j2, j3, j4: op.min(
            op.min(
                op.min(self.MinDiJetDEtaLoose(j1, j2, j3),
                       op.abs(j1.eta - j4.eta)), op.abs(j2.eta - j4.eta)),
            op.abs(j3.eta - j4.eta))
        self.MinDiJetDPhiLoose = lambda j1, j2, j3: op.min(
            op.min(op.abs(op.deltaPhi(j1.p4, j2.p4)),
                   op.abs(op.deltaPhi(j2.p4, j3.p4))),
            op.abs(op.deltaPhi(j1.p4, j3.p4)))
        self.MinDiJetDPhiTight = lambda j1, j2, j3, j4: op.min(
            op.min(
                op.min(self.MinDiJetDPhiLoose(j1, j2, j3),
                       op.abs(op.deltaPhi(j1.p4, j4.p4))),
                op.abs(op.deltaPhi(j2.p4, j4.p4))),
            op.abs(op.deltaPhi(j3.p4, j4.p4)))

        self.MaxDiJetDRLoose = lambda j1, j2, j3: op.max(
            op.max(op.deltaR(j1.p4, j2.p4), op.deltaR(j2.p4, j3.p4)),
            op.deltaR(j1.p4, j3.p4))
        self.MaxDiJetDRTight = lambda j1, j2, j3, j4: op.max(
            op.max(
                op.max(self.MaxDiJetDRLoose(j1, j2, j3), op.deltaR(
                    j1.p4, j4.p4)), op.deltaR(j2.p4, j4.p4)),
            op.deltaR(j3.p4, j4.p4))
        self.MaxDiJetDEtaLoose = lambda j1, j2, j3: op.max(
            op.max(op.abs(j1.eta - j2.eta), op.abs(j2.eta - j3.eta)),
            op.abs(j1.eta - j3.eta))
        self.MaxDiJetDEtaTight = lambda j1, j2, j3, j4: op.max(
            op.max(
                op.max(self.MaxDiJetDEtaLoose(j1, j2, j3),
                       op.abs(j1.eta - j4.eta)), op.abs(j2.eta - j4.eta)),
            op.abs(j3.eta - j4.eta))
        self.MaxDiJetDPhiLoose = lambda j1, j2, j3: op.max(
            op.max(op.abs(op.deltaPhi(j1.p4, j2.p4)),
                   op.abs(op.deltaPhi(j2.p4, j3.p4))),
            op.abs(op.deltaPhi(j1.p4, j3.p4)))
        self.MaxDiJetDPhiTight = lambda j1, j2, j3, j4: op.max(
            op.max(
                op.max(self.MaxDiJetDPhiLoose(j1, j2, j3),
                       op.abs(op.deltaPhi(j1.p4, j4.p4))),
                op.abs(op.deltaPhi(j2.p4, j4.p4))),
            op.abs(op.deltaPhi(j3.p4, j4.p4)))

        # ------------------------------------ lambdas for BDT variables ------------------------------------ #
        # min jet-lep DR
        self.mindr_lep1_jet = lambda lep, jets: op.deltaR(
            lep.p4,
            op.sort(jets, lambda j: op.deltaR(lep.p4, j.p4))[0].p4)

        # HT
        self.HTfull = lambda fleps, j1p4, j2p4, j3p4, j4p4: j1p4.Pt(
        ) + j2p4.Pt() + j3p4.Pt() + j4p4.Pt() + op.rng_sum(
            fleps, lambda l: l.p4.Pt())
        self.HTmiss = lambda fleps, j1p4, j2p4, j3p4: j1p4.Pt() + j2p4.Pt(
        ) + j3p4.Pt() + op.rng_sum(fleps, lambda l: l.p4.Pt())

        # mT2
        ET = lambda lepp4: op.sqrt(
            op.pow(lepp4.M(), 2) + op.pow(lepp4.Pt(), 2))
        self.mT2 = lambda jetp4, lepp4, metp4: (
            op.pow(jetp4.M(), 2) + op.pow(lepp4.M(), 2) + op.pow(metp4.M(), 2)
            + 2 * (ET(lepp4) * ET(jetp4) -
                   (lepp4.Px() * jetp4.Px() + lepp4.Py() * jetp4.Py())) + 2 *
            (ET(lepp4) * ET(metp4) -
             (lepp4.Px() * metp4.Px() + lepp4.Py() * metp4.Py())) + 2 *
            (ET(jetp4) * ET(metp4) -
             (jetp4.Px() * metp4.Px() + jetp4.Py() * metp4.Py())))

        # pZ component of met
        # https://github.com/HEP-KBFI/hh-bbww/blob/f4ab60f81a920268a3f2187b97a58ec449b26883/src/comp_metP4_B2G_18_008.cc
        # some necessary constants (visP4 = lepP4 + Wjj_simple)
        # - - - - - used to compute neuP4 - - - - - #
        ax = lambda visP4, met: 125.18 * 125.18 - op.pow(visP4.M(
        ), 2) + 2. * visP4.Px() * met.p4.Px() + 2. * visP4.Py() * met.p4.Py()
        A = lambda visP4: 4.0 * op.pow(visP4.E(), 2) - op.pow(visP4.Pz(), 2)
        B = lambda visP4, met: -4.0 * ax(visP4, met) * visP4.Pz()
        C = lambda visP4, met: 4.0 * op.pow(visP4.E(), 2) * (op.pow(
            met.p4.Px(), 2) + op.pow(met.p4.Py(), 2)) - op.pow(
                ax(visP4, met), 2)
        D = lambda visP4, met: (op.pow(B(visP4, met), 2) - 4.0 * A(visP4) * C(
            visP4, met))
        pos = lambda visP4, met: (-B(visP4, met) + op.sqrt(D(visP4, met))) / (
            2. * A(visP4))
        neg = lambda visP4, met: (-B(visP4, met) - op.sqrt(D(visP4, met))) / (
            2. * A(visP4))
        neuPz = lambda visP4, met: (op.switch(
            D(visP4, met) < 0., -B(visP4, met) / (2 * A(visP4)),
            op.switch(
                op.abs(pos(visP4, met)) < op.abs(neg(visP4, met)),
                pos(visP4, met), neg(visP4, met))))
        # - - - - - - - - - - - - - - - - - - - - - #
        self.neuP4 = lambda visP4, met: op._to.Construct(
            "ROOT::Math::LorentzVector<ROOT::Math::PxPyPzE4D<float> >",
            (met.p4.Px(), met.p4.Py(), neuPz(visP4, met),
             op.sqrt(
                 op.pow(met.p4.Px(), 2) + op.pow(met.p4.Py(), 2) + op.pow(
                     neuPz(visP4, met), 2)))).result

        # P4 of W1 (l,neu)
        self.Wlep_simple = lambda wj1P4, wj2P4, lepP4, met: lepP4 + self.neuP4(
            wj1P4 + wj2P4 + lepP4, met)
        # P4 of W2 (j,j)
        self.Wjj_simple = lambda j1P4, j2P4: j1P4 + j2P4
        # DR_HadW_bJet
        self.dR_HadW_bjet = lambda bP4, j1P4, j2P4: op.deltaR(
            self.Wjj_simple(j1P4, j2P4), bP4)
        # P4 of HWW (W1 + W2)
        self.HWW_simple = lambda wj1P4, wj2P4, lepP4, met: self.Wjj_simple(
            wj1P4, wj2P4) + self.Wlep_simple(wj1P4, wj2P4, lepP4, met)
        # dR_HWW
        self.dR_Hww = lambda j1P4, j2P4, lepP4, met: op.deltaR(
            self.Wjj_simple(j1P4, j2P4),
            self.Wlep_simple(j1P4, j2P4, lepP4, met))
        self.dEta_Hww = lambda j1P4, j2P4, lepP4, met: op.abs(
            self.Wjj_simple(j1P4, j2P4).Eta() - self.Wlep_simple(
                j1P4, j2P4, lepP4, met).Eta())
        self.dPhi_Hww = lambda j1P4, j2P4, lepP4, met: op.abs(
            op.deltaPhi(self.Wjj_simple(j1P4, j2P4),
                        self.Wlep_simple(j1P4, j2P4, lepP4, met)))
        # P4 of lep + met
        self.Wlep_met_simple = lambda lepP4, metP4: lepP4 + metP4
        # SimpleP4 of HWW (W1 + W2)
        self.HWW_met_simple = lambda j1P4, j2P4, lepP4, metP4: self.Wjj_simple(
            j1P4, j2P4) + self.Wlep_met_simple(lepP4, metP4)
        # Total P4
        self.HHP4_simple_met = lambda HbbRegP4, j1P4, j2P4, lepP4, metP4: HbbRegP4 + self.Wjj_simple(
            j1P4, j2P4) + self.Wlep_met_simple(lepP4, metP4)

        # CosThetaS calculation
        #comp_cosThetaS = lambda ob1p4, ob2p4 : op.abs(ob1p4.Boost(-(ob1p4+ob2p4).BoostVector()).CosTheta())
        motherPx = lambda ob1p4, ob2p4: (ob1p4.Px() + ob2p4.Px())
        motherPy = lambda ob1p4, ob2p4: (ob1p4.Py() + ob2p4.Py())
        motherPz = lambda ob1p4, ob2p4: (ob1p4.Pz() + ob2p4.Pz())
        motherE = lambda ob1p4, ob2p4: (ob1p4.E() + ob2p4.E())
        betaX = lambda ob1p4, ob2p4: motherPx(ob1p4, ob2p4) / motherE(
            ob1p4, ob2p4)
        betaY = lambda ob1p4, ob2p4: motherPy(ob1p4, ob2p4) / motherE(
            ob1p4, ob2p4)
        betaZ = lambda ob1p4, ob2p4: motherPz(ob1p4, ob2p4) / motherE(
            ob1p4, ob2p4)
        beta2 = lambda ob1p4, ob2p4: op.pow(betaX(ob1p4, ob2p4), 2) + op.pow(
            betaY(ob1p4, ob2p4), 2) + op.pow(betaZ(ob1p4, ob2p4), 2)
        gamma = lambda ob1p4, ob2p4: 1.0 / op.sqrt(1 - beta2(ob1p4, ob2p4))
        betap = lambda ob1p4, ob2p4: betaX(ob1p4, ob2p4) * motherPx(
            ob1p4, ob2p4) + betaY(ob1p4, ob2p4) * motherPy(
                ob1p4, ob2p4) + betaZ(ob1p4, ob2p4) * motherPz(ob1p4, ob2p4)
        gamma2 = lambda ob1p4, ob2p4: op.switch(
            beta2(ob1p4, ob2p4) > 0,
            (gamma(ob1p4, ob2p4) - 1) / beta2(ob1p4, ob2p4), op.c_float(0.0))
        boostPx = lambda ob1p4, ob2p4: ob1p4.Px() + gamma2(
            ob1p4, ob2p4) * betap(ob1p4, ob2p4) * betaX(ob1p4, ob2p4) + gamma(
                ob1p4, ob2p4) * betaX(ob1p4, ob2p4) * ob1p4.E()
        boostPy = lambda ob1p4, ob2p4: ob1p4.Px() + gamma2(
            ob1p4, ob2p4) * betap(ob1p4, ob2p4) * betaY(ob1p4, ob2p4) + gamma(
                ob1p4, ob2p4) * betaY(ob1p4, ob2p4) * ob1p4.E()
        boostPz = lambda ob1p4, ob2p4: ob1p4.Pz() + gamma2(
            ob1p4, ob2p4) * betap(ob1p4, ob2p4) * betaZ(ob1p4, ob2p4) + gamma(
                ob1p4, ob2p4) * betaZ(ob1p4, ob2p4) * ob1p4.E()
        boostP = lambda ob1p4, ob2p4: op.sqrt(
            op.pow(boostPx(ob1p4, ob2p4), 2) + op.pow(boostPy(ob1p4, ob2p4), 2)
            + op.pow(boostPz(ob1p4, ob2p4), 2))
        self.comp_cosThetaS = lambda ob1p4, ob2p4: op.abs(
            boostPz(ob1p4, ob2p4) / boostP(ob1p4, ob2p4))

        #BoostP3  = lambda ob1p4,ob2p4 : op._to.Construct("ROOT::Math::TVector<ROOT::Math::PxPyPz3D<float>>",(-motherPx(ob1p4,ob2p4), -motherPy(ob1p4,ob2p4), -motherPz(ob1p4,ob2p4))).result
        #boost = lambda ob1p4,ob2p4 : op.construct("ROOT::Math::Boost", (-motherPx(ob1p4,ob2p4)/motherE(ob1p4,ob2p4),
        #                                                                -motherPy(ob1p4,ob2p4)/motherE(ob1p4,ob2p4),
        #                                                                -motherPz(ob1p4,ob2p4)/motherE(ob1p4,ob2p4)))
        #self.comp_cosThetaS = lambda ob1p4,ob2p4 : op.abs(boost(ob1p4,ob2p4)(ob1p4).CosTheta())

        #p4_boosted = lambda ob1p4,ob2p4 : op.extMethod("ROOT::Math::Boost{-motherPx(ob1p4,ob2p4)/motherE(ob1p4,ob2p4), -motherPy(ob1p4,ob2p4)/motherE(ob1p4,ob2p4), -motherPz(ob1p4,ob2p4)/motherE(ob1p4,ob2p4)}", returnType=(ob1p4+ob2p4)._typeName)(ob1p4+ob2p4)
        #self.comp_cosThetaS = lambda ob1p4,ob2p4 : op.deltaR(ob1p4, p4_boosted(ob1p4,ob2p4))

        #boost = lambda ob1p4, ob2p4: op.construct("ROOT::Math::Boost", (-betaX(ob1p4, ob2p4), -betaY(ob1p4, ob2p4), -betaZ(ob1p4, ob2p4)))
        #boostP4 = lambda ob1p4,ob2p4 : boost(ob1p4,ob2p4)(ob1p4)
        #self.comp_cosThetaS = lambda ob1p4,ob2p4 : op.abs(boostP4(ob1p4,ob2p4).Pz()/op.sqrt(op.pow(boostP4(ob1p4,ob2p4).Px(),2) + op.pow(boostP4(ob1p4,ob2p4).Py(),2) + op.pow(boostP4(ob1p4,ob2p4).Pz(),2)))

        # MET_LD
        # Equation 3 (page 33) of AN-2019/111 v13
        # Similar to MET, but more robust against pileup
        jetSumPx = lambda jets: op.rng_sum(jets, lambda j: j.p4.Px())
        jetSumPy = lambda jets: op.rng_sum(jets, lambda j: j.p4.Py())
        #lepSumPx = lambda leps : op.rng_sum(leps, lambda l : l.p4.Px())
        #lepSumPy = lambda leps : op.rng_sum(leps, lambda l : l.p4.Py())
        lepSumPx = lambda mus, els: op.rng_sum(mus, lambda l: l.p4.Px(
        )) + op.rng_sum(els, lambda l: l.p4.Px())
        lepSumPy = lambda mus, els: op.rng_sum(mus, lambda l: l.p4.Py(
        )) + op.rng_sum(els, lambda l: l.p4.Py())
        self.MET_LD = lambda met, jets, mus, els: 0.6 * met.pt + 0.4 * op.sqrt(
            op.pow(jetSumPx(jets) + lepSumPx(mus, els), 2) + op.pow(
                jetSumPy(jets) + lepSumPy(mus, els), 2))

        empty_p4 = op.construct(
            "ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<float> >",
            ([op.c_float(0.),
              op.c_float(0.),
              op.c_float(0.),
              op.c_float(0.)]))
        self.MET_LD_DL = lambda met, jets, electrons, muons : 0.6 * met.pt +\
                    0.4* (op.rng_sum(jets, (lambda j : j.p4), start=empty_p4) + op.rng_sum(electrons, (lambda e : e.p4), start=empty_p4) + op.rng_sum(muons, (lambda m : m.p4), start=empty_p4)).Pt()

        # conept
        self.lambdaConePt = lambda lep: op.switch(
            op.abs(lep.pdgId) == 13, HHself.muon_conept[lep.idx], HHself.
            electron_conept[lep.idx])

        # angle between 2 planes
        aDotB = lambda a, b: a.Px() * b.Px() + a.Py() * b.Py() + a.Pz() * b.Pz(
        )
        aMagB = lambda a, b: (op.sqrt(
            op.pow(a.Px(), 2) + op.pow(a.Py(), 2) + op.pow(a.Pz(), 2))) * (
                op.sqrt(
                    op.pow(b.Px(), 2) + op.pow(b.Py(), 2) + op.pow(b.Pz(), 2)))
        self.angleWWplane = lambda lp4, met, j3p4, j4p4: op.acos(
            aDotB(j3p4 + j4p4,
                  self.neuP4(j3p4 + j4p4 + lp4, met) + lp4) / aMagB(
                      j3p4 + j4p4,
                      self.neuP4(j3p4 + j4p4 + lp4, met) + lp4))
        #self.angleWWplane = lambda lp4, met, j3p4, j4p4 : ((j3p4+j4p4).Vect().Unit()).Angle((self.neuP4(j3p4+j4p4+lp4, met)+lp4).Vect().Unit())
        self.angleBetPlanes = lambda j1p4, j2p4, j3p4, j4p4: op.acos(
            op.c_float(
                aDotB(j1p4 + j2p4, j3p4 + j4p4) / aMagB(
                    j1p4 + j2p4, j3p4 + j4p4)))

        self.empty_p4 = op.construct(
            "ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<float> >",
            ([op.c_float(0.),
              op.c_float(0.),
              op.c_float(0.),
              op.c_float(0.)]))
        self.MET_LD_DL = lambda met, jets, electrons, muons : 0.6 * met.pt +\
                    0.4* (op.rng_sum(jets, (lambda j : j.p4), start=self.empty_p4) + op.rng_sum(electrons, (lambda e : e.p4), start=self.empty_p4) + op.rng_sum(muons, (lambda m : m.p4), start=self.empty_p4)).Pt()

        self.isBoosted = op.AND(
            op.rng_len(HHself.ak8BJets) >= 1,
            op.rng_len(HHself.ak4JetsCleanedFromAk8b) >= 1)
        #self.isBoosted  = op.rng_len(HHself.ak8BJets) >= 1
        self.isResolved = op.AND(
            op.rng_len(HHself.ak4Jets) >= 3,
            op.rng_len(HHself.ak4BJets) >= 1,
            op.rng_len(HHself.ak8BJets) == 0)
        #self.has1Wj     = op.rng_len(HHself.probableWJets) == 1
        #self.has2Wj     = op.rng_len(HHself.wJetsPairs) >= 1
        #self.isFullReco = op.AND(op.rng_len(HHself.bJetsByScore) >= 2, op.rng_len(HHself.wJetsPairs) >= 1)
        #self.isMissReco = op.AND(op.rng_len(HHself.bJetsByScore) >= 2, op.rng_len(HHself.probableWJets) == 1)

        #self.comp_m_hh_bregcorr = lambda bjets, wjets, lep, met : (op.rng_sum(bjets, (lambda bj : self.bJetCorrP4(bj)), start=empty_p4) +
        #                                                           op.rng_sum(wjets, (lambda wj : self.bJetCorrP4(wj)), start=empty_p4) +
        #                                                           met.p4 +
        #                                                           lep.p4).M()
        self.comp_m_hh_bregcorr = lambda bjets, wjets, lepconep4, met: (
            op.rng_sum(bjets, (lambda bj: self.bJetCorrP4(bj)), start=empty_p4)
            + op.rng_sum(wjets, (lambda wj: self.bJetCorrP4(wj)),
                         start=empty_p4) + met.p4 + lepconep4).M()

        #self.comp_pt_hh         = lambda bjets, wjets, lep, met : (op.rng_sum(bjets, (lambda bj : bj.p4), start=empty_p4) +
        #                                                           op.rng_sum(wjets, (lambda wj : wj.p4), start=empty_p4) +
        #                                                           met.p4 +
        #                                                           lep.p4).Pt()
        self.comp_pt_hh = lambda bjets, wjets, lepconep4, met: (op.rng_sum(
            bjets, (lambda bj: bj.p4), start=empty_p4) + op.rng_sum(
                wjets,
                (lambda wj: wj.p4), start=empty_p4) + met.p4 + lepconep4).Pt()
        #self.comp_dphi_hbb_hww  = lambda bjets, wjets, lep, met : op.deltaPhi((op.rng_sum(wjets, (lambda wj : wj.p4), start=empty_p4) + met.p4 + lep.p4),
        #                                                                            op.rng_sum(bjets, (lambda bj : bj.p4), start=empty_p4))
        #self.comp_dphi_hbb_hwwvis = lambda bjets, wjets, lep : op.deltaPhi((op.rng_sum(wjets, (lambda wj : wj.p4), start=empty_p4) + lep.p4),
        #                                                                         op.rng_sum(bjets, (lambda bj : bj.p4), start=empty_p4))
        self.comp_dphi_hbb_hww = lambda bjets, wjets, lepconep4, met: op.deltaPhi(
            (op.rng_sum(wjets, (lambda wj: wj.p4), start=empty_p4) + met.p4 +
             lepconep4), op.rng_sum(bjets, (lambda bj: bj.p4), start=empty_p4))
        self.comp_dphi_hbb_hwwvis = lambda bjets, wjets, lepconep4: op.deltaPhi(
            (op.rng_sum(wjets,
                        (lambda wj: wj.p4), start=empty_p4) + lepconep4),
            op.rng_sum(bjets, (lambda bj: bj.p4), start=empty_p4))
Ejemplo 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.),
            }
Ejemplo n.º 23
0
def makeControlPlotsForBasicSel(self, sel, jets, dilepton, uname):
    binScaling = 1
    plots = []
    plots.append(
        Plot.make1D("{0}_leadJetPT".format(uname),
                    jets[0].pt,
                    sel,
                    EqB(60, 0., 450.),
                    title="P_{T} (leading Jet) [GeV]",
                    plotopts=utils.getOpts(uname)))
    plots.append(
        Plot.make1D("{0}_subleadJetPT".format(uname),
                    jets[1].pt,
                    sel,
                    EqB(60, 0., 450.),
                    title="P_{T} (sub-leading Jet) [GeV]",
                    plotopts=utils.getOpts(uname)))

    plots.append(
        Plot.make1D("{0}_leadJetETA".format(uname),
                    jets[0].eta,
                    sel,
                    EqB(10, -2.4, 2.4),
                    title="Eta (leading Jet)",
                    plotopts=utils.getOpts(uname)))
    plots.append(
        Plot.make1D("{0}_subleadJetETA".format(uname),
                    jets[1].eta,
                    sel,
                    EqB(10, -2.4, 2.4),
                    title="Eta (sub-leading Jet)",
                    plotopts=utils.getOpts(uname)))

    for i in range(2):
        plots.append(
            Plot.make1D(f"{uname}_jet{i+1}_phi",
                        jets[i].phi,
                        sel,
                        EqB(50 // binScaling, -3.1416, 3.1416),
                        title=f"{utils.getCounter(i+1)} jet phi",
                        plotopts=utils.getOpts(uname, **{"log-y": False})))

    plots.append(
        Plot.make1D("{0}_jjpT".format(uname), (jets[0].p4 + jets[1].p4).pt,
                    sel,
                    EqB(100, 0., 450.),
                    title="dijet P_{T} [GeV]",
                    plotopts=utils.getOpts(uname)))

    plots.append(
        Plot.make1D("{0}_jjPhi".format(uname), (jets[0].p4 + jets[1].p4).phi,
                    sel,
                    EqB(50 // binScaling, -3.1416, 3.1416),
                    title="dijet phi",
                    plotopts=utils.getOpts(uname)))

    plots.append(
        Plot.make1D("{0}_jjEta".format(uname), (jets[0].p4 + jets[1].p4).eta,
                    sel,
                    EqB(50 // binScaling, -2.4, 2.4),
                    title="dijet eta",
                    plotopts=utils.getOpts(uname)))

    plots.append(
        Plot.make1D("{0}_mjj".format(uname),
                    op.invariant_mass(jets[0].p4, jets[1].p4),
                    sel,
                    EqB(100, 0., 800.),
                    title="mjj [GeV]",
                    plotopts=utils.getOpts(uname)))

    plots.append(
        Plot.make1D("{0}_mlljj".format(uname),
                    (dilepton[0].p4 + dilepton[1].p4 + jets[0].p4 +
                     jets[1].p4).M(),
                    sel,
                    EqB(100, 0., 1000.),
                    title="mlljj [GeV]",
                    plotopts=utils.getOpts(uname)))
    plots.append(
        Plot.make2D(
            "{0}_mlljjvsmjj".format(uname),
            (op.invariant_mass(jets[0].p4, jets[1].p4),
             (dilepton[0].p4 + dilepton[1].p4 + jets[0].p4 + jets[1].p4).M()),
            sel, (EqB(1000, 0., 1000.), EqB(1000, 0., 1000.)),
            title="mlljj vs mjj invariant mass [Gev]",
            plotopts=utils.getOpts(uname)))
    return plots
Ejemplo n.º 24
0
def makeFatJetPlots(self, sel, fatjet, suffix, channel):
    """
    Make fatjet basic plots
    sel         = refine selection 
    fatjet      = fatjet object (AK8 jet) (can contain 0,1 or 2 subjets), where at least on subjet is btagged
    suffix      = string identifying the selecton 
    channel     = string identifying the channel of the dilepton (can be "NoChannel")
    """

    plots = []
    # Refine to check what and how many subjets were present #
    lambda_subjet1 = lambda fatjet: fatjet.subJet1._idx.result != -1
    lambda_subjet2 = lambda fatjet: fatjet.subJet2._idx.result != -1
    lambda_notSubjet1 = lambda fatjet: fatjet.subJet1._idx.result == -1
    lambda_notSubjet2 = lambda fatjet: fatjet.subJet2._idx.result == -1
    has_subjet1 = sel.refine("has_subjet1_%s_%s" % (channel, suffix),
                             cut=[lambda_subjet1(fatjet)])
    has_subjet2 = sel.refine("has_subjet2_%s_%s" % (channel, suffix),
                             cut=[lambda_subjet2(fatjet)])
    has_notSubjet1 = sel.refine("has_notSubjet1_%s_%s" % (channel, suffix),
                                cut=[lambda_notSubjet1(fatjet)])
    has_notSubjet2 = sel.refine("has_notSubjet2_%s_%s" % (channel, suffix),
                                cut=[lambda_notSubjet2(fatjet)])
    has_bothSubjets = sel.refine(
        "has_bothSubjets_%s_%s" % (channel, suffix),
        cut=[lambda_subjet1(fatjet),
             lambda_subjet2(fatjet)])
    has_notBothSubjets = sel.refine(
        "has_notBothSubjets_%s_%s" % (channel, suffix),
        cut=[op.OR(lambda_notSubjet1(fatjet), lambda_notSubjet2(fatjet))])

    # PT Plot #
    plot_hasSubjet1_Pt = Plot.make1D(
        "%s_fatjet_hasSubjet1PT_%s" % (channel, suffix),
        fatjet.subJet1.p4.Pt(),
        has_subjet1,
        EquidistantBinning(100, -10, 500.),
        title='Transverse momentum of the first subjet',
        xTitle="P_{T} (first subjet) [GeV]")
    plot_notSubjet1_Pt = Plot.make1D(
        "%s_fatjet_notSubjet1PT_%s" % (channel, suffix),
        op.c_float(-10.),
        has_notSubjet1,
        EquidistantBinning(100, -10, 500.),
        title='Transverse momentum of the first subjet',
        xTitle="P_{T} (first subjet) [GeV]")
    plots.append(
        SummedPlot("%s_fatjet_subjet1PT_%s" % (channel, suffix),
                   [plot_hasSubjet1_Pt, plot_notSubjet1_Pt],
                   xTitle="P_{T} (first subjet) [GeV]"))

    plot_hasSubjet2_Pt = Plot.make1D(
        "%s_fatjet_hasSubjet2PT_%s" % (channel, suffix),
        fatjet.subJet2.p4.Pt(),
        has_subjet2,
        EquidistantBinning(100, -10, 500.),
        title='Transverse momentum of the second subjet',
        xTitle="P_{T} (second subjet) [GeV]")
    plot_notSubjet2_Pt = Plot.make1D(
        "%s_fatjet_notSubjet2PT_%s" % (channel, suffix),
        op.c_float(-10.),
        has_notSubjet2,
        EquidistantBinning(100, -10, 500.),
        title='Transverse momentum of the second subjet',
        xTitle="P_{T} (second subjet) [GeV]")
    plots.append(
        SummedPlot("%s_fatjet_subjet2PT_%s" % (channel, suffix),
                   [plot_hasSubjet2_Pt, plot_notSubjet2_Pt],
                   xTitle="P_{T} (second subjet) [GeV]"))

    # Eta plot #
    plot_hasSubjet1_Eta = Plot.make1D(
        "%s_fatjet_hasSubjet1Eta_%s" % (channel, suffix),
        fatjet.subJet1.p4.Eta(),
        has_subjet1,
        EquidistantBinning(20, -3., 3.),
        title='Pseudorapidity of the first subjet',
        xTitle="#eta (first subjet) [GeV]")
    plot_notSubjet1_Eta = Plot.make1D(
        "%s_fatjet_notSubjet1Eta_%s" % (channel, suffix),
        op.c_float(-3.),
        has_notSubjet1,
        EquidistantBinning(20, -3., 3.),
        title='Pseudorapidity of the first subjet',
        xTitle="#eta (first subjet) [GeV]")
    plots.append(
        SummedPlot("%s_fatjet_subjet1Eta_%s" % (channel, suffix),
                   [plot_hasSubjet1_Eta, plot_notSubjet1_Eta],
                   xTitle="#eta (first subjet) [GeV]"))

    plot_hasSubjet2_Eta = Plot.make1D(
        "%s_fatjet_hasSubjet2Eta_%s" % (channel, suffix),
        fatjet.subJet2.p4.Eta(),
        has_subjet2,
        EquidistantBinning(20, -3., 3.),
        title='Pseudorapidity of the second subjet',
        xTitle="#eta (second subjet) [GeV]")
    plot_notSubjet2_Eta = Plot.make1D(
        "%s_fatjet_notSubjet2Eta_%s" % (channel, suffix),
        op.c_float(-3.),
        has_notSubjet2,
        EquidistantBinning(20, -3., 3.),
        title='Pseudorapidity of the second subjet',
        xTitle="#eta (second subjet) [GeV]")
    plots.append(
        SummedPlot("%s_fatjet_subjet2Eta_%s" % (channel, suffix),
                   [plot_hasSubjet2_Eta, plot_notSubjet2_Eta],
                   xTitle="#eta (second subjet) [GeV]"))

    # Phi Plot #
    plot_hasSubjet1_Phi = Plot.make1D(
        "%s_fatjet_hasSubjet1Phi_%s" % (channel, suffix),
        fatjet.subJet1.p4.Phi(),
        has_subjet1,
        EquidistantBinning(20, -3.2, 3.2),
        title='Azimutal angle of the first subjet',
        xTitle="#phi (first subjet) [GeV]")
    plot_notSubjet1_Phi = Plot.make1D(
        "%s_fatjet_notSubjet1Phi_%s" % (channel, suffix),
        op.c_float(-3.2),
        has_notSubjet1,
        EquidistantBinning(20, -3.2, 3.2),
        title='Azimutal angle of the first subjet',
        xTitle="#phi (first subjet) [GeV]")
    plots.append(
        SummedPlot("%s_fatjet_subjet1Phi_%s" % (channel, suffix),
                   [plot_hasSubjet1_Phi, plot_notSubjet1_Phi],
                   xTitle="#phi (first subjet) [GeV]"))

    plot_hasSubjet2_Phi = Plot.make1D(
        "%s_fatjet_hasSubjet2Phi_%s" % (channel, suffix),
        fatjet.subJet2.p4.Phi(),
        has_subjet2,
        EquidistantBinning(20, -3.2, 3.2),
        title='Azimutal angle of the second subjet',
        xTitle="#phi (second subjet) [GeV]")
    plot_notSubjet2_Phi = Plot.make1D(
        "%s_fatjet_notSubjet2Phi_%s" % (channel, suffix),
        op.c_float(-3.2),
        has_notSubjet2,
        EquidistantBinning(20, -3.2, 3.2),
        title='Azimutal angle of the second subjet',
        xTitle="#phi (second subjet) [GeV]")
    plots.append(
        SummedPlot("%s_fatjet_subjet2Phi_%s" % (channel, suffix),
                   [plot_hasSubjet2_Phi, plot_notSubjet2_Phi],
                   xTitle="#phi (second subjet) [GeV]"))

    # Invariant mass #
    plot_hasBothSubjets_invMass = Plot.make1D(
        "%s_fatjet_hasBothSubjets_invMass_%s" % (channel, suffix),
        op.invariant_mass(fatjet.subJet1.p4, fatjet.subJet2.p4),
        has_bothSubjets,
        EquidistantBinning(100, -10., 300.),
        title="Fatjet invariant mass (channel %s)" % channel,
        xTitle="Invariant mass [GeV]")
    plot_hasNotBothSubjets_invMass = Plot.make1D(
        "%s_fatjet_notBothSubjets_invMass_%s" % (channel, suffix),
        op.c_float(-10.),
        has_notBothSubjets,
        EquidistantBinning(100, -10., 300.),
        title="Fatjet invariant mass (channel %s)" % channel,
        xTitle="Invariant mass [GeV]")

    plots.append(
        SummedPlot(
            "%s_fatjet_invMass_%s" % (channel, suffix),
            [plot_hasBothSubjets_invMass, plot_hasNotBothSubjets_invMass],
            xTitle="Invariant mass [GeV]"))

    return plots
Ejemplo n.º 25
0
    def definePlots(self, t, noSel, sample=None, sampleCfg=None):    
        from bamboo.analysisutils import forceDefine
        from bamboo.plots import Plot
        from bamboo.plots import EquidistantBinning as EqB
        from bamboo import treefunctions as op

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

                # --- to get the Ellipses plots  
                plots.extend(MakeEllipsesPLots(self, TwoLeptonsTwoBjets_Res, bjets_resolved, dilepton, wp, channel, "resolved"))
                plots.extend(MakeEllipsesPLots(self, TwoLeptonsTwoBjets_Boo, bjets_boosted, dilepton, wp, channel, "boosted"))
        
        return plots
Ejemplo n.º 26
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
    def definePlots(self, t, noSel, sample=None, sampleCfg=None):
        from bamboo.plots import Plot, CutFlowReport
        from bamboo.plots import EquidistantBinning as EqB
        from bamboo import treefunctions as op

        plots = []

        #definitions

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

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

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

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

        met = op.select(t.metpuppi)

        #selections

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        # Efficiency Report on terminal and the .tex output

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

        plots.append(cfr)
                            
        return plots
Ejemplo n.º 28
0
    def __init__(self, HHself):
        # All the attributes of the BaseHH are contained in HHself object
        # All the lambdas will be saved in the highlevelLambdas object to avoid confusions of all the attributes of HH base object

        # 4-Momentum association #
        self.ll_p4 = lambda l1, l2: l1.p4 + l2.p4
        self.lljj_p4 = lambda l1, l2, j1, j2: l1.p4 + l2.p4 + j1.p4 + j2.p4
        self.lep1j_p4 = lambda lep, j1: lep.p4 + j1.p4
        self.lep2j_p4 = lambda lep, j1, j2: lep.p4 + j1.p4 + j2.p4
        self.lep3j_p4 = lambda lep, j1, j2, j3: lep.p4 + j1.p4 + j2.p4 + j3.p4
        self.lep4j_p4 = lambda lep, j1, j2, j3, j4: lep.p4 + j1.p4 + j2.p4 + j3.p4 + j4.p4

        # bReg corr 4 momenta of ak4-bTagged jet #
        self.bJetCorrP4 = lambda j: op._to.Construct(
            "ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiM4D<float> >",
            (j.pt * j.bRegCorr, j.eta, j.phi, j.mass)).result

        # Dilep-Met variables #
        self.DilepMET_deltaPhi = lambda l1, l2, met: self.ll_p4(l1, l2).Phi(
        ) - met.phi
        self.DilepMET_Pt = lambda l1, l2, met: op.sqrt(
            op.pow(met.pt * op.cos(met.phi) + self.ll_p4(l1, l2).Px(), 2) + op.
            pow(met.pt * op.sin(met.phi) + self.ll_p4(l1, l2).Py(), 2))
        # SingleLep-Met variables
        self.SinglepMet_Pt = lambda lep, met: op.sqrt(
            op.pow(met.pt * op.cos(met.phi) + lep.p4.Px(), 2) + op.pow(
                met.pt * op.sin(met.phi) + lep.p4.Py(), 2))
        self.SinglepMet_dPhi = lambda lep, met: lep.p4.Phi() - met.phi

        # Transverse mass #
        self.MT_ll = lambda l1, l2, met: op.sqrt(2 * self.ll_p4(l1, l2).Pt(
        ) * met.pt * (1 - op.cos(self.ll_p4(l1, l2).Phi() - met.phi)))
        self.MT_lljj = lambda l1, l2, j1, j2, met: op.sqrt(
            2 * self.lljj_p4(l1, l2, j1, j2).Pt() * met.pt *
            (1 - op.cos(self.lljj_p4(l1, l2, j1, j2).Phi() - met.phi)))
        self.MT = lambda lep, met: op.sqrt(2 * lep.p4.Pt() * met.pt * (
            1 - op.cos(lep.p4.Phi() - met.phi)))
        self.MT_W1W2_ljj = lambda lep, j1, j2, met: op.sqrt(
            2 * self.lep2j_p4(lep, j1, j2).Pt() * met.pt *
            (1 - op.cos(self.lep2j_p4(lep, j1, j2).Phi() - met.phi)))
        self.MT_W1W2_lj = lambda lep, j1, met: op.sqrt(
            2 * self.lep1j_p4(lep, j1).Pt() * met.pt *
            (1 - op.cos(self.lep1j_p4(lep, j1).Phi() - met.phi)))
        # TODO : clean different versions (eg MT)

        # dilep + dijet #
        self.M_lljj = lambda l1, l2, j1, j2: op.invariant_mass(
            self.lljj_p4(l1, l2, j1, j2))
        self.MinDR_lj = lambda l1, l2, j1, j2: op.min(
            op.min(op.deltaR(l1.p4, j1.p4), op.deltaR(l1.p4, j2.p4)),
            op.min(op.deltaR(l2.p4, j1.p4), op.deltaR(l2.p4, j2.p4)))

        self.MinDR_lep3j = lambda lep, j1, j2, j3: op.min(
            op.min(op.deltaR(lep.p4, j1.p4), op.deltaR(lep.p4, j2.p4)),
            op.deltaR(lep.p4, j3.p4))

        # Higgs related variables #
        self.HT2 = lambda l1, l2, j1, j2, met: op.sqrt(
            op.pow(met.pt * op.cos(met.phi) + l1.p4.Px() + l2.p4.Px(), 2) + op.
            pow(met.pt * op.sin(met.phi) + l1.p4.Py() + l2.p4.Py(), 2
                )) + op.abs((j1.p4 + j2.p4).Pt())
        self.HT2R = lambda l1, l2, j1, j2, met: self.HT2(
            met, l1, l2, j1, j2) / (met.pt + l1.p4.Pt() + l2.p4.Pt() + j1.p4.
                                    Pt() + j2.p4.Pt())
        self.HT2_l3jmet = lambda l, j1, j2, j3, met: op.sqrt(
            op.pow(met.pt * op.cos(met.phi) + l.p4.Px(), 2) + op.pow(
                met.pt * op.sin(met.phi) + l.p4.Py(), 2)) + op.abs(
                    (j1.p4 + j2.p4 + j3.p4).Pt())
        self.HT2R_l3jmet = lambda l, j1, j2, j3, met: self.HT2_l3jmet(
            met, l, j1, j2, j3) / (met.pt + l.p4.Pt() + j1.p4.Pt() + j2.p4.Pt(
            ) + j3.p4.Pt())
        self.HT2_l4jmet = lambda l, j1, j2, j3, j4, met: op.sqrt(
            op.pow(met.pt * op.cos(met.phi) + l.p4.Px(), 2) + op.pow(
                met.pt * op.sin(met.phi) + l.p4.Py(), 2)) + op.abs(
                    (j1.p4 + j2.p4 + j3.p4 + j4.p4).Pt())
        self.HT2R_l4jmet = lambda l, j1, j2, j3, j4, met: self.HT2_l4jmet(
            met, l, j1, j2, j3, j4) / (met.pt + l.p4.Pt() + j1.p4.Pt() + j2.p4.
                                       Pt() + j3.p4.Pt() + j4.p4.Pt())

        #min j1j2DR
        self.MinDiJetDRLoose = lambda j1, j2, j3: op.min(
            op.min(op.deltaR(j1.p4, j2.p4), op.deltaR(j2.p4, j3.p4)),
            op.deltaR(j1.p4, j3.p4))

        # ------------------------------------ lambdas for BDT variables ------------------------------------ #
        self.mindr_lep1_jet = lambda lep, jets: op.deltaR(
            lep.p4,
            op.sort(jets, lambda j: op.deltaR(lep.p4, j.p4))[0].p4)
        self.HT = lambda jets: op.rng_sum(jets, lambda j: j.p4.Pt())

        # mT2
        self.ET = lambda lep: op.sqrt(
            op.pow(lep.p4.M(), 2) + op.pow(lep.p4.Pt(), 2))
        self.mT2 = lambda jet, lep, met: (
            op.pow(jet.p4.M(), 2) + op.pow(lep.p4.M(), 2) + op.pow(
                met.p4.M(), 2) + 2 *
            (ET(lep) * ET(jet) -
             (lep.p4.Px() * jet.p4.Px() + lep.p4.Py() * jet.p4.Py())) + 2 *
            (ET(lep) * ET(met) -
             (lep.p4.Px() * met.p4.Px() + lep.p4.Py() * met.p4.Py())) + 2 *
            (ET(jet) * ET(met) -
             (jet.p4.Px() * met.p4.Px() + jet.p4.Py() * met.p4.Py())))

        # pZ component of met
        # https://github.com/HEP-KBFI/hh-bbww/blob/f4ab60f81a920268a3f2187b97a58ec449b26883/src/comp_metP4_B2G_18_008.cc
        # some necessary constants (visP4 = lepP4 + Wjj_simple)
        # - - - - - used to compute neuP4 - - - - - #
        _a = lambda visP4, met, mH: (op.pow(mH, 2) - op.pow(visP4.M(
        ), 2) + 2. * visP4.Px() * met.p4.Px() + 2. * visP4.Py() * met.p4.Py())
        _A = lambda visP4: 4.0 * op.pow(visP4.E(), 2) - op.pow(visP4.Pz(), 2)
        _B = lambda visP4, met, mH: -4.0 * _a(visP4, met, mH) * visP4.Pz()
        _C = lambda visP4, met, mH: 4.0 * op.pow(visP4.E(), 2) * (op.pow(
            met.p4.Px(), 2) + op.pow(met.p4.Py(), 2)) - op.pow(
                _a(visP4, met, mH), 2)
        _D = lambda visP4, met, mH: (op.pow(_B(visP4, met, mH), 2) - 4.0 * _A(
            visP4) * _C(visP4, met, mH))
        _pos = lambda visP4, met, mH: (-_B(visP4, met, mH) + op.sqrt(
            _D(visP4, met, mH))) / (2. * _A(visP4))
        _neg = lambda visP4, met, mH: (-_B(visP4, met, mH) - op.sqrt(
            _D(visP4, met, mH))) / (2. * _A(visP4))
        neuPz = lambda visP4, met, mH: (op.switch(
            _D(visP4, met, mH) < 0., -_B(visP4, met, mH) / (2. * _A(visP4)),
            op.switch(
                op.abs(_pos(visP4, met, mH)) < op.abs(_neg(visP4, met, mH)),
                _pos(visP4, met, mH), _neg(visP4, met, mH))))
        # - - - - - - - - - - - - - - - - - - - - - #
        neuP4 = lambda visP4, met, mH: op._to.Construct(
            "ROOT::Math::LorentzVector<ROOT::Math::PxPyPzE4D<float> >",
            (met.p4.Px(), met.p4.Py(), neuPz(visP4, met, mH),
             op.sqrt(
                 op.pow(met.p4.Px(), 2) + op.pow(met.p4.Py(), 2) + op.pow(
                     neuPz(visP4, met, mH), 2)))).result

        # P4 of W1 (l,neu)
        self.Wlep_simple = lambda j1P4, j2P4, lepP4, met, mH: lepP4 + neuP4(
            j1P4 + j2P4 + lepP4, met, mH)
        # P4 of W2 (j,j)
        self.Wjj_simple = lambda j1P4, j2P4: j1P4 + j2P4
        # P4 of HWW (W1 + W2)
        self.HWW_simple = lambda j1P4, j2P4, lepP4, met, mH: Wjj_simple(
            j1P4, j2P4) + Wlep_simple(lepP4, neuP4(j1P4 + j2P4 + lepP4, met, mH
                                                   ))
        # dR_HWW
        self.dR_Hww = lambda j1P4, j2P4, lepP4, met, mH: op.deltaR(
            Wjj_simple(j1P4, j2P4), Wlep_simple(j1P4, j2P4, lepP4, met, mH))
        # P4 of lep + met
        self.Wlep_met_simple = lambda lepP4, metP4: lepP4 + metP4
        # SimpleP4 of HWW (W1 + W2)
        self.HWW_met_simple = lambda j1P4, j2P4, lepP4, metP4: Wjj_simple(
            j1P4, j2P4) + Wlep_met_simple(lepP4, metP4)
        # Total P4
        self.HHP4_simple_met = lambda HbbRegP4, j1P4, j2P4, lepP4, metP4: HbbRegP4 + Wjj_simple(
            j1P4, j2P4) + Wlep_met_simple(lepP4, metP4)

        # CosThetaS calculation
        #comp_cosThetaS = lambda ob1p4, ob2p4 : op.abs(ob1p4.Boost(-(ob1p4+ob2p4).BoostVector()).CosTheta())
        motherPx = lambda ob1p4, ob2p4: (ob1p4.Px() + ob2p4.Px())
        motherPy = lambda ob1p4, ob2p4: (ob1p4.Py() + ob2p4.Py())
        motherPz = lambda ob1p4, ob2p4: (ob1p4.Pz() + ob2p4.Pz())
        motherE = lambda ob1p4, ob2p4: (ob1p4.E() + ob2p4.E())
        BoostP4 = lambda ob1p4, ob2p4: op._to.Construct(
            "ROOT::Math::LorentzVector<ROOT::Math::PxPyPzE4D<float> >",
            (motherPx(ob1p4, ob2p4), motherPy(ob1p4, ob2p4),
             motherPz(ob1p4, ob2p4), motherE(ob1p4, ob2p4))).result
        self.comp_cosThetaS = lambda ob1p4, ob2p4: op.abs(
            op.cos(op.deltaR(BoostP4(ob1p4, ob2p4), ob1p4)))

        # MET_LD
        # Equation 3 (page 33) of AN-2019/111 v13
        # Similar to MET, but more robust against pileup
        jetSumPx = lambda jets: op.rng_sum(jets, lambda j: j.p4.Px())
        jetSumPy = lambda jets: op.rng_sum(jets, lambda j: j.p4.Py())
        lepSumPx = lambda leps: op.rng_sum(leps, lambda l: l.p4.Px())
        lepSumPy = lambda leps: op.rng_sum(leps, lambda l: l.p4.Py())
        self.MET_LD = lambda met, jets, leps: 0.6 * met.pt + 0.4 * op.sqrt(
            op.pow(jetSumPx(jets) + lepSumPx(leps), 2) + op.pow(
                jetSumPy(jets) + lepSumPy(leps), 2))
Ejemplo n.º 29
0
def returnHighLevelMVAInputs(self, lep, conep4, bjets, wjets, VBFJetPairs, channel):
    if channel == 'El':
        lepconept  = self.electron_conept[lep.idx]
    elif channel == 'Mu':
        lepconept  = self.muon_conept[lep.idx]
    else:
        raise RuntimeError('Please mention the correct channel name!')

    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) )

    
    return {
        #('m_hh_bregcorr',    'm_hh_bregcorr',     (50,0,400))  : self.HLL.comp_m_hh_bregcorr(bjets, wjets, lep, self.corrMET),
        ('m_hh_bregcorr',    'm_hh_bregcorr',     (50,0,400))  : self.HLL.comp_m_hh_bregcorr(bjets, wjets, conep4, self.corrMET),
        #('pt_hh',            'pt_hh',             (50,0,400))  : self.HLL.comp_pt_hh(bjets, wjets, lep, self.corrMET),
        ('pt_hh',            'pt_hh',             (50,0,400))  : self.HLL.comp_pt_hh(bjets, wjets, conep4, self.corrMET),
        ('m_hbb_bregcorr',   'm_hbb_bregcorr',    (25,0,200))  : 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]))),
        ('pt_hbb',           'pt_hbb',            (25,0,200))  : op.multiSwitch((op.rng_len(bjets) == 0, op.c_float(0.)),
                                                                                (op.rng_len(bjets) == 1, bjets[0].pt),
                                                                                (bjets[0].p4 + bjets[1].p4).Pt()),
        #('m_hww',            'm_hww',             (25,0,200))  : op.multiSwitch((op.rng_len(wjets) >= 2, op.invariant_mass(wjets[0].p4 ,wjets[1].p4, self.corrMET.p4, lep.p4)),
        #                                                                        (op.rng_len(wjets) == 1, op.invariant_mass(wjets[0].p4 ,self.corrMET.p4, lep.p4)),
        #                                                                        op.invariant_mass(self.corrMET.p4, lep.p4)),
        ('m_hww',            'm_hww',             (25,0,200))  : op.multiSwitch((op.rng_len(wjets) >= 2, op.invariant_mass(wjets[0].p4 ,wjets[1].p4, self.corrMET.p4, conep4)),
                                                                                (op.rng_len(wjets) == 1, op.invariant_mass(wjets[0].p4 ,self.corrMET.p4, conep4)),
                                                                                op.invariant_mass(self.corrMET.p4, conep4)),
        #('pt_hww',           'pt_hww',            (25,0,200))  : op.multiSwitch((op.rng_len(wjets) >= 2, (wjets[0].p4 + wjets[1].p4 + self.corrMET.p4 + lep.p4).Pt()),
        #                                                                        (op.rng_len(wjets) == 1, (wjets[0].p4 + self.corrMET.p4 + lep.p4).Pt()),
        #                                                                        (self.corrMET.p4 + lep.p4).Pt()),
        ('pt_hww',           'pt_hww',            (25,0,200))  : op.multiSwitch((op.rng_len(wjets) >= 2, (wjets[0].p4 + wjets[1].p4 + self.corrMET.p4 + conep4).Pt()),
                                                                                (op.rng_len(wjets) == 1, (wjets[0].p4 + self.corrMET.p4 + conep4).Pt()),
                                                                                (self.corrMET.p4 + conep4).Pt()),
        ('m_wjj',            'm_wjj',             (25,0,200))  : op.multiSwitch((op.rng_len(wjets) >= 2, op.invariant_mass(wjets[0].p4 ,wjets[1].p4)),
                                                                                (op.rng_len(wjets) == 1, wjets[0].mass),
                                                                                op.c_float(0.)),
        ('pt_wjj',           'pt_wjj',            (25,0,200))  : op.multiSwitch((op.rng_len(wjets) >= 2, (wjets[0].p4 + wjets[1].p4).Pt()),
                                                                                (op.rng_len(wjets) == 1, wjets[0].pt),
                                                                                op.c_float(0.)),
        #('m_wlep',           'm_wlep',            (25,0,200))  : op.invariant_mass(self.corrMET.p4, lep.p4),    
        ('m_wlep',           'm_wlep',            (25,0,200))  : op.invariant_mass(self.corrMET.p4, conep4),    
        #('pt_wlep',          'pt_wlep',           (25,0,200))  : (self.corrMET.p4 + lep.p4).Pt(),
        ('pt_wlep',          'pt_wlep',           (25,0,200))  : (self.corrMET.p4 + conep4).Pt(),
        ('min_dr_lepbjets',  'min_dr_lepbjets',   (25,0,5))    : op.switch(op.rng_len(bjets) > 0, self.HLL.MinDR_part1_partCont(lep, bjets), op.c_float(0.)),
        #('dphi_hbb_hww',     'dphi_hbb_hww',      (22,0,3.2))  : op.abs(self.HLL.comp_dphi_hbb_hww(bjets, wjets, lep, self.corrMET)),
        ('dphi_hbb_hww',     'dphi_hbb_hww',      (22,0,3.2))  : op.abs(self.HLL.comp_dphi_hbb_hww(bjets, wjets, conep4, self.corrMET)),
        #('dphi_hbb_hwwvis',  'dphi_hbb_hwwvis',   (22,0,3.2))  : op.abs(self.HLL.comp_dphi_hbb_hwwvis(bjets, wjets, lep)),
        ('dphi_hbb_hwwvis',  'dphi_hbb_hwwvis',   (22,0,3.2))  : op.abs(self.HLL.comp_dphi_hbb_hwwvis(bjets, wjets, conep4)),
        #('dphi_met_lep',     'dphi_met_lep',      (22,0,3.2))  : op.abs(op.deltaPhi(self.corrMET.p4, lep.p4)),
        ('dphi_met_lep',     'dphi_met_lep',      (22,0,3.2))  : op.abs(op.deltaPhi(self.corrMET.p4, conep4)),
        ('dphi_met_hbb',     'dphi_met_hbb',      (22,0,3.2))  : op.multiSwitch((op.rng_len(bjets) >= 2, op.abs(op.deltaPhi(self.corrMET.p4,(bjets[0].p4 + bjets[1].p4)))),
                                                                                (op.rng_len(bjets) == 1, op.abs(op.deltaPhi(self.corrMET.p4, bjets[0].p4))),
                                                                                op.c_float(0.)),
        ('dphi_met_wjj',     'dphi_met_wjj',      (22,0,3.2))  : op.multiSwitch((op.rng_len(wjets) >= 2, op.abs(op.deltaPhi(self.corrMET.p4,(wjets[0].p4 + wjets[1].p4)))),
                                                                                (op.rng_len(wjets) == 1, op.abs(op.deltaPhi(self.corrMET.p4,wjets[0].p4))),
                                                                                op.c_float(0.)),
        ('dr_lep_hbb',       'dr_lep_hbb',        (25,0,5))    : op.multiSwitch((op.rng_len(bjets) >= 2, op.deltaR(conep4, (bjets[0].p4+bjets[1].p4))), 
                                                                                (op.rng_len(bjets) == 1, op.deltaR(conep4, bjets[0].p4)),
                                                                                op.c_float(0.)),
        ('dr_lep_wjj',       'dr_lep_wjj',        (25,0,5))    : op.multiSwitch((op.rng_len(wjets) >= 2, op.deltaR(conep4, (wjets[0].p4+wjets[1].p4))),
                                                                                (op.rng_len(wjets) == 1, op.deltaR(conep4, wjets[0].p4)),
                                                                                op.c_float(0.)),
        ('min_dr_wjets',     'min_dr_wjets',      (25,0,5))    : op.switch(op.rng_len(wjets) >= 2, op.deltaR(wjets[0].p4, wjets[1].p4), op.c_float(0.)),
        ('min_dhi_wjets',    'min_dphi_wjets',    (22,0,3.2))  : op.switch(op.rng_len(wjets) >= 2, op.abs(op.deltaPhi(wjets[0].p4,wjets[1].p4)),op.c_float(0.)),
        ('min_dr_bjets',     'min_dr_bjets',      (25,0,5))    : op.switch(op.rng_len(bjets) >= 2, op.deltaR(bjets[0].p4,bjets[1].p4), op.c_float(0.)),
        ('min_dphi_bjets',   'min_dphi_bjets',    (22,0,3.2))  : op.switch(op.rng_len(bjets) >= 2, op.abs(op.deltaPhi(bjets[0].p4,bjets[1].p4)),op.c_float(0.)),
        ('ht',               'ht',                (50,0,300))  : op.rng_sum(self.ak4Jets, lambda j : j.pt),
        #('smin',             'smin',              (50,0,300))  : self.HLL.comp_smin(lep,self.corrMET,self.ak4Jets,bjets,wjets), 
        ('smin',             'smin',              (50,0,300))  : self.HLL.comp_smin(conep4,self.corrMET,self.ak4Jets,bjets,wjets), 
        ('vbf_pair_mass',    'vbf_pair_mass',     (50,0,300))  : 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_pairs_absdeltaeta', (22,0,3.2)) : op.switch(op.rng_len(VBFJetPairs) > 0,op.abs(VBFJetPairs[0][0].eta - VBFJetPairs[0][1].eta),
                                                                                   op.c_float(0.)),
        ('lep_conept',       'lep_conept',        (25,0,200))  : lepconept,
        ('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.rng_len(self.ak8BJets) > 0),
        ('n_btag',           'n_btag',            (5,0,5))     : op.c_float(op.rng_len(self.ak4BJets)),
        ('sphericity',       'sphericity',        (1,0,1))     : op.c_float(0.), # not used
        ('sphericity_T',     'sphericity_T',      (1,0,1))     : op.c_float(0.), # not used
        ('aplanarity',       'aplanarity',        (1,0,1))     : op.c_float(0.), # not used
        ('eventshape_C',     'eventshape_C',      (1,0,1))     : op.c_float(0.), # not used
        ('eventshape_D',     'eventshape_D',      (1,0,1))     : op.c_float(0.), # not used
        ('eventshape_Y',     'eventshape_Y',      (1,0,1))     : op.c_float(0.), # not used
        ('foxwolfram1',      'foxwolfram1',       (1,0,1))     : op.c_float(0.), # not used
        ('foxwolfram2',      'foxwolfram2',       (1,0,1))     : op.c_float(0.), # not used
        ('foxwolfram3',      'foxwolfram3',       (1,0,1))     : op.c_float(0.), # not used
        ('foxwolfram4',      'foxwolfram4',       (1,0,1))     : op.c_float(0.), # not used
        ('foxwolfram5',      'foxwolfram5',       (1,0,1))     : op.c_float(0.), # not used
        ('centrality',       'centrality',        (1,0,1))     : op.c_float(0.), # not used
        ('centrality_jets',  'centrality_jets',   (1,0,1))     : op.c_float(0.), # not used
        ('eigenvalue1',      'eigenvalue1',       (1,0,1))     : op.c_float(0.), # not used
        ('eigenvalue2',      'eigenvalue2',       (1,0,1))     : op.c_float(0.), # not used
        ('eigenvalue3',      'eigenvalue3',       (1,0,1))     : op.c_float(0.), # not used
        ('sphericity_met',   'sphericity_met',    (1,0,1))     : op.c_float(0.), # not used
        ('sphericity_T_met', 'sphericity_T_met',  (1,0,1))     : op.c_float(0.), # not used
        ('aplanarity_met',   'aplanarity_met',    (1,0,1))     : op.c_float(0.), # not used
        ('eventshape_C_met', 'eventshape_C_met',  (1,0,1))     : op.c_float(0.), # not used
        ('eventshape_D_met', 'eventshape_D_met',  (1,0,1))     : op.c_float(0.), # not used
        ('eventshape_Y_met', 'eventshape_Y_met',  (1,0,1))     : op.c_float(0.), # not used
        ('foxwolfram1_met',  'foxwolfram1_met',   (1,0,1))     : op.c_float(0.), # not used
        ('foxwolfram2_met',  'foxwolfram2_met',   (1,0,1))     : op.c_float(0.), # not used
        ('foxwolfram3_met',  'foxwolfram3_met',   (1,0,1))     : op.c_float(0.), # not used
        ('foxwolfram4_met',  'foxwolfram4_met',   (1,0,1))     : op.c_float(0.), # not used
        ('foxwolfram5_met',  'foxwolfram5_met',   (1,0,1))     : op.c_float(0.), # not used
        ('centrality_met',   'centrality_met',    (1,0,1))     : op.c_float(0.), # not used
        ('centrality_jets_met','centrality_jets_met', (1,0,1)) : op.c_float(0.), # not used
        ('eigenvalue1_met',  'eigenvalue1_met',   (1,0,1))     : op.c_float(0.), # not used
        ('eigenvalue2_met',  'eigenvalue2_met',   (1,0,1))     : op.c_float(0.), # not used
        ('eigenvalue3_met',  'eigenvalue3_met',   (1,0,1))     : op.c_float(0.)  # not used
    }