Skip to content

inconsistent autoscaling around axvlines #14651

New issue

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

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
anntzer opened this issue Jun 29, 2019 · 25 comments
Open

inconsistent autoscaling around axvlines #14651

anntzer opened this issue Jun 29, 2019 · 25 comments

Comments

@anntzer
Copy link
Contributor

anntzer commented Jun 29, 2019

Bug report

Bug summary

Autoscaling behavior around axvlines is inconsistent.

Code for reproduction

from pylab import *

fig, axs = plt.subplots(2, 2)

axs[0, 0].axvline(0.9)

axs[0, 1].axvline(1.1)

axs[1, 0].plot([10, 11], [10, 11])
axs[1, 0].axvline(11.04)

axs[1, 1].plot([10, 11], [10, 11])
axs[1, 1].axvline(11.06)

plt.show()

Actual outcome

test

Top row: when the axvline is drawn in (0, 1) (the default), the margins are left as is; when the axvline is drawn outside of it, the margins move to surround it.

Bottom row: when the axvline is drawn within the margins imposed by the "other" line plot, the margins are left as is; when the axvline is drawn outside of it, yet another 5% margins are applied to it.

Expected outcome

Consistent behavior between left and right.

I think it's mostly just a matter of

--- i/lib/matplotlib/axes/_axes.py
+++ w/lib/matplotlib/axes/_axes.py
@@ -893,20 +886,13 @@ class Axes(_AxesBase):
 
         if "transform" in kwargs:
             raise ValueError(
-                "'transform' is not allowed as a kwarg;"
-                + "axvline generates its own transform.")
-        xmin, xmax = self.get_xbound()
-
-        # We need to strip away the units for comparison with
-        # non-unitized bounds
+                "'transform' is not allowed as a kwarg; "
+                "axvline generates its own transform")
         self._process_unit_info(xdata=x, kwargs=kwargs)
-        xx = self.convert_xunits(x)
-        scalex = (xx < xmin) or (xx > xmax)
-
         trans = self.get_xaxis_transform(which='grid')
         l = mlines.Line2D([x, x], [ymin, ymax], transform=trans, **kwargs)
         self.add_line(l)
-        self._request_autoscale_view(scalex=scalex, scaley=False)
+        self._request_autoscale_view(scalex=True, scaley=False)
         return l
 
     @docstring.dedent_interpd

(and likewise for axhline); OTOH I guess some may possibly actually be relying on non-expansion of margins when drawing axvlines just outside of the data limits but still within the margins? dunno.

Matplotlib version

  • Operating system: linux
  • Matplotlib version: 3.1
  • Matplotlib backend (print(matplotlib.get_backend())): qt5agg
  • Python version: 37
  • Jupyter version (if applicable):
  • Other libraries:
@timhoffm
Copy link
Member

I guess autoscaling should always take avhlines into account.

@stevenlis
Copy link

stevenlis commented Aug 21, 2019

fig, ax = plt.subplots()
ax.axvline(0.5, color='b', transform=ax.transAxes)

I got: ValueError: 'transform' is not allowed as a kwarg;axvline generates its own transform.

but the doc suggested that transform is supported.

Am I missing something? If I wanna plot a line in the middle of a Axes, how should I do it for now rather than set xlim?

@ImportanceOfBeingErnest
Copy link
Member

@StevenLi-DS axvline is a high-level convenience function for the special, but frequently used case where you want a vertical line spanning (part of the axes) positionned at a certain x coordinate in data units. The documentation does not suggest that transform is supported, in fact it clearly states

Valid kwargs are Line2D properties, with the exception of 'transform':

You can always achieve the same with a usual line and the respective transform, hence ax.axvline(0.5) is equivalent to ax.plot([.5,.5], [0,1], transform=ax.get_xaxis_transform()).

If you want your line to be completely in axes coordinates, it would be ax.plot([.5,.5], [0,1], transform=ax.transAxes).

All of this is unrelated to the original issue here. It would help to use a new issue in such cases in order to not disturb the thread of arguments in existing ones.

@jklymak
Copy link
Member

jklymak commented Aug 22, 2019

Back to the original thread. I think axvline should not change the axes limits. Ever. It’s a way of annotating data, not data. If someone wants to plot a vertical line then that’s what plot is for.

@ImportanceOfBeingErnest
Copy link
Member

I think I would personally agree with "axvline should not change the axes limits".

Related to this: #7742, which already did undergo two unsuccessful attempts to fix.

@anntzer
Copy link
Contributor Author

anntzer commented Aug 22, 2019

So should it also not change limits even if plotting outside of the current limits? (I'm fine with that solution too.)

@ImportanceOfBeingErnest
Copy link
Member

That would be what I would expect. But maybe other users not? In particular, I think it would be a significant change to how it is handled now.

@jklymak
Copy link
Member

jklymak commented Aug 22, 2019

In an ideal world it would not auto scale at all and explicitly say that in the docs

@anntzer
Copy link
Contributor Author

anntzer commented Aug 22, 2019

It's probably not too hard to change that behavior with a deprecation warning (check whether the limits would change and if so warn), the only question is whether it's worth the trouble.

@timhoffm
Copy link
Member

axvline should not change the axes limits

not sure I agree with that. If the user plots this line, there's some intent behind it and it's most likely undesired if the line does not show up.

Example: Plot some relative values. Values larger than 1 represent data that got larger, values below 1 got smaller. It can be reasonable to axhline(1) to define the different semantics. It might be an essential information. If my data happen to be all smaller than 1, not taking into account the line would shift it off-screen, which would remove an important aspect of the graph.

@jklymak
Copy link
Member

jklymak commented Aug 22, 2019

I'd argue in that case the user can specify those important limits manually. My conceptualization of axvline is that its a special grid line.

I appreciate other folks might conceptualize it differently, so we should decide if it autoscales (in x) or not, but not do something that is half way.

@dopplershift
Copy link
Contributor

dopplershift commented Aug 22, 2019

If I plot a vertical line at x=0.5, I'd expect 0.5 to be considered when automatically determining X plot limits. I would not expect to need to manually tell matplotlib to include this.

@jklymak
Copy link
Member

jklymak commented Aug 22, 2019

... and would you expect an auto scaling margin around the line? If so, we should remove the funky logic and just autoscale.

@timhoffm
Copy link
Member

timhoffm commented Aug 22, 2019

I would expect a margin, for the same reason we have margins at all. Removing funky logic sounds good 😄.

@anntzer
Copy link
Contributor Author

anntzer commented Aug 22, 2019

@dopplershift If you plot a vertical line at x=0.99 while the current limits (computed on the rest of the data) is (0, 1), do you expect the 5% margin to go to 1.05(-epsilon)?
Just trying to clarify what everyone's opinion is...

@stevenlis
Copy link

stevenlis commented Aug 23, 2019

@ImportanceOfBeingErnest

The documentation does not suggest that transform is supported

The reason why I was confused is that transform is listed in Other Parameters:
image

https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.axes.Axes.axvline.html

@jklymak
Copy link
Member

jklymak commented Aug 23, 2019

Yeah, thats an unfortunate artifact of just repeating the Line2D kwargs. The caveat at the beginning tries to warn about that, but its kinda hard to catch if you are looking at a list of 30 properties.

@dopplershift
Copy link
Contributor

@anntzer Personally, I expect the margin to increase as well. It may "just" be a notational line, but the whole point of margins is better aesthetics around things on the plot, keeping all items (dataspace wise) from being right on the edge.

@anntzer
Copy link
Contributor Author

anntzer commented Aug 23, 2019

so in #14651 (comment) you think we should increase the margins in the lower left plot?

@dopplershift
Copy link
Contributor

Yes.

@jklymak
Copy link
Member

jklymak commented Aug 23, 2019

Do we understand why the complicated logic was put in, and does removing it fail any tests?

@anntzer
Copy link
Contributor Author

anntzer commented Aug 23, 2019

This came in in d4965f (2008); all the commit message says is "fixed a problem with axh and vline scaling". Previously it was never scaling, which is the behavior you (@jklymak) are advocating.
So I guess the answer to your question is "to fix a problem" :)

@jklymak
Copy link
Member

jklymak commented Aug 23, 2019

I feel strongly that the behaviour should be simple and consistent. I feel mildly that these should not participate in auto scaling, but don’t mind the opposite behaviour

@dopplershift
Copy link
Contributor

I agree about simple and consistent. I can say that my reaction, if I call axvline or axhline, and the line does not appear in my plot due to unadjusted data bounds, will be WTF matplotlib?

@tacaswell tacaswell added this to the v3.3.0 milestone Aug 27, 2019
@elmer-garduno
Copy link

pathces.Rectangle has the non-auto-scaling behavior, which is problematic if some things remain where they are and others are scaled. I agree the behavior should be consistent.

@tacaswell tacaswell modified the milestones: v3.3.0, v3.4.0 Jun 2, 2020
@QuLogic QuLogic removed this from the v3.4.0 milestone Jan 27, 2021
@QuLogic QuLogic added this to the v3.5.0 milestone Jan 27, 2021
@QuLogic QuLogic modified the milestones: v3.5.0, v3.6.0 Sep 25, 2021
@QuLogic QuLogic modified the milestones: v3.6.0, v3.7.0 Aug 24, 2022
@ksunden ksunden modified the milestones: v3.7.0, v3.7.1 Feb 14, 2023
@QuLogic QuLogic modified the milestones: v3.7.1, future releases Mar 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants