GeoRinex: Python RINEX Reader and Converter

repository·main·Indexed 43 days ago

https://github.com/geospace-code/georinex

A Python-based reader and batch converter for RINEX (versions 2, 3, and 4) navigation and observation files. It converts ASCII RINEX data into high-performance NetCDF4/HDF5 formats and provides in-memory access via xarray Datasets for efficient GNSS dataset analysis. Supports compressed ASCII, Hatanaka compression, and SP3 ephemeris/clock files.

Tokens
8.4K
Snippets
42
Records
46
Agent score
55%

What's inside GeoRinex

  1. Index RINEX observation data

    main

    Since georinex.load() returns an xarray.Dataset, you can use standard xarray indexing methods to select specific satellites, parameters, or time ranges.

    Select a specific satellite

    Use .sel(sv='...') to pick a satellite by its identifier.

    Select a specific measurement

    Access measurements (like L1) using bracket notation obs['L1'].

    Filter by satellite system

    You can filter by system (e.g., Galileo) during loading using the use parameter, or after loading using Boolean indexing on the sv index.

    import georinex as gr
    
    # Load only Galileo (E) data
    obs = gr.load('myfile.o', use='E')
    
    # OR: Filter after loading using Boolean indexing
    obs = gr.load('myfile.o')
    Eind = obs.sv.to_index().str.startswith('E')
    Edata = obs.isel(sv=Eind)
    
    # Select a specific satellite and clean NaNs
    sat_data = obs.sel(sv='G13').dropna(dim='time', how='all')
    
    # Select a specific measurement across all satellites
    l1_data = obs['L1'].dropna(dim='time', how='all')
  2. Access receiver location and ECEF coordinates

    main

    If the RINEX OBS file contains APPROX LOCATION XYZ, this information is stored in the NetCDF4/HDF5 output. You can access it via xarray or h5py.

    To convert ECEF coordinates to Latitude, Longitude, or Altitude, use the PyMap3d library.

    import xarray as xarray
    
    # Accessing via xarray
    obs = xarray.open_dataset('my.nc')
    ecef = obs.position
    # latlon is available only if pymap3d was used during conversion
    latlon = obs.position_geodetic 
    
    # Accessing via h5py
    import h5py
    with h5py.File('my.nc') as f:
        ecef = f['OBS'].attrs['position']
        latlon = f['OBS'].attrs['position_geodetic']
  3. Configure loading speed and strictness

    main

    GeoRinex uses speculative time preallocation by default (fast=True) to improve performance. If you encounter issues with preallocation, you can force a slower, more reliable 'double-read strict' mode.

    • API: Set fast=False in gr.load().
    • CLI: Use the -strict flag with python -m georinex.read.
    # Fallback to strict preallocation if fast loading fails
    obs = gr.load('myfile.rnx', fast=False)
  4. Join data from multiple RINEX files

    main

    To combine multiple xarray.Dataset objects (e.g., from different files) into one, use xarray.concat or xarray.merge.

    • Use xarray.concat(..., dim='time') if the data can be concatenated along the time dimension.
    • Use xarray.merge(...) if the files contain different SV observation types, as concat may fail in that scenario.
    import xarray as xarray
    
    # Assuming obs1 and obs2 are loaded xarray Datasets
    # Try concatenation first
    try:
        obs = xarray.concat((obs1, obs2), dim='time')
    except:
        # Fallback to merge if observation types differ
        obs = xarray.merge((obs1, obs2))
  5. Index NAV data in the xarray.Dataset

    main

    Once a NAV file is loaded into an xarray.Dataset (e.g., variable nav), you can access specific data using xarray indexing methods:

    • Select by satellite (sv): Use .sel(sv='...') to filter for a specific satellite (e.g., G13).
    • Select by parameter: Use bracket notation ['...'] to pick a specific parameter (e.g., M0) across all satellites and time.
    # Select satellite G13
    nav.sel(sv='G13')
    
    # Pick parameter M0 across all satellites and time
    nav['M0']
  6. Analyze and save Xarray Datasets

    main

    Since GeoRinex returns xarray.Dataset objects, you can leverage high-performance big data operations. To speed up loading and conserve memory, it is recommended to use the use= option (e.g., use='E') when loading original RINEX files.

    You can save processed data to NetCDF4 for fast reloading and out-of-core processing using .to_netcdf().

    import georinex as gr
    
    # Load data
    obs = gr.load('my.rnx')
    
    # Save to NetCDF4 for fast future access
    obs.to_netcdf('process.nc', group='OBS')
  7. Install GeoRinex

    main

    You can install the latest stable release of GeoRinex via pip. For development, you can clone the repository and install it in editable mode.

    To verify your installation, run the included pytest suite.

    # Latest stable release
    pip install georinex
    
    # Current development version
    git clone https://github.com/geospace-code/georinex
    python -m pip install -e ./georinex
    
    # Selftest
    python -m pytest
  8. Read RINEX 2 or 3 OBS files

    main

    Use georinex.load() to read RINEX observation (OBS) files. This returns an xarray.Dataset containing the data. Because NaN is used as a filler value for non-observable data, it is common practice to use .dropna(dim='time', how='all') to clean the dataset.

    Note that valid fields depend on the satellite system and receiver capabilities.

    import georinex as gr
    obs = gr.load('tests/demo_MO.rnx')
    # Recommended: remove non-observable data
    obs = obs.dropna(dim='time', how='all')
  9. Optimize loading with measurement selection and indicators

    main

    You can speed up loading and reduce memory usage by specifying exactly what you need.

    Load specific measurements

    Use the meas argument in gr.load() to only read specific measurement codes.

    Load Signal and Loss of Lock indicators

    By default, SSI and LLI (loss of lock indicators) are not loaded. To include them, use the useindicators parameter (or the -useindicators CLI flag).

    # Load only specific measurements
    dat = gr.load('my.rnx', meas=['C1C', 'L1C'])
    
    # Load with indicators (SSI/LLI)
    # Note: Check documentation for specific parameter name if using API vs CLI
    obs = gr.load('my.rnx', useindicators=True)
  10. Get RINEX file time information

    main

    You can retrieve time information for RINEX files using either the CLI or the Python API.

    Using the CLI

    Use the georinex.gtime module to print the start time, stop time, and measurement interval for a file or multiple files.

    # For a single file
    python -m georinex.gtime ~/my.rnx
    
    # For all RINEX files in a directory
    python -m georinex.gtime ~/data *.rnx

    Using the Python API

    Use georinex.gettimes() to get a vector of datetime.datetime objects representing the Epoch / ToC (Time of Clock) in the RINEX file.

    import georinex as gr
    times = gr.gettimes('~/my.rnx')
  11. Plot RINEX observation data

    main

    You can plot RINEX data using matplotlib. Since the data is an xarray.Dataset, you can use the built-in .plot() method for convenience.

    import georinex as gr
    from matplotlib.pyplot import figure, show
    
    # Plot all satellites for measurement L1C
    ax = figure().gca()
    ax.plot(obs.time, obs['L1C'])
    show()
    
    # Plot a specific satellite's L1C pseudorange
    obs['L1C'].sel(sv='G13').dropna(dim='time', how='all').plot()
    show()