umber
umber is a plotting library for Python with a rendering core written in Rust. It draws line, scatter, area, bar and histogram charts with careful typography, three built-in themes, and PNG or SVG output.
- Fast on large data. Rendering runs in Rust: a 1,000,000-point line renders to PNG in about 55 ms, and a 100,000-point scatter in about 50 ms (see Performance).
- Explicit. Every option is a typed value (
Color,Size,Dash,TickFormat, …). There are no format strings, no positional style arguments and no silent conversions. - Fails fast, pointing at the problem. Invalid input raises at the call that caused it, with a message, a hint and the offending argument highlighted in the traceback.
- Statically typed. Category and numeric axes are distinct types: calling
baron a numeric axes is reported by pyright and mypy before the code runs. - Bundled fonts. Text in the bundled fonts' coverage looks the same on every machine; other characters fall back to system fonts.
Installation
pip install umber
umber requires Python 3.12 or newer and NumPy 2. Prebuilt wheels are published for Linux (x86_64 and aarch64), macOS (Apple silicon and Intel) and Windows (x64). On other platforms pip builds from source, which needs Rust 1.88 or newer.
Quick start
import numpy as np
import umber as ub
t = np.linspace(0, 10, 1_000)
ub.line(t, np.sin(t), label="sin").title("A first chart").figure.save_png("chart.png")
The quick functions ub.line, ub.scatter, ub.bar and ub.hist create a figure with one axes and return the axes, so the rest of the chart is built by chaining.
Building a figure
import numpy as np
import umber as ub
rng = np.random.default_rng(7)
days = np.arange(60)
north = 20 + np.cumsum(rng.normal(0, 1, 60))
south = 18 + np.cumsum(rng.normal(0, 1, 60))
fig = ub.Figure(6, 4, theme=ub.Theme.GRAPHITE) # width and height in inches
ax = fig.add_axes()
ax.title("Daily temperature").subtitle("Two stations, last 60 days")
ax.xlabel("Day").ylabel("°C")
ax.line(days, north, label="North")
ax.line(days, south, label="South", dash=ub.Dash.DASHED)
fig.save_png("temperature.png", dpi=200)
fig.save_svg("temperature.svg")
This is the chart at the top of this page. Data can be a list, a tuple, a NumPy array, or a pandas or polars Series. Missing values (NaN, or nulls in nullable pandas and polars columns) leave a gap.
| Chart | Method |
|---|---|
| Line | ax.line(x, y) |
| Scatter | ax.scatter(x, y, marker=ub.Marker.TRIANGLE, size=ub.Size.times(1.5)) |
| Area | ax.area(x, y) |
| Bar, grouped, stacked | ax.bar(categories, heights), ax.grouped_bar(categories, series), ax.stacked_bar(categories, series) |
| Histogram | ax.hist(values, bins=30) |
Bar charts need a category x axis: fig.add_axes(x=ub.Scale.category()). Log axes use ub.Scale.log(). Limits, ticks and tick label formats are set with xlim, ylim, xticks, xticks_labeled, ytick_format(ub.TickFormat.percent()) and their counterparts on the other axis.
Themes
Three themes are built in: Theme.PIGMENT (warm paper, serif titles), Theme.GRAPHITE (neutral, sans-serif) and Theme.MIDNIGHT (dark, monospaced figures). A theme is an immutable value; derive a variant with its with_* methods:
import umber as ub
theme = ub.Theme.MIDNIGHT.with_fill_style(ub.FillStyle.SOLID).with_legend_style(
ub.LegendStyle.HEADER
)
fig = ub.Figure(theme=theme)
Errors
An error is raised by the call that caused it: umber.DataError for invalid data, umber.StyleError for an invalid option value, umber.UsageError for a call that is not allowed in the current state, and TypeError for a value of the wrong type. The three umber errors derive from umber.UmberError. The traceback points at the argument:
Traceback (most recent call last):
File "example.py", line 7, in <module>
ax.line(t, y, label="signal")
~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
umber.DataError: Axes.line(): y[2] is inf; values must be finite.
ax.line(t, y, label="signal")
^
hint: use NaN to leave a gap in the line.
TypeError: Axes.line(): color is str; color must be of type Color.
ax.line([0, 1, 2], [1, 3, 2], color="red")
^^^^^^^^^^^
hint: use Color.hex("#3366B8"), Color.rgb() or a named color such as Color.BLUE.
In a terminal that supports it, the hint and the highlight are shown in color; set NO_COLOR to turn color off or FORCE_COLOR to force it. The same notes appear in Jupyter.
Static typing
The package ships type information (py.typed) and is checked with pyright and mypy in strict mode. Figure().add_axes() is Axes[float, float]; add_axes(x=Scale.category()) is Axes[str, float]. Methods that only make sense on one kind of axis are typed accordingly:
import umber as ub
ax = ub.Figure().add_axes()
ax.bar(["a", "b"], [1, 2]) # pyright and mypy: bar() needs Axes[str, float]
Performance
Medians from the criterion suite in crates/umber-core/benches, 6 × 4 in at 200 dpi, on an Intel Core Ultra 9 290HX running Linux:
| Case | Time |
|---|---|
| 1,000,000-point line → PNG | 53 ms |
| 1,000,000-point line → SVG | 21 ms |
| 100,000-point scatter → PNG | 47 ms |
| Histogram of 1,000,000 values → PNG | 20 ms |
Lines with sorted numeric x values are downsampled when they have more than four points per pixel column of the plot (counted at a nominal 300 dpi), keeping the first, last, minimum and maximum point in each column, which is visually lossless. Large scatter plots are composited on up to 8 threads; the output is the same for any number of threads.
Rust
The rendering core is published as the umber-core crate and can be used directly from Rust:
use umber_core::{AxisData, Figure, LineOptions, ScaleKind, Theme};
let mut figure = Figure::new(6.0, 4.0, Theme::pigment())?;
figure
.add_axes(ScaleKind::Linear, ScaleKind::Linear)?
.title("Signal")
.line(AxisData::Numbers(vec![0.0, 1.0, 2.0, 3.0]), &[1.0, 3.0, 2.0, 4.0], LineOptions::default())?;
std::fs::write("signal.png", figure.to_png(144)?)?;
Status
umber is at version 0.x. The API is not yet stable and may change or be removed without a deprecation period. More examples are in examples/.
License
Licensed under either of MIT or Apache-2.0, at your option (MIT OR Apache-2.0). Bundled fonts are under the SIL Open Font License 1.1; see crates/umber-core/fonts/LICENSES and crates/umber-core/fonts/MANIFEST.md. Wheels include statically linked Rust dependencies; their licenses are listed in THIRD-PARTY-LICENSES.txt.
Metadata
Release files for umber 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| umber-0.1.0.tar.gz | 951.6 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| umber-0.1.0-cp312-abi3-win_amd64.whl | CPython 3.12 | abi3 | Windows x86-64 | Details |
| umber-0.1.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.12 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| umber-0.1.0-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.12 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| umber-0.1.0-cp312-abi3-macosx_11_0_arm64.whl | CPython 3.12 | abi3 | macOS 11.0+ ARM64 | Details |
| umber-0.1.0-cp312-abi3-macosx_10_12_x86_64.whl | CPython 3.12 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 14.7 MB
Release files / umber-0.1.0.tar.gz
| Download URL | umber-0.1.0.tar.gz |
|---|---|
| Size | 951.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2c7ed1a53d8c031e51aa6cea3c95432b8fe4636ac98d073c30aefc7c19121cb7
|
|
BLAKE2b-256 checksum How to use checksums |
e0400df4cac11cc67a32cc483cc5e0e8ffdc6a968c32a0381a22b90211c5835e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.
Transparency logRelease files / umber-0.1.0-cp312-abi3-win_amd64.whl
| Download URL | umber-0.1.0-cp312-abi3-win_amd64.whl |
|---|---|
| Size | 2.5 MB |
| Tags | CPython 3.12 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
43579118f79d0de9d37f4bca6f4368becddb57c80a431f5601190798d06e8b47
|
|
BLAKE2b-256 checksum How to use checksums |
a019b5d1e8d3bf48105da553af98338a2e32e2e17b5b84153f5f5a7b65c1ed9d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.
Transparency logRelease files / umber-0.1.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | umber-0.1.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 2.9 MB |
| Tags | CPython 3.12 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
2940c6772d0226637283ccfb0b96cd325f1dcbcc145a380bb19ce3fbfe40e986
|
|
BLAKE2b-256 checksum How to use checksums |
3bed3fa026427fe3e438f14015b180b0a1310f2e053c108da507a3738927ff7f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.
Transparency logRelease files / umber-0.1.0-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | umber-0.1.0-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 2.9 MB |
| Tags | CPython 3.12 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
68c1d393ece3bd8ccc11ab03145dc47157899243086014d5e5123c77e82b7b0d
|
|
BLAKE2b-256 checksum How to use checksums |
730878396b09c3138a0796720f45b3f73b45c5122d5415c824b2b4a04f767b25
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.
Transparency logRelease files / umber-0.1.0-cp312-abi3-macosx_11_0_arm64.whl
| Download URL | umber-0.1.0-cp312-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 2.7 MB |
| Tags | CPython 3.12 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
e3e275ec2f2c416100d3cf1efb3c3de709194dbd63273c361fb0b7ec3348c9f2
|
|
BLAKE2b-256 checksum How to use checksums |
d3152b9ab242f9fa884ffc1c2de38168bd5c4b7861cf57a7465c6d549f783136
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.
Transparency logRelease files / umber-0.1.0-cp312-abi3-macosx_10_12_x86_64.whl
| Download URL | umber-0.1.0-cp312-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 2.7 MB |
| Tags | CPython 3.12 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
5570f56f1258d4d47d46c2bba81d01a766a45522cb419ee7d0eda733fec37463
|
|
BLAKE2b-256 checksum How to use checksums |
79a9a1083eede327f74185f15031f6e0b097095e8aa96856553ea7df586c569e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.
Transparency log