Problem
equal_interval() raises ZeroDivisionError when the input has max == min (all pixels equal, modulo NaN/inf). Other classifiers handle this case: std_mean collapses to a single class (see test_std_mean_all_same_values).
Reproduction
import numpy as np
import xarray as xr
from xrspatial.classify import equal_interval
agg = xr.DataArray(np.full((4, 5), 7.0))
equal_interval(agg)
# ZeroDivisionError: division by zero
Root Cause
_run_equal_interval in xrspatial/classify.py:890-892:
width = (max_data - min_data) / k
cuts = np.arange(min_data + width, max_data + width, width)
When max_data == min_data, width = 0 and np.arange(x, x, 0) raises ZeroDivisionError.
Fix
Short-circuit the degenerate case: if max_data == min_data (or min/max are non-finite), assign every finite pixel to a single class.
Scope
Affects numpy, cupy, dask-numpy, and dask-cupy backends (shared _run_equal_interval).
Found by
Security sweep (Cat 3 - NaN/Inf logic error, MEDIUM severity).
Problem
equal_interval()raisesZeroDivisionErrorwhen the input hasmax == min(all pixels equal, modulo NaN/inf). Other classifiers handle this case:std_meancollapses to a single class (seetest_std_mean_all_same_values).Reproduction
Root Cause
_run_equal_intervalinxrspatial/classify.py:890-892:When
max_data == min_data,width = 0andnp.arange(x, x, 0)raisesZeroDivisionError.Fix
Short-circuit the degenerate case: if
max_data == min_data(or min/max are non-finite), assign every finite pixel to a single class.Scope
Affects numpy, cupy, dask-numpy, and dask-cupy backends (shared
_run_equal_interval).Found by
Security sweep (Cat 3 - NaN/Inf logic error, MEDIUM severity).