gnssrefl.extract_arcs module

extract_arcs.py - Standalone module for extracting satellite arcs from SNR data.

This module provides a clean API for detecting and extracting satellite arcs from Signal-to-Noise Ratio (SNR) data files. It refactors arc detection logic from gnssir_v2.py into reusable functions.

An “arc” represents a continuous satellite pass (rising or setting) across the sky. Arcs are split when: 1. Time gap > 600 seconds (10 minutes) 2. Elevation angle direction reverses (rising <-> setting)

gnssrefl.extract_arcs.apply_refraction(snr_array, lsp, year, doy)

Apply refraction correction to SNR elevation angles.

Returns a copy of snr_array with corrected elevations; rows where the correction is invalid (e.g. ele < 1.5 for NITE/MPF) are removed.

gnssrefl.extract_arcs.attach_gnssir_processing_results(arcs, results, time_tolerance=0.17)

Attach gnssir processing results to extracted arcs.

For each arc, finds the matching row in the gnssir result file based on satellite number, frequency, rise/set direction, and UTC time proximity. Sets metadata['gnssir_processing_results'] to a dict or None.

gnssrefl.extract_arcs.attach_phase_processing_results(arcs, results, time_tolerance=0.17)

Attach phase processing results to extracted arcs.

For each arc, finds the matching row in the phase result file based on satellite number, frequency, and UTC time proximity. Sets metadata['phase_processing_results'] to a dict or None.

gnssrefl.extract_arcs.attach_vwc_track_results(arcs, station, year, doy, extension='', az_tolerance=5.0, time_tolerance=0.25)

Attach VWC track results to extracted arcs.

Matches track file rows to arcs by sat, freq suffix, azimuth, and hour. Sets metadata['vwc_track_results'] to a dict or None.

gnssrefl.extract_arcs.check_azimuth_compliance(az_min_ele: float, azlist: List[float]) bool

Check if azimuth is within allowed regions.

Parameters:
  • az_min_ele (float) – Azimuth angle (degrees) at the lowest elevation point of the arc

  • azlist (list of float) – Azimuth regions as pairs [az1_start, az1_end, az2_start, az2_end, …] e.g., [0, 90, 180, 270] means 0-90 and 180-270 degrees

Returns:

True if azimuth is within any of the allowed regions

Return type:

bool

gnssrefl.extract_arcs.extract_arcs(snr_array: ndarray, freq: int | List[int] | None = None, e1: float = 5.0, e2: float = 25.0, ellist: List[float] | None = None, azlist: List[float] | None = None, sat_list: List[int] | None = None, min_pts: int = 20, polyV: int = 4, pele: List[float] | None = None, dbhz: bool = False, screenstats: bool = False, detrend: bool = True, split_arcs: bool = True, filter_to_day: bool = True, year: int | None = None, doy: int | None = None, dec: int = 1) List[Tuple[Dict[str, Any], Dict[str, ndarray]]]

Extract satellite arcs from SNR data array.

Parameters:
  • snr_array (np.ndarray) – 2D array with columns: [sat, ele, azi, seconds, edot, snr1, snr2, …]

  • freq (int, list of int, or None) – Frequency code(s). Default: None (auto-detect)

  • e1 (float) – Minimum elevation angle (degrees). Default: 5.0

  • e2 (float) – Maximum elevation angle (degrees). Default: 25.0

  • ellist (list of floats, optional) – Multiple elevation angle ranges as pairs. Overrides e1/e2.

  • azlist (list of floats, optional) – Azimuth regions as pairs. Default: [0, 360]

  • sat_list (list of int, optional) – Specific satellites to process. Default: all satellites in data

  • min_pts (int) – Minimum points required per arc. Default: 20

  • polyV (int) – Polynomial order for DC removal. Default: 4

  • pele (list of float, optional) – Elevation angle range [min, max] for polynomial fit. Default: [e1, e2]

  • dbhz (bool) – If True, keep SNR in dB-Hz. Default: False

  • screenstats (bool) – If True, print debug information. Default: False

  • detrend (bool) – If True (default), remove DC component via polynomial fit.

  • split_arcs (bool) – If True (default), split data into separate arcs.

  • filter_to_day (bool) – If True (default), only return arcs within the principal day (0-24h).

  • year (int, optional) – Year, used for L2C/L5 satellite list lookup.

  • doy (int, optional) – Day of year, used with year.

  • dec (int) – Decimation factor. Default: 1 (no decimation).

Returns:

Each arc is represented as: - metadata: dict with keys: sat, freq, arc_num, arc_type, ele_start, ele_end,

az_min_ele, az_avg, time_start, time_end, arc_timestamp, num_pts, delT, edot_factor, cf

  • data: dict with keys: ele, azi, snr, seconds, edot (all np.ndarray)

Return type:

list of (metadata, data) tuples

gnssrefl.extract_arcs.extract_arcs_from_file(obsfile: str, freq: int | List[int] | None = None, buffer_hours: float = 2, **kwargs) List[Tuple[Dict[str, Any], Dict[str, ndarray]]]

Extract satellite arcs from an SNR file.

Loads the file with read_snr() and extracts arcs in one call.

Parameters:
  • obsfile (str) – Path to the SNR observation file.

  • freq (int, list of int, or None) – Frequency code(s). Default: None (auto-detect)

  • buffer_hours (float) – Hours of data from adjacent days. Default: 2

  • **kwargs – Additional keyword arguments passed to extract_arcs()

Returns:

See extract_arcs() for format details.

Return type:

list of (metadata, data) tuples

Raises:
  • FileNotFoundError – If obsfile does not exist.

  • RuntimeError – If read_snr() fails to load the file.

gnssrefl.extract_arcs.extract_arcs_from_station(station: str, year: int, doy: int, freq: int | List[int] | None = None, snr_type: int = 66, buffer_hours: float = 2, attach_results: bool = False, extension: str = '', lsp: Dict[str, Any] | None = None, gzip: bool = True, **kwargs) List[Tuple[Dict[str, Any], Dict[str, ndarray]]]

Extract satellite arcs for a station/year/day.

Resolves the SNR file path, loads SNR data, optionally applies refraction correction and decimation, extracts arcs, and optionally saves arc files and attaches processing results.

Parameters:
  • station (str) – Station name (4 characters, e.g. ‘mchl’)

  • year (int) – Full year (e.g. 2025)

  • doy (int) – Day of year (1-366)

  • freq (int, list of int, or None) – Frequency code(s). Default: None (auto-detect)

  • snr_type (int) – SNR file type (66, 77, 88, etc.). Default: 66

  • buffer_hours (float) – Hours of data from adjacent days for midnight-crossing arcs. Default: 2

  • attach_results (bool) – If True, attach gnssir/phase/vwc results to arc metadata. Default: False

  • extension (str) – Strategy extension for result file paths. Default: ‘’

  • lsp (dict, optional) – Station analysis parameters. When provided, enables refraction correction (if lsp['refraction']) and savearcs (if lsp['savearcs']).

  • gzip (bool) – If True, gzip the SNR file after reading. Default: False

  • **kwargs – Additional keyword arguments passed to extract_arcs()

Returns:

See extract_arcs() for format details.

Return type:

list of (metadata, data) tuples

Raises:

FileNotFoundError – If the SNR file does not exist and cannot be decompressed.

gnssrefl.extract_arcs.move_arc_to_failqc(meta, station, year, doy, extension='')

Move a saved arc file from arcs/ to arcs/failQC/.

gnssrefl.extract_arcs.save_arc(meta, data, sdir, station, year, doy, savearcs_format='txt')

Save a single arc file to sdir.

gnssrefl.extract_arcs.setup_arcs_directory(station, year, doy, extension='', nooverwrite=False)

Create arcs directory, optionally clearing old contents.