Skip to content

xarray imshow and pcolormesh behave badly when the array does not contain values larger the BoundaryNorm vmax #7014

Closed
@ghiggi

Description

@ghiggi

What happened?

If cmap.set_over is specified, the array color mapping and the colorbar behave badly if the array does not contain values above the norm.vmax.

Let's take an array and apply a colormap and norm (see code below)
image
Now, if in the array I change the array values larger than the norm.vmax (the 2 bottom right pixels) with other values inside the norm:

  • Using matplotlib I get the expected results
    image
  • Using xarray I get this weird behavior.
    image

What did you expect to happen?

The colorbar should not "shift" and the array should be colormapped correctly
This is possibily related also to #4061

Minimal Complete Verifiable Example

import matplotlib.colors
import numpy as np
import xarray as xr 
import matplotlib as mpl 
import matplotlib.pyplot as plt

# Define DataArray 
arr = np.array([[0, 10, 15, 20],
                [ np.nan, 40, 50, 100], 
                [150, 158, 160, 161],
               ])
lon = np.arange(arr.shape[1])
lat = np.arange(arr.shape[0])[::-1]
lons, lats = np.meshgrid(lon, lat)
da = xr.DataArray(arr,
                  dims=["y", "x"],
                  coords={"lon": (("y","x"), lons),
                          "lat": (("y","x"), lats),
                          }
                  )
da

# Define colormap  
color_list = ["#9c7e94", "#640064",   "#009696", "#C8FF00",  "#FF7D00"]
levels =  [0.05, 1, 10, 20, 150, 160]
cmap = mpl.colors.LinearSegmentedColormap.from_list("cmap", color_list, len(levels) - 1)
norm = mpl.colors.BoundaryNorm(levels, cmap.N)
cmap.set_over("darkred")   # color for above 160
cmap.set_under("none")     # color for below 0.05
cmap.set_bad("gray", 0.2)  # color for nan 

# Define colorbar settings 
ticks = levels 
cbar_kwargs = {     
    'extend': "max",  
     
}    

# Correct plot 
p = da.plot.pcolormesh(x="lon", y="lat", cmap=cmap, norm=norm, cbar_kwargs=cbar_kwargs)
plt.show()

# Remove values larger than the norm.vmax level
da1 = da.copy() 
da1.data[da1.data>=norm.vmax] = norm.vmax - 1 # could be replaced with any value inside the norm 

# With matplotlib.pcolormesh [OK]
p = plt.pcolormesh(da1["lon"].data, 
                   da1["lat"],
                   da1.data, 
                   cmap=cmap, norm=norm)
plt.colorbar(p, **cbar_kwargs)
plt.show()

# With matplotlib.imshow [OK]
p = plt.imshow(da1.data, 
               cmap=cmap, norm=norm)
plt.colorbar(p, **cbar_kwargs)
plt.show()

# With xarray.pcolormesh [BUG]
# --> The colorbar shift !!!  
da1.plot.pcolormesh(x="lon", y="lat", cmap=cmap, norm=norm, cbar_kwargs=cbar_kwargs)
plt.show()

# With xarray.imshow [BUG]
# --> The colorbar shift !!!
da1.plot.imshow(cmap=cmap, norm=norm, cbar_kwargs=cbar_kwargs, origin="upper")

MVCE confirmation

  • Minimal example — the example is as focused as reasonably possible to demonstrate the underlying issue in xarray.
  • Complete example — the example is self-contained, including all data and the text of any traceback.
  • Verifiable example — the example copy & pastes into an IPython prompt or Binder notebook, returning the result.
  • New issue — a search of GitHub Issues suggests this is not a duplicate.

Relevant log output

No response

Anything else we need to know?

No response

Environment

INSTALLED VERSIONS

commit: None
python: 3.9.13 | packaged by conda-forge | (main, May 27 2022, 16:56:21)
[GCC 10.3.0]
python-bits: 64
OS: Linux
OS-release: 5.4.0-124-generic
machine: x86_64
processor: x86_64
byteorder: little
LC_ALL: None
LANG: en_US.UTF-8
LOCALE: ('en_US', 'UTF-8')
libhdf5: 1.12.1
libnetcdf: 4.8.1

xarray: 2022.6.0
pandas: 1.4.3
numpy: 1.22.4
scipy: 1.9.0
netCDF4: 1.6.0
pydap: None
h5netcdf: 1.0.2
h5py: 3.7.0
Nio: None
zarr: 2.12.0
cftime: 1.6.1
nc_time_axis: None
PseudoNetCDF: None
rasterio: 1.3.0
cfgrib: None
iris: None
bottleneck: 1.3.5
dask: 2022.7.1
distributed: 2022.7.1
matplotlib: 3.5.2
cartopy: 0.20.3
seaborn: 0.11.2
numbagg: None
fsspec: 2022.7.1
cupy: None
pint: 0.19.2
sparse: None
flox: None
numpy_groupies: None
setuptools: 63.3.0
pip: 22.2.2
conda: None
pytest: None
IPython: 7.33.0
sphinx: 5.1.1
/home/ghiggi/anaconda3/envs/gpm_geo/lib/python3.9/site-packages/_distutils_hack/init.py:33: UserWarning: Setuptools is replacing distutils.
warnings.warn("Setuptools is replacing distutils.")

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugneeds triageIssue that has not been reviewed by xarray team member

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions