mirage package#

Subpackages#

Submodules#

mirage.albedo module#

mirage.albedo.albedo_irradiance(date: datetime, sat_pos_ecef: ndarray) float#

Computes the total irradiance reflected from the surface of Earth at a satellite [W/m^2] The surface BRDF function used here is found in Blanc 2014

Parameters:
  • date (datetime.datetime) – Date to evaluate at (UTC)

  • sat_pos_ecef (np.ndarray) – Position of the satellite in Earth-Centered Earth-Fixed coordianates (ex. ITRF)

Returns:

Total irradiance due to Earth albedo [W/m^2]

Return type:

float

mirage.attitude module#

class mirage.attitude.AlignedAndConstrainedAttitude(v_align: ndarray, v_const: ndarray, dates: ndarray[datetime, Any], axis_order: Tuple[int] = (0, 1, 2))#

Bases: object

basis_vectors_at_dates(dates: ndarray[datetime, Any]) tuple[ndarray, ndarray, ndarray]#

Body basis vectors in inertial coordinates

Parameters:

dates (np.ndarray[datetime.datetime, Any] [n,]) – Dates (UTC)

Returns:

First, second, and third body basis vectors in inertial coordinates

Return type:

tuple[np.ndarray, np.ndarray, np.ndarray]

dcms_at_dates(dates_or_jds: ndarray[datetime | float]) ndarray#

DCM from inertial to body axes

Parameters:

dates_or_jds (np.ndarray[Union[datetime.datetime, float]] [n,]) – Dates or Julian dates (UTC)

Returns:

DCM array

Return type:

np.ndarray [3,3xn]

propagate(epsecs: ndarray) tuple[ndarray, ndarray]#

Propagates the attitude profile to an array of epoch seconds

Parameters:

epsecs (np.ndarray [n,]) – Seconds after the definition epoch

Returns:

Quaternion and angular velocity [rad/s] at each requested time

Return type:

tuple[np.ndarray [n,4], np.ndarray [n,3]]

class mirage.attitude.AttitudeRepresentation(repr_name: str, components: ndarray)#

Bases: object

identity()#

Returns the identity element of SO3 as the current representation type, if possible

Returns:

The identity element

Return type:

AttitudeRepresentation

inverse()#

Returns the inverse of the attitude in the current representation via quaternions

Returns:

Inverse of the current attitude

Return type:

AttitudeRepresentation

to(target_repr_name: str)#

Converts the attitude in self to a new representation

Parameters:

target_repr_name (str) – Name of the target representation name

Returns:

Coverted attitude representation

Return type:

AttitudeRepresentation

to_upper_hemisphere()#

Transforms the attitude representation to the upper hemisphere of \(S^3\) via quaternions

Returns:

Upper hemisphere representation

Return type:

AttitudeRepresentation

class mirage.attitude.RbtfAttitude(w0: ndarray, q0: ndarray, itensor: ndarray)#

Bases: object

Class for rigid body torque free attitude propatation using accelerated semi-analytical solution with elliptic integrals

dcms_at_dates(dates_or_jds: ndarray[datetime | float]) ndarray#

The direction cosine matrices for the orientation of this attitude profile at a set of datetimes or Julian dates

Parameters:

dates_or_jds (np.ndarray[Union[datetime.datetime, float]]) – Array of datetimes or Julian dates

Returns:

Stack of DCMs \(A_i\) which each transform inertial vectors into the body frame via multiplication on the left

Return type:

np.ndarray [3,3xn]

propagate(epsec_space: ndarray) Tuple[ndarray, ndarray]#

Propagates attitude forward to all epoch seconds

Parameters:

epsec_space (np.ndarray) – Seconds after the definition epoch to propagate to

Returns:

Orientation of body over time as a quaternion and body frame angular velocity

Return type:

Tuple[np.ndarray [n,4], np.ndarray [n,3]]

class mirage.attitude.SpinStabilizedAttitude(rot_rate: float, inertial_rot_axis: ndarray, jd0: float, rot_angle0: float)#

Bases: object

basis_vectors_at_jds(jd_eval: ndarray) Tuple[ndarray, ndarray, ndarray]#

Returns the set of basis vectors in the inertial frame at a given Julian date, used for plotting

Parameters:

jd_eval (np.ndarray [n,]) – Julian dates to evaluate at

Returns:

Unit vector bases at each time

Return type:

Tuple[np.ndarray [n,3], np.ndarray [n,3], np.ndarray [n,3]]

dcms_at_dates(dates_or_jds: ndarray[datetime | float]) ndarray#

DCM from inertial to body axes

Parameters:

dates_or_jds (np.ndarray[Union[datetime.datetime, float]] [n,]) – Dates or Julian dates to evaluate at (UTC)

Returns:

DCMs

Return type:

np.ndarray [3,3xn]

propagate(epsecs: ndarray) ndarray#

Propagates the attitude profile to an array of epoch seconds

Parameters:

epsecs (np.ndarray [n,]) – Seconds after the definition epoch

Returns:

Quaternion and angular velocity [rad/s] at each requested time

Return type:

tuple[np.ndarray [n,4], np.ndarray [n,3]]

mirage.attitude.analytic_torque_free_angular_velocity(omega0: ndarray, itensor: ndarray, teval: ndarray, itensor_org_factor: int = 1) Tuple[ndarray, float, float, float, bool]#

Analytically propogates angular velocity assuming no torque is being applied

Parameters:
  • omega0 (np.ndarray [n,3]) – Initial angular velocity in body frame [rad/s]

  • itensor (np.ndarray [3,3]) – Principal moments of inertia satisfying i[3,3] < i[2,2] < i[1,1] [kg m^2]

  • teval (np.ndarray [n,]) – Times to compute angular velocity for after initial state time [seconds]

  • itensor_org_factor (int, optional) – If inertia tensor was reorganized with an even or odd number of flips, defaults to 1

Returns:

Angular velocity [rad/s]; \(k^2\) term of elliptic integral, \(\tau_0\), \(\dot{\tau}\); short-axis model (SAM) flag

Return type:

Tuple[np.ndarray [n,3], float, float, float, bool]

mirage.attitude.analytic_torque_free_attitude(quat0: ndarray, omega: ndarray, itensor: ndarray, teval: ndarray, ksquared: float, tau0: float, tau_dot: float, is_sam: bool, itensor_org_factor: int = 1, itensor_inv_inds: list = [0, 1, 2]) ndarray#

Analytically propagates orientation under torque-free rigid-body motion

Parameters:
  • quat0 (np.ndarray [4x1]) – Quaternion from the body frame to inertial at initial time step

  • omega (np.ndarray [n,3]) – Body angular velocities at each point in teval [rad/s]

  • itensor (np.ndarray [3,3]) – Principal inertia tensor satisfying itensor[0,0] <= itensor[1,1] <= itensor[2,2] [kg m^2]

  • teval (np.ndarray [n,]) – Times to output attitude soliution at, teval[0] corresponds to quat0 and omega[0,:]

  • ksquared (float) – \(k^2\) parameter from the angular velocity propagation

  • tau0 (float) – Initial value of :math:` au` from the angular velocity propagation

  • tau_dot (float) – Rate of change of :math:` au` from the angular velocity propagation

  • is_sam (bool) – Indicates the rotation mode. 0 = long-axis mode (LAM), 1 = short-axis mode (SAM)

  • itensor_org_factor (int, optional) – Indicates if an even or odd number of flips was required to reorganize the inertia tensor, defaults to 1

  • itensor_inv_inds (list, optional) – Inverse mapping from the user’s inertia tensor to the one used here, defaults to [0, 1, 2]

Returns:

Propagated quaternions at each time in teval

Return type:

np.ndarray [n,]

mirage.attitude.davenport(rhat_body: ndarray, rhat_ref: ndarray) ndarray#

Computes the quaternion estimate of the attitude of a body using Davenport’s q-method.

Parameters:
  • rhat_body (np.ndarray [n,3]) – The unit vectors in the body frame

  • rhat_ref (np.ndarray [n,3]) – The same unit vectors in the reference frame

Returns:

Quaternion estimate of the attitude of the body

Return type:

np.ndarray [4,1]

mirage.attitude.dcm_to_ea313(dcm: ndarray) ndarray#

Finds the Euler angle (3-1-3) body frame sequence corresponding to the input direction cosine matrices

Parameters:

dcm (np.ndarray [3,3xn]) – DCM array

Returns:

Euler angle array

Return type:

np.ndarray [n,3]

mirage.attitude.dcm_to_mrp(c: ndarray) ndarray#

Converts direction cosine matrices to modified Rodrigues parameters via quaternions

Parameters:

c (np.ndarray [3,3xn]) – Direction cosine matrix array

Returns:

MRP array

Return type:

np.ndarray [n,3]

mirage.attitude.dcm_to_quat(c: ndarray) ndarray#

Converts DCMs to quaternions using Sheppard’s method

Parameters:

c (np.ndarray [3,3xn]) – Input DCM array

Returns:

Computed quaternions

Return type:

np.ndarray [n,4]

mirage.attitude.dcm_to_rv(c: ndarray) ndarray#

Converts DCMs to rotation vectors by way of quaternions

Parameters:

c (np.ndarray [3,3xn]) – Input DCM array

Returns:

Computed rotation vectors

Return type:

np.ndarray [n,3]

mirage.attitude.ea_to_dcm(seq: Tuple[int, int, int], a1: ndarray, a2: ndarray, a3: ndarray) ndarray#

Converts a set of Euler angle (EA) sequences (in radians) to DCMs

Parameters:
  • seq (Tuple[int, int, int]) – Axes to rotate about, ex: (1,2,3) gives 1-2-3 sequence

  • a1 (np.ndarray [n,]) – First rotation angle [rad]

  • a2 (np.ndarray [n,]) – Second rotation angle [rad]

  • a3 (np.ndarray [n,]) – Third rotation angle [rad]

Returns:

Computed DCMs

Return type:

np.ndarray [3,3xn]

mirage.attitude.gravity_gradient_torque(itensor: ndarray, rvec: ndarray, mu: float = 398600.4418) ndarray#

Computes gravity gradient torque in the body frame

Parameters:
  • itensor (np.ndarray [3,3]) – Inertia tensor in body axes [kg m^2]

  • rvec (np.ndarray [1x3]) – Position vector of body [km]

  • mu (float, optional) – Gravitational parameter of central body, defaults to AstroConstants.earth_mu

Returns:

Gravity gradient torque in body frame [N m]

Return type:

np.ndarray [1x3]

mirage.attitude.integrate_rigid_attitude_dynamics(q0: ~numpy.ndarray, omega0: ~numpy.ndarray, itensor: ~numpy.ndarray, teval: ~numpy.ndarray, body_torque: ~typing.Callable = <function <lambda>>, int_tol: float = 1e-13, method: str = 'RK45') Tuple[ndarray, ndarray]#

Integration for rigid body rotational dynamics

Parameters:
  • q0 (np.ndarray [1x4]) – Initial quaternion from inertial to body frame

  • omega0 (np.ndarray [1x3]) – Initial angular velocity vector of body relative to inertial space [rad/s]

  • itensor (np.ndarray [3,3]) – Principal inertia tensor [kg m^2]

  • teval (np.ndarray [n,]) – Times to return integrated trajectory at [second]

  • body_torque (Callable, optional) – Body torques function f(t,y) -> [3,] [Nm], defaults to np.zeros(3)

  • int_tol (float, optional) – Integration rtol and atol for RK45, defaults to 1e-13

  • method (str, optional) – scipy.integrate.solve_ivp method keyword argument to use, defaults to ‘RK45’

Returns:

Integrated quaternions [n,4]; integrated angular velocities [n,3]

Return type:

Tuple[np.ndarray, np.ndarray]

mirage.attitude.itensor_is_symmetric(itensor: ndarray) Tuple#
mirage.attitude.mrp_add(s1: ndarray, s2: ndarray) ndarray#

Adds modified Rodrigues parameters (see quat_add)

Parameters:
  • s1 (np.ndarray [n,3]) – Modified Rodrigues parameter array

  • s2 (np.ndarray [n,3]) – Modified Rodrigues parameter array

Returns:

Modified Rodrigues parameter array

Return type:

np.ndarray [n,3]

mirage.attitude.mrp_to_dcm(s: ndarray) ndarray#

Converts modified Rodrigues parameters to direction cosine matrices

Parameters:

s (np.ndarray [n,3]) – Modified Rodrigues parameter array

Returns:

Direction cosine matrix array

Return type:

np.ndarray [3,3xn]

mirage.attitude.mrp_to_quat(s: ndarray) ndarray#

Converts modified Rodrigues parameters to quaternions

Parameters:

s (np.ndarray [n,3]) – Modified Rodrigues parameter array

Returns:

Quaternion array

Return type:

np.ndarray [n,4]

mirage.attitude.mrp_to_rv(s: ndarray) ndarray#

Converts modified Rodrigues parameters to rotation vectors

Parameters:

s (np.ndarray [n,3]) – Modified Rodrigues parameter array

Returns:

Rotation vector array

Return type:

np.ndarray [n,3]

mirage.attitude.propagate_attitude_torque_free(quat0: ndarray, omega0: ndarray, itensor: ndarray, teval: ndarray) Tuple[ndarray, ndarray]#

Computes torque free motion for a arbitrary inertia tensor using elliptic integrals and Jacobi elliptic functions

Parameters:
  • quat0 (np.ndarray [n,4]) – Initial orientation as quaternion

  • omega0 (np.ndarray [n,3]) – Initial angular velocity [rad/s]

  • itensor (np.ndarray [3,3]) – Inertia tensor in principal axes [kg m^2]

  • teval (np.ndarray [m,]) – Times to evaluate at past initial state [second]

Returns:

Orientation of body over time as a quaternion and body frame angular velocity

Return type:

Tuple[np.ndarray [n,m,4], np.ndarray [n,m,3]]

mirage.attitude.propagate_attitude_torque_free_axisymmetric(quat0: ndarray, omega0: ndarray, itensor: ndarray, teval: ndarray) ndarray#

Propagates torque-free axisymmetric motion using an analytic solution to the constant spin and precession rate

Parameters:
  • quat0 (np.ndarray [n,4]) – Initial quaternion transforming from the inertial to body frames

  • omega0 (np.ndarray [n,3]) – Initial angular velocity [rad/s]

  • itensor (np.ndarray) – Inertia tensor [kg m^2]

  • teval (np.ndarray [n,]) – Time space in seconds after the definition epoch where quat0 and omega0 are defined

Returns:

The time history of the quaterion at the requested epochs

Return type:

np.ndarray [n,4]

mirage.attitude.quat_add(q1: ndarray, q2: ndarray) ndarray#

Adds (multiplies) quaternions together such that quat_add(quat_inv(q1), q2) gives the rotation between q1 and q2

Parameters:
  • q1 (np.ndarray [n,4]) – Quaternion array

  • q2 (np.ndarray [n,4]) – Quaternion array

Returns:

Quaternion array

Return type:

np.ndarray [n,4]

mirage.attitude.quat_ang(q1: ndarray, q2: ndarray) ndarray#

Angle between orientations expressed as quaternion arrays (makes sure they are on the same hemisphere of the hypersphere first)

Parameters:
  • q1 (np.ndarray [n,4]) – Quaternion array

  • q2 (np.ndarray [n,4]) – Quaternion array

Returns:

Angle between quaternion arrays [rad]

Return type:

np.ndarray [n,]

mirage.attitude.quat_inv(q: ndarray) ndarray#

Finds the quaternion inverse (conjugate for unit quaternions)

Parameters:

q (np.ndarray [n,4]) – Input quaternion array

Returns:

Inverse quaternion array

Return type:

np.ndarray [n,4]

mirage.attitude.quat_inverse_kinematics(q: ndarray, qdot: ndarray) ndarray#

Inverse kinematic differential equations, returns angular velocity [rad/s]

Parameters:
  • q (np.ndarray [n,4]) – Quaternions

  • qdot (np.ndarray [n,4]) – Quaternion derivatives

Returns:

Angular velocity of body frame [rad/s]

Return type:

np.ndarray [n,3]

mirage.attitude.quat_kinematics(q: ndarray, w: ndarray) ndarray#

Kinematic differential equations for quaternion time evolution

Parameters:
  • q (np.ndarray [1x4]) – Current quaternion from inertial to body

  • w (np.ndarray [1x3]) – Current angular velocity in body frame [rad/s]

Returns:

Time derivative of input quaternion

Return type:

np.ndarray [1x3]

mirage.attitude.quat_r_from_eas(hhat: ndarray, phi: ndarray, theta: ndarray, psi: ndarray, is_sam: bool) ndarray#

Computes quaternion for attitude solution from Euler angle sequence

Parameters:
  • hhat (np.ndarray [1x3]) – Inertial angular momentum direction

  • phi (np.ndarray [n,]) – Spin angle [rad]

  • theta (np.ndarray [n,]) – Nutation angle [rad]

  • psi (np.ndarray [n,]) – Precession angle [rad]

  • is_sam (bool) – Whether the rotation is short axis mode (SAM)

Returns:

Computed quaternions

Return type:

np.ndarray [n,4]

mirage.attitude.quat_to_dcm(q: ndarray) ndarray#

Converts quaternions to direction cosine matrices

Parameters:

q (np.ndarray [n,4]) – Quaternion array

Returns:

Direction cosine matrix array

Return type:

np.ndarray [3,3xn]

mirage.attitude.quat_to_mrp(q: ndarray) ndarray#

Converts quaternions to modified Rodrigues parameters

Parameters:

q (np.ndarray [n,4]) – Quaternion array

Returns:

Modified Rodrigues parameter array

Return type:

np.ndarray [n,3]

mirage.attitude.quat_to_rv(q: ndarray) ndarray#

Converts quaternions to rotation vectors

Parameters:

q (np.ndarray [n,4]) – Quaternion array

Returns:

Rotation vector array

Return type:

np.ndarray [n,3]

mirage.attitude.quat_upper_hemisphere(q: ndarray) ndarray#

Transforms any quaternions in q to the upper hemisphere of S^3 such that q[:,3] > 0

Parameters:

q (np.ndarray [n,4]) – Quaternion array

Returns:

Transformed quaternion array

Return type:

np.ndarray [n,4]

mirage.attitude.r1(t: ndarray | float) ndarray#

Rotation about the first body axis with input in radians

Parameters:

t (Union[np.ndarray, float]) – Angle t (short for theta) [rad]

Returns:

Rotation matrix(s) about the first body axis

Return type:

np.ndarray

mirage.attitude.r2(t: ndarray | float) ndarray#

Rotation about the second body axis with input in radians

Parameters:

t (Union[np.ndarray, float]) – Angle t (short for theta) [rad]

Returns:

Rotation matrix(s) about the second body axis

Return type:

np.ndarray

mirage.attitude.r3(t: ndarray | float) ndarray#

Rotation about the third body axis with input in radians

Parameters:

t (Union[np.ndarray, float]) – Angle t (short for theta) [rad]

Returns:

Rotation matrix(s) about the third body axis

Return type:

np.ndarray

mirage.attitude.rand_quaternions(num: int) ndarray#

Generates uniform random vectors on \(S^3\) (interpreted as unit quaternions)

Parameters:

num (int) – Number of unit vectors to generate

Returns:

Sampled quaternions

Return type:

np.ndarray [n,4]

mirage.attitude.rigid_rotation_dynamics(t: float, w: ndarray, itensor: ndarray, torque: Callable | None = None) ndarray#

Rigid body rotational dynamics (Euler’s equations of motion)

Parameters:
  • t (float) – Current integration time [seconds]

  • w (np.ndarray [1x3]) – Angular velocity vector of body relative to inertial space [rad/s]

  • itensor (np.ndarray [3,3]) – Inertia tensor in principal axes, should be diagonal [kg m^2]

  • torque (Callable, optional) – Torque applied to the body due to external forces [N m], defaults to None

Returns:

Angular acceleration vector [rad/s^2]

Return type:

np.ndarray [1x3]

mirage.attitude.rv_add(p1: ndarray, p2: ndarray) ndarray#

Adds rotation vectors (see quat_add)

Parameters:
  • p1 (np.ndarray [n,3]) – Rotation vector array

  • p2 (np.ndarray [n,3]) – Rotation vector array

Returns:

Rotation vector array

Return type:

np.ndarray [n,3]

mirage.attitude.rv_to_dcm(p: ndarray) ndarray#

Converts rotation vectors to direction cosine matrices

Parameters:

p (np.ndarray [n,3]) – Rotation vector array

Returns:

Direction cosine matrix array

Return type:

np.ndarray [3,3xn]

mirage.attitude.rv_to_mrp(p: ndarray) ndarray#

Converts rotation vectors to modified Rodrigues parameters via quaternions

Parameters:

p (np.ndarray [n,3]) – Rotation vector array

Returns:

Quaternion array

Return type:

np.ndarray [n,4]

mirage.attitude.rv_to_quat(p: ndarray) ndarray#

Converts rotation vectors to quaternions

Parameters:

p (np.ndarray [n,3]) – Rotation vector array

Returns:

Quaternion array

Return type:

np.ndarray [n,4]

mirage.background module#

mirage.background.aint(station, z_obs: ndarray, lambda_lims: Tuple = (100, 1050), is_ground_based: bool = True) ndarray#

Computes the count rate per steradian for the airglow spectrum [Kra03]

Parameters:
  • station (Station) – The station to observe from

  • z_obs (np.ndarray) – Zenith angle of observation [rad]

  • lambda_lims (Tuple, optional) – Wavelength limits to integrate over [m], defaults to (100, 1050) [nm]

  • is_ground_based (bool) – Whether the station taking the observation is ground or space based

Returns:

Count rate per steradian [ADU/s/sterad]

Return type:

np.ndarray

mirage.background.airglow_radiance(lambdas: ndarray) ndarray#

Computes spectral radiances due to airglow :cite:p:daniels1977:

Parameters:

lambdas (np.ndarray) – Wavelengths to interpolate [nm]

Returns:

Spectral radiances [W/m^2/nm/ster]

Return type:

np.ndarray

mirage.background.airglow_signal(dates: ndarray[datetime, Any], station, look_dirs_eci_eq: ndarray, obs_pos_eci_eq: ndarray, integration_time_s: float, is_ground_based: bool = True) ndarray#

Signal on CCD sensor due to airglow [Kra03]

Parameters:
  • dates (np.ndarray[datetime.datetime, Any]) – Dates to evaluate at (UTC)

  • station (Station) – The station to observe from

  • look_dirs_eci_eq (np.ndarray) – Look unit vectors in ecliptic Earth-centered inertial (ECI)

  • obs_pos_eci_eq (np.ndarray) – Observer positions in ecliptic Earth-centered inertial (ECI) [km]

  • is_ground_based (bool) – Whether the station taking the observation is ground or space based

Returns:

Signal on CCD [e-/pixel]

Return type:

np.ndarray

mirage.background.atmospheric_extinction(lambdas: ndarray) ndarray#

Calculates atmospheric extinction coefficient as described in [Kra03]

Parameters:

lambdas (np.ndarray) – Wavelengths to sample [m]

Returns:

Atmospheric extinction coefficient [nondim]

Return type:

np.ndarray

mirage.background.equatorial_dir_to_ecliptic_azel(dates: ndarray[datetime, Any], look_dirs_eci_eq: ndarray) Tuple[ndarray, ndarray]#

Converts from equatorial to ecliptic azimuth and elevation

Parameters:
  • dates (np.ndarray[datetime.datetime, Any]) – Dates to evaluate at (UTC)

  • look_dirs_eci_eq (np.ndarray) – Look directions in Earth-Centered Inertial (ex. J2000), referenced to the Earth equator

Returns:

Ecliptic-referenced azimuth and elevation, both [rad]

Return type:

Tuple[np.ndarray, np.ndarray]

mirage.background.individual_atmospheric_transmission(lambdas: ndarray, zenith_angles_rad: ndarray = 0.0, observer_altitude_km: float = 0.0)#
mirage.background.integrated_spectrum(station, z_obs: ndarray, lambdas: ndarray = array([330., 353.79310345, 377.5862069, 401.37931034, 425.17241379, 448.96551724, 472.75862069, 496.55172414, 520.34482759, 544.13793103, 567.93103448, 591.72413793, 615.51724138, 639.31034483, 663.10344828, 686.89655172, 710.68965517, 734.48275862, 758.27586207, 782.06896552, 805.86206897, 829.65517241, 853.44827586, 877.24137931, 901.03448276, 924.82758621, 948.62068966, 972.4137931, 996.20689655, 1020.]), spectrum: ndarray | None = None, area: float | None = None, is_ground_based: bool = True, include_atmospheric_transmission: bool = True) ndarray#

Computes the count rate in [ADU / s] due to an exoatmospheric photon spectrum [Kra03]

Parameters:
  • station (Station) – The station to observe from

  • z_obs (np.ndarray [mx1]) – Zenith angle of observation [rad]

  • lambdas (np.ndarray [nx1], optional) – Wavelengths to integrate over [nm], defaults to np.linspace(330, 1020, 30)

  • spectrum (Union[np.ndarray [nx1], None], optional) – Irradiance or radiance spectrum to integrate over, None defaults to the Sun spectrum [W / m^2 / nm]

  • area – Area to distribute the signal over, [m^2] if the spectrum is [W / m^2 / nm]. Defaults to station.telescope.aperture_area. If the spectrum is [W / m^2 / nm / sr], area is [sr]

  • is_ground_based (bool) – Whether the station taking the observation is ground or space based

Returns:

Count rate [ADU / s] that can be multiplied by integration time for counts

Return type:

np.ndarray

mirage.background.integrated_starlight_signal(station, look_dirs_eci_eq: ndarray, obs_pos_eci_eq: ndarray, integration_time_s: float, is_ground_based: bool = True, **_) ndarray#

Computes the mean signal [e-/pix] on the CCD due to integrated starlight from magnitudes 16 to 21 using a patched Gaia catalog [Kra03]

Parameters:
  • station (Station) – The station to observe from

  • look_dirs_eci_eq (np.ndarray) – Look unit vectors in equatorial Earth-centered inertial (ECI)

  • obs_pos_eci_eq (np.ndarray) – Observer positions in equatorial Earth-centered inertial (ECI) [km]

  • is_ground_based (bool) – Whether the station taking the observation is ground or space based

Returns:

Signal on CCD [e-/pixel]

Return type:

np.ndarray

mirage.background.moon_phase_fraction(moon_phase_angle: ndarray) ndarray#

Computes the brightness fraction at a given lunar phase angle [Kra03]

Parameters:

moon_phase_angle (np.ndarray) – Angle between Earth and Sun from the perspective of the Moon [rad]

Returns:

Fraction of full Moon radiance at observer [nondim]

Return type:

np.ndarray

mirage.background.moonlight_signal(dates: ndarray[datetime, Any], station, look_dirs_eci_eq: ndarray, obs_pos_eci_eq: ndarray, integration_time_s: float, is_ground_based: bool = True) ndarray#

Mean signal on image background due to scattered moonlight

Parameters:
  • dates (np.ndarray[datetime.datetime, Any]) – Dates to evaluate brightnesss at [utc]

  • station (Station) – The station to observe from

  • look_dirs_eci_eq (np.ndarray) – Look unit vectors in ecliptic Earth-centered inertial (ECI)

  • obs_pos_eci_eq (np.ndarray) – Observer positions in ecliptic Earth-centered inertial (ECI) [km]

  • is_ground_based (bool) – Whether the station taking the observation is ground or space based

Returns:

Background signal due to moonlight [e-/pix]

Return type:

np.ndarray

mirage.background.proof_zero_mag_stellar_spectrum(lambdas: ndarray) ndarray#

Interpolates the spectrum of a representative zero-magnitude star

Parameters:

lambdas (np.ndarray) – Wavelengths to sample [nm]

Returns:

Interpolated spectrum [W/m^2/nm]

Return type:

np.ndarray

mirage.background.sint(station, z_obs: ndarray, lambda_lims: Tuple = (100, 1050), is_ground_based: bool = True) ndarray#

Computes the electron rate per unit irradiance for the Sun spectrum [Kra03]

Parameters:
  • station (Station) – The station to observe from

  • z_obs (np.ndarray) – Zenith angle of observation [rad]

  • lambda_lims (Tuple, optional) – Wavelength limits to integrate over [m], defaults to (100, 1050 nm)

  • is_ground_based (bool) – Whether the station taking the observation is ground or space based

Returns:

Count rate per unit irradiance [e- / (W / m^2 * s)] that can be multiplied by irradiance and integration time for counts

Return type:

np.ndarray

mirage.background.twilight_signal(dates: ndarray[datetime, Any], station, look_dirs_eci_eq: ndarray, obs_pos_eci_eq: ndarray, integration_time_s: float, is_ground_based: bool = True, band: str = 'V') ndarray#

Signal on CCD sensor due to the setting or rising sun [PatatUgolnikovPostylyakov06]

Parameters:
  • dates (np.ndarray[datetime.datetime, Any]) – Dates to evalute at (UTC)

  • station (Station) – The station to observe from

  • look_dirs_eci_eq (np.ndarray) – Look unit vectors in equatorial Earth-centered inertial (ECI)

  • obs_pos_eci_eq (np.ndarray) – Observer positions in equatorial Earth-centered inertial (ECI) [km]

  • is_ground_based (bool) – Whether the station taking the observation is ground or space based

  • band (str, optional) – Which UVBRI band the observation is in

Returns:

Signal on CCD [e-/pixel]

Return type:

np.ndarray

mirage.background.twilight_zenith_mpsas(gamma: ndarray, band: str = 'V') ndarray#

Zenith brightness due to twilight :cite:p:patat2006:

Parameters:
  • gamma (np.ndarray) – Zenith angle [deg]

  • band (str, optional) – Observation band (UBVRI filter), defaults to “V”

Returns:

Twilight brightness in magnitudes per square arcsecond

Return type:

np.ndarray

mirage.background.zodiacal_signal(dates: ndarray[datetime, Any], station, look_dirs_eci_eq: ndarray, obs_pos_eci_eq: ndarray, integration_time_s: float, is_ground_based: bool = True) ndarray#

Computes signal in CCD due to zodiac light [Kra03]

Parameters:
  • look_dirs_eci_eq (np.ndarray) – Look unit vectors in ecliptic Earth-centered inertial (ECI)

  • obs_pos_eci_eq (np.ndarray) – Observer positions in ecliptic Earth-centered inertial (ECI) [km]

  • station (Station) – The station to observe from

  • is_ground_based (bool) – Whether the station taking the observation is ground or space based

Returns:

Signal on CCD [e-/pixel]

Return type:

np.ndarray

mirage.ccd module#

class mirage.ccd.ChargeCoupledDevice(preset: str = 'pogs')#

Bases: object

generate_ccd_image(date: datetime, integration_time_s: float, station, look_dir_eci: ndarray, tracking_rates: ndarray, lc_adu: float, catalog: StarCatalog, up_dir_eci: ndarray, noise: bool = True, sky_brightness: bool = True, add_catalog: bool = True, add_distortion: bool = True, verbose: bool = True, binning: tuple | None = None, flat_field: Callable | None = None) ndarray#

Generates a CCD image for a set of observation conditions

Parameters:
  • date (datetime.datetime) – The midpoint of the integration time as a UTC datetime

  • integration_time_s (float) – Integration time in seconds

  • station (Station) – Station taking the observation

  • look_dir_eci (np.ndarray) – Look direction (unit vectors) in Earth-centered inertial (ECI) at the midpoint of the integration time

  • tracking_rates (np.ndarray) – The tracking rates of the telescope in RA/Dec at the midpoint of the integration time in [arcsec/s]

  • lc_adu (float) – The total brightness of the object (ADU)

  • catalog (StarCatalog) – The catalog to use for the background stars

  • up_dir_eci (np.ndarray) – The up directions of the telescope in ECI at the midpoint of the integration time

  • noise (bool, optional) – Whether to add noise to the image, defaults to True

  • sky_brightness (bool, optional) – Whether to account for the simulated sky brightness of the background, defaults to True

  • add_catalog (bool, optional) – Whether to add the catalog objects to the image, defaults to True

  • add_distortion (bool, optional) – Whether to add distortion to the image, defaults to True

  • binning (Union[tuple, None], optional) – Binning to add, i.e. (2,2), defaults to None

  • flat_field (Union[Callable, None], optional) – Flat field intensity as a function of the x,y pixel locations, defaults to None (1.0 for all pixels)

Returns:

Image matrix with the dimensions of the station’s telescope’s sensor (ADU)

Return type:

np.ndarray

mean(pixels: ndarray, integration_time_s: float) float#

Returns the mean noise signal due to the non-zero-mean noise terms: readout and integration noise

Parameters:
  • pixels (np.ndarray) – Number of pixels for each case

  • integration_time_s (float) – Integration time in seconds for each case

Returns:

Mean noise signal in each case

Return type:

float

quantum_efficiency(lambdas: ndarray) ndarray#

Computes quantum efficiency for a representative CCD sensor [Kra03]

Parameters:

lambdas (np.ndarray) – Sample wavelengths [nm]

Returns:

Quantum efficiency [photoelectrons/photon]

Return type:

np.ndarray

sample_noise(integration_time_s: float, pixels: int, shape: tuple) ndarray#

Samples the total noise signal in the CCD for a given number of pixels and integration time

Parameters:
  • integration_time_s (float) – Seconds of integration time

  • pixels (int) – Number of pixels being sampled

  • shape (tuple) – Shape of the output

Returns:

Sampled noise, each component independently sampled from the same noise distributions defined by the other inputs

Return type:

np.ndarray

variance(integration_time_s: ndarray | float) ndarray | float#

The variance of the noise signal due to dark integration, dark readout, and read noise

Parameters:

integration_time_s (Union[np.ndarray, float]) – Integration time in seconds

Returns:

Variance in [ADU^2]

Return type:

Union[np.ndarray, float]

mirage.ccd.ccd_minus_parabolic_background(ccd_adu: ndarray) ndarray#

Returns a copy of the CCD image with the parabolic background subtracted.

Parameters:

ccd_adu (np.ndarray) – CCD image in ADU

Returns:

CCD image with the parabolic background subtracted

Return type:

np.ndarray

mirage.ccd.convolve_with_kernel(image: ndarray, kernel: ndarray) ndarray#

Convolves an image with a given kernel

Parameters:
  • image (np.ndarray) – The image to convolve

  • kernel (np.ndarray) – The kernel to convolve with

Returns:

The convolved image

Return type:

np.ndarray

mirage.ccd.image_background_naive(ccd_adu: ndarray, frac_cuts: tuple[float, float] = (0.0001, 0.002)) tuple[ndarray, float]#

A naive approach to finding the constant background of a CCD image by cutting off a fraction of the brightest and dimmest pixels

Parameters:
  • ccd_adu (np.ndarray) – CCD image in ADU

  • frac_cuts (tuple[float, float], optional) – Fraction of values to cut off of the bottom and top of the sorted pixel counts, defaults to (1e-4, 1e-3)

Returns:

Boolean mask of pixels that are in the background, and the mean background ADU

Return type:

tuple[np.ndarray, float]

mirage.ccd.image_background_parabola(ccd_adu: ndarray, return_eq_str: bool = False, reduction_factor: int = 16) ndarray#

Fits a parabola to the background of a CCD image

Parameters:
  • ccd_adu (np.ndarray) – CCD image in ADU

  • return_eq_str (bool, optional) – Whether to return the string form of the parabola equation, defaults to False

  • reduction_factor (int, optional) – Factor to reduce the image by for speed, defaults to 10

Returns:

Mean background values for each pixel in the CCD image

Return type:

np.ndarray

mirage.ccd.solve_star_streak_angle(img: ndarray, template_streak_length: int = 100, square_size_of_image_used: int = 500) float#
mirage.ccd.streak_convolution(image: ndarray, direction: tuple[float, float], length: float) ndarray#

Convolves an image with a streak kernel of a given length in a given direction

Parameters:
  • image (np.ndarray) – Image to streak

  • direction (tuple[float, float]) – Direction to streak in, in the image plane frame

  • length (float) – Length of the streak kernel [pix]

Returns:

Streaked image

Return type:

np.ndarray

mirage.ccd.streak_convolution_kernel(direction: tuple[float, float], length: float) ndarray#

Generates the convolution kernel for a streak

Parameters:
  • direction (tuple[float, float]) – Direction to streak the image in, in the image plane frame

  • length (float) – Length of the streak kernel [pix]

Returns:

Convolution kernel

Return type:

np.ndarray

mirage.constants module#

class mirage.constants.AstroConstants#

Bases: object

Collection of astrodynamically-relevant constants

au_to_km: Final[float] = 149600000.0#
deg_to_arcsecond: Final[int] = 3600#
earth_angular_velocity: Final[float] = 7.292115e-05#
earth_f: Final[float] = 0.0033528106647474805#
earth_j2: Final[float] = 0.00108262668#
earth_mass_kg: Final[float] = 5.98e+24#
earth_mu: Final[float] = 398600.4418#
earth_r_eq: Final[float] = 6378.137#
earth_sec_in_day: Final[int] = 86400#
lunar_month_days: Final[float] = 29.530588853#
moon_f: Final[float] = 0.0012#
moon_inertial_angular_velocity: Final[float] = 2.6616995272150692e-06#
moon_mu: Final[float] = 4902.8001224453#
moon_orbit_semimajor_axis: Final[float] = 384400#
moon_r_eq: Final[float] = 1739#
moon_sidereal_period_days: Final[float] = 27.321661#
moon_sidereal_period_sec: Final[float] = 2360591.5104#
moon_solid_angle: Final[float] = 6.418e-05#
moon_synodic_period_days: Final[float] = 29.530588#
moon_synodic_period_sec: Final[float] = 2551442.8032#
planck_constant: Final[float] = 6.62607015e-34#
rad_to_arcsecond: Final[float] = np.float64(206264.80624709636)#
rev_to_arsecond: Final[int] = 1296000#
speed_of_light_vacuum: Final[float] = 299792458.0#
steradian_to_arcsecond2: Final[float] = np.float64(42545170296.15221)#
sun_irradiance_vacuum: Final[float] = 1361#
sun_luminosity: Final[float] = 3.846e+26#
sun_magnitude: Final[float] = -26.832#
sun_mu: Final[float] = 132712440041.27942#
sun_r_eq: Final[float] = 696340.0#
sun_solid_angle: Final[float] = 6.794e-05#
vega_irradiance: Final[float] = 2.518021002e-08#

mirage.constraints module#

class mirage.constraints.ElevationConstraint(min_angle_deg: float)#

Bases: ObserverConstraint

DIFFICULTY = 0#
class mirage.constraints.MoonExclusionConstraint(min_angle_deg: float)#

Bases: ObserverConstraint

DIFFICULTY = 3#
class mirage.constraints.ObserverConstraint#

Bases: object

class mirage.constraints.ObserverEclipseConstraint(station)#

Bases: ObserverConstraint

DIFFICULTY = 2#
class mirage.constraints.SnrConstraint(min_snr: float)#

Bases: ObserverConstraint

DIFFICULTY = 5#
class mirage.constraints.TargetIlluminatedConstraint#

Bases: ObserverConstraint

DIFFICULTY = 2#
class mirage.constraints.VisualMagnitudeConstraint(max_visual_magnitude: float)#

Bases: ObserverConstraint

DIFFICULTY = 1#

mirage.coordinates module#

class mirage.coordinates.EarthFixedFrame(home: str, to: str)#

Bases: object

Handles transformations between various Earth-centered reference frames

get_functions()#

Gets the functions required to transform between the requested frames

rotms_at_dates(dates: datetime | ndarray[datetime, Any]) ndarray#

Transformation matrices from the home frame into the target frame at a given date(s)

Parameters:

dates (Union[datetime.datetime, np.ndarray[datetime.datetime, Any]]) – Date(s) to evaluate [utc]

Returns:

DCM from home frame to target frame

Return type:

np.ndarray [n,3]

vecs_at_dates(dates: datetime | ndarray[datetime, Any], vecs_in_home_frame: ndarray) ndarray#

Transforms vectors in the home frame into the target frame at a given date(s)

Parameters:
  • dates (Union[datetime.datetime, np.ndarray[datetime.datetime, Any]]) – Date(s) to evaluate at [UTC’

  • vecs_in_home_frame (np.ndarray [1x3] or [n,3]) – Single vector (at evaluated at all dates), or a vector for each date - must be in the home frame

Returns:

Transformed vectors in the target frame

Return type:

np.ndarray [1x3] or [n,3]

class mirage.coordinates.FrameInterpolator(frame_from: str, frame_to: str, dates: ndarray, max_surface_error_km: float = 0.001)#

Bases: object

build()#
mirage.coordinates.asc_node_moon(dates: datetime | ndarray[datetime, Any]) ndarray#
mirage.coordinates.az_el_to_enu(az: ndarray, el: ndarray) ndarray#

Converts from azimuth and eleation on the local viewing sphere to East North Up (ENU) vectors

Parameters:
  • az (np.ndarray [n,]) – Azimuth [rad], measured CCW from the East vector

  • el (np.ndarray [n,]) – Elevation [rad], measured from the East-North plane, with positive elevations above the plane

Returns:

ECI unit vectors

Return type:

np.ndarray [n,3]

mirage.coordinates.date_to_et(dates: ndarray[datetime, Any]) ndarray[float]#

Computes J2000 ephemeris time (ET) from a set of UTC dates

Parameters:

dates (np.ndarray[datetime.datetime, Any]) – Date array (UTC)

Returns:

Ephemeris time past J2000 epoch [sec]

Return type:

np.ndarray[float]

mirage.coordinates.date_to_gast(dates: ndarray[datetime, Any] | datetime, scale: str = 'ut1') ndarray#

Computes Greenwich Apparent Sidereal Time (GAST)

Parameters:
  • dates (Union[np.ndarray[datetime.datetime, Any], datetime.datetime]) – Dates [UTC]

  • scale (str, optional) – Time scale to use from [‘utc’, ‘ut1’, ‘tai’, ‘tt’], defaults to ‘ut1’

Returns:

GAST in radians

Return type:

np.ndarray

mirage.coordinates.delta_psi_delta_epsilon(dates: datetime | ndarray[datetime, Any]) Tuple[ndarray, ndarray, ndarray]#

Difference in Earth equator and equinox due to nutation

Parameters:

date (Union[datetime.datetime, np.ndarray[datetime.datetime, Any]]) – Date to evaluate at [utc]

Returns:

\(\Delta \psi\), \(\Delta \varepsilon\), \(\bar{\varepsilon}\) (mean obliquity) for each date

Return type:

Tuple[np.ndarray, np.ndarray, np.ndarray]

mirage.coordinates.ecef_to_enu(enu_origin_in_ecef: ndarray) ndarray#

Rotation matrix from Earth-centered, Earth-fixed (ECEF) coordinates to East, North, Up (ENU) coordinates

Parameters:

enu_origin_in_ecef (np.ndarray [1x3]) – ENU origin point in ECEF coordinates [km]

Returns:

Rotation matrix at that ECEF point

Return type:

np.ndarray [3,3]

mirage.coordinates.eci_to_ra_dec(eci_dir: ndarray) tuple[ndarray, ndarray]#

Converts from an Earth-centered inertial (ECI) direction to inertial right ascension (RA) and declination (Dec)

Parameters:

eci_dir (np.ndarray [n,3]) – Directions of interest in ECI

Returns:

Right ascension [rad] and declination [rad] angles

Return type:

tuple[np.ndarray, np.ndarray]

mirage.coordinates.eci_to_sun_ec(dates: ndarray[datetime, Any]) ndarray#

Rotation matrix from Earth-centered inertial (ECI) to Sun-relative ECI

Parameters:

dates (np.ndarray[datetime.datetime, Any]) – Dates to evaluate at (UTC)

Returns:

Stack of DCMs

Return type:

np.ndarray

mirage.coordinates.enu_to_az_el(r_enu: ndarray) tuple[ndarray, ndarray]#

Converts a vector from topocentric East, North, Up to an azimuth and elevation direction. Azimuth is referenced to North and proceeds clockwise

Parameters:

r_enu (np.ndarray) – _description_

Returns:

_description_

Return type:

tuple[np.ndarray, np.ndarray]

mirage.coordinates.enu_to_ecef(enu_origin_in_ecef: ndarray) ndarray#

Rotation matrix from East, North, Up (ENU) coordinates to Earth-centered, Earth-fixed (ECEF) coordinates

Parameters:

enu_origin_in_ecef (np.ndarray [1x3]) – ENU origin point in ECEF coordinates [km]

Returns:

Rotation matrix at that ECEF point

Return type:

np.ndarray [3,3]

mirage.coordinates.gtod_to_itrf(dates: datetime | ndarray[datetime, Any]) ndarray#

Rotation matrix(s) from Greenwich True of Date (GTOD) to the Internation Terrestrial Reference Frame (ITRF)

Parameters:

dates (Union[datetime.datetime, np.ndarray[datetime.datetime, Any]]) – Date to evaluate at [utc]

Returns:

Rotation matrix

Return type:

np.ndarray [3,3xn] or [3,3]

mirage.coordinates.itrf_to_lla(r_itrf_km: ndarray) Tuple[ndarray, ndarray, ndarray]#

Converts from the International Terrestrial Reference Frame (ITRF) to latitude, longitude, and altitude above the WGS84 ellipsoid

Parameters:

r_itrf_km (np.ndarray [n,3]) – ITRF positions for each LLA triplet [km]

Returns:

Geodetic latitude [rad], longitude [rad], and altitude [km]

Return type:

Tuple[np.ndarray, np.ndarray, np.ndarray] each [n,]

mirage.coordinates.j2000_to_itrf(dates: ndarray[datetime, Any] | datetime) ndarray#

Converts from Earth-centered inertial (ECI) J2000 to Earth-centered, Earth-fixed (ECEF) ITRF coordinates. Accounts for precession, nutation, and polar motion.

Parameters:

dates (Union[datetime.datetime, np.ndarray[datetime.datetime, Any]]) – Date(s), assumed to be UTC

Returns:

Rotation matrix from ECI to ECEF

Return type:

np.ndarray [3,3xn] if more than one date provided, otherwise [3,3]

mirage.coordinates.j2000_to_mod(dates: datetime | ndarray[datetime, Any]) ndarray | float#

Rotation matrix from J2000 to Mean of Date (MOD), accounts for precession

Parameters:

date (Union[datetime.datetime, np.ndarray[datetime.datetime, Any]]) – Date to evaluate at [utc]

Returns:

Rotation matrix or stack of rotation matrices

Return type:

Union[np.ndarray, float] [3,3xn] or [3,3]

mirage.coordinates.jupiter(dates: ndarray[datetime, Any]) ndarray#

Computes the position of Jupiter in equatorial J2000 using SPICE

Parameters:

dates (np.ndarray[datetime.datetime, Any] [n,]) – Array of UTC dates

Returns:

Vector to Jupiter from Earth center [km]

Return type:

np.ndarray [n,3]

mirage.coordinates.mars(dates: ndarray[datetime, Any]) ndarray#

Computes the position of Mars in equatorial J2000 using SPICE

Parameters:

dates (np.ndarray[datetime.datetime, Any] [n,]) – Array of UTC dates

Returns:

Vector to Mars from Earth center [km]

Return type:

np.ndarray [n,3]

mirage.coordinates.mcmf_to_j2000(dates: ndarray[datetime, Any]) ndarray#

Rotation matrix from Moon-Centered-Moon-Fixed (MCMF) to J2000

Parameters:

dates (np.ndarray[datetime.datetime, Any] [n,]) – Date(s) to evaluate at (UTC)

Returns:

Rotation matrices from MCMF to J2000

Return type:

np.ndarray [3,3xn] if n > 1 else [3,3]

mirage.coordinates.mean_obliquity_of_ecliptic(dates: datetime | ndarray[datetime, Any]) Tuple[ndarray | float]#

Inclination of the ecliptic plane relative to the equator [rad]

Parameters:

date (Union[datetime.datetime, np.ndarray[datetime.datetime, Any]]) – Date to evaluate at [UTC]

Returns:

Inclination angle [rad]

Return type:

Union[np.ndarray, float]

>>> date = datetime.datetime(2000, 12, 9, 13, 14, 15, tzinfo=datetime.timezone.utc)
>>> i = mean_obliquity_of_ecliptic(date)
>>> 0.4090906724834187
mirage.coordinates.mercury(dates: ndarray[datetime, Any]) ndarray#

Computes the position of Mercury in equatorial J2000 using SPICE

Parameters:

dates (np.ndarray[datetime.datetime, Any] [n,]) – Array of UTC dates

Returns:

Vector to Mercury from Earth center [km]

Return type:

np.ndarray [n,3]

mirage.coordinates.mod_to_tod(dates: datetime | ndarray[datetime, Any]) ndarray#

Rotation matrix(s) from Mean of Date (MOD) to True of Date (TOD), accounts for nutation

Parameters:

date (Union[datetime.datetime, np.ndarray[datetime.datetime, Any]]) – Date to evaluate at [utc]

Returns:

Rotation matrix

Return type:

np.ndarray [3,3xn] or [3,3]

mirage.coordinates.moon(dates: ndarray[datetime, Any]) ndarray#

Computes the position of the Moon in equatorial J2000 using the JPL NAIF SPICE toolkit

Parameters:

dates (np.ndarray[datetime.datetime, Any] [n,]) – Array of UTC dates

Returns:

Vector to Moon from Earth center [km]

Return type:

np.ndarray [n,3]

mirage.coordinates.neptune(dates: ndarray[datetime, Any]) ndarray#

Computes the position of Neptune in equatorial J2000 using SPICE

Parameters:

dates (np.ndarray[datetime.datetime, Any] [n,]) – Array of UTC dates

Returns:

Vector to Neptune from Earth center [km]

Return type:

np.ndarray [n,3]

mirage.coordinates.pluto(dates: ndarray[datetime, Any]) ndarray#

Computes the position of Pluto in equatorial J2000 using SPICE

Parameters:

dates (np.ndarray[datetime.datetime, Any] [n,]) – Array of UTC dates

Returns:

Vector to Pluto from Earth center [km]

Return type:

np.ndarray [n,3]

mirage.coordinates.ra_dec_to_eci(ra_rad: ndarray, dec_rad: ndarray) ndarray#

Converts from ECI right ascension and declination to an inertial unit vector in the same reference system

Parameters:
  • ra_rad (np.ndarray) – Right ascensions in [rad]

  • dec_rad (np.ndarray) – Declinations in [rad]

Returns:

ECI look directions

Return type:

np.ndarray

mirage.coordinates.saturn(dates: ndarray[datetime, Any]) ndarray#

Computes the position of Saturn in equatorial J2000 using SPICE

Parameters:

dates (np.ndarray[datetime.datetime, Any] [n,]) – Array of UTC dates

Returns:

Vector to Saturn from Earth center [km]

Return type:

np.ndarray [n,3]

mirage.coordinates.sun(dates: ndarray[datetime, Any]) ndarray#

Computes the position of the Sun in equatorial J2000 using the JPL NAIF SPICE toolkit

Parameters:

dates (np.ndarray[datetime.datetime, Any] [n,]) – Array of UTC dates

Returns:

Vector to Sun from Earth center [km]

Return type:

np.ndarray [n,3]

mirage.coordinates.sun_angle_to_horizon(date: ndarray[datetime, Any], r_ecef: ndarray) ndarray#

The angle between the Sun and a set of earth-fixed points at a given date, with positive angles meaning the Sun is above the horizon

Parameters:
  • date (np.ndarray[datetime.datetime, Any]) – UTC datetime to evaluate at

  • r_ecef (np.ndarray [n,3]) – Array of position vectors in ECEF coordinates to test

Returns:

Angle between Sun and horizon [rad]

Return type:

np.ndarray [n,]

mirage.coordinates.sun_ecliptic_longitude(dates: ndarray[datetime, Any]) ndarray#

Longitude of the Sun projected onto the ecliptic plane

Parameters:

dates (np.ndarray[datetime.datetime, Any]) – Dates to evaluate at (UTC)

Returns:

Ecliptic longitude [rad]

Return type:

np.ndarray

mirage.coordinates.sun_irradiance_fraction(dates: ndarray[datetime, Any], r_eci: ndarray) ndarray#

Computes the fraction of the nominal Sun irradiance received at a given ECI position, taking into account the geometry of the solar penumbra

Parameters:
  • dates (np.ndarray[datetime.datetime, Any]) – Dates to evaluate at [UTC]

  • r_eci (np.ndarray [n,3]) – Position of interest in ECI [km]

Returns:

Irradiance fraction at given points: unshadowed -> 1.0, full shadow -> 0.0, semi-shadow lies between

Return type:

np.ndarray [n,]

mirage.coordinates.teme_to_gtod(dates: datetime | ndarray[datetime, Any]) ndarray#

Rotation matrix(s) from True Equator Mean Equinox (TEME) to Greenwich True of Date (GTOD)

Parameters:

dates (Union[datetime.datetime, np.ndarray[datetime.datetime, Any]]) – Date to evaluate at [utc]

Returns:

Rotation matrix(s)

Return type:

np.ndarray [3,3xn] or [3,3]

mirage.coordinates.tod_to_teme(dates: datetime | ndarray[datetime, Any]) ndarray#

Rotation matrix(s) from True of Date (TOD) to True Equator Mean Equinox (TEME)

Parameters:

dates (Union[datetime.datetime, np.ndarray[datetime.datetime, Any]]) – Date to evaluate at [utc]

Returns:

Rotation matrix(s)

Return type:

np.ndarray [3,3xn] or [3,3]

mirage.coordinates.uranus(dates: ndarray[datetime, Any]) ndarray#

Computes the position of Uranus in equatorial J2000 using SPICE

Parameters:

dates (np.ndarray[datetime.datetime, Any] [n,]) – Array of UTC dates

Returns:

Vector to Uranus from Earth center [km]

Return type:

np.ndarray [n,3]

mirage.coordinates.venus(dates: ndarray[datetime, Any]) ndarray#

Computes the position of Venus in equatorial J2000 using SPICE

Parameters:

dates (np.ndarray[datetime.datetime, Any] [n,]) – Array of UTC dates

Returns:

Vector to Venus from Earth center [km]

Return type:

np.ndarray [n,3]

mirage.coordinates.with_spice_kernels(f: Callable)#

mirage.dataio module#

mirage.dataio.download_data(urls_and_dirs: dict) Callable#

Downloads a data file to a given

Parameters:

urls_and_dirs (dict[str, str], optional) – Directories (values) to save to and urls (keys) to download from, defaults to None

Returns:

The decorated function

Return type:

Callable

mirage.dataio.load_json_data(file_name: str) dict[str, ndarray]#

Loads a dictionary of data arrays from the pyspaceaware data directory

Parameters:

file_name (str) – File name to load within os.environ['DATADIR']

Returns:

Dictionary of data arrays loaded from the file

Return type:

dict[str, np.ndarray]

mirage.dataio.purge_user_secrets() None#

Deletes the .env.secret file, which contains user credentials

mirage.dataio.save_file_from_url(url: str, directory: str, extension: str = None)#
mirage.dataio.save_json_data(save_dict: dict[str, ndarray], file_name: str, round_digits: int = 9) None#

Saves a given dictionary of arrays to a JSON file in the pyspaceaware data directory

Parameters:
  • save_dict (dict) – Dictionary to be json-ified

  • file_name (str) – File name to save as within os.environ['DATADIR']

  • round_digits (int, optional) – Number of decimals to round data to, defaults to 9

mirage.dataio.with_earthdata(func: Callable) Callable#

Decorator for functions that require EarthData credentials

Parameters:

func (Callable) – The function being decorated

Returns:

The decorated function

Return type:

Callable

mirage.dataio.with_spacetrack(func: Callable) Callable#

Decorator for functions that require SpaceTrack credentials

Parameters:

func (Callable) – The function being decorated

Returns:

The decorated function

Return type:

Callable

mirage.engine module#

mirage.engine.rgba_to_f32(rgba: ndarray) ndarray#

Interpret an array with the last dimension containing sets of 4 bytes as a single float32 array

Parameters:

rgba – uint32 array with shape (n, m, 4)

Returns:

float32 array with shape (n, m)

mirage.engine.run_light_curve_engine(brdf: Brdf, obj: SpaceObject | str, svb: ndarray, ovb: ndarray, save_imgs: bool = False, output_dir: str | None = None, instances: int = 25, instance_width_pix: int = 360, frame_rate: int = 1000, show_window: bool = False, verbose: bool = False, rotate_panels: bool = False) ndarray#

Runs the LightCurveEngine executable on the input model, observation geometry, and BRDF

Parameters:
  • brdf (Brdf) – BRDF to use

  • obj (Union[str, SpaceObject]) – Loaded SpaceObject or *.obj file name in the os.environ["MODELDIR"] to use

  • svb (np.ndarray [n,3]) – Sun vectors in the object body frame

  • ovb (np.ndarray [n,3]) – Observer vectors in the object body frame

  • save_imgs (bool, optional) – Flag to output rendered images to calling directory/out, defaults to False

  • output_dir (str, optional) – Directory to output images to, defaults to None

  • instances (int, optional, \(1 \leq \texttt{instances} \leq 25\)) – Instances to render at once, leads to roughly linear performance improvement, defaults to 9

  • instance_width_pix (int, optional) – Width of each instance in pixels, defaults to 120

  • frame_rate (int, optional) – Frame rate for the renderer to shoot for, defaults to 1000

  • show_window (bool, optional) – Whether to show the window as frames are rendered, defaults to False

  • verbose (bool, optional) – Whether to print the command string and output of the LightCurveEngine, defaults to False

  • rotate_panels (bool, optional) – Whether to rotate solar panel meshes, if any exist, defaults to False

Returns:

Irradiance at unit distance in given geometries

Return type:

np.ndarray [n,]

mirage.engine.write_light_curve_command_file(svb: array, ovb: array, command_file_name: str) None#

Writes the command file read by the LightCurveEngine executable

Parameters:
  • svb (np.array [n,3]) – Sun vectors in the object body frame

  • ovb (np.array [n,3]) – Observer vectors in the object body frame

  • command_file (str, optional) – Command file name read by LightCurveEngine

mirage.environment module#

mirage.environment.apparent_refacted_elevation(pressure_mbar: ndarray, temp_kelvin: ndarray, el_true_rad: ndarray) ndarray#

Computes the apparent elevation angle of a celestial object, accounting for atmospheric refraction

Parameters:
  • pressure_mbar (np.ndarray) – Atmospheric pressure in millibars

  • temp_kelvin (np.ndarray) – Atmospheric temperature in Kelvin

  • el_true_rad (np.ndarray) – True elevation angle of an exoatmospheric object [rad]

Returns:

Apparent elevation angle of an exoatmospheric object [rad]

Return type:

np.ndarray

mirage.environment.atmospheric_transmission(lambdas: ndarray, zenith_angles: ndarray, altitudes: ndarray = 0.0) ndarray#

Computes atmospheric transmission by interpolating a precomputed dataset

Parameters:
  • lambdas (np.ndarray) – Wavelengths [nm]

  • zenith_angles (np.ndarray) – Zenith angles [rad]

  • altitudes (np.ndarray) – Altitudes of the observer [km]

Returns:

Atmospheric transmissions

Return type:

np.ndarray

mirage.environment.light_time_delay(obs_pos: ndarray, obj_pos: ndarray) ndarray#

Computes the approximate light time for an observation between a station and a space object

Parameters:
  • obs_pos (np.ndarray [n,3]) – Position of the observer

  • obj_pos – Position of the object being observed

Returns:

Light time delay in seconds

Return type:

np.ndarray

mirage.environment.relative_airmass(z_rad: ndarray, approx: bool = False) ndarray#

Computes the cumulative airmass (relative to that at zenith) along a ray leaving the atmosphere, equation from [Pickering02]

Parameters:
  • z_rad (np.ndarray) – Angle from zenith, measured in radians

  • approx (bool, optional) – Whether to approximate with \(\sec\z_{rad}\), defaults to False

Returns:

Airmasses

Return type:

np.ndarray

mirage.environment.total_solar_irradiance_at_dates(dates: ndarray[datetime, Any]) ndarray#

Computes the total irradiance in \(\left[\frac{W}{m^2}\right]\) at the Earth’s instantaneous orbital radius

Parameters:

dates (np.ndarray[datetime.datetime, Any]) – Dates to evaluate at (assumed to be UTC)

Returns:

Irradiance at Earth’s orbital radius \(\left[\frac{W}{m^2}\right]\)

Return type:

np.ndarray

mirage.fits module#

mirage.fits.approximate_background_variance(fits_info: dict) float#
mirage.fits.expected_star_centroids_in_fits(station: Station, catalog: StarCatalog, look_dir_eci: ndarray, up_dir_eci: ndarray, add_distortion: bool = True) ndarray#
mirage.fits.find_stars_in_rotated_image(img: ndarray, rotated_image_raw: ndarray, rotated_image: ndarray, theta_rad: float, total_pix_tracked: float) list[dict]#
mirage.fits.generate_matched_image(info_path: str, img_ind: int, station: Station, catalog: StarCatalog, add_distortion: bool = True, add_refraction: bool = True, noise: bool = False, obj_total_brightness: float = 30000.0)#
mirage.fits.info_from_fits(fits_path: str, telescope: ~mirage.station.Telescope = <mirage.station.Telescope object>, minimal: bool = False) dict#

Loads a FITS file and returns a dictionary of observation information

Parameters:
  • fits_path (str) – Path to the FITS file

  • telescope (Telescope, optional) – The telescope used to take the observation

  • minimal (bool, optional) – If True, time-consuming operations will be skipped

Returns:

Dictionary of observation information

Return type:

dict

mirage.fits.load_obs_data(station, obs_mat_path: str, ind: int) dict#

Loads Nathan’s observation data from a .mat file

Parameters:
  • station (Station) – The station object

  • obs_mat_path (str) – Path to the ObservationData.mat file

  • ind (int) – Index of the observation in the .mat file

Returns:

Dictionary of observation information

Return type:

dict

mirage.fits.load_obs_mat(obs_mat_path: str) dict#

Loads Nathan’s observation data from the processing pipeline

Parameters:

obs_mat_path (str) – Path to the observations.mat file

Returns:

dict of saved data

Return type:

dict

mirage.fits.prepare_fits_for_plotting(img_adu: ndarray, background_method: str = 'parabola') dict#
mirage.fits.solve_star_centroids(fits_info: dict) list[dict]#
mirage.fits.update_refraction(station: Station, look_dir_eci: ndarray, up_dir_eci: ndarray, date: datetime, p_mbar: float, t_k: float) ndarray#

mirage.geodetic module#

mirage.geodetic.geocentric_lat_to_geodetic(lat_geod: ndarray) ndarray#

Converts geocentric latitude to geodetic latitude

Parameters:

lat_geod (np.ndarray) – Geocentric latitudes [rad]

Returns:

Geodetic latitudes [rad]

Return type:

np.ndarray

mirage.geodetic.geodetic_lat_to_geocentric(lat_geod: ndarray) ndarray#

Converts geodetic latitude to geocentric latitude

Parameters:

lat_geod (np.ndarray) – Geodetic latitudes [rad]

Returns:

Geocentric latitudes [rad]

Return type:

np.ndarray

mirage.geodetic.lat_lon_cell_area(lat_lims_rad: tuple[float], lon_lims_rad: tuple[float], radius: float = 40680631590769.0) float#

Area of a rectangular latitude longitude cell with ascending limits from this article

Parameters:
  • lat_lims_rad (tuple[float]) – Ascending latitude limits [rad]

  • lon_lims_rad (tuple[float]) – Ascending longitude limits [rad]

  • radius (float, optional) – The radius of the sphere, defaults to the Earth radius in [m]

Returns:

Area of the cell [radius unit^2]

Return type:

float

mirage.geodetic.radius_at_geodetic_lat(lat_geodetic: ndarray, ellipsoid_height_km: ndarray = 0) ndarray#

Earth’s ellipsoidal radius at the given geodetic latitude, referenced to WGS84 DEPRECATED :param lat_geodetic: Geodetic latitudes [rad] :type lat_geodetic: np.ndarray :param ellipsoid_height_km: Height of points above the ellipsoid [km] :type ellipsoid_height_km: np.ndarray :return: Earth ellipsoidal radius at given latitudes [km] :rtype: np.ndarray

mirage.iod module#

mirage.iod.check_admissibility(station: Station, dates: ndarray[datetime, Any], ras_rad: ndarray, decs_rad: ndarray, ras_dot_rad: ndarray, decs_dot_rad: ndarray, rhos_km: ndarray) ndarray#
mirage.iod.gauss_iod(station: Station, dates: ndarray[datetime, Any], ras_rad: ndarray, decs_rad: ndarray) ndarray#
mirage.iod.gibbs_iod(r_eci_vecs: ndarray) ndarray#
mirage.iod.herrick_gibbs_iod(r_eci_vecs: ndarray, dates: ndarray) ndarray#
mirage.iod.laplace_iod(station: Station, dates: ndarray[datetime, Any], ras_rad: ndarray, decs_rad: ndarray) ndarray#

mirage.lighting module#

class mirage.lighting.Brdf(name: str, cd: float | ndarray | None = None, cs: float | ndarray | None = None, n: float | ndarray | None = None, validate: bool = True)#

Bases: object

compute_reflection_matrix(sun_vectors: array, observer_vectors: array, normal_vectors: array) ndarray#

Computes the reflection matrix for the EGI estimation stage of shape inversion (or for convex shape light curve simulation)

Parameters:
  • sun_vectors (np.array [n,3]) – Unit vector illumination directions

  • observer_vectors (np.array [n,3]) – Unit vector observation directions

  • N (np.array [mx3]) – Unit vector surface normals

Returns:

Reflection matrix, (i,j) entry is normalized irradiance per unit area for facet j at time i

Return type:

np.ndarray [nxm]

eval(L: ndarray, O: ndarray, N: ndarray, cd: float | ndarray = None, cs: float | ndarray = None, n: float | ndarray = None) ndarray#

Evaluates the BRDF with the given observation and illumination geometry

Parameters:
  • L (np.ndarray [n,3]) – Unit vector illumination directions

  • O (np.ndarray [n,3]) – Unit vector observation directions

  • N (np.ndarray [n,3]) – Unit vector surface normals

  • cd (float or np.ndarray, defaults to None) – Coefficients of diffuse reflection, optional

  • cs (float or np.ndarray, defaults to None) – Coefficients of specular reflection, optional

  • n (float or np.ndarray, defaults to None) – Specular exponents, optional

Returns:

Fraction of incident irradiance reflected towards observer

Return type:

np.ndarray [n,]

eval_normalized_brightness(L: ndarray, O: ndarray, N: ndarray, cd: float | ndarray = None, cs: float | ndarray = None, n: float | ndarray = None) ndarray#

Computes the observed irradiance per unit incident irradiance at a unit distance for this BRDF

Parameters:
  • L (np.ndarray [n,3]) – Unit vector illumination directions

  • O (np.ndarray [n,3]) – Unit vector observation directions

  • N (np.ndarray [n,3]) – Unit vector surface normals

  • cd (float or np.ndarray, defaults to None) – Coefficients of diffuse reflection, optional

  • cs (float or np.ndarray, defaults to None) – Coefficients of specular reflection, optional

  • n (float or np.ndarray, defaults to None) – Specular exponents, optional

Returns:

Fraction of incident irradiance reflected towards observer at unit distance

Return type:

np.ndarray [n,]

validate()#

Decides if a BRDF is valid

Raises:

ValueError if energy conservation/other violations are made

mirage.lighting.apparent_magnitude_to_irradiance(m: ndarray) ndarray#

Computes irradiance [W/m^2] from apparent magnitude (assumed same spectrum as sunlight)

Parameters:

m (np.ndarray) – Apparent magnitude

Returns:

Irradiance [W/m^2]

Return type:

np.ndarray

mirage.lighting.brdf_ashikhmin_shirley(L: ndarray, O: ndarray, N: ndarray, cd: ndarray, cs: ndarray, n: ndarray) ndarray#

Bidirectional Reflectance Distribution Function (BRDF) reflectance for the Ashikhmin-Shirley model

Parameters:
  • L (np.ndarray [n,3]) – Unit vector illumination directions

  • O (np.ndarray [n,3]) – Unit vector observation directions

  • N (np.ndarray [n,3]) – Unit vector surface normals

  • cd (np.ndarray [n,]) – Coefficients of diffuse reflection for each face

  • cs (np.ndarray [n,]) – Coefficients of specular reflection for each face

  • n (np.ndarray [n,]) – Specular exponents for each face

Returns:

Fraction of incident light reflected towards observer

Return type:

np.ndarray [n,]

mirage.lighting.brdf_blinn_phong(L: ndarray, O: ndarray, N: ndarray, cd: ndarray, cs: ndarray, n: ndarray) ndarray#

Bidirectional Reflectance Distribution Function (BRDF) reflectance for the Blinn-Phong model

Parameters:
  • L (np.ndarray [n,3]) – Unit vector illumination directions

  • O (np.ndarray [n,3]) – Unit vector observation directions

  • N (np.ndarray [n,3]) – Unit vector surface normals

  • cd (np.ndarray [n,]) – Coefficients of diffuse reflection for each face

  • cs (np.ndarray [n,]) – Coefficients of specular reflection for each face

  • n (np.ndarray [n,]) – Specular exponents for each face

Returns:

Fraction of incident light reflected towards observer

Return type:

np.ndarray [n,]

mirage.lighting.brdf_cook_torrance(L: ndarray, O: ndarray, N: ndarray, cd: ndarray, cs: ndarray, a: float) ndarray#

Bidirectional Reflectance Distribution Function (BRDF) reflectance for the Cook-Torrance model

Parameters:
  • L (np.ndarray [n,3]) – Unit vector illumination directions

  • O (np.ndarray [n,3]) – Unit vector observation directions

  • N (np.ndarray [n,3]) – Unit vector surface normals

  • cd (np.ndarray [n,]) – Coefficients of diffuse reflection for each face

  • cs (np.ndarray [n,]) – Coefficients of specular reflection for each face

  • a (np.ndarray [n,]) – Surface roughness \(a \in [0,1]\)

Returns:

Fraction of incident light reflected towards observer

Return type:

np.ndarray [n,]

mirage.lighting.brdf_diffuse(cd: ndarray) ndarray#

Bidirectional Reflectance Distribution Function (BRDF) reflectance for a diffuse surface

Parameters:

cd (np.ndarray) – Coefficients of diffuse reflection for each face

Returns:

Fraction of incident light reflected towards observer

Return type:

np.ndarray

mirage.lighting.brdf_glossy(L: ndarray, O: ndarray, N: ndarray, cs: ndarray, s: ndarray, **_) ndarray#

Bidirectional Reflectance Distribution Function (BRDF) reflectance for the glossy model

Parameters:
  • L (np.ndarray [n,3]) – Unit vector illumination directions

  • O (np.ndarray [n,3]) – Unit vector observation directions

  • N (np.ndarray [n,3]) – Unit vector surface normals

  • cs (np.ndarray [n,]) – Coefficients of specular reflection for each face

  • s (float) – Variance of BRDF Gaussian

Returns:

Fraction of incident light reflected towards observer

Return type:

np.ndarray [n,]

mirage.lighting.brdf_oren_naymar(L: ndarray, O: ndarray, N: ndarray, cd: ndarray, s: float, **_) ndarray#

Bidirectional Reflectance Distribution Function (BRDF) reflectance for the Oren-Nayar model

Parameters:
  • L (np.ndarray [n,3]) – Unit vector illumination directions

  • O (np.ndarray [n,3]) – Unit vector observation directions

  • N (np.ndarray [n,3]) – Unit vector surface normals

  • cd (np.ndarray [n,]) – Coefficients of diffuse reflection for each face

  • s (float) – Variance of BRDF Gaussian

Returns:

Fraction of incident light reflected towards observer

Return type:

np.ndarray [n,]

mirage.lighting.brdf_phong(L: ndarray, O: ndarray, N: ndarray, cd: ndarray, cs: ndarray, n: ndarray) ndarray#

Bidirectional Reflectance Distribution Function (BRDF) reflectance for the Phong model

Parameters:
  • L (np.ndarray [n,3]) – Unit vector illumination directions

  • O (np.ndarray [n,3]) – Unit vector observation directions

  • N (np.ndarray [n,3]) – Unit vector surface normals

  • cd (np.ndarray [n,]) – Coefficients of diffuse reflection for each face

  • cs (np.ndarray [n,]) – Coefficients of specular reflection for each face

  • n (np.ndarray [n,]) – Specular exponents for each face

Returns:

Fraction of incident light reflected towards observer

Return type:

np.ndarray [n,]

mirage.lighting.candela_to_watt_per_sr(cd: ndarray, lambdas: ndarray | float = 555.0) ndarray#

Converts from candela (cd) to watts per steradian (W/sr)

Parameters:
  • cd (np.ndarray) – Candela value(s)

  • lambdas (Union[np.ndarray, float], optional) – Wavelength [nm] of monochromatic source, defaults to 555

Returns:

Watts per square meter

Return type:

np.ndarray

mirage.lighting.cook_torrance_beckmann(H: ndarray, N: ndarray, a: float) ndarray#
mirage.lighting.cook_torrance_fresnel_schlick(H: ndarray, L: ndarray, cs: float) ndarray#
mirage.lighting.cook_torrance_g_smith(O: ndarray, N: ndarray, L: ndarray, a: ndarray) ndarray#
mirage.lighting.cook_torrance_ggx(M: ndarray, N: ndarray, a: float) ndarray#

Calculates the GGX normal distribution function

Parameters:
  • M (np.ndarray [n,3]) – Microfacet surface normal direction

  • N (np.ndarray [n,3]) – Macro surface normal

  • a (float) – Surface roughness

Returns:

Normal distribution density

Return type:

np.ndarray

mirage.lighting.irradiance_to_apparent_magnitude(E: ndarray, zero_point_irradiance: float = 2.518021002e-08) ndarray#

Computes apparent magnitude from irradiance [W/m^2] (assumed same spectrum as sunlight)

Parameters:
  • E (np.ndarray) – Irradiance [W/m^2]

  • zero_point_irradiance (float, optional) – Irradiance at the zero point, defaults to AstroConstants.vega_irradiance

Returns:

Apparent magnitude

Return type:

np.ndarray

mirage.lighting.irradiance_to_s10(e: ndarray, w: ndarray) ndarray#

Converts irradiance \(\frac{W}{m^2}\) spread over a solid angle into surface brightness \(S_{10}\). \(S_{10}\) is defined as the number of 10th magnitude stars per square degree

Parameters:
  • e (np.ndarray) – Total irradiance [W/m^2]

  • w (np.ndarray) – Solid angle of the source in [rad^2]

Returns:

Surface brightness in \(S_{10}\)

Return type:

np.ndarray

mirage.lighting.mcd_m2_to_watt_m2_sr(mcd_per_m2: ndarray) ndarray#

Converts from milli-candela per square meter to watts per square meter per steradian

Parameters:

mcd_per_m2 (np.ndarray) – Milli-candela per square meter value(s)

Returns:

Watts per square meter per steradian value(s)

Return type:

np.ndarray

mirage.lighting.mcd_per_m2_to_mpsas(mcd_per_m2: ndarray, lam_nm: float = 473.74960958) ndarray#

Converts milli-candela per square meter to MPSAS

Parameters:

mcd_per_m2 (np.ndarray) – Milli-candela per square meter (artificial sky brightness)

Returns:

Magnitudes per square arcsecond (MPSAS)

Return type:

np.ndarray

mirage.lighting.mpsas_to_irradiance_per_steradian(mpsas: ndarray) ndarray#

Converts surface brightness in magnitudes per arcsecond squared to irradiance per steradian

Parameters:

mpsas (np.ndarray) – Surface brightness in magnitudes per arcsecond squared

Returns:

Irradiance per steradian [W/m^2/sr]

Return type:

np.ndarray

mirage.lighting.mpsas_to_mcd_per_m2(mag_per_arcsec2: ndarray, lam_nm: float = 473.74960958) ndarray#

Converts MPSAS to milli-candela per square meter

Parameters:

mag_per_arcsec2 (np.ndarray) – Magnitudes per square arcsecond (MPSAS)

Returns:

Equivalent milli-candela per square meter

Return type:

np.ndarray

mirage.lighting.normalized_light_curve_sphere(cd_sphere: float, r_sphere_m: float, phase_angle_rad: ndarray) ndarray#

Computes a normalized light curve (irradiance at one meter from the object) for a diffuse sphere

Parameters:
  • cd_sphere (float) – Coefficient of diffuse reflection

  • r_sphere_m (float) – Radius of the sphere in [m]

  • phase_angle_rad (np.ndarray) – Angle between the object-Sun and object-Observer vectors [rad]

Returns:

Normalized light curve

Return type:

np.ndarray

mirage.lighting.query_brdf_shader_ind(brdf: Brdf) int#

Figures out if a Brdf is known to the LightCurveEngine shaders, and if it is, returns its registry index

Parameters:

brdf (Brdf) – BRDF to check

Returns:

Index of BRDF as known by the shaders

Return type:

int

mirage.lighting.reflect(from_dir: ndarray, normal_dir: ndarray) ndarray#
mirage.lighting.s10_to_irradiance(b: ndarray, w: ndarray) ndarray#

Converts surface brightness \(S_{10}\) over a solid angle into irradiance \(\frac{W}{m^2}\). \(S_{10}\) is defined as the number of 10th magnitude stars per square degree

Parameters:
  • b (np.ndarray) – Surface brightness in \(S_{10}\)

  • w (np.ndarray) – Solid angle of the source in [rad^2]

Returns:

Total irradiance [W/m^2]

Return type:

np.ndarray

mirage.lighting.watt_per_sr_to_candela(watt_per_sr: ndarray, lambdas: ndarray = 555.0) ndarray#

Converts from watts per steradian (w/sr) to candela (cd)

Parameters:
  • cd (np.ndarray) – Watts per square meter

  • lambdas (np.ndarray, optional) – Wavelength [nm] of monochromatic source, defaults to 555 [nm]

Returns:

Candela value(s)

Return type:

np.ndarray

mirage.math module#

mirage.math.acosd(x: ndarray | float | int) ndarray | float#

Computes \(\cos^{-1}(x)\) outputting in degrees

Parameters:

x (Union[np.ndarray, float, int]) – Input

Returns:

\(\cos^{-1}(x)\) in [deg]

Return type:

Union[np.ndarray, float]

mirage.math.adjoint(arr: ndarray) ndarray#

Computes the classical adjoint of a square matrix, equivalent to the MATLAB method of the same name.

Parameters:

arr (np.ndarray [n,n]) – Square matrix to compute adjoint of

Returns:

Adjoint of input matrix

Return type:

np.ndarray [n,n]

mirage.math.angle_between_deg(a1: ndarray, a2: ndarray) ndarray#

Given two angular quantities, finds smallest angle between their unit circle vectors, ex: f(50, 40) -> 10, f(-30, 20) = 50

Parameters:
  • a1 (np.ndarray) – First angle [deg]

  • a2 (np.ndarray) – Second angle [deg]

Returns:

Smallest angle difference [deg]

Return type:

np.ndarray

mirage.math.angle_between_rad(a1: ndarray, a2: ndarray) ndarray#

Given two angular quantities, finds smallest angle between their unit circle vectors, see angle_between_deg

Parameters:
  • a1 (np.ndarray) – First angle [rad]

  • a2 (np.ndarray) – Second angle [rad]

Returns:

Smallest angle difference [rad]

Return type:

np.ndarray

mirage.math.angle_between_vecs(v1: ndarray, v2: ndarray) ndarray#

Computes the angle between two vectors in radians, expands one out to fit the other if sizes do not match

Parameters:
  • v1 (np.ndarray [n,3] or [1x3] if v2 is [n,3]) – First vector

  • v2 (np.ndarray [n,3] or [1x3] if v1 is [n,3]) – Second vector

Returns:

Angle between the pairs of vectors [rad]

Return type:

np.ndarray

mirage.math.asind(x: ndarray | float | int) ndarray | float#

Computes \(\sin^{-1}(x)\) outputting in degrees

Parameters:

x (Union[np.ndarray, float, int]) – Input

Returns:

\(\sin^{-1}(x)\) in [deg]

Return type:

Union[np.ndarray, float]

mirage.math.atan2d(y: ndarray, x: ndarray) ndarray | float#

Four quadrant inverse tangent \(\tan^{-1}(y/x)\) outputting in degrees

Parameters:

x (np.ndarray) – Input [deg]

Returns:

\(\tan^{-1}(y/x)\) [deg]

Return type:

Union[np.ndarray, float]

mirage.math.atand(x: ndarray | float | int) ndarray | float#

Computes \(\tan^{-1}(x)\) outputting in degrees

Parameters:

x (Union[np.ndarray, float, int]) – Input

Returns:

\(\tan^{-1}(x)\) [deg]

Return type:

Union[np.ndarray, float]

mirage.math.cart_to_sph(x: ndarray, y: ndarray, z: ndarray) Tuple[ndarray, ndarray, ndarray]#

Converts from Cartesian (x,y,z) to spherical (azimuth, elevation, range)

Parameters:
  • x (np.ndarray) – Cartesian x

  • y (np.ndarray) – Cartesian y

  • z (np.ndarray) – Cartesian z

Returns:

(azimuth, elevation, range) angles in [rad]

Return type:

Tuple[np.ndarray, np.ndarray, np.ndarray]

mirage.math.close_egi(egi: ndarray) ndarray#

Enforces closure condition by adding mean closure error to each row [RF22]

Parameters:

egi (np.ndarray [n,3]) – Extended Gaussian Image (EGI)

Returns:

Shifted EGI such that the sum of rows is zero

Return type:

np.ndarray [n,3]

mirage.math.cosd(x: ndarray | float | int) ndarray | float#

Computes \(\cos(x)\) with \(x\) in degrees

Parameters:

x (Union[np.ndarray, float, int]) – Input [deg]

Returns:

\(\cos(x)\)

Return type:

Union[np.ndarray, float]

mirage.math.dms_to_rad(deg: ndarray | float | int, min: ndarray | float | int, sec: ndarray | float | int) ndarray | float | int#

Converts from degrees, arcminutes, and arcseconds to radians

Parameters:
  • deg (Union[np.ndarray, float, int]) – Degrees

  • min (Union[np.ndarray, float, int]) – Arcminutes

  • sec (Union[np.ndarray, float, int]) – Arcseconds

Returns:

Radians

Return type:

Union[np.ndarray, float, int]

mirage.math.dot(v1: ndarray, v2: ndarray) ndarray#

Euclidean dot product between corresponding rows of v1 and v2

Parameters:
  • v1 (np.ndarray [nxm]) – First input vector

  • v2 (np.ndarray [nxm]) – Second input vector

Returns:

Dot products of corresponding rows

Return type:

np.ndarray [n,]

mirage.math.elliptic_pi_complete(n: ndarray, ksquared: ndarray) ndarray#

Computes the complete elliptic integral of the third kind based on Carlson symmetric forms \(R_f, R_j\)

Parameters:
  • n (np.ndarray [mx1]) – \(n\) parameter of the integral

  • ksquared (np.ndarray [mx1]) – \(k^2\) parameter of the integral

Returns:

\(\pi(n, \phi, k^2)\)

Return type:

np.ndarray [mx1]

mirage.math.elliptic_pi_incomplete(n: ndarray, phi: ndarray, ksquared: ndarray) ndarray#

Computes the incomplete elliptic integral of the third kind based on Carlson symmetric forms \(R_f, R_j\)

Parameters:
  • n (np.ndarray [n,]) – \(n\) parameter of the integral

  • phi (np.ndarray [n,]) – \(\phi\)

  • ksquared (np.ndarray [n,]) – \(k^2\) parameter of the integral

Returns:

\(\Pi(n, \phi, k^2)\)

Return type:

np.ndarray [n,]

mirage.math.fit_2d_gaussian(data: ndarray, mahal_dist_tol: float = 3.0, max_iter: int = 100, return_used_inds: bool = False)#
mirage.math.fit_poisson_process(data: ndarray) float#

Fits a Poisson random process to the given data

Parameters:

data (np.ndarray) – Independent, identically distributed data to fit

Returns:

The optimal Poisson rate parameter \(\lambda\)

Return type:

float

mirage.math.hat(v: ndarray) ndarray#

Normalizes input np.ndarray n,3 such that each row is unit length. If a row is [0,0,0], hat() returns it unchanged

Parameters:

v (np.ndarray [n,3]) – Input vectors

Returns:

Unit vectors

Return type:

np.ndarray [n,3]

mirage.math.hms_to_rad(hour: ndarray, min: ndarray, sec: ndarray) ndarray#

Converts from hours, arcminutes, and arcseconds to radians out of a 24 hour day

Parameters:
  • deg (np.ndarray) – Hours

  • min (np.ndarray) – Minutes

  • sec (np.ndarray) – Seconds

Returns:

Radians

Return type:

np.ndarray

mirage.math.least_squares_line_intersection(p1: ndarray, p2: ndarray) ndarray#

Least-squares intersection of \(n\) lines in \(m\)-dimensional space

Parameters:
  • p1 (np.ndarray [n, m]) – The first point on each line

  • p2 (np.ndarray [n, m]) – The second point on each line

Returns:

The intersection point [1, m]

Source: https://stackoverflow.com/questions/52088966/nearest-intersection-point-to-many-lines-in-python

mirage.math.look_at_matrix(eye: ndarray, target: ndarray, up: ndarray) ndarray#

Look matrix for a camera placed at eye, looking at target, with up vector up. Transforms from world frame coordinates to camera frame coordinates. Source

Parameters:
  • eye (np.ndarray [1x3]) – Location of camera origin in world coordinates

  • target (np.ndarray [1x3]) – Location of camera target in world coordinates

  • up (np.ndarray [1x3]) – Up vector constraining the vertical camera axis

Returns:

Look matrix \(V\) such that \(V[x \: 1]^T\) transforms the vector \(x\) into camera coordinates \(\frac{V[x \: 1]_{1:3}^T}{V[x \: 1]_{4}^T}\)

Return type:

np.ndarray [4x4]

mirage.math.mahal(pts: ndarray, mu: ndarray, cov: ndarray) ndarray#

Computes the Mahalanobis distance from a set of points to a Gaussian distribution defined by its mean and covariance

Parameters:
  • pts (np.ndarray [nxm]) – Points to test

  • mu (np.ndarray [1xm]) – Mean of the distribution

  • cov (np.ndarray [mxm]) – Covariance matrix of the distribution

Returns:

Mahalanobis distances

Return type:

np.ndarray [n,]

mirage.math.matching_indices(x: ndarray, y: ndarray) Tuple[ndarray, ndarray]#

Returns the indices into x and indices into y that match, x should be sorted for speed

Parameters:
  • x (np.ndarray) – Array 1, usually the much larger array (sorted if possible)

  • y (np.ndarray) – Array 2, smaller

Returns:

Indices a such that x[a[0]] == y[a[1]]

Return type:

Tuple[np.ndarray, np.ndarray]

mirage.math.merge_clusters(v: ndarray, atol: float, miter: int = 3) ndarray#

Merges clusters of vectors in \(R^3\) within an angle tolerance by addition

Parameters:
  • v (np.ndarray [n,3]) – Array of row vectors to merge

  • atol (float) – Angle between vectors to merge by [rad]

  • miter (int, optional) – Merge iterations, defaults to 3

Returns:

Merged vectors

Return type:

np.ndarray [mx3], m <= n

mirage.math.multithreaded_gaussian(mu: ndarray, sigma: ndarray, seed: int = None, threads: int = 4) ndarray#
mirage.math.multithreaded_poisson(lam: ndarray, seed: int = None, threads: int = 8) ndarray#

Multithreaded Poisson random variable number generation

Parameters:
  • lam (np.ndarray) – Means (and equivalently variances) of the Poisson distributions to sample

  • seed (int, optional) – Seed value for the PRNG, defaults to None

  • threads (int, optional) – Number of threads to use, defaults to None

Returns:

Sampled values, uint32

Return type:

np.ndarray

mirage.math.perspective_projection_matrix(fov_deg: float, aspect: float, near: float, far: float) ndarray#

Transforms from camera coordinates to image plane coordinates for a perspective camera

Parameters:
  • fov_deg (float) – Field of view [deg]

  • aspect (float) – Aspect ratio of camera: the ratio of the horizontal to vertical fields of view

  • near (float) – Near plane distance from camera origin, avoid going much below 0.01 to avoid numerical issues at 0

  • far (float) – Far plane distance from camera origin

Returns:

Projection matrix \(P\) such that \(P[x \: 1]^T\) transforms the vector \(x\) into image coordinates \(\frac{P[x \: 1]_{1:3}^T}{P[x \: 1]_{4}^T}\)

Return type:

np.ndarray [4x4]

mirage.math.points_to_planes_dist(pt: ndarray, plane_n: ndarray, support: ndarray) ndarray#

Computes the signed distance from a set of points to a set of planes

Parameters:
  • pt (np.ndarray [n,3]) – Array of points in R^3

  • plane_n (np.ndarray [n,3]) – Normal vectors of planes

  • support (np.ndarray [n,]) – Distance from each plane to the origin

Returns:

Distance from points to planes

Return type:

np.ndarray [n,]

mirage.math.r3_grid(grid_half_width: float, grid_side_count: int)#
mirage.math.rad_to_dms(x: ndarray) tuple[ndarray, ndarray, ndarray]#

Converts radians to degrees, minutes, seconds

Parameters:

x (np.ndarray) – Array or float in radians

Returns:

degrees, minutes, seconds

Return type:

tuple[np.ndarray, np.ndarray, np.ndarray]

mirage.math.rad_to_hms(x: ndarray) tuple[ndarray, ndarray, ndarray]#

Converts radians to hours, minutes, seconds

Parameters:

x (np.ndarray) – Radians, either float or array

Returns:

Hours, minutes, seconds

Return type:

tuple[np.ndarray, np.ndarray, np.ndarray]

mirage.math.rdot(v1: ndarray, v2: ndarray, eps: float = 0.0) ndarray#

Rectified dot product, where 0 if dot(v1,v2) < 0 else dot(v1,v2)

Parameters:
  • v1 (np.ndarray [nxm]) – First input vector

  • v2 (np.ndarray [nxm]) – Second input vector

  • eps (float, optional) – Cutoff where dot products of v1 and v2 less than eps return zero

Returns:

Positive dot product of v1 rows with v2` rows

Return type:

np.ndarray [n,]

mirage.math.remove_zero_rows(v: ndarray) ndarray#

Removes all rows from the 2D array v that have a norm of zero

Parameters:

v (np.ndarray [nxm]) – Array to operate on

Returns:

Copy of v with zero rows removed

Return type:

np.ndarray [n-k x m]

mirage.math.rk4(f: Callable, tspace: ndarray, y0: ndarray) ndarray#
mirage.math.rotate_points_about_point(points: ndarray, angle: float, center: ndarray) ndarray#

Rotates points in 2D about a center point

Parameters:
  • points (np.ndarray) – The points to rotate

  • angle (float) – The angle to rotate by [rad]

  • center (np.ndarray) – The center of rotation

Returns:

The rotated points

Return type:

np.ndarray

mirage.math.rv_to_daz_del(r: ndarray, v: ndarray) tuple[ndarray, ndarray]#

Converts sets of position and velocity vectors to azimuth and elevation time derivatives (position and velocity must be expressed in the same units)

Parameters:
  • r (np.ndarray) – Position [nx3]

  • v (np.ndarray) – Velocity [nx3], any units as long as they match position

Returns:

Azimuth and elevation time derivatives

Return type:

tuple[np.ndarray, np.ndarray]

mirage.math.sind(x: ndarray | float | int) ndarray | float#

Computes \(\sin(x)\) with \(x\) in degrees

Parameters:

x (Union[np.ndarray, float, int]) – Input [deg]

Returns:

\(\sin(x)\)

Return type:

Union[np.ndarray, float]

mirage.math.sph_to_cart(az: ndarray, el: ndarray, r: ndarray | None = None) Tuple[ndarray, ndarray, ndarray]#

Converts from spherical (azimuth, elevation, range) to Cartesian (x, y, z)

Parameters:
  • az (np.ndarray) – Azimuth [rad]

  • el (np.ndarray) – Elevation [rad]

  • r (np.ndarray, defaults to None) – Range, if not provided assumed to be 1

Returns:

Cartesian (x, y, z)

Return type:

Tuple[np.ndarray, np.ndarray, np.ndarray]

mirage.math.spherical_voronoi_weighting(ref_points: ndarray, ref_weights: ndarray, query_points: ndarray) ndarray#

Given a set of reference points and weights, returns the nearest reference weight value at the query point locations

Parameters:
  • ref_points (np.ndarray [n,3]) – Reference points on \(\mathbb{S}^2\)

  • ref_weights (np.ndarray [n,]) – Weights associated with each reference point

  • query_points (np.ndarray [n,3]) – Query points elsewhere on \(\mathbb{S}^2\)

Returns:

Query weights, computed through a nearest neighbor query of the Voronoi diagram of the reference points

Return type:

np.ndarray [n,]

mirage.math.spherical_voronoi_weighting_az_el(ref_points: ndarray, ref_weights: ndarray, query_az: ndarray, query_el) ndarray#

Given a set of reference points and weights, returns the nearest reference weight value at the query point locations

Parameters:
  • ref_points (np.ndarray [n,3]) – Reference points on \(\mathbb{S}^2\)

  • ref_weights (np.ndarray [n,]) – Weights associated with each reference point

  • query_az (np.ndarray [n,]) – Query point azimuths [rad]

  • query_el (np.ndarray [n,]) – Query point elevations [rad]

Returns:

Query weights, computed through a nearest neighbor query of the Voronoi diagram of the reference points

Return type:

np.ndarray [n,]

mirage.math.stack_mat_mult_mat(*matrices: Tuple[ndarray] | ndarray) ndarray#

Multiplies each matrix in the next, page-wise

Parameters:

matrices (Union[Tuple[np.ndarray], np.ndarray], each must be [mxmxn]) – Matrix stacks to multiply together

Returns:

Multiplied product obeying result[:,:,i] = np.matmul(*mats[:,:,i])

Return type:

np.ndarray [mxmxn]

mirage.math.stack_mat_mult_vec(mats: ndarray, v: ndarray) ndarray#

Multiplies each row in v by each page of mats

Parameters:
  • mats (np.ndarray [mxmxn]) – Matrices to multiply by

  • v (np.ndarray [nxm]) – Vectors to be multiplied

Returns:

Multiplied product obeying result[i, :] = mats[:,:,i] @ v[[i], :].T

Return type:

np.ndarray [nxm]

mirage.math.tand(x: ndarray | float | int) ndarray | float#

Computes \(\tan(x)\) with \(x\) in degrees

Parameters:

x (Union[np.ndarray, float, int]) – Input [deg]

Returns:

\(\tan(x)\)

Return type:

Union[np.ndarray, float]

mirage.math.tilde(v: ndarray) ndarray#

Matrix cross product operator such that \(v \times x = \left[\tilde{v}\right]x\)

Parameters:

v (np.ndarray [n,3]) – Vector to operate on

Returns:

Cross product matrices

Return type:

np.ndarray [3,3xn]

mirage.math.udot(v1: ndarray, v2: ndarray) ndarray#

Unit dot product, clips the result of the dot product to [-1,1]

Parameters:
  • v1 (np.ndarray [nxm]) – First input vector

  • v2 (np.ndarray [nxm]) – Second input vector

Returns:

Dot product of v1 with v2, clipped to [-1,1]

Return type:

np.ndarray [n,]

mirage.math.unique_rows(v: ndarray, decimals: int = 6, **kwargs) ndarray#

Extracts unique rows from the input 2D array

Parameters:
  • v (np.ndarray [nxm]) – Input vector

  • decimals (int) – Number of decimals to compare when determining uniqueness, defaults to 6

  • **kwargs – Additional arguments to pass to np.unique

Returns:

Unique rows of v

Return type:

np.ndarray [n-k x m], \(k \geq 0\)

mirage.math.vecnorm(v: ndarray) ndarray#

Takes the \(L_2\) norm of the rows of v

Parameters:

v (np.ndarray [nxm]) – Input vector

Returns:

Norm of each row

Return type:

np.ndarray [n,]

mirage.math.wrap_to_180(lon: ndarray) ndarray#

Wraps angular quantities to their remainder on [-180, 180]

Parameters:

lon (np.ndarray) – Angle to wrap [deg]

Returns:

Wrapped angle [deg]

Return type:

np.ndarray

mirage.math.wrap_to_360(lon: ndarray) ndarray#

Wraps angular quantities to their remainder on [0, 360]

Parameters:

lon (np.ndarray) – Angle to wrap [deg]

Returns:

Wrapped angle [deg]

Return type:

np.ndarray

mirage.math.wrap_to_pi(lon: ndarray) ndarray#

Wraps angular quantities to their remainder on [-pi, pi]

Parameters:

lon (np.ndarray) – Angle to wrap [rad]

Returns:

Wrapped angle [rad]

Return type:

np.ndarray

mirage.math.wrap_to_two_pi(lon: ndarray) ndarray#

Wraps angular quantities to their remainder on [0, 2pi]

Parameters:

lon (np.ndarray) – Angle to wrap [rad]

Returns:

Wrapped angle [rad]

Return type:

np.ndarray

mirage.modelio module#

mirage.modelio.download_listing()#

Downloads a listing of all models available on the model archive

mirage.modelio.download_model_file(model_file: str)#

Downloads a model file (.obj) from the light curve models repository

Parameters:

model_file (str) – Model file name (not path) ending in .obj

mirage.modelio.get_model_path(model_name: str) str#

Gets the path in the remote model repository to a given model

Parameters:

model_name (str) – Model name like cube.obj

Returns:

The path of the remote model

Return type:

str

mirage.modelio.local_models() list[str]#

Returns a list of the models in the current model storage directory

mirage.modelio.online_models() list[str]#

Returns a list of the models in the remote model repository

mirage.orbit module#

mirage.orbit.coe_to_rv(coe: ndarray, mu: float = 398600.4418) ndarray#

Converts classical orbital elements to a state vector defined in the same frame.

Parameters:
  • coe (np.ndarray [nx6]) – Classical orbital elements in the form [a, e, i, Omega, omega, nu]

  • mu (float, optional) – Gravitational parameter of the central body, defaults to AstroConstants.earth_mu

Returns:

State vector in the form [r, v]

Return type:

np.ndarray [nx6]

mirage.orbit.get_catalog_satrecs(date: datetime) Tuple[SatrecArray, list, list]#

Gets the nearest catalog with cacheing. This function will be much faster if the date is rounded to the nearest hour or day

Parameters:

date (datetime.datetime) – Date (UTC) to query satrecs for

Returns:

sgp4.SatrecArray, satnums, and satellite names

Return type:

Tuple[SatrecArray, list]

mirage.orbit.integrate_orbit_and_attitude(r0: ~numpy.ndarray, v0: ~numpy.ndarray, q0: ~numpy.ndarray, w0: ~numpy.ndarray, itensor: ~numpy.ndarray, teval: ~numpy.ndarray, orbit_perturbations: ~typing.Callable = <function <lambda>>, external_torque: ~typing.Callable = <function <lambda>>, internal_torque: ~typing.Callable = <function <lambda>>, int_tol: float = 1e-13) ndarray#
mirage.orbit.integrate_orbit_dynamics(rv0: ndarray, dates: ndarray[datetime, Any], gravity_harmonics_degree: int = 16, third_bodies: list[str] | None = None, int_tol: float = 1e-13) ndarray#

Integration for orbital dynamics with perturbations

Parameters:

rv0 (np.ndarray [1x6]) – Initial position and velocity state in Earth-centered inertial coordinates

Returns:

Integrated orbit state in ECI in position [km] and velocity [km/s]

Return type:

np.ndarray [nx6]

mirage.orbit.j2_acceleration(rvec: ndarray) ndarray#

Acceleration due to the J2 perturbation (Earth oblateness)

Parameters:

rvec (np.ndarray [n,3]) – Position vector of the satellite [km]

Returns:

Acceleration due to J2 [km/s^2]

Return type:

np.ndarray [n,3]

mirage.orbit.moon_acceleration(date: datetime, rv: ndarray) ndarray#

3rd body acceleration due to the Moon

Parameters:
  • date – UTC date to evaluate at

  • rv (np.ndarray [n,3]) – Position and velocity state in Earth-centered inertial coordinates

Returns:

Acceleration due to the sun [m/s^2]

Return type:

np.ndarray [n,3]

mirage.orbit.propagate_catalog_to_dates(dates: ndarray[datetime] | datetime, rmag_limit: float = 100000.0, return_satnums: bool = False, return_names: bool = False) ndarray#

Propgates a satellite catalog to an array of dates, output in J2000 ECI [km]

Parameters:
  • dates (Union[np.ndarray[datetime.datetime], datetime.datetime]) – Array of datetimes [UTC]

  • rmag_limit (float, optional) – Remove all propagated positions with magnitudes greater than, defaults to 1e5

  • return_satnums (bool, optional) – Whether to return satnums with the positions, defaults to False

  • return_names (bool, optional) – Whether to return names with the positions, defaults to False

Returns:

Position [km] and velocity [km/s] in J2000

Return type:

Tuple[np.ndarray [n,3], np.ndarray [n,3]], optional names as 3rd tuple entry [n,]

mirage.orbit.propagate_satnum_to_dates(dates: datetime, satnum: int, target_frame: str = 'teme') ndarray#

Propagates a satellite number to the given UTC datetimes

Parameters:
  • dates (datetime.datetime [n,]) – Array of datetimes [UTC]

  • satnum (int) – NORAD satellite number

  • target_frame (str, optional) – Reference frame to propagate in, defaults to “teme”

Returns:

Position [km] in the target reference frame

Return type:

np.ndarray [n,3]

mirage.orbit.rv_to_coe(rv: ndarray, mu: float = 398600.4418) ndarray#

Converts a state vector to classical orbital elements defined in the same frame.

Parameters:
  • rv (np.ndarray [nx6]) – State vector in the form [r, v]

  • mu (float, optional) – Gravitational parameter of the central body, defaults to AstroConstants.earth_mu

Returns:

Classical orbital elements in the form [a, e, i, Omega, omega, nu]

Return type:

np.ndarray

mirage.orbit.third_body_acceleration(epsecs: ndarray, rv: ndarray, interpolator: SpiceInterpolator) ndarray#

3rd body acceleration on a satellite due to a solar system body

Parameters:
  • epsecs (np.ndarray) – Epoch seconds to evaluate at after the initial epoch

  • rv (np.ndarray [n,3]) – Position and velocity state in Earth-centered inertial coordinates

  • interpolator (SpiceInterpolator) – SpiceInterpolator object for the body

Returns:

Acceleration due to the sun [m/s^2]

Return type:

np.ndarray [n,3]

mirage.orbit.tle_propagate_with_switching(satnum_or_tles: int | ndarray[str, str], dates: ndarray[datetime, Any], switch_strategy: str = 'interp', pad_time: timedelta = datetime.timedelta(days=2), frame: str = 'j2000', return_velocity: bool = False) ndarray#

Propagates a satellite with SGP4 over a set of datetimes with a switching strategy

Parameters:
  • satnum (int) – NORAD SAT ID, ex. 25544 for ISS (ZARYA) OR array of TLE strings [n,2]

  • dates (np.ndarray[datetime.datetime, Any]) – Datetimes to propagate to

  • switch_strategy (str, optional) – Switching strategy, either ‘interp’, ‘closest’, and ‘nearest’, defaults to ‘interp’ (which tends to have the lowest error)

  • pad_time (datetime.timedelta, optional) – Time to grab TLEs before and after the range of the input dates, defaults to days(1)

  • frame (str, optional) – Output frame, any of ‘j2000’, ‘teme’, ‘tod’, ‘mod’, ‘itrf’, defaults to ‘j2000’

  • return_velocity (bool, optional) – Whether to output velocity too, defaults to False

Returns:

Position of the satellite at the datetimes

Return type:

np.ndarray [n,3]

mirage.orbit.two_body_dynamics(rv: ndarray) ndarray#

Relative two-body dynamics for orbits

Parameters:

rv (np.ndarray [6,]) – Position [:3] [km] and velocity [3:] [km/s] of the satellite

Returns:

Time derivative of position and velocity states

Return type:

np.ndarray [6,]

mirage.profiling module#

mirage.profiling.get_profiling_results() dict#

Returns the results of the mirage profiler.

Returns:

The results dictionary of the mirage profiler.

Return type:

dict

mirage.profiling.print_profiling_results() None#

Prints the results of the mirage profiler.

mirage.profiling.profile_script(script_path: str) None#

Runs the mirage profiler on a Python script file.

Parameters:

script_path (str) – Path to the Python script to be profiled.

Raises:
  • FileNotFoundError – If the script file is not found.

  • Exception – If an error occurs while executing the script.

mirage.profiling.set_profile_dt_threshold(threshold: float) None#

Sets the threshold for the mirage profiler.

Parameters:

threshold (float) – The threshold in seconds.

mirage.profiling.tic(msg: str | None = None)#

Starts a timer, ended by toc()

Parameters:

msg (str, optional) – Message to come before the elapsed time statement, defaults to None

Raises:

Exception – If there is already an active tic

mirage.profiling.toc(return_elapsed_seconds: bool = False) None | float#

Ends the timer began by the most recent tic(), returns the elapsed time

Parameters:

return_elapsed_seconds (bool, optional) – Whether to return the time as well as printing it, defaults to False

Raises:

Exception – If there’s no active tic() timer running with the given message

Returns:

The elapsed time in seconds, if requested

Return type:

Union[None, float]

mirage.profiling.with_profiler(func: Callable)#

mirage.sampling module#

mirage.sampling.closest_fibonacci_index(p: ndarray, n: int) int#

Finds the index of the Fibonacci sphere sampling closest to the given point following [Keinert et al. 2015]

Parameters:
  • p (np.ndarray [1x3]) – Point to find the closest neighbor of

  • n (int) – Number of points in the Fibonacci point set

Returns:

Index of the closest point

Return type:

int

mirage.sampling.fibonacci_sample_sphere(num: int) ndarray#

Computes a point set of num points of the form described by Marques et al. in 2013

Parameters:

num (int) – Number of vectors to sample

Returns:

Sampled unit vectors

Return type:

np.ndarray [n,3]

mirage.sampling.quaternion_fibonacci_sample(n: int) ndarray#

Samples the hypersphere with a fibonacci spiral

Parameters:

n (int) – Number of quaternions to return

Returns:

Sampled unit quaternions

Return type:

np.ndarray

mirage.sampling.rand_cone_vectors(cone_axis: ndarray, cone_half_angle: float, num: int) ndarray#

Generates uniform random unit vectors in a cone

Parameters:
  • cone_axis (np.ndarray [1x3]) – Axis of symmetry for the cone

  • cone_half_angle (float) – Half-angle of the cone [rad]

  • num (int) – Number of vectors to sample

Returns:

Sampled unit vectors

Return type:

np.ndarray [n,3]

mirage.sampling.rand_points_in_ball(r: float | ndarray, num: int) ndarray#

Samples random points in a solid ball

Parameters:
  • r (Union[float, np.ndarray]) – Radius of the ball, or one unique radius per sample

  • num (int) – Number to sample

Raises:

ValueError – If the number of provided radii is not 1 or equal to num

Returns:

Sampled points

Return type:

np.ndarray [n,3]

mirage.sampling.rand_points_in_cube(num: int, origin: tuple = (0.0, 0.0, 0.0), scale: tuple = (1.0, 1.0, 1.0)) ndarray#

Samples random points in a cube

Parameters:
  • num (int) – Number to sample

  • origin (tuple, optional) – Origin of the cube, defaults to (0., 0., 0.)

  • scale (tuple, optional) – Scale of the cube, defaults to (1., 1., 1.)

Returns:

Sampled points

Return type:

np.ndarray [n,3]

mirage.sampling.rand_points_in_shell(r_lims: Tuple[float, float], num: int) ndarray#

Samples a random point in a solid spherical shell defined by r_lims

Parameters:
  • r_lims (Tuple[float, float]) – Minimum and maximum shell radii

  • num (int) – Number of points to sample

Returns:

Sampled points

Return type:

np.ndarray [n,3]

mirage.sampling.rand_unit_vectors(num: int) ndarray#

Generates uniform random vectors on the unit sphere \(S^2\)

Parameters:

num (int) – Number of unit vectors to generate

Returns:

Sampled unit vectors

Return type:

np.ndarray [n,3]

mirage.sampling.spiral_sample_sphere(num: int) ndarray#

Generates relatively uniform samples on the unit sphere via Fibonacci sampling

Parameters:

num (int) – Number of vectors to sample

Returns:

Sampled unit vectors

Return type:

np.ndarray [n,3]

mirage.sdf module#

class mirage.sdf.SDF(vertices: ndarray, faces: ndarray)#

Bases: object

gradient(r_query: ndarray, h: float = 0.0001) ndarray#
normal_az_el_at_point(r_query: ndarray) tuple[ndarray, ndarray]#
query_grid(grid_half_width: float, grid_density: int, flatten: bool = False) ndarray#
query_points(query_pts: ndarray) ndarray#
class mirage.sdf.SphericalWeight(ref_pts: ndarray, ref_weights: ndarray)#

Bases: object

query_az_el(az: ndarray, el: ndarray, method: str = 'nearest') ndarray#
query_points(query_pts: ndarray, method: str = 'nearest') ndarray#

mirage.solarsystem module#

class mirage.solarsystem.SpiceInterpolator(body_name: str, dates: ndarray, atol: float = 1e-05)#

Bases: object

build()#

mirage.spaceobject module#

class mirage.spaceobject.SpaceObject(model_file: str | None = None, vertices_and_faces: Tuple[ndarray, ndarray] | None = None, is_dual: bool = False, identifier: int | str | None = None, enforce_convex_normals: bool = False)#

Bases: object

build_properties()#

Builds all relevant object properties for shape inversion or visualization

build_pyvista_mesh()#
clean()#
compute_center_of_mass() ndarray#

Computes the center of mass for this triangle mesh

compute_face_areas()#

Computes the area of each face

compute_face_centroids()#

Computes the centroids of each face by averaging vertices

compute_face_normals()#

Computes the normals of each face

compute_inertia_tensor()#

Computes the body-frame inertia tensor of the object, from (MatlabCentral)

compute_supports(trunc_limit: float = 1e-07)#

Computes the support (perpendicular distance from plane containing face to origin)

compute_volume()#

Computes the volume via the supports and unique areas

convex_light_curve(brdf: Brdf, svb: ndarray, ovb: ndarray) ndarray#

Computes the light curve of a covex object with a given BRDF Fan [Fan20]

Parameters:
  • brdf (Brdf) – BRDF to render with

  • svb (np.ndarray [n,]) – Sun unit vectors in the body frame

  • ovb (np.ndarray [n,]) – Observer unit vectors in the body frame

Returns:

Observed irradiance at unit distance

Return type:

np.ndarray [n,]

property dual#
flip_normals()#

For convex objects, flips any normal vectors pointing inside the object

get_dual()#

Sets the dual object

get_egi()#

Computes the Extended Gaussian Image (EGI)

get_face_vertices() Tuple[ndarray]#

Reshapes face vertices into tuple of all 1st vertices, 2nd vertices, 3rd vertices

get_inner_vertices()#

Computes which vertices are within the convex hull (not contained in any faces of the convex hull)

get_sdf()#
introduce_concavity(displacement_direction: ndarray, internal_angle_deg: float, normal_selection_tolerance=0.8707963267948966, linear_iter: int = 5, loop_iter: int = 0)#
is_convex(volume_tol: float = 0.001) bool#

Determines whether the object is convex

Parameters:

volume_tol (float, optional) – Tolerance for the difference in the volume of the object and its convex hull, which is ideally zero if the object is truly convex, defaults to 1e-3

Returns:

True of the object is convex

Return type:

bool

property principal_itensor#
propagate(dates: ndarray[datetime, Any], return_velocity: bool = False)#
rotate_by_quat(quat: ndarray) None#

Rotates the object’s mesh by the given quaternion

Parameters:

quat (np.ndarray [1x4]) – Quaternion to apply to all vertices

shift_to_center_of_mass() None#

Shifts the object’s vertices to the center of mass

subdivide(linear_iter: int = 1, loop_iter: int = 1)#
unique_areas_and_normals()#

Finds groups of unique normals and areas to save rows elsewhere

vertices_on_each_face()#

Computes a np.ndarray [3,3,n] of vertices on each face

mirage.spaceobject.build_dual(normals: ndarray, supports: ndarray) SpaceObject#

Computes the polyhedral dual of the set of normals and supports

Parameters:
  • normals (np.ndarray [n,3]) – Outward-facing normal vectors

  • supports (np.ndarray [n,]) – Support of each face (see get_supports())

Returns:

Dual object defined by the normals and supports

Return type:

SpaceObject

mirage.spaceobject.construct_from_egi_and_supports(egi: ndarray, support: ndarray) SpaceObject#

Constructs an object from an input Extended Gaussian Image (EGI) and support set

Parameters:
  • egi (np.ndarray [n,3]) – EGI of the object

  • support (np.ndarray [n,]) – Supports of each face in the EGI

Returns:

Resulting convex object, with potentially fewer faces than the original EGI depending on supports selected

Return type:

SpaceObject

mirage.spaceobject.construct_mesh_from_egi(egi: ndarray, implementation: str = 'fortran') ndarray#
mirage.spaceobject.delete_all_models()#

Removes all model files (.obj, .mtl) from the current model directory as well as the model listing file (.json)

mirage.spaceobject.faces_and_vertices_from_egi(egi: ndarray) tuple[ndarray, ndarray]#
mirage.spaceobject.get_volume(h: ndarray, egi: ndarray) float#

Computes the volume of the polytope represented by the supports and EGI input

Parameters:
  • h (np.ndarray [n,]) – Support vector

  • egi (np.ndarray [n,3]) – Extended Gaussian image to reconstruct from

Returns:

Volume of the reconstructed convex polytope

Return type:

float

mirage.spaceobject.intersects_obj(origin: ndarray, stop: ndarray, obj: SpaceObject) ndarray[bool]#

Computes whether a set of rays intersect an object

Parameters:
  • origin (np.ndarray [n,3]) – Ray origin points in world space

  • stop (np.ndarray [n,3]) – Ray stop points in world space

  • obj (SpaceObject) – Object to trace rays against

Returns:

Whether each ray intersects the object before reaching its stop point

Return type:

np.ndarray[bool] [n,]

mirage.spaceobject.little_fun(h: ndarray, egi: ndarray) float#

Little’s objective function for support vector optimization Little [Lit83]

Parameters:
  • h (np.ndarray [n,]) – Supports vector

  • egi (np.ndarray [n,3]) – Extended Gaussian image to reconstruct from

Returns:

Objective function value \(f=(h \cdot a)\)

Return type:

float

mirage.spaceobject.load_mtllib(mtllib_path: str) dict#

Loads a .mtl file

Parameters:

mtllib_path (str) – Path to the .mtl file

Returns:

Dictionary of materials arranged by material name

Return type:

dict

mirage.spaceobject.load_obj(obj_path: str, n_default: float = 10.0, **obj_kwargs) SpaceObject#

Loads a .obj file and its material properties

Parameters:
  • obj_path (str) – Path to the .obj file

  • n_default (float, optional) – Default specular exponent value, defaults to 10.0

Returns:

Loaded object

Return type:

SpaceObject

mirage.spaceobject.merge_shapes(objs: Iterable[SpaceObject], weighting_fcns: ndarray | Iterable[Callable], grid_density: int = 100) SpaceObject#

Merges any number of SpaceObjects using a weighted average of their signed distance fields

Parameters:
  • objs (Iterable[mr.SpaceObject]) – Set of objects to merge

  • weighting_fcns (Union[np.ndarray, Iterable[Callable]]) – Weights to use for each object, either an array of floats or callables of the form (az: np.ndarray, el: np.ndarray) -> np.ndarray [0,1]

  • grid_density (int, optional) – Grid density to use for the signed distance field, defaults to 100

Returns:

Merged object

Return type:

mr.SpaceObject

mirage.spaceobject.optimize_egi(lc: ndarray, svb: ndarray, ovb: ndarray, brdf: Brdf, num_candidates: int = 1000, merge_iter: int = 1, merge_angle: float = 0.3141592653589793, return_all: bool = False, weights: ndarray | None = None) ndarray#

Optimizes an Extended Gaussian Image (EGI) to fit observed irradiances [RF22]

Parameters:
  • lc (np.ndarray [n,]) – Unit irradiance light curve

  • svb (np.ndarray [n,3]) – Sun unit vectors in the body frame for each observation

  • ovb (np.ndarray [n,3]) – Observer unit vectors in the body frame

  • brdf (Brdf) – BRDF to use

  • num_candidates (int, optional) – Number of candidate normal vectors to fit, defaults to int(1e3)

  • merge_iter (int, optional) – Number of iterations for the merging step, defaults to 1

  • merge_angle (float, optional) – Angle between vectors to merge by, defaults to np.pi/10

  • return_all (bool, optional) – Whether to return the initial and merged EGIs, defaults to False

  • weights (np.ndarray, optional) – Weights for each observation, defaults to None

Returns:

Optimized EGI

Return type:

np.ndarray

mirage.spaceobject.optimize_supports_little(egi: ndarray) ndarray#

Optimizes a support vector to construct the polytope with the given Extended Gaussian Image (EGI) Little [Lit83]

Parameters:

egi (np.ndarray [n,3]) – EGI to find supports for, convergence only possible if the sum of rows is zero. See close_egi()

Returns:

Optimal set of supports

Return type:

np.ndarray [n,]

mirage.spaceobject.set_model_directory(path: str) None#

Sets the 3D model path used by all tools and methods

Parameters:

path (str) – Absolute or relative (from cwd) path to the model folder

mirage.spaceobject.spaceobject_from_pyvista_mesh(mesh)#

mirage.stars module#

class mirage.stars.GaiaSpectralStarCatalog(station, date: datetime = None, aberration: bool = False)#

Bases: StarCatalog

load()#
class mirage.stars.GaiaStarCatalog(station, date: datetime = None, aberration: bool = False)#

Bases: StarCatalog

load(**kwargs) Callable#
class mirage.stars.StarCatalog#

Bases: object

account_for_aberration()#
build_tree()#
in_fov(eci_look_dir: ndarray, scope_up: ndarray, method: Literal['brute', 'tree'] = 'tree', return_inds: bool = False) tuple[ndarray, ndarray]#

Finds stars in the field of view of a telescope

Parameters:
  • eci_look_dir (np.ndarray) – The look direction of the telescope in ECI coordinates

  • scope_up (np.ndarray) – The up direction of the telescope in ECI coordinates (orthogonal to the look direction, defining the vertical axis of the image)

  • method (Literal["brute", "tree"], optional) – The method to use for finding stars in the field of view, defaults to “tree”

  • return_inds (bool, optional) – Whether to return the in-frame indices as an additional output, defaults to False

Returns:

The unit vectors and associated values of the stars in the field of view

Return type:

tuple[np.ndarray, np.ndarray]

load_tree_lazy()#

Loads the star catalog from a file

save_tree_lazy()#

Saves the star catalog to a file

class mirage.stars.Tycho2StarCatalog(station, date: datetime = None, aberration: bool = False)#

Bases: StarCatalog

load(**kwargs) Callable#
mirage.stars.adjust_spectrum_to_mag_in_band(lambdas: ndarray, spec: ndarray, mag: ndarray | float, band_name: str) ndarray#

Adjusts a spectrum so that it has a given apparent magnitude in a passband

Parameters:
  • lambdas (np.ndarray [mx1]) – Wavelengths [nm]

  • spec (np.ndarray [mx1]) – Input spectrum, i.e. the spectrum of the Sun. Units do not matter as long as they are linear

  • mag (Union[np.ndarray [n,], float]) – Magnitude(s) to adjust the spectrum to

  • band_name (str) – Name of the band to use, ex. ‘G’

Returns:

The adjusted spectra

Return type:

np.ndarray [nxm]

mirage.stars.apparent_magnitude_in_band(lambdas: ndarray, fluxes: ndarray, band: str | ndarray | None = None) float#

Computes the apparent magnitude of a flux spectrum passed through a band

Parameters:
  • lambdas (np.ndarray) – Wavelengths [nm]

  • fluxes (np.ndarray) – Fluxes [W / m^2 / nm]

  • band (Union[str, np.ndarray, None], optional) – Passband name, or array of fraction of light at each wavelength that is transmitted, defaults to None

Returns:

Apparent magnitude using the Vega zero point

Return type:

np.ndarray

mirage.stars.apparent_star_positons(dates: ndarray[datetime, Any], obs_lat_geod_rad: float, alpha_rad: ndarray, delta_rad: ndarray) tuple[ndarray, ndarray]#

The apparent positions of stars from an observer’s point of view at a given set of dates

Parameters:
  • dates (np.ndarray[datetime.datetime, Any]) – Dates to evaluate at (UTC)

  • obs_lat_geod_rad (float) – Geodetic latitude of the observer [rad]

  • alpha_rad (np.ndarray) – Right ascension at the reference epoch [rad]

  • delta_rad (np.ndarray) – Declinations at the reference epoch [rad]

Returns:

Apparent right ascensions and declinations

Return type:

tuple[np.ndarray, np.ndarray]

mirage.stars.irradiance_in_band(lambdas: ndarray, fluxes: ndarray, band: str | ndarray | None = None) float#

Computes the irradiance of a flux spectrum passed through a band

Parameters:
  • lambdas (np.ndarray) – Wavelengths [nm]

  • fluxes (np.ndarray) – Fluxes [W / m^2 / nm]

  • band (Union[str, np.ndarray, None]) – Passband name, or array of fraction of light at each wavelength that is transmitted. If None, no band will be applied

Returns:

Integrated irradiance

Return type:

np.ndarray

mirage.stars.unit_vector_inds_in_fov(telescope, eci_look_dir: ndarray, scope_up: ndarray, uvs: ndarray) ndarray#

mirage.station module#

class mirage.station.ObservationCache#

Bases: object

class mirage.station.Station(**kwargs)#

Bases: object

az_el_to_eci(az_rad: ndarray, el_rad: ndarray, dates: ndarray[datetime, Any] | datetime, end_frame: str = 'j2000') ndarray#

Takes local azimuth and elevation angles to an ECI unit vector from the perspective of the station

Parameters:
  • az_rad (np.ndarray) – Azimuth angles, measured in the positive sense from North proceeding East [rad]

  • el_rad (np.ndarray) – Elevation angles, measured from the North East plane proceeding Up

  • date (Union[np.ndarray[datetime.datetime, Any], datetime.datetime]) – Date(s) to evaluate at (UTC)

  • end_frame (str, optional) – Frame to express the ECI unit vector in, defaults to “j2000”

Returns:

ECI unit vector

Return type:

np.ndarray [n,3] or [3,]

eci_to_az_el(dates: ndarray[datetime, Any], r_eci_hat: ndarray) tuple[ndarray, ndarray]#

Converts an ECI unit vector to local azimuth and elevation angles in radians

Parameters:
  • dates (np.ndarray[datetime.datetime, Any]) – Dates to convert at (UTC)

  • r_eci_hat (np.ndarray) – Positions of target in ECI [km]

Returns:

Azimuth and elevation angles [rad]

Return type:

tuple[np.ndarray, np.ndarray]

eci_to_enu(dates: ndarray[datetime, Any] | datetime) ndarray#

Rotation matrix(s) from an ECI look direction to topocentric East-North-Up

Parameters:

dates (Union[np.ndarray[datetime.datetime, Any], datetime.datetime]) – Dates to evaluate at (UTC)

Returns:

Stack of rotation matrices

Return type:

np.ndarray [3,3xn] or [3,3]

eval_constraints(evaluate_all: bool = False, **kwargs) ndarray[bool] | tuple[ndarray[bool], ndarray[bool]]#

Evaluates station observations constraints at a set of times and inertial look directions

Parameters:

evaluate_all (bool, optional) – Whether to evaluate constraints in the provided order to output individual satisfaction, defaults to False. Setting to True will reduce performance significantly

Returns:

Whether all constraints are met at each time, and whether each constraint is met at each time (if evaluate_all=True)

Return type:

Union[np.ndarray[bool], tuple[np.ndarray[bool], np.ndarray[bool]]]

j2000_at_dates(dates: ndarray[datetime, Any] | datetime, return_velocity: bool = False) ndarray | Tuple[ndarray, ndarray]#

J2000 position of the station at a given set of dates

Parameters:
  • dates (Union[np.ndarray[datetime.datetime, Any], datetime.datetime]) – Date(s) in UTC

  • return_velocity (bool, optional) – Whether to return J2000 velocity vectors too, defaults to False

Returns:

J2000 positions of the station

Return type:

Union[np.ndarray, Tuple[np.ndarray, np.ndarray]], each ndarray is [n,3] or [3,]

lc_snr(dates: ndarray[datetime, Any], lc: ndarray, z_obs: ndarray, sat_to_station_inertial: ndarray, integration_time_s: float, return_intermediate: bool = False)#
object_line_of_sight(obj: SpaceObject, dates: ndarray[datetime], apparent: bool = True, frame: str = 'j2000') ndarray#

Computes unit vector lines of sight from the station to a space object

Parameters:
  • obj (SpaceObject) – Space object to observe

  • dates (np.ndarray[datetime.datetime, Any]) – Dates to evaluate at (UTC)

  • apparent (bool, optional) – Whether to compute the apparent line of sight (accounting for atmospheric refraction and light travel time), defaults to True

Returns:

Line of sight vectors from the station to the object

Return type:

np.ndarray [n,3]

observe_light_curve(obj: SpaceObject, obj_attitude: RbtfAttitude, brdf: Brdf, dates: ndarray[datetime, Any], integration_time_s: float, model_scale_factor: float = 1.0, use_engine: bool = False, **engine_kwargs) Tuple[Callable, dict[str, ndarray]]#

Observes a light curve with noise, returning results in ADU

Parameters:
  • obj (SpaceObject) – Space object to simulate, must have the identifier attribute set for SGP4 propagation

  • obj_attitude (RbtfAttitude) – Attitude profile for the space object

  • brdf (Brdf) – Bidirectional Reflectance Distribution Function for the object

  • dates (np.ndarray[datetime.datetime, Any]) – UTC dates to observe at

  • model_scale_factor (float, optional) – Scale factor for the object, on top of its model file scale, defaults to 1.0

  • use_engine (bool, optional) – Whether to use the LightCurveEngine for the simulation, defaults to False

  • **engine_kwargs (dict, optional) – Additional keyword arguments to pass to the LightCurveEngine

Returns:

Anonymous function for sampling light curves [ADU}], dictionary of relevant simulation time series

Return type:

Tuple[Callable, dict[str, np.ndarray]]

ra_dec_to_az_el(ras: ndarray, decs: ndarray, dates: ndarray[datetime, Any]) Tuple[ndarray, ndarray]#

Converts from inertial right ascension (RA) and declination (Dec) to local azimuth and elevation, with azimuth referenced to North and increasing clockwise

Parameters:
  • ras (np.ndarray) – Right ascensions [rad]

  • decs (np.ndarray) – Declinations [rad]

  • dates (np.ndarray[datetime.datetime, Any]) – Dates to evaluate at (UTC)

Returns:

Azimuth [rad] and elevation [rad]

Return type:

Tuple[np.ndarray, np.ndarray]

scintillation_noise_std(theta_z: ndarray, integration_time_s: float, H: float = 8000.0, method: str = 'young', factor_of_safety: float = 1.5) ndarray#
sky_brightness(dates: ndarray[datetime, Any], look_dir_eci: ndarray, integration_time_s: float, is_ground_based: bool = True, airglow: bool = True, integrated_starlight: bool = True, moonlight: bool = True, zodiac: bool = True, pollution: bool = True, twilight: bool = True) ndarray#

Computes the mean background signal due to various sources [ADU/pix]

Parameters:
  • dates (np.ndarray[datetime.datetime, Any] [n,]) – Dates to evaluate at (UTC)

  • look_dir_eci (np.ndarray [n,3]) – Look directions in ECI

  • is_ground_based (bool, optional) – Whether the observer observing from below the atmosphere, defaults to True

  • airglow (bool, optional) – Whether to include the airglow signal, defaults to True

  • integrated_starlight (bool, optional) – Whether to include the signal due to faint background stars, defaults to True

  • moonlight (bool, optional) – Whether to include Mie and Rayleigh scattered moonlight, defaults to True

  • zodiac (bool, optional) – Whether to include zodiac light, defaults to True

  • pollution (bool, optional) – Whether to take into account light pollution at the observer location, defaults to True

  • twilight (bool, optional) – Whether to include the background signal due to twilight, defaults to True

Returns:

Background signal mean at each date [e-/pix]

Return type:

np.ndarray

class mirage.station.Telescope(preset: Literal['pogs', 'zimlat', 'zimmain'] = 'pogs')#

Bases: object

airy_disk_fwhm(lambdas: ndarray) ndarray#

The full width at half maximum of a Gaussian approximation of an Airy disk at given wavelengths

Parameters:

lambdas (np.ndarray) – Wavelengths [nm]

Returns:

FWHM of the Airy disk at each wavelength [rad]

Return type:

np.ndarray

airy_disk_pattern(total_object_signal: float, theta_rad: ndarray, lambdas: float) ndarray#

Airy disk pattern for far-field diffraction

Parameters:
  • total_object_signal (float) – Total signal of the object [e-]

  • theta_rad (np.ndarray) – Angles from the center of the Airy disk [rad]

  • lambdas (float) – Wavelengths of incoming light [nm]

Returns:

Intensity of the Airy disk at each angle

Return type:

np.ndarray

body_to_j2000(look_dir_eci: ndarray, up_dir_eci: ndarray) ndarray#
gaussian_diffraction_pattern(total_object_signal: float, theta_rad: ndarray) ndarray#

Gaussian approximation of an Airy disk pattern for far-field diffraction

Parameters:
  • total_object_signal (float) – Total signal of the object [e-]

  • theta_rad (np.ndarray) – Angles from the center of the Airy disk [rad]

Returns:

Intensity of the Airy disk at each angle

Return type:

np.ndarray

gaussian_diffraction_pattern_grid(total_signal: float, n_pix: float) ndarray#

Generates a square grid of pixels with the telescope’s Gaussian diffraction pattern

Parameters:
  • total_signal (float) – Total signal to distribute across the grid

  • n_pix (float) – Number of pixels in the grid

Returns:

The diffraction pattern grid

Return type:

np.ndarray

get_airy_disk_amplitude(s_obj: ndarray) float#

Gets the signal amplitude of an object’s unresolved object signal as a 2D Gaussian

Parameters:

s_obj (float) – Total signal of the object on the CCD [e-]

Returns:

Amplitude of the Gaussian [e-]

Return type:

float

get_airy_disk_pixels(lambdas: float = 550) float#

Approximates the number of pixels contained in an object’s unresolved Airy disk

Returns:

Pixel area covered by the Airy disk [pix]

Return type:

float

j2000_unit_vectors_to_pixels(look_dir_eci: ndarray, up_dir_eci: ndarray, uvs: ndarray, add_distortion: bool = False) tuple[ndarray, ndarray]#

Converts a set of unit vectors in J2000 ECI coordinates to image plane pixel coordinates

Parameters:
  • look_dir_eci (np.ndarray [1x3]) – Look directions in ECI

  • up_dir_eci (np.ndarray [1x3]) – Up direction of the camera frame in ECI

  • uvs (np.ndarray) – Unit vectors in ECI

  • add_distortion (bool, optional) – Whether to apply pixel distortion, defaults to False

Returns:

Pixel coordinates in the x and y directions, on [0, sensor_pixels] in both axes with [sensor_pixels//2, sensor_pixels//2] at the center of the image

Return type:

tuple[np.ndarray, np.ndarray]

pixel_distortion(pix_x: ndarray, pix_y: ndarray, center_x: float, center_y: float, undo: bool = True) Tuple[ndarray, ndarray]#

Applies or undoes pixel distortion for a given center.

Parameters:
  • pix_x (np.ndarray) – X pixel locations [pix], referenced to (0, 0) in the top-left corner

  • pix_y (np.ndarray) – Y pixel locations [pix], referenced to (0, 0) in the top-left corner

  • center_x (float) – X location of the center of the optical axis [pix], referenced to (0, 0) in the top-left corner

  • center_y (float) – Y location of the center of the optical axis [pix], referenced to (0, 0) in the top-left corner

  • undo (bool, optional) – Whether to undo or simply apply the distortion effect, defaults to True (undoing distortion)

Returns:

Apparent pixel locations in the x and y directions

Return type:

Tuple[np.ndarray, np.ndarray]

pixels_to_j2000_unit_vectors(look_dir_eci: ndarray, up_dir_eci: ndarray, xy: ndarray, input_is_distorted: bool = False) ndarray#

Converts a set of pixel coordinates to unit vectors in J2000 ECI coordinates

Parameters:
  • look_dir_eci (np.ndarray [1x3]) – Look directions in ECI

  • up_dir_eci (np.ndarray [1x3]) – Up direction of the camera frame in ECI

  • xy (np.ndarray [nx2]) – Pixel coordinates in the x and y directions, on [0, sensor_pixels] in both axes with [sensor_pixels//2, sensor_pixels//2] at the center of the image

  • input_is_distorted (bool, optional) – Whether the input pixel coordinates are distorted, defaults to False

Returns:

Unit vectors in ECI

Return type:

np.ndarray [n,3]

tracked_pixels_from_rates(ra_rate_arcsec_s: float, dec_rate_arcsec_s: float, dec_look_rad: float, integration_time_s: float) float#

The number of pixels tracked over the integration time

Parameters:
  • ra_rate_arcsec_s (float) – Right ascension tracking rate in arcseconds per second

  • dec_rate_arcsec_s (float) – Declination tracking rate in arcseconds per second

  • dec_look_rad (float) – The declination of the object being observed in radians

  • integration_time_s (float) – Integration time in seconds

Returns:

The number of pixels tracked over the integration time

Return type:

float

unit_airy_disk_volume(wavelength: float) float#

Computes the volume of the Airy disk at a specific wavelength

Parameters:

wavelength (float) – Wavelength [nm]

Returns:

Volume of airy disk

Return type:

float

up_direction_eci(look_dirs_eci: ndarray) ndarray#

The up direction in ECI for a set of look directions (the direction normal to the image plane, pointing “up” in the image)

Parameters:

look_dirs_eci (np.ndarray) – Look directions in ECI

Returns:

Direction of the “Up” side of the image in ECI

Return type:

np.ndarray

vectors_inertial_to_body(look_dir_eci: ndarray, up_dir_eci: ndarray, uv_eci: ndarray) ndarray#

mirage.time module#

mirage.time.beginning_of_day(dates: ndarray[datetime, Any]) ndarray[datetime, Any]#

Finds the beginning of the day for given datetime array

Parameters:

dates (np.ndarray[datetime.datetime, Any] [n,]) – Date array (UTC)

Returns:

Beginning of day for each date (UTC)

Return type:

np.ndarray[datetime.datetime, Any] [n,]

mirage.time.date_arange(date_start: datetime, date_stop: datetime, date_step: timedelta, return_epsecs: bool = False) Tuple[ndarray[datetime, Any], ndarray[float64]]#

Computes a range of datetime objects spaced by the same step

Parameters:
  • date_start (datetime.datetime) – Date to start at (UTC)

  • date_stop (datetime.datetime) – Date to stop at (UTC)

  • date_step (datetime.timedelta) – Step between elements, ex. date_step=datetime.timedelta(hours=3) or mr.seconds(2)

  • return_epsecs (bool, optional) – Whether to also return the EpochSecond space, defaults to False

Returns:

Sampled space of datetimes (UTC) and possibly also space of epoch seconds

Return type:

Tuple[np.ndarray[datetime.datetime, Any], np.ndarray[np.float64]]

mirage.time.date_linspace(date_start: datetime, date_stop: datetime, num: int, return_epsecs: bool = False) Tuple[ndarray[datetime, Any], ndarray[float64]]#

Computes a linspace of datetime objects

Parameters:
  • date_start (datetime.datetime) – Date to start at (UTC)

  • date_stop (datetime.datetime) – Date to stop at (UTC)

  • num (int) – Number of samples to make

  • return_epsecs (bool, optional) – Whether to also return the EpochSecond space, defaults to False

Returns:

Sampled linspace of datetimes (UTC) and possibly a linspace of epoch seconds

Return type:

Tuple[np.ndarray[datetime.datetime, Any], np.ndarray[np.float64]]

mirage.time.date_to_epsec(dates: ndarray[datetime, Any]) ndarray#

Converts date objects to an array of seconds after the initial date epoch (the first element of the dates array)

Parameters:

dates (np.ndarray[datetime.datetime, Any]) – Dates (UTC)

Returns:

Epoch seconds

Return type:

np.ndarray

mirage.time.date_to_gmst(dates: ndarray[datetime, Any] | datetime, use_astropy: bool = False, scale: str = 'ut1') ndarray#

Computes Greenwich Mean Sidereal Time (GMST)

Parameters:
  • dates (Union[np.ndarray[datetime.datetime, Any], datetime.datetime]) – Dates [UTC]

  • use_astropy (bool, optional) – Whether to use astropy for the backend calculations, defaults to False

  • scale (str, optional) – Time scale to use from [‘utc’, ‘ut1’, ‘tai’, ‘tt’], defaults to ‘ut1’

Returns:

GMST in radians

Return type:

np.ndarray

mirage.time.date_to_jd(dates: ndarray[datetime, Any], use_astropy: bool = True, scale: str = 'utc') ndarray#

Converts datetime to Julian date

Parameters:
  • dates (np.ndarray[datetime.datetime, Any]) – Date objects to compute the Julian date (UTC)

  • scale (str, optional) – Time scale to use from [‘utc’, ‘ut1’, ‘tai’, ‘tt’], defaults to ‘utc’

Returns:

Julian date of input dates

Return type:

np.ndarray


mirage.time.date_to_julian_centuries(dates: datetime | ndarray[datetime, Any], scale: str = 'tt') ndarray | float#

Julian centuries past the J2000 epoch as used in [Fru23]

Parameters:
  • date (Union[datetime.datetime, np.ndarray[datetime.datetime, Any]]) – Date to evaluate at [utc]

  • scale (str, optional) – Time scale to use from [‘utc’, ‘ut1’, ‘tai’, ‘tt’], defaults to ‘tt’

Returns:

Julian centuries [100 yr]

Return type:

Union[np.ndarray, float]

mirage.time.date_to_sidereal(dates: ndarray[datetime, Any], use_astropy: bool = False, scale: str = 'ut1') ndarray#

Converts an array of dates to Greenwich mean sidereal time (GMST)

Parameters:
  • date (np.ndarray[datetime.datetime, Any]) – Date objects (UTC)

  • use_astropy (bool, optional) – Whether to use astropy for the backend calculations, defaults to False

  • scale (str, optional) – Time scale to use from [‘utc’, ‘ut1’, ‘tai’, ‘tt’], defaults to ‘ut1’

Returns:

Sidereal times [seconds]

Return type:

np.ndarray


mirage.time.date_to_ut(date: ndarray[datetime, Any] | datetime) ndarray | float#

Converts a datetime object to Universal Time (UT)

Parameters:

date (Union[np.ndarray[datetime.datetime, Any], datetime.datetime]) – Date(s) (UTC)

Returns:

UT(s) [hr]

Return type:

Union[np.ndarray, float]

mirage.time.days(num: float | ndarray) timedelta | ndarray[timedelta]#

Returns an array of datetime.timedelta in days

Parameters:

num (Union[float, np.ndarray]) – Number(s) of days

Raises:

NotImplementedError – If num is not a float or np.ndarray

Returns:

Single datetime.timedelta or array of datetime.timedelta

Return type:

Union[datetime.timedelta, np.ndarray[datetime.timedelta]]

mirage.time.hours(num: float | ndarray) timedelta | ndarray[timedelta]#

Returns an array of datetime.timedelta in hours

Parameters:

num (Union[float, np.ndarray]) – Number(s) of hours

Raises:

NotImplementedError – If num is not a float or np.ndarray

Returns:

Single datetime.timedelta or array of datetime.timedelta

Return type:

Union[datetime.timedelta, np.ndarray[datetime.timedelta]]

mirage.time.jd_now() float#

Computes the Julian date at evaluation time

Returns:

Current Julian date [days]

Return type:

float

mirage.time.jd_to_date(jds: ndarray, scale: str = 'utc') ndarray[datetime, Any]#

Converts Julian dates to an array of datetime objects

Parameters:
  • jds (np.ndarray) – Julian dates

  • scale (str, optional) – Time scale to reference to, either “utc”, “ut1”, “tt”, or “tai”, defaults to “utc”

Returns:

Dates (UTC)

Return type:

np.ndarray[datetime.datetime, Any]

mirage.time.jd_to_epsec(jds: ndarray[float]) ndarray[float]#

Converts Julian dates to an array of seconds after the initial JD epoch (the first element of the jds array)

Parameters:

dates (np.ndarray[datetime.datetime, Any]) – Julian date (UTC)

Returns:

Epoch seconds

Return type:

np.ndarray

mirage.time.jd_to_mjd(jds: ndarray[float]) ndarray#

Converts Julian dates to modified Julian dates

Parameters:

jds (np.ndarray[float]) – Julian dates

Returns:

Modified Julian dates

Return type:

np.ndarray

mirage.time.minutes(num: float | ndarray) timedelta | ndarray[timedelta]#

Returns an array of datetime.timedelta in minutes

Parameters:

num (Union[float, np.ndarray]) – Number(s) of minutes

Raises:

NotImplementedError – If num is not a float or np.ndarray

Returns:

Single datetime.timedelta or array of datetime.timedelta

Return type:

Union[datetime.timedelta, np.ndarray[datetime.timedelta]]

mirage.time.mjd_to_jd(jds: ndarray[float]) ndarray#

Converts modified Julian dates to Julian dates

Parameters:

jds (np.ndarray[float]) – Modified Julian dates

Returns:

Julian dates

Return type:

np.ndarray

mirage.time.now() datetime#

Current datetime.datetime object

Returns:

Current UTC date object at runtime

Return type:

datetime.datetime

mirage.time.seconds(num: float | ndarray) timedelta | ndarray[timedelta]#

Returns an array of datetime.timedelta in seconds

Parameters:

num (Union[float, np.ndarray]) – Number(s) of seconds

Raises:

NotImplementedError – If num is not a float or np.ndarray

Returns:

Single datetime.timedelta or array of datetime.timedelta

Return type:

Union[datetime.timedelta, np.ndarray[datetime.timedelta]]

mirage.time.sidereal_hour_angle(obs_lon_rad: float, date: datetime | ndarray[datetime, Any]) float | ndarray#

Computes the GMST hour angle (the angle of the given longitude with respect to inertial \(\hat{x}\)) for a single observer over a range of dates

Parameters:
  • obs_lon_rad (float) – Longitude of the observer [rad]

  • date (Union[datetime.datetime, np.ndarray[datetime.datetime, Any]]) – Date(s) to evaluate at [UTC]

Returns:

Hour angle [rad]

Return type:

Union[float, np.ndarray]

mirage.time.tai_minus_utc(dates: ndarray[datetime, Any]) ndarray#

Uses Astropy to calculate the offset between TAI and UTC, accounting for leap seconds

Parameters:

dates (np.ndarray[datetime.datetime, Any]) – Dates [UTC]

Returns:

Seconds to add to UTC time to get TAI

Return type:

np.ndarray

mirage.time.today() datetime#

Beginning of today (UTC) datetime

Returns:

The UTC datetime at the beginning of today

Return type:

datetime.datetime

mirage.time.tt_minus_utc(dates: ndarray[datetime, Any]) ndarray#

Uses Astropy to calculate the offset between TT and UTC, accounting for leap seconds

Parameters:

dates (np.ndarray[datetime.datetime, Any]) – Dates [UTC]

Returns:

Seconds to add to UTC time to get TT

Return type:

np.ndarray

mirage.time.ut1_minus_utc(dates: ndarray[datetime, Any]) ndarray#

Uses Astropy to calculate the offset between UT1 and UTC, always less than 1 second by convention

Parameters:

dates (np.ndarray[datetime.datetime, Any]) – Dates [UTC]

Returns:

Seconds to add to UTC time to get UT1

Return type:

np.ndarray

mirage.time.utc(year: int, month: int, day: int, hour: int = 0, minute: int = 0, second: int = 0, microsecond: int = 0) datetime#

Returns a UTC datetime

Parameters:
  • year (int) – Year

  • month (int) – Month

  • day (int) – Day

  • hour (int, optional) – Hour, defaults to 0

  • minute (int, optional) – Minute, defaults to 0

  • second (int, optional) – Second, defaults to 0

  • microsecond (int, optional) – Microsecond, defaults to 0

Returns:

UTC datetime.datetime

Return type:

datetime.datetime

mirage.time.years(num: float | ndarray) timedelta | ndarray[timedelta]#

Returns an array of datetime.timedelta in years

Parameters:

num (Union[float, np.ndarray]) – Number(s) of years

Raises:

NotImplementedError – If num is not a float or np.ndarray

Returns:

Single datetime.timedelta or array of datetime.timedelta

Return type:

Union[datetime.timedelta, np.ndarray[datetime.timedelta]]

mirage.tle module#

class mirage.tle.SatDef(name: str, satnum: int, ides: str, launch_date: datetime, decay_date: datetime, inc_deg: float, period_min: float, apogee_km: int, perigee_km: int, object_type: str, rcs_size: str, country: str)#

Bases: object

class mirage.tle.SatDefArray(iter: Iterable[SatDef] | None = None)#

Bases: object

all_ides() list[str]#
all_names() list[str]#
all_satnums() list[int]#
append(newsat: SatDef)#
get_ides_by_name(name: str) int | None#
get_sat_by_ides(ides: str) SatDef#
get_sat_by_name(name: str) SatDef#
get_sat_by_norad(norad_id: int) SatDef#
get_satnum_by_ides(ides: str) int | None#
get_satnum_by_name(name: str) int | None#
mirage.tle.build_satdef_array() SatDefArray#
mirage.tle.get_latest_catalog_at_date(dtime: datetime = datetime.datetime(2025, 1, 14, 22, 44, 58, 510916, tzinfo=datetime.timezone.utc), days_back: datetime = datetime.timedelta(days=1), mode: str = 'tle_latest', **query_kwargs) list[list[str, str]]#

Gets the first TLE produced for a given NORAD SAT ID after the datetime provided

Parameters:
  • dtime (datetime.datetime, optional) – Datetime to query at, assumed to be UTC, defaults to now

  • days_back (datetime.datetime, optional) – Number of previous days to collect TLEs for, defaults to 5 days

  • mode (str, optional) – Mode to use for querying, defaults to “tle_latest”

  • query_kwargs (dict) – Extra keyword arguments passed to st.tle_latest

Return type:

list[list[str, str]]

mirage.tle.get_tles_between(dtimes: ndarray[datetime, Any], satnum: int | None = None) list[tuple[str, str]]#

Gets all TLEs published in the range of datetimes passed

Parameters:
  • dtimes (np.ndarray[datetime]) – Datetimes, assumed to be UTC, in chronologically ascending order

  • satnum (int, optional) – Satellite number, ex. 25544 for ISS ZARYA, defaults to None

Raises:

ValueError – If the object decays during the timespan

Returns:

List of TLE lines 1 and 2

Return type:

list[tuple[str, str]]

mirage.tle.load_satdef_array() SatDefArray#
mirage.tle.make_sync_st_request(query, endpoint: str = 'tle')#
mirage.tle.purge_tle_cache()#
mirage.tle.satdef_from_identifier(identifier: str | int) SatDef#
mirage.tle.satname_from_identifier(identifier: str | int) None | str#
mirage.tle.satnum_from_identifier(identifier: str | int) None | int#
mirage.tle.save_satdef_array(satdefs: SatDefArray)#

mirage.tools module#

mirage.tools.cache(function: Callable) Callable#

Module contents#