Skip to content

BUG: Convert grad/radian angular parameters to degrees in CRS.to_cf - #1643

Open
charan-rathore wants to merge 2 commits into
pyproj4:mainfrom
charan-rathore:fix-1641-cf-grad-units
Open

charan-rathore wants to merge 2 commits into
pyproj4:mainfrom
charan-rathore:fix-1641-cf-grad-units

Conversation

@charan-rathore

Copy link
Copy Markdown

Fixes #1641.

Problem

CRS.to_cf() wrote angular parameter values (prime meridian longitude,
longitude/latitude of natural origin, standard parallel) in whatever unit
the CRS defines them in. For CRSs with grad angular units such as the
French Lambert zones (EPSG:27571/27572/27573, NTF Paris datum), the CF dict
contained values like standard_parallel = 52.0 and
longitude_of_prime_meridian = 2.5969213 - grad numbers in fields that CF
expects to be degrees. Round-tripping through CRS.from_cf then
reinterpreted those numbers as degrees and the reprojection was off by
hundreds of kilometers.

Fix

Added a shared _to_degrees() helper in pyproj/crs/_cf1x8.py that
converts grad and radian values to degrees using the parameter's unit
conversion factor, leaving degree values untouched. CRS._to_dict() now
routes angular parameters through it, and CRS.to_cf() uses it for
longitude_of_prime_meridian.

Tests

Three regression tests in test/crs/test_crs_cf.py:

  • test_to_cf__grad_units__converts_to_degrees: EPSG:27572 exports
    standard_parallel 46.8 and longitude_of_prime_meridian 2.33722917.
  • test_to_cf__grad_prime_meridian__converts_to_degrees: +proj=longlat +pm=paris exports the Paris prime meridian in degrees.
  • test_cf_round_trip__grad_units: the from_cf round trip keeps the
    natural-origin latitude in degrees and lands within 10 m of the direct
    transform (previously ~579 km off).

Also added the change to docs/history.rst under Latest.

Verification

run_tests.sh clones the repo at the base, confirms the patch applies,
installs the released pyproj 3.8.0 wheel (its crs.py and _cf1x8.py are
byte-identical to the base commit, so the wheel exercises the same code the
patch changes), and runs master's test/crs/test_crs_cf.py against the
installed wheel:

  • Baseline (unpatched): the 3 grad-unit tests fail.
  • Patched (patch applied to the installed files): all 3 pass, and the rest
    of the suite shows zero new failures compared with baseline.

Caveats

  • The suite has 19 pre-existing failures in this setup, identical before
    and after the patch. They come from running master's tests against the
    3.8.0 wheel's bundled PROJ rather than a source build, not from this
    change.
  • Residual round-trip error is ~3 m, not exact: to_cf does not write any
    scale-factor entry for this 1SP Lambert projection, so from_cf defaults
    scale_factor_at_natural_origin to 1.0 instead of the original
    0.99987742. That is a separate pre-existing gap (a missing CF field, not
    a units bug) and is left out of scope here; the round-trip test asserts
    within 10 m and documents this.
  • The round-trip improvement was verified on the released wheel with
    bundled PROJ 9.8.1; a source build against the system's PROJ was not run.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CRS.to_cf() writes angles in grads for CRSs defined in grads

1 participant