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
{{ message }}
Repository navigation
Inconsistency with behavior of extent and origin in imshow() #8693
Following a brief discussion on Gitter, I've decided to open an issue here but I'm not 100% sure if this is a bug or intended behavior. The following script compares the usage of origin and extent when the limits are fixed to the same intervals and same axis direction:
As you can see, when no extent is specified, the origin keyword has no impact on the result whereas it does when the extent is specified.
There is either a bug here, or something that exists for historical reasons that deserves its own documentation section.
In any case, the documentation for origin doesn't make much sense:
origin : ['upper' | 'lower'], optional, default: None
Place the [0,0] index of the array in the upper left or lower left
corner of the axes. If None, default to rc `image.origin`.
the concept of 'upper left' or 'lower left' is tricky since the axes can be made to go in either direction, so whether [0,0] is at the upper or lower corner visually depends on the direction of the axes.
It seems that when extent is not specified, origin simply means that the y limits are flipped but this can be reverted by setting ylim. When extent is present, the array is truly flipped vertically.
Yes, this is about as confusing as an API plus documentation can get. I suspect that what we have to do is figure out what the code is actually doing, and then figure out how to describe that in the docstring without making the reader's head spin. I am assuming that the behavior hasn't changed any time recently, but that needs to be checked.
Note that this example involves the interaction of origin, extent, and manual setting of xlim and ylim. I think that the xlim and ylim parts are turning a moderately confusing API into a hopelessly confusing one.
Maybe we will need to come up with a new name and a new, comprehensible, API.
I've often seen this happening and I actually never considered it to be an issue. To my understanding, when setting the origin to upper, the limits as well as the extent have to be inverted in y direction.
im = ax.imshow(image, interpolation='nearest', origin=origin,extent=extent )
ax.set_xlim(0, 10)
if origin == "upper":
ax.set_ylim(10, 0)
if extent:
im.set_extent(extent[:2] + extent[2:][::-1])
else:
ax.set_ylim(0,10)
Only setting the extent, but not the ylim works fine, as well as not setting the ylim but the extent. Just, if you decide to set any of them, invert the y coordinate when using origin=upper.
So I guess the sentence in the docstring could be
"If you set origin to "upper" any y coordinates you may specify using extent and/or ylim need to be reversed."
I think there is a fundamental issue with the "origin" system, in that it assumes that a there will be a single image artist in the axes that will get to decide how to pick the axes limits. We then get inconsistencies when the limits are specified (or not) using the extent kwarg at the same time, or I guess funny things can happen too if we have two images in the same axes that have different choices of origin... See also discussion at #7471 for a similar problem: artists can provide hints as to how to layout their containing axes, but they should typically not force that layout (otherwise, there can be conflicts with another artist).
Of course, I am not suggesting to get rid of the "origin" system (which is more intuitive than manually setting the ylims to (top, bottom) instead of (bottom, top)). But a possibility would be...
when the AxesImage is created, the origin attribute is set normally.
when Axes.add_image is called, we read the origin attribute; depending on its value, we invert or not the ylims (so the last added image indeed wins... not sure there's much that can be done about it).
the origin attribute of AxesImage becomes a read-only property; before being added to an Axes, it returns the originally set value; but after being added to an Axes, it simply returns whether the Axes have inverted ylims or not.
Note that this is only somewhat related to the issue at hand, which is probably due to the following snippet:
def get_extent(self):
"""Get the image extent: left, right, bottom, top"""
if self._extent is not None:
return self._extent
else:
sz = self.get_size()
numrows, numcols = sz
if self.origin == 'upper':
return (-0.5, numcols-0.5, numrows-0.5, -0.5)
else:
return (-0.5, numcols-0.5, -0.5, numrows-0.5)
so origin is indeed (incorrectly, IMO) ignored when extent is specified...
Related to this issue, I came across the following example when I was trying to create my own custom plots using imshow. I found this a little confusing that setting the y-limits would completely flip the image that's output.
import numpy as np
from matplotlib import pyplot as plt
imm = np.array([[0, 1, 2, 3],
[1, 1, 2, 3],
[2, 2, 2, 3],
[3, 3, 3, 3]])
fig, ax = plt.subplots(ncols = 2)
for i in range(2):
ax[i].imshow(imm, cmap = 'hot', vmin = 0, vmax = 5)
ax[1].set_ylim([-0.5, 3.5])
plt.show()
not sure what exactly you find confusing there. By default, when you do an
imshow, the pixel for coordinate (0,0) is in the top-left corner. This is
true for every single plotting and drawing API I have ever encountered. In
the second axes, you explicitly stated the order of the y-axis limits,
which matplotlib obeyed. You could have done, `ax[1].set_ylim([3.5,
-0.5])`, and it would have looked like the first one.
yes, it is a very useful feature for meteorologists who want to plot
something with pressure as the vertical coordinate (pressure is greater at
the surface). You can do the same with the x limits, and the z-limits as
well for mplot3d.
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!
Activity
efiring commentedon May 31, 2017
Yes, this is about as confusing as an API plus documentation can get. I suspect that what we have to do is figure out what the code is actually doing, and then figure out how to describe that in the docstring without making the reader's head spin. I am assuming that the behavior hasn't changed any time recently, but that needs to be checked.
Note that this example involves the interaction of origin, extent, and manual setting of xlim and ylim. I think that the xlim and ylim parts are turning a moderately confusing API into a hopelessly confusing one.
Maybe we will need to come up with a new name and a new, comprehensible, API.
ImportanceOfBeingErnest commentedon Jun 1, 2017
I've often seen this happening and I actually never considered it to be an issue. To my understanding, when setting the
originto upper, the limits as well as the extent have to be inverted in y direction.Only setting the extent, but not the ylim works fine, as well as not setting the ylim but the extent. Just, if you decide to set any of them, invert the y coordinate when using origin=upper.
So I guess the sentence in the docstring could be
anntzer commentedon Jun 1, 2017
I think there is a fundamental issue with the "origin" system, in that it assumes that a there will be a single image artist in the axes that will get to decide how to pick the axes limits. We then get inconsistencies when the limits are specified (or not) using the extent kwarg at the same time, or I guess funny things can happen too if we have two images in the same axes that have different choices of origin... See also discussion at #7471 for a similar problem: artists can provide hints as to how to layout their containing axes, but they should typically not force that layout (otherwise, there can be conflicts with another artist).
Of course, I am not suggesting to get rid of the "origin" system (which is more intuitive than manually setting the ylims to (top, bottom) instead of (bottom, top)). But a possibility would be...
Note that this is only somewhat related to the issue at hand, which is probably due to the following snippet:
so origin is indeed (incorrectly, IMO) ignored when extent is specified...
p-robot commentedon Sep 27, 2017
Related to this issue, I came across the following example when I was trying to create my own custom plots using
imshow. I found this a little confusing that setting the y-limits would completely flip the image that's output.WeatherGod commentedon Sep 27, 2017
p-robot commentedon Sep 27, 2017
Whoops, I wasn't aware
set_ylimcould flip the y axis.WeatherGod commentedon Sep 27, 2017
Fix blobs on rect lattice and axis lim bug
github-actions commentedon Apr 12, 2023
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!
jklymak commentedon Apr 12, 2023
We now have a whole tutorial on this. I'll close this.