geotiff: align direct backend mask_nodata default with open_geotiff#2980
Merged
Conversation
…2976) The three direct backend entry points (_read_geotiff_dask, _read_geotiff_gpu, _read_vrt) defaulted to mask_nodata=True while the public open_geotiff defaults to masked=False. A bare backend call returned a different dtype and NaN-substituted values than the public path. Flip the three defaults to False so a direct call with no mask_nodata argument matches open_geotiff (unmasked, rioxarray-style). The public wrapper and the internal GPU-to-dask / dask-to-VRT callers all forward mask_nodata explicitly, so only direct callers are affected. Tests: add direct-backend-vs-open_geotiff parity regression tests; update existing tests that relied on the old masked default to request masking explicitly (mask_nodata=True) or assert the new unmasked default.
brendancol
commented
Jun 5, 2026
Contributor
Author
brendancol
left a comment
There was a problem hiding this comment.
PR Review: geotiff: align direct backend mask_nodata default with open_geotiff
Blockers (must fix before merge)
None.
Suggestions (should fix, not blocking)
One note, not blocking. The internal helpers that aren't public entry points kept mask_nodata: bool = True: _read_geotiff_gpu_chunked_gds in gpu.py, plus _vrt_chunk_read and the chunked dispatch in vrt.py. That's correct. They always get an explicit mask_nodata forwarded from the entry point and aren't a caller's direct surface. The tests in test_reader.py and test_kernels_and_kwargs.py now pass mask_nodata=True to both sides when they compare an entry point against an internal helper, so those comparisons stay apples-to-apples. Flagging it only so the next reader doesn't mistake the asymmetry for an oversight.
Nits (optional improvements)
None.
What looks good
- The source change is small: three default flips and the matching
default Truetodefault Falsedocstring edits. Everything else in the diff is test updates. - The public wrapper forwards
mask_nodata=maskedon every dispatch path (GPU, dask, VRT, eager), and the two internal cross-backend callers (gpu.py:1422 to_read_geotiff_dask, dask.py:227 to_read_vrt) forward it explicitly. So the default only affects direct callers. Confirmed by reading the call sites. - The new regression tests check direct-backend-vs-
open_geotiffparity for all three backends (GPU guarded byrequires_gpu): dtype, sentinel survival, no NaN, bit-equal pixels. - Existing tests that pinned the old masked default were split the right way. Masking-path tests now request
mask_nodata=True; default-behavior tests assert the new unmasked default and were renamed for #2976. - Full geotiff suite passes locally including GPU (6155 passed).
Checklist
- Behavior change matches the issue: direct backend default now matches open_geotiff
- All three backends produce consistent unmasked results with no mask_nodata arg
- NaN / sentinel handling correct: masking still available via mask_nodata=True
- Edge cases covered: int sentinel hit, float sentinel, dtype preservation, dask + GPU graphs
- Internal helper defaults left untouched (correct: they receive explicit values)
- No premature materialization or new copies (no compute path changed)
- Benchmark not needed (no perf-critical path changed)
- README feature matrix not applicable (no new public function)
- Docstrings updated to default False on all three backends
# Conflicts: # xrspatial/geotiff/tests/read/test_rioxarray_compat_2961.py # xrspatial/geotiff/tests/vrt/test_metadata.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2976
What
The three direct GeoTIFF backend entry points defaulted to
mask_nodata=Truewhile the publicopen_geotiffdefaults tomasked=False. A bare backend call returned a different dtype and NaN-substituted values than the public path, silently._read_geotiff_dask,_read_geotiff_gpu, and_read_vrttomask_nodata=Falseso a direct call with nomask_nodataargument matchesopen_geotiff(unmasked, rioxarray-compatible).mask_nodataexplicitly, so only direct callers are affected.Backend coverage
The dask and VRT entry points cover numpy and cupy graphs; the GPU entry point covers eager and dask+cupy. The default flip applies the same way on all of them.
Test plan
mask_nodataproduces the same unmasked result (dtype + sentinel preserved, no NaN) asopen_geotiff. The GPU test is guarded byrequires_gpu.mask_nodata=True; where a test pinned the bare-call behavior it asserts the new unmasked default.