astrix package¶
AsTrIX — Aerospace Trajectory Imaging & Diagnostics toolbox.
This package provides tools for aerospace trajectory analysis and visualization.
- class Acceleration(vec, time, _xp)[source]¶
Bases:
objectAcceleration vector(s) in ECEF coordinates (ax, ay, az) in m/s². Associated with a Time object for the time instances of the accelerations. Internal use only, typically created from Path objects. No data validation is performed.
- Parameters:
vec (Array) – Acceleration vectors in ECEF coordinates (ax, ay, az) in m/s². Shape (n, 3).
time (Time) – Time object associated with the accelerations. Length must match number of acceleration vectors.
backend (BackendArg, optional) – Array backend to use (numpy, jax, etc.). Defaults to numpy.
_xp (Any)
- classmethod from_data(vec, time, backend=None)[source]¶
Create an Acceleration object from acceleration vector array and Time object.
- Return type:
- Parameters:
vec (Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | complex | bytes | str | _NestedSequence[complex | bytes | str])
time (Time)
backend (str | Any | None)
- convert_to(backend)[source]¶
Convert the Acceleration object to a different backend.
- Return type:
- Parameters:
backend (str | Any | None)
- interp(time, method='linear', check_bounds=True)[source]¶
Interpolate the Acceleration to the given times using the specified method. Currently only ‘linear’ interpolation is supported.
- Return type:
- Parameters:
time (Time)
method (str)
check_bounds (bool)
- property backend: str¶
- property magnitude: Any¶
Get the acceleration magnitude in m/s².
- property unit: Any¶
Get the unit acceleration vector.
- vec: Any¶
- class FixedZoomCamera(_res, _sensor_size, _focal_length, _mat, _rad_coef, _xp)[source]¶
Bases:
CameraLikeA simple pinhole camera model with fixed zoom.
Notes
- The camera intrinsic matrix is given by:
[ fx 0 cx ] [ 0 fy cy ] [ 0 0 1 ]
where:
fx = focal_length * res[0] / sensor_size[0] fy = focal_length * res[1] / sensor_size[1] cx = res[0] / 2 cy = res[1] / 2
- The field of view is given by:
fov_x = 2 * arctan(sensor_size[0] / (2 * focal_length)) fov_y = 2 * arctan(sensor_size[1] / (2 * focal_length))
- Parameters:
_res (tuple[int, int])
_sensor_size (tuple[float, float])
_focal_length (float)
_mat (Any)
_rad_coef (Any | None)
_xp (Any)
- classmethod from_foc_len(res, sensor_size, focal_length, rad_coef=None, backend=None)[source]¶
Create a FixedZoomCamera from focal length.
- Parameters:
res (
tuple[int,int]) – Image resolution (width, height) in pixels.sensor_size (
tuple[float,float]) – Physical sensor size (width, height) in mm.focal_length (
float) – Focal length in mm.rad_coef (optional) – Radial distortion coefficients.
backend (optional) – Backend to use. Either “numpy” or “jax”.
- Return type:
- classmethod from_hoz_fov(res, hoz_fov, sensor_size, rad_coef=None, backend=None)[source]¶
Create a FixedZoomCamera from horizontal field of view.
- Parameters:
res (
tuple[int,int]) – Image resolution (width, height) in pixels.hoz_fov (
float) – Horizontal field of view in degrees.sensor_size (
tuple[float,float]) – Physical sensor size (width, height) in mm.rad_coef (optional) – Radial distortion coefficients.
backend (optional) – Backend to use. Either “numpy” or “jax”.
- Return type:
- convert_to(backend)[source]¶
Convert the camera to a different backend.
- Return type:
- Parameters:
backend (str | Any | None)
- fov(zoom=None)[source]¶
Field of view in degrees (horizontal, vertical).
- Return type:
tuple[float,float]- Parameters:
zoom (float | None)
- mat(time=Time invariant (n=1))[source]¶
Camera intrinsic matrix. No zoom parameter needed as this is a fixed zoom camera.
- Return type:
Any- Parameters:
time (Time)
- rad_coef(time=Time invariant (n=1))[source]¶
Radial distortion coefficients.
- Return type:
Any- Parameters:
time (Time)
- property backend: str¶
Backend used by the camera.
- property has_dist¶
Whether the camera has distortion coefficients.
- class Frame(rot, loc=None, ref_frame=None, backend=None, name='unnamed-frame')[source]¶
Bases:
objectA reference frame defined by a rotation and location. Can be static or time-varying, and can have rotation defined relative to another Frame. Combines RotationLike and Location objects, and manages time associations.
- Parameters:
rot (Rotation | RotationSequence) – A scipy Rotation object (single rotation) or RotationSequence (time-tagged rotations). If a single Rotation is provided, the frame rotation is static.
loc (Location, optional) – A Location object (Point or Path) defining the frame origin in ECEF coordinates. If not provided, the frame origin is assumed to be at the origin of the reference frame. If loc is provided, it must be a singular Point (1x3) for static frames. Use Path objects for time-varying locations.
ref_frame (Frame, optional) – A reference Frame object to define the rotation relative to. If not provided, the rotation is assumed to be absolute (e.g., from ECEF frame).
backend (BackendArg, optional) – Array backend to use (numpy, jax, etc.). Defaults to numpy.
name (str)
Examples
Static frame with static rotation and location:
>>> from astrix import Frame, Point >>> from scipy.spatial.transform import Rotation >>> rot = Rotation.from_euler("xyz", [90, 0, 0], degrees=True) >>> loc = Point.from_geodet([-27.47, 153.03, 0]) >>> frame_static = Frame(rot, loc) >>> frame_static.interp_rot().as_euler("xyz", degrees=True) array([[90., 0., 0.]])
Time-varying frame with rotation sequence and static location:
>>> from astrix import Time, RotationSequence >>> from datetime import datetime, timezone >>> times = Time.from_datetime([ ... datetime(2021, 1, 1, 12, 0, 0, tzinfo=timezone.utc), ... datetime(2021, 1, 1, 13, 0, 0, tzinfo=timezone.utc), ... ]) >>> rots = Rotation.from_euler("xyz", [[0, 0, 0], [90, 0, 0]], degrees=True) >>> rot_seq = RotationSequence(rots, times) >>> frame_dynamic = Frame(rot_seq, loc) >>> t_interp = Time.from_datetime( ... datetime(2021, 1, 1, 12, 30, 0, tzinfo=timezone.utc) ... ) >>> frame_dynamic.interp_rot(t_interp).as_euler("xyz", degrees=True) array([[45., 0., 0.]])
Frame defined relative to another frame:
>>> rot_ref = Rotation.from_euler("xyz", [0, 30, 0], degrees=True) >>> frame_ref = Frame(rot_ref, loc) >>> rot_rel = Rotation.from_euler("xyz", [0, 40, 0], degrees=True) >>> frame = Frame(rot_rel, ref_frame=frame_ref) >>> frame.interp_rot().as_euler("xyz", degrees=True) array([[ 0., 70., 0.]])
Notes
If both loc and ref_frame are provided, the new frame location is used and the reference frame location is disregarded.
A TimeGroup object is created internally to manage time associations between rotation, location, and reference frame.
If the frame is static (single rotation and singular Point), the time properties return TIME_INVARIANT.
Use Path objects for time-varying locations.
- convert_to(backend)[source]¶
Convert the Frame object to a different backend.
- Return type:
- Parameters:
backend (str | Any | None)
- index_loc(index)[source]¶
Get the location of the frame at the given index.
Warning: This should only be used after downsampling so that rotation indices are time-aligned. Use with caution. Prefer interp_loc for general use.
- Return type:
- Parameters:
index (int)
- index_rot(index)[source]¶
Get the absolute rotation of the frame at the given index.
Warning: This should only be used after downsampling so that location and rotation indeces align. Prefer interp_rot for general use.
- Return type:
- Parameters:
index (int)
- interp_loc(time=Time invariant (n=1), check_bounds=True)[source]¶
Get the interpolated location of the frame at the given times. If the location is static, time can be None.
- interp_rot(time=Time invariant (n=1), check_bounds=True)[source]¶
Get the interpolated absolute rotation of the frame at the given times. If all rotations are time invariant, time can be None.
- replace_rot(frame_name, new_rot)[source]¶
Replace a rotation in the rotation chain with a new rotation.
This is an advanced feature and currently only applicable for static rotations. Should primarily be used for optimisation purposes in autograd frameworks, such as correcting misalignment.
- sample_at_time(time)[source]¶
Sample the Frame object at specific times, returning a new Frame with time-varying components sampled at those times. The new frame can then be indexed at these times directly to avoid interpolation
- property backend: str¶
Get the name of the array backend in use (e.g., ‘numpy’, ‘jax’).
- property has_ref: bool¶
Check if the frame has a reference frame.
- property is_static: bool¶
Check if the frame is static (single rotation and singular Point location).
- property name: str¶
Get the name of the frame.
- property name_chain: list[str]¶
Get the names of all frames in the rotation chain, from base to current.
- property path: Path¶
Get the time-varying Path of the frame location, if applicable. If the frame location is static, raises AttributeError.
- property point: Point¶
Get the singular Point of the frame location, if applicable. If the frame location is time-varying, raises AttributeError.
- property rel_rot: RotationLike¶
Get the last rotation of the frame relative to the reference frame.
- class Path(point, backend=None)[source]¶
Bases:
LocationPath 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 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]), ... ])
Interpolate Path and get velocity:
>>> t_interp = Time.from_datetime( ... datetime(2025, 1, 1, 12, 0, 1, 500000, tzinfo=timezone.utc) ... ) >>> path.interp(t_interp).ecef array([[2.5, 4.9, 0.7]]) >>> vel = path.vel.interp(t_interp) >>> vel.magnitude array([2.48997992])
- 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:
- 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 acc: Acceleration¶
Calculate the acceleration from the Path using central differences.
- property is_singular: bool¶
Check if the Path object represents a single point. Always False for Path objects.
- class Pixel(uv, time=Time invariant (n=1), backend=None)[source]¶
Bases:
objectA pixel in an image.
Notes
The pixel coordinates are given in the image coordinate system, where the origin is at the top-left corner of the image, and the u-axis points to the right and the v-axis points down.
- Parameters:
uv (Array)
time (Time)
backend (BackendArg)
- property backend: str¶
Backend used by the pixel.
- property has_time: bool¶
Whether the pixel has a time associated with it.
- property uv: Any¶
Pixel coordinates (u, v) in pixels.
- class Point(ecef, time=Time invariant (n=1), backend=None)[source]¶
Bases:
LocationPoint(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 (Time, 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 import Point >>> p1 = Point([-5047162.4, 2568329.79, -2924521.17]) # Brisbane ECEF (m) >>> p1.geodet # Convert to geodetic (lat, lon, alt) array([[-27.47, 153.03, 0.0]]) >>> p2 = Point.from_geodet([-27.47, 153.03, 0]) >>> p2.ecef 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 ... ]) >>> pt_bris = pts[0] >>> len(pts) 2
Dynamic point with time:
>>> from datetime import datetime, timezone >>> from astrix 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), ... ]) >>> pts_time = Point([ ... [-5047162.4, 2568329.79, -2924521.17], ... [-2694045.0, -4293642.0, 3857878.0], ... ], time=times) >>> pts_time.has_time True >>> pts_time.is_singular False
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=Time invariant (n=1), backend=None)[source]¶
Create a Point object from geodetic coordinates (lat, lon, alt). Latitude and longitude are in degrees, altitude 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 Ray(dir_rel, origin_rel=array([[0., 0., 0.]]), frame=Frame(name=ECEF, static_rot=True, static_loc=True, has_ref=False, time_bounds=(Time invariant (n=1), Time invariant (n=1)), backend=numpy), time=Time invariant (n=1), check=True, backend=None)[source]¶
Bases:
objectA ray defined by an origin point, direction vector, reference frame, and optional time.
- Parameters:
dir_rel (Array) – Nx3 array of ray direction vectors in local frame. Need not be normalised. E.g., (1, 0, 0) is a ray pointing along axis 1 of reference frame.
origin_rel (Array) – 1x3 or Nx3 array defining the ray origin(s) in local frame (meters). Typically (0,0,0) for camera reference frames, or ECEF coordinates for ECEF frame rays.
frame (Frame, optional) – Reference frame for the ray origin and direction.
time (Time, optional) – Time object associated with the rays. Must be same length as origin if provided. Defaults to TIME_INVARIANT.
check (bool, optional) – If True (default), validate non-zero direction vectors; disable for JIT paths.
backend (BackendArg, optional) – Array backend to use (numpy, jax, etc.). Defaults to numpy.
Notes
For calculating metrics (e.g. az/el), the axis are assumed (1) forward, (2) right, (3) down (FRD frame).
Although stored in local coordiantes, rays are globally defined by their reference frame.
- Monotonically increasing time is required for interpolation. But to prevent data-dependent control flow,
this is not checked on initialization. Use Time.is_increasing to check if needed.
Examples
>>> from astrix import Point, Ray >>> origin = Point([0.0, 0.0, 0.0]) >>> target = Point([1.0, 0.0, 0.0]) >>> ray = Ray.from_points(target, origin) >>> ray.unit_rel array([[1., 0., 0.]])
- classmethod from_az_el(az_el, frame=Frame(name=ECEF, static_rot=True, static_loc=True, has_ref=False, time_bounds=(Time invariant (n=1), Time invariant (n=1)), backend=numpy), time=Time invariant (n=1), origin_rel=array([[0., 0., 0.]]), check=True, backend=None)[source]¶
Create a Ray object from origin points and heading/elevation angles.
- Parameters:
az_el (Array) – Nx2 array of azimuth and elevation angles in degrees, relative to the reference frame.
frame (Frame, optional) – Reference frame for the ray origin and direction. Defaults to ECEF frame.
time (Time, optional) – Time object associated with the rays.
origin_rel (Array, optional) – Nx3 array of ray origin points in local frame coordinates. Defaults to (0,0,0), which is the reference frame origin.
check (bool, optional) – Whether to check input arrays for validity (not JIT compatible). Defaults to True.
backend (BackendArg, optional) – Array backend to use (numpy, jax, etc.). Defaults to numpy.
- Return type:
- classmethod from_camera(pixel, camera, frame, backend=None)[source]¶
Create a Ray object from pixel coordinates and a camera model.
- Parameters:
pixel (Pixel) – Pixel object defining the pixel coordinates and optional time.
camera (CameraLike) – Camera model defining the camera parameters and orientation.
frame (Frame) – Reference frame for the ray origin and direction.
backend (BackendArg, optional) – Array backend to use (numpy, jax, etc.). Defaults to numpy.
- Returns:
Ray object defined by the pixel coordinates and camera model.
- Return type:
- classmethod from_points(endpoint, origin, time=Time invariant (n=1), check=True, backend=None)[source]¶
Create a Ray object from origin and endpoint arrays in ECEF frame.
- Parameters:
endpoint (Point) – End points (ECEF coordinates). Must be length N.
origin (Point) – Origin points (ECEF coordinates). Must be length N or 1.
time (Time, optional) – Time object associated with the rays. If TIME_INVARIANT, time is inferred from endpoint or origin when available.
check (bool, optional) – If True, validate geometry (non-zero directions). Disable for JIT compatibility. Defaults to True.
backend (BackendArg, optional) – Array backend to use (numpy, jax, etc.). Defaults to numpy.
- Returns:
Ray object defined by the origin and direction from origin to endpoint.
- Return type:
- classmethod from_target_frame(target, frame, check_bounds=True, backend=None)[source]¶
Create a Ray object from a reference frame and target point(s).
- Parameters:
target (Point) – Target point(s) in ECEF coordinates. Must be length N or 1.
frame (Frame) – Reference frame for the ray origin and direction.
check_bounds (bool, optional) – If True, ensure target times fall within frame time ranges.
backend (BackendArg, optional) – Array backend to use (numpy, jax, etc.). Defaults to numpy.
- Returns:
Ray object defined by the frame origin and direction to the target point(s).
- Return type:
- convert_to(backend)[source]¶
Convert the Ray object to a different backend.
- Return type:
- Parameters:
backend (str | Any | None)
- correct_refraction(alt=100000.0)[source]¶
Apply atmospheric refraction correction to the Ray object using Bennett’s formula. Altitude sets the exponential scale height (metres) for the correction.
- Returns:
New Ray object with refraction-corrected direction vectors.
- Return type:
- Parameters:
alt (float)
Notes
Assumes standard atmospheric conditions.
- interp(time, check_bounds=True)[source]¶
Interpolate the Ray origin and direction to the given times.
- project_to_cam(camera)[source]¶
Project the Ray object to pixel coordinates using a camera model.
- Parameters:
camera (CameraLike) – Camera model defining the camera parameters and orientation.
- Returns:
Pixel object defining the pixel coordinates and associated time.
- Return type:
Notes
The Ray must be defined in the same reference frame as the camera.
Rays that do not intersect the image plane will result in NaN pixel coordinates.
- replace_frame(frame)[source]¶
Replace the reference frame of the Ray without changing origin or direction. Not a transformation, but direct replacement. Use with caution.
- property az_el¶
Return the azimuth and elevation angles from the forward axis in degrees.
- property backend: str¶
Get the name of the array backend in use (e.g., ‘numpy’, ‘jax’).
- property has_time: bool¶
Check if the Ray has associated Time.
- property origin_points: Point¶
Get the ray origin point(s) as ECEF. Note: this involves a frame transformation. For repeated access, recommend converting the Ray to ECEF frame first using to_ecef().
- property origin_rel: Any¶
Get the ray origin point(s) in the local frame coordinates. Typically zero for camera reference frames, or ECEF coordinates for ECEF frame rays.
- property total_angle: Any¶
Return the total angle from the forward axis in degrees.
- property unit_ecef: Any¶
Get the unit direction vector(s) of the ray in ECEF frame. Note: this involves a frame transformation. For repeated access, recommend converting the Ray to ECEF frame first using to_ecef().
- property unit_rel: Any¶
Get the unit direction vector(s) of the ray in the local frame coordinates.
- class RotationSequence(rot, time, backend=None)[source]¶
Bases:
RotationLikeA sequence of time-tagged rotations, enabling interpolation between them. Uses scipy.spatial.transform.Slerp for interpolation.
- Parameters:
rot (Rotation | list of Rotation) – A scipy Rotation object containing multiple rotations, or a list of such objects. If a list is provided, all elements must be scipy Rotation objects.
time (Time) – A Time object with time instances corresponding to each rotation. Must be the same length as the number of rotations and strictly increasing.
backend (BackendArg, optional) – Array backend to use (numpy, jax, etc.). Defaults to numpy.
Examples
>>> from astrix import Time, RotationSequence >>> from scipy.spatial.transform import Rotation >>> from datetime import datetime, timezone >>> 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), ... ] ... ) >>> rots = Rotation.from_euler( ... "xyz", ... [ ... [0, 0, 0], ... [90, 0, 0], ... [180, 0, 0], ... ], ... degrees=True, ... ) >>> rot_seq = RotationSequence(rots, times)
>>> interp_rot = rot_seq.interp( ... Time.from_datetime(datetime(2021, 1, 1, 12, 30, 0, tzinfo=timezone.utc)) ... ) # Interpolate to halfway between first and second rotation >>> interp_rot.as_euler( ... "xyz", degrees=True ... ) # Get interpolated rotation as Euler angles array([[45., 0., 0.]])
- convert_to(backend)[source]¶
Convert the RotationSequence object to a different backend.
- Return type:
- Parameters:
backend (str | Any | None)
- downsample(dt_max)[source]¶
Downsample the rotation sequence to a coarser time resolution.
- Parameters:
dt_max (float) – Desired maximum time step in seconds for downsampling.
- Returns:
A new RotationSequence object with downsampled rotations.
- Return type:
- class Time(unix, backend=None, invariant=False)[source]¶
Bases:
objectOne or more time instances.
Represents time using seconds since Unix epoch (1970-01-01 00:00:00 UTC). Can handle single time instances or arrays of times with consistent backend support for JAX/NumPy compatibility.
- Parameters:
unix (Array | list of float | float) – Time values in seconds since Unix epoch (1970-01-01 UTC)
backend (BackendArg, optional) – Array backend to use (numpy, jax, etc.). Defaults to numpy.
invariant (bool)
Examples
Single time instance:
>>> t = Time(1609459200.0) # 2021-01-01 00:00:00 UTC
Multiple times:
>>> times = Time([1609459200.0, 1609545600.0]) # Jan 1-2, 2021
From datetime:
>>> from datetime import datetime, timezone >>> dt = datetime(2021, 1, 1, tzinfo=timezone.utc) >>> t = Time.from_datetime(dt) >>> dt_list = [ ... datetime(2021, 1, 1, tzinfo=timezone.utc), ... datetime(2021, 1, 2, tzinfo=timezone.utc), ... ] >>> times = Time.from_datetime(dt_list)
Notes
All datetime objects must be timezone-aware to avoid ambiguity.
- classmethod from_datetime(time, backend=None)[source]¶
Create a Time object from a single or list of datetime objects. Will not accept timezone-unaware datetime obejects due to ambiguity.
- Return type:
- Parameters:
time (datetime | list[datetime])
backend (str | Any | None)
- classmethod invariant(n=1, backend=None)[source]¶
Create a time-invariant Time object of length n.
- Return type:
- Parameters:
n (int)
backend (str | Any | None)
- convert_to(backend)[source]¶
Convert the Time object to a different backend.
- Return type:
- Parameters:
backend (str | Any | None)
- in_bounds(time)[source]¶
Check if the given time(s) are within the bounds of this Time object.
- Return type:
bool- Parameters:
time (Time)
- nearest_idx(time)[source]¶
Find the index of the nearest time in this Time object for each time in the input Time object.
- Parameters:
time (Time) – Time object containing times to find nearest indices for.
- Returns:
Array of indices corresponding to the nearest times in this Time object.
- Return type:
Array
Examples
>>> from astrix import Time >>> from datetime import datetime, timezone >>> t1 = Time.from_datetime( ... [ ... datetime(2021, 1, 1, tzinfo=timezone.utc), ... datetime(2021, 1, 2, tzinfo=timezone.utc), ... datetime(2021, 1, 3, tzinfo=timezone.utc), ... ] ... ) >>> t2 = Time.from_datetime( ... [ ... datetime(2021, 1, 1, 12, tzinfo=timezone.utc), ... datetime(2021, 1, 2, 12, tzinfo=timezone.utc), ... ] ... ) >>> idx = t1.nearest_idx(t2) >>> idx.tolist() [0, 1]
- offset(offset)[source]¶
Return a new Time object with offset (seconds) added to all time values.
- Return type:
- Parameters:
offset (float)
- return_in_bounds(time)[source]¶
Return a new Time object containing only the times within the bounds of this Time object.
- property backend: str¶
Get the name of the array backend in use (e.g., ‘numpy’, ‘jax.numpy’).
- property datetime: list[datetime]¶
- property duration: float | Any¶
Get the duration between the first and last time in seconds.
- property end_sec: float | Any¶
Get the end time in seconds since epoch.
- property is_increasing: bool¶
Check if the time values are strictly increasing.
- property is_invariant: bool¶
Whether the Time object represents an invariant (constant) time.
- property is_singular: bool¶
Check if the Time object represents a single time instance.
- property start_sec: float | Any¶
Get the start time in seconds since epoch.
- property unix: Any¶
Get the time values in seconds since epoch.
- class TimeGroup(times, backend=None)[source]¶
Bases:
objectA group of Time objects. Used to manage multiple time instances and determine overlapping time bounds.
- Parameters:
times (list of Time) – List of Time objects (Time, TimeGroup)
backend (BackendArg, optional) – Array backend to use (numpy, jax, etc.). Defaults to numpy.
Examples
>>> t1 = Time.from_datetime( ... [ ... datetime(2021, 1, 1, 12, 0, 0, tzinfo=timezone.utc), ... datetime(2021, 1, 1, 13, 0, 0, tzinfo=timezone.utc), ... ] ... ) >>> t2 = Time.from_datetime( ... [ ... datetime(2021, 1, 1, 12, 30, 0, tzinfo=timezone.utc), ... datetime(2021, 1, 1, 14, 0, 0, tzinfo=timezone.utc), ... ] ... ) >>> tg = TimeGroup([t1, t2]) >>> tg.duration # Duration of overlap in seconds 1800.0
>>> overlap = tg.overlap_bounds # Overlapping time range >>> assert overlap[0].datetime[0] == datetime( ... 2021, 1, 1, 12, 30, 0, tzinfo=timezone.utc ... ) >>> assert overlap[1].datetime[0] == datetime( ... 2021, 1, 1, 13, 0, 0, tzinfo=timezone.utc ... )
>>> tg.in_bounds( ... Time.from_datetime(datetime(2021, 1, 1, 12, 45, 0, tzinfo=timezone.utc)) ... ) True
- convert_to(backend)[source]¶
Convert the TimeGroup object to a different backend.
- Return type:
- Parameters:
backend (str | Any | None)
- in_bounds(time)[source]¶
Check if the given time(s) are within the overlap bounds of this TimeGroup.
- Return type:
bool- Parameters:
time (Time)
- property backend: str¶
- property duration: float | Any¶
Get the duration of the overlap bounds in seconds.
- property extreme_bounds: tuple[Time, Time]¶
Get the extreme bounds of the TimeGroup as Time objects.
- property is_invariant: bool¶
- 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 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]), ... ]) >>> vel = path.vel >>> vel.magnitude array([1.91049732, 2.29128785, 2.6925824])
- 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)
- interp(time, method='linear', check_bounds=True)[source]¶
Interpolate the Velocity to the given times using the specified method. Currently only ‘linear’ interpolation is supported.
- property acc: Acceleration¶
Calculate the acceleration from the velocity using central differences.
- property backend: str¶
- property magnitude: Any¶
Get the velocity magnitude in m/s.
- property unit: Any¶
Get the unit velocity vector.
- vec: Any¶
- resolve_backend(name_or_mod=None)[source]¶
Resolve the backend (array namespace) from a string or module.
- Return type:
ModuleType- Parameters:
name_or_mod (str | ModuleType | None)
- time_linspace(t1, t2, num)[source]¶
Create a Time object with linearly spaced times between two Time objects. If t1 and t2 are non-singular, uses t1[0] and t2[-1].
- Parameters:
- Returns:
Time object with linearly spaced times.
- Return type:
Examples
>>> from astrix import Time >>> from datetime import datetime, timezone >>> t_start = Time.from_datetime(datetime(2021, 1, 1, tzinfo=timezone.utc)) >>> t_end = Time.from_datetime(datetime(2021, 1, 2, tzinfo=timezone.utc)) >>> t_lin = time_linspace(t_start, t_end, num=5) >>> t_lin.datetime [datetime.datetime(2021, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), datetime.datetime(2021, 1, 1, 6, 0, tzinfo=datetime.timezone.utc), datetime.datetime(2021, 1, 1, 12, 0, tzinfo=datetime.timezone.utc), datetime.datetime(2021, 1, 1, 18, 0, tzinfo=datetime.timezone.utc), datetime.datetime(2021, 1, 2, 0, 0, tzinfo=datetime.timezone.utc)]
Subpackages¶
- astrix.plots package
CartPlotPlot3DPlot3D.add_2d_text()Plot3D.add_box()Plot3D.add_circle()Plot3D.add_grid()Plot3D.add_ground_track()Plot3D.add_labelled_point()Plot3D.add_legend()Plot3D.add_path()Plot3D.add_point()Plot3D.add_ray()Plot3D.add_texture()Plot3D.autocomplete()Plot3D.calc_bounds()Plot3D.clear_ground_track()Plot3D.clear_path()Plot3D.clear_point()Plot3D.close()Plot3D.frame()Plot3D.render()Plot3D.save()Plot3D.set_view()Plot3D.show()Plot3D.start_animation()Plot3D.update_2d_text()Plot3D.update_ground_track()Plot3D.update_labelled_point_pos()Plot3D.update_path()Plot3D.update_point()Plot3D.update_ray()Plot3D.aspect_ratioPlot3D.dataPlot3D.pPlot3D.text_actors
- Submodules
- astrix.post package
- astrix.spatial package
AccelerationFramePathPointRayRay.from_az_el()Ray.from_camera()Ray.from_points()Ray.from_target_frame()Ray.convert_to()Ray.correct_refraction()Ray.interp()Ray.project_to_cam()Ray.replace_frame()Ray.to_ecef()Ray.to_frame()Ray.to_ned()Ray.az_elRay.backendRay.frameRay.has_timeRay.origin_pointsRay.origin_relRay.timeRay.total_angleRay.unit_ecefRay.unit_rel
RotationRotation.singleRotation.__len__()Rotation.from_quat()Rotation.from_matrix()Rotation.from_rotvec()Rotation.from_mrp()Rotation.from_euler()Rotation.from_davenport()Rotation.as_quat()Rotation.as_matrix()Rotation.as_rotvec()Rotation.as_mrp()Rotation.as_euler()Rotation.as_davenport()Rotation.concatenate()Rotation.apply()Rotation.__mul__()Rotation.__pow__()Rotation.inv()Rotation.magnitude()Rotation.approx_equal()Rotation.mean()Rotation.reduce()Rotation.create_group()Rotation.__getitem__()Rotation.identity()Rotation.random()Rotation.align_vectors()Rotation.create_group()Rotation.align_vectors()Rotation.concatenate()Rotation.from_davenport()Rotation.from_euler()Rotation.from_matrix()Rotation.from_mrp()Rotation.from_quat()Rotation.from_rotvec()Rotation.identity()Rotation.random()Rotation.apply()Rotation.approx_equal()Rotation.as_davenport()Rotation.as_euler()Rotation.as_matrix()Rotation.as_mrp()Rotation.as_quat()Rotation.as_rotvec()Rotation.inv()Rotation.magnitude()Rotation.mean()Rotation.reduce()Rotation.shapeRotation.single
RotationSequenceVelocity- Submodules