Skip to main content

rootfig

Publication-quality figures straight from ROOT trees, without ROOT.

Docs CI codecov PyPI Python License

Documentation · Gallery · Quick start

Go from ROOT files to a styled figure in one call. Choose a variable, add a selection, and plot:

import rootfig as rf

rf.plot("events.root", "Muon_pt", tree="events", selection="Muon_pt > 20", bins=50)

Start with a single distribution; add samples, weights, stacks and ratio panels as your analysis grows. Every plot gives you a matplotlib figure to customise and save. No ROOT installation required.

Stacked simulation with data and a ratio panel Broken x axis with a ratio panel

Per-object versus per-event selections Two-dimensional histogram

Explore the gallery → See each figure alongside the code that makes it, from simple overlays to stacked data/MC comparisons, broken axes and 2D histograms.

Installation

pip install rootfig
# or
uv add rootfig

Python 3.12 or newer. No ROOT installation is needed; TTree and RNTuple files are both supported.

Compare samples in one call

import rootfig as rf

# Overlay two samples, normalised to unity, with a ratio panel.
rf.plot(
    ["signal.root", "background.root"],
    "Muon_pt",
    tree="events",
    selection="abs(Muon_eta) < 2.5",
    weight="event_weight",
    bins=(50, 0, 200),
    normalize=True,
    ratio=True,
)

Build up to a full analysis

Define samples, variables, cuts and styles once, then reuse them across plots:

import rootfig as rf

signal = rf.Sample("sig_*.root", tree="events", label="Signal", weight="mc_weight")
background = rf.Sample("bkg.root", tree="events", label="Background", weight="mc_weight")
data = rf.Sample("data.root", tree="events", label="Data", is_data=True)

pt = rf.Variable("Muon_pt", bins=(50, 0, 200), label=r"$p_T^{\mu}$", unit="GeV")
baseline = rf.Cut("nMuon >= 1") & "abs(Muon_eta) < 2.5"
style = rf.Style(experiment="ATLAS", status="Internal", lumi=140, com=13.6)

p = rf.plot(
    [background, signal],
    pt,
    observed=data,
    selection=baseline,
    stack=True,
    ratio=True,
    logy=True,
    style=style,
)
p.ax.set_ylim(top=1e5)  # it is a normal matplotlib Axes
p.save("muon_pt.pdf")

Everything you get back is a standard object: p.fig and p.ax are matplotlib Figure/Axes, p.hists are hist.Hist objects, and rf.load(...) returns Awkward arrays.

What you can do

  • Select events and objects with readable expressions. Write cuts such as count(Jet_pt) >= 2 or Muon_pt > 20; event and object selections have explicit rules, and event weights carry through to each selected object.
  • Compare samples with a few keywords. Overlays, stacks, data points and ratio panels share binning and propagate histogram uncertainties. Normalise to unity, density, bin width or luminosity.
  • Style figures for your analysis. Add experiment labels, units, log axes and broken axes, then refine the result with matplotlib.
  • Go beyond 1D plots. Draw 2D histograms, correlations, efficiencies, profiles, resolutions and significance panels; produce cut flows and summary statistics from the same inputs.
  • Work directly with your files. Read TTree and RNTuple data, combine files with globs, limit entry ranges for quick checks, and use EDM4hep split collections. Only the branches your expressions need are read.

Documentation

Read the docs or browse the gallery for examples with figures and code.

Relation to the ecosystem

rootfig brings a TTree::Draw-like workflow to the Scientific Python HEP stack, building on familiar libraries:

Task Library What rootfig adds
Reading ROOT files uproot file globs, tree auto-detection, reading only the required branches
Jagged arrays Awkward Array the per-event/per-object rules for cuts and weights
Histograms hist / boost-histogram shared binning, automatic ranges, normalisation, ratios
Drawing mplhep + matplotlib overlays, stacks, ratio panels, labels and legends with good defaults

If you already have hist.Hist objects, rf.plot_histograms draws them with the same options. If you want the arrays, rf.load returns them. See the ecosystem guide for details.

Development

git clone https://github.com/jbeirer/rootfig
cd rootfig
uv sync --all-groups
uv run pytest
uv run ruff check . && uv run ruff format --check .
uv run mypy

See CONTRIBUTING.md for details.

License

MIT. See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rootfig-0.2.2.tar.gz (1.3 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rootfig-0.2.2-py3-none-any.whl (105.1 kB view details)

Uploaded Python 3

File details

Details for the file rootfig-0.2.2.tar.gz.

File metadata

  • Download URL: rootfig-0.2.2.tar.gz
  • Upload date:
  • Size: 1.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for rootfig-0.2.2.tar.gz
Algorithm Hash digest
SHA256 e35afe61965c0546f3859924c38f6423c30b1b20ec44ea2b6f517828fab73b86
MD5 fcc9d94374dc9f1cf069423f77114c96
BLAKE2b-256 f5307d1de2e015dff5fc82b3d6cd0b0379b24353486238f8a9a26dda7d90e915

See more details on using hashes here.

Provenance

The following attestation bundles were made for rootfig-0.2.2.tar.gz:

Publisher: release.yml on jbeirer/rootfig

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rootfig-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: rootfig-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 105.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for rootfig-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 076e9f0f14108169b25aae34559fc930a456d238cd960a2b1b2ff7d2a4c700f9
MD5 a0f4c3928b9c27d542974005708d2460
BLAKE2b-256 72b2e7f5a36f53180509127e654f8f9fed1e49add02633b1290791cf001fdd00

See more details on using hashes here.

Provenance

The following attestation bundles were made for rootfig-0.2.2-py3-none-any.whl:

Publisher: release.yml on jbeirer/rootfig

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.5.0

2 files

0.4.0

2 files

0.3.0

2 files

This release

0.2.2 This release

2 files

0.2.1

2 files

0.2.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page