From 7aed950777bf28eb7ad37a96b46f36c602eac5ec Mon Sep 17 00:00:00 2001 From: dcherian Date: Sat, 2 Nov 2019 15:20:07 -0600 Subject: [PATCH 1/8] make plotting work with transposed nondim coords. --- doc/whats-new.rst | 3 +++ xarray/plot/plot.py | 14 ++++++++++---- xarray/tests/test_plot.py | 16 ++++++++++++++++ 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 47e2e58e988..30b167ebfdc 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -76,6 +76,9 @@ Bug fixes :py:meth:`xarray.core.groupby.DatasetGroupBy.reduce` when reducing over multiple dimensions. (:issue:`3402`). By `Deepak Cherian `_ +- Fix plotting with transposed 2D non-dimensional coordinates. (:issue:`3138`) + By `Deepak Cherian `_. + Documentation ~~~~~~~~~~~~~ - Fix leap year condition in example (http://xarray.pydata.org/en/stable/examples/monthly-means.html) by `Mickaƫl Lalande `_. diff --git a/xarray/plot/plot.py b/xarray/plot/plot.py index ca68f617144..c6bb231ce17 100644 --- a/xarray/plot/plot.py +++ b/xarray/plot/plot.py @@ -672,10 +672,16 @@ def newplotfunc( # check if we need to broadcast one dimension if xval.ndim < yval.ndim: - xval = np.broadcast_to(xval, yval.shape) + 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) - if yval.ndim < xval.ndim: - yval = np.broadcast_to(yval, xval.shape) + elif yval.ndim < xval.ndim: + 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) # May need to transpose for correct x, y labels # xlab may be the name of a coord, we have to check for dim names @@ -687,7 +693,7 @@ def newplotfunc( dims = yx_dims + tuple(d for d in darray.dims if d not in yx_dims) if dims != darray.dims: darray = darray.transpose(*dims, transpose_coords=True) - elif darray[xlab].dims[-1] == darray.dims[0]: + elif xval.shape[-1] == darray.shape[0]: darray = darray.transpose(transpose_coords=True) # Pass the data as a masked ndarray too diff --git a/xarray/tests/test_plot.py b/xarray/tests/test_plot.py index 7deabd46eae..58210e6ffa0 100644 --- a/xarray/tests/test_plot.py +++ b/xarray/tests/test_plot.py @@ -2145,3 +2145,19 @@ def test_yticks_kwarg(self, da): da.plot(yticks=np.arange(5)) expected = np.arange(5) assert np.all(plt.gca().get_yticks() == expected) + + +@requires_matplotlib +@pytest.mark.parametrize("plotfunc", ["pcolormesh", "contourf", "contour"]) +def test_plot_transposed_nondim_coord(plotfunc): + x = np.linspace(0, 10, 101) + h = np.linspace(3, 7, 101) + s = np.linspace(0, 1, 51) + z = s[:, np.newaxis] * h[np.newaxis, :] + da = xr.DataArray( + np.sin(x) * np.cos(z), + dims=["s", "x"], + coords={"x": x, "s": s, "z": (("s", "x"), z), "zt": (("x", "s"), z.T)}, + ) + getattr(da.plot, plotfunc)(x="x", y="zt") + getattr(da.plot, plotfunc)(x="zt", y="x") From 9b35ecf3bb2878a5cedcd3943baa5bbbfa556aac Mon Sep 17 00:00:00 2001 From: dcherian Date: Sat, 2 Nov 2019 15:49:08 -0600 Subject: [PATCH 2/8] Additional test. --- xarray/tests/test_plot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/xarray/tests/test_plot.py b/xarray/tests/test_plot.py index 58210e6ffa0..982d3cc1a73 100644 --- a/xarray/tests/test_plot.py +++ b/xarray/tests/test_plot.py @@ -265,6 +265,7 @@ def test2d_1d_2d_coordinates_contourf(self): ) a.plot.contourf(x="time", y="depth") + a.plot.contourf(x="depth", y="time") def test3d(self): self.darray.plot() From c9cc69832c657f23c5c9351f9ed1cda8609e978f Mon Sep 17 00:00:00 2001 From: dcherian Date: Wed, 13 Nov 2019 08:01:39 -0700 Subject: [PATCH 3/8] Test to make sure transpose is right --- xarray/tests/test_plot.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xarray/tests/test_plot.py b/xarray/tests/test_plot.py index 982d3cc1a73..b824e1ae9b0 100644 --- a/xarray/tests/test_plot.py +++ b/xarray/tests/test_plot.py @@ -2162,3 +2162,9 @@ def test_plot_transposed_nondim_coord(plotfunc): ) getattr(da.plot, plotfunc)(x="x", y="zt") getattr(da.plot, plotfunc)(x="zt", y="x") + + +def test_plot_transposes_properly(): + da = xr.DataArray([np.sin(2 * np.pi / 10 * np.arange(10))] * 10, dims=("y", "x")) + hdl = da.plot(x="x", y="y") + np.all(hdl.get_array() == da.to_masked_array().ravel()) From 279ff1dfc297d71431cfe9500fa5da6547f5e7ce Mon Sep 17 00:00:00 2001 From: dcherian Date: Wed, 13 Nov 2019 08:02:44 -0700 Subject: [PATCH 4/8] Undo the transpose change and add test to make sure transposition is right. --- xarray/plot/plot.py | 2 +- xarray/tests/test_plot.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/xarray/plot/plot.py b/xarray/plot/plot.py index c6bb231ce17..3bb2b88372f 100644 --- a/xarray/plot/plot.py +++ b/xarray/plot/plot.py @@ -693,7 +693,7 @@ def newplotfunc( dims = yx_dims + tuple(d for d in darray.dims if d not in yx_dims) if dims != darray.dims: darray = darray.transpose(*dims, transpose_coords=True) - elif xval.shape[-1] == darray.shape[0]: + elif darray[xlab].dims[-1] == darray.dims[0]: darray = darray.transpose(transpose_coords=True) # Pass the data as a masked ndarray too diff --git a/xarray/tests/test_plot.py b/xarray/tests/test_plot.py index b824e1ae9b0..34189d1f0b0 100644 --- a/xarray/tests/test_plot.py +++ b/xarray/tests/test_plot.py @@ -2167,4 +2167,4 @@ def test_plot_transposed_nondim_coord(plotfunc): def test_plot_transposes_properly(): da = xr.DataArray([np.sin(2 * np.pi / 10 * np.arange(10))] * 10, dims=("y", "x")) hdl = da.plot(x="x", y="y") - np.all(hdl.get_array() == da.to_masked_array().ravel()) + assert np.all(hdl.get_array() == da.to_masked_array().ravel()) From 7fd69be199a1fe832212769398635faf2243e555 Mon Sep 17 00:00:00 2001 From: dcherian Date: Wed, 13 Nov 2019 08:03:26 -0700 Subject: [PATCH 5/8] fix whats-new merge. --- doc/whats-new.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 9ca36d96c4a..4354a6d6140 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -91,7 +91,6 @@ Bug fixes - Fix :py:meth:`xarray.core.groupby.DataArrayGroupBy.reduce` and :py:meth:`xarray.core.groupby.DatasetGroupBy.reduce` when reducing over multiple dimensions. (:issue:`3402`). By `Deepak Cherian `_ - - Fix plotting with transposed 2D non-dimensional coordinates. (:issue:`3138`) By `Deepak Cherian `_. From d430ae01014e2ae42df6180a556114ee4e0a4fdc Mon Sep 17 00:00:00 2001 From: dcherian Date: Wed, 13 Nov 2019 08:27:04 -0700 Subject: [PATCH 6/8] proper fix. --- xarray/plot/plot.py | 13 +++++++++---- xarray/tests/test_plot.py | 12 +++++++++--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/xarray/plot/plot.py b/xarray/plot/plot.py index 624af0f5c06..f848143367d 100644 --- a/xarray/plot/plot.py +++ b/xarray/plot/plot.py @@ -672,16 +672,22 @@ def newplotfunc( # 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) 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 + else: + dims = (darray[ylab].dims[0], darray[xlab].dims[0]) # May need to transpose for correct x, y labels # xlab may be the name of a coord, we have to check for dim names @@ -691,10 +697,9 @@ def newplotfunc( # we transpose to (y, x, color) to make this work. yx_dims = (ylab, xlab) dims = yx_dims + tuple(d for d in darray.dims if d not in yx_dims) - if dims != darray.dims: - darray = darray.transpose(*dims, transpose_coords=True) - elif darray[xlab].dims[-1] == darray.dims[0]: - darray = darray.transpose(transpose_coords=True) + + if dims != darray.dims: + darray = darray.transpose(*dims, transpose_coords=True) # Pass the data as a masked ndarray too zval = darray.to_masked_array(copy=False) diff --git a/xarray/tests/test_plot.py b/xarray/tests/test_plot.py index ada9eb0feb0..a10f0d9a67e 100644 --- a/xarray/tests/test_plot.py +++ b/xarray/tests/test_plot.py @@ -2168,7 +2168,13 @@ def test_plot_transposed_nondim_coord(plotfunc): getattr(da.plot, plotfunc)(x="zt", y="x") -def test_plot_transposes_properly(): +@requires_matplotlib +@pytest.mark.parametrize("plotfunc", ["pcolormesh", "imshow"]) +def test_plot_transposes_properly(plotfunc): + # test that we aren't mistakenly transposing when the 2 dimensions have equal sizes. da = xr.DataArray([np.sin(2 * np.pi / 10 * np.arange(10))] * 10, dims=("y", "x")) - hdl = da.plot(x="x", y="y") - assert np.all(hdl.get_array() == da.to_masked_array().ravel()) + hdl = getattr(da.plot, plotfunc)(x="x", y="y") + # get_array doesn't work for contour, contourf. It returns the colormap intervals. + # pcolormesh returns 1D array but imshow returns a 2D array so it is necessary + # to ravel() on the LHS + assert np.all(hdl.get_array().ravel() == da.to_masked_array().ravel()) From 07eddc5f6b944a324c9a8f07a6dd4515b8f2b808 Mon Sep 17 00:00:00 2001 From: dcherian Date: Fri, 22 Nov 2019 08:44:24 -0700 Subject: [PATCH 7/8] fix whats-new --- doc/whats-new.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 17719e6a1a7..64f5e69ab00 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -29,6 +29,8 @@ New Features Bug fixes ~~~~~~~~~ +- Fix plotting with transposed 2D non-dimensional coordinates. (:issue:`3138`, :pull:`3441`) + By `Deepak Cherian `_. Documentation @@ -138,8 +140,6 @@ Bug fixes - Fix :py:meth:`xarray.core.groupby.DataArrayGroupBy.reduce` and :py:meth:`xarray.core.groupby.DatasetGroupBy.reduce` when reducing over multiple dimensions. (:issue:`3402`). By `Deepak Cherian `_ -- Fix plotting with transposed 2D non-dimensional coordinates. (:issue:`3138`) - By `Deepak Cherian `_. - Add support for cftime>=1.0.4. By `Anderson Banihirwe `_. - Rolling reduction operations no longer compute dask arrays by default. (:issue:`3161`). In addition, the ``allow_lazy`` kwarg to ``reduce`` is deprecated. From c69b21a974698c684d108aa2517b9f33e81987da Mon Sep 17 00:00:00 2001 From: dcherian Date: Mon, 25 Nov 2019 08:55:07 -0700 Subject: [PATCH 8/8] Fix whats-new --- doc/whats-new.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 023bd155951..655d23cb52b 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -150,11 +150,6 @@ Bug fixes ``reset_coords(drop=True)`` should now be unnecessary in most cases. (:issue:`3068`, :issue:`3311`, :issue:`3454`, :pull:`3453`). By `Deepak Cherian `_. -- Sync with cftime by removing `dayofwk=-1` for cftime>=1.0.4. - By `Anderson Banihirwe `_. -- Fix :py:meth:`xarray.core.groupby.DataArrayGroupBy.reduce` and - :py:meth:`xarray.core.groupby.DatasetGroupBy.reduce` when reducing over multiple dimensions. - (:issue:`3402`). By `Deepak Cherian `_ - Add support for cftime>=1.0.4. By `Anderson Banihirwe `_. - Rolling reduction operations no longer compute dask arrays by default. (:issue:`3161`). In addition, the ``allow_lazy`` kwarg to ``reduce`` is deprecated.