V2.0.1 : New Plot Types, Semantic Legends, More flexible Colorbars and Smarter Layouts
LatestUltraPlot v2.0.1
UltraPlot v2.0.1 is our biggest release yet. Since v1.72.0, we have rebuilt core parts of the library around semantic legends, more reliable layout behavior, stronger guide architecture, and a much more stable CI pipeline. We also launched a brand-new documentation site at https://ultraplot.readthedocs.io/ with a gallery that gives a bird’s-eye view of Matplotlib’s key capabilities through UltraPlot. On the performance side, import times are significantly lower thanks to a new lazy-loading system. And for complex figure composition, sharing logic is now smarter about which axes should be linked, so multi-panel layouts behave more predictably with less manual tweaking.
snippet
import numpy as np
import ultraplot as uplt
rng = np.random.default_rng(7)
fig, ax = uplt.subplots(refwidth=4, refheight = 2)
t = np.linspace(0.0, 8.0 * np.pi, 700)
signal = 0.50 * np.sin(t) + 0.20 * np.sin(0.35 * t + 0.8)
trend = 0.55 * np.cos(0.50 * t)
ax.plot(t, signal, c="blue7", lw=2.2, label="Signal", zorder=-1)
ax.plot(t, trend, c="gray6", lw=1.4, ls="--", alpha=0.8, label="Trend", zorder=-1)
ax.fill_between(t, signal - 0.11, signal + 0.11, color="blue2", alpha=0.30, lw=0)
cats = np.array(["A", "B", "C"])
cat_markers = {"A": "o", "B": "s", "C": "^"}
cat_colors = {"A": "blue7", "B": "orange7", "C": "green7"}
n = 85
xp = np.sort(rng.choice(t, size=n, replace=False))
cp = rng.choice(cats, size=n, p=[0.35, 0.40, 0.25])
yp = np.interp(xp, t, signal)
amp = np.interp(xp, t, np.abs(signal))
sizes = 24 + 220 * amp
score = np.clip(0.15 + 0.85 * amp + 0.07 * rng.normal(size=n), 0, 1)
for cat in cats:
mask = cp == cat
ax.scatter(
xp[mask],
yp[mask],
c=score[mask],
cmap="viko",
vmin=0,
vmax=1,
s=sizes[mask],
marker=cat_markers[cat],
ec="black",
lw=0.45,
alpha=0.9,
)
ax.curvedtext(
t,
signal + 0.16,
"UltraPlot v2.0",
ha="center",
va="bottom",
color="black",
size=10,
weight="bold",
)
ax.format(
title="Semantic Legends + Curved Text + Smart Layout",
xlabel="Phase",
ylabel="Amplitude",
xlim=(0, 8 * np.pi),
ylim=(-1.2, 1.2),
grid=True,
gridalpha=0.22,
)
ax.catlegend(
cats,
colors=cat_colors,
markers=cat_markers,
line=False,
loc="l",
title="Category",
frameon=False,
handle_kw={"ms": 8.5, "ec": "black", "mew": 0.8},
ncols=1,
)
ax.sizelegend(
[25, 90, 180],
color="gray7",
loc="b",
align="l",
title="Magnitude",
frameon=False,
handle_kw={"ec": "black", "linewidths": 0.8},
)
ax.numlegend(
vmin=0,
vmax=1,
n=5,
cmap="viko",
loc="r",
align="b",
title="Score",
frameon=False,
handle_kw={"edgecolors": "black", "linewidths": 0.4},
ncols=1,
)
ax.entrylegend(
[
("Reference", {"line": True, "lw": 2.2, "ls": "-", "c": "blue7"}),
("Samples", {"line": False, "m": "o", "ms": 7, "fc": "white", "ec": "black"}),
],
loc="r",
align="t",
title="Glyph key",
frameon=False,
ncols=1,
)
inax = ax.inset((0.75, 0.75, 0.2, 0.2), zoom=0, projection="ortho")
inax.format(land=1, ocean=1, landcolor="mushroom", oceancolor="ocean blue")
fig.show()Highlights
- New Layout Solver. We have replaced the layout solver to provide snappier, and better layout handling to make the even tighter.
- New semantic legend system with categorical, size, numeric, and geographic legend builders (#586).
- New legend primitives: LegendEntry and improved legend handling for wedge/pie artists (#571).
- Major legend internals refactor via a dedicated UltraLegend builder (#570).
- Colorbar architecture refactor: colorbars are now decoupled from axes internals through UltraColorbar and UltraColorbarLayout (#529).
New Features
- Top-aligned ribbon flow plot type (#559).
- Curved annotation support (#550).
- Ridgeline histogram histtype support (#557).
- Compatibility-aware auto-share defaults (#560).
- PyCirclize integration for circular/network workflows (#495).
Layout, Rendering, and Geo Improvements
- Multiple UltraLayout fixes for spanning axes, gaps, and shared labels (#555, #532, #584).
- Improved inset colorbar frame handling (#554 and related follow-ups).
- Better suptitle spacing in non-bottom vertical alignments (#574).
- Polar tight-layout fixes (#534).
- Geo tick/label robustness improvements (#579, related geo labeling fixes).
- Opt-in subplot pixel snapping plus follow-up adjustments (#561, #567).
Stability, Tooling, and Compatibility
- Python 3.14 support (#385).
- Improved CI matrix coverage and determinism (#587, #580, #577, #545 and related CI fixes).
- pytest-mpl style/baseline stabilization and improved test selection behavior (#528, #533, #535).
- Docs and theme updates, including warnings cleanup and presentation improvements (#585, #552).
Upgrade Notes
- Legend and colorbar internals were significantly refactored. Public usage remains familiar, but extensions relying on internals should be
reviewed. - Semantic legends now have a clearer API surface and are ready for richer per-entry styling workflows.
Full Changelog
v1.72.0...v2.0.1
v1.72.0...v2.0.1