Skip to content

Subfigures and Grid Layouts

Arrange multiple plots side-by-side or in grid layouts using subfigure_axis() and add_subfigure().

import math
from tikzfigure import TikzFigure

Create horizontally arranged plots with subfigure_axis():

fig = TikzFigure()
ax1 = fig.subfigure_axis(
xlabel="x", ylabel="y", xlim=(0, 360), ylim=(-1.5, 1.5), grid=True, width=0.45
)
ax1.add_plot(func="sin(x)", label="sin(x)", color="red", line_width="1.5pt")
ax1.set_legend(position="north east")
ax2 = fig.subfigure_axis(
xlabel="x", ylabel="y", xlim=(0, 360), ylim=(-1.5, 1.5), grid=True, width=0.45
)
ax2.add_plot(func="cos(x)", label="cos(x)", color="blue", line_width="1.5pt")
ax2.set_legend(position="north east")
fig.show()

Show Tikz code
print(fig)
\begin{tikzpicture}
\begin{groupplot}[group style={group size=2 by 1, horizontal sep=1.5cm}]
\nextgroupplot[domain=0:360, xlabel=x, ylabel=y, xmin=0, xmax=360, ymin=-1.5, ymax=1.5, grid=true, legend pos=north east]
\addplot[color=red, line width=1.5pt] {sin(x)};
\legend{sin(x)}
\nextgroupplot[domain=0:360, xlabel=x, ylabel=y, xmin=0, xmax=360, ymin=-1.5, ymax=1.5, grid=true, legend pos=north east]
\addplot[color=blue, line width=1.5pt] {cos(x)};
\legend{cos(x)}
\end{groupplot}
\end{tikzpicture}

Call subfigure_axis() multiple times to add more. Use width (0.0-1.0) to control sizing (typically 0.3-0.45 for 2-3 plots).

Specify rows and cols when creating the figure for multi-row layouts:

fig = TikzFigure(rows=2, cols=2)
ax1 = fig.subfigure_axis(xlabel="x", ylabel="y", width=0.45)
ax1.add_plot([0, 1], [0, 1], label="linear")
ax1.set_legend()
ax2 = fig.subfigure_axis(xlabel="x", ylabel="y", width=0.45)
ax2.add_plot([0, 1], [1, 0], label="inverse")
ax2.set_legend()
ax3 = fig.subfigure_axis(xlabel="x", ylabel="y", width=0.45)
ax3.add_plot([0, 1], [0, 2], label="double")
ax3.set_legend()
# Bottom-right left empty (partial grids are OK)
fig.show()

Show Tikz code
print(fig)
\begin{tikzpicture}
\begin{groupplot}[group style={group size=2 by 2, horizontal sep=1.5cm, vertical sep=2cm}]
\nextgroupplot[xlabel=x, ylabel=y, grid=true, legend pos=north east]
\addplot[] coordinates {(0,0) (1,1)};
\legend{linear}
\nextgroupplot[xlabel=x, ylabel=y, grid=true, legend pos=north east]
\addplot[] coordinates {(0,1) (1,0)};
\legend{inverse}
\nextgroupplot[xlabel=x, ylabel=y, grid=true, legend pos=north east]
\addplot[] coordinates {(0,0) (1,2)};
\legend{double}
\end{groupplot}
\end{tikzpicture}

Axes fill left-to-right, top-to-bottom automatically.

Leave some grid cells empty by not filling all positions:

fig = TikzFigure(rows=2, cols=3)
ax1 = fig.subfigure_axis(xlabel="Linear", ylabel="$y$", width=0.3)
ax1.add_plot([0, 1], [0, 1])
ax2 = fig.subfigure_axis(xlabel="Quadratic", ylabel="$y$", width=0.3)
ax2.add_plot([0, 1], [0, 1], plot_style="dashed")
ax3 = fig.subfigure_axis(xlabel="Cubic", ylabel="$y$", width=0.3)
ax3.add_plot([0, 1], [0, 1], plot_style="dotted")
ax4 = fig.subfigure_axis(xlabel="Square Root", ylabel="$y$", width=0.3)
x_vals = [0, 0.5, 1]
y_vals = [x**0.5 for x in x_vals]
ax4.add_plot(x_vals, y_vals)
# Bottom-right 2 cells are empty
fig.show()

Show Tikz code
print(fig)
\begin{tikzpicture}
\begin{groupplot}[group style={group size=3 by 2, horizontal sep=1.5cm, vertical sep=2cm}]
\nextgroupplot[xlabel=Linear, ylabel=$y$, grid=true]
\addplot[] coordinates {(0,0) (1,1)};
\nextgroupplot[xlabel=Quadratic, ylabel=$y$, grid=true]
\addplot[plot style=dashed] coordinates {(0,0) (1,1)};
\nextgroupplot[xlabel=Cubic, ylabel=$y$, grid=true]
\addplot[plot style=dotted] coordinates {(0,0) (1,1)};
\nextgroupplot[xlabel=Square Root, ylabel=$y$, grid=true]
\addplot[] coordinates {(0,0.0) (0.5,0.7071067811865476) (1,1.0)};
\end{groupplot}
\end{tikzpicture}

A practical 2x2 comparison:

fig = TikzFigure(rows=2, cols=2)
# Linear
ax1 = fig.subfigure_axis(xlabel="Time", ylabel="Value", width=0.45)
ax1.add_plot([0, 1, 2, 3, 4], [0, 2, 4, 6, 8], label="Linear", marker="*")
ax1.set_legend()
# Exponential
ax2 = fig.subfigure_axis(xlabel="Time", ylabel="Value", width=0.45)
ax2.add_plot([0, 1, 2, 3, 4], [1, 2, 4, 8, 16], label="Exponential", marker="o")
ax2.set_legend()
# Sine wave
ax3 = fig.subfigure_axis(xlabel="Time", ylabel="Amplitude", width=0.45)
x = [i * 0.2 for i in range(26)]
ax3.add_plot(x, [math.sin(xi) for xi in x], label="Sine")
ax3.set_legend()
# All together
ax4 = fig.subfigure_axis(xlabel="Time", ylabel="Value", width=0.45)
ax4.add_plot([0, 1, 2, 3, 4], [0, 2, 4, 6, 8], label="Linear")
ax4.add_plot([0, 1, 2, 3], [1, 2, 4, 8], label="Exponential")
ax4.set_legend()
fig.show()

Show Tikz code
print(fig)
\begin{tikzpicture}
\begin{groupplot}[group style={group size=2 by 2, horizontal sep=1.5cm, vertical sep=2cm}]
\nextgroupplot[xlabel=Time, ylabel=Value, grid=true, legend pos=north east]
\addplot[marker=*] coordinates {(0,0) (1,2) (2,4) (3,6) (4,8)};
\legend{Linear}
\nextgroupplot[xlabel=Time, ylabel=Value, grid=true, legend pos=north east]
\addplot[marker=o] coordinates {(0,1) (1,2) (2,4) (3,8) (4,16)};
\legend{Exponential}
\nextgroupplot[xlabel=Time, ylabel=Amplitude, grid=true, legend pos=north east]
\addplot[] coordinates {(0.0,0.0) (0.2,0.19866933079506122) (0.4,0.3894183423086505) (0.6000000000000001,0.5646424733950355) (0.8,0.7173560908995228) (1.0,0.8414709848078965) (1.2000000000000002,0.9320390859672264) (1.4000000000000001,0.9854497299884603) (1.6,0.9995736030415051) (1.8,0.9738476308781951) (2.0,0.9092974268256817) (2.2,0.8084964038195901) (2.4000000000000004,0.6754631805511506) (2.6,0.5155013718214642) (2.8000000000000003,0.33498815015590466) (3.0,0.1411200080598672) (3.2,-0.058374143427580086) (3.4000000000000004,-0.25554110202683167) (3.6,-0.44252044329485246) (3.8000000000000003,-0.6118578909427193) (4.0,-0.7568024953079282) (4.2,-0.8715757724135882) (4.4,-0.951602073889516) (4.6000000000000005,-0.9936910036334645) (4.800000000000001,-0.9961646088358406) (5.0,-0.9589242746631385)};
\legend{Sine}
\nextgroupplot[xlabel=Time, ylabel=Value, grid=true, legend pos=north east]
\addplot[] coordinates {(0,0) (1,2) (2,4) (3,6) (4,8)};
\addplot[] coordinates {(0,1) (1,2) (2,4) (3,8)};
\legend{Linear, Exponential}
\end{groupplot}
\end{tikzpicture}

Use add_subfigure() to place bare TikZ diagrams alongside axis-based plots. The returned object supports add_node(), draw(), and all TikZ API methods:

fig = TikzFigure(rows=1, cols=2)
# Left: axis with plot
ax = fig.subfigure_axis(xlabel="Iteration", ylabel="Error", width=0.4)
ax.add_plot(
[1, 2, 3, 4, 5], [0.8, 0.4, 0.2, 0.1, 0.05], marker="o", label="Convergence"
)
ax.set_legend()
# Right: algorithm flowchart
flowchart = fig.add_subfigure(width=0.4, height=6)
start = flowchart.add_node(
1.5, 3.5, label="start", content="Start", shape="circle", fill="green!40"
)
process = flowchart.add_node(
1.5, 2, label="process", content="Iterate", shape="rectangle", fill="yellow!40"
)
end = flowchart.add_node(
1.5, 0.5, label="end", content="Done", shape="circle", fill="red!40"
)
flowchart.draw([start, process], arrows="->")
flowchart.draw([process, end], arrows="->")
fig.show()

Show Tikz code
print(fig)
\begin{tikzpicture}
\begin{scope}[xshift=0.0cm, yshift=0.0cm]
\begin{axis}[width=5.6cm, xlabel=Iteration, ylabel=Error, grid=true, legend pos=north east]
\addplot[marker=o] coordinates {(1,0.8) (2,0.4) (3,0.2) (4,0.1) (5,0.05)};
\legend{Convergence}
\end{axis}
\end{scope}
\begin{scope}[xshift=7.6cm, yshift=0.0cm]
\node[shape=circle, fill=green!40] (start) at ({1.5}, {3.5}) {Start};
\node[shape=rectangle, fill=yellow!40] (process) at ({1.5}, {2}) {Iterate};
\node[shape=circle, fill=red!40] (end) at ({1.5}, {0.5}) {Done};
\draw[arrows=->] (start) to (process);
\draw[arrows=->] (process) to (end);
\end{scope}
\end{tikzpicture}

See Mixed Subfigures for more detailed examples.