Skip to content

[Bug]: transform keyword in ax.plot(...) #21008

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

Closed
kovalp opened this issue Sep 7, 2021 · 8 comments · Fixed by #21017
Closed

[Bug]: transform keyword in ax.plot(...) #21008

kovalp opened this issue Sep 7, 2021 · 8 comments · Fixed by #21017

Comments

@kovalp
Copy link

kovalp commented Sep 7, 2021

Bug summary

The keyword argument transform of the method ax.plot(...) malfunctions with size of the samples greater than 1000.

For example, the following script

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


ax = plt.gca()

xx = np.linspace(0.0, 4 * np.pi, num=1001)
yy = np.cos(xx)

t = transforms.Affine2D().translate(10.0, 0.0).scale(2.0, 0.5)

lines = ax.plot(xx, yy, transform=t + ax.transData)

plt.show()

Produces an expected figure

Figure_1000

with num=1000

and an empty figure

Figure_1001

with num=1001.

Code for reproduction

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


ax = plt.gca()

xx = np.linspace(0.0, 4 * np.pi, num=1001)
yy = np.cos(xx)

t = transforms.Affine2D().translate(10.0, 0.0).scale(2.0, 0.5)

lines = ax.plot(xx, yy, transform=t + ax.transData)

plt.show()

Actual outcome

Figure_1001

Expected outcome

Figure_1000

Operating system

Linux

Matplotlib Version

3.4.3

Matplotlib Backend

Qt5Agg

Python version

Python 3.8.7

Jupyter version

No response

Other libraries

No response

Installation

pip

Conda channel

No response

@jklymak
Copy link
Member

jklymak commented Sep 7, 2021

I agree this seems like a bug. It is very strange in that scatter works fine, so it is something in how plot is applying the transform

@jklymak
Copy link
Member

jklymak commented Sep 7, 2021

This is due to

if (self.axes and len(x) > 1000 and self._is_sorted(x) and

causing a slicing of the data if the size is greater than 1000 (hard coded!) and then the slicing only happening in the view window, which has been transformed. i.e. your data goes from 0 to 4pi, but the window goes from 20 to 20 + 4pi. So all the data is sliced away, and nothing is plotted.

I'm not sure what the todo is here. My tendency would be to just remove the slicing under the hope that modern machines don't need this optimization. As you can see it is only applied in a very limited set of circumstances. Conversely, one could (should) apply the transform to the data first, but that is a bit ugly.

This optimization was last touched 12 years ago.

@kovalp
Copy link
Author

kovalp commented Sep 7, 2021 via email

@anntzer
Copy link
Contributor

anntzer commented Sep 7, 2021

I would just add a check to restrict the optimization to the case where self.get_transform() == self.axes.transData, I guess.

@jklymak
Copy link
Member

jklymak commented Sep 7, 2021

Yeah that's reasonable as well. OTOH it's a pretty specialized optimization.

@kovalp
Copy link
Author

kovalp commented Sep 7, 2021

This is due to

if (self.axes and len(x) > 1000 and self._is_sorted(x) and

Gosh, this is deep. The condition to allow for the optimization turned out not sufficiently excluding after all.

When I found this bug, the outcome of the plotting was not obviously wrong. Namely, I used the transform to account for the units. When up-scaling (smaller units), the plot appeared as expected, but when down-scaling, the plot was visible, but smaller that the original and cut.

This made me think that I am not getting some matplotlib argument right. However, when the 1000 threshold appeared, things become more certain.

@jklymak
Copy link
Member

jklymak commented Sep 7, 2021

We should totally fix this, but the question is if we a) remove the optimization or if we b) add yet another exclusion to it? I guess I prefer a), though that is a breaking change.

@kovalp
Copy link
Author

kovalp commented Sep 7, 2021

I guess we need a benchmark to have the full picture.

@QuLogic QuLogic added this to the v3.4.4 milestone Sep 9, 2021
@QuLogic QuLogic modified the milestones: v3.4.4, v3.5.0 Nov 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants