Unable to use aspect="equal" in plot.imshow() whereas option is given in the doc
What is your issue?
I'm using the version 2023.12.0.
In the doc of imshow (https://docs.xarray.dev/en/stable/generated/xarray.DataArray.plot.imshow.html) it is written for the aspect parameter:
aspect ("auto", "equal", scalar or None, optional) – Aspect ratio of plot, so that aspect * size gives the width in inches. Only used if a size is provided.
But if I try this simple code:
import xarray as xr
import numpy as np
import matplotlib.pyplot as plt
data_array = np.random.randint(0, 255, size=(3, 2), dtype=np.uint8)
xarray_data = xr.DataArray(data_array, dims=('dim1', 'dim2'))
xarray_data.plot.imshow(size=5, aspect="equal")
plt.show()
I get the following error:
...
File "...\lib\site-packages\xarray\plot\dataarray_plot.py", line 1598, in newplotfunc
raise ValueError("plt.imshow's `aspect` kwarg is not available in xarray")
ValueError: plt.imshow's `aspect` kwarg is not available in xarray
Indeed in the code here there is:
if "imshow" == plotfunc.__name__ and isinstance(aspect, str):
# forbid usage of mpl strings
raise ValueError("plt.imshow's `aspect` kwarg is not available in xarray")
which seems quite clear.
So is there something I'm doing wrong or is it an issue between doc and code ? Thanks !
Thanks for opening your first issue here at xarray! Be sure to follow the issue template! If you have an idea for a solution, we would really welcome a Pull Request with proposed changes. See the Contributing Guide for more. It may take us a while to respond here, but we really value your contribution. Contributors like you help make xarray better. Thank you!
@aspyk Thanks for raising this. I've followed the code to the PR, where this was introduced: https://github.com/pydata/xarray/pull/1168. It looks like there's a reason to not have aspect forwarded to imshow as a string, so I'm assuming that there is a slight inconsistency with the docstring.
You could still provide the aspect as scalar value (eg. 1.0). I've no detailed knowledge of xarray's plotting, so appreciate comments of others here.
Thanks for your quick answer. I just tried the aspect as scalar value but it doesn't seem to "lock" the aspect ratio, when I resize dynamically the window the aspect ratio follow the resizing and does not keep its initial value :/
@aspyk Let's wait for some more informed opinions here.
You might use plt.gca().axes.set_aspect('equal', 'box') before show to work around this (no resizing tested). See https://stackoverflow.com/questions/2934878/matplotlib-pyplot-preserve-aspect-ratio-of-the-plot
Thank, it works nice! In my case I have several axis, so I'm ended with this:
ax = xarray_data.plot.imshow()
ax.axes.set_aspect("equal")
plt.show()
Indeed the trick was to apply set_aspect to ax.axes and not only ax...
Same issue here. After checking the error message and the source code. aspect works differently in xarray and matplotlib. In matplotlib imshow, aspect controls the axis ratio, while in xarray the figure size ratio. That's why xarray raise an error when we try to pass 'equal' to aspect. Xarray did not impl axis ratio control for its imshow, so we have to control by mpl ourself as suggested by @kmuehlbauer
@aspyk Let's wait for some more informed opinions here.
You might use
plt.gca().axes.set_aspect('equal', 'box')before show to work around this (no resizing tested). See https://stackoverflow.com/questions/2934878/matplotlib-pyplot-preserve-aspect-ratio-of-the-plot