https://img.shields.io/badge/CNES_AVISO-Contribution-%20?color=grey&labelColor=blue

SWOT L3 KaRIn and Nadir Ocean Data Products

This tutorial will introduce you to some sample SWOT L3 data products and show you how to download these data from AVISO and perform basic plots using Python related libraries.

The Sea Level Anomaly is represented by the SSHA fields in L3 LR SSH products. These fields are described as follow:

SLA field

Calibrated

Edited

Filtered

ssha_unedited

X

ssha_unfiltered

X

X

ssha_filtered

X

X

X

Note

Required environment to run this notebook:

  • xarray

  • matplotlib+cartopy

  • altimetry_downloader_aviso: see documentation.

  • altimetry.io: available here.

Tutorial Objectives

  • Present SWOT sample L3 data products (Basic and Expert versions)

  • Download locally SWOT KaRIn (2D swath) and nadir (along-track) altimetry combined data using the altimetry_downloader_aviso

  • Show you how to query SWOT Sea Level Anomaly (SLA) data sets (nadir+swath, only nadir) using altimetry.io

  • How to visualise data using matplotlib

Import + code

[1]:
# Install Cartopy with mamba to avoid discrepancies
# ! mamba install -q -c conda-forge cartopy
[2]:
# Configure logging if you want more details
import logging
logging.basicConfig(level=logging.INFO)
[3]:
from pathlib import Path

import cartopy.crs as ccrs
import cartopy.feature as cft
import cartopy.mpl.geoaxes as cmplgeo
import cartopy.mpl.gridliner as cmplgrid
import matplotlib.pyplot as plt

%matplotlib inline

Parameters

Define a local filepath to download files

[4]:
output_dir= Path.home() / "TMP_DATA"
[5]:
cycle_number = 34
pass_number = 39
[6]:
# California
bbox = (233, 35, 237, 42)
localbox = [233, 237, 35, 42]

Download data using altimetry_downloader_aviso

[7]:
import altimetry_downloader_aviso as dl_aviso

Consult Aviso’s catalog

[8]:
cat = dl_aviso.summary()
INFO:altimetry_downloader_aviso.catalog_client.client:Fetching products from Aviso's catalog...
[9]:
for product in cat.products:
    print(f"{product.short_name}  {product.title}")
SWOT_L3_LR_WIND_WAVE_Extended  Wind & Wave product SWOT Level-3 WindWave - Extended
L4_exp_with_SWOT  Experimental Products: Multimission Gridded (with SWOT) Level-4 Sea Surface Heights and Velocities
SWOT_L3_LR_WIND_WAVE_Light  Wind & Wave product SWOT Level-3 WindWave - Light
SWOT_L3_LR_SSH_Unsmoothed  Altimetry product SWOT Level-3 Low Rate SSH - Unsmoothed
SWOT_L3_LR_SSH_Technical  Altimetry product SWOT Level-3 Low Rate SSH - Technical
SWOT_L2_LR_SSH_Expert  Altimetry product SWOT Level-2 KaRIn Low Rate SSH - Expert
SWOT_L3_LR_SSH_Expert  Altimetry product SWOT Level-3 Low Rate SSH - Expert
SWOT_L2_LR_SSH_Basic  Altimetry product SWOT Level-2 KaRIn Low Rate SSH - Basic
SWOT_L2_LR_SSH_WindWave  Altimetry product SWOT Level-2 KaRIn Low Rate SSH - WindWave
SWOT_L2_LR_SSH_Unsmoothed  Altimetry product SWOT Level-2 KaRIn Low Rate SSH - Unsmoothed
SWOT_L3_LR_SSH_Basic  Altimetry product SWOT Level-3 Low Rate SSH - Basic

Download basic half orbit

[10]:
dl_aviso.get(
    'SWOT_L3_LR_SSH_Basic',
    output_dir=output_dir,
    cycle_number=cycle_number,
    pass_number=pass_number,
)
INFO:altimetry_downloader_aviso.catalog_client.client:Fetching products from Aviso's catalog...
INFO:altimetry_downloader_aviso.catalog_client.granule_discoverer:Filtering SWOT_L3_LR_SSH_Basic product with filters {'cycle_number': 34, 'pass_number': 39}...
INFO:altimetry_downloader_aviso.core:1 files to download. 0 files already exist.
INFO:altimetry_downloader_aviso.tds_client:File /home/atonneau/TMP_DATA/SWOT_L3_LR_SSH_Basic_034_039_20250610T025623_20250610T034751_v3.0.nc downloaded.
[10]:
['/home/atonneau/TMP_DATA/SWOT_L3_LR_SSH_Basic_034_039_20250610T025623_20250610T034751_v3.0.nc']

Download expert half orbit

[11]:
dl_aviso.get(
    'SWOT_L3_LR_SSH_Expert',
    output_dir=output_dir,
    cycle_number=cycle_number,
    pass_number=pass_number,
)
INFO:altimetry_downloader_aviso.catalog_client.client:Fetching products from Aviso's catalog...
INFO:altimetry_downloader_aviso.catalog_client.granule_discoverer:Filtering SWOT_L3_LR_SSH_Expert product with filters {'cycle_number': 34, 'pass_number': 39}...
INFO:altimetry_downloader_aviso.core:1 files to download. 0 files already exist.
INFO:altimetry_downloader_aviso.tds_client:File /home/atonneau/TMP_DATA/SWOT_L3_LR_SSH_Expert_034_039_20250610T025623_20250610T034751_v3.0.nc downloaded.
[11]:
['/home/atonneau/TMP_DATA/SWOT_L3_LR_SSH_Expert_034_039_20250610T025623_20250610T034751_v3.0.nc']

Open data using altimetry.io

[12]:
from altimetry.io import AltimetryData, FileCollectionSource

Open data source

[13]:
alti_data = AltimetryData(
    source=FileCollectionSource(
        path=output_dir,
        ftype="SWOT_L3_LR_SSH",
        subset="Basic"
    ),
)
alti_data.query_orbit?

Query data

[14]:
ds_basic = alti_data.query_orbit(
    cycle_number=cycle_number,
    pass_number=pass_number
)
INFO:fcollections.core._readers:Files to read: 1

3. Basic product

This product contains two versions of SLA (ssha_unfiltered in the datasets). The ssha_filtered field is obtained by denoising the ssha_unfiltered field. The mean dynamic topography is also included in order to derive the absolute dynamic topography.

[15]:
[v for v in ds_basic.variables]
[15]:
['time',
 'mdt',
 'ssha_filtered',
 'ssha_unfiltered',
 'latitude',
 'longitude',
 'cycle_number',
 'pass_number']

3.1 Sea level anomalies

Let’s visualize SWOT KaRIn and Nadir data using cartopy. Adapt this code to visualize other variables or regions, or try importing another file.

[16]:
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(21, 12), subplot_kw=dict(projection=ccrs.PlateCarree()))
ax1.set_extent(localbox)
ax2.set_extent(localbox)

plot_kwargs = dict(
    x="longitude",
    y="latitude",
    cmap="Spectral_r",
    vmin=-0.2,
    vmax=0.2,
    cbar_kwargs={"shrink": 0.3},)

# SWOT KaRIn SLA plots
ds_basic.ssha_unfiltered.plot.pcolormesh(ax=ax1, **plot_kwargs)
ds_basic.ssha_filtered.plot.pcolormesh(ax=ax2, **plot_kwargs)

ax1.set_title("SLA unfiltered")
ax1.coastlines()
ax1.gridlines()
ax2.set_title("SLA filtered")
ax2.coastlines()
ax2.gridlines()
[16]:
<cartopy.mpl.gridliner.Gridliner at 0x7d40c31d7a50>
../_images/SWOT-Oceanography_ex_swot_l3_startup_32_1.png

4. Expert product

This product contains all the Basic fields, and additional fields that allow a deeper investigation by Expert users. This includes the corrections used for the SLA and the currents (absolute and relative) computed for the denoised SLA.

Open data source

[17]:
alti_data = AltimetryData(
    source=FileCollectionSource(
        path=output_dir,
        ftype="SWOT_L3_LR_SSH",
        subset="Expert"
    ),
)

Query data with half orbit with geographical selection

[18]:
ds_expert = alti_data.query_orbit(
    cycle_number=cycle_number,
    pass_number=pass_number,
    polygon=bbox
)
ds_expert
INFO:fcollections.implementations.optional._predicates:The bbox intersects with pass numbers (calval phase): [13, 26]
INFO:fcollections.implementations.optional._predicates:The bbox intersects with pass numbers (science phase): [11, 24, 39, 52, 67, 302, 317, 330, 345, 358, 373, 580]
INFO:fcollections.core._readers:Files to read: 1
INFO:fcollections.implementations.optional._area_selectors:Size of the dataset matching the bbox: {'num_lines': 410, 'num_pixels': 69}
[18]:
<xarray.Dataset> Size: 4MB
Dimensions:               (num_lines: 410, num_pixels: 69)
Coordinates:
    time                  (num_lines) datetime64[ns] 3kB dask.array<chunksize=(410,), meta=np.ndarray>
    latitude              (num_lines, num_pixels) float64 226kB dask.array<chunksize=(410, 69), meta=np.ndarray>
    longitude             (num_lines, num_pixels) float64 226kB dask.array<chunksize=(410, 69), meta=np.ndarray>
Dimensions without coordinates: num_lines, num_pixels
Data variables: (12/20)
    calibration           (num_lines, num_pixels) float64 226kB dask.array<chunksize=(410, 69), meta=np.ndarray>
    dac                   (num_lines, num_pixels) float64 226kB dask.array<chunksize=(410, 69), meta=np.ndarray>
    internal_tide         (num_lines, num_pixels) float64 226kB dask.array<chunksize=(410, 69), meta=np.ndarray>
    mdt                   (num_lines, num_pixels) float64 226kB dask.array<chunksize=(410, 69), meta=np.ndarray>
    mss                   (num_lines, num_pixels) float64 226kB dask.array<chunksize=(410, 69), meta=np.ndarray>
    ocean_tide            (num_lines, num_pixels) float64 226kB dask.array<chunksize=(410, 69), meta=np.ndarray>
    ...                    ...
    vgos_filtered         (num_lines, num_pixels) float64 226kB dask.array<chunksize=(410, 69), meta=np.ndarray>
    vgosa_filtered        (num_lines, num_pixels) float64 226kB dask.array<chunksize=(410, 69), meta=np.ndarray>
    vgosa_unfiltered      (num_lines, num_pixels) float64 226kB dask.array<chunksize=(410, 69), meta=np.ndarray>
    cross_track_distance  (num_pixels) float64 552B dask.array<chunksize=(69,), meta=np.ndarray>
    cycle_number          (num_lines) uint16 820B 34 34 34 34 34 ... 34 34 34 34
    pass_number           (num_lines) uint16 820B 39 39 39 39 39 ... 39 39 39 39
Attributes: (12/43)
    Conventions:                     CF-1.9
    Metadata_Conventions:            Unidata Dataset Discovery v1.0
    cdm_data_type:                   Swath
    comment:                         Sea Surface Height measured by Altimetry
    data_used:                       SWOT KaRIn L2_LR_SSH PGC0/PIC0/PIC2/PID0...
    doi:                             https://doi.org/10.24400/527896/A01-2023...
    ...                              ...
    geospatial_lon_max:              311.639351
    date_modified:                   2025-11-24T16:35:32Z
    history:                         2025-11-24T16:35:32Z: Created by DUACS K...
    date_created:                    2025-11-24T16:35:32Z
    date_issued:                     2025-11-24T16:35:32Z
    temporality:                     forward
[19]:
[v for v in ds_expert.variables if v not in ds_basic]
[19]:
['calibration',
 'dac',
 'internal_tide',
 'mss',
 'ocean_tide',
 'quality_flag',
 'sigma0',
 'ssha_unedited',
 'ugos_filtered',
 'ugosa_filtered',
 'ugosa_unfiltered',
 'vgos_filtered',
 'vgosa_filtered',
 'vgosa_unfiltered',
 'cross_track_distance']

4.1 Sea level anomalies

Let’s visualize SWOT KaRIn abd Nadir data using cartopy. Adapt this code to visualize other variables or regions, or try importing another file.

[20]:
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(21, 12), subplot_kw=dict(projection=ccrs.PlateCarree()))

plot_kwargs = dict(
    x="longitude",
    y="latitude",
    cmap="Spectral_r",
    vmin=-0.2,
    vmax=0.2,
    cbar_kwargs={"shrink": 0.3},)

# SWOT KaRIn SLA plots
ds_expert.ssha_unfiltered.plot.pcolormesh(ax=ax1, **plot_kwargs)
ds_expert.ssha_filtered.plot.pcolormesh(ax=ax2, **plot_kwargs)
ds_expert.ssha_unedited.plot.pcolormesh(ax=ax3, **plot_kwargs)

ax1.set_title("SLA unfiltered")
ax1.coastlines()
ax1.gridlines()
ax2.set_title("SLA filtered")
ax2.coastlines()
ax2.gridlines()
ax3.set_title("SLA unedited")
ax3.coastlines()
ax3.gridlines()
[20]:
<cartopy.mpl.gridliner.Gridliner at 0x7d40c13e4c10>
../_images/SWOT-Oceanography_ex_swot_l3_startup_41_1.png

4.2 Sigma 0

[21]:
fig, ax = plt.subplots(figsize=(8, 8), subplot_kw=dict(projection=ccrs.PlateCarree()))
# ax.set_extent(localbox)

plot_kwargs = dict(
    x="longitude",
    y="latitude",
    cmap="gray_r",
    vmin=0,
    vmax=30,
    cbar_kwargs={"shrink": 0.3},)

# SWOT KaRIn SLA plots
ds_expert.sigma0.plot.pcolormesh(ax=ax, **plot_kwargs)

ax.set_title("Sigma 0")
ax.coastlines()
ax.gridlines()
[21]:
<cartopy.mpl.gridliner.Gridliner at 0x7d40c1363ad0>
../_images/SWOT-Oceanography_ex_swot_l3_startup_43_1.png