Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Bug]: bad autolimit behavior with fill_between and transforms #21976

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
bmcfee opened this issue Dec 16, 2021 · 3 comments
Open

[Bug]: bad autolimit behavior with fill_between and transforms #21976

bmcfee opened this issue Dec 16, 2021 · 3 comments

Comments

@bmcfee
Copy link
Contributor

bmcfee commented Dec 16, 2021

Bug summary

Using a fill_between artist with a custom transform to displace data along the y-axis, the autolimiting behavior does not work as I would expect: the axes use the non-transformed data extents. A normal line plot with the same transform does work as I would expect: autolimits match the transformed data.

Code for reproduction

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.transforms import Transform

class TransformDemo(Transform):
    
    def __init__(self):
        
        super().__init__()
        
        self.input_dims = 2
        self.output_dims = 2
        self.is_separable = False
        
    def transform_non_affine(self, values):
        output = np.empty_like(values)
        output[:, 0] = values[:, 0]
        output[:, 1] = 100 + values[:, 1] / (1 + np.abs(values[:, 0]))
        
        return output

# Make some random data
y = np.random.randn(1000)
x = np.arange(len(y))

fig, ax = plt.subplots(ncols=2)

T = TransformDemo()

# First with plot, everything works as expected
ax[0].plot(x, y, transform=T + ax[0].transData)

# With fill_between, limits are not inferred correctly
ax[1].fill_between(x, -np.abs(y), np.abs(y), transform=T + ax[1].transData)

Actual outcome

image

Expected outcome

If I force the ylimits on the second plot via

ax[1].set_ylim(ax[0].get_ylim())

it looks like
image

which is basically how I would expect.

Additional information

I'm not sure that the plot behavior is actually to spec here, but the disagreement between the two artists' behavior seems to me like a bug somewhere.

Operating system

Ubuntu

Matplotlib Version

3.5.0

Matplotlib Backend

module://matplotlib_inline.backend_inline

Python version

sys.version_info(major=3, minor=9, micro=7, releaselevel='final', serial=0)

Jupyter version

3.2.5 (dev), 3.2.4 (app)

Installation

conda

@jklymak
Copy link
Member

jklymak commented Dec 16, 2021

fill_between does a very naive autolim on its data points, but ignores the transform. We also do not appear to have a limit update method for Collections, though there may be one lurking somewhere. Collections are tricky because its not always clear how you want to auto limit them in general.

@bmcfee
Copy link
Contributor Author

bmcfee commented Dec 16, 2021

We also do not appear to have a limit update method for Collections

Ah right - I remember seeing this in the docs, and it may have been the initial motivation for my question about bypassing specific artists in limit calculations.

@anntzer
Copy link
Contributor

anntzer commented Dec 16, 2021

Re: bypassing specific artists, see #15595.

For the specific issue here, it looks like the "natural"

diff --git i/lib/matplotlib/axes/_axes.py w/lib/matplotlib/axes/_axes.py
index b8a7c3b2c6..fdc35d9335 100644
--- i/lib/matplotlib/axes/_axes.py
+++ w/lib/matplotlib/axes/_axes.py
@@ -5242,14 +5242,7 @@ default: :rc:`scatter.edgecolors`
             polys.append(pts)
 
         collection = mcoll.PolyCollection(polys, **kwargs)
-
-        # now update the datalim and autoscale
-        pts = np.row_stack([np.column_stack([ind[where], dep1[where]]),
-                            np.column_stack([ind[where], dep2[where]])])
-        if ind_dir == "y":
-            pts = pts[:, ::-1]
-        self.update_datalim(pts, updatex=True, updatey=True)
-        self.add_collection(collection, autolim=False)
+        self.add_collection(collection)
         self._request_autoscale_view()
         return collection

fixes it. It's probably worth going through all add_collection(..., autolim=False) calls and see whether the autolim=False can be removed together with a neighboring manual datalim update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants