Description
The planar dask backends of aspect() (and by extension northness() /
eastness()) advertise a lazy dtype of float64, but the array they
actually compute is float32. The numpy and cupy backends correctly
report float32.
This is a backend-inconsistent metadata bug. Code that reads agg.dtype
to make a decision (buffer allocation, storage class, a dtype assertion)
gets a different answer on the dask backends than on numpy/cupy, and the
dtype silently flips from float64 to float32 once .compute() runs.
Root cause
In xrspatial/aspect.py, the planar dask functions call map_overlap
with a default-dtype meta:
_run_dask_numpy: meta=np.array(()) (defaults to float64)
_run_dask_cupy: meta=cupy.array(()) (defaults to float64)
But the chunk functions _cpu / _run_cupy cast to and return float32.
Dask trusts meta for the advertised dtype, so the lazy DataArray reports
float64 while the realized data is float32. The geodesic dask paths already
pass meta=np.array((), dtype=np.float32), so they are fine. Only the
planar paths are affected.
Reproduction
import numpy as np, xarray as xr, dask.array as da
from xrspatial import aspect
data = np.random.rand(8, 10).astype(np.float64) * 100
arr = xr.DataArray(da.from_array(data, chunks=(4, 5)),
dims=['y', 'x'],
coords={'y': np.arange(8), 'x': np.arange(10)})
out = aspect(arr)
print(out.dtype) # float64 (advertised)
print(out.compute().dtype) # float32 (realized)
Expected: both print float32, matching the numpy and cupy backends.
Fix
Pass an explicit dtype to the planar dask meta: np.float32 for the
numpy path and cupy.float32 for the cupy path, mirroring what the
geodesic dask paths already do.
Note
slope.py and curvature.py share the same default-dtype meta pattern on
their planar dask paths. They are out of scope here but likely have the
same inconsistency.
Found via metadata-propagation sweep.
Description
The planar dask backends of
aspect()(and by extensionnorthness()/eastness()) advertise a lazy dtype offloat64, but the array theyactually compute is
float32. The numpy and cupy backends correctlyreport
float32.This is a backend-inconsistent metadata bug. Code that reads
agg.dtypeto make a decision (buffer allocation, storage class, a dtype assertion)
gets a different answer on the dask backends than on numpy/cupy, and the
dtype silently flips from
float64tofloat32once.compute()runs.Root cause
In
xrspatial/aspect.py, the planar dask functions callmap_overlapwith a default-dtype meta:
_run_dask_numpy:meta=np.array(())(defaults to float64)_run_dask_cupy:meta=cupy.array(())(defaults to float64)But the chunk functions
_cpu/_run_cupycast to and return float32.Dask trusts
metafor the advertised dtype, so the lazy DataArray reportsfloat64 while the realized data is float32. The geodesic dask paths already
pass
meta=np.array((), dtype=np.float32), so they are fine. Only theplanar paths are affected.
Reproduction
Expected: both print
float32, matching the numpy and cupy backends.Fix
Pass an explicit
dtypeto the planar daskmeta:np.float32for thenumpy path and
cupy.float32for the cupy path, mirroring what thegeodesic dask paths already do.
Note
slope.pyandcurvature.pyshare the same default-dtype meta pattern ontheir planar dask paths. They are out of scope here but likely have the
same inconsistency.
Found via metadata-propagation sweep.