Transforms Module¶
The transforms module provides coordinate transformation functionality for converting between pixel, geodetic, and sensor coordinate systems.
Overview¶
VISTA supports various coordinate transformations needed for geospatial imagery analysis:
Pixel to geodetic coordinates (lat/lon)
Geodetic to pixel coordinates
Sensor to ground plane transformations
Altitude/Range/Frame (ARF) transformations
Polynomial-based transformations
These transformations are essential for working with imagery from calibrated sensors and for integrating VISTA with geospatial tools.
Module Reference¶
Transforms¶
General transform support functions
- vista.transforms.transforms.spherical_to_cartesian(azimuth, elevation)[source]¶
Convert spherical angle(s) to Cartesian vector(s)
- vista.transforms.transforms.cartesian_to_spherical(unit_vector)[source]¶
Convert Cartesian vector(s) to spherical angle(s)
- Parameters:
unit_vector (NDArray) – Unit vector or vector (as array of column vectors)
- Returns:
NDArray – Angle(s) in radians in the x-y plane
NDArray – Angle(s) in radians coming off the x-y plane toward the z-axis
- Return type:
Tuple[ndarray[tuple[Any, …], dtype[_ScalarT]], ndarray[tuple[Any, …], dtype[_ScalarT]]]
Earth Intersection¶
- vista.transforms.earth_intersection.los_to_earth(position, pointing)[source]¶
Find the intersection of a pointing vector with the Earth
Finds the intersection of a pointing vector u and starting point s with the WGS-84 geoid
- Parameters:
position (NDArray) – Length 3 or (3 X N) array defining the starting point location(s) in kilometers
pointing (NDArray) – Length 3 or (3 X N) array defining the pointing vector(s) (must be a unit vector)
- Returns:
NDArray – Distance(s) to the Earth’s surface
NDArray – Length 3 or (3 X N) array of point(s) of intersection with the Earth in kilometers. NaN’s represent non-intersection
- Return type:
Tuple[ndarray[tuple[Any, …], dtype[_ScalarT]], ndarray[tuple[Any, …], dtype[_ScalarT]]]
ARF Transforms¶
Attitude Reference Frame support functions
- vista.transforms.arf.get_arf_transform(sensor_pos, sensor_pointing)[source]¶
Create a matrix to transform vectors in a global reference frame into the Attitude Reference Frame (ARF)
Note
The purpose of the ARF and it’s definition are described and illustrated in detail in notebooks/attitude_reference_frame.ipynb
- Parameters:
sensor_pos (NDArray) – Sensor position vector in global reference frame in kilometers
sensor_pointing (NDArray) – Sensor pointing unit-vector in global reference frame
- Returns:
A matrix to transform vectors in the global reference frame into the ARF. Use this matrix like arf_vectors = transformation_matrix @ vectors.
- Return type:
NDArray
Polynomial Transforms¶
- vista.transforms.polynomials.fit_2d_polynomial(x, y, f, order)[source]¶
Fit a 2D polynomial to data using least squares.
Given arrays of x, y coordinates and corresponding function values f, finds the polynomial coefficients that minimize the squared error.
- Parameters:
x (np.ndarray) – X coordinates of data points (1D array)
y (np.ndarray) – Y coordinates of data points (1D array)
f (np.ndarray) – Function values at each (x, y) point (1D array)
order (int) – Order of the polynomial to fit
- Returns:
coeffs (np.ndarray) – Array of fitted polynomial coefficients, length (order+1)*(order+2)/2
residuals (float) – Sum of squared residuals
rank (int) – Rank of the design matrix
singular_values (np.ndarray) – Singular values of the design matrix
- Raises:
ValueError – If input arrays have inconsistent shapes or if there are insufficient data points
Examples
>>> # Fit a linear function f(x,y) = 1 + 2*x + 3*y >>> x = np.array([0, 1, 0, 1, 2]) >>> y = np.array([0, 0, 1, 1, 1]) >>> f = 1 + 2*x + 3*y >>> coeffs, _, _, _ = fit_2d_polynomial(x, y, f, order=1) >>> # coeffs should be approximately [1, 2, 3]
>>> # Fit with noisy data >>> x = np.random.rand(100) >>> y = np.random.rand(100) >>> f_true = 1 + 2*x + 3*y + x*y >>> f_noisy = f_true + 0.1 * np.random.randn(100) >>> coeffs, residuals, _, _ = fit_2d_polynomial(x, y, f_noisy, order=2)
Notes
The polynomial terms follow the same ordering as evaluate_2d_polynomial: ordered by total degree, then by decreasing powers of x.
- vista.transforms.polynomials.evaluate_2d_polynomial(coeffs, x, y, order=None)[source]¶
Evaluate a 2D polynomial of arbitrary order.
The polynomial terms are ordered by total degree, then by decreasing powers of x: - Order 0: c0 - Order 1: c1*x + c2*y - Order 2: c3*x^2 + c4*x*y + c5*y^2 - Order 3: c6*x^3 + c7*x^2*y + c8*x*y^2 + c9*y^3 - etc.
For a polynomial of order n, there are (n+1)*(n+2)/2 coefficients.
- Parameters:
coeffs (np.ndarray) – Array of polynomial coefficients, length must be (n+1)*(n+2)/2 for some integer n
x (np.ndarray or float) – X coordinates (can be scalar or array)
y (np.ndarray or float) – Y coordinates (can be scalar or array)
order (int, optional) – Order of the polynomial. If None, inferred from length of coeffs.
- Returns:
Evaluated polynomial values with same shape as input x and y
- Return type:
np.ndarray or float
- Raises:
ValueError – If the length of coeffs doesn’t correspond to a valid polynomial order
Examples
>>> # Evaluate f(x,y) = 1 + 2*x + 3*y (order 1) >>> coeffs = np.array([1, 2, 3]) >>> evaluate_2d_polynomial(coeffs, 1.0, 2.0) 9.0
>>> # Evaluate f(x,y) = 1 + x + y + x^2 + xy + y^2 (order 2) >>> coeffs = np.array([1, 1, 1, 1, 1, 1]) >>> evaluate_2d_polynomial(coeffs, 2.0, 3.0, order=2) 24.0
Basic Usage¶
Pixel ↔ Geodetic Conversion via Sensor¶
Pixel-to-geodetic and geodetic-to-pixel conversions are performed through the sensor object associated with the imagery, not through standalone functions in this module. See Custom Sensors for the full sensor API.
import numpy as np
from astropy.coordinates import EarthLocation
import astropy.units as u
# Convert pixel coordinates to geodetic (lat/lon/alt)
# frame can be a single int or an array of per-point frame numbers
location = sensor.pixel_to_geodetic(
frame=0,
rows=np.array([100.0, 200.0]),
columns=np.array([300.0, 400.0]),
)
print(location.lat.deg, location.lon.deg)
# Convert geodetic coordinates to pixel
loc = EarthLocation(lat=40.7128 * u.deg, lon=-74.0060 * u.deg, height=0 * u.m)
rows, columns = sensor.geodetic_to_pixel(frame=0, loc=loc)
Low-Level Transforms¶
The vista.transforms module provides lower-level building blocks used
internally by sensor geolocation pipelines:
from vista.transforms import (
spherical_to_cartesian,
cartesian_to_spherical,
los_to_earth,
get_arf_transform,
)
# Convert spherical angles to a Cartesian unit vector
vec = spherical_to_cartesian(azimuth=0.1, elevation=0.3)
# Find where a line-of-sight vector intersects the Earth (WGS-84)
distance, intersection = los_to_earth(position_ecef_km, pointing_unit_vec)