html_url,issue_url,id,node_id,user,created_at,updated_at,author_association,body,reactions,performed_via_github_app,issue
https://github.com/pydata/xarray/issues/4061#issuecomment-1464035444,https://api.github.com/repos/pydata/xarray/issues/4061,1464035444,IC_kwDOAMm_X85XQ2h0,60435591,2023-03-10T16:10:44Z,2023-03-10T16:10:44Z,CONTRIBUTOR,"@rjp23 with the latest update to the PR (thanks to @jklymak), your example code produced identical figures without changing it.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",,618141254
https://github.com/pydata/xarray/issues/4061#issuecomment-1456441488,https://api.github.com/repos/pydata/xarray/issues/4061,1456441488,IC_kwDOAMm_X85Wz4iQ,31730876,2023-03-06T16:20:20Z,2023-03-06T16:20:20Z,NONE,"I’m not sure that’s a solution if we argue that xarray should do what matplotlib does with the same keywords.
I can test if this “works” and will report back but it’s still not a fix.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",,618141254
https://github.com/pydata/xarray/issues/4061#issuecomment-1456434882,https://api.github.com/repos/pydata/xarray/issues/4061,1456434882,IC_kwDOAMm_X85Wz27C,60435591,2023-03-06T16:16:31Z,2023-03-06T16:16:31Z,CONTRIBUTOR,@rjp23: could you close the issue if this indeed resolves your problem?,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",,618141254
https://github.com/pydata/xarray/issues/4061#issuecomment-1446096001,https://api.github.com/repos/pydata/xarray/issues/4061,1446096001,IC_kwDOAMm_X85WMayB,60435591,2023-02-27T10:43:51Z,2023-02-27T11:16:59Z,CONTRIBUTOR,"As suggested by https://github.com/pydata/xarray/pull/7553#discussion_r1117264787, pass `levels=bounds` instead of `norm=norm` to `data.plot()`. Your example code results in a plot as expected. Would this solve your issue?
```
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import xarray
#example from https://matplotlib.org/3.1.1/tutorials/colors/colormapnorms.html
#for colormap normalisation
N = 100
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
Z = (Z1 - Z2) * 2
fig, ax = plt.subplots(2, 1, figsize=(8, 8))
ax = ax.flatten()
bounds = np.linspace(-1, 1, 10)
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=256)
ax[0].pcolormesh(X, Y, Z, norm=norm, cmap='RdBu_r')
#now add data into dataset and plot it using same normalisation
data = xarray.DataArray(Z, dims=('x', 'y'), coords={'x': X[:,0], 'y': Y[0,:]})
data.plot(ax=ax[1], x='x', y='y', levels=bounds, add_colorbar=False)
```

","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",,618141254
https://github.com/pydata/xarray/issues/4061#issuecomment-977165503,https://api.github.com/repos/pydata/xarray/issues/4061,977165503,IC_kwDOAMm_X846Ply_,33153877,2021-11-23T21:01:17Z,2021-11-23T21:01:17Z,NONE,"I also have an issue where xarray doesn't produce the correct plot when normalizing with BoundaryNorm:
```python
import xarray as xr
import matplotlib.pyplot as plt
import matplotlib.colors as colors
from cmcrameri import cm
airtemps = xr.tutorial.open_dataset(""air_temperature"")
# Convert to Celsius.
air = airtemps.air - 273.15
air.attrs = airtemps.air.attrs
air.attrs[""units""] = ""deg C""
# Select a timestep.
air2d = air.isel(time=500)
# Plotting discrete bounds with matplotlib works fine.
bounds = [x for x in range(-30, 31, 10)]
norm = colors.BoundaryNorm(boundaries=bounds, extend='both', ncolors=cm.vik.N)
fig, ax = plt.subplots()
cs = ax.pcolormesh(air2d.lon, air2d.lat, air2d, cmap=cm.vik, norm=norm)
fig.colorbar(cs)
plt.show()
# Plotting with xarray doesn't work.
fig, ax = plt.subplots()
air2d.plot.pcolormesh(ax=ax, norm=norm)
plt.show()
```
First one is from matplotlib:

Second one is from xarray:

I also get the following traceback after running the script:
```bash
Traceback (most recent call last):
File ""/home/michael/miniconda3/envs/testing_xarray/lib/python3.10/site-packages/matplotlib/cbook/__init__.py"", line 287, in process
func(*args, **kwargs)
File ""/home/michael/miniconda3/envs/testing_xarray/lib/python3.10/site-packages/matplotlib/backend_bases.py"", line 3056, in mouse_move
s = self._mouse_event_to_message(event)
File ""/home/michael/miniconda3/envs/testing_xarray/lib/python3.10/site-packages/matplotlib/backend_bases.py"", line 3048, in _mouse_event_to_message
data_str = a.format_cursor_data(data).rstrip()
File ""/home/michael/miniconda3/envs/testing_xarray/lib/python3.10/site-packages/matplotlib/artist.py"", line 1282, in format_cursor_data
neighbors = self.norm.inverse(
File ""/home/michael/miniconda3/envs/testing_xarray/lib/python3.10/site-packages/matplotlib/colors.py"", line 1832, in inverse
raise ValueError(""BoundaryNorm is not invertible"")
ValueError: BoundaryNorm is not invertible
```
Output of xr.show_versions()
INSTALLED VERSIONS
------------------
commit: None
python: 3.10.0 | packaged by conda-forge | (default, Nov 20 2021, 02:25:18) [GCC 9.4.0]
python-bits: 64
OS: Linux
OS-release: 5.14.18-300.fc35.x86_64
machine: x86_64
processor: x86_64
byteorder: little
LC_ALL: None
LANG: en_GB.UTF-8
LOCALE: ('en_GB', 'UTF-8')
libhdf5: 1.12.1
libnetcdf: 4.8.1
xarray: 0.20.1
pandas: 1.3.4
numpy: 1.21.4
scipy: 1.7.2
netCDF4: 1.5.8
pydap: None
h5netcdf: None
h5py: None
Nio: None
zarr: None
cftime: 1.5.1.1
nc_time_axis: None
PseudoNetCDF: None
rasterio: None
cfgrib: None
iris: None
bottleneck: None
dask: None
distributed: None
matplotlib: 3.5.0
cartopy: 0.20.1
seaborn: None
numbagg: None
fsspec: None
cupy: None
pint: None
sparse: None
setuptools: 59.2.0
pip: 21.3.1
conda: None
pytest: None
IPython: 7.29.0
sphinx: None
","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",,618141254
https://github.com/pydata/xarray/issues/4061#issuecomment-630280798,https://api.github.com/repos/pydata/xarray/issues/4061,630280798,MDEyOklzc3VlQ29tbWVudDYzMDI4MDc5OA==,2448579,2020-05-18T16:03:40Z,2020-05-18T16:03:40Z,MEMBER,Seems like we should do whatever mpl does when given a norm and a colormap,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",,618141254
https://github.com/pydata/xarray/issues/4061#issuecomment-629695308,https://api.github.com/repos/pydata/xarray/issues/4061,629695308,MDEyOklzc3VlQ29tbWVudDYyOTY5NTMwOA==,10194086,2020-05-16T19:30:14Z,2020-05-16T19:30:14Z,MEMBER,"That's probably gonna need a `extend=""both""`","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",,618141254
https://github.com/pydata/xarray/issues/4061#issuecomment-629689922,https://api.github.com/repos/pydata/xarray/issues/4061,629689922,MDEyOklzc3VlQ29tbWVudDYyOTY4OTkyMg==,31730876,2020-05-16T18:44:55Z,2020-05-16T18:44:55Z,NONE,"Neither of those solutions seem to work for diverging colormaps where the data extends outside the range, i.e. the < and > data ends up with no colour.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",,618141254
https://github.com/pydata/xarray/issues/4061#issuecomment-629387430,https://api.github.com/repos/pydata/xarray/issues/4061,629387430,MDEyOklzc3VlQ29tbWVudDYyOTM4NzQzMA==,10194086,2020-05-15T17:33:33Z,2020-05-15T17:33:33Z,MEMBER,"If you use
```python
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=9)
```
it works. A new norm with `ncolors=9` is built in `_build_discrete_cmap` - however, it is not used as `norm` is already defined:
https://github.com/pydata/xarray/blob/2542a63f6ebed1a464af7fc74b9f3bf302925803/xarray/plot/utils.py#L290-L292
The fix might be to use:
```python
if levels is not None or isinstance(norm, mpl.colors.BoundaryNorm):
cmap, norm = _build_discrete_cmap(cmap, levels, extend, filled)
```
this breaks one test which is probably fixable (it tests that the norm is not changed when it is given).
Note that mpl seems to use a `LinearSegmentedColormap` while xarray creates a `ListedColormap`.
","{""total_count"": 1, ""+1"": 1, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",,618141254
https://github.com/pydata/xarray/issues/4061#issuecomment-629197481,https://api.github.com/repos/pydata/xarray/issues/4061,629197481,MDEyOklzc3VlQ29tbWVudDYyOTE5NzQ4MQ==,10194086,2020-05-15T12:05:39Z,2020-05-15T12:05:39Z,MEMBER,"What should also work is `img = ds['var'].plot(ax=ax, cmap=cmap, levels=levels)`","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",,618141254
https://github.com/pydata/xarray/issues/4061#issuecomment-628619788,https://api.github.com/repos/pydata/xarray/issues/4061,628619788,MDEyOklzc3VlQ29tbWVudDYyODYxOTc4OA==,31730876,2020-05-14T13:03:12Z,2020-05-14T13:03:12Z,NONE,"It might be useful to note here that my solution for now was just to pass the arrays directly to pcolormesh rather than going through the xarray plot interface.
i.e. I changed from
`img = ds['var'].plot(ax=ax, cmap=cmap, norm=norm)`
to
`img = ax.pcolormesh(ds.x.values, ds.y.values, ds.tas.values, cmap=cmap, norm=norm)`
","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",,618141254