diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 26bd72b0727..c45ecba6c69 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -161,6 +161,9 @@ Bug fixes By `Michael Niklas `_. - Fix static typing of :py:meth:`xr.polyval` (:issue:`7312`, :pull:`7315`). By `Michael Niklas `_. +- Fix matplotlib raising a UserWarning when plotting a scatter plot + with an unfilled marker (:issue:`7313`, :pull:`7318`). + By `Jimmy Westling `_. - Fix multiple reads on fsspec S3 files by resetting file pointer to 0 when reading file streams (:issue:`6813`, :pull:`7304`). By `David Hoese `_ and `Wei Ji Leong `_. - Fix :py:meth:`Dataset.assign_coords` resetting all dimension coordinates to default (pandas) index (:issue:`7346`, :pull:`7347`). diff --git a/xarray/plot/dataarray_plot.py b/xarray/plot/dataarray_plot.py index f18495e5e94..4cec98c3744 100644 --- a/xarray/plot/dataarray_plot.py +++ b/xarray/plot/dataarray_plot.py @@ -52,6 +52,11 @@ ) from xarray.plot.facetgrid import FacetGrid +_styles: MutableMapping[str, Any] = { + # Add a white border to make it easier seeing overlapping markers: + "scatter.edgecolors": "w", +} + def _infer_line_data( darray: DataArray, x: Hashable | None, y: Hashable | None, hue: Hashable | None @@ -884,6 +889,8 @@ def newplotfunc( # All 1d plots in xarray share this function signature. # Method signature below should be consistent. + plt = import_matplotlib_pyplot() + if subplot_kws is None: subplot_kws = dict() @@ -895,6 +902,7 @@ def newplotfunc( allargs = locals().copy() allargs.update(allargs.pop("kwargs")) allargs.pop("darray") + allargs.pop("plt") allargs["plotfunc"] = globals()[plotfunc.__name__] return _easy_facetgrid(darray, kind="plot1d", **allargs) @@ -974,24 +982,25 @@ def newplotfunc( ckw = {vv: cmap_params[vv] for vv in ("vmin", "vmax", "norm", "cmap")} cmap_params_subset.update(**ckw) - if z is not None: - if ax is None: - subplot_kws.update(projection="3d") - ax = get_axis(figsize, size, aspect, ax, **subplot_kws) - # Using 30, 30 minimizes rotation of the plot. Making it easier to - # build on your intuition from 2D plots: - ax.view_init(azim=30, elev=30, vertical_axis="y") - else: - ax = get_axis(figsize, size, aspect, ax, **subplot_kws) - - primitive = plotfunc( - xplt, - yplt, - ax=ax, - add_labels=add_labels, - **cmap_params_subset, - **kwargs, - ) + with plt.rc_context(_styles): + if z is not None: + if ax is None: + subplot_kws.update(projection="3d") + ax = get_axis(figsize, size, aspect, ax, **subplot_kws) + # Using 30, 30 minimizes rotation of the plot. Making it easier to + # build on your intuition from 2D plots: + ax.view_init(azim=30, elev=30, vertical_axis="y") + else: + ax = get_axis(figsize, size, aspect, ax, **subplot_kws) + + primitive = plotfunc( + xplt, + yplt, + ax=ax, + add_labels=add_labels, + **cmap_params_subset, + **kwargs, + ) if np.any(np.asarray(add_labels)) and add_title: ax.set_title(darray._title_for_slice()) @@ -1234,9 +1243,6 @@ def scatter( hueplt: DataArray | None = kwargs.pop("hueplt", None) sizeplt: DataArray | None = kwargs.pop("sizeplt", None) - # Add a white border to make it easier seeing overlapping markers: - kwargs.update(edgecolors=kwargs.pop("edgecolors", "w")) - if hueplt is not None: kwargs.update(c=hueplt.to_numpy().ravel()) diff --git a/xarray/tests/test_plot.py b/xarray/tests/test_plot.py index e7f0323e3b4..95e447592f0 100644 --- a/xarray/tests/test_plot.py +++ b/xarray/tests/test_plot.py @@ -30,6 +30,7 @@ from xarray.tests import ( assert_array_equal, assert_equal, + assert_no_warnings, requires_cartopy, requires_cftime, requires_matplotlib, @@ -3220,3 +3221,38 @@ def test_facetgrid_axes_raises_deprecation_warning() -> None: ds = xr.tutorial.scatter_example_dataset() g = ds.plot.scatter(x="A", y="B", col="x") g.axes + + +@requires_matplotlib +def test_plot1d_default_rcparams() -> None: + import matplotlib as mpl + + ds = xr.tutorial.scatter_example_dataset(seed=42) + + with figure_context(): + # scatter markers should by default have white edgecolor to better + # see overlapping markers: + fig, ax = plt.subplots(1, 1) + ds.plot.scatter(x="A", y="B", marker="o", ax=ax) + np.testing.assert_allclose( + ax.collections[0].get_edgecolor(), mpl.colors.to_rgba_array("w") + ) + + # Facetgrids should have the default value as well: + fg = ds.plot.scatter(x="A", y="B", col="x", marker="o") + ax = fg.axs.ravel()[0] + np.testing.assert_allclose( + ax.collections[0].get_edgecolor(), mpl.colors.to_rgba_array("w") + ) + + # scatter should not emit any warnings when using unfilled markers: + with assert_no_warnings(): + fig, ax = plt.subplots(1, 1) + ds.plot.scatter(x="A", y="B", ax=ax, marker="x") + + # Prioritize edgecolor argument over default plot1d values: + fig, ax = plt.subplots(1, 1) + ds.plot.scatter(x="A", y="B", marker="o", ax=ax, edgecolor="k") + np.testing.assert_allclose( + ax.collections[0].get_edgecolor(), mpl.colors.to_rgba_array("k") + )