Description
Problem
I find the syntax of pyplot a bit difficult to remember, and I have been thinking for a while about a way of making it friendlier taking advantage of Python tools. After some years of on/off iteration, I converged to what I think is a really nice interface. In very brief, I use:
- A dataclass for all the setup (figure size, labels, ticks, grid, whether to save/show the figure...)
- A context manager to plot, and then do what I call "postprocessing" (color lines, create legend, adjust boundaries, show figure, save figure to a file...) automatically when the plot goes out of scope.
This is a (rather complete) example script, and the figure it generates:
import nastro.graphics as ng
import numpy as np
if __name__ == "__main__":
# Generate data
x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(x)
z = np.cos(x)
error = np.abs(np.random.normal(0.0, 0.1, x.shape))
xbar = np.arange(8)
ybar = np.random.normal(5, 2, 8)
gen = np.random.default_rng(1234797)
# Figure configuration
figure_setup = ng.PlotSetup(
canvas_size=(12, 7),
title="A simple figure with different types of subplots",
save=True,
dir=".",
name="plots.png",
show=False,
)
a_setup = ng.PlotSetup(ylabel="left", rlabel="right", plabel="parasite")
c_setup = ng.PlotSetup(grid=False)
d_setup = ng.PlotSetup(ylabel="sin(x)", rlabel="cos(x)")
with ng.Mosaic("ab;cd;ef", figure_setup) as fig:
with fig.subplot(a_setup, ng.ParasiteAxis) as a:
a.line(x, x, fmt=".-", markersize=2, label="x")
a.line(x, x**2, fmt="--", axis="right", label="x^2")
a.line(x, x**3, axis="parasite", label="x^3")
with fig.subplot(generator=ng.SingleAxis) as b:
b.line(x, y, label="sin")
b.line(x, z, label="cos")
b.boundary(0.5, reference="sin")
b.boundary(0.25, reference="sin", alpha=0.3)
with fig.subplot(c_setup) as c:
c.bar(xbar, ybar)
with fig.subplot(d_setup, ng.DoubleAxis) as d:
d.errorbar(x, y, np.abs(gen.normal(0.0, 0.1, x.shape)))
d.errorbar(
x, z, np.abs(gen.normal(0.0, 0.1, x.shape)), axis="right"
)
d.line(x, 0.8 * y)
with fig.subplot(generator=ng.DoubleAxis) as e:
e.step(x, y, fmt=".-")
e.step(x, z, axis="right")
with fig.subplot() as f:
f.barh(xbar[:4], ybar[:4])
This interface was born as a submodule of a library I was writing for astrodynamics, but I have been using it for general plotting for about a year now, and it seems flexible and robust. I don't think I have the technical knowledge, or the time to add this to matplotlib, but maybe someone here does.
All my source code is open, and I'd be happy to discuss the details of my implementation, or to improve the description of this issue if you are interested :)
Proposed solution
No response