Advanced plotext
This tutorial focuses on practical terminal workflows that are easy to miss when moving from Matplotlib to the Plotext backend: layer-by-layer output, subplot dashboards, terminal-safe files, and backend limitations.
from pathlib import Path
import matplotlib.patches as patchesimport numpy as np
from maxplotlib import Canvas1. Build a terminal dashboard
Section titled “1. Build a terminal dashboard”Canvas.subplots() works with Plotext too. Keep subplot titles short enough for a terminal and render with keep_colors=False when the output will be logged or tested.
canvas, axes = Canvas.subplots(nrows=1, ncols=2)x = np.linspace(0, 2 * np.pi, 80)
axes[0].plot(x, np.sin(x), label="signal")axes[0].set_title("Signal")axes[0].set_grid(True)axes[0].set_legend(True)
axes[1].bar([0, 1, 2], [4, 7, 3], label="count")axes[1].set_xticks([0, 1, 2], labels=["A", "B", "C"])axes[1].set_title("Counts")
print(canvas.render(backend="plotext").build(keep_colors=False)) Signal Counts ┌┬────┬─────┬────┬────┬─────┬────┬┐ ┌─────┬───────────┬───────────┬─────┐ 1.00┼┌──────────┐────┼────┼─────┼────┼┤7.0┼┌─────────┐─███████████──────┼─────┤ ││ │ │ │signal ││ ││ │ ███████████ │ │ ││ ▚ signal │▖ │ │ │ ││ ││ █ count │ ███████████ │ │ ││ │▝▖ │ │ │ ││ ││ │ ███████████ │ │ 0.50┼└──────────┘─▚──┼────┼─────┼────┼┤5.2┼└─────────┘─███████████──────┼─────┤ ││ ▐ │ │ ▘ │ │ │ ││ │ │ ███████████ │ │ ││▗▘ │ │ ▝▖│ │ │ ││ │ │ ███████████ │ │ ││▖ │ │ ▚│ │ │ ││ │███████████ ███████████ │ │ │▝ │ │ ▖ │ │ ││ │███████████ ███████████ │ │ 0.00┼▝────┼─────┼────▝────┼─────┼────▌┤3.5┼███████████─███████████──────┼─────┤ ││ │ │ │▚ │ │ ▝││ │███████████ ███████████ ███████████│ ││ │ │ │▝▖ │ │ ▗▘││ │███████████ ███████████ ███████████│ ││ │ │ │ ▗ │ │ ▌ ││ │███████████ ███████████ ███████████│-0.50┼┼────┼─────┼────┼──▚─┼─────┼─▝──┼┤1.8┼███████████─███████████─███████████┤ ││ │ │ │ ▝▖│ │▗▘ ││ │███████████ ███████████ ███████████│ ││ │ │ │ ▝▖ ▗▌ ││ │███████████ ███████████ ███████████│ ││ │ │ │ ▝▖ ▄▘ ││ │███████████ ███████████ ███████████│-1.00┼┼────┼─────┼────┼────┼▝▀▀▀▘┼────┼┤0.0┼███████████─███████████─███████████┤ └┼────┼─────┼────┼────┼─────┼────┼┘ └─────┼───────────┼───────────┼─────┘ 0.0 1.0 2.1 3.1 4.2 5.2 6.3 A B C2. Add uncertainty and annotations
Section titled “2. Add uncertainty and annotations”Error bars accept scalar, symmetric-array, and Matplotlib’s two-row asymmetric-array forms. Reference lines, text, and annotations are rendered as terminal primitives.
x = np.arange(5)y = np.array([1.0, 1.8, 1.3, 2.5, 2.0])canvas, ax = Canvas.subplots()ax.errorbar( x, y, yerr=[[0.1] * 5, [0.25] * 5], label="observations",)ax.axhline(y.mean(), color="yellow")ax.annotate("peak", xy=(3, 2.5), xytext=(2, 2.8))ax.set_title("Measurements")ax.set_legend(True)
print(canvas.render(backend="plotext").build(keep_colors=False)) Measurements ┌──────────────────────────────────────────────────────────────────────────┐2.80┤┌────────────────┐ peak │ ││ │ observations │ ││ ┼ observations │ │ │ ││ │───────────────────┼────────────────── │2.31┤└────────────────┘ │ │ │ │ │ │ │ │ │ │ ─────────────────────────┼────────────────────────│ │ │ │ │1.81┼────────────┼─────────────────────────────────────────────────────────────┤ │ │ │ │ │ │ │ │ │1.32┤ ────────────┼───────────── │ ││ │ │ │┼ │ ││ │0.82┤│ │ └┬───────────┬───────────┬────────────┬───────────┬───────────┬───────────┬┘ 0 1 2 3 4 5 63. Render layers incrementally
Section titled “3. Render layers incrementally”Layers are useful for progress reports and debugging. Pass a list to render(..., layers=[...]), or use savefig(..., layer_by_layer=True) to write successive text files.
canvas, ax = Canvas.subplots()ax.plot(x, y, label="raw", layer=0)ax.plot(x, np.maximum.accumulate(y), label="running max", layer=1)ax.set_title("Layered diagnostics")ax.set_legend(True)
for selected_layers in ([0], [0, 1]): text = canvas.render(backend="plotext", layers=selected_layers).build( keep_colors=False ) print(f"--- layers={selected_layers} ---") print(text)--- layers=[0] --- Layered diagnostics ┌──────────────────────────────────────────────────────────────────────────┐2.50┤┌───────┐ ▖ │ ││ │ raw │ ││ ▚ raw │ │ ││ │ │2.12┤└───────┘ │ │ │ │ ▘│ │ │ │ ▝ │1.75┤ │ │ │ │ │ │ │1.38┤ │ │ ▘ │ │ │ │ │1.00┤▝ │ └┬───────────┬───────────┬────────────┬───────────┬───────────┬───────────┬┘ 0.0 0.7 1.3 2.0 2.7 3.3 4.0
--- layers=[0, 1] --- Layered diagnostics ┌──────────────────────────────────────────────────────────────────────────┐2.50┤┌───────────────┐ ▖ ▖│ ││ │ raw │ ││ ▚ raw │ │ ││ │ running max │2.12┤│ ▚ running max │ │ ││ │ │ │└───────────────┘ ▘│ │ │ │ ▝ ▘ │1.75┤ │ │ │ │ │ │ │1.38┤ │ │ ▘ │ │ │ │ │1.00┤▝ │ └┬───────────┬───────────┬────────────┬───────────┬───────────┬───────────┬┘ 0.0 0.7 1.3 2.0 2.7 3.3 4.04. Save terminal output
Section titled “4. Save terminal output”Plotext output is text, not an image. Saving without ANSI colors makes the file portable to CI logs, issue trackers, and plain-text artifacts.
output_path = Path("plotext-output.txt")figure = canvas.render(backend="plotext")figure.savefig(output_path, keep_colors=False)print(f"wrote {output_path}")wrote plotext-output.txt5. Matrix plots and patches
Section titled “5. Matrix plots and patches”Matrix data is displayed with Plotext’s heatmap primitive. Common Matplotlib patches are approximated by their polygon outline, which is useful for lightweight terminal diagnostics.
canvas, ax = Canvas.subplots()ax.add_imshow(np.arange(16).reshape(4, 4))ax.add_patch(patches.Rectangle((0.5, 0.5), 2, 2, fill=False, label="window"))ax.add_colorbar(label="intensity")ax.set_title("Matrix diagnostic")ax.set_legend(True)
print(canvas.render(backend="plotext").build(keep_colors=False)) Matrix diagnostic | intensity: 0..15 ┌───────────────────────────────────────────────────────────────────────────┐3.0┤┌──────────┐ █ █ █│ ││ │ window │ ││ ▚ window │ │ ││ │▝ ▘ │2.2┤└──────────┘ │ │ │ │█ █ █ █│ │ │ │ │1.5┤ │ │ │ │█ █ █ █│ │ │0.8┤ │ │ ▗ ▖ │ │ │ │ │0.0┤█ █ █ █│ └┬───────────┬────────────┬───────────┬───────────┬────────────┬───────────┬┘ 0.0 0.5 1.0 1.5 2.0 2.5 3.0Current limitations
Section titled “Current limitations”The backend intentionally raises NotImplementedError for plot types that do not have a faithful Plotext 6 equivalent, such as histograms, pie charts, stem plots, and secondary/twin axes. Use Matplotlib or Plotly for those cases.