Subplots and Multi-Panel Figures
Why Multi-Panel Figures Matter
Journal papers typically allow 6-8 figures. Packing multiple related plots into a single figure β BER on the left, constellation on the right, spectrum below β communicates more per figure. GridSpec and insets give you pixel-level control over panel placement.
Definition: plt.subplots β Quick Regular Grids
plt.subplots β Quick Regular Grids
plt.subplots(nrows, ncols, **kwargs) creates a Figure with a
regular grid of Axes:
fig, axes = plt.subplots(2, 3, figsize=(12, 6),
sharex=True, sharey='row')
axes[0, 0].plot(x, y) # top-left panel
axes[1, 2].scatter(a, b) # bottom-right panel
sharex / sharey link axes for consistent scales across panels.
When nrows=ncols=1, axes is a single Axes, not an array.
Use fig, ax = plt.subplots() in that case.
Definition: GridSpec β Flexible Panel Layouts
GridSpec β Flexible Panel Layouts
matplotlib.gridspec.GridSpec creates layouts where panels span
multiple rows or columns:
from matplotlib.gridspec import GridSpec
fig = plt.figure(figsize=(10, 6))
gs = GridSpec(2, 3, figure=fig, hspace=0.3, wspace=0.3)
ax_big = fig.add_subplot(gs[0, :]) # top row, full width
ax_left = fig.add_subplot(gs[1, 0:2]) # bottom left 2/3
ax_right = fig.add_subplot(gs[1, 2]) # bottom right 1/3
Definition: Inset Axes for Zoom and Detail Views
Inset Axes for Zoom and Detail Views
ax.inset_axes([x, y, width, height]) creates a small Axes inside
an existing one, useful for zoom panels:
axins = ax.inset_axes([0.55, 0.55, 0.4, 0.4])
axins.plot(x_zoom, y_zoom)
ax.indicate_inset_zoom(axins, edgecolor='red')
Coordinates are in axes-relative units: [0, 0] is bottom-left,
[1, 1] is top-right.
Theorem: Constrained Layout vs. Tight Layout
fig.set_layout_engine('constrained') (or layout='constrained')
uses a constraint solver to prevent overlapping labels and titles.
It handles colorbars, legends, and suptitles better than the older
fig.tight_layout().
fig, axes = plt.subplots(2, 2, layout='constrained')
Use constrained for all new code. Fall back to tight_layout()
only when constrained layout fails with certain artist combinations.
tight_layout adjusts subplot params heuristically;
constrained solves a proper constraint system.
Example: Publication-Quality Multi-Panel with GridSpec
Create a figure with a wide spectrum plot on top and two smaller panels (time domain and constellation) below.
Layout
from matplotlib.gridspec import GridSpec
fig = plt.figure(figsize=(10, 7), layout='constrained')
gs = GridSpec(2, 2, figure=fig, height_ratios=[1, 1.2])
ax_spec = fig.add_subplot(gs[0, :]) # full-width top
ax_time = fig.add_subplot(gs[1, 0]) # bottom-left
ax_const = fig.add_subplot(gs[1, 1]) # bottom-right
Panel labels
for label, ax in zip(['(a)', '(b)', '(c)'],
[ax_spec, ax_time, ax_const]):
ax.text(-0.08, 1.05, label, transform=ax.transAxes,
fontsize=14, fontweight='bold', va='top')
Example: Inset Zoom on a BER Curve
Add a zoom panel showing the BER curve near the waterfall region (10-14 dB) within the main plot.
Implementation
fig, ax = plt.subplots(figsize=(7, 5))
ax.semilogy(snr_db, ber, 'o-', color='#2563EB')
ax.set(xlabel=r' (dB)', ylabel='BER')
axins = ax.inset_axes([0.5, 0.5, 0.45, 0.45])
axins.semilogy(snr_db, ber, 'o-', color='#2563EB')
axins.set_xlim(10, 14)
axins.set_ylim(1e-5, 1e-3)
axins.grid(True, alpha=0.3)
ax.indicate_inset_zoom(axins, edgecolor='#DC2626', lw=2)
Subplot Layout Explorer
Experiment with different numbers of rows and columns and see how constrained layout adjusts spacing automatically.
Parameters
Subplot Creation Methods
| Method | Use Case | Spanning Panels? | Ease |
|---|---|---|---|
| plt.subplots(n, m) | Regular grids | No | Simplest |
| GridSpec | Irregular layouts, spanning | Yes | Moderate |
| subplot_mosaic | Named layouts via ASCII art | Yes | Moderate |
| inset_axes | Zoom panels, mini-plots | N/A | Easy |
| add_axes([l,b,w,h]) | Exact pixel placement | N/A | Manual |
GridSpec
A Matplotlib class for creating flexible subplot layouts where panels can span multiple rows or columns.
Inset Axes
A small Axes embedded inside a larger one, typically used for zoom views or mini-plots.