Skip to content

apply() and focal_stats() give backend-dependent results on non-binary kernels #2848

@brendancol

Description

@brendancol

Describe the bug

apply() and focal_stats() in xrspatial/focal.py document the kernel argument as "2D array where values of 1 indicate the kernel", i.e. a binary membership mask. But the CPU and GPU paths disagree on what a non-binary value (say, 2) means, so the same call can return different numbers depending on the backend.

CPU: _apply_numpy only copies a neighbour into the window when kernel[...] == 1. A cell with weight 2 is neither masked out (0) nor included (1), so it gets dropped. focal_stats on numpy and dask+numpy delegates to apply and inherits this.

GPU: _focal_sum_cuda and _focal_mean_cuda treat every nonzero cell as a weight and accumulate w * v, so a 2 doubles that neighbour's contribution. The min/max/range/variety kernels treat nonzero as plain membership and ignore the weight, which is yet another interpretation of the same kernel.

So focal_stats(..., stats_funcs=['mean', 'sum']) and apply(...) can give different answers on the same non-binary kernel depending which backend runs.

Expected behavior

Same result across all four backends for a given kernel. The documented contract is a binary mask, and weighting is supposed to happen inside the user's func (the apply docstring example does exactly that). So apply and focal_stats should reject non-binary kernels with a clear error instead of silently producing backend-dependent numbers. convolve_2d and hotspots genuinely use weighted kernels and are unaffected.

Additional context

Affected functions: apply, focal_stats. Backends: numpy, cupy, dask+numpy, dask+cupy.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinggpuCuPy / CUDA GPU support

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions