Skip to content

Fix read_vrt dropping SimpleSource <NODATA>0</NODATA> (#1655)#1663

Merged
brendancol merged 1 commit into
mainfrom
deep-sweep-accuracy-geotiff-2026-05-12
May 12, 2026
Merged

Fix read_vrt dropping SimpleSource <NODATA>0</NODATA> (#1655)#1663
brendancol merged 1 commit into
mainfrom
deep-sweep-accuracy-geotiff-2026-05-12

Conversation

@brendancol
Copy link
Copy Markdown
Contributor

Summary

Closes #1655.

xrspatial.geotiff._vrt.read_vrt silently treated <NODATA>0</NODATA> on a SimpleSource as if the element were absent. The per-source nodata fallback used src.nodata or nodata; Python evaluates 0.0 or <anything> to <anything> because 0.0 is falsy. The in-code comment described the behaviour as "backward compatibility" but the result is silent data corruption on VRTs that mosaic sources using 0 as a sentinel (a common remote-sensing convention for unsigned imagery).

Switch to an explicit is not None check so a legitimate zero sentinel survives the fallback. The behaviour now matches the per-source nodata semantics that GDAL applies.

Test plan

  • New regression tests in test_vrt_source_nodata_zero_1655.py (5 tests): source NODATA=0 with no band fallback, integer XML literal <NODATA>0</NODATA>, non-zero unchanged, band-level <NoDataValue>0</NoDataValue> still honoured, per-source NODATA precedence over a different band sentinel.
  • All 100 existing vrt-related geotiff tests still pass.
  • Full geotiff suite: 1475 passed (3 pre-existing matplotlib palette failures unrelated to this change).

Notes

Found via /deep-sweep accuracy pass 19 on the geotiff module. State file updated in the same commit.

The per-source nodata fallback used `src.nodata or nodata`, and Python
treats `0.0` as falsy. A SimpleSource that declared `<NODATA>0</NODATA>`
silently picked up the band-level `<NoDataValue>` (or `None` when none
was set), so pixels equal to 0.0 in the source file survived as valid
data instead of being masked to NaN. The in-code comment described the
behaviour as "backward compatibility" but the result is silent data
corruption on VRTs that mosaic sources using 0 as a sentinel (a common
remote-sensing convention).

Switch to an explicit `is not None` check so a legitimate zero sentinel
survives the fallback.

Add `test_vrt_source_nodata_zero_1655.py` covering five cases: source
NODATA=0 with no band fallback, integer XML literal, non-zero unchanged,
band-level NoDataValue=0 still honoured when no per-source NODATA is
set, and per-source precedence over a different band-level sentinel.
@github-actions github-actions Bot added the performance PR touches performance-sensitive code label May 12, 2026
@brendancol brendancol merged commit 2d0e067 into main May 12, 2026
12 checks passed
@brendancol brendancol deleted the deep-sweep-accuracy-geotiff-2026-05-12 branch May 15, 2026 04:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance PR touches performance-sensitive code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

geotiff: read_vrt silently drops SimpleSource <NODATA>0</NODATA>

1 participant