UltraPlot v2.1.5
The biggest additions are richer semantic size legends and first-class
choropleth support for geographic axes, alongside typing, plotting, CI, and
documentation improvements.
Highlights
Custom labels for Axes.sizelegend
sizelegend can now describe marker magnitudes in domain language instead of
just echoing the raw numeric levels.
Snippet
import numpy as np
import ultraplot as uplt
np.random.seed(42)
cities = [
"Tokyo",
"Delhi",
"Shanghai",
"Sao Paulo",
"Mumbai",
"Cairo",
"Beijing",
"Dhaka",
"Osaka",
"Lagos",
"Istanbul",
"London",
]
population = np.array(
[37.4, 32.9, 29.2, 22.4, 21.7, 21.3, 20.9, 23.2, 19.1, 16.6, 15.8, 9.5]
)
gdp_pc = np.array([42, 8, 23, 12, 7, 4, 22, 3, 38, 3, 14, 55])
growth = np.array([0.2, 2.8, 0.5, 0.7, 1.1, 1.9, 0.4, 3.1, 0.1, 3.5, 1.4, 0.8])
fig, ax = uplt.subplots(refwidth=4.5, refaspect=1.1)
ax.scatter(
gdp_pc,
growth,
s=population * 12,
c="cherry red",
edgecolor="gray8",
linewidth=0.5,
alpha=0.85,
absolute_size=True,
)
for i, city in enumerate(cities):
offset = (5, 5)
if city == "Osaka":
offset = (5, -10)
elif city == "Beijing":
offset = (-5, 8)
ax.annotate(
city,
(gdp_pc[i], growth[i]),
fontsize=6,
textcoords="offset points",
xytext=offset,
color="gray8",
)
ax.sizelegend(
[10 * 12, 20 * 12, 35 * 12],
labels={10 * 12: "10M", 20 * 12: "20M", 35 * 12: "35M"},
title="Population",
loc="ur",
frameon=False,
color="gray6",
edgecolor="gray8",
)
ax.format(
title="Megacities: Wealth vs Growth",
xlabel="GDP per capita (k USD)",
ylabel="Annual growth rate (%)",
xgrid=True,
ygrid=True,
xlim=(-2, 62),
ylim=(-0.3, 4.2),
)
fig.show()GeoAxes.choropleth for thematic maps
You can now color countries and polygon features directly from numeric values
while keeping the same UltraPlot formatting and colorbar workflow used on
cartesian plots.
Snippet
import numpy as np
import ultraplot as uplt
values = {
"United States of America": 83.6,
"Canada": 81.7,
"Mexico": 75.1,
"Brazil": 75.9,
"Argentina": 76.7,
"United Kingdom": 81.0,
"France": 82.5,
"Germany": 80.9,
"Italy": 83.5,
"Spain": 83.4,
"Norway": 83.2,
"Sweden": 83.0,
"Russia": 73.2,
"China": 78.2,
"Japan": 84.8,
"South Korea": 83.7,
"India": 70.8,
"Australia": 83.3,
"New Zealand": 82.1,
"South Africa": 64.9,
"Nigeria": 53.9,
"Egypt": 72.1,
"Saudi Arabia": 76.5,
"Turkey": 76.0,
"Indonesia": 71.9,
"Thailand": 78.7,
}
fig, ax = uplt.subplots(proj="merc", proj_kw={"lon0": 10}, refwidth=5.5)
m = ax.choropleth(
values,
country=True,
cmap="Glacial",
vmin=50,
vmax=88,
edgecolor="none",
linewidth=0,
colorbar="b",
colorbar_kw={"label": "Life expectancy (years)", "length": 0.7},
missing_kw={"facecolor": "gray8", "hatch": "///", "edgecolor": "gray5"},
)
ax.format(
title="Global Life Expectancy (2023)",
land=True,
landcolor="gray2",
ocean=True,
oceancolor="gray1",
coast=True,
coastcolor="gray4",
coastlinewidth=0.3,
borders=True,
borderscolor="gray4",
borderslinewidth=0.2,
longrid=False,
latgrid=False,
)
fig.show()Other changes
- Better static-analysis support for the lazy top-level API.
- Numeric scatter plots with explicit numeric colors now respect
cmap. - Shared boxplot tick labels no longer duplicate.
SubplotGridsingle-item 2D slices now keep returningSubplotGrid.- Helper and release-metadata coverage expanded and the CI flow was tightened.
What's Changed
- Honor cmap for numeric scatter colors by @cvanelteren in #616
- Fix release metadata and Zenodo flow by @cvanelteren in #620
- Publish Zenodo releases via API by @cvanelteren in #625
- Support Python 3.10 TOML loading by @cvanelteren in #626
- Bump dorny/paths-filter from 3 to 4 in the github-actions group by @dependabot[bot] in #624
- Add choropleth support to GeoAxes by @cvanelteren in #623
- CI: re-add Codecov upload by @cvanelteren in #633
- Fix duplicate shared boxplot tick labels by @cvanelteren in #630
- CI: restore PR Codecov uploads by @cvanelteren in #635
- add pytest tag by @cvanelteren in #637
- Increase coverage to 85% with targeted tests by @cvanelteren in #636
- Docs: cache jupytext conversion and restore incremental html by @cvanelteren in #603
- Improve gallery widget and thumbnail backgrounds by @cvanelteren in #644
- Support custom labels in sizelegend by @cvanelteren in #629
- fix: Refresh outdated contributor setup instructions by @JiwaniZakir in #646
- Refresh constructor registries after ticker reload by @cvanelteren in #645
- Honor patch linewidth rc for edgefix by @cvanelteren in #649
- Add typing block for inspection by @cvanelteren in #659
- Fix issue where single object returns object itself by @cvanelteren in #666
- Fix/gridspec indexing by @cvanelteren in #667
- Fix choropleth horizontal line artifacts on projected maps by @cvanelteren in #668
New Contributors
- @JiwaniZakir made their first contribution in #646
Full Changelog: v2.1.3...v2.1.5
What's Changed
- Honor cmap for numeric scatter colors by @cvanelteren in #616
- Fix release metadata and Zenodo flow by @cvanelteren in #620
- Publish Zenodo releases via API by @cvanelteren in #625
- Support Python 3.10 TOML loading by @cvanelteren in #626
- Bump dorny/paths-filter from 3 to 4 in the github-actions group by @dependabot[bot] in #624
- Add choropleth support to GeoAxes by @cvanelteren in #623
- CI: re-add Codecov upload by @cvanelteren in #633
- Fix duplicate shared boxplot tick labels by @cvanelteren in #630
- CI: restore PR Codecov uploads by @cvanelteren in #635
- add pytest tag by @cvanelteren in #637
- Increase coverage to 85% with targeted tests by @cvanelteren in #636
- Docs: cache jupytext conversion and restore incremental html by @cvanelteren in #603
- Improve gallery widget and thumbnail backgrounds by @cvanelteren in #644
- Support custom labels in sizelegend by @cvanelteren in #629
- fix: Refresh outdated contributor setup instructions by @JiwaniZakir in #646
- Refresh constructor registries after ticker reload by @cvanelteren in #645
- Honor patch linewidth rc for edgefix by @cvanelteren in #649
- Add typing block for inspection by @cvanelteren in #659
- Fix issue where single object returns object itself by @cvanelteren in #666
New Contributors
- @JiwaniZakir made their first contribution in #646
Full Changelog: v2.1.3...v2.1.5