geotiff: keep no-georef int coords through to_geotiff round-trip (#1949)#1954
Merged
brendancol merged 3 commits intoMay 15, 2026
Merged
Conversation
6989b91 to
497d7c5
Compare
Contributor
Author
PR Review: geotiff: keep no-georef int coords through to_geotiff round-trip (#1949)Blockers (must fix before merge)
Suggestions (should fix, not blocking)
Nits (optional improvements)
What looks good
Checklist
|
brendancol
added a commit
that referenced
this pull request
May 15, 2026
brendancol
added a commit
that referenced
this pull request
May 15, 2026
b3c3644 to
c996afc
Compare
Contributor
Author
PR Review: geotiff: keep no-georef int coords through to_geotiff round-trip (#1949) (re-review after rebase)Rebased onto Blockers
Suggestions
Nits
What looks good
Checklist
|
``_coords_to_transform`` previously inferred a unit GeoTransform from the integer pixel coords the read-side no-georef branch emits (``np.arange(N, dtype=np.int64)``), so writing a no-georef DataArray back through ``to_geotiff`` silently injected ``ModelPixelScale`` / ``ModelTiepoint`` tags. On the next read the file looked georeferenced, the coord dtype flipped to float64, and a synthetic ``attrs['transform']`` appeared. Short-circuit when either spatial coord array has an integer dtype -- that signal only comes from the read-side no-georef fallback, so returning ``None`` here keeps the no-georef contract across an arbitrary number of read -> write -> read cycles on every writer path (eager numpy, dask streaming, GPU). An explicit ``attrs['transform']`` still wins because the writers consult it before calling this helper. Adds ``test_no_georef_writer_round_trip_1949.py`` covering the helper directly, eager / dask streaming / GPU round-trips, a double round-trip, and the explicit-attr override.
tifffile is not a runtime dep, so the unconditional module-level import broke collection on CI where tifffile isn't installed. Switch to ``pytest.importorskip`` to skip the file gracefully instead, matching the pattern used by other geotiff tests (``test_miniswhite_nodata_1809``, ``test_predictor3_big_endian``). Also drop two unused stdlib imports.
c996afc to
8da3ca7
Compare
Contributor
Author
|
Rebased onto current main at |
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 #1949.
Summary
_coords_to_transformnow returnsNonewhen either spatial coord array has an integer dtype, so the read-side no-georef contract (open_geotiff windowed reads of non-georef TIFFs produce float64 half-pixel-shifted coords #1710, geotiff: GPU stripped windowed read of non-georef TIFF emits float64 coords (regression of #1710) #1753) survives a round-trip throughto_geotiff.[0, 1, 2, ...]produced a unitGeoTransform(origin_x=-0.5, origin_y=-0.5, pixel_width=1.0, pixel_height=1.0)that the writer emitted asModelPixelScale/ModelTiepointtags. On the next read the file looked georeferenced, the coord dtype silently flipped tofloat64, and a syntheticattrs['transform']appeared.attrs['transform']still wins because the writers consult it first; the helper only feeds the implicit-from-coords fallback.Test plan
_coords_to_transformfor int64 / int32 / float / 3D-yxband.to_geotiff(eager numpy, dask streaming, GPU).attrs['transform']override test.test_coords_to_transform_3d_1643.py,test_metadata_round_trip_1484.py,test_attrs_parity_1548.py,test_coord_regularity_1720.py,test_coords_1813.py,test_georef_edges.pystill pass.mainare unrelated to this change:test_predictor2_big_endian_gpu_1517.py,test_reader_kwarg_order_1935.py,test_size_param_validation_gpu_vrt_1776.py::TestWriteGeotiffGpuTileSize::test_tile_size_positive_works).