Skip to content

reproject ignores attrs['nodatavals'] when rioxarray is not installed #1573

@brendancol

Description

@brendancol

reproject() reads nodata from attrs['_FillValue'], attrs['nodata'], attrs['missing_value'] (via _detect_nodata in _crs_utils.py), but skips the rasterio convention key attrs['nodatavals'].

When rioxarray is installed the raster.rio.nodata accessor picks up nodatavals and the fall-through never matters. Without rioxarray, a raster carrying only nodatavals is treated as if nodata is NaN, so the user-provided sentinel pixels survive resampling as if they were real data. The output then carries the old nodatavals attr alongside a fresh nodata of NaN -- two contradictory keys for the same concept.

resample.py already handles nodatavals (lines 1389-1396), so the convention is recognised elsewhere in xrspatial; the inconsistency is local to reproject.

Reproduction

# Without rioxarray installed:
import numpy as np
import xarray as xr
from xrspatial.reproject import reproject

r = xr.DataArray(
    np.full((16, 16), -9999, dtype=np.int32),
    dims=['y', 'x'],
    coords={'y': np.linspace(50, 40, 16), 'x': np.linspace(-5, 5, 16)},
    attrs={'crs': 'EPSG:4326', 'nodatavals': (-9999,)},
)
out = reproject(r, 'EPSG:3857')
# out.attrs['nodata'] == nan  (-9999 sentinel was ignored)
# out.attrs['nodatavals'] == (-9999,)  (stale, carried forward)
# Data was resampled treating -9999 as a real value.

Expected behaviour

  • _detect_nodata should consult attrs['nodatavals'] after _FillValue / nodata / missing_value.
  • On output, if input carried nodatavals, replace its value with the resolved nodata to keep both keys consistent (or drop nodatavals after the nodata key is set authoritatively).

Suggested fix

  1. In _crs_utils.py::_detect_nodata, add nodatavals to the attrs scan (handle the tuple shape: take element 0).
  2. In reproject.__init__::reproject (around line 715-727 where out_attrs is built), if nodatavals is present in input attrs, update it to a tuple of the resolved nodata (or drop it so only the canonical nodata remains).
  3. Same fix for merge() (around line 1629-1641).

Metadata

Metadata

Assignees

No one assigned

    Labels

    apiAPI design and consistencybugSomething isn't workinginput-validationInput validation and error messages

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions