Skip to content
Projects

TikzFigure subplots

Download notebookView on GitHubRun when the site was built.

This tutorial demonstrates how to create subplots using the tikzfigure backend: side by side, stacked, or in a grid.

The simplest use case: two plots side by side.

import numpy as np
from maxplotlib import Canvas
%load_ext autoreload
%autoreload 2
# Create a 1×2 canvas with custom width
x = np.linspace(0, 2 * np.pi, 200)
canvas, (ax1, ax2) = Canvas.subplots(ncols=2, width="10cm", ratio=0.3)
# Left subplot: sine wave
ax1.plot(x, np.sin(x), color="royalblue", label="sin(x)", linewidth=1.5)
ax1.set_title("sin(x)")
ax1.set_xlabel("x")
ax1.set_ylabel("amplitude")
# Right subplot: cosine wave
ax2.plot(x, np.cos(x), color="tomato", label="cos(x)", linewidth=1.5)
ax2.set_title("cos(x)")
ax2.set_xlabel("x")
# Set overall title
canvas.suptitle("1 × 2 Layout: Trigonometric Functions")
# Render with tikzfigure backend
result = canvas.show(backend="tikzfigure")
2026-10-30 07:52:05.668671936 [W:onnxruntime:Default, device_discovery.cc:95 GetPciBusId] Skipping pci_bus_id for PCI path at "/sys/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0004:00/MSFT1000:00/5620e0c7-8062-4dce-aeb7-520c7ef76171" because filename "5620e0c7-8062-4dce-aeb7-520c7ef76171" did not match expected pattern of [0-9a-f]+:[0-9a-f]+:[0-9a-f]+[.][0-9a-f]+
/home/runner/work/maxplotlib/maxplotlib/.venv/lib/python3.12/site-packages/fitz/__init__.py:17: FutureWarning: The `fitz` API is deprecated and will be removed in future. Use `import pymupdf` instead.
warnings.warn(
Notebook output

Inspecting the generated subplot dimensions

Section titled “Inspecting the generated subplot dimensions”

Every subplot is a pgfplots axis with the position and size Matplotlib gives it: at= is its lower left corner in the figure, width= and height= its box (scale only axis). Printing the \begin{axis}[...] lines makes that explicit.

tikz = canvas.render(backend="tikzfigure")
subplot_code = tikz.generate_tikz()
for line in subplot_code.splitlines():
if "\\begin{axis}" in line:
options = line.strip()
print(
[
part
for part in options.split(", ")
if part.startswith(("at=", "width=", "height="))
]
)
# With width="10cm" and ratio=0.3, the two axes share the figure width.
['at={(0.4921in,0.1299in)}', 'width=1.4669in', 'height=0.9094in]']
['at={(2.0764in,0.1299in)}', 'width=1.4669in', 'height=0.9094in]']

You can create layouts with more than 2 subplots.

# Create a 1×3 canvas
canvas, axes = Canvas.subplots(ncols=3, width="12cm", ratio=0.35)
# Three different functions
x = np.linspace(0, 2 * np.pi, 100)
axes[0].plot(x, np.sin(x), color="blue")
axes[0].set_title("sin(x)")
axes[0].set_xlabel("x")
axes[1].plot(x, np.cos(x), color="red")
axes[1].set_title("cos(x)")
axes[1].set_xlabel("x")
axes[2].plot(x, np.tan(x), color="darkgreen")
axes[2].set_title("tan(x)")
axes[2].set_xlabel("x")
axes[2].set_ylim(-5, 5) # Limit y-range for tan
canvas.suptitle("1 × 3 Layout: Three Trigonometric Functions")
result = canvas.show(backend="tikzfigure")
print(result)
Notebook output
None

Any nrows × ncols layout converts, with shared axes and hidden tick labels as in Matplotlib.

canvas, axes = Canvas.subplots(nrows=2, ncols=2, width="12cm", ratio=0.6)
x = np.linspace(0, 2 * np.pi, 100)
for index, ax in enumerate(np.ravel(axes)):
ax.plot(x, np.sin((index + 1) * x), color=f"C{index}")
ax.set_title(f"sin({index + 1}x)")
canvas.show(backend="tikzfigure")
Notebook output
  • Any layout converts: rows, columns and grids, with shared and twin axes, as Matplotlib lays them out
  • Each subplot’s title becomes a pgfplots title= entry in the generated LaTeX output
  • Meshes, images and colorbars are included as images; see Tutorial 07 for what becomes what