ruviz
Rust-powered plotting for Python. ruviz wraps the ruviz
rendering engine in a fluent, fully typed Python API: build a plot by chaining
method calls, then export it to PNG, SVG, or PDF, display it in a Jupyter cell,
drive it live from an observable, or open it in a native desktop window. NumPy
arrays cross into Rust with a single memcpy and rendering runs with the GIL
released, so million-point series stay interactive.
Install
pip install ruviz
The base install pulls in NumPy only. Everything else is an extra:
| Extra | Install | Adds |
|---|---|---|
| — | pip install ruviz |
Static PNG/SVG/PDF export, native show(), static notebook display |
widget |
pip install "ruviz[widget]" |
anywidget + traitlets for plot.widget() and RuvizWidget |
pandas |
pip install "ruviz[pandas]" |
pandas DataFrame columns through data= |
polars |
pip install "ruviz[polars]" |
Polars DataFrame columns through data= |
dataframes |
pip install "ruviz[dataframes]" |
Both dataframe backends |
all |
pip install "ruviz[all]" |
Every extra |
import ruviz works without any extra; plot.widget() and ruviz.RuvizWidget
raise an ImportError that names ruviz[widget] when the extra is missing.
Quick Start
import numpy as np
import ruviz
x = np.linspace(0.5, 12.0, 60)
fast = 8.0 * np.exp(-x * 0.62)
slow = 6.0 * np.exp(-x * 0.22)
(
ruviz.plot()
.size_px(760, 420)
.title("Decay Rates")
.xlabel("time")
.ylabel("intensity")
.line(x, fast, label="fast decay", color="#2563eb", width=2.0)
.line(x, slow, label="slow decay", color="orange", linestyle="dashed")
.yscale("log")
.grid(True)
.legend("upper_right")
.save("decay.png")
)
Features
- 15 plot types — line, scatter, bar, histogram, boxplot, violin, kde, ecdf, error bars (y and xy), heatmap, contour, pie, radar, polar line.
- Per-series styling — labels, colors, alpha, widths, line styles, markers,
plus kind-specific
bins,bandwidth, andlevels. - Axis control —
legend(),grid(),xlim/ylim, and linear, log, or symlog scales. - Static export —
save()writes PNG, SVG, or PDF;render_png()returns bytes andrender_svg()returns a string. - Jupyter — plots display as a static PNG by default;
plot.widget()gives you the synced, zoomable WASM widget with theruviz[widget]extra. - Live data —
ruviz.observable(...)series support elementwise arithmetic and NumPy ufuncs, and push updates into attached widgets. - DataFrames — pandas, Polars, plain dicts, and anything else indexable by
column name through
data=. - Experimental 3D alpha — deterministic static export for
scatter3d,line3d,surface, andwireframe. - Typed — inline annotations with a
py.typedmarker, so a type checker rejects a badmarker=,linestyle=, legend position, or axis scale before the call reaches the renderer. - Fast — adding a 1,000,000-point line series takes about 1 ms (it was
141 ms before the arrays were passed as a single
memcpy), and rendering, saving, and native display all release the GIL.
Styling
Series style arguments are keyword-only, and each kind accepts exactly what the renderer honors for it:
| method | keywords |
|---|---|
line |
label, color, alpha, width, linestyle, marker, marker_size |
scatter |
label, color, alpha, marker, marker_size |
bar |
label, color, alpha |
histogram |
label, color, alpha, bins |
boxplot |
label, color, alpha, width, linestyle |
kde |
label, color, alpha, width, bandwidth |
ecdf, violin, polar_line, error_bars, error_bars_xy |
label, color, alpha, width |
contour |
alpha, width, levels |
heatmap, pie, and radar take no style keywords.
colortakes a hex string ("#2563eb","#25f","#2563eb80") or a named color such as"red","orange","teal", or"crimson"; a typo raisesValueErrorwith a "did you mean" suggestion.linestyleis one ofsolid,dashed,dotted,dash-dot,dash-dot-dot.markeris one ofcircle,square,triangle,triangle-down,diamond,plus,cross,star,circle-open,square-open,triangle-open,diamond-open.- The matplotlib shorthands are accepted as aliases —
"o","s","^","v","D","+","x","*"formarkerand"-","--",":","-."forlinestyle— and snapshots store the canonical name. - Unsupported names raise
ValueErrorlisting the accepted values at the call that used them, not at render time.
Plot-level settings are legend(position="best") — "best" plus lowercase
position names such as "upper_right", "center", or "outside_right" —
grid(enabled=True), dpi(dpi), xlim(min, max), ylim(min, max), and
xscale(scale, linthresh=None) / yscale(...) with "linear", "log", or
"symlog". dpi scales the exported pixels from size_px(...), so
size_px(640, 480).dpi(200) writes a 1280×960 image. Axis limits must be finite
and different; passing them inverted, as in xlim(10, 0), renders a descending
axis (Plot3D limits stay strictly ascending).
Notebook widgets render these settings too: the WASM runtime applies series
styles, dpi, legend, grid, axis limits, and axis scales from the
snapshot.
Notebook and Desktop Usage
- In Jupyter, a bare plot result and
plot.show()both display a static PNG. - Use
plot.widget()when you want the synced WASM-backed notebook widget. plot.size_px(width, height)also controls the widget's displayed size and aspect ratio.- Without
size_px(...), the widget uses the default PNG size (640x480) and shrinks proportionally if the notebook column is narrower. - Drag the widget's bottom-right handle to resize the display freely; hold
ShiftorCtrlwhile dragging to preserve the aspect ratio. - In the widget, the mouse wheel zooms, left drag pans, right drag box-zooms, and right click opens the export menu.
- Outside notebooks,
plot.show()opens the native interactive window. - The published Linux wheel focuses on static rendering and notebook widgets. Install from source on Linux if you need the native desktop
plot.show()window. plot.render_png()returns PNG bytes andplot.render_svg()returns an SVG string.plot.save(path)writes PNG, SVG, or PDF according to the file extension and returns the outputPath; any other extension, or a path without one, raisesValueError.
Reactive Notebook Data
Use ruviz.observable(...) for notebook-driven updates that keep explicit
widgets in sync:
import numpy as np
import ruviz
x = np.linspace(0.0, 6.0, 200)
y = ruviz.observable(np.sin(x))
plot = ruviz.plot().size_px(640, 360).line(x, y).title("Live Sine Wave")
widget = plot.widget()
ObservableSeries supports elementwise arithmetic and NumPy ufuncs. Derived
observables stay live until you write to them directly. Live observable series
are supported by line, scatter, bar, histogram, boxplot,
error_bars, and error_bars_xy; other plot types reject them with a
TypeError and expect static values.
import numpy as np
scaled = np.sin(y * 2.0 + 0.25)
plot.line(x, scaled)
y.replace(np.cos(x))
replace() is atomic: when the new length would break a bound series — directly
or through a derived observable — it raises ValueError before anything
mutates. Derived observables resize along with their source, so a plot of x
against np.sin(x) stays consistent when x grows, and writing to an
observable with replace() or set_at() permanently detaches it from its own
sources. len(series) and series[i] read the current values.
deepcopy(plot) creates an independent live copy with fresh observables, while
plot.clone() remains a static snapshot copy.
Experimental 3D Alpha
The Python wheel includes the Rust crate's opt-in Cargo feature named exactly
3d. The initial Python surface provides deterministic CPU export for opaque
scatter3d, line3d, regular-grid surface, and wireframe plots:
import numpy as np
import ruviz
x = np.linspace(-2.0, 2.0, 32)
y = np.linspace(-2.0, 2.0, 24)
grid_x, grid_y = np.meshgrid(x, y)
z = np.sin(grid_x**2 + grid_y**2)
(
ruviz.surface(x, y, z)
.size_px(720, 480)
.title("3D surface alpha")
.xlabel("x")
.ylabel("y")
.zlabel("z")
.save("surface.png")
)
For surfaces and wireframes, rows of z correspond to y and columns
correspond to x, so z.shape == (len(y), len(x)). Orthographic projection is
the default; .perspective_deg(45.0) opts into perspective. This alpha is
static-only in Python: interactive orbit widgets, transparency, volume plots,
arbitrary meshes, and mixed 2D/3D axes are not yet exposed.
Supported Python Versions and Platforms
- Python 3.10 or newer. Wheels are built as a single
abi3artifact per platform and are tested against 3.10 and 3.13. - Wheels: macOS x86_64 and arm64, Windows x86_64, Linux x86_64 and aarch64 (manylinux 2_28). A source distribution is published as well.
- The Linux wheels are built without the native interactive backend, so
plot.show()raises there and asks you to install from source.
Documentation
- Python docs source — getting started, interactivity, gallery, and the generated API reference
- Python examples — the runnable scripts the gallery is generated from
- Project README and Rust API docs
Contributor Workflow
cd bindings/python
uv sync
uv run maturin develop
uv run python scripts/generate_gallery.py
uv run mkdocs serve
Rebuild the bundled widget frontend from the repository root when you change
the web SDK or packages/ruviz/src/python-widget.ts:
bun run build:python-widget
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ruviz-0.7.0.tar.gz.
File metadata
- Download URL: ruviz-0.7.0.tar.gz
- Upload date:
- Size: 6.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d21a05801a59e891a5ec19327e239d7819ed782930529f50ed81dc83cb45ff4
|
|
| MD5 |
d129de5fd12f5b26e5a6589f042d7480
|
|
| BLAKE2b-256 |
46ac725c6ccc7922eedc3701728d4bfee7b9390b2f8d51419a65a6a59c182e42
|
Provenance
The following attestation bundles were made for ruviz-0.7.0.tar.gz:
Publisher:
release.yml on Ameyanagi/ruviz
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ruviz-0.7.0.tar.gz -
Subject digest:
9d21a05801a59e891a5ec19327e239d7819ed782930529f50ed81dc83cb45ff4 - Sigstore transparency entry: 2343853036
- Sigstore integration time:
-
Permalink:
Ameyanagi/ruviz@8ec84427d9818b9cb13d3dc252ebf44a9846b5bc -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/Ameyanagi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8ec84427d9818b9cb13d3dc252ebf44a9846b5bc -
Trigger Event:
push
-
Statement type:
File details
Details for the file ruviz-0.7.0-cp310-abi3-win_amd64.whl.
File metadata
- Download URL: ruviz-0.7.0-cp310-abi3-win_amd64.whl
- Upload date:
- Size: 7.6 MB
- Tags: CPython 3.10+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6631befa28ab58e0b6a07d9335a99e26034ffe35bdb155347254492829097fe4
|
|
| MD5 |
101def8c6a927fb9c25ac6228145541a
|
|
| BLAKE2b-256 |
03c87c3d9fb03f766277009b8dc6aed50cb16fddc8eee77173f435d8cc489ac2
|
Provenance
The following attestation bundles were made for ruviz-0.7.0-cp310-abi3-win_amd64.whl:
Publisher:
release.yml on Ameyanagi/ruviz
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ruviz-0.7.0-cp310-abi3-win_amd64.whl -
Subject digest:
6631befa28ab58e0b6a07d9335a99e26034ffe35bdb155347254492829097fe4 - Sigstore transparency entry: 2343853075
- Sigstore integration time:
-
Permalink:
Ameyanagi/ruviz@8ec84427d9818b9cb13d3dc252ebf44a9846b5bc -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/Ameyanagi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8ec84427d9818b9cb13d3dc252ebf44a9846b5bc -
Trigger Event:
push
-
Statement type:
File details
Details for the file ruviz-0.7.0-cp310-abi3-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: ruviz-0.7.0-cp310-abi3-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 7.5 MB
- Tags: CPython 3.10+, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b83d0362d69e61954b1f70dbedf0199ac05ee8fbbf2c841ab90c139c0dfb0f9e
|
|
| MD5 |
c8cee6a735c4f523a4d21af1f06eaf39
|
|
| BLAKE2b-256 |
c470c0536b6b29124102f106a21c3f7eefe1405f11485a4c5a4e3155bb79f813
|
Provenance
The following attestation bundles were made for ruviz-0.7.0-cp310-abi3-manylinux_2_28_x86_64.whl:
Publisher:
release.yml on Ameyanagi/ruviz
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ruviz-0.7.0-cp310-abi3-manylinux_2_28_x86_64.whl -
Subject digest:
b83d0362d69e61954b1f70dbedf0199ac05ee8fbbf2c841ab90c139c0dfb0f9e - Sigstore transparency entry: 2343853117
- Sigstore integration time:
-
Permalink:
Ameyanagi/ruviz@8ec84427d9818b9cb13d3dc252ebf44a9846b5bc -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/Ameyanagi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8ec84427d9818b9cb13d3dc252ebf44a9846b5bc -
Trigger Event:
push
-
Statement type:
File details
Details for the file ruviz-0.7.0-cp310-abi3-manylinux_2_28_aarch64.whl.
File metadata
- Download URL: ruviz-0.7.0-cp310-abi3-manylinux_2_28_aarch64.whl
- Upload date:
- Size: 7.3 MB
- Tags: CPython 3.10+, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a21e04142f1aa1fc097c5fbf77b42ed9601a18a1a7c5d899945473fcd95c41c2
|
|
| MD5 |
519b36dd6ac8597714738c8d20c333a5
|
|
| BLAKE2b-256 |
df194e545cf4429245364345079f4fe01e24b093c1357f1a925de7514d28e7d4
|
Provenance
The following attestation bundles were made for ruviz-0.7.0-cp310-abi3-manylinux_2_28_aarch64.whl:
Publisher:
release.yml on Ameyanagi/ruviz
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ruviz-0.7.0-cp310-abi3-manylinux_2_28_aarch64.whl -
Subject digest:
a21e04142f1aa1fc097c5fbf77b42ed9601a18a1a7c5d899945473fcd95c41c2 - Sigstore transparency entry: 2343853097
- Sigstore integration time:
-
Permalink:
Ameyanagi/ruviz@8ec84427d9818b9cb13d3dc252ebf44a9846b5bc -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/Ameyanagi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8ec84427d9818b9cb13d3dc252ebf44a9846b5bc -
Trigger Event:
push
-
Statement type:
File details
Details for the file ruviz-0.7.0-cp310-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: ruviz-0.7.0-cp310-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 7.6 MB
- Tags: CPython 3.10+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cd423f605e2711f1ef612e071d51f6475f5c8b3977c76ace16812b2712711982
|
|
| MD5 |
c9fa3336dd504376a33b27476a9899d2
|
|
| BLAKE2b-256 |
f189a084e098d5a8cf2c08d02fc1cb4a70a18f4dcdea4ad76d6d9a57c4511de7
|
Provenance
The following attestation bundles were made for ruviz-0.7.0-cp310-abi3-macosx_11_0_arm64.whl:
Publisher:
release.yml on Ameyanagi/ruviz
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ruviz-0.7.0-cp310-abi3-macosx_11_0_arm64.whl -
Subject digest:
cd423f605e2711f1ef612e071d51f6475f5c8b3977c76ace16812b2712711982 - Sigstore transparency entry: 2343853062
- Sigstore integration time:
-
Permalink:
Ameyanagi/ruviz@8ec84427d9818b9cb13d3dc252ebf44a9846b5bc -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/Ameyanagi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8ec84427d9818b9cb13d3dc252ebf44a9846b5bc -
Trigger Event:
push
-
Statement type:
File details
Details for the file ruviz-0.7.0-cp310-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: ruviz-0.7.0-cp310-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 7.8 MB
- Tags: CPython 3.10+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0d7824f102977e3c96bc292be6a9f2e3eaa74fe1e588a9b32ae3e0d01b4975af
|
|
| MD5 |
36de15d04c36e44b6d7a11196d11ac56
|
|
| BLAKE2b-256 |
b79c4cb98359e94352e2c5ad43f1ff46f3a358baf8018dff3f8840aa5b5584fa
|
Provenance
The following attestation bundles were made for ruviz-0.7.0-cp310-abi3-macosx_10_12_x86_64.whl:
Publisher:
release.yml on Ameyanagi/ruviz
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ruviz-0.7.0-cp310-abi3-macosx_10_12_x86_64.whl -
Subject digest:
0d7824f102977e3c96bc292be6a9f2e3eaa74fe1e588a9b32ae3e0d01b4975af - Sigstore transparency entry: 2343853136
- Sigstore integration time:
-
Permalink:
Ameyanagi/ruviz@8ec84427d9818b9cb13d3dc252ebf44a9846b5bc -
Branch / Tag:
refs/tags/v0.7.0 - Owner: https://github.com/Ameyanagi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8ec84427d9818b9cb13d3dc252ebf44a9846b5bc -
Trigger Event:
push
-
Statement type: