astrix.spatial.location module¶
- class Location[source]¶
Bases:
Generic[T],ABCAbstract base class for location objects (Point, Path). ‘interp’ function is required for integration with other modules.
- property backend: str¶
- property ecef: Any¶
- property geodet: Any¶
- abstract property is_singular: bool¶
- property time: T¶
- class Path(point, backend=None)[source]¶
-
Path of multiple Point objects with associated Time. Enables interpolation between points over time and calculation of velocity. Must have at least 2 points with associated Time.
- Parameters:
Examples
Instantiating a Path from a list of Points:
>>> from astrix.primitives import Point, Time, Path >>> from datetime import datetime, timezone >>> times = Time.from_datetime( ... [ ... datetime(2025, 1, 1, 12, 0, 0, tzinfo=timezone.utc), ... datetime(2025, 1, 1, 12, 0, 1, tzinfo=timezone.utc), ... datetime(2025, 1, 1, 12, 0, 2, tzinfo=timezone.utc), ... ] ... ) >>> path = Path( ... [ ... Point([1, 2, 0], time=times[0]), ... Point([2, 3.8, 0.4], time=times[1]), ... Point([3, 6.0, 1], time=times[2]), ... ] ... ) # Somewhere very hot in the middle of the Earth
Interpolate the Path to a new time and get velocity:
>>> path.interp( Time.from_datetime(datetime(2025, 1, 1, 12, 0, 1, 500000, tzinfo=timezone.utc)), method="linear" ).ecef # Interpolate to halfway between second and third point, return ECEF array array([[2.5, 4.9, 0.7]]) >>> vel = path.interp_vel( Time.from_datetime(datetime(2025, 1, 1, 12, 0, 1, 500000, tzinfo=timezone.utc)), ) >>> vel.magnitude # Interpolated velocity magnitude in m/s array([2.48997992]) >>> vel.unit # Interpolated unit velocity vector array([[0.40160966, 0.88354126, 0.2409658 ]])
- convert_to(backend)[source]¶
Convert the Path object to a different backend.
- Return type:
- Parameters:
backend (str | Any | None)
- downsample(dt_max)[source]¶
Downsample the Path to a maximum time step of dt_max seconds. Note: This function is not JIT-compatible due to data validation checks.
- Return type:
- Parameters:
dt_max (float)
- interp(time, method='linear', check_bounds=True)[source]¶
Interpolate the Path to the given times using the specified method.
- Parameters:
time (Time) – Times to interpolate to.
method (str, optional) – Interpolation method. Currently only ‘linear’ is supported. Defaults to ‘linear’.
check_bounds (bool, optional) – Whether to check if the interpolation times are within the path time bounds. Defaults to True.
- Returns:
Interpolated Point object at the given times.
- Return type:
- interp_vel(time, method='linear', check_bounds=True)[source]¶
Interpolate the Path velocity to the given times using the specified method. Currently only ‘linear’ interpolation is supported.
- time_at_alt(alt)[source]¶
Find the times when the Path crosses the given altitude (in metres). Uses linear interpolation between points to find the crossing times. Note: This function is not JIT-compatible due to data validation checks.
- Return type:
- Parameters:
alt (float)
- truncate(start_time=None, end_time=None)[source]¶
Truncate the Path to the given start and end times. If start_time or end_time is None, the Path is truncated to the start or end of the Path respectively.
Note: This function is not JIT-compatible due to data validation checks.
- property is_singular: bool¶
Check if the Path object represents a single point. Always False for Path objects.
- class Point(ecef, time=TimeInvariant object, backend=None)[source]¶
-
Point(s) in ECEF coordinates, stored as (x, y, z) in metres. Can represent a single point or multiple points, and can be associated with a Time object for time instances of the points.
- Parameters:
ecef (Array) – ECEF coordinates as (x, y, z) in metres. Shape (3,) or (1,3) for single points, (n, 3) for multiple points.
time (TimeLike, optional) – Time object associated with the points. If provided, the length of time must match the number of points. Defaults to TIME_INVARIANT for static points.
backend (BackendArg, optional) – Array backend to use (numpy, jax, etc.). Defaults to numpy.
Examples
Single static point:
>>> from astrix.primitives import Point >>> p1 = Point( ... [-5047162.4, 2568329.79, -2924521.17] ... ) # ECEF coordinates of Brisbane in metres >>> p1.geodet # Convert to geodetic coordinates (lat, lon, alt) array([[-27.47, 153.03, 0.0]]) >>> p2 = Point.from_geodet([-27.47, 153.03, 0]) # lat, lon in degrees, alt in metres >>> p2.ecef # Convert back to ECEF coordinates array([[-5047162.4, 2568329.79, -2924521.17]])
Multiple static points:
>>> pts = Point( ... [ ... [-5047162.4, 2568329.79, -2924521.17], # Brisbane ... [-2694045.0, -4293642.0, 3857878.0], # San Francisco ... [3877000.0, 350000.0, 5027000.0], # Somewhere else ... ] ... ) >>> pt_bris = pts[0] # First point (Brisbane) >>> assert len(pts) == 3
Dynamic point with time:
>>> from datetime import datetime, timezone >>> from astrix.primitives import Time >>> times = Time.from_datetime( ... [ ... datetime(2021, 1, 1, 12, 0, 0, tzinfo=timezone.utc), ... datetime(2021, 1, 1, 13, 0, 0, tzinfo=timezone.utc), ... datetime(2021, 1, 1, 14, 0, 0, tzinfo=timezone.utc), ... ] ... ) >>> pts_time = Point( ... [ ... [-5047162.4, 2568329.79, -2924521.17], # Brisbane ... [-2694045.0, -4293642.0, 3857878.0], # San Francisco ... [3877000.0, 350000.0, 5027000.0], # Somewhere else ... ], ... time=times, ... ) >>> pts.has_time True >>> pts.is_singular False >>> pts_new = pts + Point( ... [[-1000, -1000, -1000]], ... time=Time.from_datetime( ... datetime(2021, 1, 1, 15, 0, 0, tzinfo=timezone.utc) ... ), ... ) >>> assert len(pts_new) == 4
Notes
When associating a Time object, the length of the Time must match the number of points.
Use Path objects for interpolating between multiple points over time.
- classmethod from_geodet(geodet, time=TimeInvariant object, backend=None)[source]¶
Create a Point object from geodetic coordinates (lat, lon, alt). Lat and lon are in degrees, alt is in meters.
- convert_to(backend)[source]¶
Convert the Point object to a different backend.
- Return type:
- Parameters:
backend (str | Any | None)
- property has_time: bool¶
Check if the Point has associated Time.
- property is_singular: bool¶
Check if the Point object represents a single point.
- class Velocity(vec, time, _xp)[source]¶
Bases:
objectVelocity vector(s) in ECEF coordinates (vx, vy, vz) in m/s. Associated with a Time object for the time instances of the velocities. Internal use only, typically created from Path objects. No data validation is performed.
- Parameters:
vec (Array) – Velocity vectors in ECEF coordinates (vx, vy, vz) in m/s. Shape (n, 3).
time (Time) – Time object associated with the velocities. Length must match number of velocity vectors.
backend (BackendArg, optional) – Array backend to use (numpy, jax, etc.). Defaults to numpy.
_xp (Any)
Examples
Velocity objects are typically created from Path objects.
>>> from astrix.primitives import Point, Time, Path >>> from datetime import datetime, timezone >>> times = Time.from_datetime( ... [ ... datetime(2025, 1, 1, 12, 0, 0, tzinfo=timezone.utc), ... datetime(2025, 1, 1, 12, 0, 1, tzinfo=timezone.utc), ... datetime(2025, 1, 1, 12, 0, 2, tzinfo=timezone.utc), ... ] ... ) >>> path = Path( ... [ ... Point([1, 2, 0], time=times[0]), ... Point([2, 3.8, 0.4], time=times[1]), ... Point([3, 6.0, 1], time=times[2]), ... ] ... ) # Somewhere very hot in the middle of the Earth >>> vel = path.vel >>> vel.magnitude # Velocity magnitudes in m/s array([1.91049732, 2.29128785, 2.6925824]) >>> vel.unit # Unit velocity vectors array([[0.52342392, 0.83747828, 0.15702718], [0.43643578, 0.87287156, 0.21821789], [0.37139068, 0.89133762, 0.25997347]])
- classmethod from_data(vec, time, backend=None)[source]¶
Create a Velocity object from velocity vector array and Time object.
- convert_to(backend)[source]¶
Convert the Velocity object to a different backend.
- Return type:
- Parameters:
backend (str | Any | None)
- property backend: str¶
- property magnitude: Any¶
Get the velocity magnitude in m/s.
- property unit: Any¶
Get the unit velocity vector.
-
vec:
Any¶