You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/superpowers/specs/2026-03-24-hypsometric-integral-design.md
+45-26Lines changed: 45 additions & 26 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -20,7 +20,9 @@ catchment, or arbitrary polygon).
20
20
defhypsometric_integral(
21
21
zones,
22
22
values,
23
-
nodata=np.nan,
23
+
nodata=0,
24
+
column=None,
25
+
rasterize_kw=None,
24
26
name='hypsometric_integral',
25
27
) -> xr.DataArray:
26
28
```
@@ -29,16 +31,19 @@ def hypsometric_integral(
29
31
30
32
| Parameter | Type | Description |
31
33
|-----------|------|-------------|
32
-
|`zones`|`DataArray` or `GeoDataFrame`| 2D zone IDs (integer). GeoDataFrame is rasterized via existing `_maybe_rasterize_zones`. |
33
-
|`values`|`DataArray`| 2D elevation raster, same shape as zones. |
34
-
|`nodata`|`float`| Fill value for cells outside any zone. Default `np.nan`. |
34
+
|`zones`|`DataArray`, `GeoDataFrame`, or list of `(geometry, value)` pairs | 2D integer zone IDs. Vector inputs are rasterized via `_maybe_rasterize_zones` using `values` as the template grid. |
35
+
|`values`|`DataArray`| 2D elevation raster (float), same shape as zones. |
36
+
|`nodata`|`int`, default `0`| Zone ID that represents "no zone". Cells with this zone ID are excluded from computation and filled with `NaN` in the output. Matches `apply()` convention. Set to `None` to include all zone IDs. |
37
+
|`column`|`str` or `None`| Column in a GeoDataFrame containing zone IDs. Required when `zones` is a GeoDataFrame. |
38
+
|`rasterize_kw`|`dict` or `None`| Extra keyword arguments passed to `rasterize()` when vector zones are provided. |
35
39
|`name`|`str`| Name for the output DataArray. Default `'hypsometric_integral'`. |
36
40
37
41
### Returns
38
42
39
-
`xr.DataArray` — same shape, dims, coords, and attrs as `values`. Each cell
40
-
contains the HI of its zone. Cells outside any zone get `nodata`. Zones with
41
-
zero elevation range (flat) get `nodata`.
43
+
`xr.DataArray` (dtype `float64`) — same shape, dims, coords, and attrs as
44
+
`values`. Each cell contains the HI of its zone. Cells belonging to the
45
+
`nodata` zone or with non-finite elevation values get `NaN`. Zones with zero
46
+
elevation range (flat) also get `NaN`.
42
47
43
48
## Placement
44
49
@@ -52,50 +57,64 @@ structurally a zonal operation, not a local neighborhood transform.
52
57
53
58
All four backends via `ArrayTypeFunctionMapping`:
54
59
55
-
-**numpy**: iterate unique zones, compute min/mean/max per zone, paint back.
56
-
Can reuse existing `_sort_and_stride` infrastructure for grouping values by
57
-
zone.
58
-
-**cupy**: same logic on GPU arrays. Use `cupy.unique`, scatter/gather.
59
-
-**dask+numpy**: `map_blocks` or blockwise aggregation. Two-pass: first pass
60
-
computes per-zone min/sum/max/count across chunks, second pass reduces and
61
-
paints back.
62
-
-**dask+cupy**: same as dask+numpy but with cupy chunk functions.
60
+
-**numpy**: use `_sort_and_stride` to group values by zone, compute
61
+
min/mean/max per zone, build a zone-to-HI lookup, paint back with
62
+
vectorized indexing.
63
+
-**cupy**: same logic using `cupy.unique` and device-side scatter/gather.
0 commit comments