Overview

rads handles conventional nadir altimetry distributed through the Radar Altimeter Database System (RADS). RADS stores each mission as thousands of small pass-level NetCDF files, one per half-orbit. This package repackages those pass files into cycle NetCDFs and subsets a bounding box into one along-track NetCDF4 of detided SSHA.

/spray/rads/data/{mission}/{phase}/c{cycle}/{mission}p{pass}c{cycle}.nc

Scanning that many files is the bottleneck for downstream mapping and optimal interpolation. Cycle repack writes one regular NetCDF per mission / phase / cycle, with (pass, sample) dimensions and missing passes / unused sample slots filled. Regional subset writes one concatenated (obs,) table. Both reuse the same search, indexing, and time/bbox helpers, plus a demo SSHA map.

Missions are addressed by their RADS directory codes (j2 j3 3a 3b 6a, …) and phases by their letter subdirectories (a b c, …).

Installation & dependencies

Install the odsl distribution in editable mode from the repo root:

python -m pip install -e .            # core repackaging + subsetting
python -m pip install -e ".[plot]"    # adds cartopy for the demo map
  • Core deps (always installed): numpy, pandas, netCDF4. The repackaging and indexing paths need nothing more.
  • plot extra (cartopy): only demo_plot_gulf_america_ssha.py needs it. The demo degrades gracefully to a plain matplotlib axes if cartopy is absent.

Entry points & scripts

File Console script Purpose
repack_rads_cycles.py odsl-rads-repack Repackage pass files into one NetCDF per mission/phase/cycle.
subset_region.py odsl-rads-subset Subset all missions in a bbox to one along-track NetCDF4 (ssha − tide_internal).
utils.py — (library) RADS root/table constants, BBox, pass discovery/indexing, time & bbox filtering, subset_rads_*.
demo_plot_gulf_america_ssha.py — (run directly) Search + subset SSHA for a bbox/time window and save a PNG map.

Reusable logic lives in utils.py; the scripts stay thin (see ../README.md#conventions).

Usage

Repackage a range of Jason-3 cycles, phase c, using the curated core variables and rebuilding the pass index:

odsl-rads-repack \
    --missions j3 \
    --phases c \
    --cycles 500 501 510-520 \
    --out-dir /spray/rads/cycle_files \
    --refresh-index

Repackage several missions at once (defaults: --shape-mode mission, --variable-mode core, --index-source auto, --compression-level 4):

odsl-rads-repack --missions j2 j3 3a 3b 6a --out-dir /spray/rads/cycle_files

Write every 1-D time variable, keep float64, and unpack scaled variables to physical floats:

odsl-rads-repack --missions j3 --cycles 500 \
    --variable-mode all --keep-float64 --unpack-scaled

Smoke-test on the first two cycle groups only, using tables-only indexing:

odsl-rads-repack --missions j3 --index-source tables --limit-cycles 2

Subset every nadir mission over the Gulf of America into one NetCDF4. Output ssha is the RADS precomputed SLA (standard corrections already applied) minus tide_internal (HRET v8.1). --discover-passes learns intersecting pass numbers from the first hit cycle per mission/phase so a full-archive run does not open every global file:

odsl-rads-subset \
    --bbox -98 18 -80 31 \
    --out tmp/rads_gulf_america_ssha.nc \
    --discover-passes

Optional --start / --end / --missions / --passes restrict the extract. Ocean-only is the default (topo < 0); keep land with --allow-land. Samples (and whole older missions such as ERS / Geosat / Envisat / CryoSat-2 in this archive) without tide_internal are dropped so the file never mixes tided and detided SSHA.

Plot RADS SSHA over the Gulf of America for a date range (needs [plot]):

python rads/demo_plot_gulf_america_ssha.py \
    --start 2025-01-01 --end 2025-01-10 \
    --bbox -98 18 -80 31 \
    --out tmp/rads_gulf_america_ssha_20250101_20250110.png

Key odsl-rads-repack flags (see build_parser() for the full set):

  • --root / --tables-dir / --out-dir — RADS input root, .pas tables dir, output root.
  • --missions / --phases / --cycles — filters; cycles accept ints and A-B ranges.
  • --index-file / --refresh-index — index CSV path (default OUT_DIR/lookup_tables/rads_pass_index.csv) and rebuild toggle.
  • --index-source {auto,tables,netcdf} — build the index from .pas tables, NetCDF headers, or tables with NetCDF fallback (auto).
  • --shape-mode {mission,cycle} — fixed mission/phase dims for every cycle, or minimal per-cycle dims.
  • --variable-mode {core,all} / --variables … — curated core set, all 1-D time vars, or an explicit list.
  • --keep-float64 / --unpack-scaled — keep float64 instead of float32; unpack scale_factor/add_offset variables.
  • --compression-level 0-9 / --overwrite / --limit-cycles N.

Data layout / outputs

Output files are written under:

OUT_DIR/{mission}/{phase}/{mission}_{cycle:03d}_{start}_{end}.nc

Each cycle NetCDF (NETCDF4) has dimensions pass and sample, plus:

  • Coordinate / bookkeeping vars on (pass,): pass (RADS pass number), n_valid (valid samples per pass), pass_present (0/1 flag), source_file.
  • Data vars on (pass, sample): the selected core or all variables (time, lat, lon, ssha, flags, tide/tropo/MSS/MDT fields, …). time is always float64.
  • Global attrs: title, source, mission, phase, cycle_number, mission_name, time_coverage_start/end, history.

A run summary is written to OUT_DIR/repack_summary.csv, and the pass metadata index to OUT_DIR/lookup_tables/rads_pass_index.csv (reused on later runs unless --refresh-index).

Colocate reads rads.utils.DEFAULT_PASS_INDEX (/spray/rads/data/lookup_tables/rads_pass_index.csv) instead of scanning data/{sat}/{cycle}/. Refresh that table with odsl-colocate-refresh refresh --targets rads (or --refresh-index on a repack whose --out-dir is /spray/rads/data). The CSV carries pass times; bbox is applied when the NetCDF is opened.

The default core variable set:

time lat lon ssha flags surface_type dist_coast topo_srtm15plus topo_ace2
seaice_conc seaice_conc_era5 swh_ku sig0_ku wind_speed_alt
dry_tropo_era5 wet_tropo_era5 inv_bar_static_era5 tide_ocean_fes14
tide_load_fes14 tide_solid tide_pole mss_dtu21 mss_cnescls15 mdt_cnescls18

Conventions & notes

  • Packed variables preserved. Integer variables carrying scale_factor / add_offset keep their packed dtype, fill value, and scale metadata by default (readers decode on the fly). --unpack-scaled writes physical floats instead. Floats downcast to float32 unless --keep-float64.
  • --shape-mode mission with --cycles. The mission/phase pass axis and sample length are computed from the full selected mission/phase index, then only the requested cycles are written — so cycle files stay dimensionally aligned across a mission.
  • --limit-cycles semantics. A debugging guard that keeps only the first N cycle groups (groups[:N]). It is checked with is not None, so an explicit --limit-cycles 0 correctly writes nothing rather than being treated as "unlimited".
  • BBox dateline handling. utils.BBox (used by the demo and subset helpers) normalizes longitudes to [0,360) and tests membership by angular offset from the western edge, so boxes that cross the antimeridian (e.g. west=170, east=-170) work correctly. A full-globe span is detected when west == east.
  • .pas tables. --index-source auto/tables reads cycle, pass, start/end time, and sample count from lightweight /spray/rads/tables/*.pas files, avoiding opening every NetCDF. Mission/phase pairs without a clean table match fall back to NetCDF header reads.
  • Shared plotting. demo_plot_gulf_america_ssha.py draws basemap context via common.plotting.add_map_context(ax, bbox) rather than a local helper.
  • ../common — shared plotting (add_map_context) and swath→grid regridding.
  • ../colocate — matchups against DEFAULT_PASS_INDEX.
  • ../multi_altimeters — multi-altimeter optimal interpolation that consumes these repackaged RADS cycle files (alongside SWOT).
  • ../README.md — repo-wide conventions (CLI structure, bbox handling, /spray data roots, packed-variable preservation).