Axes box aspect#

This demo shows how to set the aspect of an Axes box directly via set_box_aspect. The box aspect is the ratio between axes height and axes width in physical units, independent of the data limits. This is useful to e.g. produce a square plot, independent of the data it contains, or to have a usual plot with the same axes dimensions next to an image plot with fixed (data-)aspect.

The following lists a few use cases for set_box_aspect.

A square axes, independent of data#

Produce a square axes, no matter what the data limits are.

import matplotlib.pyplot as plt
import numpy as np

fig1, ax = plt.subplots()

ax.set_xlim(300, 400)
ax.set_box_aspect(1)

plt.show()
axes box aspect

Shared square axes#

Produce shared subplots that are squared in size.

fig2, (ax, ax2) = plt.subplots(ncols=2, sharey=True)

ax.plot([1, 5], [0, 10])
ax2.plot([100, 500], [10, 15])

ax.set_box_aspect(1)
ax2.set_box_aspect(1)

plt.show()
axes box aspect

Square twin axes#

Produce a square axes, with a twin axes. The twinned axes takes over the box aspect of the parent.

axes box aspect

Normal plot next to image#

When creating an image plot with fixed data aspect and the default adjustable="box" next to a normal plot, the axes would be unequal in height. set_box_aspect provides an easy solution to that by allowing to have the normal plot's axes use the images dimensions as box aspect.

This example also shows that constrained layout interplays nicely with a fixed box aspect.

fig4, (ax, ax2) = plt.subplots(ncols=2, layout="constrained")

np.random.seed(19680801)  # Fixing random state for reproducibility
im = np.random.rand(16, 27)
ax.imshow(im)

ax2.plot([23, 45])
ax2.set_box_aspect(im.shape[0]/im.shape[1])

plt.show()
axes box aspect

Square joint/marginal plot#

It may be desirable to show marginal distributions next to a plot of joint data. The following creates a square plot with the box aspect of the marginal axes being equal to the width- and height-ratios of the gridspec. This ensures that all axes align perfectly, independent on the size of the figure.

fig5, axs = plt.subplots(2, 2, sharex="col", sharey="row",
                         gridspec_kw=dict(height_ratios=[1, 3],
                                          width_ratios=[3, 1]))
axs[0, 1].set_visible(False)
axs[0, 0].set_box_aspect(1/3)
axs[1, 0].set_box_aspect(1)
axs[1, 1].set_box_aspect(3/1)

np.random.seed(19680801)  # Fixing random state for reproducibility
x, y = np.random.randn(2, 400) * [[.5], [180]]
axs[1, 0].scatter(x, y)
axs[0, 0].hist(x)
axs[1, 1].hist(y, orientation="horizontal")

plt.show()
axes box aspect

Set data aspect with box aspect#

When setting the box aspect, one may still set the data aspect as well. Here we create an Axes with a box twice as long as it is tall and use an "equal" data aspect for its contents, i.e. the circle actually stays circular.

fig6, ax = plt.subplots()

ax.add_patch(plt.Circle((5, 3), 1))
ax.set_aspect("equal", adjustable="datalim")
ax.set_box_aspect(0.5)
ax.autoscale()

plt.show()
axes box aspect

Box aspect for many subplots#

It is possible to pass the box aspect to an Axes at initialization. The following creates a 2 by 3 subplot grid with all square Axes.

fig7, axs = plt.subplots(2, 3, subplot_kw=dict(box_aspect=1),
                         sharex=True, sharey=True, layout="constrained")

for i, ax in enumerate(axs.flat):
    ax.scatter(i % 3, -((i // 3) - 0.5)*200, c=[plt.cm.hsv(i / 6)], s=300)
plt.show()
axes box aspect

References

The use of the following functions, methods, classes and modules is shown in this example:

Total running time of the script: (0 minutes 2.950 seconds)

Gallery generated by Sphinx-Gallery