diff --git a/.claude/sweep-documentation-state.csv b/.claude/sweep-documentation-state.csv index 5a7de5e2b..205cc7d17 100644 --- a/.claude/sweep-documentation-state.csv +++ b/.claude/sweep-documentation-state.csv @@ -1,4 +1,5 @@ module,last_inspected,issue,severity_max,categories_found,notes,doc_coverage +classify,2026-06-25,3506,MEDIUM,1;3,"Cat3: reclassify (numpy/dask/cupy blocks) + equal_interval example outputs were stale/wrong, binary used np.nan in array repr; corrected to actual output (tests confirm code is correct). Cat1: added missing Examples to std_mean, head_tail_breaks, percentiles, maximum_breaks, box_plot. Fixed in deep-sweep-documentation-classify-2026-06-25 (PR for #3506). Cat2 natural_breaks num_sample-None omission already tracked in #3501 (left alone). All 10 public funcs listed in reference/classification.rst (no Cat4 gap). CUDA available: ran numpy examples; cupy/dask reprs reviewed statically.",10/10 geotiff,2026-06-25,,MEDIUM,1,"to_geotiff (public write entry point) had Parameters/Returns/Raises but no Examples section while open_geotiff does (Cat1 MEDIUM); added Examples block (plain GeoTIFF, cog=True, .vrt mosaic) modeled on open_geotiff; fixed on deep-sweep-documentation-geotiff-2026-06-25; repo issues disabled so no issue number. Cat2/3/4/5 clean: open_geotiff/to_geotiff signature-docstring parity locked by parity/test_signature_contract.py + write/test_bigtiff.py + test_polish.py; both funcs in autosummary in reference/geotiff.rst; reference page mirrors SUPPORTED_FEATURES tiers (tier-parity gate); CUDA available, all docstring examples are +SKIP illustrative only",2/2 fire,2026-06-25,,MEDIUM,1;5,"all 7 public funcs (dnbr, rdnbr, burn_severity_class, fireline_intensity, flame_length, rate_of_spread, kbdi) lacked Examples section (Cat1 MEDIUM) and backend-support note (Cat5 MEDIUM); fixed in deep-sweep-documentation-fire-2026-06-25-01; repo issues disabled so no issue number; examples run and outputs match numpy backend; all 7 listed in reference/fire.rst; no Cat2/Cat3/Cat4 issues",7/7 perlin,2026-06-23,,MEDIUM,2;5,"name param undocumented (Cat2) + float-dtype requirement/ValueError undocumented, no Raises section (Cat5); fixed in deep-sweep-documentation-perlin-2026-06-23; repo has issues disabled so no issue number; example runs and output matches; 1 public func (perlin) listed in reference/surface.rst",1/1 diff --git a/xrspatial/classify.py b/xrspatial/classify.py index 2a3d59e48..facf4c48c 100644 --- a/xrspatial/classify.py +++ b/xrspatial/classify.py @@ -156,10 +156,10 @@ def binary(agg: xr.DataArray, values, name: Optional[str] = 'binary') -> xr.Data >>> agg_binary = binary(agg, values) >>> print(agg_binary) - array([[np.nan, 1., 1., 1., 0.], - [0., 0., 0., 0., 0.], - [0., 0., 0., 0., 0.], - [0., 0., 0., 0., np.nan]], dtype=float32) + array([[nan, 1., 1., 1., 0.], + [ 0., 0., 0., 0., 0.], + [ 0., 0., 0., 0., 0.], + [ 0., 0., 0., 0., nan]], dtype=float32) Dimensions without coordinates: dim_0, dim_1 """ _validate_raster(agg, func_name='binary', name='agg', ndim=None) @@ -360,9 +360,9 @@ def reclassify(agg: xr.DataArray, >>> print(agg_reclassify) array([[nan, 1., 1., 1., 1.], + [ 1., 1., 1., 1., 1.], [ 1., 2., 2., 2., 2.], - [ 2., 2., 2., 2., 2.], - [ 2., 3., 3., 3., 3.]], dtype=float32) + [ 2., 3., 3., 3., nan]], dtype=float32) Dimensions without coordinates: dim_0, dim_1 Reclassify works with Dask with NumPy backed xarray DataArray @@ -373,19 +373,19 @@ def reclassify(agg: xr.DataArray, >>> agg_da = xr.DataArray(data_da, name='agg_da') >>> print(agg_da) - dask.array + dask.array Dimensions without coordinates: dim_0, dim_1 >>> agg_reclassify_da = reclassify(agg_da, bins=bins, new_values=new_values) # noqa >>> print(agg_reclassify_da) - dask.array<_run_numpy_bin, shape=(4, 5), dtype=float32, chunksize=(3, 3), chunktype=numpy.ndarray> + dask.array Dimensions without coordinates: dim_0, dim_1 >>> print(agg_reclassify_da.compute()) # print the computed the results array([[nan, 1., 1., 1., 1.], + [ 1., 1., 1., 1., 1.], [ 1., 2., 2., 2., 2.], - [ 2., 2., 2., 2., 2.], - [ 2., 3., 3., 3., 3.]], dtype=float32) + [ 2., 3., 3., 3., nan]], dtype=float32) Dimensions without coordinates: dim_0, dim_1 Reclassify works with CuPy backed xarray DataArray. @@ -397,13 +397,13 @@ def reclassify(agg: xr.DataArray, >>> agg_cupy = xr.DataArray(data_cupy) >>> agg_reclassify_cupy = reclassify(agg_cupy, bins, new_values) >>> print(type(agg_reclassify_cupy.data)) - + >>> print(agg_reclassify_cupy) array([[nan, 1., 1., 1., 1.], + [ 1., 1., 1., 1., 1.], [ 1., 2., 2., 2., 2.], - [ 2., 2., 2., 2., 2.], - [ 2., 3., 3., 3., 3.]], dtype=float32) + [ 2., 3., 3., 3., nan]], dtype=float32) Dimensions without coordinates: dim_0, dim_1 Reclassify works with Dask with CuPy backed xarray DataArray. @@ -1033,10 +1033,10 @@ def equal_interval(agg: xr.DataArray, >>> print(numpy_equal_interval) array([[nan, 0., 0., 0., 0.], - [ 0., 0., 0., 0., 1.], - [ 1., 1., 1., 1., 1.], - [ 1., 2., 2., 2., 2.], - [ 2., 2., 2., 2., nan]], dtype=float32) + [ 0., 1., 1., 1., 1.], + [ 2., 2., 2., 2., 2.], + [ 3., 3., 3., 3., 4.], + [ 4., 4., 4., 4., nan]], dtype=float32) Dimensions without coordinates: dim_0, dim_1 Attributes: res: (10.0, 10.0) @@ -1113,6 +1113,33 @@ def std_mean(agg: xr.DataArray, References ---------- - PySAL: https://pysal.org/mapclassify/_modules/mapclassify/classifiers.html#StdMean + + Examples + -------- + .. sourcecode:: python + + >>> import numpy as np + >>> import xarray as xr + >>> from xrspatial.classify import std_mean + >>> elevation = np.array([ + [np.nan, 1., 2., 3., 4.], + [ 5., 6., 7., 8., 9.], + [10., 11., 12., 13., 14.], + [15., 16., 17., 18., 19.], + [20., 21., 22., 23., np.inf] + ]) + >>> agg_numpy = xr.DataArray(elevation, attrs={'res': (10.0, 10.0)}) + >>> numpy_std_mean = std_mean(agg_numpy) + >>> print(numpy_std_mean) + + array([[nan, 1., 1., 1., 1.], + [ 1., 2., 2., 2., 2.], + [ 2., 2., 2., 2., 2.], + [ 2., 2., 2., 2., 3.], + [ 3., 3., 3., 3., nan]], dtype=float32) + Dimensions without coordinates: dim_0, dim_1 + Attributes: + res: (10.0, 10.0) """ _validate_raster(agg, func_name='std_mean', name='agg', ndim=None) @@ -1224,6 +1251,33 @@ def head_tail_breaks(agg: xr.DataArray, References ---------- - PySAL: https://pysal.org/mapclassify/_modules/mapclassify/classifiers.html#HeadTailBreaks + + Examples + -------- + .. sourcecode:: python + + >>> import numpy as np + >>> import xarray as xr + >>> from xrspatial.classify import head_tail_breaks + >>> elevation = np.array([ + [np.nan, 1., 2., 3., 4.], + [ 5., 6., 7., 8., 9.], + [10., 11., 12., 13., 14.], + [15., 16., 17., 18., 19.], + [20., 21., 22., 23., np.inf] + ]) + >>> agg_numpy = xr.DataArray(elevation, attrs={'res': (10.0, 10.0)}) + >>> numpy_head_tail_breaks = head_tail_breaks(agg_numpy) + >>> print(numpy_head_tail_breaks) + + array([[nan, 0., 0., 0., 0.], + [ 0., 0., 0., 0., 0.], + [ 0., 0., 0., 1., 1.], + [ 1., 1., 1., 1., 1.], + [ 1., 1., 1., 1., nan]], dtype=float32) + Dimensions without coordinates: dim_0, dim_1 + Attributes: + res: (10.0, 10.0) """ _validate_raster(agg, func_name='head_tail_breaks', name='agg', ndim=None) @@ -1305,6 +1359,33 @@ def percentiles(agg: xr.DataArray, References ---------- - PySAL: https://pysal.org/mapclassify/_modules/mapclassify/classifiers.html#Percentiles + + Examples + -------- + .. sourcecode:: python + + >>> import numpy as np + >>> import xarray as xr + >>> from xrspatial.classify import percentiles + >>> elevation = np.array([ + [np.nan, 1., 2., 3., 4.], + [ 5., 6., 7., 8., 9.], + [10., 11., 12., 13., 14.], + [15., 16., 17., 18., 19.], + [20., 21., 22., 23., np.inf] + ]) + >>> agg_numpy = xr.DataArray(elevation, attrs={'res': (10.0, 10.0)}) + >>> numpy_percentiles = percentiles(agg_numpy) + >>> print(numpy_percentiles) + + array([[nan, 0., 1., 1., 2.], + [ 2., 2., 2., 2., 2.], + [ 2., 2., 2., 3., 3.], + [ 3., 3., 3., 3., 3.], + [ 3., 4., 4., 5., nan]], dtype=float32) + Dimensions without coordinates: dim_0, dim_1 + Attributes: + res: (10.0, 10.0) """ _validate_raster(agg, func_name='percentiles', name='agg', ndim=None) @@ -1444,6 +1525,33 @@ def maximum_breaks(agg: xr.DataArray, References ---------- - PySAL: https://pysal.org/mapclassify/_modules/mapclassify/classifiers.html#MaximumBreaks + + Examples + -------- + .. sourcecode:: python + + >>> import numpy as np + >>> import xarray as xr + >>> from xrspatial.classify import maximum_breaks + >>> elevation = np.array([ + [np.nan, 1., 2., 3., 4.], + [ 5., 6., 7., 8., 9.], + [10., 11., 12., 13., 14.], + [15., 16., 17., 18., 19.], + [20., 21., 22., 23., np.inf] + ]) + >>> agg_numpy = xr.DataArray(elevation, attrs={'res': (10.0, 10.0)}) + >>> numpy_maximum_breaks = maximum_breaks(agg_numpy) + >>> print(numpy_maximum_breaks) + + array([[nan, 0., 0., 0., 0.], + [ 0., 0., 0., 0., 0.], + [ 0., 0., 0., 0., 0.], + [ 0., 0., 0., 0., 0.], + [ 1., 2., 3., 4., nan]], dtype=float32) + Dimensions without coordinates: dim_0, dim_1 + Attributes: + res: (10.0, 10.0) """ _validate_raster(agg, func_name='maximum_breaks', name='agg', ndim=None) _validate_scalar(k, func_name='maximum_breaks', name='k', dtype=int, min_val=2) @@ -1578,6 +1686,33 @@ def box_plot(agg: xr.DataArray, References ---------- - PySAL: https://pysal.org/mapclassify/_modules/mapclassify/classifiers.html#BoxPlot + + Examples + -------- + .. sourcecode:: python + + >>> import numpy as np + >>> import xarray as xr + >>> from xrspatial.classify import box_plot + >>> elevation = np.array([ + [np.nan, 1., 2., 3., 4.], + [ 5., 6., 7., 8., 9.], + [10., 11., 12., 13., 14.], + [15., 16., 17., 18., 19.], + [20., 21., 22., 23., np.inf] + ]) + >>> agg_numpy = xr.DataArray(elevation, attrs={'res': (10.0, 10.0)}) + >>> numpy_box_plot = box_plot(agg_numpy) + >>> print(numpy_box_plot) + + array([[nan, 1., 1., 1., 1.], + [ 1., 1., 2., 2., 2.], + [ 2., 2., 2., 3., 3.], + [ 3., 3., 3., 4., 4.], + [ 4., 4., 4., 4., nan]], dtype=float32) + Dimensions without coordinates: dim_0, dim_1 + Attributes: + res: (10.0, 10.0) """ _validate_raster(agg, func_name='box_plot', name='agg', ndim=None)