Subplots with imshow and suptitle: bad default layout

Viewed 82

A very simple example with subplots and imshow seems to have bad default behavior.

import matplotlib.pyplot as plt
import numpy as np

grid = np.random.rand(2, 4)
fig, (ax1, ax2) = plt.subplots(1, 2)
ax1.imshow(grid)
ax1.set_title('damped')
ax2.imshow(grid)
ax2.set_title('undamped')
fig.suptitle('Different types of oscillations', fontsize=16)
plt.tight_layout()
plt.savefig('foo.png')

Result:

enter image description here

Why is the suptitle so high? Do I really have to manually adjust it every time based on the height of the subplots? A hint about what's going on can be seen by commenting the second imshow, though I have no guesses for a solution.

Result:

enter image description here

The figure is the same size, and seemingly the layout and suptitle etc. are determined based on the empty axes.

2 Answers

With pyplot.subplots(), I believe you would have to manually adjust the axes as you suggested.

gridspec.GridSpec() handles the layout differently. Originally I thought it collapsed the empty space by default, but after Jody's comment, I double checked and realized this was because I'd accidentally created an extra row (nrows=2 even though we're only using 1 row). It seems gridspec collapses the unused specs:

import matplotlib.gridspec as gridspec

fig = plt.figure(constrained_layout=True)
spec = gridspec.GridSpec(nrows=2, ncols=2, figure=fig)

ax1 = fig.add_subplot(spec[0, 0])
ax1.imshow(grid)
ax2 = fig.add_subplot(spec[0, 1])
ax2.imshow(grid)

fig.suptitle('Different types of oscillations', fontsize=16)

imshows with gridspec

imshow sets the aspect ratio of your axes to 1, and given your data range that makes the axes wider than they are tall. If you then put two of them side by side, then there will be blank space above and below the figure.

You can do imshow(Z, aspect='auto') as one solution. If you want the aspect ratio to be 1:1, then you should make the figure wider and/or shorter.

Related