Skip to content

Refactor GeoTIFF Phase 2: centralize transform/georef contract (PR-B of #2211) #2225

@brendancol

Description

@brendancol

Summary

Part of epic #2211. Phase 2 deliverable: one shared transform/georef resolver that every backend (read and write) calls, with parity tests across the supported cases. Replaces hand-copied coord-to-transform and georef classification logic that currently lives in multiple modules.

Scope

Refactor + parity tests. No public API change.

Files

  • Modify: xrspatial/geotiff/_coords.py — promote/centralize coords_to_transform, add resolve_georef() that returns a typed result.
  • Modify: xrspatial/geotiff/_attrs.pygeoref_status derivation routes through resolve_georef().
  • Modify: xrspatial/geotiff/_writers/eager.py, _writers/gpu.py, _writers/vrt.py — call the resolver instead of inline logic.
  • Modify: xrspatial/geotiff/_backends/vrt.py — call the resolver.
  • Create: xrspatial/geotiff/tests/test_georef_resolver_parity_2211.py.

Resolver contract

  • Input: a DataArray, or coord arrays + crs hint + transform hint.
  • Output: a GeorefResolution dataclass:
    • transform: GeoTransform | None
    • georef_status: Literal["none","coords","transform-only","crs-only","rotated-dropped","full"]
    • dropped_reason: str | None
    • applied_no_georef_marker: bool
  • Owns: coord-to-transform inference, no-georef marker behavior, degenerate axis policy, rotated-affine read-only/drop policy.

Parity tests

Cover at minimum:

  • y/x dim names
  • lat/lon dim names
  • row/col dim names (no georef)
  • transform-only (no CRS)
  • CRS-only (no transform)
  • rotated-affine dropped on read

For each case, assert identical GeorefResolution produced from every supported call site.

Acceptance

  • All 6 fixture cases produce identical GeorefResolution across eager/Dask/VRT call sites.
  • xrspatial/geotiff/tests/test_georef_status_2136.py and the test_allow_rotated_* suites still pass.
  • No call site outside _coords.py / _attrs.py builds a GeoTransform by hand on the read or write paths covered.
  • No public API change.

Closes part of #2211.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions