I'm trying to create a figure with subplots using the GridSpec method of a specific size. The size I'm trying to specify is 4.205 x 2.2752 inches to fit as a panel in an academic figure. I'm using fig.subplots_adjust to have the subplots fill the entirety of the figure. However, the output figure has completely different dimensions. Here is my code:
# set up the figure
fig = plt.figure(figsize = (4.2055, 2.2752))
# number of columns in the Gridspec
fwid = 22
# set up the grid
grid = plt.GridSpec(1,fwid)
# set up the number of columns allocated to each subplot
h0 = int((fwid-1)/3)
h1 = int(h0*2)
ax = [
fig.add_subplot(grid[:h0]),
fig.add_subplot(grid[h0:h1]),
fig.add_subplot(grid[h1]),
]
hm1 = np.random.randn(10,10)
hm2 = np.random.randn(10,10)
# plot the heatmaps
sns.heatmap(
hm1, ax = ax[0],
vmin = 0, vmax = 1,
cbar = False
)
sns.heatmap(
hm2, ax = ax[1],
vmin = 0, vmax = 1,
# put the colorbar in the 3rd subplot
cbar_ax = ax[2]
)
ax[0].set_xticks(np.arange(0.5,10))
ax[0].set_xticklabels(np.arange(0.5,10))
ax[0].set_yticks(np.arange(0.5,10))
ax[1].set_yticks([])
ax[1].set_xticks(np.arange(0.5, 10))
ax[1].set_xticklabels(np.arange(0.5,10))
fig.subplots_adjust(left = 0, right = 1, bottom = 0, top = 1)
plt.savefig('example.png', facecolor = 'white', transparent = False,
bbox_inches = 'tight', dpi = 300)
Here is what the output figure looks like:

Instead of being 4.205 x 2.2752 inches, it is 2.96 x 2.3166 inches. Not sure what is going on here. Any help is appreciated!
Fine-tuning precisely customized figure image file output dimensions with Matplotlib
GridSpecsubplots ofsns.heatmap(including a thirdaxesobject for the colorbar legend)Key changes implemented below:
Axes.set_aspect)matplotlib.pyplot.savefig.bbox_inchesparameter to ensure figure output dimensions in MatplotlibA few additional changes had to also be implemented (see code below). Essentially, the approach taken here was the result of some trial and error in fine-tuning the
figsize, DPI, and subplots margins (see:matplotlib.pyplot.subplots_adjust), followed by image cropping usingPIL. The final result, though, as shown, is a matplotlibGridSpec-arrayed figure of two Seaborn heatmap subplots which neatly fill the given dimensions you specify.*(See
GridSpecdocs regarding the implementation of subplots here.)where the final output produced (
cropped_fig.png) is:and the direct output from Matplotlib was (the black dashed line bounding box was measured to precisely match the specified dimensions; this and the red dimension annotations were added in photoshop, but the image file size was not cropped - i.e., the raw dimensions output from matplotlib are preserved):
In the solution provided, the aspect ratio of the Seaborn subplots axes objects is explicitly modified to effectively stretch / widen the heatmaps, thus filling out the area defined by the given dimensions specifications. Using the values for all the various customizable figure and axes parameters as shown above, however, results in the generation of substantial amounts of whitespace padding the output figure (see directly above screenshot viewing the raw matplotlib output figure file before cropping). To account for this, the figure is initialized by the required dimensions multiplied by a scalar factor (i.e.,
figsize=(w * 1.5, h * 1.5)) set such that the final resulting visualization matches to the desired size when subsequently cropped out as close as possible. The fine-tuned values of these parameters can of course be adjusted / tailored as needed.*Note: It is the use of
bbox_inches="tight"which results in the output file not having the exact dimensions as specified.