Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

imshow() subplots with shared axes generate unwanted white spaces #1789

Closed
rycmak opened this Issue Feb 27, 2013 · 9 comments

Comments

Projects
None yet
5 participants

rycmak commented Feb 27, 2013

When plotting two (or more) subplots which share the same axes, I see large areas of white spaces within the plots as seen here:
sharexImage

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot(2, 1, 1)
ax.imshow(np.random.random((10,10)))
ax.autoscale(False)
ax2 = fig.add_subplot(2, 1, 2, sharex=ax, sharey=ax)
ax2.imshow(np.random.random((10,10)))
ax2.autoscale(False)
plt.show()

These white spaces persist even after autoscale(False), ax.set_xlim(0, 10), and/or ax.set_xbound(0, 10). One way to get rid of the white spaces is to set aspect=auto in imshow(), but this is not always ideal.
One could also set a figsize and manually adjust the axes to get the image contained exactly within the figure without white spaces, but resizing the figure would make the white spaces appear again.

Is there a way to correct for this behaviour?

Member

pelson commented Feb 27, 2013

One way to get rid of the white spaces is to set aspect=auto in imshow(), but this is not always ideal.

Hi @mlynn1 - it looks like sharing forces the aspect ratio to be equal. As you say, setting the aspect to 'auto' stretches the image. The only other behaviour I can come up with is being able to reduce the size of the actual Axes itself. Is that what you had in mind? As far as I'm aware, there is no such functionality to do that automatically.

Thanks,

rycmak commented Feb 27, 2013

I guess what I don't understand is why imshow() has to show all that white space in the figure above. The equal aspect ratio of the images would remain even if the white spaces were not there, wouldn't it?

Yes, I could manually set axes positions and sizes with fig.add_axes() etc., but I was hoping that there was some way for fig.add_subplot() to take care of automatically resizing the shared axes and display everything perfectly ;-).

Member

pelson commented Feb 27, 2013

The equal aspect ratio of the images would remain even if the white spaces were not there, wouldn't it?

Only if the black y axis lines moved inwards to be tight against the image boundary. (unless I've misunderstood you). That was the bit that I don't know whether it is possible - I've never seen it done, though I'm no expert in this.

I believe these are your options:

  • Change the size of the figure that you are drawing. An aspect ratio of ~1:2 would be ideal.
  • Allow the image to stretch by turning off the aspect ratio='equal' constraint.
  • Reduce the amount of whitespace inside the axes (but increase it outside of them) by (somehow) forcing the x axis to go from the range [0, 9] - basically, the images would stay as they are in your example screenshot, just the black lines would move.
  • Change the coordinate system of your images such that the ratio='equal' constraint can hold, but the images can stretch wider (perhaps in the range [-10, 20].

I'm struggling to see any other way of arranging the plot (be it in matplotlib, or by pen and paper). Sorry if I'm missing something obvious.

Cheers,

@rycmak rycmak closed this Feb 27, 2013

@rycmak rycmak reopened this Feb 27, 2013

rycmak commented Feb 27, 2013

I tried your first three suggestions above, and while the amount of white space is reduced, it is still there. And there are times when one would like an unstretched image...

Only if the black y axis lines moved inwards to be tight against the image boundary.

I don't know why this is not done automatically by imshow()?

Basically, if I do not add the sharex and sharey options in the code above, I get exactly the plots I want. I can resize the figure, and each subplot would resize accordingly. The reason I would like the axes to be shared is that when I zoom in on one subplot, I would like the other subplot to zoom in correspondingly.

Member

WeatherGod commented Feb 27, 2013

On Wed, Feb 27, 2013 at 4:46 PM, mlynn1 notifications@github.com wrote:

I tried your first three suggestions above, and while the amount of white
space is reduced, it is still there. And there are times when one would
like an unstretched image...

Only if the black y axis lines moved inwards to be tight against the image
boundary.

I don't know why this is not done automatically by imshow()?

Basically, if I do not add the sharex and sharey options in the code
above, I get exactly the plots I want. I can resize the figure, and each
subplot would resize accordingly. The reason I would like the axes to be
shared is that when I zoom in on one subplot, I would like the other
subplot to zoom in correspondingly.

I suspect this is indeed a bug. imshow() does work as expected when
dealing with a single image. It is when doing these subplots that it gets
messed up.

Member

pelson commented Feb 27, 2013

@mlynn1 - thanks I now know what you're after (the behaviour before vs after of the share definition was the key).
I've just learnt something new about mpl in the process of digging into this one. There is an adjustable attribute (if you look in matplotlib.axes.Axes.__init__ you will see that this is set when sharing) which controls whether the axis is squeezed up to the data. To force the behaviour which you see when not sharing, set this to 'bbox-forced':

ax.set_adjustable('box-forced')
ax2.set_adjustable('box-forced')

When I do this, I get the same behaviour as when not sharing, only with the nice functionality that sharing adds.

HTH

Owner

efiring commented Feb 27, 2013

@WeatherGod, no it is not a bug. @pelson has the right solution. Sharing and adjustable 'box' are not always compatible.

rycmak commented Feb 27, 2013

@pelson: Thank you for your solution and time!

@rycmak rycmak closed this Feb 27, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment