Describe the bug
build_geo_tags in xrspatial/geotiff/_geotags.py decides whether to write GeographicTypeGeoKey or ProjectedCSTypeGeoKey from the EPSG number range:
# xrspatial/geotiff/_geotags.py:1403
if crs_epsg == 4326 or (crs_epsg >= 4000 and crs_epsg < 5000):
model_type = MODEL_TYPE_GEOGRAPHIC
else:
model_type = MODEL_TYPE_PROJECTED
EPSG codes aren't allocated by type. Plenty of geographic CRSes live outside the 4000-4999 window. A few examples that get mis-tagged today:
- EPSG:6318, NAD83(2011) geographic 2D
- EPSG:7844, GDA2020 geographic 2D
- EPSG:9057, WGS 84 (G2139) geographic 3D
- EPSG:8252, NAD83(FBN) geographic 2D
All four get written with ProjectedCSTypeGeoKey. That's CRS corruption at write time. A spec-compliant reader will treat the file as projected with linear units of metres, when the coordinates are actually decimal degrees on an ellipsoid.
The current test suite only covers EPSG 4326 and 32610 (xrspatial/geotiff/tests/test_geotags.py:80), so this hole is untested.
Expected behavior
build_geo_tags should consult pyproj when available and use CRS.from_epsg(crs_epsg).is_geographic to decide the GeoKey. If pyproj isn't installed and the EPSG code isn't one of the few that can be hard-coded with confidence (4326 plus the 4000-4999 geographic block), the writer should raise rather than guess. Silent CRS corruption is worse than an explicit error at write time.
Additional context
Fix sketch:
- A helper that returns the model type for an EPSG code, preferring pyproj and falling back to a tight hard-coded allowlist.
- Call it from
build_geo_tags in place of the range check.
- Honour
XRSPATIAL_GEOTIFF_STRICT on the fail-closed path so behaviour matches the rest of the geotiff module.
- Tests for EPSG 6318 and 7844 (geographic, outside 4000-4999) plus an unknown EPSG with pyproj patched out to exercise the raise path.
Describe the bug
build_geo_tagsinxrspatial/geotiff/_geotags.pydecides whether to writeGeographicTypeGeoKeyorProjectedCSTypeGeoKeyfrom the EPSG number range:EPSG codes aren't allocated by type. Plenty of geographic CRSes live outside the 4000-4999 window. A few examples that get mis-tagged today:
All four get written with
ProjectedCSTypeGeoKey. That's CRS corruption at write time. A spec-compliant reader will treat the file as projected with linear units of metres, when the coordinates are actually decimal degrees on an ellipsoid.The current test suite only covers EPSG 4326 and 32610 (
xrspatial/geotiff/tests/test_geotags.py:80), so this hole is untested.Expected behavior
build_geo_tagsshould consult pyproj when available and useCRS.from_epsg(crs_epsg).is_geographicto decide the GeoKey. If pyproj isn't installed and the EPSG code isn't one of the few that can be hard-coded with confidence (4326 plus the 4000-4999 geographic block), the writer should raise rather than guess. Silent CRS corruption is worse than an explicit error at write time.Additional context
Fix sketch:
build_geo_tagsin place of the range check.XRSPATIAL_GEOTIFF_STRICTon the fail-closed path so behaviour matches the rest of the geotiff module.