Skip to content

Commit 49a0c89

Browse files
authored
Addition of strategy argument for exact extract (#117)
* Addition of the strategy argument for _zonal_stats_exactextract, allows for the specification of feature-sequential or raster-sequential * Addition of doc strings for strategy * Run precommit fix * addition of test_exactextract * Adjustment of zonal param to kwarg from named strategy argument, allowing for kwarg passing to exact extract for other configuration options - resolves mypy formatting complaints
1 parent 5affd7a commit 49a0c89

File tree

2 files changed

+57
-3
lines changed

2 files changed

+57
-3
lines changed

xvec/tests/test_zonal_stats.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,3 +425,34 @@ def test_variable_geometry_single(glaciers):
425425

426426
assert result.sizes == {"year": 3, "name": 5, "band": 11}
427427
assert result.statistics.mean() == 13168.585
428+
429+
430+
def test_exactextract_strategy():
431+
ds = xr.tutorial.open_dataset("eraint_uvz")
432+
world = gpd.read_file(geodatasets.get_path("naturalearth land"))
433+
434+
result_feature_sequential = ds.z.xvec.zonal_stats(
435+
world.geometry,
436+
"longitude",
437+
"latitude",
438+
method="exactextract",
439+
strategy="feature-sequential",
440+
)
441+
result_raster_sequential = ds.z.xvec.zonal_stats(
442+
world.geometry,
443+
"longitude",
444+
"latitude",
445+
method="exactextract",
446+
strategy="raster-sequential",
447+
)
448+
449+
xr.testing.assert_allclose(result_feature_sequential, result_raster_sequential)
450+
451+
with pytest.raises(KeyError):
452+
ds.z.xvec.zonal_stats(
453+
world.geometry,
454+
"longitude",
455+
"latitude",
456+
method="exactextract",
457+
strategy="invalid_strategy",
458+
)

xvec/zonal.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ def _zonal_stats_exactextract(
309309
y_coords: Hashable,
310310
stats: str | Callable | Sequence[str | Callable | tuple] = "mean",
311311
name: str = "geometry",
312+
**kwargs,
312313
) -> xr.DataArray | xr.Dataset:
313314
"""Extract the values from a dataset indexed by a set of geometries
314315
@@ -363,7 +364,15 @@ def _zonal_stats_exactextract(
363364
raise ValueError(f"{stat} is not a valid aggregation.")
364365

365366
results, original_shape, coords_info, locs = _agg_exactextract(
366-
acc, geometry, crs, x_coords, y_coords, stats, name, original_is_ds
367+
acc,
368+
geometry,
369+
crs,
370+
x_coords,
371+
y_coords,
372+
stats,
373+
name,
374+
original_is_ds,
375+
**kwargs,
367376
)
368377
i = 0
369378
for stat in stats: # type: ignore
@@ -393,7 +402,15 @@ def _zonal_stats_exactextract(
393402
)
394403
elif isinstance(stats, str):
395404
results, original_shape, coords_info, _ = _agg_exactextract(
396-
acc, geometry, crs, x_coords, y_coords, stats, name, original_is_ds
405+
acc,
406+
geometry,
407+
crs,
408+
x_coords,
409+
y_coords,
410+
stats,
411+
name,
412+
original_is_ds,
413+
**kwargs,
397414
)
398415
# Unstack the result
399416
arr = results.values.reshape(original_shape)
@@ -429,6 +446,7 @@ def _agg_exactextract(
429446
stats: str | Callable | Iterable[str | Callable | tuple] = "mean",
430447
name: str = "geometry",
431448
original_is_ds: bool = False,
449+
strategy: str = "feature-sequential",
432450
):
433451
"""Extract the values from a dataset indexed by a set of geometries
434452
@@ -458,6 +476,9 @@ def _agg_exactextract(
458476
If True, all pixels touched by geometries will be considered. If False, only
459477
pixels whose center is within the polygon or that are selected by
460478
Bresenham’s line algorithm will be considered.
479+
strategy : str, optional
480+
The strategy to use for the extraction, by default "feature-sequential"
481+
Use either "feature-sequential" and "raster-sequential".
461482
462483
Returns
463484
-------
@@ -492,7 +513,9 @@ def _agg_exactextract(
492513

493514
# Aggregation result
494515
gdf = gpd.GeoDataFrame(geometry=geometry, crs=crs)
495-
results = exactextract.exact_extract(rast=data, vec=gdf, ops=stats, output="pandas")
516+
results = exactextract.exact_extract(
517+
rast=data, vec=gdf, ops=stats, output="pandas", strategy=strategy
518+
)
496519
# Get all the dimensions execpt x_coords, y_coords, they will be used to stack the
497520
# dataarray later
498521
if original_is_ds is True:

0 commit comments

Comments
 (0)