You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
missing imshow() subplots when using tight_layout() #4976
Hello, I've found an unexpected behavior when I make grids of subplots with imshow and tight_layout the second to last plot is missing, for example:
import numpy as np
import matplotlib.pyplot as plt
plt.figure()
for i in range(16):
ax= plt.subplot(4,4 ,i+1)
im=ax.imshow(np.random.normal(size=100).reshape([10,10]))
plt.tight_layout()
plt.title(i)
plt.savefig("imshow_4x4.png")
generates:
Whereas the same loop with pcolor works:
import numpy as np
import matplotlib.pyplot as plt
plt.figure()
for i in range(16):
ax= plt.subplot(4,4 ,i+1)
im=ax.pcolor(np.random.normal(size=100).reshape([10,10]))
plt.tight_layout()
plt.title(i)
plt.savefig("pcolor_4x4.png")
gives:
If I omit the tight_layout() call from the first example it works:
I'm using matplotlib 1.4.3 and numpy 1.9.2 in Anaconda 2.2.0.
yes, the work around works, thanks. Calling tight_layout inside the loop is admittedly an inefficient approach but not one I expected to delete a figure...
I agree, something very strange is going on here. Removing the call to imshow makes it work correctly. The bug is in some interaction between plt.tight_layout and plt.subplot(...).
That is f-ed up. I wonder if the axes isn't really removed, just misplaced?
On Aug 21, 2015 4:50 PM, "Thomas A Caswell" notifications@github.com
wrote:
plt.tight_layout() is removing an axes from the fig.axes list.
There is a simple work around here, just call plt.tight_layout once
outside of the loop and it works correctly.
—
Reply to this email directly or view it on GitHub #4976 (comment)
.
It seems like tight_layout is not removing the subplots but when you tried to call tight_layout on the figure it resized the subplots that were already on it(which made them bigger because it had avaliable space), then when you add another subplot to the figure with the already resized plot they will disappear because subplot is plotting in their region.
by making these at 0, the subplot can only shrink or stay the same even when there is avaliable space, thus the existing subplots shouldn't be overwritten by any new ones when a new subplot is plotted.
This is caused by fully_overlaps returning True for the last axes, and hence the old one gets deleted, as pointed out by #7393. What happens is that the "tight" axes is larger and the new axes overlaps the old axes and deletes it. I'm not sure what we can do to fix this, since the stated behaviour is that if you (partially) cover an axes it gets deleted. Better is to create the axes first (fig, axs = plt.subplots(4, 4)) and then call tight_layout, hence avoiding too much magic.
I think(?) you just emit a warning if an axes that would have been removed under the old behavior will no longer be removed with the new one? (telling whoever was relying on the old behavior that they need to explicitly call ax.remove() to suppress the warning)
That means no one can actually benefit from the new behavior until the deprecation elapses, but that seems OK?
Here you are only calling tight layout at the end. If this is indeed reproducible then please provide a self-contained example and open a new issue. If it's not reproducible, because you are really calling tight_layout in the middle of the process sometimes, then it is the same bug. Also if you want to add subplots to an existing figure just call fig.subplots(1,2)
Activity
tacaswell commentedon Aug 21, 2015
... what
I can reproduce this on current master.
tacaswell commentedon Aug 21, 2015
plt.tight_layout()is removing an axes from thefig.axeslist.There is a simple work around here, just call
plt.tight_layoutonce outside of the loop and it works correctly.douglase commentedon Aug 21, 2015
yes, the work around works, thanks. Calling tight_layout inside the loop is admittedly an inefficient approach but not one I expected to delete a figure...
tacaswell commentedon Aug 21, 2015
I agree, something very strange is going on here. Removing the call to
imshowmakes it work correctly. The bug is in some interaction betweenplt.tight_layoutandplt.subplot(...).I suggest re-writing this loop as
WeatherGod commentedon Aug 22, 2015
That is f-ed up. I wonder if the axes isn't really removed, just misplaced?
On Aug 21, 2015 4:50 PM, "Thomas A Caswell" notifications@github.com
wrote:
Hongyu1230 commentedon Mar 2, 2016
This is my attempted fix of the problem
It seems like tight_layout is not removing the subplots but when you tried to call tight_layout on the figure it resized the subplots that were already on it(which made them bigger because it had avaliable space), then when you add another subplot to the figure with the already resized plot they will disappear because subplot is plotting in their region.
I'm not really sure if this is a good fix though.
https://github.com/Hongyu1230/matplotlib/commit/f21fc17117ee67cf39dae218bf88ea1ef2d572fc
tacaswell commentedon Mar 2, 2016
@hamgyu1230 Can you open a pull request with that change (with a better commit message!).
Can you explain why clipping these values at 0 fixes the problem?
Hongyu1230 commentedon Mar 2, 2016
#6096
by making these at 0, the subplot can only shrink or stay the same even when there is avaliable space, thus the existing subplots shouldn't be overwritten by any new ones when a new subplot is plotted.
adizhol commentedon Sep 14, 2021
Was this fixed? I have the same problem
jklymak commentedon Sep 14, 2021
Not really, but if you just call
tight_layoutonce, at the end, it all works fine.jklymak commentedon Sep 14, 2021
This is caused by
fully_overlapsreturning True for the last axes, and hence the old one gets deleted, as pointed out by #7393. What happens is that the "tight" axes is larger and the new axes overlaps the old axes and deletes it. I'm not sure what we can do to fix this, since the stated behaviour is that if you (partially) cover an axes it gets deleted. Better is to create the axes first (fig, axs = plt.subplots(4, 4)) and then calltight_layout, hence avoiding too much magic.anntzer commentedon Sep 14, 2021
I actually think the "remove overlapping subplots" behavior is pretty bad and should be deprecated and removed; see #11435 and #7377 (comment).
jklymak commentedon Sep 14, 2021
I agree, but I'm not sure how you deprecate that without a huge rigamarole.
anntzer commentedon Sep 14, 2021
I think(?) you just emit a warning if an axes that would have been removed under the old behavior will no longer be removed with the new one? (telling whoever was relying on the old behavior that they need to explicitly call ax.remove() to suppress the warning)
That means no one can actually benefit from the new behavior until the deprecation elapses, but that seems OK?
fzyzcjy commentedon Sep 24, 2021
I have the same problem
MacOS, matplotlib 3.1.3, MacOSX backend
In my case, @jklymak 's workaround does not work. Once in a while some figures disappear.
I do not want to call
subplotssince it will create a new figure but I want to use the old one.code:
example result (once in a while)
jklymak commentedon Sep 24, 2021
Here you are only calling tight layout at the end. If this is indeed reproducible then please provide a self-contained example and open a new issue. If it's not reproducible, because you are really calling tight_layout in the middle of the process sometimes, then it is the same bug. Also if you want to add subplots to an existing figure just call fig.subplots(1,2)
fzyzcjy commentedon Sep 24, 2021
@jklymak Thanks I will look at it to see how to reproduce it
back2yes commentedon Nov 30, 2021
@jklymak Thanks you saved my day.
Godfreyoise commentedon Mar 17, 2024
Please why is this code not running
plt.figure(figsize=(10, 10))
for image, labels in data_train.take(1):
for i in range(9):
plt.subplot(3,3,i+1)
Godfreyoise commentedon Mar 17, 2024
Godfreyoise commentedon Mar 17, 2024
rcomer commentedon Mar 17, 2024
@Godfreyoise for usage questions please go to https://discourse.matplotlib.org/. You will need to provide a complete code example so that others can reproduce the problem.