-
Notifications
You must be signed in to change notification settings - Fork 10
test: cover utils helpers and xsg accessor; fix deprecations #124
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import numpy as np | ||
| import pytest | ||
| import xarray as xr | ||
|
|
||
| import xarray_subset_grid.accessor # noqa: F401 -- register accessor | ||
|
|
||
|
|
||
| def test_accessor_warns_when_no_grid_recognized(): | ||
| ds = xr.Dataset() | ||
| with pytest.warns(UserWarning, match="no grid type"): | ||
| accessor = ds.xsg | ||
| assert accessor.grid is None | ||
|
|
||
|
|
||
| def test_subset_polygon_and_bbox_return_none_without_grid(): | ||
| ds = xr.Dataset() | ||
| poly = np.array( | ||
| [ | ||
| [-72.0, 41.0], | ||
| [-70.0, 41.0], | ||
| [-71.0, 39.0], | ||
| [-72.0, 41.0], | ||
| ] | ||
| ) | ||
| with pytest.warns(UserWarning, match="no grid type"): | ||
| assert ds.xsg.subset_polygon(poly) is None | ||
| assert ds.xsg.subset_bbox((-72, 39, -70, 41)) is None | ||
|
|
||
|
|
||
| def test_subset_vars_passthrough_without_grid(): | ||
| ds = xr.Dataset({"a": (("x",), [1, 2, 3])}) | ||
| with pytest.warns(UserWarning, match="no grid type"): | ||
| out = ds.xsg.subset_vars(["a"]) | ||
| # Without a recognized grid, subset_vars returns the dataset unchanged. | ||
| assert "a" in out.data_vars | ||
|
|
||
|
|
||
| def test_has_vertical_levels_false_without_grid(): | ||
| ds = xr.Dataset() | ||
| with pytest.warns(UserWarning, match="no grid type"): | ||
| assert ds.xsg.has_vertical_levels is False | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ | |
| from xarray_subset_grid.grids.sgrid import _get_location_info_from_topology | ||
|
|
||
| # open dataset as zarr object using fsspec reference file system and xarray | ||
| zarr__version__ = 0 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we need to check the status of zarr3 and FSpec AWS -- this may be a non_issue now. |
||
| try: | ||
| import fsspec | ||
| import zarr | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,17 @@ | ||
| import os | ||
| from datetime import datetime | ||
|
|
||
| import cftime | ||
| import numpy as np | ||
| import pytest | ||
| import xarray as xr | ||
|
|
||
| from tests.conftest import EXAMPLE_DATA | ||
| from xarray_subset_grid import utils as xsg_utils | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should either import the whole utils module, or import a bunch of names, but not both. |
||
| from xarray_subset_grid.utils import ( | ||
| asdatetime, | ||
| compute_2d_subset_mask, | ||
| format_bytes, | ||
| normalize_bbox_x_coords, | ||
| normalize_polygon_x_coords, | ||
| ray_tracing_numpy, | ||
|
|
@@ -125,3 +133,72 @@ def test_ray_tracing_numpy(): | |
| result = ray_tracing_numpy(points[:, 0], points[:, 1], poly) | ||
|
|
||
| assert np.array_equal(result, [False, True, False]) | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| "num, unit", | ||
| [ | ||
| (512, "bytes"), | ||
| (2048, "KB"), | ||
| (3 * 1024**2, "MB"), | ||
| ], | ||
| ) | ||
| def test_format_bytes(num, unit): | ||
| assert unit in format_bytes(num) | ||
|
|
||
|
|
||
| def test_asdatetime_none(): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks! I actually copied that ober from another project and forgot to bring the tests over -- so this is nice. |
||
| assert asdatetime(None) is None | ||
|
|
||
|
|
||
| def test_asdatetime_datetime_passthrough(): | ||
| dt = datetime(2020, 6, 15, 12, 30, 0) | ||
| assert asdatetime(dt) is dt | ||
|
|
||
|
|
||
| def test_asdatetime_cftime_passthrough(): | ||
| dt = cftime.datetime(2020, 6, 15, 12) | ||
| assert asdatetime(dt) is dt | ||
|
|
||
|
|
||
| def test_asdatetime_parse_string(): | ||
| dt = asdatetime("2020-06-15T12:30:00") | ||
| assert dt.year == 2020 and dt.month == 6 and dt.day == 15 | ||
|
|
||
|
|
||
| def test_compute_2d_subset_mask_all_inside(): | ||
| ny, nx = 5, 5 | ||
| lat = np.linspace(40.0, 44.0, ny) | ||
| lon = np.linspace(-74.0, -70.0, nx) | ||
| lat2d, lon2d = np.meshgrid(lat, lon, indexing="ij") | ||
| lat_da = xr.DataArray(lat2d, dims=("y", "x")) | ||
| lon_da = xr.DataArray(lon2d, dims=("y", "x")) | ||
| poly = np.array([(-75.0, 39.0), (-69.0, 39.0), (-69.0, 45.0), (-75.0, 45.0)]) | ||
| mask = compute_2d_subset_mask(lat_da, lon_da, poly) | ||
| assert mask.dims == ("y", "x") | ||
| assert bool(mask.all()) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you don't need the bool() call here -- |
||
|
|
||
|
|
||
| def test_compute_2d_subset_mask_partial(): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it would be nice to have a simple test case that checks that the mask is actually correct. the actual point-in-polygon code should be tested elswhere, but good to know it's being applied properly -- at least on one example. |
||
| ny, nx = 7, 7 | ||
| lat = np.linspace(40.0, 46.0, ny) | ||
| lon = np.linspace(-74.0, -68.0, nx) | ||
| lat2d, lon2d = np.meshgrid(lat, lon, indexing="ij") | ||
| lat_da = xr.DataArray(lat2d, dims=("y", "x")) | ||
| lon_da = xr.DataArray(lon2d, dims=("y", "x")) | ||
| # Small polygon over the south-west corner only | ||
| poly = np.array([(-74.5, 40.0), (-73.0, 40.0), (-73.0, 41.0), (-74.5, 41.0)]) | ||
| mask = compute_2d_subset_mask(lat_da, lon_da, poly) | ||
| assert mask.dims == ("y", "x") | ||
| assert bool(mask.any()) | ||
| assert not bool(mask.all()) | ||
|
|
||
|
|
||
| def test_assign_ugrid_topology_utils_deprecation_wrapper(): | ||
| nc = EXAMPLE_DATA / "SFBOFS_subset1.nc" | ||
| if not nc.is_file(): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should either make sure it's there or not -- semi-silently skipping is not good. |
||
| pytest.skip("example NetCDF not present") | ||
| ds = xr.open_dataset(nc) | ||
| with pytest.warns(DeprecationWarning, match="assign_ugrid_topology"): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, let's jsut get rid of that Depricated Function -- and make sure that none of the examples use it! |
||
| ds2 = xsg_utils.assign_ugrid_topology(ds, face_node_connectivity="nv") | ||
| assert "mesh" in ds2.variables | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,12 +19,14 @@ def normalize_polygon_x_coords(x, poly): | |
| If the x coords are between 0 and 180 (i.e. both will work), the polygon | ||
| is not changed. | ||
|
|
||
| NOTE: polygon is normalized in place! | ||
| NOTE: ``poly`` is normalized in place when it is already an ndarray; | ||
| a copy is made when ``poly`` is a sequence. | ||
|
|
||
| Args: | ||
| x (np.array): x-coordinates of the vertices | ||
| poly (np.array): polygon vertices | ||
| """ | ||
| poly = np.asarray(poly) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea, thanks! |
||
| x_min, x_max = x.min(), x.max() | ||
|
|
||
| poly_x = poly[:, 0] | ||
|
|
@@ -97,10 +99,11 @@ def ray_tracing_numpy(x, y, poly): | |
| # this placeholder for backwards compatibility for a brief period | ||
| def assign_ugrid_topology(*args, **kwargs): | ||
| warnings.warn( | ||
| DeprecationWarning, | ||
| "The function `assign_grid_topology` has been moved to the " | ||
| "The function `assign_ugrid_topology` has been moved to the " | ||
| "`grids.ugrid` module. It will not be able to be called from " | ||
| "the utils `module` in the future.", | ||
| DeprecationWarning, | ||
| stacklevel=2, | ||
| ) | ||
| from .grids.ugrid import assign_ugrid_topology | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm -- this might take a bit of thought -- I think it should simply raise an Error.
There is no use-case for subset_vars without a grid, and having it be do-nothing might be more surprising.