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
The interaction of setting axis limits and autoscaling changed in 3.2 with little guidance, introducing unexpected behavior that doesn't always make sense.
Code for reproduction
Here is a plot that looks very different on 3.1.2 and 3.2.1
I suspect that this related to making the auto-scaling lazier.
On master I get a flash of the wrong scaling before it goes to the correct limits but it is still broken an v3.2.x.
I suspect the problem is that adding the scatter "arms" the rescale, but setting the ylim does not "disarm" it. If you force a f.canvas.draw() just before setting the ylim it works correctly.
This only happens w/ auto=None, which says to keep the autoscaling as it was before the set_ylim. So I'd argue the plot is correct since you are asking for the y-axis to be autoscaled, at least according to the docs.
What did auto=None do before? Only autoscale only if more data is added? Thats super confusing in my opinion, but maybe seaborn has a use case?
So I'd argue the plot is correct since you are asking for the y-axis to be autoscaled, at least according to the docs.
No, I'm asking for the y axis limits to be (-.5, +.5) at this moment in time. I am also asking for this action not to change whether or not the plot will continue to autoscale in the future.
What did auto=None do before? Only autoscale only if more data is added?
Yes. My understanding, and the previous behavior, is that the auto parameter of set_{x,y}lim influences what happens in the future, not in response to that call.
Thats super confusing in my opinion, but maybe seaborn has a use case?
Why is that super confusing? If I am calling a method to set explicit limits, I don't think matplotlib should ignore my limits and autoscale to narrower values.
diff --git i/lib/matplotlib/axes/_base.py w/lib/matplotlib/axes/_base.py
index 8f60cfedd..bd727a529 100644
--- i/lib/matplotlib/axes/_base.py+++ w/lib/matplotlib/axes/_base.py@@ -3331,6 +3331,9 @@ class _AxesBase(martist.Artist):
left, right = sorted([left, right], reverse=bool(reverse))
self._viewLim.intervalx = (left, right)
+ # Mark viewlims as no longer stale without triggering an autoscale.+ for ax in self._shared_x_axes.get_siblings(self):+ ax._stale_viewlim_x = False
if auto is not None:
self._autoscaleXon = bool(auto)
@@ -3600,6 +3603,9 @@ class _AxesBase(martist.Artist):
bottom, top = sorted([bottom, top], reverse=bool(reverse))
self._viewLim.intervaly = (bottom, top)
+ # Mark viewlims as no longer stale without triggering an autoscale.+ for ax in self._shared_y_axes.get_siblings(self):+ ax._stale_viewlim_y = False
if auto is not None:
self._autoscaleYon = bool(auto)
is what we need, can you confirm that works for you?
Why is that super confusing? If I am calling a method to set explicit limits, I don't think matplotlib should ignore my limits and autoscale to narrower values.
I agree, but then to autoscale if I add something new is surprising. I can see that its a useful feature, but it adds some complexity to the state of the plot that we have to keep track of, and obviously got dropped here.
@anntzer, your patch appears to work for me. But I guess we need to test this flag better.
I agree, but then to autoscale if I add something new is surprising. I can see that its a useful feature, but it adds some complexity to the state of the plot that we have to keep track of, and obviously got dropped here.
Well the reason seaborn uses auto=None is mostly for backwards compatibility, as it matches how ax.set{x,y}lim had previously worked. I recall the original change causing some pain that seemed best solved at the time by just preserving the old behavior, but I don't remember the details of the issues.
What I really want from explicit limits / autoscaling is something closer to a ratchet: I want to set limits that won't hide to-be-added data that lie outside of the limits but will also not contract when to-be-added data lie inside the limits (minus the margin).
But I'd settle for some better/less tautological documentation for how autoscale is supposed to work :)
Activity
mwaskom commentedon May 5, 2020
Is "autoscaling" actually documented anywhere? https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.autoscale.html just says "turn autoscaling on or off" but that's a bit tautological: it's saying "function f does f". What effect does f have?
jklymak commentedon May 5, 2020
Bisects to 160de56 #13593 @anntzer any quick idea what's going on here?
I didn't even know about the
auto=Noneoption.tacaswell commentedon May 5, 2020
https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.autoscale_view.html is the method that actually does the rescaling and has a slightly better explaination. This also gets coupled with "margins" and "sticky edges" https://matplotlib.org/gallery/subplots_axes_and_figures/axes_margins.html.
I suspect that this related to making the auto-scaling lazier.
On master I get a flash of the wrong scaling before it goes to the correct limits but it is still broken an v3.2.x.
I suspect the problem is that adding the scatter "arms" the rescale, but setting the ylim does not "disarm" it. If you force a
f.canvas.draw()just before setting the ylim it works correctly.jklymak commentedon May 5, 2020
This only happens w/
auto=None, which says to keep the autoscaling as it was before theset_ylim. So I'd argue the plot is correct since you are asking for the y-axis to be autoscaled, at least according to the docs.What did
auto=Nonedo before? Only autoscale only if more data is added? Thats super confusing in my opinion, but maybe seaborn has a use case?mwaskom commentedon May 5, 2020
No, I'm asking for the y axis limits to be
(-.5, +.5)at this moment in time. I am also asking for this action not to change whether or not the plot will continue to autoscale in the future.Yes. My understanding, and the previous behavior, is that the
autoparameter ofset_{x,y}liminfluences what happens in the future, not in response to that call.Why is that super confusing? If I am calling a method to set explicit limits, I don't think matplotlib should ignore my limits and autoscale to narrower values.
mwaskom commentedon May 5, 2020
To be clear, there has been a change when
auto=Trueas well.3.1.2:
3.2.1:
anntzer commentedon May 5, 2020
I guess
is what we need, can you confirm that works for you?
jklymak commentedon May 5, 2020
I agree, but then to autoscale if I add something new is surprising. I can see that its a useful feature, but it adds some complexity to the state of the plot that we have to keep track of, and obviously got dropped here.
@anntzer, your patch appears to work for me. But I guess we need to test this flag better.
mwaskom commentedon May 5, 2020
Well the reason seaborn uses
auto=Noneis mostly for backwards compatibility, as it matches howax.set{x,y}limhad previously worked. I recall the original change causing some pain that seemed best solved at the time by just preserving the old behavior, but I don't remember the details of the issues.mwaskom commentedon May 5, 2020
What I really want from explicit limits / autoscaling is something closer to a ratchet: I want to set limits that won't hide to-be-added data that lie outside of the limits but will also not contract when to-be-added data lie inside the limits (minus the margin).
But I'd settle for some better/less tautological documentation for how autoscale is supposed to work :)
FIX: cancel pending autoscale on manually setting limits
FIX: cancel pending autoscale on manually setting limits
ianhi commentedon Aug 20, 2020
@mwaskom I agree, that would be great. Until such a dream is realized I found that I could get satisfactory results like so:
Full code + associated
x_limversion lives here:https://github.com/ianhi/mpl-interactions/blob/a5cd394514418215ed61462c5c35d33e312f52cd/mpl_interactions/jupyter.py#L64-L70
mwaskom commentedon Aug 20, 2020
@ianhi cleaner to write that code as