Skip to content
Open
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-style-state.csv
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module,last_inspected,issue,severity_max,categories_found,notes
geotiff,2026-05-27,2481,HIGH,1;3;4,"Bundled 387 flake8 + ~30 isort fixes since #2285/#2430. F401 x9, F811 x6, F841 x3. E501 x250 (mostly wrapped, 3 file-scope imports keep noqa: E402+E501). E252 x62, blank-line cluster, E128/E127 indents. importorskip imports use # noqa: E402. Cat 5 grep clean."
polygonize,2026-05-27,2534,HIGH,1;3;4,"F401 line 58 (is_cupy_array unused, not re-exported). E127 lines 83/88 (overload continuation indent in generated_jit). isort: 5-line .utils import block collapses to one line at 100-char limit. Cat 2 clean. Cat 5 grep clean."
proximity,2026-05-29,2725,HIGH,1;3;4;5,"F841 line 1274 original_chunks dead local in unbounded dask+cupy branch (refactor leftover). Cat 5 mutable default target_values: list = [] in proximity/allocation/direction -> None sentinel, normalized to [] in body (never mutated, behaviour preserved). E128 line 291 np.where continuation under-indent in _vectorized_calc_direction. isort: re-sorted xrspatial import block + blank line after inline import cupy as cp. flake8+isort clean after fix; 69 proximity tests pass + new parametrized regression test. Pre-existing E127 (test_proximity.py 726/752) + test-file isort drift left untouched (out of module scope)."
rasterize,2026-05-27,2503,HIGH,1;3,F401 line 15 + F811 line 1193 (paired: local import warnings shadowed unused module-level import); E306 line 1775 (nested @cuda.jit). isort clean. Cat 5 grep clean. Fix in PR #2507.
resample,2026-05-27,2543,MEDIUM,4,isort drift only: 4 multi-line parenthesised imports collapsed to single/one-per-line under line_length=100 (top-of-file scipy.ndimage + xrspatial.utils; local cupyx imports in _nan_aware_interp_cupy and _interp_block_cupy); two blank-line nits after import math in _run_dask_numpy/_run_dask_cupy. flake8 clean. Cat 5 grep clean. 169 resample tests pass.
zonal,2026-05-27,2522,HIGH,1;3;4,"F401 not_implemented_func (line 42, only present on import line). E501 line 455 (dd.concat one-liner, 117 chars) wrapped across 3 lines. isort: consolidated xrspatial.utils block (merged has_dask_array, dropped not_implemented_func, alphabetised, trimmed extra blank line). Cat 5 grep clean. 125 zonal tests pass."
28 changes: 17 additions & 11 deletions xrspatial/proximity.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,10 @@
class cupy(object):
ndarray = False

from xrspatial.pathfinding import _available_memory_bytes
from xrspatial.utils import (
_validate_raster,
cuda_args, get_dataarray_resolution, has_cuda_and_cupy,
is_cupy_array, is_dask_cupy, ngjit,
)
from xrspatial.dataset_support import supports_dataset
from xrspatial.pathfinding import _available_memory_bytes
from xrspatial.utils import (_validate_raster, cuda_args, get_dataarray_resolution,
has_cuda_and_cupy, is_cupy_array, is_dask_cupy, ngjit)

EUCLIDEAN = 0
GREAT_CIRCLE = 1
Expand Down Expand Up @@ -288,7 +285,7 @@ def _vectorized_calc_direction(x1, x2, y1, y2):
dy = y2 - y1
d = np.arctan2(-dy, dx) * 57.29578
result = np.where(d < 0, 90.0 - d,
np.where(d > 90.0, 360.0 - d + 90.0, 90.0 - d))
np.where(d > 90.0, 360.0 - d + 90.0, 90.0 - d))
result[(x1 == x2) & (y1 == y2)] = 0.0
return result.astype(np.float32)

Expand Down Expand Up @@ -1269,9 +1266,9 @@ def _process_dask(raster, xs, ys):
was_dask_cupy = has_cuda_and_cupy() and is_dask_cupy(raster)
if was_dask_cupy:
import cupy as cp

# Unbounded: convert to dask+numpy for KDTree/line-sweep
# (KDTree is CPU-only; O(N log T) beats brute-force O(NT))
original_chunks = raster.data.chunks
raster = raster.copy(
data=raster.data.map_blocks(
lambda x: x.get(), dtype=raster.dtype,
Expand Down Expand Up @@ -1344,7 +1341,7 @@ def proximity(
raster: xr.DataArray,
x: str = "x",
y: str = "y",
target_values: list = [],
target_values: list = None,
max_distance: float = np.inf,
distance_metric: str = "EUCLIDEAN",
) -> xr.DataArray:
Expand Down Expand Up @@ -1460,6 +1457,9 @@ def proximity(
* x (x) int64 0 1 2 3 4
"""

if target_values is None:
target_values = []

_validate_raster(raster, func_name='proximity', name='raster')

proximity_img = _process(
Expand Down Expand Up @@ -1487,7 +1487,7 @@ def allocation(
raster: xr.DataArray,
x: str = "x",
y: str = "y",
target_values: list = [],
target_values: list = None,
max_distance: float = np.inf,
distance_metric: str = "EUCLIDEAN",
):
Expand Down Expand Up @@ -1600,6 +1600,9 @@ def allocation(
* x (x) int64 0 1 2 3 4
"""

if target_values is None:
target_values = []

_validate_raster(raster, func_name='allocation', name='raster')

allocation_img = _process(
Expand Down Expand Up @@ -1627,7 +1630,7 @@ def direction(
raster: xr.DataArray,
x: str = "x",
y: str = "y",
target_values: list = [],
target_values: list = None,
max_distance: float = np.inf,
distance_metric: str = "EUCLIDEAN",
):
Expand Down Expand Up @@ -1746,6 +1749,9 @@ def direction(
* x (x) int64 0 1 2 3 4
"""

if target_values is None:
target_values = []

_validate_raster(raster, func_name='direction', name='raster')

direction_img = _process(
Expand Down
23 changes: 23 additions & 0 deletions xrspatial/tests/test_proximity.py
Original file line number Diff line number Diff line change
Expand Up @@ -961,3 +961,26 @@ def test_no_scipy_dask_unbounded_memory_guard():
proximity(raster, x='lon', y='lat')
finally:
prox_mod.cKDTree = original_ckdtree


@pytest.mark.parametrize("func", [proximity, allocation, direction])
def test_target_values_none_default_matches_empty_list(func):
# target_values default switched from [] to a None sentinel; passing
# None (the default) must behave exactly like passing an empty list.
data = np.asarray([[0., 0., 0., 0., 0.],
[0., 0., 0., 1., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 2., 0., 0.],
[0., 0., 0., 0., 0.]])
n, m = data.shape
raster = xr.DataArray(data, dims=['y', 'x'])
raster['y'] = np.arange(n)[::-1]
raster['x'] = np.arange(m)

default_result = func(raster)
explicit_result = func(raster, target_values=[])

np.testing.assert_array_equal(
np.nan_to_num(default_result.data),
np.nan_to_num(explicit_result.data),
)
Loading