Skip to content

How rootfig relates to uproot, Awkward, hist, mplhep, matplotlib and SciPy

rootfig is a thin, opinionated layer over the Scientific Python HEP stack. It owns no file format, array type, histogram type or drawing primitive of its own; every object you get back belongs to one of the libraries below.

uproot

uproot reads and writes ROOT files in pure Python. rootfig uses it for all I/O: opening files, detecting the tree, listing branches, and reading the branches an expression needs from one or many files (TTree and RNTuple). uproot also has its own expression language for TTree.arrays(expressions, cut=...); rootfig implements a similar one so that it can validate names before reading, give precise errors, support in-memory data, and define the per-object/per-event rules that arrays(cut=...) leaves to the caller.

Awkward Array

Awkward Array is the array library for jagged data. Everything rootfig computes is an Awkward array; the selection layer is a small set of rules (broadcast, mask, flatten) expressed with ak.num, ak.broadcast_arrays, boolean indexing and ak.flatten. rf.load returns an Awkward record array, and rf.evaluate runs one expression on arrays you already have.

hist and boost-histogram

hist provides the histogram objects. rootfig fills hist.Hist with Weight storage (sum of weights and sum of squared weights per bin), including under/overflow bins, and returns them unchanged: rf.histogram gives you the hist.Hist, Plot.hists lists them. Rebinning, projecting, slicing, saving to ROOT files with uproot: all of that is hist functionality and works directly on the returned objects. Histograms stored in ROOT files (TH1, TH2) are converted by uproot's to_hist(); rootfig adds the summing over files, the scaling and the drawing.

mplhep

mplhep draws histograms with matplotlib and ships the style sheets and label helpers of the LHC experiments. rootfig draws every histogram through mplhep.histplot/hist2dplot and uses mplhep's per-experiment label functions when a Style(experiment=...) is given. The experiment-neutral default style and the lower panel (ratios, differences, asymmetries, pulls and significances of histograms; ratios, differences, asymmetries and pulls of efficiencies and profiles) are rootfig's, and so are the Poisson intervals of data: mplhep's (and hist.intervals) give an empty bin of scaled counts the scale of a neighbour, where rootfig keeps the bin's own (see SciPy).

matplotlib

Every figure is a plain matplotlib.figure.Figure with plain Axes. rootfig applies its style only inside a plt.style.context while drawing, so it does not change global rcParams (unless you call rf.use_style). Anything you would do to a matplotlib figure, you can do to Plot.fig and Plot.ax.

SciPy

SciPy supplies the quantiles behind rootfig's intervals, from scipy.special: the inverse incomplete gamma functions for the Garwood interval of data (ROOT's TH1::kPoisson) and the inverse incomplete beta function for the Clopper–Pearson and Bayesian intervals of efficiencies (TEfficiency's default and its Beta priors); scipy.optimize.brentq finds the bounds that have no closed form (the shortest Bayesian interval). rootfig decides what the quantiles are taken of (the counts behind scaled or normalised contents, which interval ROOT would choose) and imports SciPy only when it computes one. hist.intervals holds the same Garwood, Clopper–Pearson and Poisson-ratio intervals, and rootfig's tests check that both agree to round-off. rootfig does not call it at run time: it imports scipy.stats, which takes 0.4 s or more on the first interval of every session, for a computation of a few lines.

Trees and histogram files

rootfig reads trees and stored TH1/TH2 histograms without ROOT, independently of the framework that wrote them. A Sample identifies each input process, a Group combines processes into a category, and stack= selects the categories to stack. Files already scaled to expected yields are read as they are; trees can be scaled with Sample(xsec=..., ngen=...) and lumi=.

The same Variable describes a stored histogram and the branch it was filled from: its bins and range crop and merge existing bins, moving the rest into flow bins. PlotBook prepares each variable once for its drawing variants and can discover shared histograms with rf.ALL. See the complete histogram-file example.

When to use something else

  • You have flat NumPy columns rather than ROOT files or histograms, or want a comparison rootfig's lower panel does not offer (a goodness-of-fit panel): plothist.
  • You need a full columnar analysis framework with lazy, distributed processing: coffea. rootfig reads the branches a plot needs a chunk of entries at a time, in threads, and holds the values it fills (see large inputs), all in one process: it suits quick looks and ntuples that one machine reads in minutes, not multi-terabyte datasets.
  • You want to build fit templates and workspaces: cabinetry.
  • You want a quick terminal look at a branch: histoprint.