Description
convolution_2d / convolve_2d promote an integer or float32 raster to float32 on the eager numpy and cupy backends, but the dask backends advertise float64. The declared dask dtype also does not match the float32 chunks that dask actually computes, because the meta array passed to map_overlap is hardcoded to the numpy default float64.
float32 rasters are common (most GeoTIFF elevation data), so a pipeline that switches from a numpy DataArray to a dask-backed one sees the output dtype change from float32 to float64 for the same input, and result.dtype disagrees with the values produced on compute.
Reproduction
import numpy as np
import dask.array as da
from xrspatial.convolution import convolve_2d, circle_kernel
K = circle_kernel(1, 1, 1)
data = np.arange(64, dtype=np.float32).reshape(8, 8)
eager = convolve_2d(data, K)
lazy = convolve_2d(da.from_array(data, chunks=(4, 4)), K)
print("eager :", eager.dtype) # float32
print("dask :", lazy.dtype) # float64 (declared)
print("dask computed:", lazy.compute().dtype) # float32 (actual)
Observed:
eager : float32
dask : float64
dask computed: float32
The same mismatch happens for int32 input. For float64 input all backends agree (float64), so the bug only shows up when the input is promoted.
Cause
In xrspatial/convolution.py, _convolve_2d_dask_numpy and _convolve_2d_dask_cupy cast the data with _promote_float(data.dtype) but pass meta=np.array(()) / meta=cupy.array(()), which is float64. map_overlap takes the declared dtype from meta, so the array claims float64 even though every chunk is float32.
Fix
Pass the promoted float dtype into meta so the declared dtype matches both the eager backends and the computed chunks.
Description
convolution_2d/convolve_2dpromote an integer or float32 raster to float32 on the eager numpy and cupy backends, but the dask backends advertisefloat64. The declared dask dtype also does not match the float32 chunks that dask actually computes, because themetaarray passed tomap_overlapis hardcoded to the numpy default float64.float32 rasters are common (most GeoTIFF elevation data), so a pipeline that switches from a numpy DataArray to a dask-backed one sees the output dtype change from float32 to float64 for the same input, and
result.dtypedisagrees with the values produced on compute.Reproduction
Observed:
The same mismatch happens for int32 input. For float64 input all backends agree (float64), so the bug only shows up when the input is promoted.
Cause
In
xrspatial/convolution.py,_convolve_2d_dask_numpyand_convolve_2d_dask_cupycast the data with_promote_float(data.dtype)but passmeta=np.array(())/meta=cupy.array(()), which is float64.map_overlaptakes the declared dtype frommeta, so the array claims float64 even though every chunk is float32.Fix
Pass the promoted float dtype into
metaso the declared dtype matches both the eager backends and the computed chunks.