Xarray: cmap.set_under() does not work as expected

Created on 3 Dec 2019  路  5Comments  路  Source: pydata/xarray

When using matplotlib, the set_under() method can be used to set values below the range of a colormap to a certain color, for example

import matplotlib
from matplotlib import pyplot
import numpy

dat = numpy.linspace(0, 1)[numpy.newaxis, :]*numpy.linspace(0, 1)[:, numpy.newaxis]

cmap = matplotlib.cm.viridis
#cmap.set_under('w')

pyplot.contourf(dat, vmin=.3, cmap=cmap)
pyplot.colorbar()
pyplot.show()

produces
matplotlib_no-set_under

while uncommenting the cmap.set_under() call produces
matplotlib

However, using xarray to do the same thing,

import matplotlib
from matplotlib import pyplot
from xarray import DataArray
import numpy

da = DataArray(numpy.linspace(0, 1)[numpy.newaxis, :]*numpy.linspace(0, 1)[:, numpy.newaxis])

cmap = matplotlib.cm.viridis
cmap.set_under('w')

da.plot.contourf(vmin=.3, cmap=cmap)
pyplot.show()

produces
xarray
where it seems the call to cmap.set_under('w') had no effect. Expected behaviour would be output like the second plot.

Output of xr.show_versions()

In [2]: xarray.show_versions()                                                                                                                                                                                                                

INSTALLED VERSIONS
------------------
commit: None
python: 3.6.9 (default, Nov  7 2019, 10:44:02) 
[GCC 8.3.0]
python-bits: 64
OS: Linux
OS-release: 5.0.0-37-generic
machine: x86_64
processor: x86_64
byteorder: little
LC_ALL: None
LANG: en_GB.UTF-8
LOCALE: en_GB.UTF-8
libhdf5: 1.10.0
libnetcdf: 4.6.0

xarray: 0.14.1
pandas: 0.24.2
numpy: 1.16.3
scipy: 1.2.1
netCDF4: 1.3.1
pydap: None
h5netcdf: None
h5py: 2.9.0
Nio: None
zarr: None
cftime: None
nc_time_axis: None
PseudoNetCDF: None
rasterio: None
cfgrib: None
iris: None
bottleneck: None
dask: 2.1.0
distributed: None
matplotlib: 3.1.1
cartopy: None
seaborn: None
numbagg: None
setuptools: 41.0.1
pip: 19.3.1
conda: None
pytest: 4.4.1
IPython: 7.6.1
sphinx: None

bug plotting

All 5 comments

Thanks for the report @johnomotani. I expect we are recreating the colormap from scratch somewhere in plot/utils.py

Might be somethnig to do with
https://github.com/pydata/xarray/blob/ed05f9862622b00f40f7b9b99ccdb0ab3766ff0f/xarray/plot/dataset_plot.py#L137
?

The docstring for matplotlib.colors.Normalize says

If clip is True, masked values are set to 1; otherwise they remain masked. Clipping silently defeats the purpose of setting the over, under, and masked colors in the colormap, so it is likely to lead to surprises; therefore the default is clip = False.

No that's for dataset plotting and is a norm for size of points plotted by scatter.

I would look here:
https://github.com/pydata/xarray/blob/ed05f9862622b00f40f7b9b99ccdb0ab3766ff0f/xarray/plot/utils.py#L77-L101

Looks like that was it, thanks @dcherian!

As a workaround (until #3601) is finished you can do:

import matplotlib
from matplotlib import pyplot
from xarray import DataArray
import numpy

da = DataArray(numpy.linspace(0, 1)[numpy.newaxis, :]*numpy.linspace(0, 1)[:, numpy.newaxis])

cmap = matplotlib.cm.viridis

h = da.plot.contourf(vmin=.3, cmap=cmap)

cmap = h.get_cmap()
cmap.set_under('w')

h.set_cmap(cmap)
Was this page helpful?
0 / 5 - 0 ratings