Пример #1
0
    def test_1d_padded_but_no_change_in_grid_position(self):
        def diff_center_to_center_second_order(a):
            b = a[..., 2:]
            c = a[..., :-2]
            return 0.5 * (b - c)

        grid = create_1d_test_grid("depth")
        da = grid._ds.depth_c**2
        da.coords["depth_c"] = grid._ds.depth_c

        diffed = 0.5 * (da - da.roll(depth_c=2, roll_coords=False)).data
        expected = xr.DataArray(
            diffed, dims=["depth_c"], coords={"depth_c": grid._ds.depth_c}
        )

        def pad_args(func, pad_width):
            def padding_version_of_func(*args):
                padded_args = [
                    np.pad(a, pad_width=pad_width, mode="wrap") for a in args
                ]
                return func(*padded_args)

            return padding_version_of_func

        # Test direct application
        result = apply_as_grid_ufunc(
            pad_args(diff_center_to_center_second_order, pad_width=[(2, 0)]),
            da,
            axis=[("depth",)],
            grid=grid,
            signature="(X:center)->(X:center)",
            boundary_width=None,
        )
        assert_equal(result, expected)
Пример #2
0
    def test_zero_width_boundary(self):
        def increment(x):
            """Mocking up a function which can only act on in-memory arrays, and requires no padding"""
            if isinstance(x, np.ndarray):
                return np.add(x, 1)
            else:
                raise TypeError

        grid = create_1d_test_grid("depth")
        a = np.sin(grid._ds.depth_g * 2 * np.pi / 9).chunk(2)
        a.coords["depth_g"] = grid._ds.depth_g

        expected = a + 1
        result = apply_as_grid_ufunc(
            increment,
            a,
            axis=[("depth",)],
            grid=grid,
            signature="(X:left)->(X:left)",
            boundary_width=None,
            dask="allowed",
            map_overlap=True,
        ).compute()
        assert_equal(result, expected)

        # in this case the result should be the same as using just map_blocks
        expected_data = dask.array.map_blocks(increment, a.data)
        np.testing.assert_equal(result.data, expected_data)
Пример #3
0
    def test_cumsum(self):
        def cumsum_center_to_left(a):
            return np.cumsum(a, axis=-1)[..., :-1]

        grid = create_1d_test_grid("depth")
        da = grid._ds.depth_c**2
        da.coords["depth_c"] = grid._ds.depth_c

        cum = da.cumsum(dim="depth_c").roll(depth_c=1, roll_coords=False)
        cum[0] = 0
        expected = xr.DataArray(
            cum.data, dims=["depth_g"], coords={"depth_g": grid._ds.depth_g}
        )

        result = apply_as_grid_ufunc(
            cumsum_center_to_left,
            da,
            axis=[("depth",)],
            grid=grid,
            signature="(X:center)->(X:left)",
            boundary_width={"X": (1, 0)},
            boundary="fill",
            fill_value=0,
            pad_before_func=False,
        )
        assert_equal(result, expected)
Пример #4
0
    def test_apply_along_one_axis(self):
        grid = create_2d_test_grid("lon", "lat")

        def diff_center_to_left(a):
            return a - np.roll(a, shift=-1, axis=-1)

        da = grid._ds.lat_c**2 + grid._ds.lon_c**2

        diffed = (da - da.roll(lon_c=-1, roll_coords=False)).data
        expected = xr.DataArray(
            diffed,
            dims=["lat_c", "lon_g"],
            coords={"lat_c": grid._ds.lat_c, "lon_g": grid._ds.lon_g},
        )

        # Test direct application
        result = apply_as_grid_ufunc(
            diff_center_to_left,
            da,
            axis=[("lon",)],
            grid=grid,
            signature="(X:center)->(X:left)",
        )
        assert_equal(result, expected)

        # Test decorator
        @as_grid_ufunc()
        def diff_center_to_left(
            a: Annotated[np.ndarray, "X:center"]
        ) -> Annotated[np.ndarray, "X:left"]:
            return a - np.roll(a, shift=-1, axis=-1)

        result = diff_center_to_left(grid, da, axis=[("lon",)])
        assert_equal(result, expected)
Пример #5
0
    def test_1d_unchanging_size_but_padded_dask_parallelized(self):
        """
        This test checks that the process of padding a non-chunked core dimension doesn't turn it into a chunked core
        dimension. See GH #430.
        """

        def diff_center_to_left(a):
            return a[..., 1:] - a[..., :-1]

        grid = create_1d_test_grid("depth")
        da = np.sin(grid._ds.depth_c * 2 * np.pi / 9).chunk()
        da.coords["depth_c"] = grid._ds.depth_c

        diffed = (da - da.roll(depth_c=1, roll_coords=False)).data
        expected = xr.DataArray(
            diffed, dims=["depth_g"], coords={"depth_g": grid._ds.depth_g}
        ).compute()

        # Test direct application
        result = apply_as_grid_ufunc(
            diff_center_to_left,
            da,
            axis=[("depth",)],
            grid=grid,
            signature="(X:center)->(X:left)",
            boundary_width={"X": (1, 0)},
            dask="parallelized",
        ).compute()
        assert_equal(result, expected)

        # Test Grid method
        result = grid.apply_as_grid_ufunc(
            diff_center_to_left,
            da,
            axis=[("depth",)],
            signature="(X:center)->(X:left)",
            boundary_width={"X": (1, 0)},
            dask="parallelized",
        )
        assert_equal(result, expected)

        # Test decorator
        @as_grid_ufunc(
            "(X:center)->(X:left)",
            boundary_width={"X": (1, 0)},
            dask="parallelized",
        )
        def diff_center_to_left(a):
            return a[..., 1:] - a[..., :-1]

        result = diff_center_to_left(
            grid,
            da,
            axis=[("depth",)],
        ).compute()
        assert_equal(result, expected)
Пример #6
0
    def test_chunked_core_dims_unchanging_chunksize(self):
        def diff_center_to_left(a):
            return a[..., 1:] - a[..., :-1]

        grid = create_1d_test_grid("depth")
        da = np.sin(grid._ds.depth_c * 2 * np.pi / 9).chunk(3)
        da.coords["depth_c"] = grid._ds.depth_c

        diffed = (da - da.roll(depth_c=1, roll_coords=False)).data
        expected = xr.DataArray(
            diffed, dims=["depth_g"], coords={"depth_g": grid._ds.depth_g}
        ).compute()

        # Test direct application
        result = apply_as_grid_ufunc(
            diff_center_to_left,
            da,
            axis=[("depth",)],
            grid=grid,
            signature="(X:center)->(X:left)",
            boundary_width={"X": (1, 0)},
            dask="allowed",
            map_overlap=True,
        ).compute()
        assert_equal(result, expected)

        # Test Grid method
        result = grid.apply_as_grid_ufunc(
            diff_center_to_left,
            da,
            axis=[("depth",)],
            signature="(X:center)->(X:left)",
            boundary_width={"X": (1, 0)},
            dask="allowed",
            map_overlap=True,
        )
        assert_equal(result, expected)

        # Test decorator
        @as_grid_ufunc(
            boundary_width={"X": (1, 0)},
            dask="allowed",
            map_overlap=True,
        )
        def diff_center_to_left(
            a: Annotated[np.ndarray, "X:center"]
        ) -> Annotated[np.ndarray, "X:left"]:
            return a[..., 1:] - a[..., :-1]

        result = diff_center_to_left(
            grid,
            da,
            axis=[("depth",)],
        ).compute()
        assert_equal(result, expected)
Пример #7
0
    def test_1d_overlap_dask_allowed(self):
        from dask.array import map_overlap

        def diff_center_to_left(a):
            return a - np.roll(a, shift=-1)

        def diff_overlap(a):
            return map_overlap(diff_center_to_left, a, depth=1, boundary="periodic")

        grid = create_1d_test_grid("depth")
        da = np.sin(grid._ds.depth_c * 2 * np.pi / 9).chunk(1)
        da.coords["depth_c"] = grid._ds.depth_c

        diffed = (da - da.roll(depth_c=-1, roll_coords=False)).data
        expected = xr.DataArray(
            diffed, dims=["depth_g"], coords={"depth_g": grid._ds.depth_g}
        ).compute()

        # Test direct application
        result = apply_as_grid_ufunc(
            diff_overlap,
            da,
            axis=[("depth",)],
            grid=grid,
            signature="(X:center)->(X:left)",
            dask="allowed",
        ).compute()
        assert_equal(result, expected)

        # Test Grid method
        result = grid.apply_as_grid_ufunc(
            diff_overlap,
            da,
            axis=[("depth",)],
            signature="(X:center)->(X:left)",
            dask="allowed",
        )
        assert_equal(result, expected)

        # Test decorator
        @as_grid_ufunc(dask="allowed")
        def diff_overlap(
            a: Annotated[np.ndarray, "X:center"]
        ) -> Annotated[np.ndarray, "X:left"]:
            return map_overlap(diff_center_to_left, a, depth=1, boundary="periodic")

        result = diff_overlap(
            grid,
            da,
            axis=[("depth",)],
        ).compute()
        assert_equal(result, expected)
Пример #8
0
    def test_multiple_outputs(self):
        def diff_center_to_inner(a, axis):
            result = a - np.roll(a, shift=1, axis=axis)
            return np.delete(result, 0, axis)  # remove first element along axis

        def grad_to_inner(a):
            return diff_center_to_inner(a, axis=0), diff_center_to_inner(a, axis=1)

        grid = create_2d_test_grid("lon", "lat")

        a = grid._ds.lon_c**2 + grid._ds.lat_c**2

        expected_u = 2 * grid._ds.lon_i.expand_dims(dim={"lat_c": len(grid._ds.lat_c)})
        expected_u.coords["lat_c"] = grid._ds.lat_c
        expected_v = 2 * grid._ds.lat_i.expand_dims(dim={"lon_c": len(grid._ds.lon_c)})
        expected_v.coords["lon_c"] = grid._ds.lon_c

        # Test direct application
        u, v = apply_as_grid_ufunc(
            grad_to_inner,
            a,
            axis=[("lon", "lat")],
            grid=grid,
            signature="(X:center,Y:center)->(X:inner,Y:center),(X:center,Y:inner)",
        )
        assert_equal(u.T, expected_u)
        assert_equal(v, expected_v)

        # Test Grid method
        u, v = grid.apply_as_grid_ufunc(
            grad_to_inner,
            a,
            axis=[("lon", "lat")],
            signature="(X:center,Y:center)->(X:inner,Y:center),(X:center,Y:inner)",
        )
        assert_equal(u.T, expected_u)
        assert_equal(v, expected_v)

        # Test decorator
        @as_grid_ufunc()
        def grad_to_inner(
            a: Annotated[np.ndarray, "X:center,Y:center"]
        ) -> Tuple[
            Annotated[np.ndarray, "X:inner,Y:center"],
            Annotated[np.ndarray, "X:center,Y:inner"],
        ]:
            return diff_center_to_inner(a, axis=0), diff_center_to_inner(a, axis=1)

        u, v = grad_to_inner(grid, a, axis=[("lon", "lat")])
        assert_equal(u.T, expected_u)
        assert_equal(v, expected_v)
Пример #9
0
    def test_multiple_outputs(self):
        def diff_center_to_inner(a, axis):
            result = a - np.roll(a, shift=1, axis=axis)
            return np.delete(result, 0, axis)  # remove first element along axis

        def grad_to_inner(a):
            return diff_center_to_inner(a, axis=0), diff_center_to_inner(a, axis=1)

        grid = create_2d_test_grid("lon", "lat")

        a = (grid._ds.lon_c**2 + grid._ds.lat_c**2).chunk(1)

        # Test direct application
        with pytest.raises(NotImplementedError, match="multiple outputs"):
            apply_as_grid_ufunc(
                grad_to_inner,
                a,
                axis=[("lon", "lat")],
                grid=grid,
                signature="(X:center,Y:center)->(X:inner,Y:center),(X:center,Y:inner)",
                map_overlap=True,
                dask="allowed",
            )
Пример #10
0
    def test_input_on_wrong_positions(self):
        grid = create_1d_test_grid("depth")
        grid._ds.drop_vars("depth_o")
        da = np.sin(grid._ds.depth_g * 2 * np.pi / 9)

        with pytest.raises(
            ValueError,
            match=re.escape("Axis:positions pair depth:outer does not exist"),
        ):
            da: Annotated[np.ndarray, "X:outer"]
            apply_as_grid_ufunc(
                lambda x: x, da, axis=[("depth",)], grid=grid, signature="(X:outer)->()"
            )

        with pytest.raises(ValueError, match="coordinate depth_c does not appear"):
            da: Annotated[np.ndarray, "X:center"]
            apply_as_grid_ufunc(
                lambda x: x,
                da,
                axis=[("depth",)],
                grid=grid,
                signature="(X:center)->()",
            )
Пример #11
0
    def test_1d_changing_size_dask_parallelized(self):
        def interp_center_to_inner(a):
            return 0.5 * (a[:-1] + a[1:])

        grid = create_1d_test_grid("depth")
        da = xr.DataArray(
            np.arange(10, 19), dims=["depth_c"], coords={"depth_c": grid._ds.depth_c}
        ).chunk()

        expected = da.interp(depth_c=np.arange(1.5, 9), method="linear").rename(
            depth_c="depth_i"
        )

        # Test direct application
        result = apply_as_grid_ufunc(
            interp_center_to_inner,
            da,
            axis=[("depth",)],
            grid=grid,
            signature="(X:center)->(X:inner)",
            dask="parallelized",
        ).compute()
        assert_equal(result, expected)

        # Test Grid method
        result = grid.apply_as_grid_ufunc(
            interp_center_to_inner,
            da,
            axis=[("depth",)],
            signature="(X:center)->(X:inner)",
            dask="parallelized",
        ).compute()
        assert_equal(result, expected)

        # Test decorator
        @as_grid_ufunc(dask="parallelized")
        def interp_center_to_inner(
            a: Annotated[np.ndarray, "X:center"]
        ) -> Annotated[np.ndarray, "X:inner"]:
            return 0.5 * (a[:-1] + a[1:])

        result = interp_center_to_inner(grid, da, axis=[("depth",)]).compute()
        assert_equal(result, expected)
Пример #12
0
    def test_multiple_inputs(self):
        def inner_product_left_right(a, b):
            return np.inner(a, b)

        grid = create_1d_test_grid("depth")
        a = np.sin(grid._ds.depth_g * 2 * np.pi / 9)
        a.coords["depth_g"] = grid._ds.depth_g
        b = np.cos(grid._ds.depth_r * 2 * np.pi / 9)
        b.coords["depth_r"] = grid._ds.depth_r

        expected = xr.DataArray(np.inner(a, b))

        # Test direct application
        result = apply_as_grid_ufunc(
            inner_product_left_right,
            a,
            b,
            axis=[("depth",), ("depth",)],
            grid=grid,
            signature="(X:left),(X:right)->()",
        )
        assert_equal(result, expected)

        # Test Grid method
        result = grid.apply_as_grid_ufunc(
            inner_product_left_right,
            a,
            b,
            axis=[("depth",), ("depth",)],
            signature="(X:left),(X:right)->()",
        )
        assert_equal(result, expected)

        # Test decorator
        @as_grid_ufunc()
        def inner_product_left_right(
            a: Annotated[np.ndarray, "X:left"], b: Annotated[np.ndarray, "X:right"]
        ):
            return np.inner(a, b)

        result = inner_product_left_right(grid, a, b, axis=[("depth",), ("depth",)])
        assert_equal(result, expected)
Пример #13
0
    def test_1d_unchanging_size_no_dask(self):
        def diff_center_to_left(a):
            return a - np.roll(a, shift=-1)

        grid = create_1d_test_grid("depth")
        da = np.sin(grid._ds.depth_c * 2 * np.pi / 9)
        da.coords["depth_c"] = grid._ds.depth_c

        diffed = (da - da.roll(depth_c=-1, roll_coords=False)).data
        expected = xr.DataArray(
            diffed, dims=["depth_g"], coords={"depth_g": grid._ds.depth_g}
        )

        # Test direct application
        result = apply_as_grid_ufunc(
            diff_center_to_left,
            da,
            axis=[("depth",)],
            grid=grid,
            signature="(X:center)->(X:left)",
        )
        assert_equal(result, expected)

        # Test Grid method
        result = grid.apply_as_grid_ufunc(
            diff_center_to_left, da, axis=[("depth",)], signature="(X:center)->(X:left)"
        )
        assert_equal(result, expected)

        # Test decorator
        @as_grid_ufunc()
        def diff_center_to_left(
            a: Annotated[np.ndarray, "X:center"]
        ) -> Annotated[np.ndarray, "X:left"]:
            return a - np.roll(a, shift=-1)

        result = diff_center_to_left(grid, da, axis=[("depth",)])
        assert_equal(result, expected)
Пример #14
0
    def test_1d_padded_but_no_change_in_grid_position(self):
        def diff_center_to_center_second_order(a):
            return 0.5 * (a[..., 2:] - a[..., :-2])

        grid = create_1d_test_grid("depth")
        da = np.sin(grid._ds.depth_c * 2 * np.pi / 9)
        da.coords["depth_c"] = grid._ds.depth_c

        diffed = 0.5 * (da - da.roll(depth_c=2, roll_coords=False)).data
        expected = xr.DataArray(
            diffed, dims=["depth_c"], coords={"depth_c": grid._ds.depth_c}
        )

        # Test direct application
        result = apply_as_grid_ufunc(
            diff_center_to_center_second_order,
            da,
            axis=[("depth",)],
            grid=grid,
            signature="(X:center)->(X:center)",
            boundary_width={"X": (2, 0)},
        )
        assert_equal(result, expected)