Skip to content
Projects

Subplot spacing

Download notebookView on GitHubRun when the site was built.

This tutorial shows how to build NxM subplot grids with the matplotlib backend and control the distance between plots using wspace=... and hspace=....

It includes both:

  • line plots
  • color plots (add_imshow)

and prints measured subplot gaps so you can verify spacing changes numerically.

import matplotlib.pyplot as plt
import numpy as np
from maxplotlib import Canvas
def measure_gaps(axes):
"""Measure one representative horizontal and vertical subplot gap."""
horizontal_gap = axes[0, 1].get_position().x0 - axes[0, 0].get_position().x1
vertical_gap = axes[0, 0].get_position().y0 - axes[1, 0].get_position().y1
return horizontal_gap, vertical_gap
x = np.linspace(0, 2 * np.pi, 200)
tight_canvas, tight_axes = Canvas.subplots(
nrows=2,
ncols=3,
width="14cm",
ratio=0.65,
wspace=0.05,
hspace=0.08,
)
for i, row in enumerate(tight_axes):
for j, ax in enumerate(row):
tight_canvas.plot(
x, np.sin((i + 1) * (j + 1) * x), label=f"sin({(i + 1) * (j + 1)}x)"
)
tight_canvas.set_title(f"line {i},{j}")
tight_fig, tight_m_axes = tight_canvas.render(backend="matplotlib")
tight_fig.suptitle("Line plots - tight spacing")
tight_h, tight_v = measure_gaps(tight_m_axes)
print(f"tight line gaps: h={tight_h:.4f}, v={tight_v:.4f}")
loose_canvas, loose_axes = Canvas.subplots(
nrows=2,
ncols=3,
width="14cm",
ratio=0.65,
wspace=0.45,
hspace=0.45,
)
for i, row in enumerate(loose_axes):
for j, ax in enumerate(row):
loose_canvas.plot(
x, np.sin((i + 1) * (j + 1) * x), label=f"sin({(i + 1) * (j + 1)}x)"
)
loose_canvas.set_title(f"line {i},{j}")
loose_fig, loose_m_axes = loose_canvas.render(backend="matplotlib")
loose_fig.suptitle("Line plots - loose spacing")
loose_h, loose_v = measure_gaps(loose_m_axes)
print(f"loose line gaps: h={loose_h:.4f}, v={loose_v:.4f}")
assert loose_h > tight_h
assert loose_v > tight_v
tight line gaps: h=0.0125, v=0.0296
loose line gaps: h=0.0894, v=0.1414
Notebook output Notebook output

2 · NxM color plots (imshow) with spacing control

Section titled “2 · NxM color plots (imshow) with spacing control”
base = np.arange(100).reshape(10, 10)
tight_canvas, tight_axes = Canvas.subplots(
nrows=2,
ncols=3,
width="14cm",
ratio=0.75,
wspace=0.05,
hspace=0.08,
)
idx = 0
for row in tight_axes:
for ax in row:
tight_canvas.imshow(base + idx, cmap="viridis")
tight_canvas.set_title(f"heatmap {idx}")
idx += 1
tight_fig, tight_m_axes = tight_canvas.render(backend="matplotlib")
tight_fig.suptitle("Color plots - tight spacing")
tight_h, tight_v = measure_gaps(tight_m_axes)
print(f"tight color gaps: h={tight_h:.4f}, v={tight_v:.4f}")
loose_canvas, loose_axes = Canvas.subplots(
nrows=2,
ncols=3,
width="14cm",
ratio=0.75,
wspace=0.45,
hspace=0.45,
)
idx = 0
for row in loose_axes:
for ax in row:
loose_canvas.imshow(base + idx, cmap="viridis")
loose_canvas.set_title(f"heatmap {idx}")
idx += 1
loose_fig, loose_m_axes = loose_canvas.render(backend="matplotlib")
loose_fig.suptitle("Color plots - loose spacing")
loose_h, loose_v = measure_gaps(loose_m_axes)
print(f"loose color gaps: h={loose_h:.4f}, v={loose_v:.4f}")
assert loose_h > tight_h
assert loose_v > tight_v
plt.show()
tight color gaps: h=0.0125, v=0.0480
loose color gaps: h=0.0894, v=0.1661
Notebook output Notebook output

The spacing measurements above are Matplotlib-specific. You can still preview the same canvas with the Plotly backend (layout/spacing will differ):

# Reuse the last canvas created above
loose_canvas.show(backend="plotly")