broccoli008
broccoli008

Reputation: 13

How to create python imshow subplots with same pixel size

I'm trying to create imshow subplots with the same pixel size without having the figure height automatically scaled, but I haven't been able to figure out how.

Ideally, I'm looking for a plot similar to the second picture, without the extra white space (ylim going from -0.5 to 4.5) and maybe centered vertically. My pictures will always have the same width, so maybe if I could fix the subplot width instead of the height that would help. Does anyone have any ideas?

close('all')
f,ax=subplots(1,2)
ax[0].imshow(random.rand(30,4),interpolation='nearest')
ax[1].imshow(random.rand(4,4),interpolation='nearest')
tight_layout()

f,ax=subplots(1,2)
ax[0].imshow(random.rand(30,4),interpolation='nearest')
ax[1].imshow(random.rand(4,4),interpolation='nearest')
ax[1].set_ylim((29.5,-0.5))
tight_layout()

Plot without ylim adjustment:

Plot without ylim adjustment

Plot with ylim adjustment:

Plot with ylim adjustment

Upvotes: 1

Views: 3775

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339270

In principle you can just make the figure size small enough in width, such that it constrains the widths of the subplots. E.g. figsize=(2,7) would work here.

For an automated solution, you may adjust the subplot parameters, such that the left and right margin constrain the subplot width. This is shown in the code below. It assumes that there is one row of subplots, and that all images have the same pixel number in horizontal direction.

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots(1,2)
im1 = ax[0].imshow(np.random.rand(30,4))
im2 = ax[1].imshow(np.random.rand(4,4))


def adjustw(images, wspace="auto"):
    fig = images[0].axes.figure
    if wspace=="auto":
        wspace = fig.subplotpars.wspace
    top = fig.subplotpars.top
    bottom = fig.subplotpars.bottom
    shapes = np.array([im.get_array().shape for im in images])
    w,h = fig.get_size_inches()
    imw = (top-bottom)*h/shapes[:,0].max()*shapes[0,1] #inch
    n = len(shapes)
    left = -((n+(n-1)*wspace)*imw/w - 1)/2.
    right = 1.-left
    fig.subplots_adjust(left=left, right=right, wspace=wspace)

adjustw([im1, im2], wspace=1)

plt.show()

If you need to use tight_layout(), do so before calling the function. Also you would then definitely need to set the only free parameter here, wspace to something other than "auto". wspace=1 means to have as much space between the plots as their width.

The result is a figure where the subplots have the same size in width.

enter image description here

Upvotes: 2

Related Questions