planviz
The figure library for OpenPlan Labs — grid maps, search animations, plan timelines and benchmark charts, in the Frontier palette, light and dark from the same call.
Planners not included. This draws results; it does not produce them. It knows
nothing about any solver's types: a grid is a 2-D array where truthy means
blocked, a path is a sequence of (row, col) pairs, and a benchmark series is
a mapping. Anything that can produce those can be plotted.
That figure is the reason this package exists. Every search algorithm has the same three sets — the nodes you expanded, the nodes on the frontier, and the path you returned — so the brand's three colours are that legend, and the three sets differ by shape as well as hue, which is what survives greyscale printing and red/green colour blindness. Drawing it correctly by hand, in four repositories, twice each for light and dark, was the duplication this replaces.
Install
pip install planviz
Two dependencies, both of which a plotting library obviously needs:
matplotlib>=3.7 and numpy>=1.24. Python 3.10 or newer.
Not yet on PyPI — until then:
pip install git+https://github.com/openplan-labs/planviz.
GIF and MP4 writing needs a little more:
pip install 'planviz[animation]' # pillow for GIF, a bundled ffmpeg for MP4
Quickstart
import planviz
grid = [[0, 0, 0, 0], [0, 1, 1, 0], [0, 0, 0, 0]] # truthy = blocked
ax = planviz.draw_search(
expanded=[(0, 0), (1, 0), (2, 0), (2, 1)],
frontier=[(0, 1), (2, 2)],
path=[(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)],
grid=grid,
dark=True,
)
planviz.save(ax, "search.png")
Four things hold across the whole API:
- Importing
planvizchanges no matplotlib state. The style is applied byplanviz.use_style(dark=...), or per-figure inside astyle_contextthat restores rcParams on exit. A solver library can depend on this without repainting its user's notebook. - Every figure function takes
dark: bool = Falseand an optionalax=, so light and dark variants come from one call and figures compose into panels. - Nothing is saved or shown for you. Functions return the
Axesthey drew on (or theFigure, for multi-panel figures).planviz.save(...)is the explicit write. - The brand ships inside the wheel.
planviz/tokens.pyandplanviz/styles/frontier.mplstyleare generated fromopenplan-labs/brandingand checked for drift in CI, so nothing looks up a repository at runtime and a figure rendered offline matches one rendered on a laptop.
To style figures you draw yourself with the same values:
import matplotlib.pyplot as plt
from planviz import tokens
with planviz.style_context(dark=False) as t:
fig, ax = plt.subplots()
ax.plot(xs, ys, color=t.path) # the solution: the only warm value
ax.plot(xs, others, color=t.agent(0)) # supporting series: the agent ramp
Gallery
Every image below is generated by examples/gallery.py
from synthetic data, in both schemes, and is regenerated in CI. The full
gallery with code for each figure is at
openplan-labs.github.io/planviz/gallery.
Grids and agents
draw_grid |
draw_paths |
draw_paths(highlight=...) |
draw_heatmap |
animate_search and animate_paths. The frontier moves, the expanded set
accumulates, and the path appears once at the end and stays — the accumulated
closed list is the cost of the search, so erasing it hides the thing the
figure is arguing about. GIFs are capped at 12 fps and 800 px wide, because
they are read in a README on a train.
Search progress
search_panels |
radial_wavefront |
plan_timeline |
plan_timeline(timeline_from_paths(...)) |
Benchmarks
scaling_curve |
success_heatmap |
phase_breakdown |
crossover_plot |
The API
| Style | use_style(dark=False), style_context(dark=False), STYLE_PATH |
| Tokens | planviz.tokens — LIGHT, DARK, AGENT_RAMP, Tokens.agent(i), Tokens.sequential() |
| Grids and agents | draw_grid, draw_paths, draw_search, draw_heatmap, animate_paths, animate_search |
| Search progress | search_progress, search_panels, radial_wavefront, plan_timeline, timeline_from_paths, Step |
| Benchmarks | scaling_curve, success_heatmap, phase_breakdown, throughput_curve, crossover_plot |
| Output | save, save_animation, to_jshtml |
Full signatures: API reference.
What it does not do
- No solver adapters. There is no
plot_solution(pymapf.Solution). Callers pass arrays and mappings, which is what keeps one library serving four repositories with different problem types. - No grouped-bar chart and no parity scatter yet.
pymapf'splot_cost_comparisonandcuplan's_fig_qualityhave no home here in 1.0.0; see migration. - No 3-D space-time cube.
pymapf.viz.plot_spacetimestays where it is. - No live views.
LiveSolveViewand jupyddl'sLiveSearchPlotare solver observers, not figures; they belong with the solver they observe. - No interactivity, no web renderer. Static matplotlib output, plus GIF and MP4.
Who uses this
| Repository | What it draws with planviz |
|---|---|
| pymapf | grid maps, multi-agent routes, plan animations, congestion heatmaps, move/wait timelines, scaling charts |
| cuda-planning | the Experiments figures: scaling curves with min–max bands, coverage heatmaps, device phase breakdowns, throughput saturation, crossovers |
| PythonPDDL | --plot search progress, --tree radial wavefront, --plan-plot plan timelines |
| openplan-bench | the cross-repository comparison charts |
docs/migration.md maps each of their existing functions
onto a planviz call, one line at a time.
Contributing
Bug reports, figures that are wrong, and figures that are missing are all
welcome — see CONTRIBUTING.md. The binding constraint is
brand/figures.md;
the parts of it this library enforces are summarised in
design rules.
MIT licensed.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
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 planviz-1.0.0.tar.gz.
File metadata
- Download URL: planviz-1.0.0.tar.gz
- Upload date:
- Size: 58.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ca3bc01d718e967fa28af7a641ade85e74388df698083c90b82359bdf7f58074
|
|
| MD5 |
cf2212a3ff89f0ed4b4e769aa83d8804
|
|
| BLAKE2b-256 |
a8ca625ef4766c0f987fd2788ff9d038446d950595453f4c97a514f956a00e3f
|
Provenance
The following attestation bundles were made for planviz-1.0.0.tar.gz:
Publisher:
release.yml on openplan-labs/planviz
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
planviz-1.0.0.tar.gz -
Subject digest:
ca3bc01d718e967fa28af7a641ade85e74388df698083c90b82359bdf7f58074 - Sigstore transparency entry: 2539093546
- Sigstore integration time:
-
Permalink:
openplan-labs/planviz@7e9bc34977c23791ed8ccb407ba1b29a0814424e -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/openplan-labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7e9bc34977c23791ed8ccb407ba1b29a0814424e -
Trigger Event:
push
-
Statement type:
File details
Details for the file planviz-1.0.0-py3-none-any.whl.
File metadata
- Download URL: planviz-1.0.0-py3-none-any.whl
- Upload date:
- Size: 41.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ecda40561f02d805cf366724e6c55676145a51a2578dbe5d1c0f12df1bab2056
|
|
| MD5 |
ba71b20bcb05903a2c95f7ea2437eb46
|
|
| BLAKE2b-256 |
a781e16008ace705872e6c9c1a4048daf908af067d317cb7d2101e87324fe795
|
Provenance
The following attestation bundles were made for planviz-1.0.0-py3-none-any.whl:
Publisher:
release.yml on openplan-labs/planviz
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
planviz-1.0.0-py3-none-any.whl -
Subject digest:
ecda40561f02d805cf366724e6c55676145a51a2578dbe5d1c0f12df1bab2056 - Sigstore transparency entry: 2539093616
- Sigstore integration time:
-
Permalink:
openplan-labs/planviz@7e9bc34977c23791ed8ccb407ba1b29a0814424e -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/openplan-labs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7e9bc34977c23791ed8ccb407ba1b29a0814424e -
Trigger Event:
push
-
Statement type: