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:
MeasurementComputes path delays due to tropospheric and ionospheric media corrections.
This class is a subclass of
Measurementand provides correction models for signal propagation through Earth’s atmosphere. It is consumed byDopplerRealandSequentialRangingReal.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 toNone.tropo_non_seasonal_file_path (
PathLike, optional) – Path to the JSON file containing non-seasonal tropospheric correction data. Defaults toNone.iono_file_path (
PathLike, optional) – Path to the JSON file containing ionospheric correction data. Defaults toNone.
See also
scarabaeus.DopplerRealReal Doppler model that consumes MediaCorrections.
scarabaeus.SequentialRangingRealReal ranging model that consumes MediaCorrections.
References
- Attributes:
instrumentThe instrument.
iono_file_pathAbsolute path to the selected ionosphere JSON, if set.
nameThe name of the model.
tropo_non_seasonal_file_pathAbsolute path to the selected troposphere JSON, if set.
tropo_seasonal_file_pathAbsolute path to the selected troposphere JSON, if set.
Methods
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:
- 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:
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:
- 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
Noneif no file covers the query date.- Return type:
- 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:
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:
- 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:
- 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_pathandself.tropo_non_seasonal_file_path. Each should expose an"aux_tropo"table compatible withMediaCorrections.get_media_data_for_et(). - The elevation angle is computed viaSpiceManager.get_elevation_angle()using the DSN station name fromself.instrument.nameand the provided target identifier. - Mapping to slant delay is performed usingMediaCorrections.chao_mapping()(dry and wet components). - Ionospheric delay handling is scaffolded (flag_iono) but not yet implemented.See also
MediaCorrections.get_media_data_for_etInterval selection and coefficient extraction for a given site/mode/time.
MediaCorrections.chao_mappingDry/wet mapping functions as a function of elevation angle.
MediaCorrections.mediafun_trigTrigonometric (seasonal) delay evaluator.
MediaCorrections.mediafun_nrmpowNormalized 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 toNone.epoch_start (
EpochArray, optional) – The starting epoch. Defaults toNone.epoch_end (
EpochArray, optional) – The end epoch. Defaults toNone.tstep (
int, optional) – The integration timestep. Defaults to1.observed_measurements (
list, optional) – The observed measurements. Defaults toNone.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 toFalse.
- 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 indicesof :py:class:`the outlier_flag:Notes
The MeasurementDataSet output is generated in 6 steps:
Computed measurements
Partials
Residuals
Sigmas
Outlier flag
Pack everything in a list
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 (
strorNone) – 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:
- 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:
- Returns:
delta_sum – Media correction value delay at the requested time, expressed in meters.
- Return type:
- Raises:
KeyError – If one or more required coefficients (C1–C10) 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:
- Returns:
delta_sum – Media correction value delay at the requested time, expressed in meters.
- Return type:
- Raises:
KeyError – If one or more required coefficients (C1–C10) 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 tounitless.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_etEpochArrayThe time in ephemeris time.
[1]= meas_Secnumpy.ndarrayThe times in seconds.
[2]= meas_obsArrayWFrameAn AWF with the quantities in AWU.
[3]= meas_outliersnumpy.ndarrayThe 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:
- 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, overridesepoch_start,epoch_end, andtstep.epoch_start (
EpochArray, optional) – The starting epoch for the range measurement computations. Required ifepoch_arrayis not provided.epoch_end (
EpochArray, optional) – The ending epoch for the range measurement computations. Required ifepoch_arrayis not provided.tstep (
float, optional) – The time step, in seconds, between consecutive range measurements. If epoch_array is not provided. Defaults to1second.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) – WhenTrue, epochs where the instrument cannot observe the target are removed before generating measurements. The specific check is instrument-dependent:GroundStationuses an elevation-angle test;Camerauses a FOV projection test. Defaults toFalse.elevation_mask (
float, optional) – Minimum elevation angle in degrees used by theGroundStationvisibility check. Ignored forCamerainstruments. Only relevant whencheck_visibility=True. Defaults to10.0.folder_path_override (
str, optional) – If provided, the JSON file is saved directly to this path instead of the defaultdata/measurements/radiometricordata/measurements/opticalfolder. The directory is created automatically if it does not exist. Defaults toNone.
- Return type:
- property instrument: Instrument#
The instrument.