rootfig 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rootfig-0.1.0/.gitignore +21 -0
- rootfig-0.1.0/CHANGELOG.md +87 -0
- rootfig-0.1.0/CONTRIBUTING.md +129 -0
- rootfig-0.1.0/LICENSE +21 -0
- rootfig-0.1.0/PKG-INFO +202 -0
- rootfig-0.1.0/README.md +168 -0
- rootfig-0.1.0/docs/api.md +51 -0
- rootfig-0.1.0/docs/composable.md +128 -0
- rootfig-0.1.0/docs/ecosystem.md +59 -0
- rootfig-0.1.0/docs/expressions.md +145 -0
- rootfig-0.1.0/docs/gallery.md +68 -0
- rootfig-0.1.0/docs/hooks/gallery.py +63 -0
- rootfig-0.1.0/docs/images/gallery/arrays.png +0 -0
- rootfig-0.1.0/docs/images/gallery/cms_density.png +0 -0
- rootfig-0.1.0/docs/images/gallery/correlation.png +0 -0
- rootfig-0.1.0/docs/images/gallery/efficiency.png +0 -0
- rootfig-0.1.0/docs/images/gallery/expressions.png +0 -0
- rootfig-0.1.0/docs/images/gallery/fill_stats.png +0 -0
- rootfig-0.1.0/docs/images/gallery/hist2d.png +0 -0
- rootfig-0.1.0/docs/images/gallery/log_axes.png +0 -0
- rootfig-0.1.0/docs/images/gallery/luminosity.png +0 -0
- rootfig-0.1.0/docs/images/gallery/many_plots.png +0 -0
- rootfig-0.1.0/docs/images/gallery/object_vs_event.png +0 -0
- rootfig-0.1.0/docs/images/gallery/overlay_ratio.png +0 -0
- rootfig-0.1.0/docs/images/gallery/profile.png +0 -0
- rootfig-0.1.0/docs/images/gallery/quick.png +0 -0
- rootfig-0.1.0/docs/images/gallery/ratio_reference.png +0 -0
- rootfig-0.1.0/docs/images/gallery/robust_range.png +0 -0
- rootfig-0.1.0/docs/images/gallery/stack_data.png +0 -0
- rootfig-0.1.0/docs/images/gallery/style_colors.png +0 -0
- rootfig-0.1.0/docs/images/gallery/variable_bins.png +0 -0
- rootfig-0.1.0/docs/images/gallery/xbreak_ratio.png +0 -0
- rootfig-0.1.0/docs/index.md +25 -0
- rootfig-0.1.0/docs/plotting.md +197 -0
- rootfig-0.1.0/docs/quickstart.md +111 -0
- rootfig-0.1.0/examples/gallery.py +635 -0
- rootfig-0.1.0/mkdocs.yml +70 -0
- rootfig-0.1.0/pyproject.toml +151 -0
- rootfig-0.1.0/src/rootfig/__init__.py +97 -0
- rootfig-0.1.0/src/rootfig/_typing.py +21 -0
- rootfig-0.1.0/src/rootfig/api.py +1297 -0
- rootfig-0.1.0/src/rootfig/errors.py +73 -0
- rootfig-0.1.0/src/rootfig/expressions/__init__.py +34 -0
- rootfig-0.1.0/src/rootfig/expressions/functions.py +151 -0
- rootfig-0.1.0/src/rootfig/expressions/parser.py +462 -0
- rootfig-0.1.0/src/rootfig/histograms/__init__.py +67 -0
- rootfig-0.1.0/src/rootfig/histograms/build.py +197 -0
- rootfig-0.1.0/src/rootfig/histograms/cutflow.py +195 -0
- rootfig-0.1.0/src/rootfig/histograms/efficiency.py +214 -0
- rootfig-0.1.0/src/rootfig/histograms/normalize.py +124 -0
- rootfig-0.1.0/src/rootfig/histograms/pipeline.py +186 -0
- rootfig-0.1.0/src/rootfig/histograms/ratio.py +161 -0
- rootfig-0.1.0/src/rootfig/histograms/stats.py +183 -0
- rootfig-0.1.0/src/rootfig/io/__init__.py +12 -0
- rootfig-0.1.0/src/rootfig/io/sources.py +487 -0
- rootfig-0.1.0/src/rootfig/model/__init__.py +27 -0
- rootfig-0.1.0/src/rootfig/model/binning.py +237 -0
- rootfig-0.1.0/src/rootfig/model/cuts.py +85 -0
- rootfig-0.1.0/src/rootfig/model/samples.py +284 -0
- rootfig-0.1.0/src/rootfig/model/style.py +144 -0
- rootfig-0.1.0/src/rootfig/model/units.py +107 -0
- rootfig-0.1.0/src/rootfig/model/variables.py +95 -0
- rootfig-0.1.0/src/rootfig/plotting/__init__.py +78 -0
- rootfig-0.1.0/src/rootfig/plotting/annotations.py +165 -0
- rootfig-0.1.0/src/rootfig/plotting/correlation.py +93 -0
- rootfig-0.1.0/src/rootfig/plotting/figure.py +458 -0
- rootfig-0.1.0/src/rootfig/plotting/hist1d.py +421 -0
- rootfig-0.1.0/src/rootfig/plotting/hist2d.py +59 -0
- rootfig-0.1.0/src/rootfig/plotting/points.py +78 -0
- rootfig-0.1.0/src/rootfig/plotting/ratio.py +163 -0
- rootfig-0.1.0/src/rootfig/plotting/result.py +131 -0
- rootfig-0.1.0/src/rootfig/plotting/style.py +308 -0
- rootfig-0.1.0/src/rootfig/py.typed +0 -0
- rootfig-0.1.0/src/rootfig/selection/__init__.py +23 -0
- rootfig-0.1.0/src/rootfig/selection/columns.py +479 -0
- rootfig-0.1.0/tests/conftest.py +181 -0
- rootfig-0.1.0/tests/data/split_collection.root +0 -0
- rootfig-0.1.0/tests/test_api.py +1008 -0
- rootfig-0.1.0/tests/test_expressions.py +310 -0
- rootfig-0.1.0/tests/test_gallery.py +111 -0
- rootfig-0.1.0/tests/test_histograms.py +775 -0
- rootfig-0.1.0/tests/test_io.py +321 -0
- rootfig-0.1.0/tests/test_model.py +420 -0
- rootfig-0.1.0/tests/test_plotting.py +977 -0
- rootfig-0.1.0/tests/test_selection.py +397 -0
- rootfig-0.1.0/tests/test_tutorials.py +63 -0
rootfig-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*.egg-info/
|
|
4
|
+
dist/
|
|
5
|
+
build/
|
|
6
|
+
.venv/
|
|
7
|
+
.pytest_cache/
|
|
8
|
+
.mypy_cache/
|
|
9
|
+
.ruff_cache/
|
|
10
|
+
.coverage
|
|
11
|
+
coverage.xml
|
|
12
|
+
htmlcov/
|
|
13
|
+
site/
|
|
14
|
+
*.root
|
|
15
|
+
!tests/data/*.root
|
|
16
|
+
.ipynb_checkpoints/
|
|
17
|
+
.DS_Store
|
|
18
|
+
|
|
19
|
+
# generated example output and pytest-mpl results
|
|
20
|
+
examples/out/
|
|
21
|
+
mpl-results/
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to rootfig are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses
|
|
5
|
+
[Semantic Versioning](https://semver.org/): until 1.0 the public API may
|
|
6
|
+
change in minor releases, with deprecation warnings where practical.
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2026-09-11
|
|
11
|
+
|
|
12
|
+
First release.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- `rf.plot`: one call from ROOT files (TTree or RNTuple, globs, multiple
|
|
17
|
+
files) to a styled matplotlib figure, with selections, weights, shared
|
|
18
|
+
binning, overlays, stacks, observed-data points, normalisation, ratio
|
|
19
|
+
panels, log axes, flow-bin display, a broken x axis (`xbreak`), legends,
|
|
20
|
+
statistics boxes and experiment labels.
|
|
21
|
+
- `rf.plot_histograms` for existing `hist.Hist` objects (plain count
|
|
22
|
+
storages are converted to `Weight` storage; overlays may differ in
|
|
23
|
+
binning), `rf.plot2d`, `rf.correlation`, `rf.summarize`,
|
|
24
|
+
`rf.histogram`/`rf.histograms`, `rf.load`, `rf.evaluate`, `rf.ratio`,
|
|
25
|
+
`rf.log_bins`, `rf.use_style`.
|
|
26
|
+
- `rf.cutflow()`: weighted yields, raw counts and step efficiencies after
|
|
27
|
+
successive cuts, per sample (`CutflowTable`, `Cutflow`).
|
|
28
|
+
- `rf.efficiency()`: pass/total versus a variable with Wilson intervals
|
|
29
|
+
(`Efficiency`); `rf.profile()`: mean or standard deviation of `y` in bins
|
|
30
|
+
of `x` (`Profile`), for resolution plots.
|
|
31
|
+
- Significance panel: `ratio="significance"` / `"s/sqrt(b)"` /
|
|
32
|
+
`"s/sqrt(s+b)"` or `("s/sqrt(b)", "Signal")`; `rf.significance()`.
|
|
33
|
+
- Luminosity normalisation: `Sample(xsec=..., ngen=...)` plus `lumi=` scales
|
|
34
|
+
simulated samples to expected yields (`xsec × lumi / ngen`, units in
|
|
35
|
+
strings such as `"1.2 fb"`, `"10.8 ab^-1"`); `ngen` may name an object in
|
|
36
|
+
the file (a `TParameter` such as FCCAnalyses' `eventsProcessed`, or a
|
|
37
|
+
sum-of-weights histogram). `LuminosityError`.
|
|
38
|
+
- `Sample`, `Variable`, `Cut` and `Style` descriptions for composable
|
|
39
|
+
analysis scripts; `Style.lumi`/`Style.com` accept units and
|
|
40
|
+
`Style(lumi_unit=..., com_unit=...)` set the defaults for numbers.
|
|
41
|
+
- Expression language in Python syntax with `and`/`or`/`not`, chained
|
|
42
|
+
comparisons, backtick-quoted and dotted branch names
|
|
43
|
+
(`ReconstructedParticles.momentum.x`, as podio/EDM4hep files write them),
|
|
44
|
+
NumPy functions, per-event reductions (`count`, `sum`, `min`, `max`,
|
|
45
|
+
`mean`, `any`, `all`, `first`, ...) and kinematic helpers `pt`, `p`,
|
|
46
|
+
`theta`, `costheta`, `eta`, `phi`, `mass` from Cartesian components.
|
|
47
|
+
- Documented and tested per-event/per-object semantics for selections and
|
|
48
|
+
weights, with explicit errors for ambiguous combinations. Fixed-size
|
|
49
|
+
collections (`float x[3]` branches, two-dimensional NumPy arrays) follow
|
|
50
|
+
the per-object rules like variable-length lists. Split TTree branches and
|
|
51
|
+
nested RNTuple fields are listed and read by their dotted leaf name.
|
|
52
|
+
- Experiment-neutral default style with a 40-colour cycle (`tab10` extended
|
|
53
|
+
by the `tab20` light companions and `tab20b`/`tab20c`); mplhep styles and
|
|
54
|
+
labels for ATLAS, CMS, LHCb, ALICE and DUNE via `Style(experiment=...)`.
|
|
55
|
+
- Automatic y headroom accounts for the actual legend, experiment label,
|
|
56
|
+
statistics box and text sizes, so they never cover a histogram (unless
|
|
57
|
+
`ylim` sets the upper value).
|
|
58
|
+
- A gallery (`examples/gallery.py`, `docs/gallery.md`) with 20 examples
|
|
59
|
+
covering the plotting options, each shown next to its code, doubling as an
|
|
60
|
+
image-regression suite (`tests/test_gallery.py`, pytest-mpl) whose
|
|
61
|
+
baselines are the documentation images.
|
|
62
|
+
- Lower-layer entry points for callers building on rootfig:
|
|
63
|
+
`rootfig.selection.prepare`/`boolean_mask`, `rootfig.histograms.fill`,
|
|
64
|
+
`normalize_hist`, `as_weight_storage`, `read_arrays`, `source_length`,
|
|
65
|
+
`rootfig.plotting.draw_histograms`, `show_flow_bins`, `fold_flow_bins`.
|
|
66
|
+
|
|
67
|
+
### Behaviour worth knowing
|
|
68
|
+
|
|
69
|
+
- `nan`/`inf` values are dropped with a `RootfigWarning`
|
|
70
|
+
(`nonfinite="error"` raises), also in cut flows; missing values (`None`),
|
|
71
|
+
missing collections and missing event weights drop the entry or event and
|
|
72
|
+
are counted separately in `Summary`.
|
|
73
|
+
- Negative weights: a weighted variance that comes out negative gives `nan`
|
|
74
|
+
for the standard deviation of `Summary` and `Profile` (and the profile
|
|
75
|
+
error); an efficiency outside `[0, 1]` has `nan` interval bounds and
|
|
76
|
+
warns. Histogram contents, means and yields are unaffected.
|
|
77
|
+
- `flow="show"` and `flow="sum"` are applied by rootfig before ratios,
|
|
78
|
+
significances, stack bands and limits are computed, identically for all
|
|
79
|
+
samples; `normalize="width"`/`"density"` divide flow bins by the
|
|
80
|
+
neighbouring bin width.
|
|
81
|
+
- Ratios, significances and efficiencies require identical bin edges (up to
|
|
82
|
+
a millionth of a bin width). `Sample.scale`, `xsec`, `ngen` and `lumi`
|
|
83
|
+
must be finite. `logx`/`logy` default to the `Variable`'s `log` flag.
|
|
84
|
+
- Requires Python 3.12 and matplotlib 3.10 or newer.
|
|
85
|
+
|
|
86
|
+
[Unreleased]: https://github.com/jbeirer/rootfig/compare/v0.1.0...HEAD
|
|
87
|
+
[0.1.0]: https://github.com/jbeirer/rootfig/releases/tag/v0.1.0
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Contributing to rootfig
|
|
2
|
+
|
|
3
|
+
Thanks for helping. Issues and pull requests are welcome at
|
|
4
|
+
<https://github.com/jbeirer/rootfig>.
|
|
5
|
+
|
|
6
|
+
## Development setup
|
|
7
|
+
|
|
8
|
+
rootfig is managed with [uv](https://docs.astral.sh/uv/).
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
git clone https://github.com/jbeirer/rootfig
|
|
12
|
+
cd rootfig
|
|
13
|
+
uv sync --all-groups # runtime, dev and docs dependencies
|
|
14
|
+
uv run pre-commit install # optional: run the linters on every commit
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Checks
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
uv run pytest # tests (ROOT files are generated on the fly)
|
|
21
|
+
uv run pytest --cov # with coverage
|
|
22
|
+
uv run ruff check . && uv run ruff format --check .
|
|
23
|
+
uv run mypy # strict type checking of src/
|
|
24
|
+
uv run mkdocs serve # documentation preview
|
|
25
|
+
uv build && uvx twine check dist/* # packaging
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
CI runs all of these on Python 3.12, 3.13 and 3.14 (Linux), plus macOS
|
|
29
|
+
on 3.13. Tests that use ROOT's tutorial files run only when
|
|
30
|
+
`root-config` is available locally and are skipped otherwise; do not add
|
|
31
|
+
tests that require ROOT or network access.
|
|
32
|
+
|
|
33
|
+
## Layout
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
src/rootfig/
|
|
37
|
+
api.py plot(), histogram(), load(), ... (orchestration only)
|
|
38
|
+
errors.py exception hierarchy
|
|
39
|
+
expressions/ parse, validate and evaluate expression strings
|
|
40
|
+
io/ file and in-memory data sources
|
|
41
|
+
model/ Sample, Variable, Cut, Style, binning
|
|
42
|
+
selection/ per-event / per-object semantics -> flat columns
|
|
43
|
+
histograms/ filling, normalisation, ratios, statistics, pipeline
|
|
44
|
+
plotting/ matplotlib/mplhep rendering, styles, annotations
|
|
45
|
+
tests/ one module per layer plus end-to-end API tests
|
|
46
|
+
docs/ MkDocs sources
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Keep the layers independent: `plotting` must not read files, `selection`
|
|
50
|
+
must not know about matplotlib, and so on. Public functions carry NumPy-style
|
|
51
|
+
docstrings and full type hints.
|
|
52
|
+
|
|
53
|
+
## Test data
|
|
54
|
+
|
|
55
|
+
Almost all tests generate their ROOT files with uproot on the fly. The one
|
|
56
|
+
committed file, `tests/data/split_collection.root`, has a split
|
|
57
|
+
`std::vector<struct>` branch and a `TParameter` the way podio/EDM4hep and
|
|
58
|
+
FCCAnalyses write them. uproot cannot write such a file, so it was produced
|
|
59
|
+
with PyROOT (ROOT 6.40) by this script; rerun it only if the layout has to
|
|
60
|
+
change, and keep the file small:
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
import ROOT
|
|
64
|
+
|
|
65
|
+
ROOT.gInterpreter.Declare("""
|
|
66
|
+
struct Vec3 { float x; float y; float z; };
|
|
67
|
+
struct Particle { Vec3 momentum; float energy; int charge; };
|
|
68
|
+
""")
|
|
69
|
+
f = ROOT.TFile("split_collection.root", "RECREATE")
|
|
70
|
+
t = ROOT.TTree("events", "events")
|
|
71
|
+
v = ROOT.std.vector("Particle")()
|
|
72
|
+
t.Branch("ReconstructedParticles", v, 32000, 99) # split level 99 -> dotted sub-branches
|
|
73
|
+
r = ROOT.TRandom3(1)
|
|
74
|
+
for _ in range(200):
|
|
75
|
+
v.clear()
|
|
76
|
+
for _ in range(r.Poisson(3)):
|
|
77
|
+
p = ROOT.Particle()
|
|
78
|
+
p.momentum.x, p.momentum.y, p.momentum.z = r.Gaus(0, 20), r.Gaus(0, 20), r.Gaus(0, 20)
|
|
79
|
+
p.energy = (p.momentum.x**2 + p.momentum.y**2 + p.momentum.z**2) ** 0.5 + 0.1
|
|
80
|
+
p.charge = -1 if r.Uniform() < 0.5 else 1
|
|
81
|
+
v.push_back(p)
|
|
82
|
+
t.Fill()
|
|
83
|
+
ROOT.TParameter("int")("eventsProcessed", 200).Write()
|
|
84
|
+
f.Write()
|
|
85
|
+
f.Close()
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Figures and the gallery
|
|
89
|
+
|
|
90
|
+
`examples/gallery.py` is both the showcase and the image-regression suite. Each
|
|
91
|
+
example is a small function returning a `Plot`; `docs/gallery.md` shows every
|
|
92
|
+
figure next to that function's source (a MkDocs hook, `docs/hooks/gallery.py`),
|
|
93
|
+
and `tests/test_gallery.py` renders all of them and, with `--mpl`, compares
|
|
94
|
+
them pixel-wise (pytest-mpl, RMS tolerance 2) against `docs/images/gallery/`.
|
|
95
|
+
Those PNGs are therefore the documentation images *and* the baselines.
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
MPLBACKEND=Agg uv run python examples/gallery.py # look at examples/out/*.png
|
|
99
|
+
uv run pytest tests/test_gallery.py --mpl # compare against the baselines
|
|
100
|
+
uv run pytest tests/test_gallery.py --mpl-generate-path=docs/images/gallery # accept changes
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
After any visual change: regenerate the baselines, open the PNGs and check
|
|
104
|
+
them by eye, and commit them with the code. CI compares on Linux only (fonts
|
|
105
|
+
differ elsewhere) and, when a comparison fails, uploads an HTML report with
|
|
106
|
+
baseline, result and difference images as the `mpl-results-*` artifact. To add
|
|
107
|
+
an example, register a function with `@example(name, title)` and give it a
|
|
108
|
+
docstring; the test suite fails until its baseline image exists.
|
|
109
|
+
|
|
110
|
+
## Pull requests
|
|
111
|
+
|
|
112
|
+
- Add tests for behaviour changes; unit tests assert histogram contents and
|
|
113
|
+
matplotlib structure. Rendered output is covered by the gallery (below).
|
|
114
|
+
- Update `CHANGELOG.md` under "Unreleased".
|
|
115
|
+
- Run the checks above before pushing; `pre-commit run --all-files` does most
|
|
116
|
+
of it.
|
|
117
|
+
|
|
118
|
+
## Releasing
|
|
119
|
+
|
|
120
|
+
1. Update the version in `src/rootfig/__init__.py` and move the changelog
|
|
121
|
+
entries under a new heading.
|
|
122
|
+
2. Commit, tag `vX.Y.Z`, push the tag.
|
|
123
|
+
3. The `release.yml` workflow builds the distribution and publishes it to
|
|
124
|
+
PyPI via Trusted Publishing (configure the publisher on PyPI first:
|
|
125
|
+
repository `jbeirer/rootfig`, workflow `release.yml`, environment `pypi`).
|
|
126
|
+
|
|
127
|
+
The documentation is published by the `docs` job of `ci.yml` on every push to
|
|
128
|
+
`main` (`mkdocs gh-deploy` to the `gh-pages` branch). Once, in the repository
|
|
129
|
+
settings, set GitHub Pages to serve from that branch.
|
rootfig-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Joshua Falco Beirer
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
rootfig-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: rootfig
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Publication-quality figures straight from ROOT trees, without ROOT: uproot + Awkward + hist + mplhep with a TTree::Draw-like API.
|
|
5
|
+
Project-URL: Homepage, https://github.com/jbeirer/rootfig
|
|
6
|
+
Project-URL: Documentation, https://github.com/jbeirer/rootfig#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/jbeirer/rootfig
|
|
8
|
+
Project-URL: Issues, https://github.com/jbeirer/rootfig/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/jbeirer/rootfig/blob/main/CHANGELOG.md
|
|
10
|
+
Author-email: Joshua Falco Beirer <jbeirer@cern.ch>
|
|
11
|
+
License-Expression: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: HEP,RNTuple,ROOT,TTree,awkward,histogram,matplotlib,mplhep,plotting,uproot
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
25
|
+
Classifier: Typing :: Typed
|
|
26
|
+
Requires-Python: >=3.12
|
|
27
|
+
Requires-Dist: awkward>=2.6
|
|
28
|
+
Requires-Dist: hist>=2.7
|
|
29
|
+
Requires-Dist: matplotlib>=3.10
|
|
30
|
+
Requires-Dist: mplhep>=0.3.50
|
|
31
|
+
Requires-Dist: numpy>=1.26
|
|
32
|
+
Requires-Dist: uproot>=5.3
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# rootfig
|
|
36
|
+
|
|
37
|
+
**Publication-quality figures straight from ROOT trees, without ROOT.**
|
|
38
|
+
|
|
39
|
+
`rootfig` is the `TTree::Draw` workflow for the Scientific Python HEP stack:
|
|
40
|
+
give it ROOT files, a tree, an expression, a selection and a weight, and get a
|
|
41
|
+
styled matplotlib figure back in one call. It reads with
|
|
42
|
+
[uproot](https://github.com/scikit-hep/uproot5), computes with
|
|
43
|
+
[Awkward Array](https://github.com/scikit-hep/awkward), fills
|
|
44
|
+
[hist](https://github.com/scikit-hep/hist) histograms and draws with
|
|
45
|
+
[mplhep](https://github.com/scikit-hep/mplhep). It adds the missing glue:
|
|
46
|
+
predictable per-event/per-object selection semantics, weights, shared
|
|
47
|
+
binning across samples, normalisation, ratio panels and good defaults.
|
|
48
|
+
|
|
49
|
+
[](https://github.com/jbeirer/rootfig/actions/workflows/ci.yml)
|
|
50
|
+
[](https://codecov.io/gh/jbeirer/rootfig)
|
|
51
|
+
[](https://pypi.org/project/rootfig/)
|
|
52
|
+
[](https://pypi.org/project/rootfig/)
|
|
53
|
+
[](LICENSE)
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
import rootfig as rf
|
|
57
|
+
|
|
58
|
+
rf.plot("events.root", "Muon_pt", tree="events", selection="Muon_pt > 20", bins=50)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
<p align="center">
|
|
62
|
+
<img src="docs/images/gallery/stack_data.png" alt="Stacked simulation with data and a ratio panel" width="48%">
|
|
63
|
+
<img src="docs/images/gallery/xbreak_ratio.png" alt="Broken x axis with a ratio panel" width="48%">
|
|
64
|
+
</p>
|
|
65
|
+
<p align="center">
|
|
66
|
+
<img src="docs/images/gallery/object_vs_event.png" alt="Per-object versus per-event selections" width="48%">
|
|
67
|
+
<img src="docs/images/gallery/hist2d.png" alt="Two-dimensional histogram" width="48%">
|
|
68
|
+
</p>
|
|
69
|
+
|
|
70
|
+
These and a dozen more figures, each next to the code that made it, are in the
|
|
71
|
+
[gallery](https://jbeirer.github.io/rootfig/gallery/). All of them come from
|
|
72
|
+
[`examples/gallery.py`](examples/gallery.py), which writes toy ROOT files and
|
|
73
|
+
draws every example in a few seconds; the same figures are pixel-compared in CI.
|
|
74
|
+
|
|
75
|
+
## Installation
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install rootfig
|
|
79
|
+
# or
|
|
80
|
+
uv add rootfig
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Python 3.12 or newer. No ROOT installation is needed; `TTree` and `RNTuple`
|
|
84
|
+
files are both supported.
|
|
85
|
+
|
|
86
|
+
## Quick start
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
import rootfig as rf
|
|
90
|
+
|
|
91
|
+
# Overlay two samples, normalised to unity, with a ratio panel.
|
|
92
|
+
rf.plot(
|
|
93
|
+
["signal.root", "background.root"],
|
|
94
|
+
"Muon_pt",
|
|
95
|
+
tree="events",
|
|
96
|
+
selection="abs(Muon_eta) < 2.5",
|
|
97
|
+
weight="event_weight",
|
|
98
|
+
bins=(50, 0, 200),
|
|
99
|
+
normalize=True,
|
|
100
|
+
ratio=True,
|
|
101
|
+
)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
For analysis scripts with many samples, variables and plots, describe things
|
|
105
|
+
once and reuse them:
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
import rootfig as rf
|
|
109
|
+
|
|
110
|
+
signal = rf.Sample("sig_*.root", tree="events", label="Signal", weight="mc_weight")
|
|
111
|
+
background = rf.Sample("bkg.root", tree="events", label="Background", weight="mc_weight")
|
|
112
|
+
data = rf.Sample("data.root", tree="events", label="Data", is_data=True)
|
|
113
|
+
|
|
114
|
+
pt = rf.Variable("Muon_pt", bins=(50, 0, 200), label=r"$p_T^{\mu}$", unit="GeV")
|
|
115
|
+
baseline = rf.Cut("nMuon >= 1") & "abs(Muon_eta) < 2.5"
|
|
116
|
+
style = rf.Style(experiment="ATLAS", status="Internal", lumi=140, com=13.6)
|
|
117
|
+
|
|
118
|
+
p = rf.plot(
|
|
119
|
+
[background, signal],
|
|
120
|
+
pt,
|
|
121
|
+
observed=data,
|
|
122
|
+
selection=baseline,
|
|
123
|
+
stack=True,
|
|
124
|
+
ratio=True,
|
|
125
|
+
logy=True,
|
|
126
|
+
style=style,
|
|
127
|
+
)
|
|
128
|
+
p.ax.set_ylim(top=1e5) # it is a normal matplotlib Axes
|
|
129
|
+
p.save("muon_pt.pdf")
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Everything you get back is a standard object: `p.fig` and `p.ax` are
|
|
133
|
+
matplotlib `Figure`/`Axes`, `p.hists` are `hist.Hist` objects, and
|
|
134
|
+
`rf.load(...)` returns Awkward arrays.
|
|
135
|
+
|
|
136
|
+
## Features
|
|
137
|
+
|
|
138
|
+
- **One call from files to figure**, reading only the branches the expressions need.
|
|
139
|
+
- **Expressions in Python syntax**: `sqrt(px**2 + py**2)`, `count(Jet_pt) >= 2`,
|
|
140
|
+
`` `jet1_b-tag` > 0.5 ``, `and`/`or`/`not`, chained comparisons.
|
|
141
|
+
- **Jagged branches done right**: per-object cuts mask objects, per-event
|
|
142
|
+
cuts drop events, ambiguous combinations raise a clear error instead of
|
|
143
|
+
silently broadcasting.
|
|
144
|
+
- **Weights**: per-event weights broadcast onto objects, per-object weights,
|
|
145
|
+
constant scale factors, multiplicative combination of sample and plot weights.
|
|
146
|
+
- **Histograms with uncertainties** (`hist` with `Weight` storage), shared
|
|
147
|
+
binning across samples, automatic or robust ranges, log bins, flow bins.
|
|
148
|
+
- **Overlays, stacks, data points, ratio panels** with correct error
|
|
149
|
+
propagation for weighted histograms and a reference-uncertainty band.
|
|
150
|
+
- **Normalisation**: to unity, density, per bin width, or to a number; or to
|
|
151
|
+
a **luminosity** from cross sections and generated-event counts
|
|
152
|
+
(`Sample(xsec="0.2 pb", ngen="eventsProcessed")`, `lumi="10.8 ab^-1"`).
|
|
153
|
+
- **Analysis tables and panels**: cut flows with yields and efficiencies,
|
|
154
|
+
significance panels (S/√B), efficiency-versus-variable plots with binomial
|
|
155
|
+
intervals, profiles and resolutions.
|
|
156
|
+
- **Experiment-neutral defaults**, with mplhep styles and labels for ATLAS,
|
|
157
|
+
CMS, LHCb, ALICE and DUNE one keyword away; any other experiment name, GeV
|
|
158
|
+
and ab⁻¹ work too.
|
|
159
|
+
- **EDM4hep-friendly**: sub-branches of split collections are addressed as
|
|
160
|
+
`ReconstructedParticles.momentum.x`, with `pt`, `p`, `theta`, `costheta`,
|
|
161
|
+
`eta`, `phi` and `mass` helpers.
|
|
162
|
+
- **Also**: 2D histograms, summary statistics tables, statistics boxes,
|
|
163
|
+
correlation matrices, multi-file globs, entry ranges for quick looks.
|
|
164
|
+
|
|
165
|
+
## Documentation
|
|
166
|
+
|
|
167
|
+
- [Quick start](docs/quickstart.md)
|
|
168
|
+
- [Expressions and selections](docs/expressions.md)
|
|
169
|
+
- [Samples, variables, cuts and styles](docs/composable.md)
|
|
170
|
+
- [Plotting options](docs/plotting.md)
|
|
171
|
+
- [Relation to uproot, Awkward, hist, mplhep and matplotlib](docs/ecosystem.md)
|
|
172
|
+
|
|
173
|
+
## Relation to the ecosystem
|
|
174
|
+
|
|
175
|
+
`rootfig` does not replace any of the libraries it builds on:
|
|
176
|
+
|
|
177
|
+
| Task | Library | What rootfig adds |
|
|
178
|
+
| --- | --- | --- |
|
|
179
|
+
| Reading ROOT files | uproot | file globs, tree auto-detection, reading only the required branches |
|
|
180
|
+
| Jagged arrays | Awkward Array | the per-event/per-object rules for cuts and weights |
|
|
181
|
+
| Histograms | hist / boost-histogram | shared binning, automatic ranges, normalisation, ratios |
|
|
182
|
+
| Drawing | mplhep + matplotlib | overlays, stacks, ratio panels, labels and legends with good defaults |
|
|
183
|
+
|
|
184
|
+
If you already have `hist.Hist` objects, `rf.plot_histograms` draws them with
|
|
185
|
+
the same options. If you want the arrays, `rf.load` returns them.
|
|
186
|
+
|
|
187
|
+
## Development
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
git clone https://github.com/jbeirer/rootfig
|
|
191
|
+
cd rootfig
|
|
192
|
+
uv sync --all-groups
|
|
193
|
+
uv run pytest
|
|
194
|
+
uv run ruff check . && uv run ruff format --check .
|
|
195
|
+
uv run mypy
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
|
|
199
|
+
|
|
200
|
+
## License
|
|
201
|
+
|
|
202
|
+
MIT. See [LICENSE](LICENSE).
|
rootfig-0.1.0/README.md
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# rootfig
|
|
2
|
+
|
|
3
|
+
**Publication-quality figures straight from ROOT trees, without ROOT.**
|
|
4
|
+
|
|
5
|
+
`rootfig` is the `TTree::Draw` workflow for the Scientific Python HEP stack:
|
|
6
|
+
give it ROOT files, a tree, an expression, a selection and a weight, and get a
|
|
7
|
+
styled matplotlib figure back in one call. It reads with
|
|
8
|
+
[uproot](https://github.com/scikit-hep/uproot5), computes with
|
|
9
|
+
[Awkward Array](https://github.com/scikit-hep/awkward), fills
|
|
10
|
+
[hist](https://github.com/scikit-hep/hist) histograms and draws with
|
|
11
|
+
[mplhep](https://github.com/scikit-hep/mplhep). It adds the missing glue:
|
|
12
|
+
predictable per-event/per-object selection semantics, weights, shared
|
|
13
|
+
binning across samples, normalisation, ratio panels and good defaults.
|
|
14
|
+
|
|
15
|
+
[](https://github.com/jbeirer/rootfig/actions/workflows/ci.yml)
|
|
16
|
+
[](https://codecov.io/gh/jbeirer/rootfig)
|
|
17
|
+
[](https://pypi.org/project/rootfig/)
|
|
18
|
+
[](https://pypi.org/project/rootfig/)
|
|
19
|
+
[](LICENSE)
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
import rootfig as rf
|
|
23
|
+
|
|
24
|
+
rf.plot("events.root", "Muon_pt", tree="events", selection="Muon_pt > 20", bins=50)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
<p align="center">
|
|
28
|
+
<img src="docs/images/gallery/stack_data.png" alt="Stacked simulation with data and a ratio panel" width="48%">
|
|
29
|
+
<img src="docs/images/gallery/xbreak_ratio.png" alt="Broken x axis with a ratio panel" width="48%">
|
|
30
|
+
</p>
|
|
31
|
+
<p align="center">
|
|
32
|
+
<img src="docs/images/gallery/object_vs_event.png" alt="Per-object versus per-event selections" width="48%">
|
|
33
|
+
<img src="docs/images/gallery/hist2d.png" alt="Two-dimensional histogram" width="48%">
|
|
34
|
+
</p>
|
|
35
|
+
|
|
36
|
+
These and a dozen more figures, each next to the code that made it, are in the
|
|
37
|
+
[gallery](https://jbeirer.github.io/rootfig/gallery/). All of them come from
|
|
38
|
+
[`examples/gallery.py`](examples/gallery.py), which writes toy ROOT files and
|
|
39
|
+
draws every example in a few seconds; the same figures are pixel-compared in CI.
|
|
40
|
+
|
|
41
|
+
## Installation
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install rootfig
|
|
45
|
+
# or
|
|
46
|
+
uv add rootfig
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Python 3.12 or newer. No ROOT installation is needed; `TTree` and `RNTuple`
|
|
50
|
+
files are both supported.
|
|
51
|
+
|
|
52
|
+
## Quick start
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
import rootfig as rf
|
|
56
|
+
|
|
57
|
+
# Overlay two samples, normalised to unity, with a ratio panel.
|
|
58
|
+
rf.plot(
|
|
59
|
+
["signal.root", "background.root"],
|
|
60
|
+
"Muon_pt",
|
|
61
|
+
tree="events",
|
|
62
|
+
selection="abs(Muon_eta) < 2.5",
|
|
63
|
+
weight="event_weight",
|
|
64
|
+
bins=(50, 0, 200),
|
|
65
|
+
normalize=True,
|
|
66
|
+
ratio=True,
|
|
67
|
+
)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
For analysis scripts with many samples, variables and plots, describe things
|
|
71
|
+
once and reuse them:
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
import rootfig as rf
|
|
75
|
+
|
|
76
|
+
signal = rf.Sample("sig_*.root", tree="events", label="Signal", weight="mc_weight")
|
|
77
|
+
background = rf.Sample("bkg.root", tree="events", label="Background", weight="mc_weight")
|
|
78
|
+
data = rf.Sample("data.root", tree="events", label="Data", is_data=True)
|
|
79
|
+
|
|
80
|
+
pt = rf.Variable("Muon_pt", bins=(50, 0, 200), label=r"$p_T^{\mu}$", unit="GeV")
|
|
81
|
+
baseline = rf.Cut("nMuon >= 1") & "abs(Muon_eta) < 2.5"
|
|
82
|
+
style = rf.Style(experiment="ATLAS", status="Internal", lumi=140, com=13.6)
|
|
83
|
+
|
|
84
|
+
p = rf.plot(
|
|
85
|
+
[background, signal],
|
|
86
|
+
pt,
|
|
87
|
+
observed=data,
|
|
88
|
+
selection=baseline,
|
|
89
|
+
stack=True,
|
|
90
|
+
ratio=True,
|
|
91
|
+
logy=True,
|
|
92
|
+
style=style,
|
|
93
|
+
)
|
|
94
|
+
p.ax.set_ylim(top=1e5) # it is a normal matplotlib Axes
|
|
95
|
+
p.save("muon_pt.pdf")
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Everything you get back is a standard object: `p.fig` and `p.ax` are
|
|
99
|
+
matplotlib `Figure`/`Axes`, `p.hists` are `hist.Hist` objects, and
|
|
100
|
+
`rf.load(...)` returns Awkward arrays.
|
|
101
|
+
|
|
102
|
+
## Features
|
|
103
|
+
|
|
104
|
+
- **One call from files to figure**, reading only the branches the expressions need.
|
|
105
|
+
- **Expressions in Python syntax**: `sqrt(px**2 + py**2)`, `count(Jet_pt) >= 2`,
|
|
106
|
+
`` `jet1_b-tag` > 0.5 ``, `and`/`or`/`not`, chained comparisons.
|
|
107
|
+
- **Jagged branches done right**: per-object cuts mask objects, per-event
|
|
108
|
+
cuts drop events, ambiguous combinations raise a clear error instead of
|
|
109
|
+
silently broadcasting.
|
|
110
|
+
- **Weights**: per-event weights broadcast onto objects, per-object weights,
|
|
111
|
+
constant scale factors, multiplicative combination of sample and plot weights.
|
|
112
|
+
- **Histograms with uncertainties** (`hist` with `Weight` storage), shared
|
|
113
|
+
binning across samples, automatic or robust ranges, log bins, flow bins.
|
|
114
|
+
- **Overlays, stacks, data points, ratio panels** with correct error
|
|
115
|
+
propagation for weighted histograms and a reference-uncertainty band.
|
|
116
|
+
- **Normalisation**: to unity, density, per bin width, or to a number; or to
|
|
117
|
+
a **luminosity** from cross sections and generated-event counts
|
|
118
|
+
(`Sample(xsec="0.2 pb", ngen="eventsProcessed")`, `lumi="10.8 ab^-1"`).
|
|
119
|
+
- **Analysis tables and panels**: cut flows with yields and efficiencies,
|
|
120
|
+
significance panels (S/√B), efficiency-versus-variable plots with binomial
|
|
121
|
+
intervals, profiles and resolutions.
|
|
122
|
+
- **Experiment-neutral defaults**, with mplhep styles and labels for ATLAS,
|
|
123
|
+
CMS, LHCb, ALICE and DUNE one keyword away; any other experiment name, GeV
|
|
124
|
+
and ab⁻¹ work too.
|
|
125
|
+
- **EDM4hep-friendly**: sub-branches of split collections are addressed as
|
|
126
|
+
`ReconstructedParticles.momentum.x`, with `pt`, `p`, `theta`, `costheta`,
|
|
127
|
+
`eta`, `phi` and `mass` helpers.
|
|
128
|
+
- **Also**: 2D histograms, summary statistics tables, statistics boxes,
|
|
129
|
+
correlation matrices, multi-file globs, entry ranges for quick looks.
|
|
130
|
+
|
|
131
|
+
## Documentation
|
|
132
|
+
|
|
133
|
+
- [Quick start](docs/quickstart.md)
|
|
134
|
+
- [Expressions and selections](docs/expressions.md)
|
|
135
|
+
- [Samples, variables, cuts and styles](docs/composable.md)
|
|
136
|
+
- [Plotting options](docs/plotting.md)
|
|
137
|
+
- [Relation to uproot, Awkward, hist, mplhep and matplotlib](docs/ecosystem.md)
|
|
138
|
+
|
|
139
|
+
## Relation to the ecosystem
|
|
140
|
+
|
|
141
|
+
`rootfig` does not replace any of the libraries it builds on:
|
|
142
|
+
|
|
143
|
+
| Task | Library | What rootfig adds |
|
|
144
|
+
| --- | --- | --- |
|
|
145
|
+
| Reading ROOT files | uproot | file globs, tree auto-detection, reading only the required branches |
|
|
146
|
+
| Jagged arrays | Awkward Array | the per-event/per-object rules for cuts and weights |
|
|
147
|
+
| Histograms | hist / boost-histogram | shared binning, automatic ranges, normalisation, ratios |
|
|
148
|
+
| Drawing | mplhep + matplotlib | overlays, stacks, ratio panels, labels and legends with good defaults |
|
|
149
|
+
|
|
150
|
+
If you already have `hist.Hist` objects, `rf.plot_histograms` draws them with
|
|
151
|
+
the same options. If you want the arrays, `rf.load` returns them.
|
|
152
|
+
|
|
153
|
+
## Development
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
git clone https://github.com/jbeirer/rootfig
|
|
157
|
+
cd rootfig
|
|
158
|
+
uv sync --all-groups
|
|
159
|
+
uv run pytest
|
|
160
|
+
uv run ruff check . && uv run ruff format --check .
|
|
161
|
+
uv run mypy
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
|
|
165
|
+
|
|
166
|
+
## License
|
|
167
|
+
|
|
168
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# API reference
|
|
2
|
+
|
|
3
|
+
## Top level
|
|
4
|
+
|
|
5
|
+
::: rootfig.plot
|
|
6
|
+
::: rootfig.plot_histograms
|
|
7
|
+
::: rootfig.plot2d
|
|
8
|
+
::: rootfig.histogram
|
|
9
|
+
::: rootfig.histograms
|
|
10
|
+
::: rootfig.load
|
|
11
|
+
::: rootfig.summarize
|
|
12
|
+
::: rootfig.correlation
|
|
13
|
+
::: rootfig.cutflow
|
|
14
|
+
::: rootfig.efficiency
|
|
15
|
+
::: rootfig.profile
|
|
16
|
+
::: rootfig.significance
|
|
17
|
+
::: rootfig.evaluate
|
|
18
|
+
::: rootfig.ratio
|
|
19
|
+
::: rootfig.log_bins
|
|
20
|
+
::: rootfig.use_style
|
|
21
|
+
|
|
22
|
+
## Descriptions
|
|
23
|
+
|
|
24
|
+
::: rootfig.Sample
|
|
25
|
+
::: rootfig.Variable
|
|
26
|
+
::: rootfig.Cut
|
|
27
|
+
::: rootfig.Style
|
|
28
|
+
|
|
29
|
+
## Results
|
|
30
|
+
|
|
31
|
+
::: rootfig.Plot
|
|
32
|
+
::: rootfig.Histogram
|
|
33
|
+
::: rootfig.Ratio
|
|
34
|
+
::: rootfig.Summary
|
|
35
|
+
::: rootfig.SummaryTable
|
|
36
|
+
::: rootfig.Cutflow
|
|
37
|
+
::: rootfig.CutflowTable
|
|
38
|
+
::: rootfig.Efficiency
|
|
39
|
+
::: rootfig.Profile
|
|
40
|
+
|
|
41
|
+
## Errors and warnings
|
|
42
|
+
|
|
43
|
+
::: rootfig.errors
|
|
44
|
+
|
|
45
|
+
## Lower layers
|
|
46
|
+
|
|
47
|
+
::: rootfig.io
|
|
48
|
+
::: rootfig.expressions
|
|
49
|
+
::: rootfig.selection
|
|
50
|
+
::: rootfig.histograms
|
|
51
|
+
::: rootfig.plotting
|