MediaCorrections#

class MediaCorrections(name: str, instrument: Instrument, tropo_seasonal_file_path: str | Path | None = None, tropo_non_seasonal_file_path: str | Path | None = None, iono_file_path: str | Path | None = None)#

Bases: Measurement

Computes path delays due to tropospheric and ionospheric media corrections.

This class is a subclass of Measurement and provides correction models for signal propagation through Earth’s atmosphere. It is consumed by DopplerReal and SequentialRangingReal.

Tropospheric delay (Chao mapping)

The total one-way excess tropospheric path length is the sum of seasonal and non-seasonal zenith delays mapped to slant via the Chao functions (Estefan 1995; Moyer eq. 10-8 to 10-10):

\[\Delta\rho_{tropo} = R_{dry}(\varepsilon)\,\Delta\tau_{dry} + R_{wet}(\varepsilon)\,\Delta\tau_{wet}\]

where the dry and wet mapping functions are

\[R_{dry} = \frac{1}{\sin\varepsilon + \dfrac{A_{dry}}{\tan\varepsilon + B_{dry}}}, \qquad R_{wet} = \frac{1}{\sin\varepsilon + \dfrac{A_{wet}}{\tan\varepsilon + B_{wet}}}\]

with constants \(A_{dry}=0.00143\), \(B_{dry}=0.0445\), \(A_{wet}=0.00035\), \(B_{wet}=0.017\). The zenith delays are represented by Fourier (seasonal) or normalized polynomial (non-seasonal) expansions loaded from JSON files at construction time.

Ionospheric delay

The dispersive ionospheric group delay scales as \(f^{-2}\):

\[\Delta\rho_{iono} \propto \frac{1}{f^2}\int N_e\,ds\]

where \(f\) is the carrier frequency and \(N_e\) is the electron column density.

Sign conventions

  • DopplerReal: ionosphere enters with a negative sign (Moyer eq. 10-28, 10-29).

  • SequentialRangingReal: ionosphere enters with a positive sign (Moyer eq. 10-27).

Parameters:
  • name (str) – The name of the media correction model object.

  • instrument (Instrument) – The observation instrument or ground station to which the corrections apply.

  • tropo_seasonal_file_path (PathLike, optional) – Path to the JSON file containing seasonal tropospheric correction data. Defaults to None.

  • tropo_non_seasonal_file_path (PathLike, optional) – Path to the JSON file containing non-seasonal tropospheric correction data. Defaults to None.

  • iono_file_path (PathLike, optional) – Path to the JSON file containing ionospheric correction data. Defaults to None.

See also

scarabaeus.DopplerReal

Real Doppler model that consumes MediaCorrections.

scarabaeus.SequentialRangingReal

Real ranging model that consumes MediaCorrections.

References

Attributes:
instrument

The instrument.

iono_file_path

Absolute path to the selected ionosphere JSON, if set.

name

The name of the model.

tropo_non_seasonal_file_path

Absolute path to the selected troposphere JSON, if set.

tropo_seasonal_file_path

Absolute path to the selected troposphere JSON, if set.

Methods

chao_mapping()

Compute the tropospheric mapping functions for dry and wet delays using the Chao model.

compute_partials(target, epoch_array, frame)

Stacks together measurement _partials for an epoch array at different epochs.

computed_rtlt_delays(query_time_et, ...[, ...])

Compute a radio signal path delay due to Earth's media at a given epoch.

find_ion_metadata(folder, query_year, query_doy)

Locate ionosphere metadata files covering a given year and day-of-year.

find_tro_metadata(folder, query_year, query_doy)

Locate troposphere metadata files covering a given year and day-of-year.

generate_measurement_dataset(dataset_name, ...)

Generates a MeasurementDataSet object that can be used by filters downstream.

get_media_data_for_et(site_query, ...)

Extract media-correction coefficients for a given DSN site and epoch, with optional wet/dry filtering.

mediafun_nrmpow(query_time_et)

Evaluate media correction function using a normalized power series expansion.

mediafun_trig(query_time_et)

Evaluate media correction function using a trigonometric series expansion.

observed_measurements(file_name, meas_name, ...)

Reads measurements from a .json file.

residuals(observed_meas, computed_meas)

Generates the measurement model's residuals given observed and computed ArrayWFrames.

update_reference_state(state_vector)

Call this once per iteration (before generate_measurement_dataset). The model will pull: - meas_bias_ideal_* (as ArrayWUnits) - gs_delta_location_ECEF_* (as ArrayWFrame) for this instrument (matching spice_id).

write_observed_measurements(target, ...)

Generates synthetic measurements and write them as a .json file.

static find_ion_metadata(folder: str, query_year: int, query_doy: int) Dict | None#

Locate ionosphere metadata files covering a given year and day-of-year.

This scans the specified folder for files named with any prefix followed by YYYY_DDD_YYYY_DDD_ion.json (e.g., orex_beno_2018_213_2018_244_ion.json). The method returns the metadata dictionary for the file whose interval contains the provided query year/day. Intervals crossing year boundaries are handled correctly.

Parameters:
  • folder (str) – Path to the folder containing ionosphere metadata files.

  • query_year (int) – Year of interest in four-digit format (e.g., 2018).

  • query_doy (int) – Day-of-year (1–366) within query_year.

Returns:

metadata – Dictionary describing the matching file with fields: - “file” : filename - “start_year”, “start_doy” : start of coverage interval - “end_year”, “end_doy” : end of coverage interval Returns None if no file covers the query date.

Return type:

dict or None

Notes

If multiple files cover the same query date, the one with the tightest interval span is returned.

static find_tro_metadata(folder: str, query_year: int, query_doy: int) Dict | None#

Locate troposphere metadata files covering a given year and day-of-year.

This scans the specified folder for files named according to the pattern YYYY_DDD_YYYY_DDD_tro.json. Each file encodes the start and end year/DOY interval it covers. The method returns the metadata dictionary for the file whose interval contains the provided query year/day. Intervals that cross year boundaries (e.g. 2017_335_2018_001_tro.json) are handled correctly.

Parameters:
  • folder (str) – Path to the folder containing the troposphere metadata files.

  • query_year (int) – Year of interest in four-digit format (e.g., 2017).

  • query_doy (int) – Day-of-year (1–366) within query_year.

Returns:

metadata – Dictionary describing the matching file with fields:

  • "file" : filename of the tro file

  • "start_year", "start_doy" : start of coverage interval

  • "end_year", "end_doy" : end of coverage interval

Returns None if no file covers the query date.

Return type:

dict or None

Raises:

None

Notes

If multiple files cover the same query date, the one with the tightest interval span is returned.

Examples

meta = MediaCorrections.find_tro_metadata(
    folder="data/tropo",
    query_year=2017,
    query_doy=346
)
print(meta["file"])
# -> "2017_335_2018_001_tro.json"
chao_mapping() tuple[float, float]#

Compute the tropospheric mapping functions for dry and wet delays using the Chao model.

Parameters:

E (float) – Elevation angle of the observation [rad].

Returns:

  • R_dry (float) – Dry mapping function value at the given elevation angle.

  • R_wet (float) – Wet mapping function value at the given elevation angle.

Notes

The mapping functions are based on:

  • Estefan (1995), equations (7)–(8a,b).

  • Moyer (2000), equations (10–8 to 10–10).

The dry and wet components are computed as:

\[ \begin{align}\begin{aligned}R_{dry} = \frac{1}{\sin(E) + \frac{A_{dry}}{\tan(E) + B_{dry}}}\\R_{wet} = \frac{1}{\sin(E) + \frac{A_{wet}}{\tan(E) + B_{wet}}}\end{aligned}\end{align} \]

with constants \(A_{dry} = 0.00143\), \(B_{dry} = 0.0445\), \(A_{wet} = 0.00035\), and \(B_{wet} = 0.017\).

References

[1]

Estefan, J. A. (1995). Tropospheric Delay Effects on GPS Measurements.

[2]

Moyer, T. D. (2000). Formulation for Observed and Computed Values of Deep Space Network Data Types for Navigation. JPL 00-7.

Examples

# Example: compute mapping functions at 30 degrees elevation
import numpy as np
E = np.deg2rad(30.0)
R_dry, R_wet = scb.MediaCorrections.chao_mapping(E)
compute_partials(target: Spacecraft, epoch_array: EpochArray, frame: Frame = J2000 (0 - SOLAR SYSTEM BARYCENTER)) list#

Stacks together measurement _partials for an epoch array at different epochs.

Parameters:
  • target (Spacecraft) – The target spacecraft.

  • epoch_array (EpochArray) – The epochs.

  • frame (Frame, optional) – The reference frame. Defaults to a J2000 Frame object.

Returns:

_partials – A list with all the _partials evaluated at different epochs in the epoch_array.

Return type:

list

computed_rtlt_delays(query_time_et: float, target_spice_id: str, frequency: float | None = None, gs_delta_awf: ArrayWFrame | None = None) tuple[float, float]#

Compute a radio signal path delay due to Earth’s media at a given epoch.

This method evaluates the tropospheric contribution (seasonal + non-seasonal, dry + wet) mapped by the Chao functions at the station elevation angle. If an ionospheric dataset is available (self.iono_file_path), the ionospheric term may also be included (currently not implemented).

Parameters:
  • query_time_et (float) – SPICE Ephemeris Time (seconds past J2000) at which to evaluate the delay.

  • target_spice_id (str) – SPICE name or NAIF ID of the tracked target (e.g., spacecraft) used to compute the elevation angle at the DSN station.

  • frequency (float, optional) – Uplink or downlink frequency in Hz. Required to compute ionospheric group delay (∝ 1/frequency²). If None, iono contribution is skipped.

  • gs_delta_awf (ArrayWFrame | None) – If not None, this is the delta vector for the ground station in the SSB space-time relativistic frame of reference.

Returns:

p_total – Total media path delay in meters (troposphere + ionosphere if available). The troposphere term sums seasonal and non-seasonal dry/wet components and applies the Chao mapping functions at the current elevation angle.

Return type:

float

Raises:
  • KeyError – If required keys are missing from the loaded JSON files (e.g., "aux_tropo").

  • FileNotFoundError – If one of the provided JSON file paths does not exist.

  • ValueError – If the JSON content is malformed or contains invalid time ranges.

Notes

  • The method expects JSON files at the paths

self.tropo_seasonal_file_path and self.tropo_non_seasonal_file_path. Each should expose an "aux_tropo" table compatible with MediaCorrections.get_media_data_for_et(). - The elevation angle is computed via SpiceManager.get_elevation_angle() using the DSN station name from self.instrument.name and the provided target identifier. - Mapping to slant delay is performed using MediaCorrections.chao_mapping() (dry and wet components). - Ionospheric delay handling is scaffolded (flag_iono) but not yet implemented.

See also

MediaCorrections.get_media_data_for_et

Interval selection and coefficient extraction for a given site/mode/time.

MediaCorrections.chao_mapping

Dry/wet mapping functions as a function of elevation angle.

MediaCorrections.mediafun_trig

Trigonometric (seasonal) delay evaluator.

MediaCorrections.mediafun_nrmpow

Normalized power-series (non-seasonal) delay evaluator.

Examples

et = scb.SpiceManager.utc2et("2018-12-03 12:00:00 UTC")
p_media = media_correction.computed_rtlt_delays(
    query_time_et=et,
    target_spice_id="ORX"
)
generate_measurement_dataset(dataset_name: str, target: Body, observed_meas: tuple | list | None = None, epochs: EpochArray | None = None, frame: Frame = J2000 (0 - SOLAR SYSTEM BARYCENTER), noisy: bool = False) list[MeasurementDataSet]#

Generates a MeasurementDataSet object that can be used by filters downstream.

Parameters:
  • dataset_name (str) – The name of the MeasurementDataSet.

  • target (Spacecraft) – The target spacecraft.

  • epoch_list (EpochArray, optional) – The epochs. Defaults to None.

  • epoch_start (EpochArray, optional) – The starting epoch. Defaults to None.

  • epoch_end (EpochArray, optional) – The end epoch. Defaults to None.

  • tstep (int, optional) – The integration timestep. Defaults to 1.

  • observed_measurements (list, optional) – The observed measurements. Defaults to None.

  • frame (Frame, optional) – The reference frame. Defaults to a J2000 Frame object.

  • noisy (bool, optional) – Indicates if noise is added to the measurements or not. Defaults to False.

Returns:

mds_list – A list of MeasurementDataSet objects representing the measurements with their key properties to be used by a filter.

Return type:

list[MeasurementDataSet]

:raises If the observed_meas list is only made by 3 elements`, it throws an error because it needs the 4th element in the list for the indices of :py:class:`the outlier_flag:

Notes

The MeasurementDataSet output is generated in 6 steps:

  1. Computed measurements

  2. Partials

  3. Residuals

  4. Sigmas

  5. Outlier flag

  6. Pack everything in a list

  7. Pack the list in a MeasurementDataSet object

get_media_data_for_et(site_query: str, wetdry_query: str | None, query_et: float) dict | None#

Extract media-correction coefficients for a given DSN site and epoch, with optional wet/dry filtering. Works for both troposphere tables (with ‘wet_or_dry’ and possibly ‘type’) and ionosphere tables (which may omit those fields).

Parameters:
  • dict_input (dict) – Table-like dictionary with row-aligned lists: required: ‘dsn’, ‘start_day’, ‘start_time’, ‘end_day’, ‘end_time’ optional: ‘wet_or_dry’, ‘type’, any ‘C#’ coefficient fields, etc.

  • site_query (str) – DSN site code to filter (e.g., “C40”).

  • wetdry_query (str or None) – If provided and ‘wet_or_dry’ exists, filter by this mode (“WET”/”DRY”). If None or the column is missing, only the site filter is applied.

  • query_et (float) – Ephemeris Time (ET) at which the values are requested.

Returns:

A single-interval dictionary slice whose [start_et, end_et] contains query_et. All row-wise fields are reduced to the selected row; non row-wise/scalar fields are carried as-is. Returns None if no match.

Return type:

dict or None

mediafun_nrmpow(query_time_et) float#

Evaluate media correction function using a normalized power series expansion. Applicable for seasonal, non-seasonal, and ionospheric corrections.

Parameters:
  • media_data (dict) – Dictionary containing the polynomial coefficients (C1C10) and the interval bounds start_et and end_et. Coefficients are expected to be convertible to float.

  • query_time_et (float) – Ephemeris Time (ET) at which the correction is to be evaluated.

Returns:

delta_sum – Media correction value delay at the requested time, expressed in meters.

Return type:

float

Raises:

KeyError – If one or more required coefficients (C1C10) or ET bounds (start_et, end_et) are missing from media_data.

Notes

The function evaluates a normalized power series of the form:

\[ \begin{align}\begin{aligned}X = 2 \frac{t - A}{B - A} - 1\\\Delta(t) = C_0 X^0 + C_1 X^1 + C_2 X^2 + \ldots + C_9 X^9\end{aligned}\end{align} \]

where \(A\) and \(B\) are the start and end ephemeris times of the interval, respectively.

Examples

# Example evaluation
et = scb.SpiceManager.utc2et("2010-01-15 12:00:00 UTC")
correction = scb.MediaCorrections.mediafun_nrmpow(media_data, et)
mediafun_trig(query_time_et) float#

Evaluate media correction function using a trigonometric series expansion. Applicable for seasonal, non-seasonal, and ionospheric corrections.

Parameters:
  • media_data (dict) – Dictionary containing the trigonometric coefficients (C1C10) and the interval bounds start_et and end_et. Coefficients are expected to be convertible to float.

  • query_time_et (float) – Ephemeris Time (ET) at which the correction is to be evaluated.

Returns:

delta_sum – Media correction value delay at the requested time, expressed in meters.

Return type:

float

Raises:

KeyError – If one or more required coefficients (C1C10) or ET bounds (start_et, end_et) are missing from media_data.

Notes

The function evaluates a truncated Fourier series of the form:

\[\Delta(t) = C_1 + C_2 \cos(X) + C_3 \sin(X) + C_4 \cos(2X) + C_5 \sin(2X) + C_6 \cos(3X) + C_7 \sin(3X) + C_8 \cos(4X) + C_9 \sin(4X)\]

where \(X = 2 \pi (t - A)/P\), with \(A\) being the start_et and \(P\) the fundamental period C1.

Examples

# Example evaluation
et = scb.SpiceManager.utc2et("2010-01-15 12:00:00 UTC")
correction = scb.MediaCorrections.mediafun_trig(media_data, et)
observed_measurements(file_name, meas_name: str = 'meas_ideal', units: Units = unitless, frame: Frame = J2000 (0 - SOLAR SYSTEM BARYCENTER)) Tuple[EpochArray, ndarray, ArrayWFrame]#

Reads measurements from a .json file.

Parameters:
  • file_name (str) – The filename of the .json file containig the measurement information.

  • meas_name (str, optional) – The name of the measurement data to access from the dictionary. Defaults to 'meas_ideal'.

  • units (Units, optional) – Units to be used to write the output AWU. Defaults to unitless.

  • frame (Frame, optional) – Frame to be used to write the output AWF. Defaults to a J2000 Frame object.

Returns:

meas_time_et, meas_sec, meas_obs – A tuple with the following values corresponding to their respective indices:

  • [0] = meas_time_etEpochArray

    The time in ephemeris time.

  • [1] = meas_Secnumpy.ndarray

    The times in seconds.

  • [2] = meas_obsArrayWFrame

    An AWF with the quantities in AWU.

  • [3] = meas_outliersnumpy.ndarray

    The np.array of measurements outliers

Return type:

Tuple[EpochArray, numpy.ndarray, ArrayWFrame]

Notes

The writing of the json assumes or requires units and frames.

residuals(observed_meas: ArrayWFrame, computed_meas: ArrayWFrame) ArrayWFrame#

Generates the measurement model’s residuals given observed and computed ArrayWFrames.

Parameters:
  • observed_meas (ArrayWFrame) – The observed measurements values (O).

  • computed_meas (ArrayWFrame) – The computed measurements values (C).

Returns:

residuals – AWF with the residual O-C.

Return type:

ArrayWFrame

update_reference_state(state_vector: StateArray)#

Call this once per iteration (before generate_measurement_dataset). The model will pull:

  • meas_bias_ideal_* (as ArrayWUnits)

  • gs_delta_location_ECEF_* (as ArrayWFrame)

for this instrument (matching spice_id).

write_observed_measurements(target: Spacecraft, epoch_array: EpochArray = None, epoch_start: EpochArray = None, epoch_end: EpochArray = None, tstep: float = 1, frame: Frame = J2000 (0 - SOLAR SYSTEM BARYCENTER), noisy: bool = False, file_name: str = 'ideal_measurement', check_visibility: bool = False, elevation_mask: float = 10.0, folder_path_override: str = None) None#

Generates synthetic measurements and write them as a .json file. The input of this method encapsulate the ones needed for the “computed_meas” method in each measurement model class.

Parameters:
  • target (Spacecraft) – The target spacecraft for which the range measurement is to be computed.

  • epoch_array (EpochArray, optional) – An array of epochs (times) at which the range measurements should be computed. If provided, overrides epoch_start, epoch_end, and tstep.

  • epoch_start (EpochArray, optional) – The starting epoch for the range measurement computations. Required if epoch_array is not provided.

  • epoch_end (EpochArray, optional) – The ending epoch for the range measurement computations. Required if epoch_array is not provided.

  • tstep (float, optional) – The time step, in seconds, between consecutive range measurements. If epoch_array is not provided. Defaults to 1 second.

  • frame (Frame , optional) – The reference frame in which the range computation is performed. Defaults to None.

  • noisy (bool , optional) – Whether to add noise to the computed range measurement. Defaults to False.

  • file_name (str, optional) – The filename of the JSON in which the measurement is saved, Defaults to 'ideal_measurement'.

  • check_visibility (bool, optional) – When True, epochs where the instrument cannot observe the target are removed before generating measurements. The specific check is instrument-dependent: GroundStation uses an elevation-angle test; Camera uses a FOV projection test. Defaults to False.

  • elevation_mask (float, optional) – Minimum elevation angle in degrees used by the GroundStation visibility check. Ignored for Camera instruments. Only relevant when check_visibility=True. Defaults to 10.0.

  • folder_path_override (str, optional) – If provided, the JSON file is saved directly to this path instead of the default data/measurements/radiometric or data/measurements/optical folder. The directory is created automatically if it does not exist. Defaults to None.

Return type:

None

property instrument: Instrument#

The instrument.

property iono_file_path: Path | None#

Absolute path to the selected ionosphere JSON, if set.

property name: str#

The name of the model.

property tropo_non_seasonal_file_path: Path | None#

Absolute path to the selected troposphere JSON, if set.

property tropo_seasonal_file_path: Path | None#

Absolute path to the selected troposphere JSON, if set.