Skip to content
Projects

Advanced plotext

Download notebookView on GitHubRun when the site was built.

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 patches
import numpy as np
from maxplotlib import Canvas

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 C

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 6

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.0

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.txt

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.0

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.