5

I have a figure containing three subplots. The first subplot is an image (imshow), while the other two are distributions (plot).

Here's the code:

# collects data
imgdata = ...      # img of shape  (800, 1600, 3)    
x = ...            # one 1600-dimensional vector
y = ...            # one  800-dimensional vector

# create the figure 
f = plt.figure()    

# create subplots   
subplot_dim = (1, 3)
p_img = plt.subplot2grid(subplot_dim, (0, 0), aspect="auto")
p_x = plt.subplot2grid(subplot_dim, (0, 1), aspect="auto")
p_y = plt.subplot2grid(subplot_dim, (0, 2), aspect="auto")

p_img.imshow(imgdata, interpolation="None")
p_x.plot(x)         
p_y.plot(y)         


# save figure       
f.set_size_inches(21.0, 12.0)
f.savefig("some/path/image.pdf", dpi=80)

My problem is, that the two subplots p_x, p_y always have a greater height than the image subplot p_img.

Thus, the result always looks like this:

                  ###############   ###############   
                  #             #   #  *****      #
                  #        *****#   # *     *     #
###############   #     ***     #   # *      *    #
#             #   #    *        #   # *        *  #
#    image    #   #   *         #   #*           *#
#             #   #***          #   #*           *#
###############   ###############   ###############
     p_img              p_x               p_y

How can I enforce an equal size (or at least height) of p_img, p_x and p_y?

EDIT: Here is a simple example code that generates random data and uses plt.show() instead of saving a figure. However, one can easily see the same behaviour there: the image is much smaller (height) than the other subplots:

from matplotlib import pyplot as plt 
from matplotlib import image as mpimg
import numpy as np

imgdata = np.random.rand(200, 400, 3)  
x = np.random.normal(loc=100.0, scale=20.0, size=400)
y = np.random.normal(loc=150.0, scale=15.0, size=200) 

# create the figure
f = plt.figure()

# create subplots
subplot_dim = (1, 3)
p_img = plt.subplot2grid(subplot_dim, (0, 0), aspect="auto")
p_x = plt.subplot2grid(subplot_dim, (0, 1), aspect="auto")
p_y = plt.subplot2grid(subplot_dim, (0, 2), aspect="auto")

p_img.imshow(imgdata, interpolation="None")
p_x.plot(x)
p_y.plot(y)


# save figure
plt.show()
4
  • Try plt.axis() function to set axis dimensions Commented Jun 11, 2016 at 18:14
  • That did not change anything :( btw: isn't axis() taking a list of [xmin, xmax, ymin, ymax]? The p_img, p_x and p_y have a (pairwise) different y-axis. 800 for p_img (height of the image) and normally something in the interval [1, 10] for y_max of p_x and p_y. Therefore they never share the y-axis (scaling). Commented Jun 11, 2016 at 18:21
  • gridspec? Check this question to see if its of any help Commented Jun 11, 2016 at 18:43
  • I've tested my example code with gridspec (created axes with gridspec instead of subplot2grid and added height_ratios to gridspec). This seems to enforce a certain width/height. However, I do not understand the scaling and it looks like the values are somehow absolute? Doesn't matplotlib have some method to make the height of subplots fixed? This looks like a huge design flaw to me...do one really has to determine every subplots width/height and then rescale it manually to get equal size subplots? Commented Jun 11, 2016 at 18:55

1 Answer 1

1

You can do it by specifying it directly in the subplots like this:

from matplotlib import pyplot as plt
from matplotlib import image as mpimg
import numpy as np

imgdata = np.random.rand(200, 400, 3)
x = np.random.normal(loc=100.0, scale=20.0, size=400)
y = np.random.normal(loc=150.0, scale=15.0, size=200)

# create the figure
f = plt.figure()

# create subplots
subplot_dim = (1, 3)
p_img = plt.subplot2grid(subplot_dim, (0, 0), aspect="auto")
p_x = plt.subplot2grid(subplot_dim, (0, 1), aspect="auto", adjustable='box-forced', sharex=p_img, sharey=p_img)
p_y = plt.subplot2grid(subplot_dim, (0, 2), aspect="auto", adjustable='box-forced', sharex=p_img, sharey=p_img)

p_img.imshow(imgdata, interpolation="None")
p_x.plot(x)
p_y.plot(y)

, which results in this:

Same height for all matplotlib subplots

The problem is your data does not have the same limits. So you'll have to make adjustments with set_xlim and set_ylim. I would also recommend testing other combinations for sharey, since they might provide better results.

Sign up to request clarification or add additional context in comments.

1 Comment

Matplotlib 3.4 gives this error: ValueError: 'box-forced' is not a valid value for adjustable; supported values are 'box', 'datalim'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.