Parent: #2162
Depends on: #2177 (adds the eager helper)
Goal
Replace duplicated finalization in the four eager paths with _finalize_eager_read from #2177.
Scope
Four call sites:
xrspatial/geotiff/__init__.py:711-867 — eager numpy in open_geotiff. About 150 lines.
xrspatial/geotiff/_backends/gpu.py:470-508 — GPU CPU-fallback eager (stripped or bps-mismatch path).
xrspatial/geotiff/_backends/gpu.py:861-880 — GPU local eager (main path).
xrspatial/geotiff/_backends/gpu.py:980-1016 — GPU HTTP eager.
Each site is a near-copy of: validate geo_info, populate attrs, mask using a sentinel, compute nodata_pixels_present, cast dtype, record nodata_dtype_cast, call _set_nodata_attrs, construct DataArray.
The three GPU sites derive mask_sentinel three different ways:
_backends/gpu.py:470-508: from _cpu_fallback_geo._mask_nodata.
_backends/gpu.py:861-880: from _mw_mask_nodata local.
_backends/gpu.py:980-1016: from raw nodata.
The helper takes mask_sentinel as an explicit parameter. Callers pass whichever they have.
Preserve all current behavior:
attrs['nodata_pixels_present'] is set as a bool from a real scan of the array.
- Float vs int sentinel branching: integer sources with a sentinel promote to float64; float sources mask in place.
- MinIsWhite inversion still happens before finalization.
- GPU paths return CuPy-backed DataArrays.
Tests
Add xrspatial/geotiff/tests/test_eager_finalization_parity_2162.py. Parametrize over numpy and cupy (eager GPU). Assert:
- Both backends produce the same attrs dict (modulo array backend) for matched inputs.
nodata_pixels_present matches as a bool across both.
nodata_dtype_cast matches.
- Float-vs-int sentinel handling matches.
georef_status matches.
Skip GPU tests when CUDA is unavailable.
Files
xrspatial/geotiff/__init__.py (rewrite 711-867 to call _finalize_eager_read)
xrspatial/geotiff/_backends/gpu.py (rewrite three eager sites to call _finalize_eager_read)
xrspatial/geotiff/tests/test_eager_finalization_parity_2162.py (new)
Constraints
- No public API change.
- Existing eager tests must still pass, especially:
test_nodata_lifecycle_attrs_2135.py, test_nodata_semantics_split_1988.py, test_georef_status_2136.py, test_gpu_nodata_1542.py.
_validate_read_geo_info runs first. Partial attrs must not leak on validation failure.
Out of scope
- Dask backends (sibling PR C in wave 2).
- VRT (PR E in wave 3).
Parent: #2162
Depends on: #2177 (adds the eager helper)
Goal
Replace duplicated finalization in the four eager paths with
_finalize_eager_readfrom #2177.Scope
Four call sites:
xrspatial/geotiff/__init__.py:711-867— eager numpy inopen_geotiff. About 150 lines.xrspatial/geotiff/_backends/gpu.py:470-508— GPU CPU-fallback eager (stripped or bps-mismatch path).xrspatial/geotiff/_backends/gpu.py:861-880— GPU local eager (main path).xrspatial/geotiff/_backends/gpu.py:980-1016— GPU HTTP eager.Each site is a near-copy of: validate geo_info, populate attrs, mask using a sentinel, compute
nodata_pixels_present, cast dtype, recordnodata_dtype_cast, call_set_nodata_attrs, construct DataArray.The three GPU sites derive
mask_sentinelthree different ways:_backends/gpu.py:470-508: from_cpu_fallback_geo._mask_nodata._backends/gpu.py:861-880: from_mw_mask_nodatalocal._backends/gpu.py:980-1016: from rawnodata.The helper takes
mask_sentinelas an explicit parameter. Callers pass whichever they have.Preserve all current behavior:
attrs['nodata_pixels_present']is set as a bool from a real scan of the array.Tests
Add
xrspatial/geotiff/tests/test_eager_finalization_parity_2162.py. Parametrize overnumpyandcupy(eager GPU). Assert:nodata_pixels_presentmatches as a bool across both.nodata_dtype_castmatches.georef_statusmatches.Skip GPU tests when CUDA is unavailable.
Files
xrspatial/geotiff/__init__.py(rewrite 711-867 to call_finalize_eager_read)xrspatial/geotiff/_backends/gpu.py(rewrite three eager sites to call_finalize_eager_read)xrspatial/geotiff/tests/test_eager_finalization_parity_2162.py(new)Constraints
test_nodata_lifecycle_attrs_2135.py,test_nodata_semantics_split_1988.py,test_georef_status_2136.py,test_gpu_nodata_1542.py._validate_read_geo_inforuns first. Partial attrs must not leak on validation failure.Out of scope