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)

Parameters:
  • azimuth (Tuple[float, NDArray]) – Angle(s) in radians in the x-y plane

  • elevation (Tuple[float, NDArray]) – Angle(s) in radians coming off the x-y plane toward the z-axis

Returns:

Cartesian unit-vector(s) pointing in the direction of the given anglees

Return type:

NDArray

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

Coordinate Transformations

from vista.transforms import pixel_to_geodetic, geodetic_to_pixel

# Convert pixel coordinates to lat/lon
lat, lon = pixel_to_geodetic(x=100, y=200, imagery=img)

# Convert lat/lon to pixel coordinates
x, y = geodetic_to_pixel(lat=40.7128, lon=-74.0060, imagery=img)

Using Sensor Transforms

from vista.transforms import sensor_to_ground

# Transform from sensor coordinates to ground plane
ground_x, ground_y = sensor_to_ground(
    sensor_x, sensor_y,
    sensor=sensor,
    altitude=1000.0
)