Describe the bug
The planar slope() path passes cell sizes straight into divisions in the slope kernel without validating them first. Bad resolutions produce confusing results:
- Zero resolution raises a raw
ZeroDivisionError, which is cryptic and doesn't point at the cause.
- NaN resolution silently returns NaN across the interior, with no hint that the cell size was the problem.
- Inf resolution yields wrong values that look plausible, with no warning.
curvature() already guards against this. It reads the resolution, checks that both axes are non-zero and finite, and raises a clear ValueError naming the bad values. slope() should do the same.
To Reproduce
import numpy as np
import xarray as xr
from xrspatial import slope
data = np.zeros((5, 5), dtype=np.float32)
agg = xr.DataArray(data, attrs={'res': (0, 0)})
slope(agg) # ZeroDivisionError instead of a clear message
Expected behavior
slope() should raise a clear ValueError for zero, negative, NaN, or infinite cell sizes on either axis, matching the existing curvature() guard. The message should name the offending values and say how to fix the resolution.
Additional context
The check belongs in the public slope() wrapper so it applies uniformly across all four backends (numpy, cupy, dask+numpy, dask+cupy) on the planar path. The geodesic path takes its scale from lat/lon coordinates and is unaffected.
Describe the bug
The planar
slope()path passes cell sizes straight into divisions in the slope kernel without validating them first. Bad resolutions produce confusing results:ZeroDivisionError, which is cryptic and doesn't point at the cause.curvature()already guards against this. It reads the resolution, checks that both axes are non-zero and finite, and raises a clearValueErrornaming the bad values.slope()should do the same.To Reproduce
Expected behavior
slope()should raise a clearValueErrorfor zero, negative, NaN, or infinite cell sizes on either axis, matching the existingcurvature()guard. The message should name the offending values and say how to fix the resolution.Additional context
The check belongs in the public
slope()wrapper so it applies uniformly across all four backends (numpy, cupy, dask+numpy, dask+cupy) on the planar path. The geodesic path takes its scale from lat/lon coordinates and is unaffected.