Bug summary
When pushing the home button the subplots sometimes get larger and larger, sometimes smaller and smaller and sometimes stay in the correct size. The code and procedure below trigger it for me everytime in both QT5 and tkinter but other use cases has also triggered it but much more randomly
import matplotlib.pyplot as plt
import numpy as np
fig=plt.figure(1)
fig.clf()
N=3
for i in range(N*N):
fig.add_subplot(N,N,i+1).plot(np.random.randn(10000))
fig.set_tight_layout(True)
zoom in one of the subplots
push the home button
resize the plot window
push the home button
push the home more times get an even worse plot
(it can also be done with the backward and forward buttons).
The subplot plots starts to overlap for me with this procedure.
A new draw or zoom results in a correct plot which I found kind of weird.
I tried to figure out what causes the problem and I think that the problem is in
backend_bases , line 3100, _update_view()
def _update_view(self):
"""Update the viewlim and position from the view and
position stack for each axes.
"""
nav_info = self._nav_stack()
if nav_info is None:
return
# Retrieve all items at once to avoid any risk of GC deleting an Axes
# while in the middle of the loop below.
items = list(nav_info.items())
for ax, (view, (pos_orig, pos_active)) in items:
ax._set_view(view)
# Restore both the original and modified positions
ax._set_position(pos_orig, 'original')
ax._set_position(pos_active, 'active')
self.canvas.draw_idle()
The home button seems to (almost) work as expected if those lines are commented out. Almost because the view seems to change a little when I push the home button the first time.
Matplotlib 2.2.2
python 3.6.3
IPython 6.1.0
windows 10
installed with conda
changed the title [-]Home button together with tight_layout sometimes don't work[/-][+]Home button together with tight_layout sometimes doesn't work[/+]on Apr 8, 2018
The problem seems to be that
ax.get_subplotspec().get_topmost_subplotspec().get_position(fig)
that is used in the tight_layout calculation is not equal to the axis position in the "home stack" (that is set as the ax position with the home button) and that result in an incorrect tight_layout calculation. I am not sure how to fix that in a good why but it seems to work to add self.canvas.figure.tight_layout() before self.canvas.draw_idle() in the code above. That result in bad but consistent parameters in my case and the following drawing works as expected.
I am not sure if the solution is general though and it feels like it is the wrong place to use figure.
def _update_view(self):
"""Update the viewlim and position from the view and
position stack for each axes.
"""
nav_info = self._nav_stack()
if nav_info is None:
return
# Retrieve all items at once to avoid any risk of GC deleting an Axes
# while in the middle of the loop below.
items = list(nav_info.items())
for ax, (view, (pos_orig, pos_active)) in items:
ax._set_view(view)
# Restore both the original and modified positions
ax._set_position(pos_orig, 'original')
ax._set_position(pos_active, 'active')
if self.canvas.figure.get_tight_layout():
self.canvas.figure.tight_layout()
self.canvas.draw_idle()
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!
Activity
fredrik-1 commented on Apr 9, 2018
The problem seems to be that
ax.get_subplotspec().get_topmost_subplotspec().get_position(fig)
that is used in the tight_layout calculation is not equal to the axis position in the "home stack" (that is set as the ax position with the home button) and that result in an incorrect tight_layout calculation. I am not sure how to fix that in a good why but it seems to work to add self.canvas.figure.tight_layout() before self.canvas.draw_idle() in the code above. That result in bad but consistent parameters in my case and the following drawing works as expected.
I am not sure if the solution is general though and it feels like it is the wrong place to use figure.
def _update_view(self): """Update the viewlim and position from the view and position stack for each axes. """ nav_info = self._nav_stack() if nav_info is None: return # Retrieve all items at once to avoid any risk of GC deleting an Axes # while in the middle of the loop below. items = list(nav_info.items()) for ax, (view, (pos_orig, pos_active)) in items: ax._set_view(view) # Restore both the original and modified positions ax._set_position(pos_orig, 'original') ax._set_position(pos_active, 'active') if self.canvas.figure.get_tight_layout(): self.canvas.figure.tight_layout() self.canvas.draw_idle()fredrik-1 commented on Apr 13, 2018
Any comments about this? Should I write a pull request? I don't really know what it can break.
fix home button matplotlib#10989
fix home button matplotlib#10989
fix home button matplotlib#10989
github-actions commented on May 3, 2023
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!
tacaswell commented on Jun 2, 2023
I can not reproduce this any more.
I do not think it is worth bisecting to when we fixed it, but from the linked issues I suspect #11754