Harvest a regional, time-windowed subset from eleven /spray observation
archives — SWOT, RADS, AVISO L4, Argo, drifters, gliders, ICESat-2, in-situ
wind, PACE, SNPP SST, and GOES ABI SST — into one HDF5 file (netCDF4 with nested groups;
readable by both xarray(group=…) and h5py). Unlike the multi-altimeter OI
driver — which flattens every source to scattered points — this tool
preserves each source's native data structure.
Console script: odsl-super-subsetter (super_subsetter/subset.py).
Installation & dependencies
Ships with the odsl distribution. Core deps (numpy, pandas, xarray, netCDF4,
scipy, pyproj, …) are always installed:
python -m pip install -e "." # or ".[all]"
Layout
| Module | Purpose |
|---|---|
subset.py |
CLI / main() for odsl-super-subsetter: orchestrates the run and writes the HDF5 + summary. |
utils.py |
Native-structure subset core: AVISO L4 grid, SWOT swath slabs, RADS along-track profiles, and the subset_observations orchestrator. |
sources.py |
Per-source native-structure subsetters for the non-altimetry archives (argo, drifter, glider, icesat2, wind, pace, snpp, geos). |
vars_config.py |
Variable-selection catalogs, template writer, and +/- markdown parser. |
Usage
odsl-super-subsetter \
--start 2023-03-25 --end 2023-03-31 \
--bbox -70 30 -50 45 \
--sources rads aviso argo drifter glider \
--out tmp/subset.h5
Output layout (one group per source, sub-group per platform/pass/granule):
subset.h5
├─ /swot/cycle###_pass### native 2-D swath (num_lines × num_pixels)
├─ /rads/<mission>_c###_p#### along-track profile (obs)
├─ /aviso_l4 gridded L4 map (time × latitude × longitude)
├─ /argo/<dac>_<wmo> profile stack (N_PROF × N_LEVELS)
├─ /drifter/<id> trajectory (obs)
├─ /glider/<deployment> trajectory (row)
├─ /icesat2/<granule> along-track segments (obs, all beams stacked)
├─ /wind/<family>_<station> station time series (obs)
├─ /pace/<granule> native 2-D swath (number_of_lines × pixels_per_line)
├─ /snpp/viirs_<stamp> native 2-D L2P swath (nj × ni)
└─ /geos/goes_<stamp> native 2-D GOES ABI L2P swath (nj × ni)
Variable selection — which variables each product contributes is controlled
by an editable markdown config with +/- markers:
# 1. write the per-product variable lists (inspecting one sample file per archive)
odsl-super-subsetter --init-vars-config subset_variables.md
# 2. edit the +/- markers, then run with it
odsl-super-subsetter --vars-config subset_variables.md --start … --bbox … --sources …
Without a config, built-in essentials-with-uncertainties defaults apply (e.g.
SWOT ssha_karin+ssha_karin_2 with _qual flags and ssh_karin_uncert; Argo
PRES/TEMP/PSAL with _ADJUSTED/_ADJUSTED_ERROR/_QC; SNPP SST with
sses_bias/sses_standard_deviation). Per-product --<product>-vars flags
override both. Coordinates/time/positions are always kept.
Behavior notes
- Swath sources (SWOT / PACE / SNPP / GOES) keep the full cross-track width; only the along-track extent is clipped to the bbox (SWOT by the monotonic nadir-latitude band; PACE/SNPP/GOES by the rows whose swath touches the bbox). Slabs therefore extend a little past the bbox on purpose — the original swath geometry is retained.
- SWOT SSHA is stored corrected:
ssha_karinandssha_karin_2each haveheight_cor_xover+internal_tide_hretadded back (group attrs record it; disable with--no-swot-xover/--no-swot-internal-tide). - Search reuses the colocation indices (argo profile index, drifter/glider
footprints, ICESat-2/PACE/SNPP/GOES granule footprints, RADS pass-index CSV,
AVISO L4 daily-map parquet, wind station footprints — see
odsl-colocate-refresh); PACE falls back to a date-tree scan when the footprint index doesn't cover the window. ICESat-2 reads the analysis-readypolar-segmentsparquet. - Sources with no data in the window are logged and skipped, never fatal (the archives don't fully overlap: AVISO L4 is early 2023, SWOT science data begins 2023-07-26, SNPP is May–Jul 2023, PACE begins 2024; NDBC wind rows carry no positions and are skipped with a warning).
--max-files Ncaps each source at N produced groups (not files inspected).- A markdown data summary is written next to the HDF5 file
(
<out>.summary.md): run parameters, the AVISO per-variable table, and one table per source (group, shape, time span, lon/lat coverage, NaN-safe stats of a representative variable). Override with--summary PATH, disable with--no-summary.
Useful flags: --sources {swot,rads,aviso,argo,drifter,glider,icesat2,wind,pace,snpp,geos,all},
--rads-missions j2 j3 3a, --icesat2-products ATL07 ATL10,
--pace-products bgc iop, --allow-land, --max-sea-ice-conc,
--no-swot-nadir-prefilter, per-source roots (--drifter-root, --snpp-root,
--geos-root, …).
Longitudes accept -180..180 or 0..360 and are preserved as -180..180 on output
when the bbox is given that way. A single SWOT granule can set the window via
--swot-file <name> --delta-t-days 2 instead of --start/--end.
Tests
pytest super_subsetter/tests
Related
../multi_altimeters— multi-altimeter OI mapping & point-vortex SSH; sharesmulti_altimeters/utils.py(BBox, longitude/bbox helpers, the SWOT/RADS search index used for broad-phase discovery).../swot— SWOT L2 LR SSH Expert loading (swot/utils.py).../rads— RADS nadir altimetry loading and indexing (rads/utils.py).../common/DATA_PATHS.md— per-dataset/spraylayout (globs, var names, lon conventions, coverage).../README.md— repo-wide conventions (CLI structure, bbox/longitude, data roots, extras).