How to force same size between matplotlib subplot image axes
Asked Answered
B

2

8

Suppose I have the following code to create three side-by-side images:

    n=10
    x = np.random.rand(n,1)
    y = np.random.rand(1,n)
    z = np.random.rand(n,n)

    fig, ax = plt.subplots(1, 3)
    ax[0].imshow(x)
    ax[1].imshow(z)
    ax[2].imshow(y)

However, the axes autoscale so that the vertical axis in the first image is larger than the vertical axis in the second.

enter image description here

Is there a way to programmatically force all image dimensions of size n to look the same in the three plots, regardless of window size? I'm looking for a way to either link the axes or the images so that the vertical axis of the first plot is the same size as the vertical axis of the second plot, and the horizontal axis of the third plot is the same size as the horizontal axis of the second plot, regardless of window size. i.e. something like this: enter image description here

Berkelium answered 11/5, 2018 at 18:34 Comment(0)
K
2

I think one easiest way is to use aspect='auto' with ax[1].imshow(z). But this will distort the image in a way that may be not the same as what you've shown in the question. And it may not work for cases where there is no single n. I'm not sure if I got you 100%, but let me try this method. The key idea here are:

  1. Change the aspect ratio of your fig. The exact ratio comes from both your image data and your subplot layout.
  2. Use tight layout to eliminate unnecessary between axes which may offset your graph a little bit.

Here is my example code and figure:

import matplotlib.pyplot as plt
from matplotlib.figure import figaspect
import numpy as np

n = 10
x = np.random.rand(n,1)
y = np.random.rand(1,n)
z = np.random.rand(n,n)

width_max = max(s.shape[0] for s in [x, y, z])
height_max = max(s.shape[1] for s in [x, y, z])

row = 1
col = 3
fig, ax = plt.subplots(row, col)
w, h = figaspect(row*width_max/(col*height_max))
fig.set_size_inches(w, h)

ax[0].imshow(x)
ax[1].imshow(z)
ax[2].imshow(y)

plt.tight_layout()
plt.show()

enter image description here

I hope this solves your real problem. I think this also works for a case like:

x = np.random.rand(3,1)
y = np.random.rand(1,10)
z = np.random.rand(7,6)
Kinfolk answered 11/5, 2018 at 19:49 Comment(2)
This doesn't quite work: The generated figure window is extremely large for a large n and resizing the window changes the ratios again. I'm looking for a way to either link the axes or the images so that the relative dimensions remain the same regardless of window size. (Added this to the original question to clarify)Berkelium
@Berkelium I'm sorry but I'm not familiar with what you are talking about. What is you "generated figure window"? I've tested the code with Jupyter notebook. It stays the same no matter how I change the size of my Chrome window. It's also fine if I save the figure with fig.savefig('test.png'). If you feel like the figure is too big in size, you can scale down w and h accordingly. By default, it is based on your rcParams['figure.figsize'][1].Kinfolk
H
0

You may restrict your figure size and/or the subplot parameters in the vertical direction to leave less space for the axes to scale.

fig, ax = plt.subplots(1, 3, figsize=(6.4,3))
fig.subplots_adjust(bottom=0.26, top=0.74)

plot

Hock answered 12/5, 2018 at 1:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.