Skip to content

[Bug]: axes vlines() / hlines() incorrectly use data coordinate as min when blended transform is applied #23171

Closed

Description

@orionlee

Bug summary

For Axes.vlines(), when I want to use axes coordinate for ymin / ymax, as suggested in blended transformation, ymin is incorrectly treated as data coordinate.

Axes.hlines() has a similar problem with xmin.

Code for reproduction

# Sample derived from
# https://matplotlib.org/3.5.0/gallery/lines_bars_and_markers/vline_hline_demo.html#sphx-glr-gallery-lines-bars-and-markers-vline-hline-demo-py
    
import matplotlib.pyplot as plt
import numpy as np

import matplotlib 
print('matplotlib', matplotlib.__version__)


t = np.arange(5.0, 10.0, 0.1)
s = np.exp(-t) + np.sin(2 * np.pi * t) + 10

vax = plt.figure(figsize=(12, 6)).gca()
vax.plot(t, s, '^')

# By using ``transform=vax.get_xaxis_transform()`` the y coordinates are scaled
# such that 0 maps to the bottom of the axes and 1 to the top.

vax.vlines([6, 7], ymin=0, ymax=0.15, transform=vax.get_xaxis_transform(), colors='r')
# if I use axvline() instead, it correctly treats ymin as axes coordinate.
# vax.axvline(6, ymin=0, ymax=0.15, c='r')
# vax.axvline(7, ymin=0, ymax=0.15, c='r')

vax.set_xlabel('time (s)')
vax.set_title('Vertical lines demo');

Actual outcome

One can see that while ymax is applied correctly (about 15% of the y-axis), ymin is applied incorrectly. ymin is treated as data coordinate, incorrectly stretching the y-axis.

image

Expected outcome

The expected outcome can be obtained using multiple axvline() instead of vlines():

vax.axvline(6, ymin=0, ymax=0.15, c='r')
vax.axvline(7, ymin=0, ymax=0.15, c='r')

image

Additional information

I've encountered the problem in earlier versions. I cannot recall it ever works correctly.

Axes.hlines() has a similar problem with xmin.

One can add the following to the example codes above to test it:

# axes.hlines() has similar problem.
vax.hlines([9, 9,5], xmin=0, xmax=0.2, transform=vax.get_yaxis_transform(), colors='green')
# uses multiple axhline() call would work correctly
# vax.axhline(9, xmin=0, xmax=0.2, c='green')
# vax.axhline(9.5, xmin=0, xmax=0.2, c='green')

Operating system

Windows

Matplotlib Version

3.5.2

Matplotlib Backend

module://matplotlib_inline.backend_inline

Python version

Python 3.9.10

Jupyter version

6.4.11

Installation

conda

Activity

  1. changed the title [-][Bug]: axes vlines() / hlines() incorrectly use data coordinate as min when transform is applied[/-] [+][Bug]: axes vlines() / hlines() incorrectly use data coordinate as min when blended transform is applied[/+] on May 31, 2022
  2. added this to the v3.6.0 milestone on Jun 1, 2022
  3. added
    🌱 Good first issueOpen a pull request against these issues if there are no active ones!
    Difficulty: Mediumhttps://matplotlib.org/devdocs/devel/contribute.html#good-first-issues
    on Jun 1, 2022
  4. tacaswell commented on Jun 1, 2022

    @tacaswell
    Member

    Labeling this as a good first issue because there is no API design and this appears to be a clearly identified bug that should be fixed.

    Labeling as medium difficulty as this is probably not a project someone new to Python should take on.

  5. orionlee commented on Jun 1, 2022

    @orionlee
    Author

    I suspect the problem lies with the scaling done at the end of vlines() implementation

    minx = x.min()
    maxx = x.max()
    miny = min(ymin.min(), ymax.min())
    maxy = max(ymin.max(), ymax.max())
    corners = (minx, miny), (maxx, maxy)
    self.update_datalim(corners)
    self._request_autoscale_view()

    In the example scenario, the miny and maxy used in scaling are probably in axes coordinates, while the actual scaling in update_datalim() treat them as data coordinates.

    In contrast, axvlines() has no such issue, because its scaling logic keeps y-axis scale unchanged.

  6. njj67229 commented on Jul 14, 2022

    @njj67229

    Is anyone currently working on this issue? I have not done any open source contribution before and would be interested in giving it a stab as a first issue.

  7. QuLogic commented on Jul 20, 2022

    @QuLogic
    Member

    I don't think anyone is working on this; feel free to take a stab at it.

  8. modified the milestones: v3.6.0, v3.7.0 on Aug 24, 2022
  9. Ailieena commented on Aug 28, 2022

    @Ailieena

    Hi, I'm new to open source and wanted to take a look at this issue.
    I looked at the code and I'm not fully convinced that the current behavior is incorrect. The description of vlines function suggests that it should plot "vertical lines at each x from ymin to ymax.".
    It seems to me that vlines using ymin and ymax as coordinates is the expected outcome, am I wrong?

  10. story645 commented on Aug 28, 2022

    @story645
    Member

    It seems to me that vlines using ymin and ymax as coordinates is the expected outcome, am I wrong?

    Forgive me if I'm misinterpreting your question, but the issue is that this function supports multiple coordinate systems and the original poster is trying to plot the vlines in the axes coordinate system. The axes coordinates are independent of the data coordinates and are fixed to the displayed axes:

    The coordinate system of the Axes; (0, 0) is bottom left of the axes, and (1, 1) is top right of the axes.

    In the expected image provided by the original poster, 0 in axes coordinates is the bottom of the displayed axes, which is supposed to be more or less at the same place as the data 9.
    image

    The bug is that instead of plotting the bottom of the line in axes coordinates (so at around data 9), it is plotting the line at 0 in data coordinates, which in turn is changing the axes to produce the incorrect example.

  11. Ailieena commented on Aug 28, 2022

    @Ailieena

    Thank you for the explanation, I understand now. I'll look into it more.

  12. modified the milestones: v3.7.0, v3.7.1 on Feb 14, 2023
  13. modified the milestones: v3.7.1, v3.7.2 on Mar 4, 2023
  14. modified the milestones: v3.7.2, v3.8.0 on Jun 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Difficulty: Mediumhttps://matplotlib.org/devdocs/devel/contribute.html#good-first-issues🌱 Good first issueOpen a pull request against these issues if there are no active ones!

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions