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

Add grid_bounds_to_polygons #478

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
55 changes: 55 additions & 0 deletions cf_xarray/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,3 +293,58 @@
j += n

return xr.DataArray(geoms, dims=node_count.dims, coords=node_count.coords)


def grid_to_polygons(ds: xr.Dataset) -> xr.DataArray:
dcherian marked this conversation as resolved.
Show resolved Hide resolved
dcherian marked this conversation as resolved.
Show resolved Hide resolved
"""
Converts a regular 2D lat/lon grid to a 2D array of shapely polygons.
dcherian marked this conversation as resolved.
Show resolved Hide resolved

Modified from https://notebooksharing.space/view/c6c1f3a7d0c260724115eaa2bf78f3738b275f7f633c1558639e7bbd75b31456.

Parameters
----------
ds : xr.Dataset
Dataset with "latitude" and "longitude" variables as well as their bounds variables.
1D "latitude" and "longitude" variables are supported. This function will automatically
broadcast them against each other.
dcherian marked this conversation as resolved.
Show resolved Hide resolved
dcherian marked this conversation as resolved.
Show resolved Hide resolved

Returns
-------
DataArray
DataArray with shapely polygon per grid cell.
"""
import shapely

Check warning on line 316 in cf_xarray/geometry.py

View check run for this annotation

Codecov / codecov/patch

cf_xarray/geometry.py#L316

Added line #L316 was not covered by tests

grid = ds.cf[["latitude", "longitude"]].load().reset_coords()
bounds = ds.cf.bounds

Check warning on line 319 in cf_xarray/geometry.py

View check run for this annotation

Codecov / codecov/patch

cf_xarray/geometry.py#L318-L319

Added lines #L318 - L319 were not covered by tests

assert "latitude" in bounds
assert "longitude" in bounds
(lon_bounds,) = bounds["longitude"]
(lat_bounds,) = bounds["latitude"]

Check warning on line 324 in cf_xarray/geometry.py

View check run for this annotation

Codecov / codecov/patch

cf_xarray/geometry.py#L321-L324

Added lines #L321 - L324 were not covered by tests

(points,) = xr.broadcast(grid)

Check warning on line 326 in cf_xarray/geometry.py

View check run for this annotation

Codecov / codecov/patch

cf_xarray/geometry.py#L326

Added line #L326 was not covered by tests

bounds_dim = grid.cf.get_bounds_dim_name("latitude")
points = points.transpose(..., bounds_dim)
lonbnd = points[lon_bounds].data
latbnd = points[lat_bounds].data

Check warning on line 331 in cf_xarray/geometry.py

View check run for this annotation

Codecov / codecov/patch

cf_xarray/geometry.py#L328-L331

Added lines #L328 - L331 were not covered by tests

if points.sizes[bounds_dim] == 2:

Check warning on line 333 in cf_xarray/geometry.py

View check run for this annotation

Codecov / codecov/patch

cf_xarray/geometry.py#L333

Added line #L333 was not covered by tests
# geopandas needs this
lonbnd = lonbnd[..., [0, 0, 1, 1]]
mask = lonbnd[..., 0] >= 180
lonbnd[mask, :] = lonbnd[mask, :] - 360
latbnd = latbnd[..., [0, 1, 1, 0]]

Check warning on line 338 in cf_xarray/geometry.py

View check run for this annotation

Codecov / codecov/patch

cf_xarray/geometry.py#L335-L338

Added lines #L335 - L338 were not covered by tests

elif points.sizes[bounds_dim] == 4:
raise NotImplementedError

Check warning on line 341 in cf_xarray/geometry.py

View check run for this annotation

Codecov / codecov/patch

cf_xarray/geometry.py#L340-L341

Added lines #L340 - L341 were not covered by tests
else:
raise ValueError(

Check warning on line 343 in cf_xarray/geometry.py

View check run for this annotation

Codecov / codecov/patch

cf_xarray/geometry.py#L343

Added line #L343 was not covered by tests
f"The size of the detected bounds or vertex dimension {bounds_dim} is not 2 or 4."
)

polyarray = shapely.polygons(shapely.linearrings(lonbnd, latbnd))
boxes = points[lon_bounds][..., 0].copy(data=polyarray)

Check warning on line 348 in cf_xarray/geometry.py

View check run for this annotation

Codecov / codecov/patch

cf_xarray/geometry.py#L347-L348

Added lines #L347 - L348 were not covered by tests

return boxes

Check warning on line 350 in cf_xarray/geometry.py

View check run for this annotation

Codecov / codecov/patch

cf_xarray/geometry.py#L350

Added line #L350 was not covered by tests
Loading