Author of Proposal: brendan
Reason or problem
focal_stats supports mean, max, min, range, std, var, and sum, but not variety (count of distinct values in a neighborhood window). Variety matters for categorical rasters like land-use or land-cover grids, where you want to know how many different classes fall within a given window.
Proposal
Add a variety statistic to focal_stats.
Design:
- CPU: a
_calc_variety function with @ngjit. Takes the kernel-masked neighborhood values, drops NaNs, counts unique values. The existing _apply_numpy / _apply_dask_numpy machinery handles windowing and dispatch.
- GPU: a
_focal_variety_cuda kernel with @cuda.jit. Iterates over the neighborhood and counts distinct values using a small local buffer (kernel sizes are typically small; a fixed-size buffer of 25 slots works). Wire it into _stats_cupy_mapper and _stats_cuda_mapper.
- Dask: no extra work. The CPU/GPU paths are already wrapped by
map_overlap through the existing dispatch in _focal_stats_cpu and _focal_stats_dask_cupy.
- Output type:
float32 (like other stats). NaN means no valid neighbors.
Usage:
from xrspatial.focal import focal_stats
from xrspatial.convolution import circle_kernel
kernel = circle_kernel(1, 1, 1)
result = focal_stats(land_cover, kernel, stats_funcs=['variety'])
# result shape: (1, rows, cols), values are integer counts cast to float32
Value: Variety is a standard focal statistic in ArcGIS and QGIS. Adding it lets users do categorical raster analysis without writing custom kernels.
Stakeholders and impacts
Users working with land-cover or other classified rasters. The change is additive (new stat name in the dispatch dicts) and doesn't touch existing behavior.
Drawbacks
Variety on continuous floating-point data can produce misleading results (every pixel may be unique). This matches how ArcGIS handles it, so no special guard is needed beyond documentation.
Alternatives
Users could write a custom @ngjit function and pass it to focal.apply(), but that gives no GPU support and no way to request it by name in focal_stats.
Unresolved questions
None.
Additional notes
range was mentioned in the original request but already exists in focal_stats.
Author of Proposal: brendan
Reason or problem
focal_statssupportsmean,max,min,range,std,var, andsum, but notvariety(count of distinct values in a neighborhood window). Variety matters for categorical rasters like land-use or land-cover grids, where you want to know how many different classes fall within a given window.Proposal
Add a
varietystatistic tofocal_stats.Design:
_calc_varietyfunction with@ngjit. Takes the kernel-masked neighborhood values, drops NaNs, counts unique values. The existing_apply_numpy/_apply_dask_numpymachinery handles windowing and dispatch._focal_variety_cudakernel with@cuda.jit. Iterates over the neighborhood and counts distinct values using a small local buffer (kernel sizes are typically small; a fixed-size buffer of 25 slots works). Wire it into_stats_cupy_mapperand_stats_cuda_mapper.map_overlapthrough the existing dispatch in_focal_stats_cpuand_focal_stats_dask_cupy.float32(like other stats). NaN means no valid neighbors.Usage:
Value: Variety is a standard focal statistic in ArcGIS and QGIS. Adding it lets users do categorical raster analysis without writing custom kernels.
Stakeholders and impacts
Users working with land-cover or other classified rasters. The change is additive (new stat name in the dispatch dicts) and doesn't touch existing behavior.
Drawbacks
Variety on continuous floating-point data can produce misleading results (every pixel may be unique). This matches how ArcGIS handles it, so no special guard is needed beyond documentation.
Alternatives
Users could write a custom
@ngjitfunction and pass it tofocal.apply(), but that gives no GPU support and no way to request it by name infocal_stats.Unresolved questions
None.
Additional notes
rangewas mentioned in the original request but already exists infocal_stats.