Skip to content

Systematic uncertainties in a stack and its ratio panel

A sample lists its sources of systematic uncertainty by name: a pair of weight expressions, a relative normalisation uncertainty, or a mapping of shifted branches, which also move the selection. systematics= on the plot adds a source to every simulated sample. The hatched band and the ratio band combine the statistical and systematic uncertainties; a source with the same name in several samples is correlated, different sources add in quadrature. p.uncertainty() returns every component.

import rootfig as rf

style = rf.Style()

jes = {"MET": ("MET_jesUp", "MET_jesDown")}
zjets = rf.Sample(
    "background.root",
    tree="events",
    label="Z + jets",
    weight="weight",
    systematics={"pileup": ("weight_pu_up", "weight_pu_down"), "jes": jes},
)
diboson = rf.Sample(
    "diboson.root",
    tree="events",
    label="Diboson",
    weight="weight",
    scale=0.15,
    systematics={"jes": jes, "xsec": 0.10},
)
rf.plot(
    [zjets, diboson, signal],
    met,
    observed=data,
    stack=True,
    ratio=True,
    logy=True,
    systematics={"lumi": 0.02},
    style=style,
)
import rootfig as rf

style = rf.Style(experiment="ATLAS", status="Internal", lumi=140, com=13.6)

jes = {"MET": ("MET_jesUp", "MET_jesDown")}
zjets = rf.Sample(
    "background.root",
    tree="events",
    label="Z + jets",
    weight="weight",
    systematics={"pileup": ("weight_pu_up", "weight_pu_down"), "jes": jes},
)
diboson = rf.Sample(
    "diboson.root",
    tree="events",
    label="Diboson",
    weight="weight",
    scale=0.15,
    systematics={"jes": jes, "xsec": 0.10},
)
rf.plot(
    [zjets, diboson, signal],
    met,
    observed=data,
    stack=True,
    ratio=True,
    logy=True,
    systematics={"lumi": 0.02},
    style=style,
)
import rootfig as rf

style = rf.Style(experiment="CMS", status="Preliminary", lumi=138, com=13.6)

jes = {"MET": ("MET_jesUp", "MET_jesDown")}
zjets = rf.Sample(
    "background.root",
    tree="events",
    label="Z + jets",
    weight="weight",
    systematics={"pileup": ("weight_pu_up", "weight_pu_down"), "jes": jes},
)
diboson = rf.Sample(
    "diboson.root",
    tree="events",
    label="Diboson",
    weight="weight",
    scale=0.15,
    systematics={"jes": jes, "xsec": 0.10},
)
rf.plot(
    [zjets, diboson, signal],
    met,
    observed=data,
    stack=True,
    ratio=True,
    logy=True,
    systematics={"lumi": 0.02},
    style=style,
)
import rootfig as rf

style = rf.Style(experiment="LHCb", status="Preliminary", lumi=9, com=13.6)

jes = {"MET": ("MET_jesUp", "MET_jesDown")}
zjets = rf.Sample(
    "background.root",
    tree="events",
    label="Z + jets",
    weight="weight",
    systematics={"pileup": ("weight_pu_up", "weight_pu_down"), "jes": jes},
)
diboson = rf.Sample(
    "diboson.root",
    tree="events",
    label="Diboson",
    weight="weight",
    scale=0.15,
    systematics={"jes": jes, "xsec": 0.10},
)
rf.plot(
    [zjets, diboson, signal],
    met,
    observed=data,
    stack=True,
    ratio=True,
    logy=True,
    systematics={"lumi": 0.02},
    style=style,
)
import rootfig as rf

style = rf.Style(experiment="ALICE", status="Preliminary")

jes = {"MET": ("MET_jesUp", "MET_jesDown")}
zjets = rf.Sample(
    "background.root",
    tree="events",
    label="Z + jets",
    weight="weight",
    systematics={"pileup": ("weight_pu_up", "weight_pu_down"), "jes": jes},
)
diboson = rf.Sample(
    "diboson.root",
    tree="events",
    label="Diboson",
    weight="weight",
    scale=0.15,
    systematics={"jes": jes, "xsec": 0.10},
)
rf.plot(
    [zjets, diboson, signal],
    met,
    observed=data,
    stack=True,
    ratio=True,
    logy=True,
    systematics={"lumi": 0.02},
    style=style,
)
import rootfig as rf

style = rf.Style(experiment="DUNE", status="Preliminary")

jes = {"MET": ("MET_jesUp", "MET_jesDown")}
zjets = rf.Sample(
    "background.root",
    tree="events",
    label="Z + jets",
    weight="weight",
    systematics={"pileup": ("weight_pu_up", "weight_pu_down"), "jes": jes},
)
diboson = rf.Sample(
    "diboson.root",
    tree="events",
    label="Diboson",
    weight="weight",
    scale=0.15,
    systematics={"jes": jes, "xsec": 0.10},
)
rf.plot(
    [zjets, diboson, signal],
    met,
    observed=data,
    stack=True,
    ratio=True,
    logy=True,
    systematics={"lumi": 0.02},
    style=style,
)
Setup

The code reads the toy dataset. In a checkout of rootfig, python examples/gallery writes it to examples/out/ in a few seconds; run the code inside that directory.

It uses these samples and variables, shared by the gallery examples (see Samples, variables, cuts and styles):

signal = rf.Sample("signal.root", tree="events", label="Signal", weight="weight", scale=0.03)
zjets = rf.Sample("background.root", tree="events", label="Z + jets", weight="weight")
diboson = rf.Sample("diboson.root", tree="events", label="Diboson", weight="weight", scale=0.15)
data = rf.Sample("data.root", tree="events", label="Data", is_data=True)
mc = [zjets, diboson, signal]  # stacked bottom to top

pt = rf.Variable("Muon_pt", bins=(30, 0, 300), label=r"$p_T^{\mu}$", unit="GeV")
mll = rf.Variable("m_ll", bins=(70, 50, 260), label=r"$m_{\ell\ell}$", unit="GeV")
met = rf.Variable("MET", bins=(40, 0, 400), label=r"$E_T^{miss}$", unit="GeV")