Geometry#
Geometric computations are performed by low-level geometric engine described below and by a set of utilities based on the NAIF SPICE toolkit wrapped in Python by the SpiceyPy library. The main geometry object is the UVIS Geometry class, which provides a high-level interface to the geometric computations and stores the relevant geometric information for a given observation epoch.
Main geometry object#
Geometry engine#
Computational utilities#
- cassini_upyp.geometry.computational.xyz2radec(vectors, return_r=False, units='radians', ra_range=None)#
Convert Cartesian vectors to (RA, Dec) spherical coordinates.
- Parameters:
vectors (array-like, shape (..., 3)) – Cartesian vectors to convert.
return_r (bool, optional) – If True, also return the radial distance
r = ||vector||. Default is False.units ({'radians', 'degrees'}, optional) – Units of the returned angles. Default is ‘radians’.
ra_range ((float, float) or None, optional) – Desired wrapping interval for right ascension (RA). If None, defaults to (0, 2*pi) for radians or (0, 360) for degrees. Values are wrapped into
[min_ra, max_ra).
- Returns:
If
return_ris False: array of shape (…, 2) with columns (RA, Dec). Ifreturn_ris True: array of shape (…, 3) with columns (r, RA, Dec). If the input is a single vector of shape (3,), a 1D array is returned.- Return type:
numpy.ndarray
Notes
Dec is computed as
asin(z / r)(with safe handling for r=0).RA is computed with
atan2(y, x)and wrapped tora_range.
- cassini_upyp.geometry.computational.radec2xyz(coords, units='radians')#
Convert (RA, Dec) sky coordinates to Cartesian unit vectors.
- Parameters:
coords (array-like, shape (..., 2)) – Right ascension and declination pairs (RA, Dec).
units ({'radians', 'degrees'}, optional) – Units of the input angles. Default is ‘radians’.
- Returns:
Cartesian unit vectors of shape (…, 3). If the input is a single pair (shape (2,)), a 1D array of shape (3,) is returned.
- Return type:
numpy.ndarray
- Raises:
ValueError – If
unitsis not ‘radians’ or ‘degrees’.
- cassini_upyp.geometry.computational.vec_angle(v1, v2, units='degrees')#
Calculates the angle(s) between vectors.
If one of the inputs is a single vector and the other is an array of vectors, the function calculates the angle between the single vector and each vector in the array.
- Parameters:
v1 (array-like) – Vectors or arrays of vectors. The last dimension must be the vector size.
v2 (array-like) – Vectors or arrays of vectors. The last dimension must be the vector size.
units ({'radians', 'degrees'}, optional) – Units of the returned angle. Default is ‘degrees’.
- Returns:
The angle(s) between v1 and v2 in the specified units.
- Return type:
float or numpy.ndarray
- Raises:
ValueError – If the vector dimensions do not match or if the shapes are incompatible for broadcasting. If units is not ‘degrees’ or ‘radians’.
Examples
>>> vec_angle([1, 0, 0], [0, 1, 0]) 90.0 >>> vec_angle([1, 0, 0], [[0, 1, 0], [1, 0, 0]]) array([90., 0.]) >>> vec_angle([[1, 0], [0, 1]], [1, 1]) array([45., 45.])
- cassini_upyp.geometry.computational.max_angular_diameter(points)#
Compute the maximum angular separation among a set of vectors.
This returns the largest angle between any pair of input vectors, i.e. the maximum angular diameter of the point cloud on the unit sphere (after normalization).
- Parameters:
points (array-like, shape (N, 3)) – Input vectors.
- Returns:
Maximum angular separation in degrees.
- Return type:
float
- Raises:
ValueError – If any input vector has zero norm.
- cassini_upyp.geometry.computational.rotation_matrix(ra_center_deg, dec_center_deg)#
Build a rotation matrix for the observer reference frame (ORF) centered on (RA, Dec).
The returned matrix rotates J2000 Cartesian vectors so that the provided sky direction becomes the new reference center. The transformation implemented is:
rotation about z by
-RA_centerrotation about y by
Dec_center
- Parameters:
ra_center_deg (float) – Center right ascension in degrees.
dec_center_deg (float) – Center declination in degrees.
- Returns:
Rotation matrix.
- Return type:
numpy.ndarray, shape (3, 3)
- cassini_upyp.geometry.computational.is_in_frame(points, xrange, yrange)#
Return a boolean mask selecting 2D points inside (x, y) bounds.
- Parameters:
points (array-like, shape (N, >=2)) – Points array. Only columns 0 and 1 are used (x and y).
xrange (tuple[float, float]) – Inclusive bounds for x.
yrange (tuple[float, float]) – Inclusive bounds for y.
- Returns:
True for points inside the rectangle.
- Return type:
numpy.ndarray of bool, shape (N,)
- cassini_upyp.geometry.computational.is_vector_in_quadrilateral(v, quad)#
Determine whether one or several 3D vectors lies “inside” a quadrilateral defined by four 3D vectors on the unit sphere.
- Parameters:
v (array-like, shape (3,) or (N, 3)) – Vector(s) to test.
quad (array-like, shape (4, 3)) – Quadrilateral vertices (need not be unit length; they are normalized).
- Returns:
Boolean result(s). A scalar is returned if the input is a single vector.
- Return type:
bool or numpy.ndarray of bool
Notes
The test is performed by checking the consistency of the signs of dot products against the edge normals (cross products of consecutive vertices). Vectors lying on an edge (within a small tolerance) are considered inside.
- Raises:
ValueError – If
quaddoes not have shape (4, 3) or if any input vector has zero norm.
- cassini_upyp.geometry.computational.is_visible(points, body_position, radii, threshold=1e-06, starmode=False)#
Determine whether points are visible (not occulted) by a triaxial ellipsoid.
Visibility is evaluated for rays starting at the observer (located at
-body_positionin the same reference frame aspoints) and pointing towards the input direction vectorspoints. If a ray intersects the ellipsoid before reaching the target point, the point is considered occulted.- Parameters:
points (array-like, shape (3,) or (N, 3)) – Direction vectors from the observer toward the points to test.
body_position (array-like, shape (3,)) – Vector from the body center to the observer (same frame as
points).radii (array-like, shape (3,)) – Ellipsoid radii (a, b, c).
threshold (float, optional) – Tolerance used when comparing the intersection distance to the point distance. Default is 1e-6.
starmode (bool, optional) – If True, any intersection implies invisibility (no distance comparison). Default is False.
- Returns:
Visibility mask. A scalar is returned if the input is a single vector.
- Return type:
bool or numpy.ndarray of bool
Notes
This function relies on
intersect()for the ray/ellipsoid intersection.
- cassini_upyp.geometry.computational.order_bool(bool_list)#
Return indices that rotate a boolean sequence to group identical values.
This helper returns a permutation of indices intended to reorder a boolean list so that transitions are moved to the ends (i.e., values are grouped as much as possible) by circularly rotating the sequence.
- Parameters:
bool_list (array-like of bool) – Input boolean sequence.
- Returns:
Indices that can be used to reorder the input (e.g.,
arr[idx]).- Return type:
numpy.ndarray of int
Notes
If the input is all True or all False, the identity ordering is returned.
- cassini_upyp.geometry.computational.intersect(observer, directions, radii, closest_point=False)#
Compute intersections between rays and a triaxial ellipsoid.
Rays are defined by an observer position and one or more direction vectors. When
closest_pointis False, the function returns the first intersection point along each ray (smallest root). Whenclosest_pointis True, it returns the point on the ray closest to the ellipsoid center (not necessarily an intersection point), along with a mask indicating whether the ray intersects the ellipsoid.- Parameters:
observer (array-like, shape (3,)) – Ray origin.
directions (array-like, shape (3,) or (N, 3)) – Ray direction vectors.
radii (array-like, shape (3,)) – Ellipsoid radii (a, b, c).
closest_point (bool, optional) – If True, return the closest point along each ray (t = -B/(2A)) and the intersection mask. Default is False.
- Returns:
(intercepts, found) –
- interceptsnumpy.ndarray, shape (N, 3)
Intersection points (or closest points if
closest_pointis True). Non-intersecting rays have NaNs whenclosest_pointis False.- foundnumpy.ndarray of bool, shape (N,)
True where an intersection exists (delta >= 0).
- Return type:
tuple
Notes
Directions do not need to be unit vectors.
- cassini_upyp.geometry.computational.ellipsoid_coords(radii, lon, lat)#
Compute Cartesian surface coordinates on a triaxial ellipsoid.
- Parameters:
radii (array-like, shape (3,)) – Ellipsoid radii (a, b, c).
lon (float or array-like) – Longitude(s) in radians.
lat (float or array-like) – Latitude(s) in radians.
- Returns:
Cartesian coordinates on the ellipsoid surface. Shape (3,) for scalar inputs or (N, 3) for array inputs.
- Return type:
numpy.ndarray
- Raises:
ValueError – If radii does not contain exactly three elements or if lon/lat cannot be broadcast to a common shape.
- cassini_upyp.geometry.computational.ellipsoid_xyz(radii, vec, return_altitude=True, units='radians')#
Convert Cartesian coordinates to (lon, lat, altitude) relative to a triaxial ellipsoid.
Longitude/latitude are computed from normalized coordinates (x/a, y/b, z/c). The returned “altitude” is a radial height-like quantity derived from the distance to the origin and the scaled radius factor
s.- Parameters:
radii (array-like, shape (3,)) – Ellipsoid radii (a, b, c).
vec (array-like, shape (3,) or (N, 3)) – Cartesian coordinates.
return_altitude (bool, optional) – If True, return a radial altitude-like quantity. If False, return the Euclidean distance to the origin. Default is True.
units ({'radians', 'degrees'}, optional) – Units for longitude and latitude. Default is ‘radians’.
- Returns:
longitude (float or numpy.ndarray) – Longitude (wrapped into [0, 2*pi) in radians, or [0, 360) in degrees).
latitude (float or numpy.ndarray) – Latitude in radians (or degrees if requested).
altitude_or_distance (float or numpy.ndarray) – Altitude if
return_altitudeis True, else distance.
- Raises:
ValueError – If any radius is non-positive.
Plotting#
Observation geometry during flyby T10 on 15 January 2006.#
Example FUV image of Titan during flyby T10 on 15 January 2006. The wavelength band used in this image is 1600-1900 Å.#
Miscellaneous#
See the resources page.
- cassini_upyp.geometry.geometry.stars_pickles()#
Load the pre-processed Pickles & Depagne (2010) Tycho-2 star catalog subset.
This function loads a NumPy structured array saved as
stars.npy. The file is derived from Table 15 of Pickles & Depagne (2010) (Tycho-2 spectrally matched catalog) and reduced/filtered for the needs of this package. Only stars with a U band magnitude brighter than 10 are included.The returned structured array contains the following fields:
tyRA: Right ascension [deg].tyDE: Declination [deg].pmRA: Proper motion in RA [mas/yr].pmDE: Proper motion in Dec [mas/yr].Bt: Tycho-2 B_T magnitude.eBt: Uncertainty on B_T.fBt: Spectrally matched / fitted B_T magnitude.U: Spectrally matched / fitted U magnitude.RA_cor: Proper-motion corrected RA at the observation epoch [°].DEC_cor: Proper-motion corrected Dec at the observation epoch [°].XYZ: Unit direction vector in the J2000 frame.
- Returns:
Structured NumPy array containing the star catalog subset.
- Return type:
numpy.ndarray
Notes
RA_cor,DEC_corandXYZare computed
later depending on the observation epoch..
- Raises:
FileNotFoundError – If the file specified by the user configuration
env.star_filedoes not exist.
References
Pickles and É. Depagne, 2010, Publications of the Astronomical Society of the Pacific, 122 1437