def makeMergedPlots(categDef, newCat, name, binning, var=None, **kwargs):
    """ Make a series of plots which will be merged.
    - cateDef can either be e.g.:
        - `[("mu", muSelection), ("el", elSelection), ...]`, in which case the same variable `var` is used for all sub-categories
        - `[("mu", muSelection, muVar), ("el", elSelection, elVar), ...]`, for cases where the variable is different for each sub-category
    - `newCat`: name of the merged category
    - `name`: name of the merged plot (-> full plot name is newCat_name)
    - `var`: variable to plot (if it is the same for all categories)
    - `binning`: binning to be used
    Any further named args will be forwarded to the plot constructor.
    The variables can also be iterables for multi-dimensional plots.
    """
    plotsToAdd = []

    for cat in categDef:
        if len(cat) == 2:
            (catName, catSel), catVar = cat, var
        elif len(cat) == 3:
            catName, catSet, catVar = cat
        else:
            raise Exception(f"{cat} should have 2 or 3 entries")
        thisName = f"{catName}_{name}"
        if not hasattr(catVar, "__len__"):
            plotType = Plot.make1D
        elif len(catVar) == 2:
            plotType = Plot.make2D
        elif len(catVar) == 3:
            plotType = Plot.make3D
        plotsToAdd.append(plotType(thisName, catVar, catSel, binning,
                                   **kwargs))

    return plotsToAdd + [SummedPlot(f"{newCat}_{name}", plotsToAdd, **kwargs)]
Ejemplo n.º 2
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.º 3
0
def plotRecoForGen(sel, gen, reco, lambda_match, name):
    n_reco = [
        op.select(
            reco, lambda r: op.switch(
                op.rng_len(gen) > i, lambda_match(gen[i], r), op.c_bool(False))
        ) for i in range(10)
    ]

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

    return plots
Ejemplo n.º 4
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
Ejemplo n.º 5
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.º 6
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, 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.º 8
0
    def definePlots(self, t, noSel, sample=None, sampleCfg=None):
        noSel = super(BtagEffAndMistagNano,
                      self).prepareObjects(t,
                                           noSel,
                                           sample,
                                           sampleCfg,
                                           channel='DL',
                                           forSkimmer=True)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        return plots
Ejemplo n.º 9
0
def plotMatching(contName, list_cont, list_sel, partName):
    plots = []

    dr_plots = []
    dr2_plots = []
    ptrel_plots = []
    TF_plots = []
    for idx, (cont, sel) in enumerate(zip(list_cont, list_sel)):
        dr_plots.append(
            Plot.make1D(contName + str(idx) + "_deltaR",
                        op.map(cont, lambda m: op.deltaR(m[0].p4, m[1].p4)),
                        sel,
                        EquidistantBinning(100, 0., 0.2),
                        xTitle="#Delta R(%s_{gen},%s_{reco})" %
                        (partName, partName)))
        dr2_plots.append(
            Plot.make1D(contName + str(idx) + "_deltaR2",
                        op.map(
                            cont,
                            lambda m: op.pow(op.deltaR(m[0].p4, m[1].p4), 2)),
                        sel,
                        EquidistantBinning(100, 0., 0.04),
                        xTitle="#Delta R^{2}(%s_{gen},%s_{reco})" %
                        (partName, partName)))

        ptrel_plots.append(
            Plot.make1D(
                contName + str(idx) + "_deltaPtRel",
                op.map(cont, lambda m: (m[1].pt - m[0].pt) / m[1].pt),
                sel,
                EquidistantBinning(100, -2., 2.),
                xTitle="P_{T}(%s_{reco})-P_{T}(%s_{gen})/P_{T}(%s_{reco})" %
                (partName, partName, partName)))
        TF_plots.append(
            Plot.make2D(contName + str(idx) + "_TF",
                        (op.map(cont, lambda m: m[0].p4.E()),
                         op.map(cont, lambda m: m[1].p4.E() - m[0].p4.E())),
                        sel, [
                            EquidistantBinning(100, 0., 500.),
                            EquidistantBinning(400, -200., 200.)
                        ],
                        xTitle="E^{parton}(e^{-})",
                        yTitle="#Delta E = E^{reco}(%s)-E^{parton}(%s)" %
                        (partName, partName)))

    plots.append(
        SummedPlot(contName + "_deltaR",
                   dr_plots,
                   xTitle="#Delta R(%s_{gen},%s_{reco})" %
                   (partName, partName)))
    plots.append(
        SummedPlot(contName + "_deltaR2",
                   dr2_plots,
                   xTitle="#Delta R^{2}(%s_{gen},%s_{reco})" %
                   (partName, partName)))
    plots.append(
        SummedPlot(contName + "_deltaPtRel",
                   ptrel_plots,
                   xTitle="P_{T}(%s_{reco})-P_{T}(%s_{gen}/P_{T}(%s_{reco})" %
                   (partName, partName, partName)))
    plots.append(
        SummedPlot(contName + "_TF",
                   TF_plots,
                   xTitle="#Delta E = E^{reco}(%s)-E^{patron}(%s)" %
                   (partName, partName)))

    return plots
Ejemplo n.º 10
0
    def definePlots(self, tree, noSel, sample=None, sampleCfg=None):
        plots = []

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

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

        mZ = 91.1876

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

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

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

        return plots