| For those unfamiliar, ProPlot was widely loved for enabling publication-quality graphics with minimal effort. UltraPlot continues that mission with active development, updated compatibility, and a focus on simplicity. Why UltraPlot? Key improvements over vanilla matplotlib: - Effortless subplot management: build complex multi-panel layouts in one line
- GeoAxes support included out of the box
- Smarter aesthetics: beautiful colormaps, fonts, and styles without extra code
- Intuitive syntax: less boilerplate, more plotting
- Seamless compatibility: everything you know from matplotlib still applies
Instead of wrestling with subplot positioning and styling, you can write:```
import ultraplot as uplt layout = [[0, 1, 2], [3, 3, 4]] fig, axs = uplt.subplots(layout) axs[0].plot(x, y1, label="Data 1") axs[1].plot(x, y2, label="Data 2") axs.format(xlabel="Hello",
ylabel="Hacker news",
abc="[A]") # format applies to all axes
fig.legend() ``` ...and get a clean, professional-looking plot in seconds. Get Started: - GitHub: https://github.com/Ultraplot/ultraplot - Docs: https://ultraplot.readthedocs.io/en/latest/ Try it out and let us know what you think — contributions and feedback are very welcome! |
| |
| ▲ | zahlman 2 days ago | parent | next [-] | | > Instead of wrestling with subplot positioning and styling, you can write: This would be more convincing if you showed the equivalent Matplotlib code and demonstrated that any improvements are not just a result of default settings being a closer match for what the example tries to do. The code shown here looks more or less like what I'd expect a Matplotlib hello-world to look like. | | |
| ▲ | cvanelteren 2 days ago | parent [-] | | You are right. I was doubting whether to make a more complicated example -- but formatting is poor in text boxes. Let me give you a more complex one. Let's say we want a 3-column plot: colormesh, polar, and geo plot. UltraPlot: import ultraplot as uplt, numpy as np
fig, ax = uplt.subplots(
ncols=3, share=0, proj="cart polar merc".split(), journal="nat2"
)
ax[0].pcolormesh(
np.random.rand(10, 10), cmap="viko", colorbar="r",
colorbar_kw=dict(title="some interesting colors")
)
angles, radii = np.random.rand(100) * 360, np.random.rand(100)
ax[1].scatter(angles, radii, c=radii, cmap="spectral_r")
x, y = np.meshgrid(np.linspace(-30, 30, 100), np.linspace(-60, 60, 100))
z = np.exp(-(x*2 + y*2) / 100)
ax[2].pcolormesh(x, y, z, cmap="Fire")
ax[2].format(landcolor="green", land=True, grid=True, lonlabels=True, latlabels=True)
ax.format(abc="[A]")
fig.show()
Matplotlib equivalent: import matplotlib.pyplot as plt, numpy as np, cartopy.crs as ccrs
fig = plt.figure(figsize=(15, 5))
ax0 = fig.add_subplot(1, 3, 1)
pcm = ax0.pcolormesh(np.random.rand(10, 10), cmap="viridis")
cbar = plt.colorbar(pcm, ax=ax0)
cbar.set_label("some interesting colors")
cbar.ax.yaxis.label.set_color("r")
ax1 = fig.add_subplot(1, 3, 2, projection="polar")
angles = np.random.rand(100) * 2 * np.pi
radii = np.random.rand(100)
sc = ax1.scatter(angles, radii, c=radii, cmap="Spectral_r")
ax2 = fig.add_subplot(1, 3, 3, projection=ccrs.Mercator())
x, y = np.meshgrid(np.linspace(-30, 30, 100), np.linspace(-60, 60, 100))
z = np.exp(-(x*2 + y*2) / 100)
pcm2 = ax2.pcolormesh(x, y, z, cmap="magma", transform=ccrs.PlateCarree())
ax2.coastlines()
ax2.gridlines(draw_labels=True)
ax2.set_extent([-30, 30, -60, 60], crs=ccrs.PlateCarree())
import cartopy.feature as cfeature
ax2.add_feature(cfeature.LAND, facecolor="green")
for i, ax in enumerate([ax0, ax1, ax2]):
ax.set_title(f"[{chr(65+i)}]")
plt.tight_layout()
plt.show()
The aim isn't to replace matplotlib but make publication-ready plots with fewer keystrokes and better defaults. We also bundle plot types not available in matplotlib like graph plotting, lollipop charts, heatmaps etc. | | |
| ▲ | zahlman 2 days ago | parent [-] | | > You are right. I was doubting to make a more complicated example -- but formatting is poor on txt boxes. I see now that you have an example in the README. I think it would be better still in the README, but as plain text rather than rendered into an SVG. |
|
| |
| ▲ | quietbritishjim 2 days ago | parent | prev [-] | | Interesting, thanks. A few questions from a newbie: * I hadn't heard of ProPlot before. I take it that it's no longer maintained? Is there an announcement, or is it just obvious from commits drying up (like with PIL which was forked into Pillow)? * Is this a (friendly) fork (again, as with PIL/Pillow), or a reimplementation (in which case are there big differences or does it aim to match)? * I hadn't of GeoAxes either and that looks pretty useful. The top web search results for that term are ProPlot and Cartopy. Is the Cartopy implementation related at all? Is this a bundling of that, or a similar reimplementation, or something fairly different? | | |
| ▲ | cvanelteren a day ago | parent | next [-] | | Thanks for your questions. - ProPlot appears to be unmaintained - I initially tried to push changes to make it compatible with matplotlib 3.9+ around mid-2024, but after repeatedly trying to contact the original owner through official and unofficial channels with no response, we decided to fork by the end of 2024. I had grown really fond of ProPlot and wanted to keep it alive.
- This is currently a friendly fork, not a reimplementation. We're carrying on the torch that ProPlot set out with, adding features along the way and refactoring when necessary.
- We implement a custom GeoAxes that allows for basemap and/or Cartopy as a backend. The GeoAxes object behaves similar to a normal axis, allowing direct plotting and manipulation without the user having to worry about projections.
| |
| ▲ | quietbritishjim 2 days ago | parent | prev [-] | | To answer my own questions: * Yes it seems ProPlot stagnated and no longer works with latest matplotlib versions. UltraPlot is a fork that fixes that: https://github.com/proplot-dev/proplot/pull/459 * Yes, the documentation says that GeoAxes is from Cartopy. (Also, typo: the project description says "succint" rather than "succinct".) |
|
|