Skip to content

apply() and focal_stats() silently downcast float64 input to float32 #2769

@brendancol

Description

@brendancol

Description

apply() and focal_stats() cast float64 input down to float32 on every backend. convolve_2d() already preserves the input floating dtype (via _promote_float) and has a test asserting this, but the focal functions don't, so a float64 raster silently comes back as float32.

The downcast happens in a few places in xrspatial/focal.py:

  • _apply_numpy casts with data.astype(np.float32) (~line 462)
  • _apply_dask_numpy casts with data.astype(np.float32) (~line 500)
  • _apply_cupy casts with data.astype(cupy.float32) (~line 513)
  • _focal_stats_func_cupy allocates the output as dtype='f4' (~line 985)
  • _focal_stats_cupy and _focal_stats_dask_cupy cast with data.astype(cupy.float32) (~lines 1041, 1092)

Expected behavior

apply() and focal_stats() should preserve the input floating dtype across all four backends (numpy, cupy, dask+numpy, dask+cupy): float64 in, float64 out, matching convolve_2d(). Integer input should still promote to at least float32.

Why it matters

Silent precision loss is a correctness footgun for downstream numerical work, and it's inconsistent: convolve_2d already preserves float64 and has a test for it. Focal should behave the same way.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdaskDask backend / chunked arraysgpuCuPy / 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