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.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, ediff: float = 2.0, polyV: int = 4, dbhz: bool = False, screenstats: bool = False, detrend: bool = True, split_arcs: bool = True, filter_to_day: bool = True) 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, …] This is the output of loading an SNR file with np.loadtxt()

  • freq (int, list of int, or None) – Frequency code(s). A single int (e.g. 1), a list (e.g. [1, 2, 5]), or None (default) to auto-detect all frequencies that have data in the file.

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

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

  • ellist (list of floats, optional) – Multiple elevation angle ranges as pairs, e.g., [5, 10, 7, 12] means ranges (5-10 deg) and (7-12 deg). When provided and non-empty, this overrides e1/e2. Each pair is processed independently. Default: None

  • azlist (list of floats, optional) – Azimuth regions as pairs, e.g., [0, 90, 180, 270] means 0-90 and 180-270. Default: [0, 360] (all azimuths)

  • 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

  • ediff (float) – Elevation difference tolerance for arc validation (degrees). Default: 2.0

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

  • dbhz (bool) – If True, keep SNR in dB-Hz; if False, convert to linear units. Default: False

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

  • detrend (bool) – If True (default), remove DC component via polynomial fit. If False, return SNR converted to linear units only (no detrending).

  • split_arcs (bool) – If True (default), split data into separate arcs by time gaps and elevation direction changes. If False, return all data for each satellite as a single arc without splitting or validation. Useful for phase processing.

  • filter_to_day (bool) – If True (default), only return arcs whose midpoint (arc_timestamp) falls within the principal day (0-24 hours). This prevents double-counting arcs when processing consecutive days with buffer_hours. Arc data may still extend beyond day boundaries. If False, return all arcs regardless of their midpoint time.

Returns:

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

az_init, az_avg, time_start, time_end, time_avg, 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 = 0, **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). A single int (e.g. 1), a list (e.g. [1, 2, 5]), or None (default) to auto-detect all frequencies that have data in the file.

  • buffer_hours (float) – Hours of data to include from adjacent days for midnight-crossing arcs. Default: 0 (single day only)

  • **kwargs – Additional keyword arguments passed to extract_arcs() (e1, e2, azlist, sat_list, etc.)

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 = 0, **kwargs) List[Tuple[Dict[str, Any], Dict[str, ndarray]]]

Extract satellite arcs for a station/year/day.

Resolves the SNR file path (handling .gz/.xz decompression), loads it, and extracts arcs in one call.

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). A single int (e.g. 1), a list (e.g. [1, 2, 5]), or None (default) to auto-detect all frequencies that have data in the file.

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

  • buffer_hours (float) – Hours of data to include from adjacent days for midnight-crossing arcs. Default: 0 (single day only)

  • **kwargs – Additional keyword arguments passed to extract_arcs() (e1, e2, azlist, sat_list, etc.)

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.