CoordinateReferenceSystem

class geodetic_engine.geodesy.CoordinateReferenceSystem[source]

Bases: object

A resolved CRS together with the axis roles and units it declares.

Wraps pyproj.CRS so that a caller never has to read PROJ’s source to find out how many axes a CRS has, what they mean, or what units they are in. Construction is cached, since resolving a CRS is expensive relative to transforming a point.

Example

>>> crs = CoordinateReferenceSystem.from_user_input("EPSG:4326")
>>> crs.axis_abbreviations
('Lat', 'Lon')
>>> crs.axis_units
('degree', 'degree')
>>> crs.dimension
2

The declared order above is EPSG’s. Coordinate values for this CRS are still ordered (lon, lat) everywhere in this package.

Wrap an already-resolved pyproj.CRS.

Prefer from_user_input(), which caches. This constructor exists for the case where a pyproj.CRS is already in hand.

Parameters:
  • crs (CRS) – The resolved CRS.

  • definition (str) – The input it was resolved from, kept for error messages and for repr().

__init__(crs, definition)[source]

Wrap an already-resolved pyproj.CRS.

Prefer from_user_input(), which caches. This constructor exists for the case where a pyproj.CRS is already in hand.

Parameters:
  • crs (CRS) – The resolved CRS.

  • definition (str) – The input it was resolved from, kept for error messages and for repr().

classmethod from_user_input(value)[source]

Resolve a CRS from an EPSG code, WKT, PROJ string or CRS object.

Parameters:

value (Any) – An authority code such as "EPSG:4326" or 4326, a WKT string, a PROJ string, a PROJJSON string, an OSDU persistableReference payload, or an existing pyproj.CRS or CoordinateReferenceSystem.

Return type:

CoordinateReferenceSystem

Returns:

The resolved CRS.

Raises:

UnresolvableCRSError – If PROJ cannot construct a CRS from the input.

Example

>>> CoordinateReferenceSystem.from_user_input(4326).authority_code
'EPSG:4326'
classmethod from_persistable_reference(payload)[source]

Resolve a CRS from an OSDU persistableReference payload.

The payload carries its own definition, so the CRS is built from the ESRI WKT it states rather than from the authority code beside it. A payload that binds a transformation resolves to a bound CRS, which settles the datum shift that would otherwise be a choice. See geodetic_engine.persistablereference.

from_user_input() accepts these too, so a payload can be passed anywhere a CRS can. This is for when a caller wants the input read as a reference and nothing else.

Parameters:

payload (str) – The payload, plain or URL-encoded JSON.

Return type:

CoordinateReferenceSystem

Returns:

The resolved CRS.

Raises:

UnresolvableCRSError – If the payload is not a readable persistableReference, states something other than a CRS, or states a definition this package will not translate.

property crs: CRS

The underlying pyproj.CRS.

property definition: str

The input this CRS was resolved from.

property name: str

Human readable CRS name, for example "WGS 84".

property axes: tuple[AxisSpec, ...]

The CRS’s axes in EPSG-declared order, not in coordinate value order.

property axis_abbreviations: tuple[str, ...]

Axis abbreviations in EPSG-declared order, for example ("Lat", "Lon").

property axis_units: tuple[str, ...]

Axis unit names in EPSG-declared order, ("degree", "degree") for 4326.

property dimension: int

Number of axes the CRS declares.

property is_geographic: bool

Whether this CRS expresses position as latitude and longitude.

True through a bound CRS wrapping a geographic one, and through a compound CRS whose horizontal part is geographic.

property authority_code: str | None

"AUTH:CODE" if the CRS is identified in an authority, else None.

property is_dynamic: bool

Whether any datum in this CRS is a dynamic reference frame.

Coordinates in a dynamic frame require a coordinate epoch to be meaningful, so this drives the epoch requirement in geodetic_engine.geodesy.transformation.

property value_axis_order: tuple[int, ...]

Indices of the declared axes, in coordinate value order.

Element i is the position, among axes, of the axis whose value comes i-th in the xy ordering this package uses. This is the bridge between what the EPSG dataset declares and the order values are actually in, and it is the thing a caller needs in order to label a coordinate correctly.

Axes are identified by direction, falling back to the abbreviation for polar CRSs whose axes share a direction: EPSG:32661 declares both of its axes pointing south, and only the N and E abbreviations distinguish them.

Returns:

A permutation of range(self.dimension).

Example

>>> crs = CoordinateReferenceSystem.from_user_input("EPSG:4326")
>>> crs.axis_abbreviations
('Lat', 'Lon')
>>> crs.value_axis_order
(1, 0)

So the first coordinate value is the axis at declared index 1, longitude.

property value_axis_abbreviations: tuple[str, ...]

Axis abbreviations in coordinate value order, ("Lon", "Lat") for 4326.