API
Coordinates Conversion
Coordinate Transformations module.
This module provides vectorized coordinate transformations for terrestrial and celestial
reference frames commonly used in SAR and orbital geometry computations. It leverages pyproj
for geodetic conversions and Astropy for precise celestial frame transformations.
Coordinate Systems Supported
- ECEF (EPSG:4978): Earth-Centered Earth-Fixed cartesian coordinates (X, Y, Z) in meters
- LLH (EPSG:4326): Geodetic coordinates, Latitude, Longitude in radians/degrees, Height in meters
- UTM (EPSG:326xx/327xx): Universal Transverse Mercator coordinates (Easting, Northing, Height) in meters
- ECI (GCRS): Earth-Centered Inertial (Geocentric Celestial Reference System)
All functions support both single point (shape (3,)) and batch operations on arrays
of coordinates (shape (N, 3)). The ECEF<->ECI transformations properly account for
Earth rotation requiring a precise UTC timestamp via PreciseDateTime and velocities.
Attributes
xyz2llh_transformer
module-attribute
llh2xyz_transformer
module-attribute
__all__
module-attribute
Classes
Functions:
xyz2llh
Convert XYZ ECEF coordinates (epsg:4978) to LLH geodetic coordinates (epsg:4326).
Output latitude and longitude may be returned in [deg] if radians input flag is set to False.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coordinates
|
NDArray[floating]
|
XYZ EEF coordinates [m] (epsg:4978), with shape (3,) or (N, 3), with 3 being X, Y and Z in meters |
required |
radians
|
bool
|
if output latitude and longitude must be expressed in radians, otherwise they are provided in deg, by default True |
True
|
Returns:
| Type | Description |
|---|---|
NDArray[floating]
|
LLH geodetic coordinates (epsg:4326), with shape (3,) or (N, 3), with 3 being Lat [rad/deg], Lon [rad/deg] and H [m] |
llh2xyz
Convert from LLH geodetic coordinates (epsg:4326) to XYZ ECEF coordinates (epsg:4978).
Input latitude and longitude may be provided in [deg] if radians input flag is set to False.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coordinates
|
NDArray[floating]
|
llh geodetic coordinates (epsg:4326), with shape (3,) or (N, 3), with 3 being Lat [rad/deg], Lon [rad/deg] and H [m] |
required |
radians
|
bool
|
if input latitude and longitude are expressed in radians, otherwise they can be provided in deg, by default True |
True
|
Returns:
| Type | Description |
|---|---|
NDArray[floating]
|
XYZ EEF coordinates (epsg:4978), with shape (3,) or (N, 3), with 3 being X, Y and Z in meters |
ecef2eci
ecef2eci(positions: NDArray[floating], velocities: NDArray[floating], times: PreciseDateTime | NDArray) -> tuple[npt.NDArray[np.floating], npt.NDArray[np.floating]]
Convert from XYZ ECEF (epsg:4978 ITRS) positions and velocities to XYZ ECI (GCRS) coordinates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
positions
|
NDArray[floating]
|
positions in ECEF coordinates expressed in [m], with shape (3,) or (N, 3) |
required |
velocities
|
NDArray[floating]
|
velocities in ECEF coordinates expressed in [m/s], with shape (3,) or (N, 3) |
required |
times
|
PreciseDateTime | NDArray
|
observation times [UTC] associated to the input positions and velocities, scalar or with shape (N,) |
required |
Returns:
| Type | Description |
|---|---|
NDArray[floating]
|
XYZ ECI position coordinates expressed in [m], with shape (3,) or (N, 3) |
NDArray[floating]
|
XYZ ECI velocities coordinates expressed in [m/s], with shape (3,) or (N, 3) |
eci2ecef
eci2ecef(positions: NDArray[floating], velocities: NDArray[floating], times: PreciseDateTime | NDArray) -> tuple[npt.NDArray[np.floating], npt.NDArray[np.floating]]
Convert from XYZ ECI (GCRS) positions and velocities to XYZ ECEF (epsg:4978 ITRS) coordinates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
positions
|
NDArray[floating]
|
positions in ECI coordinates expressed in [m], with shape (3,) or (N, 3) |
required |
velocities
|
NDArray[floating]
|
velocities in ECI coordinates expressed in [m/s], with shape (3,) or (N, 3) |
required |
times
|
PreciseDateTime | NDArray
|
observation times [UTC] associated to the input positions and velocities, scalar or with shape (N,) |
required |
Returns:
| Type | Description |
|---|---|
NDArray[floating]
|
XYZ ECEF position coordinates expressed in [m], with shape (3,) or (N, 3) |
NDArray[floating]
|
XYZ ECEF velocities coordinates expressed in [m/s], with shape (3,) or (N, 3) |
utm2llh
utm2llh(coordinates: NDArray[floating], zone: str, *, radians: bool = True) -> npt.NDArray[np.floating]
Convert UTM (Easting, Northing, Height) coordinates (epsg:326xx/327xx) to LLH geodetic coordinates (epsg:4326).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coordinates
|
NDArray[floating]
|
UTM coordinates with shape (3,) or (N, 3), with 3 being Easting, Northing, and Height in meters |
required |
zone
|
str
|
UTM zone in format 'ZZH' where ZZ is zone number (1-60) and H is hemisphere ('N' for northern, 'S' for southern) Example: '33N', '33S', '1N', '60S' |
required |
radians
|
bool
|
if output latitude and longitude must be expressed in radians, otherwise they are provided in deg, by default True |
True
|
Returns:
| Type | Description |
|---|---|
NDArray[floating]
|
LLH geodetic coordinates (epsg:4326), with shape (3,) or (N, 3), with 3 being Lat [rad/deg], Lon [rad/deg] and H [m] |
Raises:
| Type | Description |
|---|---|
ValueError
|
if zone format is invalid or zone number is out of range (1-60) |
llh2utm
llh2utm(coordinates: NDArray[floating], zone: str, *, radians: bool = True) -> npt.NDArray[np.floating]
Convert LLH geodetic coordinates (epsg:4326) to UTM (Easting, Northing, Height) coordinates (epsg:326xx/327xx).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coordinates
|
NDArray[floating]
|
LLH geodetic coordinates (epsg:4326), with shape (3,) or (N, 3), with 3 being Lat [rad/deg], Lon [rad/deg] and H [m] |
required |
zone
|
str
|
UTM zone in format 'ZZH' where ZZ is zone number (1-60) and H is hemisphere ('N' for northern, 'S' for southern) Example: '33N', '33S', '1N', '60S' |
required |
radians
|
bool
|
if input latitude and longitude are expressed in radians, otherwise they can be provided in deg, by default True |
True
|
Returns:
| Type | Description |
|---|---|
NDArray[floating]
|
UTM coordinates, with shape (3,) or (N, 3), with 3 being Easting [m], Northing [m], and Height [m] |
Raises:
| Type | Description |
|---|---|
ValueError
|
if zone format is invalid or zone number is out of range (1-60) |
Ellipsoid
Ellipsoid models and utilities for geodetic computations.
Attributes
__all__
module-attribute
__all__ = ['WGS84', 'compute_line_ellipsoid_intersections', 'create_inflated_wgs84_ellipsoid']
Functions:
create_inflated_wgs84_ellipsoid
compute_line_ellipsoid_intersections
compute_line_ellipsoid_intersections(line_directions: NDArray[floating], line_origins: NDArray[floating], ellipsoid: Geod) -> tuple[npt.NDArray[np.floating], npt.NDArray[np.floating]]
Compute the intersections between lines and an ellipsoid.
For each line, returns two intersection arrays. When a line does not intersect the ellipsoid, both arrays contain NaN. When a line is tangent, both arrays contain the same point. The first array always contains the intersection closest to line_origin.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
line_directions
|
NDArray[floating]
|
(3,), (N, 3) one or more line directions, not necessarily normalized |
required |
line_origins
|
NDArray[floating]
|
(3,), (N, 3) one or more line origins |
required |
ellipsoid
|
Geod
|
ellipsoid |
required |
Returns:
| Type | Description |
|---|---|
NDArray[floating]
|
closest intersections to line_origins, with shape (3,) for a single line or (N, 3) for multiple lines, np.nan is used as a placeholder where no intersection exists |
NDArray[floating]
|
farthest intersections to line_origins, with shape (3,) for a single line or (N, 3) for multiple lines, np.nan is used as a placeholder where no intersection exists |
Raises:
| Type | Description |
|---|---|
ValueError
|
In case of invalid input |
Examples:
no intersection
>>> first, second = compute_line_ellipsoid_intersections([0, 0, 100], [-5, 0, 2], Geod(a=2, b=1))
>>> print(first, second)
[nan nan nan] [nan nan nan]
tangent intersection (first == second)
>>> first, second = compute_line_ellipsoid_intersections([100, 0, 0], [-5, 0, 1], Geod(a=2, b=1))
>>> print(first, second)
[0. 0. 1.] [0. 0. 1.]
two intersections, first one is closer to line_origin
>>> first, second = compute_line_ellipsoid_intersections([100, 0, 0], [-5, 0, 0], Geod(a=2, b=1))
>>> print(first, second)
[-2. 0. 0.] [2. 0. 0.]
multiple lines
>>> line_origins = np.array([[-5, 0, 2], [-5, 0, 1], [-5, 0, 0]])
>>> line_directions = np.array([[0, 0, 100], [100, 0, 0], [100, 0, 0]])
>>> first, second = compute_line_ellipsoid_intersections(line_directions, line_origins, Geod(a=2, b=1))
>>> print(first)
[[nan nan nan]
[ 0. 0. 1.]
[-2. 0. 0.]]
>>> print(second)
[[nan nan nan]
[ 0. 0. 1.]
[ 2. 0. 0.]]
extract validity mask for multiple lines
>>> line_origins = np.array([[-5, 0, 2], [-5, 0, 1], [-5, 0, 0]])
>>> line_directions = np.array([[0, 0, 100], [100, 0, 0], [100, 0, 0]])
>>> first, second = compute_line_ellipsoid_intersections(line_directions, line_origins, Geod(a=2, b=1))
>>> valid_mask = ~np.isnan(first[:, 0])
>>> print(first[valid_mask], second[valid_mask])
[[ 0. 0. 1.]
[-2. 0. 0.]] [[0. 0. 1.]
[2. 0. 0.]]