Describe the bug
reproject collapses per-band nodata to a single sentinel for multi-band rasters. _detect_nodata_raw() in xrspatial/reproject/_crs_utils.py accepts the nodatavals attribute (the rasterio per-band convention) but reads only the first entry (nv[0]). The 3-D worker in xrspatial/reproject/__init__.py then applies that one sentinel to every band when converting source nodata to NaN, and the output nodatavals attr repeats the same value across all bands.
So for a raster whose bands declare different nodata values (say band 0 = -9999, band 1 = 255), only band 0's sentinel gets masked. Band 1's invalid pixels are treated as real data and resampled into the output.
Expected behavior
Each band's own nodata sentinel should be masked before resampling, so invalid pixels in every band become NaN (or the resolved output sentinel) instead of leaking through as valid data. The output nodatavals attr should keep the per-band values.
To reproduce
Build a 3-band DataArray with attrs['nodatavals'] = (-9999, 255, 0), drop a distinct sentinel into each band, and reproject. The band 1 and band 2 sentinels survive into the output as if they were valid samples.
Affected backends
numpy, cupy, dask+numpy, dask+cupy.
Additional context
Cited lines: _crs_utils.py:232 (reads nv[0] only), __init__.py:413 (per-band loop uses the single sentinel), __init__.py:1005 (output attr repeats one value).
Describe the bug
reprojectcollapses per-band nodata to a single sentinel for multi-band rasters._detect_nodata_raw()inxrspatial/reproject/_crs_utils.pyaccepts thenodatavalsattribute (the rasterio per-band convention) but reads only the first entry (nv[0]). The 3-D worker inxrspatial/reproject/__init__.pythen applies that one sentinel to every band when converting source nodata to NaN, and the outputnodatavalsattr repeats the same value across all bands.So for a raster whose bands declare different nodata values (say band 0 = -9999, band 1 = 255), only band 0's sentinel gets masked. Band 1's invalid pixels are treated as real data and resampled into the output.
Expected behavior
Each band's own nodata sentinel should be masked before resampling, so invalid pixels in every band become NaN (or the resolved output sentinel) instead of leaking through as valid data. The output
nodatavalsattr should keep the per-band values.To reproduce
Build a 3-band DataArray with
attrs['nodatavals'] = (-9999, 255, 0), drop a distinct sentinel into each band, and reproject. The band 1 and band 2 sentinels survive into the output as if they were valid samples.Affected backends
numpy, cupy, dask+numpy, dask+cupy.
Additional context
Cited lines:
_crs_utils.py:232(readsnv[0]only),__init__.py:413(per-band loop uses the single sentinel),__init__.py:1005(output attr repeats one value).