Every regional SWOT analysis starts with the same question: which passes cross my box, and when? This tutorial shows the two ways to answer it:

  1. the pass-footprint index — instant, offline, opens no data files;
  2. odsl-swot-swath-map — discovers passes for a time window via NASA CMR and plots the actual data in one command.

Prerequisites: tutorial 1. The running example is the Gulf of America box -98 18 -80 31.


1. Why footprints work

SWOT flies a fixed 21-day repeat orbit, so a pass number always traces the same ground footprint (tutorial 1). That means pass geometry can be computed once, from a single complete reference cycle, and reused forever.

A whole pass is a long, thin, diagonal ribbon — its overall bounding box is nearly useless for regional queries. So the index instead stores the pass cut into ~120 km along-track segments, each with a tight, near-square bounding box plus its along-track time offset. A plain bbox test against the segments prunes ~90% of passes without opening a single granule, and the precise repeat period turns each segment's time offset into a predicted UTC time for every cycle, past and future.

2. Build the index (once)

odsl-swot-footprints

This reads the true swath lat/lon/time from one complete 584-pass reference cycle (default: cycle 2) under /spray/swot/versionD and writes a GeoParquet index (~96k segments) to:

/spray/swot/versionD/footprints/swot_pass_segments_science.parquet

On the lab server, check whether that file already exists first — if it does, someone has built it and you can go straight to querying. Building takes a while (it reads a whole cycle) but only ever needs to happen once per data version. Use --root, --ref-cycle, or --out to override the defaults.

3. Query the index from Python

All queries are functions in swot.pass_footprints and open no data files — they run in milliseconds.

from swot.pass_footprints import candidate_passes, candidate_cycle_passes

bbox = (-98, 18, -80, 31)                      # west, south, east, north

# Which pass numbers ever cross the box?
print(sorted(candidate_passes(bbox, "2024-06-01", "2024-06-15")))

# Which (cycle, pass) pairs fly over it in a time window?
for cycle, pass_num in sorted(candidate_cycle_passes(bbox, "2024-06-01", "2024-06-15")):
    print(f"cycle {cycle:3d}  pass {pass_num:3d}")

For predicted overflight times (e.g. to plan a field campaign or match in-situ data), use predicted_segments, which returns a pandas DataFrame with cycle, pass, and predicted start/end times per segment:

from swot.pass_footprints import predicted_segments

seg = predicted_segments(bbox, "2024-06-01", "2024-06-15")
print(seg[["cycle", "pass", "pred_time_start", "pred_time_end"]].drop_duplicates())

The results are candidates from bbox intersection — a pass whose segment bbox clips the corner of your box may contribute few pixels. The next step (plotting, subsetting) confirms actual coverage. This same index is what the colocate package uses internally to skip passes that miss a region.

4. See the data: odsl-swot-swath-map

odsl-swot-swath-map scatter-plots raw swath pixels on a map. It has two selection modes.

Time-window discovery — give it a window and a box, and it finds the passes itself (via a CMR query, so it needs network):

odsl-swot-swath-map --start 2024-06-01 --end 2024-06-03 \
    --bbox -98 18 -80 31 \
    --output ~/plots/gulf_swaths.png

Explicit passes — plot exactly the cycle:pass pairs you name (e.g. the ones the footprint query returned; zero-padding optional):

odsl-swot-swath-map --cycle-pass 20:013 20:026 \
    --bbox -98 18 -80 31 \
    --variable ssha_karin_2 \
    --output ~/plots/gulf_pass13_26.png

Useful options:

  • --variable — anything in the granule (default ssha_karin_2; sig0 variables automatically get a gray colormap and their own quality flag).
  • --max-quality — quality-flag cutoff (default 2; pixels with a higher flag are dropped).
  • --gradient — plot the gradient magnitude instead of the field, which makes fronts and internal waves pop.
  • --product-type Unsmoothed — use the native-resolution product (both swath sides are loaded).
  • --vmin/--vmax, --cmap, --point-size, --figsize, --dpi — cosmetics.

The output is one combined map (--output is required) with all requested passes overlaid and coastlines clipped to your box.

Troubleshooting

  • candidate_cycle_passes returns an empty set — check the bbox order (west, south, east, north) and that your time window overlaps the science phase (mid-2023 onward). The index only covers the science orbit.
  • Footprint file not found — the index hasn't been built on this data root yet; run odsl-swot-footprints (section 2).
  • --start/--end mode finds passes but the plot is empty — the granules for those passes may not be downloaded yet; see tutorial 2. Explicit --cycle-pass mode reads only local files.

Next: Tutorial 4 — Subsetting a pass into a cube.