Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/sweep-documentation-state.csv
Original file line number Diff line number Diff line change
@@ -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
169 changes: 152 additions & 17 deletions xrspatial/classify.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,10 @@ def binary(agg: xr.DataArray, values, name: Optional[str] = 'binary') -> xr.Data
>>> agg_binary = binary(agg, values)
>>> print(agg_binary)
<xarray.DataArray 'binary' (dim_0: 4, dim_1: 5)>
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)
Expand Down Expand Up @@ -360,9 +360,9 @@ def reclassify(agg: xr.DataArray,
>>> print(agg_reclassify)
<xarray.DataArray 'reclassify' (dim_0: 4, dim_1: 5)>
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
Expand All @@ -373,19 +373,19 @@ def reclassify(agg: xr.DataArray,
>>> agg_da = xr.DataArray(data_da, name='agg_da')
>>> print(agg_da)
<xarray.DataArray 'agg_da' (dim_0: 4, dim_1: 5)>
dask.array<array, shape=(4, 5), dtype=float32, chunksize=(3, 3), chunktype=numpy.ndarray>
dask.array<array, shape=(4, 5), dtype=float64, chunksize=(3, 3), chunktype=numpy.ndarray>
Dimensions without coordinates: dim_0, dim_1
>>> agg_reclassify_da = reclassify(agg_da, bins=bins, new_values=new_values) # noqa
>>> print(agg_reclassify_da)
<xarray.DataArray 'reclassify' (dim_0: 4, dim_1: 5)>
dask.array<_run_numpy_bin, shape=(4, 5), dtype=float32, chunksize=(3, 3), chunktype=numpy.ndarray>
dask.array<xrspatial.reclassify, shape=(4, 5), dtype=float32, chunksize=(3, 3), chunktype=numpy.ndarray>
Dimensions without coordinates: dim_0, dim_1
>>> print(agg_reclassify_da.compute()) # print the computed the results
<xarray.DataArray 'reclassify' (dim_0: 4, dim_1: 5)>
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.
Expand All @@ -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))
<class 'cupy.core.core.ndarray'>
<class 'cupy.ndarray'>
>>> print(agg_reclassify_cupy)
<xarray.DataArray 'reclassify' (dim_0: 4, dim_1: 5)>
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.
Expand Down Expand Up @@ -1033,10 +1033,10 @@ def equal_interval(agg: xr.DataArray,
>>> print(numpy_equal_interval)
<xarray.DataArray 'equal_interval' (dim_0: 5, dim_1: 5)>
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)
Expand Down Expand Up @@ -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)
<xarray.DataArray 'std_mean' (dim_0: 5, dim_1: 5)>
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)

Expand Down Expand Up @@ -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)
<xarray.DataArray 'head_tail_breaks' (dim_0: 5, dim_1: 5)>
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)

Expand Down Expand Up @@ -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)
<xarray.DataArray 'percentiles' (dim_0: 5, dim_1: 5)>
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)

Expand Down Expand Up @@ -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)
<xarray.DataArray 'maximum_breaks' (dim_0: 5, dim_1: 5)>
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)
Expand Down Expand Up @@ -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)
<xarray.DataArray 'box_plot' (dim_0: 5, dim_1: 5)>
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)

Expand Down
Loading