Skip to content

geotiff: fix stripped-GPU windowed coords on non-georef TIFFs (#1753)#1759

Open
brendancol wants to merge 1 commit into
xarray-contrib:mainfrom
brendancol:deep-sweep-metadata-geotiff-2026-05-12-163707
Open

geotiff: fix stripped-GPU windowed coords on non-georef TIFFs (#1753)#1759
brendancol wants to merge 1 commit into
xarray-contrib:mainfrom
brendancol:deep-sweep-metadata-geotiff-2026-05-12-163707

Conversation

@brendancol
Copy link
Copy Markdown
Contributor

Summary

The eager numpy, dask, and tiled-GPU read paths all gate the windowed
coord computation on geo_info.has_georef so a TIFF with no GeoTIFF
tags returns int64 file-relative pixel coords.

read_geotiff_gpu's stripped-fallback branch only checked t is None,
which is never true for non-georef files (_extract_transform returns
a default unit GeoTransform with has_georef=False). The branch
synthesised float64 coords like [-0.5, -1.5, ...] from that
placeholder, breaking backend parity on every stripped, non-georef
windowed GPU read.

The tiled-GPU helper _gpu_apply_window_band already handles this
correctly; this PR brings the stripped branch in line.

Reproducer

import numpy as np
from xrspatial.geotiff import open_geotiff
from xrspatial.geotiff._writer import write

arr = np.arange(64, dtype=np.float32).reshape(8, 8)
write(arr, "/tmp/no_georef.tif", compression='none', tiled=False)

eager = open_geotiff("/tmp/no_georef.tif", window=(0, 0, 4, 4))
gpu = open_geotiff("/tmp/no_georef.tif", gpu=True, window=(0, 0, 4, 4))

eager.y.dtype, eager.y.values   # int64 [0 1 2 3]
gpu.y.dtype, gpu.y.values       # float64 [-0.5 -1.5 -2.5 -3.5]  -- before fix

Fix

read_geotiff_gpu line ~2727: route not has_georef (and the
pre-existing t is None failure mode) through the integer pixel-coord
branch, using offset-based np.arange(r0, r1) so file-relative
semantics match the eager and dask paths.

Test plan

  • New regression tests in test_no_georef_windowed_coords_1710.py
    cover the GPU offset-window case and the no-transform-attr case
  • All 17 tests in test_no_georef_windowed_coords_1710.py pass
  • All 86 metadata-propagation tests pass (test_attrs_parity_1548,
    test_metadata_round_trip_1484, test_dask_int_nodata_chunks_1597,
    test_coords_to_transform_3d_1643, test_gpu_nodata_1542,
    test_gpu_writer_attrs_1563, test_overview_nodata_inheritance_1739)
  • 4-backend parity verified end-to-end (numpy, cupy,
    dask+numpy, dask+cupy) on the stripped-non-georef-windowed case

Resolves #1753.

…h integer coords (xarray-contrib#1753)

The eager numpy / dask / tiled-GPU paths already gate the windowed coord
computation on geo_info.has_georef so a TIFF with no GeoTIFF tags returns
int64 file-relative pixel coords (e.g. [2,3,4,5] for window=(2,3,6,7)).

read_geotiff_gpu's stripped-fallback branch only checked t is None, which
is never true for non-georef files (extract_transform returns a default
unit GeoTransform with has_georef=False). The branch then synthesised
float64 coords like [-0.5, -1.5, ...] from that placeholder, breaking
backend parity on every stripped, non-georef windowed GPU read.

Mirror the eager-numpy guard: when geo_info.has_georef is False, emit
the same int64 file-relative coords every other backend produces. Use
offset-based np.arange(r0, r1) instead of the previous length-based
np.arange(r1 - r0) so the file-relative semantics match the eager and
dask paths.

Sweep-state row keyed to issue xarray-contrib#1753, severity HIGH, category 2.

Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added the performance PR touches performance-sensitive code label May 12, 2026
@brendancol brendancol requested a review from Copilot May 12, 2026 23:49
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes backend parity for windowed GPU reads of stripped, non-georeferenced TIFFs by ensuring the stripped-GPU fallback computes integer, file-relative pixel coordinates (matching eager NumPy, Dask, and tiled-GPU paths) instead of synthesizing float coords from the default placeholder GeoTransform.

Changes:

  • Update read_geotiff_gpu stripped fallback to route has_georef=False (and t is None) through the integer pixel-coordinate path using offset-based np.arange(r0, r1) / np.arange(c0, c1).
  • Add regression tests covering non-zero-origin windowed GPU reads for non-georeferenced TIFFs, including ensuring no fabricated attrs['transform'] is emitted.
  • Refresh internal sweep metadata state entry for the tracked GeoTIFF issue.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
xrspatial/geotiff/__init__.py Fixes stripped-GPU windowed coordinate computation for non-georef TIFFs to return integer file-relative coords.
xrspatial/geotiff/tests/test_no_georef_windowed_coords_1710.py Adds GPU regression tests for offset windows and verifies transform attr is not fabricated for non-georef reads.
.claude/sweep-metadata-state.csv Updates internal audit/state tracking entry for issue #1753.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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: GPU stripped windowed read of non-georef TIFF emits float64 coords (regression of #1710)

2 participants