SkillAgentSearch skills...

Ruviz

High-performance 2D plotting library for Rust combining matplotlib's ease-of-use with Makie's performance.

Install / Use

/learn @Ameyanagi/Ruviz
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

ruviz

High-performance 2D plotting library for Rust combining matplotlib's ease-of-use with Makie's performance.

Crates.io Documentation License CI

Release Notes

Package Surfaces

  • Rust crate: ruviz
  • GPUI adapter crate: ruviz-gpui
  • Raw Rust wasm bridge: ruviz-web
  • Python package: ruviz in python/
  • npm package: ruviz in packages/ruviz-web/

Release-facing media and generated docs now use the documented layout in docs/BUILD_OUTPUTS.md. Regenerate the full release docs surface with make release-docs on the release docs branch.

Quick Start

use ruviz::prelude::*;

let x: Vec<f64> = (0..50).map(|i| i as f64 * 0.1).collect();
let y: Vec<f64> = x.iter().map(|&x| x * x).collect();

Plot::new()
    .line(&x, &y)
    .title("Quadratic Function")
    .xlabel("x")
    .ylabel("y = x^2")
    .save("plot.png")?;

Need typeset math labels? See Typst Text Mode below.

Example Plot

Features

🛡️ Safety & Quality

  • Zero unsafe in public API
  • Strong type system prevents runtime errors
  • Comprehensive error handling with Result types
  • Memory-safe by design

📊 Plot Types

Basic: Line, Scatter, Bar, Histogram, Box Plot, Heatmap Distribution: Violin, KDE, ECDF Composition: Pie, Donut Continuous: Contour Polar: Polar Plot, Radar Chart Error: Error Bars (symmetric/asymmetric)

🎨 Publication Quality

  • High-DPI export: 72, 96, 300, 600 DPI for print
  • Multiple formats: PNG, SVG, and PDF (with the pdf feature)
  • Professional themes: Light, Dark, Publication, Seaborn-style
  • Custom styling: Colors, fonts, markers, line styles
  • International text: Full UTF-8 support (Japanese, Chinese, Korean, etc.) with cosmic-text

⚡ Advanced Features

  • Simple API: One-liner functions for quick plotting
  • Parallel rendering: Multi-threaded for large datasets (rayon)
  • GPU acceleration: Optional wgpu backend (experimental)
  • Interactive plots: Optional desktop window integration on Linux, macOS, and Windows
  • Mixed-coordinate insets: Embed polar, pie, and radar plots inside Cartesian figures
  • Browser runtime: Experimental ruviz-web adapter and ruviz npm SDK for wasm32 canvas rendering
  • Animation: GIF export with record! macro and easing functions
  • Cross-platform: Linux, macOS, Windows, and experimental browser/wasm targets

Installation

Add to your Cargo.toml:

[dependencies]
ruviz = "0.4.9"

Feature Flags

Choose features based on your needs:

[dependencies]
ruviz = { version = "0.4.9", features = ["parallel", "simd"] }

| Feature | Description | Use When | |---------|-------------|----------| | default | ndarray + parallel | General use | | parallel | Multi-threaded rendering | Large datasets | | simd | Vectorized transforms | Performance-critical | | animation | GIF animation export | Animated plots | | gpu | GPU acceleration backend (experimental) | Opt-in GPU rendering | | interactive | winit window support | Interactive plots | | ndarray_support | ndarray types | Scientific computing | | nalgebra_support | nalgebra vectors/matrices | Linear algebra workloads | | polars_support | DataFrame support | Data analysis | | pdf | PDF export | Publication output | | typst-math | Typst text engine for all plot text | Math-heavy publication plots | | full | Most bundled features (excludes HQ GIF/video extras) | Power users |

For minimal builds: default-features = false

Benchmark note: the current Rust feature-impact study in docs/benchmarks/rust-feature-impact.md shows parallel is the main default performance feature to care about, simd is situational, and gpu should remain opt-in rather than a default build choice.

Experimental WASM Support

The core crate now compiles for wasm32-unknown-unknown with in-memory output helpers such as Plot::render_png_bytes(), Plot::render_to_svg(), and Image::encode_png().

For browser interactivity, use the companion Rust bridge crate in crates/ruviz-web and the public JS/TS SDK package ruviz. The reference browser demo lives in demo/web. Native file-path export helpers remain desktop-only.

Note:

  • ruviz automatically registers a bundled browser fallback font for canvas sessions.
  • Custom browser fonts can still be added explicitly via ruviz::render::register_font_bytes(...).
  • The current browser adapter provides main-thread canvas and OffscreenCanvas worker sessions, plus web_runtime_capabilities() for feature diagnostics.
  • The Vite demo includes direct wasm export, main-thread interactivity, worker interactivity, and temporal signal playback plus Observable-driven updates.
  • The JS workspace is Bun-first. Use bun install, bun run build:web, and bun run test:web from the repo root for browser package and demo work.

Python Bindings

The repo now includes a mixed Python package in python built with uv, maturin, and pyO3.

cd python
uv sync
uv run maturin develop

The Python package exposes a fluent ruviz.plot() builder for static export and uses the browser runtime for notebook widgets. Outside Jupyter, plot.show() uses 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 window there. Standalone MkDocs docs and runnable examples live under python/docs and python/examples.

Web SDK Docs

The browser-first JS/TS SDK in packages/ruviz-web now ships with runtime examples under packages/ruviz-web/examples and a standalone VitePress docs site under packages/ruviz-web/docs.

Typst Text Mode

Enable Typst text rendering:

[dependencies]
ruviz = { version = "0.4.9", features = ["typst-math"] }

Use .typst(true) on a plot to render all static text surfaces (titles, axis labels, ticks, legend labels, and annotations) through Typst:

use ruviz::prelude::*;

let x: Vec<f64> = (0..50).map(|i| i as f64 * 0.1).collect();
let y: Vec<f64> = x.iter().map(|&v| (-v).exp()).collect();

Plot::new()
    .line(&x, &y)
    .title("$f(x) = e^(-x)$")
    .xlabel("$x$")
    .ylabel("$f(x)$")
    .typst(true)
    .save("typst_plot.png")?;

Notes:

  • Invalid Typst snippets fail render/export with a TypstError.
  • .typst(true) is only available when typst-math is enabled at compile time.
  • Without typst-math, the compiler reports:
error[E0599]: no method named `typst` found for struct `ruviz::core::Plot` in the current scope
  • If you select the text engine directly, TextEngineMode::Typst is also unavailable without typst-math, and the compiler reports:
error[E0599]: no variant or associated item named `Typst` found for enum `TextEngineMode` in the current scope
  • If Typst is optional in your own crate, define and forward a local feature first:
[dependencies]
ruviz = { version = "0.4.9", default-features = false }

[features]
default = []
typst-math = ["ruviz/typst-math"]
  • Then guard the call with your crate feature:
use ruviz::prelude::*;

let mut plot = Plot::new()
    .line(&x, &y)
    .title("$f(x) = e^(-x)$")
    .xlabel("$x$")
    .ylabel("$f(x)$");

#[cfg(feature = "typst-math")]
{
    plot = plot.typst(true);
}

plot.save("typst_plot.png")?;
  • Migration: .latex(true) has been removed; use .typst(true) instead.
  • Typst text in PNG output is rasterized at native output scale (1x).
  • For maximum text sharpness, prefer higher DPI (for example .dpi(300)) or vector export (.export_svg(...) / .save_pdf(...)).
  • DPI changes output density, not the intended physical size of fonts, strokes, markers, or layout spacing.
  • Prefer .size(width_in, height_in) when you care about physical figure size. .size_px(width, height) is a convenience that maps pixels through the 100-DPI reference size before final output DPI is applied.
  • Ticks are enabled by default and render inward on all four sides. Use .ticks(false) to hide tick marks and tick labels while keeping the frame and axis titles.
  • Migration: if you want the older bottom/left-only tick appearance, call .ticks_bottom_left().
  • Migration: if you previously relied on high-DPI exports making lines, markers, or text look larger, set those sizes explicitly instead of relying on DPI.

Tick customization:

use ruviz::prelude::*;

Plot::new()
    .line(&x, &y)
    .tick_direction_inout()
    .ticks_bottom_left()
    .show_top_ticks(true)
    .show_right_ticks(true)
    .save("custom_ticks.png")?;

Examples

Basic Line Plot

use ruviz::prelude::*;

let x = vec![0.0, 1.0, 2.0, 3.0, 4.0];
let y = vec![0.0, 1.0, 4.0, 9.0, 16.0];

Plot::new()
    .line(&x, &y)
    .title("My First Plot")
    .save("output.png")?;

Multi-Series with Styling

use ruviz::prelude::*;

let x = vec![0.0, 1.0, 2.0, 3.0, 4.0];

Plot::new()
    .line(&x, &x.iter().map(|&x| x).collect::<Vec<_>>())
    .label("Linear")
    .line(&x, &x.iter().map(|&x| x * x).collect::<Vec<_>>())
    .label("Quadratic")
    .line(&x, &x.iter().map(|&x| x.powi(3)).collect::<Ve
View on GitHub
GitHub Stars37
CategoryDevelopment
Updated12h ago
Forks1

Languages

Rust

Security Score

75/100

Audited on Apr 9, 2026

No findings