Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Surface plots #5101

Merged
merged 33 commits into from
May 3, 2021
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
3ad10d9
Use broadcast_like for 2d plot coordinates
johnomotani Mar 31, 2021
17151d1
Update whats-new
johnomotani Mar 31, 2021
38220a6
Implement 'surface()' plot function
johnomotani Mar 31, 2021
0ce6941
Make surface plots work with facet grids
johnomotani Mar 31, 2021
c7dbdf1
Unit tests for surface plot
johnomotani Mar 31, 2021
bc0c85a
Minor fixes for surface plots
johnomotani Mar 31, 2021
d31e193
Add surface plots to api.rst and api-hidden.rst
johnomotani Mar 31, 2021
7acce7e
Update whats-new
johnomotani Mar 31, 2021
1e4ff18
Fix tests
johnomotani Apr 1, 2021
e12b7ce
mypy fix
johnomotani Apr 1, 2021
266bd4a
seaborn doesn't work with matplotlib 3d toolkit
johnomotani Apr 1, 2021
e3de64f
Remove cfdatetime surface plot test
johnomotani Apr 1, 2021
82c708e
Ignore type checks for mpl_toolkits module
johnomotani Apr 1, 2021
f27aa45
Check matplotlib version is new enough for surface plots
johnomotani Apr 1, 2021
b0a1f40
version check requires matplotlib
johnomotani Apr 1, 2021
e592e5e
Handle matplotlib not installed for TestSurface version check
johnomotani Apr 1, 2021
43a51e9
fix flake8 error
johnomotani Apr 1, 2021
ea43177
Don't run test_plot_transposed_nondim_coord for surface plots
johnomotani Apr 1, 2021
648e13b
Apply suggestions from code review
johnomotani Apr 20, 2021
313daf0
More suggestions from code review
johnomotani Apr 20, 2021
a566744
black
johnomotani Apr 20, 2021
817d305
isort and flake8
johnomotani Apr 20, 2021
99459cc
Make surface plots more backward compatible
johnomotani Apr 20, 2021
f86f76d
Clean up matplotlib requirement
johnomotani Apr 21, 2021
7b6f470
Update xarray/plot/plot.py
johnomotani Apr 27, 2021
efdc140
Merge branch 'master' into surface-plots
johnomotani Apr 27, 2021
518110c
Apply suggestions from code review
johnomotani Apr 28, 2021
84b3e6d
Use None as default value
johnomotani Apr 28, 2021
08b9117
black
johnomotani Apr 28, 2021
c964848
More 2D plotting method examples in docs
johnomotani Apr 29, 2021
50152b3
Fix docs
johnomotani Apr 29, 2021
4831b8b
[skip-ci] Make example surface plot look a bit nicer
johnomotani Apr 29, 2021
cf9c49a
Merge branch 'master' into surface-plots
mathause May 3, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/api-hidden.rst
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,7 @@
plot.imshow
plot.pcolormesh
plot.scatter
plot.surface

plot.FacetGrid.map_dataarray
plot.FacetGrid.set_titles
Expand Down
1 change: 1 addition & 0 deletions doc/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,7 @@ Plotting
DataArray.plot.line
DataArray.plot.pcolormesh
DataArray.plot.step
DataArray.plot.surface

.. _api.ufuncs:

Expand Down
6 changes: 6 additions & 0 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ v0.17.1 (unreleased)
New Features
~~~~~~~~~~~~

- Add :py:meth:`DataArray.plot.surface` which wraps matplotlib's `plot_surface` to make
surface plots (:issue:`#2235` :issue:`#5084` :pull:`5101`).
By `John Omotani <https://github.com/johnomotani>`_.
- Add :py:meth:`Dataset.query` and :py:meth:`DataArray.query` which enable indexing
of datasets and data arrays by evaluating query expressions against the values of the
data variables (:pull:`4984`). By `Alistair Miles <https://github.com/alimanfoo>`_.
Expand Down Expand Up @@ -78,6 +81,9 @@ Deprecations

Bug fixes
~~~~~~~~~
- Fix 2d plot failure for certain combinations of dimensions when `x` is 1d and `y` is
2d (:issue:`5079`, :pull:`5099`).
By `John Omotani <https://github.com/johnomotani>`_
johnomotani marked this conversation as resolved.
Show resolved Hide resolved
- Ensure standard calendar times encoded with large values (i.e. greater than approximately 292 years), can be decoded correctly without silently overflowing (:pull:`5050`). This was a regression in xarray 0.17.0. By `Zeb Nicholls <https://github.com/znicholls>`_.
- Added support for `numpy.bool_` attributes in roundtrips using `h5netcdf` engine with `invalid_netcdf=True` [which casts `bool`s to `numpy.bool_`] (:issue:`4981`, :pull:`4986`).
By `Victor Negîrneac <https://github.com/caenrigen>`_.
Expand Down
3 changes: 2 additions & 1 deletion xarray/plot/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .dataset_plot import scatter
from .facetgrid import FacetGrid
from .plot import contour, contourf, hist, imshow, line, pcolormesh, plot, step
from .plot import contour, contourf, hist, imshow, line, pcolormesh, plot, step, surface

__all__ = [
"plot",
Expand All @@ -13,4 +13,5 @@
"pcolormesh",
"FacetGrid",
"scatter",
"surface",
]
4 changes: 3 additions & 1 deletion xarray/plot/facetgrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,9 @@ def map_dataarray(self, func, x, y, **kwargs):
if k not in {"cmap", "colors", "cbar_kwargs", "levels"}
}
func_kwargs.update(cmap_params)
func_kwargs.update({"add_colorbar": False, "add_labels": False})
func_kwargs["add_colorbar"] = False
if func.__name__ != "surface":
func_kwargs["add_labels"] = False

# Get x, y labels for the first subplot
x, y = _infer_xy_labels(
Expand Down
84 changes: 61 additions & 23 deletions xarray/plot/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,9 @@ def newplotfunc(

# Decide on a default for the colorbar before facetgrids
if add_colorbar is None:
add_colorbar = plotfunc.__name__ != "contour"
add_colorbar = plotfunc.__name__ != "contour" and not (
plotfunc.__name__ == "surface" and cmap is None
)
johnomotani marked this conversation as resolved.
Show resolved Hide resolved
imshow_rgb = plotfunc.__name__ == "imshow" and darray.ndim == (
3 + (row is not None) + (col is not None)
)
Expand All @@ -646,6 +648,24 @@ def newplotfunc(
darray = _rescale_imshow_rgb(darray, vmin, vmax, robust)
vmin, vmax, robust = None, None, False

if subplot_kws is None:
subplot_kws = dict()

if plotfunc.__name__ == "surface" and not kwargs.get("_is_facetgrid", False):
if ax is None:
# TODO: Importing Axes3D is not necessary in matplotlib >= 3.2.
johnomotani marked this conversation as resolved.
Show resolved Hide resolved
# Remove when minimum requirement of matplotlib is 3.2:
from mpl_toolkits.mplot3d import Axes3D # type: ignore # noqa: F401

del Axes3D
johnomotani marked this conversation as resolved.
Show resolved Hide resolved

# Need to create a "3d" Axes instance for surface plots
subplot_kws["projection"] = "3d"

# In facet grids, shared axis labels don't make sense for surface plots
sharex = False
sharey = False

# Handle facetgrids first
if row or col:
allargs = locals().copy()
Expand All @@ -658,6 +678,19 @@ def newplotfunc(

plt = import_matplotlib_pyplot()

if (
plotfunc.__name__ == "surface"
and not kwargs.get("_is_facetgrid", False)
and ax is not None
):
import mpl_toolkits # type: ignore

if not isinstance(ax, mpl_toolkits.mplot3d.Axes3D):
raise ValueError(
"If ax is passed to surface(), it must be created with "
'projection="3d"'
)

rgb = kwargs.pop("rgb", None)
if rgb is not None and plotfunc.__name__ != "imshow":
raise ValueError('The "rgb" keyword is only valid for imshow()')
Expand All @@ -671,28 +704,22 @@ def newplotfunc(
darray=darray, x=x, y=y, imshow=imshow_rgb, rgb=rgb
)

# better to pass the ndarrays directly to plotting functions
xval = darray[xlab].values
yval = darray[ylab].values

# check if we need to broadcast one dimension
if xval.ndim < yval.ndim:
dims = darray[ylab].dims
if xval.shape[0] == yval.shape[0]:
xval = np.broadcast_to(xval[:, np.newaxis], yval.shape)
else:
xval = np.broadcast_to(xval[np.newaxis, :], yval.shape)
xval = darray[xlab]
yval = darray[ylab]

elif yval.ndim < xval.ndim:
dims = darray[xlab].dims
if yval.shape[0] == xval.shape[0]:
yval = np.broadcast_to(yval[:, np.newaxis], xval.shape)
else:
yval = np.broadcast_to(yval[np.newaxis, :], xval.shape)
elif xval.ndim == 2:
dims = darray[xlab].dims
if xval.ndim > 1 or yval.ndim > 1 or plotfunc.__name__ == "surface":
# Passing 2d coordinate values, need to ensure they are transposed the same
# way as darray.
# Also surface plots always need 2d coordinates
xval = xval.broadcast_like(darray)
yval = yval.broadcast_like(darray)
dims = darray.dims
else:
dims = (darray[ylab].dims[0], darray[xlab].dims[0])
dims = (yval.dims[0], xval.dims[0])

# better to pass the ndarrays directly to plotting functions
xval = xval.values
yval = yval.values

# May need to transpose for correct x, y labels
# xlab may be the name of a coord, we have to check for dim names
Expand Down Expand Up @@ -741,8 +768,6 @@ def newplotfunc(
# forbid usage of mpl strings
raise ValueError("plt.imshow's `aspect` kwarg is not available in xarray")

if subplot_kws is None:
subplot_kws = dict()
ax = get_axis(figsize, size, aspect, ax, **subplot_kws)

primitive = plotfunc(
Expand All @@ -762,6 +787,8 @@ def newplotfunc(
ax.set_xlabel(label_from_attrs(darray[xlab], xlab_extra))
ax.set_ylabel(label_from_attrs(darray[ylab], ylab_extra))
ax.set_title(darray._title_for_slice())
if plotfunc.__name__ == "surface":
ax.set_zlabel(label_from_attrs(darray))

if add_colorbar:
if add_labels and "label" not in cbar_kwargs:
Expand Down Expand Up @@ -994,3 +1021,14 @@ def pcolormesh(x, y, z, ax, infer_intervals=None, **kwargs):
ax.set_ylim(y[0], y[-1])

return primitive


@_plot2d
def surface(x, y, z, ax, **kwargs):
"""
Surface plot of 2d DataArray

Wraps :func:`matplotlib:mpl_toolkits.mplot3d.axes3d.plot_surface`
"""
primitive = ax.plot_surface(x, y, z, **kwargs)
return primitive
8 changes: 8 additions & 0 deletions xarray/plot/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,14 @@ def _process_cmap_cbar_kwargs(
cmap_params
cbar_kwargs
"""
if func.__name__ == "surface":
# Leave user to specify cmap settings for surface plots
mathause marked this conversation as resolved.
Show resolved Hide resolved
kwargs["cmap"] = cmap
return {
k: kwargs.get(k, None)
for k in ["vmin", "vmax", "cmap", "extend", "levels", "norm"]
}, {}

cbar_kwargs = {} if cbar_kwargs is None else dict(cbar_kwargs)

if "contour" in func.__name__ and levels is None:
Expand Down
3 changes: 3 additions & 0 deletions xarray/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ def LooseVersion(vstring):


has_matplotlib, requires_matplotlib = _importorskip("matplotlib")
has_matplotlib_3_3_0, requires_matplotlib_3_3_0 = _importorskip(
"matplotlib", minversion="3.3.0"
)
has_scipy, requires_scipy = _importorskip("scipy")
has_pydap, requires_pydap = _importorskip("pydap.client")
has_netCDF4, requires_netCDF4 = _importorskip("netCDF4")
Expand Down
112 changes: 109 additions & 3 deletions xarray/tests/test_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import inspect
from copy import copy
from datetime import datetime
from typing import Any, Dict

import numpy as np
import pandas as pd
Expand All @@ -28,6 +29,7 @@
requires_cartopy,
requires_cftime,
requires_matplotlib,
requires_matplotlib_3_3_0,
requires_nc_time_axis,
requires_seaborn,
)
Expand All @@ -36,6 +38,7 @@
try:
import matplotlib as mpl
import matplotlib.pyplot as plt
import mpl_toolkits # type: ignore
except ImportError:
pass

Expand Down Expand Up @@ -132,8 +135,9 @@ def setup(self):
# Remove all matplotlib figures
plt.close("all")

def pass_in_axis(self, plotmethod):
fig, axes = plt.subplots(ncols=2)
def pass_in_axis(self, plotmethod, subplot_kw=None):
subplot_kw = {} if subplot_kw is None else subplot_kw
johnomotani marked this conversation as resolved.
Show resolved Hide resolved
fig, axes = plt.subplots(ncols=2, subplot_kw=subplot_kw)
plotmethod(ax=axes[0])
assert axes[0].has_data()

Expand Down Expand Up @@ -1079,6 +1083,9 @@ class Common2dMixin:
Should have the same name as the method.
"""

# Needs to be overridden in TestSurface for facet grid plots
subplot_kws: Dict[Any, Any] = {}
johnomotani marked this conversation as resolved.
Show resolved Hide resolved

@pytest.fixture(autouse=True)
def setUp(self):
da = DataArray(
Expand Down Expand Up @@ -1394,7 +1401,7 @@ def test_colorbar_kwargs(self):
def test_verbose_facetgrid(self):
a = easy_array((10, 15, 3))
d = DataArray(a, dims=["y", "x", "z"])
g = xplt.FacetGrid(d, col="z")
g = xplt.FacetGrid(d, col="z", subplot_kws=self.subplot_kws)
g.map_dataarray(self.plotfunc, "x", "y")
for ax in g.axes.flat:
assert ax.has_data()
Expand Down Expand Up @@ -1794,6 +1801,105 @@ def test_origin_overrides_xyincrease(self):
assert plt.ylim()[0] < 0


# The try/except/else is needed for the matplotlib version check, to handle the case
# when matplotlib is not installed. It should be possible to remove it once we require
# matplotlib>=3.2.0.
# Note, importing as mpl2 to avoid redefining mpl, which is a flake8 error.
try:
import matplotlib as mpl2 # noqa: F401
except ImportError:
pass
else:

class TestSurface(Common2dMixin, PlotTestCase):

plotfunc = staticmethod(xplt.surface)
subplot_kws = {"projection": "3d"}

def test_primitive_artist_returned(self):
artist = self.plotmethod()
assert isinstance(artist, mpl_toolkits.mplot3d.art3d.Poly3DCollection)

@pytest.mark.slow
def test_2d_coord_names(self):
self.plotmethod(x="x2d", y="y2d")
# make sure labels came out ok
ax = plt.gca()
assert "x2d" == ax.get_xlabel()
assert "y2d" == ax.get_ylabel()
assert f"{self.darray.long_name} [{self.darray.units}]" == ax.get_zlabel()

def test_xyincrease_false_changes_axes(self):
# Does not make sense for surface plots
pytest.skip("does not make sense for surface plots")

def test_xyincrease_true_changes_axes(self):
# Does not make sense for surface plots
pytest.skip("does not make sense for surface plots")

def test_can_pass_in_axis(self):
self.pass_in_axis(self.plotmethod, subplot_kw={"projection": "3d"})

def test_default_cmap(self):
# Does not make sense for surface plots with default arguments
pytest.skip("does not make sense for surface plots")

def test_diverging_color_limits(self):
# Does not make sense for surface plots with default arguments
pytest.skip("does not make sense for surface plots")

def test_colorbar_kwargs(self):
# Does not make sense for surface plots with default arguments
pytest.skip("does not make sense for surface plots")

def test_cmap_and_color_both(self):
# Does not make sense for surface plots with default arguments
pytest.skip("does not make sense for surface plots")

def test_seaborn_palette_as_cmap(self):
# seaborn does not work with mpl_toolkits.mplot3d
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not? I would not expect an interaction here? Or is it because you don't actually call the code determining the cmap?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the error. If I don't modify the test, I get

================================================================================================================== FAILURES ==================================================================================================================
__________________________________________________________________________________________________ TestSurface.test_seaborn_palette_as_cmap __________________________________________________________________________________________________

self = <xarray.tests.test_plot.TestSurface object at 0x7f5043826220>

    @requires_seaborn
    def test_seaborn_palette_as_cmap(self):
>       cmap_name = self.plotmethod(levels=2, cmap="husl").get_cmap().name

.../xarray/xarray/tests/test_plot.py:1232: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../xarray/xarray/plot/plot.py:873: in plotmethod
    return newplotfunc(**allargs)
.../xarray/xarray/plot/plot.py:775: in newplotfunc
    primitive = plotfunc(
.../xarray/xarray/plot/plot.py:1035: in surface
    primitive = ax.plot_surface(x, y, z, **kwargs)
.../python3.8/site-packages/matplotlib/_api/deprecation.py:431: in wrapper
    return func(*inner_args, **inner_kwargs)
.../python3.8/site-packages/mpl_toolkits/mplot3d/axes3d.py:1742: in plot_surface
    polyc = art3d.Poly3DCollection(polys, *args, **kwargs)
.../python3.8/site-packages/mpl_toolkits/mplot3d/art3d.py:715: in __init__
    super().__init__(verts, *args, **kwargs)
.../python3.8/site-packages/matplotlib/collections.py:1206: in __init__
    super().__init__(**kwargs)
.../python3.8/site-packages/matplotlib/_api/deprecation.py:431: in wrapper
    return func(*inner_args, **inner_kwargs)
.../python3.8/site-packages/matplotlib/collections.py:164: in __init__
    cm.ScalarMappable.__init__(self, norm, cmap)
.../python3.8/site-packages/matplotlib/cm.py:263: in __init__
    self.set_cmap(cmap)  # The Colormap instance of this ScalarMappable.
.../python3.8/site-packages/matplotlib/cm.py:432: in set_cmap
    cmap = get_cmap(cmap)
.../python3.8/site-packages/matplotlib/cm.py:190: in get_cmap
    _api.check_in_list(sorted(_cmap_registry), name=name)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

_values = ['Accent', 'Accent_r', 'Blues', 'Blues_r', 'BrBG', 'BrBG_r', ...], _print_supported_values = True, kwargs = {'name': 'husl'}, values = ['Accent', 'Accent_r', 'Blues', 'Blues_r', 'BrBG', 'BrBG_r', ...], key = 'name', val = 'husl'

    def check_in_list(_values, *, _print_supported_values=True, **kwargs):
        """
        For each *key, value* pair in *kwargs*, check that *value* is in *_values*.
    
        Parameters
        ----------
        _values : iterable
            Sequence of values to check on.
        _print_supported_values : bool, default: True
            Whether to print *_values* when raising ValueError.
        **kwargs : dict
            *key, value* pairs as keyword arguments to find in *_values*.
    
        Raises
        ------
        ValueError
            If any *value* in *kwargs* is not found in *_values*.
    
        Examples
        --------
        >>> _api.check_in_list(["foo", "bar"], arg=arg, other_arg=other_arg)
        """
        values = _values
        for key, val in kwargs.items():
            if val not in values:
                if _print_supported_values:
>                   raise ValueError(
                        f"{val!r} is not a valid value for {key}; "
                        f"supported values are {', '.join(map(repr, values))}")
E                   ValueError: 'husl' is not a valid value for name; supported values are 'Accent', 'Accent_r', 'Blues', 'Blues_r', 'BrBG', 'BrBG_r', 'BuGn', 'BuGn_r', 'BuPu', 'BuPu_r', 'CMRmap', 'CMRmap_r', 'Dark2', 'Dark2_r', 'GnBu', 'GnBu_r', 'Greens', 'Greens_r', 'Greys', 'Greys_r', 'OrRd', 'OrRd_r', 'Oranges', 'Oranges_r', 'PRGn', 'PRGn_r', 'Paired', 'Paired_r', 'Pastel1', 'Pastel1_r', 'Pastel2', 'Pastel2_r', 'PiYG', 'PiYG_r', 'PuBu', 'PuBuGn', 'PuBuGn_r', 'PuBu_r', 'PuOr', 'PuOr_r', 'PuRd', 'PuRd_r', 'Purples', 'Purples_r', 'RdBu', 'RdBu_r', 'RdGy', 'RdGy_r', 'RdPu', 'RdPu_r', 'RdYlBu', 'RdYlBu_r', 'RdYlGn', 'RdYlGn_r', 'Reds', 'Reds_r', 'Set1', 'Set1_r', 'Set2', 'Set2_r', 'Set3', 'Set3_r', 'Spectral', 'Spectral_r', 'Wistia', 'Wistia_r', 'YlGn', 'YlGnBu', 'YlGnBu_r', 'YlGn_r', 'YlOrBr', 'YlOrBr_r', 'YlOrRd', 'YlOrRd_r', 'afmhot', 'afmhot_r', 'autumn', 'autumn_r', 'binary', 'binary_r', 'bone', 'bone_r', 'brg', 'brg_r', 'bwr', 'bwr_r', 'cividis', 'cividis_r', 'cool', 'cool_r', 'coolwarm', 'coolwarm_r', 'copper', 'copper_r', 'crest', 'crest_r', 'cubehelix', 'cubehelix_r', 'flag', 'flag_r', 'flare', 'flare_r', 'gist_earth', 'gist_earth_r', 'gist_gray', 'gist_gray_r', 'gist_heat', 'gist_heat_r', 'gist_ncar', 'gist_ncar_r', 'gist_rainbow', 'gist_rainbow_r', 'gist_stern', 'gist_stern_r', 'gist_yarg', 'gist_yarg_r', 'gnuplot', 'gnuplot2', 'gnuplot2_r', 'gnuplot_r', 'gray', 'gray_r', 'hot', 'hot_r', 'hsv', 'hsv_r', 'icefire', 'icefire_r', 'inferno', 'inferno_r', 'jet', 'jet_r', 'magma', 'magma_r', 'mako', 'mako_r', 'nipy_spectral', 'nipy_spectral_r', 'ocean', 'ocean_r', 'pink', 'pink_r', 'plasma', 'plasma_r', 'prism', 'prism_r', 'rainbow', 'rainbow_r', 'rocket', 'rocket_r', 'seismic', 'seismic_r', 'spring', 'spring_r', 'summer', 'summer_r', 'tab10', 'tab10_r', 'tab20', 'tab20_r', 'tab20b', 'tab20b_r', 'tab20c', 'tab20c_r', 'terrain', 'terrain_r', 'turbo', 'turbo_r', 'twilight', 'twilight_r', 'twilight_shifted', 'twilight_shifted_r', 'viridis', 'viridis_r', 'vlag', 'vlag_r', 'winter', 'winter_r'

.../python3.8/site-packages/matplotlib/_api/__init__.py:126: ValueError

with pytest.raises(ValueError):
super().test_seaborn_palette_as_cmap()

# Need to modify this test for surface(), because all subplots should have labels,
# not just left and bottom
@pytest.mark.filterwarnings("ignore:tight_layout cannot")
def test_convenient_facetgrid(self):
a = easy_array((10, 15, 4))
d = DataArray(a, dims=["y", "x", "z"])
g = self.plotfunc(d, x="x", y="y", col="z", col_wrap=2)

assert_array_equal(g.axes.shape, [2, 2])
for (y, x), ax in np.ndenumerate(g.axes):
assert ax.has_data()
assert "y" == ax.get_ylabel()
assert "x" == ax.get_xlabel()

# Infering labels
g = self.plotfunc(d, col="z", col_wrap=2)
assert_array_equal(g.axes.shape, [2, 2])
for (y, x), ax in np.ndenumerate(g.axes):
assert ax.has_data()
assert "y" == ax.get_ylabel()
assert "x" == ax.get_xlabel()

@requires_matplotlib_3_3_0
def test_viridis_cmap(self):
return super().test_viridis_cmap()

@requires_matplotlib_3_3_0
def test_can_change_default_cmap(self):
return super().test_can_change_default_cmap()

@requires_matplotlib_3_3_0
def test_colorbar_default_label(self):
return super().test_colorbar_default_label()

@requires_matplotlib_3_3_0
def test_facetgrid_map_only_appends_mappables(self):
return super().test_facetgrid_map_only_appends_mappables()


class TestFacetGrid(PlotTestCase):
@pytest.fixture(autouse=True)
def setUp(self):
Expand Down