CMEMS SSH Along-Track Converter

Overview

This converter ingests Copernicus Marine Environment Monitoring Service (CMEMS) along-track sea surface height (SSH) observations and converts them into a DART obs_seq file.

The supported product is:

  • Global Ocean Along Track L3 Sea Surface Heights NRT (Product ID: SEALEVEL_GLO_PHY_L3_NRT_008_044)

The converter reads CSV files exported from CMEMS and extracts filtered sea level anomaly (SLA) observations for assimilation into ocean models such as ROMS.

The resulting observations are assigned the DART type: SATELLITE_SSH. The observations in the sequence file are in units of meters.

Data Description

The converter uses the following variable: SLA_FILTERED

This variable represents low-pass filtered sea level anomaly, including corrections for dynamic atmospheric correction (DAC), ocean tides, internal tides, and long-wavelength errors. Compared to SLA_UNFILTERED, this field is smoother, less noisy, and more representative of mesoscale variability. This makes it more appropriate for comparison with model sea surface height (e.g., ROMS zeta).

Observation Error

The converter assigns a uniform observation error standard deviation to all SSH observations. The error value is specified by the user through the converter namelist and is written to the output obs_seq file as observation error variance.

Optional Post-Processing

Additional filtering and depth-dependent error adjustment can be performed after the converter is run using the utility script:

models/ROMS_Rutgers/preprocess_ocean_obs.py

This script is intended for model-specific preprocessing of ocean observations prior to assimilation. It can:

  • remove observations located in shallow-water regions,

  • apply depth-dependent observation error models,

  • process only selected observation types,

  • preserve all other observation types unchanged.

The script currently uses ROMS bathymetry and land masks from a ROMS restart or history file.

For SSH observations, a commonly used workflow is to remove observations in water shallower than 200 m and increase the observation error in coastal regions where representativeness errors and unresolved processes are larger.

The depth-dependent error model is:

sigma = sigma_min + (sigma_max - sigma_min) * exp(-h / h0)

where:

  • sigma_min: deep-ocean observation error standard deviation,

  • sigma_max: shallow-water observation error standard deviation,

  • h: local bathymetric depth (m),

  • h0: transition depth scale (m).

Example usage:

python preprocess_ocean_obs.py obs_seq.all obs_seq.trim \
    --roms-file roms_hist.nc \
    --obs-type SATELLITE_SSH

Typical output:

Reading obs_seq:  obs_seq.all
Reading ROMS grid: roms_hist.nc

Obs types in file: ['BOTTLE_TEMPERATURE', 'CTD_TEMPERATURE',
'FLOAT_TEMPERATURE', 'MOORING_TEMPERATURE',
'SATELLITE_SSH', 'XBT_TEMPERATURE']

Input obs (SATELLITE_SSH): 3042
Looking up bathymetric depths ...

Summary (SATELLITE_SSH)
  Kept:    2305  (depth > 200 m)
  Removed: 737
  Depth range kept: 205.0 – 5000.0 m
  Error model: sigma = 0.04 + (0.08 - 0.04) * exp(-h / 500.0)

  Other obs types kept unchanged: 571

  Wrote: obs_seq.trim

Time Handling

Observation times are read from ISO-formatted strings, for example:

2026-04-16T08:43:54.000Z

These are converted to DART time_type using the Gregorian calendar.

Usage

  1. Prepare a list of input CSV files and place them in a text file, for instance ssh_list.txt

  2. Configure the namelist in input.nml:

&cmems_ssh_to_obs_nml
   file_list        = 'ssh_file_list.txt'
   file_out         = 'obs_seq.ssh'
   avg_obs_per_file = 500000
   obs_error_sd     = 0.04
   debug            = .true.
/

Namelist item

Type

Default Values

Description

file_list

character(len=256)

'' (empty string)

Path to a text file containing a list of input CSV files, one filename per line.

file_out

character(len=256)

'obs_seq.ssh'

Name of the DART observation sequence output file. If the file already exists, it will be replaced.

avg_obs_per_file

integer

500000

Estimated average number of observations per input file. Used to pre-allocate sequence memory efficiently.

obs_error_sd

real(r8)

0.04

Uniform observation error standard deviation (meters) assigned to all SSH observations.

debug

logical

.true.

If true, prints diagnostic output including sample observations and processing information.

  1. Run the converter: ./cmems_ssh_to_obs

  2. Output: The resulting observation sequence file is stored in obs_seq.ssh

When debug is turned on, the progress of the converter can be monitored which would look similar to the following:

 Input file: #2 ../data/obs_ssh_2.csv

  CSV Header Fields (10 columns):
    1  parameter
    2  platformId
    3  platformType
    4  time
    5  longitude
    6  latitude
    7  depth
    8  pressure
    9  value
   10  valueQc

   * obs #  1, lat: -14.2924, lon: 127.8070, SSH: 0.2940, QC: 0, date: 2026 Apr 14 19:26:36
   * obs #  2, lat: -14.2351, lon: 127.8010, SSH: 0.2820, QC: 0, date: 2026 Apr 14 19:26:37
   * obs #  3, lat: -14.1778, lon: 127.7949, SSH: 0.2690, QC: 0, date: 2026 Apr 14 19:26:38
   * obs #  4, lat: -14.1206, lon: 127.7888, SSH: 0.2560, QC: 0, date: 2026 Apr 14 19:26:39
   * obs #  5, lat: -14.0633, lon: 127.7827, SSH: 0.2420, QC: 0, date: 2026 Apr 14 19:26:40
   * obs #  6, lat: -14.0060, lon: 127.7766, SSH: 0.2280, QC: 0, date: 2026 Apr 14 19:26:41
   * obs #  7, lat: -13.9487, lon: 127.7705, SSH: 0.2130, QC: 0, date: 2026 Apr 14 19:26:42
   * obs #  8, lat: -13.8915, lon: 127.7645, SSH: 0.2000, QC: 0, date: 2026 Apr 14 19:26:43
   * obs #  9, lat: -13.8342, lon: 127.7584, SSH: 0.1910, QC: 0, date: 2026 Apr 14 19:26:43
   * obs # 10, lat: -13.7769, lon: 127.7523, SSH: 0.1850, QC: 0, date: 2026 Apr 14 19:26:44

> Ready to write 3042 observations:
  write_obs_seq  opening formatted observation sequence file "obs_seq.ssh"
  write_obs_seq  closed observation sequence file "obs_seq.ssh"
  cmems_ssh_to_obs Finished successfully.

References