Skip to content

Commit d26bf4a

Browse files
dcherianaulemahal
andcommitted
Speedup!
Co-authored-by: Pascal Bourgault <[email protected]>
1 parent 9c3c5b6 commit d26bf4a

File tree

1 file changed

+17
-23
lines changed

1 file changed

+17
-23
lines changed

cf_xarray/geometry.py

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ def cf_to_points(ds: xr.Dataset):
295295
return xr.DataArray(geoms, dims=node_count.dims, coords=node_count.coords)
296296

297297

298-
def grid_bounds_to_polygons(ds: xr.Dataset) -> xr.DataArray:
298+
def grid_to_polygons(ds: xr.Dataset) -> xr.DataArray:
299299
"""
300300
Converts a regular 2D lat/lon grid to a 2D array of shapely polygons.
301301
@@ -313,7 +313,7 @@ def grid_bounds_to_polygons(ds: xr.Dataset) -> xr.DataArray:
313313
DataArray
314314
DataArray with shapely polygon per grid cell.
315315
"""
316-
from shapely import Polygon
316+
import shapely
317317

318318
grid = ds.cf[["latitude", "longitude"]].load().reset_coords()
319319
bounds = ds.cf.bounds
@@ -327,30 +327,24 @@ def grid_bounds_to_polygons(ds: xr.Dataset) -> xr.DataArray:
327327

328328
bounds_dim = grid.cf.get_bounds_dim_name("latitude")
329329
points = points.transpose(..., bounds_dim)
330-
assert points.sizes[bounds_dim] == 2
331-
332330
lonbnd = points[lon_bounds].data
333331
latbnd = points[lat_bounds].data
334332

335-
# geopandas needs this
336-
expanded_lon = lonbnd[..., [0, 0, 1, 1]]
337-
mask = expanded_lon[..., 0] >= 180
338-
expanded_lon[mask, :] = expanded_lon[mask, :] - 360
339-
340-
# these magic numbers are OK :
341-
# - 4 corners to a polygon, and
342-
# - 2 from stacking lat, lon along the last axis
343-
# flatten here to make iteration easier. It would be nice to avoid that.
344-
# potentially with just np.vectorize. The polygon creation is the real slow bit.
345-
# Shapely's MultiPolygon also iterates over a list in Python...
346-
blocked = np.stack([expanded_lon, latbnd[..., [0, 1, 1, 0]]], axis=-1).reshape(
347-
-1, 4, 2
348-
)
349-
polyarray = np.array(
350-
[Polygon(blocked[i, ...]) for i in range(blocked.shape[0])], dtype="O"
351-
)
352-
newshape = latbnd.shape[:-1]
353-
polyarray = polyarray.reshape(newshape)
333+
if points.sizes[bounds_dim] == 2:
334+
# geopandas needs this
335+
lonbnd = lonbnd[..., [0, 0, 1, 1]]
336+
mask = lonbnd[..., 0] >= 180
337+
lonbnd[mask, :] = lonbnd[mask, :] - 360
338+
latbnd = latbnd[..., [0, 1, 1, 0]]
339+
340+
elif points.sizes[bounds_dim] == 4:
341+
raise NotImplementedError
342+
else:
343+
raise ValueError(
344+
f"The size of the detected bounds or vertex dimension {bounds_dim} is not 2 or 4."
345+
)
346+
347+
polyarray = shapely.polygons(shapely.linearrings(lonbnd, latbnd))
354348
boxes = points[lon_bounds][..., 0].copy(data=polyarray)
355349

356350
return boxes

0 commit comments

Comments
 (0)