Repository navigation
feat: Table-driven GeoKey to CRS builder - #182
Merged
Merged
Conversation
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The user-defined path of _crs.py no longer hand-writes PROJJSON. The geographic CRS comes from _crs_geographic (units, ellipsoid, datum and prime meridian by code or key, GDAL's citation names) and the projection from _crs_conversion, which interprets the vendored CT table: libgeotiff's key fallback order, unit scaling of angular and linear parameters, the Mercator and Polar Stereographic variant rules, pyproj's typed conversion classes where they exist and a PROJ string otherwise, and a check that every table parameter reached the conversion. Known conformance failures drop from 34 to 7: four rows need GeoKeys async-tiff does not expose yet, one is GDAL's own prime-meridian-in-grads inconsistency, and two are ESRI PE String rows where GDAL's ESRI name morphing differs from PROJ's parser. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…eys in the spec Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…, and exact degree units Review findings on GeoKey arrangements GDAL never writes but the spec allows: a coded datum no longer requires ellipsoid keys, an ellipsoid code with only a semi-major axis keeps the coded flattening (and a user-defined ellipsoid with no shape raises instead of becoming a sphere), the degree code 9102 is exactly 1.0 as in libgeotiff, and a unit with a zero conversion factor raises instead of zeroing angles. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.
Note
This PR was written by Claude (Claude Code), not by @kylebarron.
Stage 4 of the GeoKey-to-CRS work: the user-defined CRS path of
_crs.pyis now driven by the GeoTIFF CT method table shared through geotiff-test-data, built with pyproj's typed classes, and tested against GDAL's reading of every fixture in the conformance corpus. Design:dev-docs/specs/2026-10-26-geokey-crs-conformance-design.md.What changed
_crs_table.pyloads the vendoreddata/geotiff-ct-methods.jsoninto typed records (method, variants, parameters with their GeoKey fallback lists)._crs_geographic.pybuilds the geographic side the way libgeotiff'sGTIFGetDefnand GDAL'sGTIFGetOGISDefndo: angular and linear units from EPSG codes (via proj.db) or explicit sizes, the ellipsoid from its code or axes (sphere when the axes are equal), the datum and prime meridian from their codes or from GDAL's citation names (Datum = ...,Primem = ...,unknownfallback, neverundefined), and coordinate systems in the file's units and axis directions._crs_conversion.pyinterprets the table: first-present GeoKey wins (a stored0.0counts), angular and linear values scaled to degrees and metres, the Mercator and Polar Stereographic variant rules, the polar axis rule, pyproj's typed conversion classes where they exist and a PROJ string otherwise, then a check that every table parameter reached the conversion with its value. A table key async-tiff cannot read (ProjRectifiedGridAngletoday) raises instead of defaulting._crs.pyis now dispatch only;crs_from_geo_keysandprojjson_from_geo_keyskeep their signatures.Conformance
KNOWN_FAILURESintests/test_crs_conformance.pydrops from 34 rows to 7:tmerc_towgs84,omerc_variant_a,omerc_variant_b,somerc: need GeoKeys 2062/3096, merged in feat: Expose GeogTOWGS84GeoKey and ProjRectifiedGridAngleGeoKey async-tiff#368 but not yet released.lcc_1sp_paris_grad: GDAL's own write and read of a prime meridian in grads disagree (spec Q3); we follow libgeotiff's single conversion.krovak,moll: ESRI PE String rows, where GDAL layers the Geog* keys and ESRI name morphing on top of the WKT and pyproj parses the WKT alone. The PE String path is unchanged in this PR.The fresh-context review found three inputs the GDAL-written corpus never produces and that misbehaved: a coded datum without ellipsoid keys raised, an ellipsoid code with only a semi-major axis silently became a sphere, and the degree code 9102 scaled angles by a factor a hair off 1.0 (and some sexagesimal codes pyproj reports with a zero factor would have zeroed every angle). All three are fixed with tests.
uv run pytest: 511 passed, 4 skipped, 9 xfailed (the 7 above plus 2 non-strict proj.db-drift rows). Ruff and mypy clean.Follow-ups
lonc/alpha, but PROJ'slabrdtakeslon_0/azi; the builder overrides them (PROJ_KEY_OVERRIDES) and the validation step is what caught it. The table should be corrected so the override can go.KEY_ACCESSORS(and aBoundCRSfor TOWGS84) and remove the four rows..gitignoreentry fordev-docs/plans/that did not land with test: Add the CRS conformance suite from geotiff-test-data #181.🤖 Written by Claude Code
🤖 Generated with Claude Code