Mundane plotting made easy.
plotez is a Python library that simplifies common matplotlib plotting tasks with an intuitive API. Create complex
plots
with minimal boilerplate code.
| Item | Status |
|---|---|
| Latest version | v0.4.0 |
| Python support | 3.10 · 3.11 · 3.12 |
| Test coverage | 85%+ |
| Type hints | PEP 561 compliant (py.typed) |
| Documentation | Read the Docs |
| Changelog | CHANGELOG |
| License | MIT |
- Simple API: Create complex plots with just a few lines of code
- Error Bar Plotting: Comprehensive error bar support with enhanced styling options
- Error Band Plotting: Shaded error band support via
plot_errorband,plot_errorband_relative, andErrorBandConfig - Histogram & Density Plotting:
plot_histandplot_densitywithHistogramConfig/hgc - Bar & Horizontal Bar Plotting:
plot_barandplot_barhwithBarPlotConfig, including per-bar styling via list-valued parameters - Dual-Axis Support: Easy creation of dual y-axis or dual x-axis plots
- Multi-Panel Layouts: Flexible subplot arrangements with automatic labeling
- File Integration: Direct plotting from CSV files
- Extensive Customization: Full control over plot appearance via parameter classes
- Opt-In Styling: Publication-ready style convention is off by default (importing plotez never
mutates your project's matplotlib rcParams); opt in via
plotez.enable_style()at runtime or thePLOTEZ_AUTO_STYLEenvironment variable at import time - Custom Exceptions: Domain-specific exceptions for clear, catchable error handling
- Early Input Validation: Clear
ShapeError,DataLengthError, andEmptyDataErrorfailures before matplotlib - Type Safety: Complete type hints for better IDE support and type checking (PEP 561 compliant)
- Well Tested: Comprehensive test suite with 85%+ coverage
pip install plotezgit clone https://github.com/syedalimohsinbukhari/plotez.git
cd plotez
pip install -e .pip install -e ".[dev]"import numpy as np
from plotez import plot_xy
x = np.linspace(0, 10, 100)
y = np.sin(x)
plot_xy(x, y)That's it. Three lines for a labeled plot.
import numpy as np
from plotez import ErrorPlotConfig, plot_errorbar
rng = np.random.default_rng(1234)
x = np.linspace(0, 10, 20)
y = np.sin(x)
y_err = 0.2 * rng.random(size=y.shape)
ep = ErrorPlotConfig(color="darkblue", marker="o", capsize=5, ecolor="red", markerfacecolor="lime")
plot_errorbar(x, y, y_err=y_err, errorbar_config=ep)Professional error bars in a few lines of config. ecolor sets the error bar colour independently from the line colour.
import numpy as np
from plotez import plot_xyy
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.exp(-x / 10)
plot_xyy(x, y1, y2, x_label="Time (s)", y1_label="Signal (V)", y2_label="Decay",
data_labels=["Oscillation", "Envelope"])Dual axes done right. No ax.twinx() gymnastics.
import numpy as np
from plotez import n_plotter
x_data = [np.linspace(0, 10, 100) for _ in range(4)]
y_data = [np.sin(x_data[0]), np.cos(x_data[1]),
np.tan(x_data[2] / 5), x_data[3] ** 2 / 100]
n_plotter(x_data, y_data, n_rows=2, n_cols=2)Four plots, one function call.
Use ErrorBandConfig and LinePlotConfig for explicit, IDE-friendly configuration:
import numpy as np
from plotez import ErrorBandConfig, LinePlotConfig, plot_errorband
x = np.linspace(0, 10, 50)
y = np.sin(x)
y_lower = y - 0.2
y_upper = y + 0.2
band_config = ErrorBandConfig(color="darkblue", alpha=0.25)
plot_config = LinePlotConfig(color="gold", linewidth=2, linestyle="--",
marker="o", markersize=5, markeredgecolor="k")
plot_errorband(x, y, y_lower, y_upper,
data_label="Measurement", band_config=band_config, line_config=plot_config)The same result using the ebc / lpc shorthand aliases — familiar matplotlib parameter names, no class imports
needed:
import numpy as np
from plotez import ebc, lpc, plot_errorband
x = np.linspace(0, 10, 50)
y = np.sin(x)
y_lower = y - 0.2
y_upper = y + 0.2
band_config = ebc(c="darkblue", alpha=0.25)
plot_config = lpc(c="gold", lw=2, ls="--", marker="o", ms=5, mec="k")
plot_errorband(x, y, y_lower, y_upper,
data_label="Measurement", band_config=band_config, line_config=plot_config)import numpy as np
from plotez import LinePlotConfig, plot_xyy
x = np.linspace(0, 10, 50)
y1, y2 = np.sin(x), np.cos(x)
config = LinePlotConfig(
linestyle=["--", "-."],
color=["crimson", "gold"],
marker=["o", "s"],
markersize=[8, 8],
markeredgecolor=["black", "black"],
_extra={"markevery": [5, 5]},
)
plot_xyy(x, y1, y2, plot_config=config)Config classes for when defaults aren't enough. Use _extra to pass any matplotlib parameter not covered by the
dataclass fields.
Use plot_hist with the hgc shorthand to configure and plot a histogram in one go.
Switch to plot_density to get normalised probability density instead of raw counts — everything else stays the same.
Both functions accept one 1D dataset per call.
import numpy as np
from plotez import hgc, plot_hist
rng = np.random.default_rng(42)
data = rng.normal(loc=0, scale=1, size=5000)
h_cfg = hgc(bins=40, color="steelblue", ec="white", alpha=0.8)
plot_hist(data, x_label="Value", y_label="Counts",
plot_title="Histogram of Normal Distribution",
data_label="Normal", hist_config=h_cfg)Swap plot_hist for plot_density to get the probability density on the y-axis.
plot_bar and plot_barh share a BarPlotConfig; pass a list for color, edgecolor, linewidth, alpha,
width, or hatch to style each bar individually.
import numpy as np
from plotez import BarPlotConfig, plot_bar
categories = ["A", "B", "C", "D", "E"]
values = np.array([23, 45, 12, 39, 28])
b_cfg = BarPlotConfig(color="steelblue", edgecolor="black", alpha=0.85)
plot_bar(categories, values, x_label="Category", y_label="Value", bar_config=b_cfg)Swap plot_bar for plot_barh to flip to horizontal bars — x_data stays the categories, y_data stays the bar
lengths.
plotez never changes your project's global matplotlib style just because you imported it. Call
plotez.enable_style() to apply its publication-ready convention (serif fonts, grid, tick geometry) at
runtime, and plotez.disable_style() to revert to matplotlib's own defaults — or set
PLOTEZ_AUTO_STYLE=1 in the environment before import plotez to apply it automatically.
import matplotlib.pyplot as plt
import numpy as np
import plotez
from plotez import plot_errorbar
rng = np.random.default_rng(7)
x = np.linspace(0, 10, 20)
y = np.sin(x)
y_err = 0.2 * rng.random(size=y.shape)
fig = plt.figure(figsize=(15, 4.5))
ax1 = fig.add_subplot(1, 3, 1)
plot_errorbar(x, y, y_err=y_err,
plot_title="Default (no plotez style)", axis=ax1)
plotez.enable_style()
ax2 = fig.add_subplot(1, 3, 2)
plot_errorbar(x, y, y_err=y_err,
plot_title="After enable_style()", axis=ax2)
plotez.disable_style()
ax3 = fig.add_subplot(1, 3, 3)
plot_errorbar(x, y, y_err=y_err,
plot_title="After disable_style()", axis=ax3)Set PLOTEZ_AUTO_STYLE=1 before import plotez to skip the explicit enable_style() call and apply the
convention globally for the process.
pytestpytest --cov=src/plotez --cov-report=htmlmypy src/plotezcd docs
make htmlContributions are welcome! Please feel free to submit a Pull Request.
MIT License – see LICENSE file for details.
- Syed Ali Mohsin Bukhari - ali.mohsin@ist.edu.pk









