Reason or Problem
xrspatial.geotiff.open_geotiff and rioxarray's open_rasterio do the same job (read a GeoTIFF/COG/VRT into an xarray.DataArray), but their signatures diverge on parameter names and one default, so moving code between them needs edits:
- The nodata-masking flag is
mask_nodata (default True, promotes the sentinel to NaN) here, versus masked (default False) in open_rasterio. The name and the default both differ.
- The array-name kwarg is
name here, versus default_name in open_rasterio.
open_rasterio has mask_and_scale, parse_coordinates, lock, and cache; open_geotiff has no counterpart for any of them.
Proposal
Align the overlapping parameters with open_rasterio so a rioxarray-style call works on open_geotiff with minimal edits, while keeping the xrspatial-only parameters (gpu, window, bbox, max_pixels, allow_*, tier flags) and not renaming parameters that already match (chunks).
Design:
- Rename
mask_nodata -> masked and flip the default from True to False to match open_rasterio. Keep mask_nodata as a deprecated alias: passing it emits a DeprecationWarning, passing both masked and mask_nodata raises TypeError. This reuses the sentinel-based deprecation pattern already used for read_geotiff_gpu's gpu -> on_gpu_failure rename (_runtime.py sentinels + the resolution block in _backends/gpu.py).
- Rename
name -> default_name with the same deprecated-alias mechanism.
- Add
mask_and_scale (default False): read GDAL SCALE/OFFSET from attrs['gdal_metadata'], apply data * scale + offset, mask the nodata sentinel, and record attrs['scale_factor']/attrs['add_offset'], mirroring open_rasterio.
- Add
parse_coordinates (default True): when False, skip building the x/y coordinate arrays while keeping attrs['transform'] and attrs['crs'].
- Add
lock and cache for signature compatibility. xrspatial's dask reader re-opens the source per window, so there is no shared GDAL handle to lock and no caching backend to toggle; passing a non-default value emits a GeoTIFFFallbackWarning explaining this rather than silently ignoring the kwarg.
The four backend readers keep their internal kwarg names; the public contract change lives only at open_geotiff.
Usage:
from xrspatial.geotiff import open_geotiff
da = open_geotiff("dem.tif", masked=True) # was mask_nodata=True
da = open_geotiff("dem.tif", mask_and_scale=True) # apply SCALE/OFFSET, mask nodata
da = open_geotiff("dem.tif", parse_coordinates=False) # index coords, keep crs/transform attrs
Value: lowers the cost of switching from rioxarray and makes the reader's surface predictable for users who already know open_rasterio.
Stakeholders and Impacts
Affects callers of open_geotiff. The masking-default flip is a breaking behavior change: a bare open_geotiff(path) stops promoting the nodata sentinel to NaN. The deprecated mask_nodata alias keeps the old name working through a deprecation window.
Drawbacks
The masking-default flip changes the result of the default call path. mask_and_scale is new code and depends on GDAL writing scale/offset into the GDAL_METADATA tag. Sources without those items get a (1.0, 0.0) no-op.
Alternatives
- Additive aliases that keep the current masking default — rejected because a bare call would still not match
open_rasterio.
- Renaming every shared parameter including
chunks — rejected because chunks already matches.
Unresolved Questions
Whether lock/cache should map onto anything in the dask read path or stay accept-and-warn. The current plan is accept-and-warn.
Reason or Problem
xrspatial.geotiff.open_geotiffand rioxarray'sopen_rasteriodo the same job (read a GeoTIFF/COG/VRT into anxarray.DataArray), but their signatures diverge on parameter names and one default, so moving code between them needs edits:mask_nodata(defaultTrue, promotes the sentinel toNaN) here, versusmasked(defaultFalse) inopen_rasterio. The name and the default both differ.namehere, versusdefault_nameinopen_rasterio.open_rasteriohasmask_and_scale,parse_coordinates,lock, andcache;open_geotiffhas no counterpart for any of them.Proposal
Align the overlapping parameters with
open_rasterioso a rioxarray-style call works onopen_geotiffwith minimal edits, while keeping the xrspatial-only parameters (gpu,window,bbox,max_pixels,allow_*, tier flags) and not renaming parameters that already match (chunks).Design:
mask_nodata->maskedand flip the default fromTruetoFalseto matchopen_rasterio. Keepmask_nodataas a deprecated alias: passing it emits aDeprecationWarning, passing bothmaskedandmask_nodataraisesTypeError. This reuses the sentinel-based deprecation pattern already used forread_geotiff_gpu'sgpu->on_gpu_failurerename (_runtime.pysentinels + the resolution block in_backends/gpu.py).name->default_namewith the same deprecated-alias mechanism.mask_and_scale(defaultFalse): read GDALSCALE/OFFSETfromattrs['gdal_metadata'], applydata * scale + offset, mask the nodata sentinel, and recordattrs['scale_factor']/attrs['add_offset'], mirroringopen_rasterio.parse_coordinates(defaultTrue): whenFalse, skip building thex/ycoordinate arrays while keepingattrs['transform']andattrs['crs'].lockandcachefor signature compatibility. xrspatial's dask reader re-opens the source per window, so there is no shared GDAL handle to lock and no caching backend to toggle; passing a non-default value emits aGeoTIFFFallbackWarningexplaining this rather than silently ignoring the kwarg.The four backend readers keep their internal kwarg names; the public contract change lives only at
open_geotiff.Usage:
Value: lowers the cost of switching from rioxarray and makes the reader's surface predictable for users who already know
open_rasterio.Stakeholders and Impacts
Affects callers of
open_geotiff. The masking-default flip is a breaking behavior change: a bareopen_geotiff(path)stops promoting the nodata sentinel toNaN. The deprecatedmask_nodataalias keeps the old name working through a deprecation window.Drawbacks
The masking-default flip changes the result of the default call path.
mask_and_scaleis new code and depends on GDAL writing scale/offset into theGDAL_METADATAtag. Sources without those items get a(1.0, 0.0)no-op.Alternatives
open_rasterio.chunks— rejected becausechunksalready matches.Unresolved Questions
Whether
lock/cacheshould map onto anything in the dask read path or stay accept-and-warn. The current plan is accept-and-warn.