Skip to main content

xy

CI CodSpeed Python 3.11+ Docs

Grouped horizontal bar-chart comparison of xy, Matplotlib, and Plotly cold-render times at 10 million points; xy has the lowest measured time in all three output modes in this recorded run.

xy is an experimental Python charting library for large, interactive datasets. Its Rust core and WebGL2 renderer keep work bounded by what the screen can show.

[!IMPORTANT] This repo's docs will not be complete until official release. Current docs can be found here.

[!IMPORTANT] xy is early alpha; APIs may change before 1.0.

Highlights

  • Built for large data. Long lines are decimated and dense scatters become fixed-size density surfaces, then refine as you zoom.
  • Python-friendly. Compose charts from marks, axes, annotations, legends, tooltips, and callbacks—or use the familiar xy.pyplot interface.
  • Interactive by default. Pan, zoom, hover, select, and inspect exact source rows without shipping the entire dataset as JSON.
  • One chart, many outputs. Display in Jupyter, VS Code, Colab, and Marimo, or export self-contained HTML, browser-free PNG, and SVG.
  • Designed for applications. Layer marks and style both chart chrome and marks with CSS/Tailwind-friendly hooks, gradients, strokes, and curves.

Installation

uv add xy

Published wheels contain the Python package, JavaScript client, and native Rust core. End users do not need Rust, Node, npm, or a CDN.

Getting started

Create a small business chart:

import xy

months = [1, 2, 3, 4, 5, 6]
revenue = [42, 45, 48, 51, 55, 59]
pipeline = [35, 38, 42, 40, 46, 50]

chart = xy.line_chart(
    xy.line(months, revenue, name="revenue", color="#2563eb"),
    xy.line(months, pipeline, name="pipeline", color="#16a34a"),
    xy.x_axis(label="month"),
    xy.y_axis(label="USD thousands"),
    xy.legend(),
    title="Revenue vs pipeline",
)
# chart.to_html("chart.html")
# chart.to_png("chart.png")
# chart.to_svg("chart.svg")
chart

The same chart can be exported without changing how it is built.

xy currently includes line, scatter, area, histogram, bar and column, heatmap, error bar and band, box, violin, ECDF, hexbin, contour, step, stairs, stem, triangle mesh, and faceted charts. See the copyable examples for the complete surface.

Coming from matplotlib

For common pyplot workflows, change the import and keep the plotting code:

import numpy as np
import xy.pyplot as plt

x = np.linspace(0, 10, 200)
fig, ax = plt.subplots()
ax.plot(x, np.sin(x), "r--", label="signal")
ax.legend()
plt.show()

The shim intentionally covers common plotting workflows rather than every matplotlib feature. See the compatibility guide.

Benchmarks

These results come from the committed xy 0.1.0 launch baseline: identical seeded scatter data, a 900×420 output, and three isolated cold runs on an Apple M5 Pro with 64 GB RAM. Times are mean ± sample standard deviation.

Points Native static PNG Interactive, default GPU Interactive, CPU fallback xy representation
10k 0.0085 ± 0.0002 s 0.1533 ± 0.0079 s 0.9580 ± 0.0103 s direct
100k 0.0108 ± 0.0004 s 0.1742 ± 0.0029 s 0.9752 ± 0.0048 s direct
1M 0.0114 ± 0.0013 s 0.1688 ± 0.0081 s 0.9678 ± 0.0039 s density; density + sample interactive
10M 0.0232 ± 0.0023 s 0.1797 ± 0.0007 s 0.9920 ± 0.0078 s density; density + sample interactive
1B 1.1452 ± 0.0389 s 1.2530 ± 0.0018 s 2.0877 ± 0.0063 s density; density + sample interactive

At 10M points, the same recorded run measured:

900×420 output contract xy Matplotlib Plotly
Static CPU PNG 0.0232 s 2.7842 s 9.5834 s
Interactive first render, default GPU 0.1797 s 3.0029 s 3.6434 s
Interactive first render, CPU fallback 0.9920 s 3.6735 s 8.2152 s

At 1B points, xy produced a density PNG in 1.1452 seconds and an interactive density overview in 1.2530 seconds. The exact-point Plotly and Matplotlib paths did not complete within the benchmark's 36 GiB process-tree and 180-second limits. This does not mean xy draws one billion individual markers: it retains the source rows while rendering a screen-bounded density representation.

See the benchmark runbook, environment, and raw results to inspect or reproduce the measurements.

How it works

Most chart stacks serialize every value as JSON and ask the browser to draw every mark. xy instead keeps exact values in a ColumnStore, computes an appropriate level of detail in Rust, and transfers typed buffers that are bounded by the visible result.

flowchart LR
    subgraph PY["Python kernel / app process"]
        API["User APIs"] --> STORE["ColumnStore<br/>exact data + rollback checkpoints"]
        STORE --> CORE["Compute core<br/>native Rust C ABI<br/>(required; no fallback)"]
        CORE --> PAYLOAD["Payload builder"]
    end
    subgraph UI["Browser / notebook frontend"]
        WEBGL["WebGL2 renderer"]
        DOM["DOM chrome"]
        INPUT["Interaction layer"]
        WEBGL --> INPUT
        DOM --> INPUT
    end
    subgraph LOD["Adaptive large-data loop"]
        MODE["direct, decimated,<br/>density, adaptive"]
    end
    PAYLOAD -- "spec JSON + typed buffers<br/>no JSON number arrays" --> WEBGL
    INPUT --> MODE
    MODE -- "new screen-bounded payload" --> PAYLOAD

This is why zooming matters: a dense overview can use aggregation, while a narrow view can return to exact points. Canonical f64 data stays in Python so hover and selection can still return original rows.

For benchmark methodology and measured results, see the benchmark runbook and the committed launch report. For the full design, see the design dossier.

Stable vs. Experimental

Stable enough to build on today:

  • Python 3.11+ package import, the declarative composition model, notebook display, and standalone HTML, PNG, and SVG export.
  • Implemented 2D chart families, binary column payloads, and native Rust kernels bundled in published platform wheels.

Still experimental and expected to change before 1.0:

  • Reflex integration, callback payload details, chart breadth, and compatibility shims.
  • Adaptive drilldown internals and their performance thresholds.
Surface Current status Notes
Composition API Stabilizing alpha The single public chart-building API: declarative xy.chart(...children) with CSS/Tailwind hooks.
Standalone HTML export Stable alpha Self-contained output with the client and binary data included.
Native Rust backend Stable alpha; required compute core Published wheels include it; an unsupported build raises a clear error rather than degrading.
Reflex integration Experimental Kept outside the core package dependency graph.
Adaptive drilldown internals Experimental Protocols and thresholds may change.

The composition contract we are locking is intentionally narrow and durable: charts contain lightweight marks and chrome; Chart owns display and export; and class_name, class_names, and style reach stable DOM slots. It returns opaque framework objects passed to xy.legend(...) / xy.tooltip(...) to adapters without being serialized into standalone HTML. Python on_* callbacks stay widget-side; standalone HTML receives only the safe interaction flags needed for browser behavior.

Documentation

Engineering references:

Development

uv venv
uv pip install -e ".[dev]"
make check

Use make check-docs for README/API prose, examples, and public benchmark wording; make check-examples for executable examples; and make check-claims before moving measured claims into public-facing text. Benchmark changes use make check-benchmark-harness, which covers environment metadata and regression comparison scripts.

The focused gates are make check-security for standalone HTML export and browser client text handling, make check-errors for public errors and LOD/drill mutation boundaries, make check-api for public exports and public annotations, make check-import for lazy import and dependency boundaries including widget/export boundaries, and make check-ci for workflow and benchmark artifact wiring.

Browser work uses make check-browser, which runs the Browser lifecycle smoke (Chromium), Browser visual regression smoke (Chromium), and Browser interaction stress smoke (Chromium) gates. The full gate additionally needs Node 18+, cargo, rustc, and clippy (rustup component add clippy).

See CONTRIBUTING.md for the contributor workflow.

License

xy is licensed under the Apache License 2.0.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

xy-0.0.1-py3-none-musllinux_1_2_x86_64.whl (1.1 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

xy-0.0.1-py3-none-musllinux_1_2_armv7l.whl (1.0 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARMv7l

xy-0.0.1-py3-none-musllinux_1_2_aarch64.whl (1.0 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

xy-0.0.1-py3-none-manylinux_2_17_x86_64.whl (1.1 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

xy-0.0.1-py3-none-manylinux_2_17_armv7l.whl (1.0 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARMv7l

xy-0.0.1-py3-none-manylinux_2_17_aarch64.whl (1.0 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

xy-0.0.1-py3-none-macosx_11_0_arm64.whl (999.3 kB view details)

Uploaded Python 3macOS 11.0+ ARM64

xy-0.0.1-py3-none-macosx_10_12_x86_64.whl (1.0 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file xy-0.0.1-py3-none-musllinux_1_2_x86_64.whl.

File metadata

  • Download URL: xy-0.0.1-py3-none-musllinux_1_2_x86_64.whl
  • Upload date:
  • Size: 1.1 MB
  • Tags: Python 3, musllinux: musl 1.2+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.1-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 fb969fae3ab23b837d43b606c4d89c549b734571155828a61b349cf518eebf91
MD5 48113677c77a9443fffd6b1fd0960b17
BLAKE2b-256 a03a30500a86da0618f71833bf0632a926cc72c1b0db71eaed8d650565da1342

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.1-py3-none-musllinux_1_2_x86_64.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xy-0.0.1-py3-none-musllinux_1_2_armv7l.whl.

File metadata

  • Download URL: xy-0.0.1-py3-none-musllinux_1_2_armv7l.whl
  • Upload date:
  • Size: 1.0 MB
  • Tags: Python 3, musllinux: musl 1.2+ ARMv7l
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.1-py3-none-musllinux_1_2_armv7l.whl
Algorithm Hash digest
SHA256 395e4c7430d3e16ad63cd69bef025a4580ecb1f9798d806d3bc2ab7793d6d1a7
MD5 89ae7fbc2dd71a89782411b70bb968cc
BLAKE2b-256 3576909275b3c481c040fdec9f6f767f07eab56c0e0520a0aa2435bac31c7dc8

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.1-py3-none-musllinux_1_2_armv7l.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xy-0.0.1-py3-none-musllinux_1_2_aarch64.whl.

File metadata

  • Download URL: xy-0.0.1-py3-none-musllinux_1_2_aarch64.whl
  • Upload date:
  • Size: 1.0 MB
  • Tags: Python 3, musllinux: musl 1.2+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.1-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 1cdf30a8ae9427bac2077fc09b83e21ed5d0bb54b045d6d21b0ba4ec5120136b
MD5 9861161bba9f2b05209d2da442eed4ea
BLAKE2b-256 794e80152310817b07ebc6ea895be65036fa76a488035259eba055ec83e79a42

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.1-py3-none-musllinux_1_2_aarch64.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xy-0.0.1-py3-none-manylinux_2_17_x86_64.whl.

File metadata

  • Download URL: xy-0.0.1-py3-none-manylinux_2_17_x86_64.whl
  • Upload date:
  • Size: 1.1 MB
  • Tags: Python 3, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.1-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 92ff1177515a24eb87945d047572416f9c5cb7e884da1edf9d96c759a7d5c108
MD5 1ee8f37febf48d042ca1afd2c3a6c875
BLAKE2b-256 ee41119536dd3e1bef39be6004f003bcc6c2845e77909adbe6edcaa24c261951

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.1-py3-none-manylinux_2_17_x86_64.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xy-0.0.1-py3-none-manylinux_2_17_armv7l.whl.

File metadata

  • Download URL: xy-0.0.1-py3-none-manylinux_2_17_armv7l.whl
  • Upload date:
  • Size: 1.0 MB
  • Tags: Python 3, manylinux: glibc 2.17+ ARMv7l
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.1-py3-none-manylinux_2_17_armv7l.whl
Algorithm Hash digest
SHA256 c261ca75cb7cbc6a3d75c24203b5ac37fcebd0926f7e497ef73beb9c0e65865b
MD5 75da19453b7b484ffd3bcddd33883589
BLAKE2b-256 56cc91f953f903547e1cb0579ce8b2ea242b5b0defaf8516e958ee98d70b7fa6

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.1-py3-none-manylinux_2_17_armv7l.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xy-0.0.1-py3-none-manylinux_2_17_aarch64.whl.

File metadata

  • Download URL: xy-0.0.1-py3-none-manylinux_2_17_aarch64.whl
  • Upload date:
  • Size: 1.0 MB
  • Tags: Python 3, manylinux: glibc 2.17+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.1-py3-none-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 cdf6c76dc3c5a2a365c0d0daaba3b935da261f21a1dc4cfb6029e61db8283b00
MD5 63fa2a87e7f5cae35f93709030bcc52a
BLAKE2b-256 e2a13694eb1c554f99aa29d49dc34c2bbf7777e95b6ec3df654ae924f03b7b74

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.1-py3-none-manylinux_2_17_aarch64.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xy-0.0.1-py3-none-macosx_11_0_arm64.whl.

File metadata

  • Download URL: xy-0.0.1-py3-none-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 999.3 kB
  • Tags: Python 3, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.1-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 aa90b9e617dc09b997380cf4f2aeb81fefb6eb437611911162cde3fa1802e282
MD5 5eeff369adbd842499d6b0ed8ecb8202
BLAKE2b-256 148e91664f28cfbe7b84b4fafc9007696f8f3afbdf69d99d1a4e6cf71300a58c

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.1-py3-none-macosx_11_0_arm64.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file xy-0.0.1-py3-none-macosx_10_12_x86_64.whl.

File metadata

  • Download URL: xy-0.0.1-py3-none-macosx_10_12_x86_64.whl
  • Upload date:
  • Size: 1.0 MB
  • Tags: Python 3, macOS 10.12+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for xy-0.0.1-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 b48be2dc704d3c5a1201d848ec5ead5eb1279e150b801ca17ce43577c664a3e4
MD5 dfcd7b9f2a7fcbcc7dad29ca24c5dc73
BLAKE2b-256 d090fb44bfd5418942ddb2c11b5004b989012f9df08ad334aef2eace5c0fc69f

See more details on using hashes here.

Provenance

The following attestation bundles were made for xy-0.0.1-py3-none-macosx_10_12_x86_64.whl:

Publisher: release.yml on reflex-dev/xy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page