Skip to content

Promote user-defined CRS WKT to attrs['crs_wkt'] on read (#1632)#1635

Merged
brendancol merged 2 commits into
xarray-contrib:mainfrom
brendancol:deep-sweep-metadata-geotiff-2026-05-11-add09518
May 11, 2026
Merged

Promote user-defined CRS WKT to attrs['crs_wkt'] on read (#1632)#1635
brendancol merged 2 commits into
xarray-contrib:mainfrom
brendancol:deep-sweep-metadata-geotiff-2026-05-11-add09518

Conversation

@brendancol
Copy link
Copy Markdown
Contributor

Summary

  • The read path was dropping the CRS WKT on user-defined CRS GeoTIFFs (GeoKey *CSTypeGeoKey == 32767), so a read -> write round-trip silently lost the projection. Fixed by promoting the WKT-looking citation to attrs['crs_wkt'] in extract_geo_info.
  • All four read backends (numpy / dask / cupy / dask+cupy) pick up the fix through the existing _populate_attrs_from_geo_info funnel.
  • crs_name stays set for back-compat. The new _looks_like_wkt gate keeps plain names ("NAD83 / UTM Zone 12N") out of crs_wkt.

Fixes #1632.

Test plan

  • New test_user_defined_crs_wkt_1632.py covers _looks_like_wkt (positive + negative), backend parity (eager / dask / cupy / dask+cupy), the read -> write -> read round trip, and a non-regression check on EPSG-based files.
  • Existing test_attrs_parity_1548.py and test_nodata_attr_aliases_1582.py still pass (no key-set changes for EPSG files).
  • Full geotiff suite passes locally except for two pre-existing matplotlib deepcopy recursion errors unrelated to this change.

…rib#1632)

GeoTIFFs with GeoKey *CSTypeGeoKey == 32767 store their CRS WKT in the
GeoTIFF citation rather than referencing an EPSG code. extract_geo_info
parsed the citation into geo_info.crs_name but left geo_info.crs_wkt
unset, so _populate_attrs_from_geo_info emitted attrs['crs_name'] only.
to_geotiff consults attrs['crs'] / attrs['crs_wkt'] but not 'crs_name',
so a read -> write round-trip silently dropped the projection on
user-defined CRS files. All four read backends were affected.

The fix promotes the citation to geo_info.crs_wkt when the citation
parses as WKT (top-level WKT 1 / WKT 2 root keywords: PROJCS[, GEOGCS[,
PROJCRS[, GEOGCRS[, COMPD_CS[, COMPOUNDCRS[, BOUNDCRS[, VERT_CS[,
VERTCRS[, LOCAL_CS[, ENGCRS, PARAMETRICCRS, TIMECRS, DERIVEDPROJCRS).
crs_name stays set for back-compat. Citations that are plain names
(e.g. 'NAD83 / UTM Zone 12N') are unchanged because _looks_like_wkt
rejects them.
@github-actions github-actions Bot added the performance PR touches performance-sensitive code label May 11, 2026
@brendancol brendancol requested a review from Copilot May 11, 2026 21:37
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

This PR fixes a GeoTIFF read-path regression where user-defined CRS GeoTIFFs (GeoKey *CSTypeGeoKey == 32767) were losing their CRS WKT on read, causing open_geotiff(...) -> to_geotiff(...) round-trips to silently drop projection information. The fix promotes WKT-looking citations to attrs['crs_wkt'] (while keeping attrs['crs_name'] for backward compatibility), and adds regression tests covering backend parity and round-trip behavior.

Changes:

  • Add a lightweight _looks_like_wkt(...) heuristic and use it in extract_geo_info to populate crs_wkt from the citation when EPSG is not resolved.
  • Add a comprehensive regression test module covering WKT detection, all four read backends (numpy/dask/cupy/dask+cupy), and read→write→read round-trips.
  • Update internal sweep metadata CSV entry for issue tracking.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
xrspatial/geotiff/_geotags.py Adds WKT-prefix detection and promotes citation WKT to crs_wkt for user-defined CRS reads.
xrspatial/geotiff/tests/test_user_defined_crs_wkt_1632.py New regression tests for user-defined CRS WKT preservation across backends and round-trips.
.claude/sweep-metadata-state.csv Updates sweep metadata entry to reflect issue #1632.

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

import pytest
import xarray as xr

import tifffile
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in eb600ba: switched to pytest.importorskip

Matches the convention used elsewhere in xrspatial/geotiff/tests/.
Test module no longer hard-fails collection on machines without
tifffile installed.
@brendancol brendancol merged commit dbb5ceb into xarray-contrib:main May 11, 2026
11 checks passed
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.

open_geotiff drops user-defined CRS WKT on read (crs/crs_wkt not set, only crs_name)

2 participants