Skip to main content

hilbertplot

PyPI version CI Python versions License: MIT

The complete set of 40 two-dimensional Hilbert curves — and a fast way to plot long 1-D data on any of them.

Most software knows one Hilbert curve. In fact there are forty distinct space-filling curves of Hilbert type in two dimensions (up to rotation, reflection and reversion), as proved by Estevez-Rams et al., "Hilbert curves in two dimensions", Rev. Cub. Fís. 34, 9 (2017). hilbertplot implements all forty with pure-numpy generation and uses them to lay long 1-D vectors onto 2-D images.

The Hilbert curve at order 4, drawn as a colour-graded path

Install

pip install "hilbertplot[plot]"   # drop [plot] for a numpy-only core (no matplotlib)

Draw a curve

import hilbertplot

c = hilbertplot.curve(0)     # by index 0–39, by name ("Moore"), or by symbol
c.show(4)                    # draw order 4 in a window
pts = c.points(4)            # (256, 2) integer lattice points, in visit order

The forty curves come in named groups — hilbertplot.proper(), .improper(), .homogeneous(), .inhomogeneous(), .generalizing() — each of which prints as a table, and which compose:

import hilbertplot

print(hilbertplot.proper())                       # a table of the six proper curves
hilbertplot.catalog().closed().names              # ['Moore', 'Liu1', 'Improper1', 'Improper4']
hilbertplot.by_kernels(3, 5).gallery(order=3)     # draw a group as a grid of panels

In a Jupyter notebook a Curve renders itself — put hilbertplot.curve("Moore") in a cell and you get the picture, not a repr.

One cell at a time

points(order) builds all 4**order cells. When you only need where step i lands, encode answers in O(order) — so it works at orders no machine could materialise, and it does so for all forty curves, not just the classic one:

import hilbertplot

c = hilbertplot.curve(0)
c.encode(5, 2)                     # (0, 3) — the cell visited at step 5, order 2
c.decode(0, 3, 2)                  # 5      — and back again
c.encode(10**18, 40)               # (751054336, 346100736) — a 2**80-cell curve

Plot data

Walk a curve and drop data[i] on the i-th cell it visits: a locality-preserving 1-D → 2-D map where nearby values stay nearby.

import numpy as np, hilbertplot

plot = hilbertplot.hilbert_plot(0, np.arange(1, 257))
plot.show("viridis")          # a matplotlib colormap name, or a list of colours to blend

The same data laid on two different curves

The same numbers on curve 0 and curve 32 — one reason to have all forty.

Seeing more than the data

Coarse-grain it. plot.show(granularity=4) replaces each block of values by its mean. Below, a binary sequence interleaves stretches of two periodic patterns with identical density — invisible in the faithful plot, obvious once averaged.

Periodic regions revealed by coarse-graining

Find where locality breaks. plot.show(difference=True) marks the cells that are neighbours in the plane but far apart along the curve. A higher threshold keeps only the worst offenders.

The difference map at two thresholds

Transform it. plot.show(fourier=True) renders the 2-D Fourier map, exposing periodic and self-similar structure — here, a Thue–Morse sequence.

A Thue–Morse sequence and its Fourier map

Also

  • curve.unroll(img) — read a 2-D array back into 1-D, in curve order
  • curve.grid(n) — the eight generalizing() curves tile any n×n square, not just 2ᵏ
  • curve.label_map(order) — the grid of visit indices, as an image
  • curve.difference_map(order) — where the curve breaks locality, as a field
  • plot.draw(colorbar=True), or norm=LogNorm() for heavy-tailed data
  • hilbertplot.is_space_filling / canonical_form — check a path yourself; the same tools the test suite uses to prove all forty curves are distinct Hamiltonian paths
  • hilbertplot.clear_cache() / cache_info() — generated curves are memoised; this frees them
  • hilbertplot.set_cell_limit(n) — raise the guard that refuses absurdly large orders

Every figure above is reproducible: python examples/readme_figures.py. More runnable demos are in examples/; the arbitrary-square classification and its impossibility proofs are in the repository's research/quasisquares/.

License

MIT © Daniel Estevez — LICENSE

Metadata

Release files for hilbertplot 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hilbertplot 0.2.0
File Size Uploaded
hilbertplot-0.2.0.tar.gz 72.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hilbertplot 0.2.0
File Interpreter ABI Platform
hilbertplot-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 127.3 kB

Release files / hilbertplot-0.2.0.tar.gz

Download URL hilbertplot-0.2.0.tar.gz
Size 72.8 kB
Tags Source
SHA-256 checksum
How to use checksums
88aab83ff88505fd4646a10a58437f9cdbd1693c1fa02888acb1a8fdb23ac212
BLAKE2b-256 checksum
How to use checksums
b80c941958a81afbbb6d3a44453124231bf64f32f47526a75f99d9c29e359920
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.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 Jul 25, 2026.

Transparency log

Release files / hilbertplot-0.2.0-py3-none-any.whl

Download URL hilbertplot-0.2.0-py3-none-any.whl
Size 54.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
86b2d57de03b0b56226545121d25a626888d2d2ecbea264d9181e8ee964151fc
BLAKE2b-256 checksum
How to use checksums
bb57dc82e8b030f83eb7328f65ec16acabab9f7c4566d4588f1c4acdb2087c4d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.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 Jul 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

2 release files

0.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page