Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Ocean Data Analysis with Copernicus Marine Service and Argo Floats
Retrieve, process, and visualize ocean physical and biogeochemical data using
the Copernicus Marine Service (CMEMS) Python client, Argo float profiles, and
the TEOS-10 Gibbs SeaWater (GSW) toolbox.
When to Use This Skill
You need sea surface temperature, salinity, or current fields for a specific
region and time period from the Copernicus Marine Service catalog.
You want to download individual Argo float profiles and compute derived
quantities such as mixed layer depth (MLD) or potential density.
You need to produce T-S diagrams, eddy kinetic energy (EKE) maps, or
mixed-layer climatologies for research or operational purposes.
You are building ocean-climate pipelines that combine model output with
in-situ observations.
Background & Key Concepts
Copernicus Marine Service (CMEMS)
The Copernicus Marine Environment Monitoring Service provides free,
quality-controlled ocean datasets spanning physical, biogeochemical, and sea-ice
variables. Products include reanalysis, near-real-time, and forecast datasets.
The copernicusmarine Python package (v1+) replaced the legacy motuclient
and ftplib workflows.
Argo Float Program
Argo is a global array of ~4000 autonomous profiling floats that measure
temperature and salinity from 2000 m to the surface every ~10 days. Data are
freely available via GDAC servers (Ifremer / BODC) and through the
copernicusmarine catalog.
TEOS-10 / GSW Toolbox
The Thermodynamic Equation of Seawater 2010 (TEOS-10) defines Absolute
Salinity (SA) and Conservative Temperature (CT) as the preferred variables.
The gsw Python library converts Practical Salinity and in-situ temperature to
TEOS-10 variables and computes derived quantities such as potential density,
buoyancy frequency, and mixed layer depth.
Mixed Layer Depth (MLD)
MLD is commonly estimated using a density threshold criterion: the depth at
which potential density exceeds the surface value by 0.03 kg/m³ (de Boyer
Montégut et al., 2004).
Eddy Kinetic Energy (EKE)
EKE quantifies mesoscale variability: EKE = 0.5 * (u'^2 + v'^2), where u' and
v' are anomalies of eastward and northward geostrophic currents relative to a
long-term mean.
import os
import copernicusmarine as cm
username = os.getenv("COPERNICUSMARINE_USERNAME", "")
password = os.getenv("COPERNICUSMARINE_PASSWORD", "")
# Verify login works
cm.login(username=username, password=password, overwrite_configuration_file=True)
Core Workflow
Step 1 – Browse the Catalog and Download SST Data
import copernicusmarine as cm
import xarray as xr
# List available datasets matching a keyword
catalog = cm.describe(contains=["SST", "Mediterranean"])
for entry in catalog.products[:5]:
print(entry.product_id, "-", entry.title)
# Download a subset of the CMEMS global SST L4 product
ds = cm.open_dataset(
dataset_id="cmems_obs-sst_glo_phy_l4_my_0.25deg",
variables=["analysed_sst", "analysis_error"],
minimum_longitude=-20.0,
maximum_longitude=40.0,
minimum_latitude=25.0,
maximum_latitude=50.0,
start_datetime="2023-01-01T00:00:00",
end_datetime="2023-03-31T23:59:59",
)
print(ds)
# Convert from Kelvin to Celsius
ds["sst_celsius"] = ds["analysed_sst"] - 273.15
ds["sst_celsius"].attrs["units"] = "degC"
Step 2 – Download Argo Float Profiles and Compute MLD
import gsw
import numpy as np
import xarray as xr
import copernicusmarine as cm
# Download Argo BGC profiles for the North Atlantic (float WMO 6902880)
argo = cm.open_dataset(
dataset_id="cmems_obs-ins_glo_phy-temp-sal_nrt_argo_P1D-m",
variables=["TEMP", "PSAL", "PRES", "LATITUDE", "LONGITUDE", "TIME"],
minimum_longitude=-40.0,
maximum_longitude=-20.0,
minimum_latitude=40.0,
maximum_latitude=60.0,
start_datetime="2023-06-01T00:00:00",
end_datetime="2023-08-31T23:59:59",
)
defcompute_mld(temp, psal, pres, lat, threshold=0.03):
"""
Compute mixed layer depth using a density threshold criterion.
Parameters
----------
temp : array-like, in-situ temperature (ITS-90, °C)
psal : array-like, Practical Salinity (PSS-78)
pres : array-like, sea pressure (dbar)
lat : float, latitude (degrees N)
threshold : float, density difference criterion (kg/m³), default 0.03
Returns
-------
mld : float, mixed layer depth (m)
"""
SA = gsw.SA_from_SP(psal, pres, 0.0, lat)
CT = gsw.CT_from_t(SA, temp, pres)
sigma0 = gsw.sigma0(SA, CT) # potential density anomaly (kg/m³)# Reference density at shallowest valid level
valid = np.isfinite(sigma0)
if valid.sum() < 3:
return np.nan
ref_density = sigma0[valid][0]
# Find first depth where density exceeds reference + threshold
exceeds = np.where((sigma0 - ref_density) > threshold)[0]
iflen(exceeds) == 0:
returnfloat(pres[valid][-1]) # whole profile is mixedreturnfloat(pres[exceeds[0]])
# Apply to each profile
mld_values = []
for i inrange(min(50, argo.dims.get("N_PROF", 0))):
profile = argo.isel(N_PROF=i)
mld = compute_mld(
profile["TEMP"].values,
profile["PSAL"].values,
profile["PRES"].values,
float(profile["LATITUDE"].values),
)
mld_values.append(mld)
print(f"Mean MLD (N=50 profiles): {np.nanmean(mld_values):.1f} dbar")
Step 3 – Compute Eddy Kinetic Energy from Altimetry
import copernicusmarine as cm
import numpy as np
import xarray as xr
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
# Download gridded surface current anomalies (AVISO altimetry)
alt = cm.open_dataset(
dataset_id="cmems_obs-sl_glo_phy-ssh_my_allsat-l4-duacs-0.25deg_P1D",
variables=["ugosa", "vgosa"], # geostrophic current anomalies
minimum_longitude=-80.0,
maximum_longitude=-40.0,
minimum_latitude=25.0,
maximum_latitude=55.0,
start_datetime="2023-01-01T00:00:00",
end_datetime="2023-12-31T23:59:59",
)
# Compute time-mean EKE (m²/s²)
eke = 0.5 * (alt["ugosa"] ** 2 + alt["vgosa"] ** 2)
eke_mean = eke.mean(dim="time")
# Plot
fig, ax = plt.subplots(
subplot_kw={"projection": ccrs.PlateCarree()}, figsize=(10, 7)
)
ax.add_feature(cfeature.LAND, facecolor="lightgray")
ax.add_feature(cfeature.COASTLINE, linewidth=0.5)
ax.gridlines(draw_labels=True, linewidth=0.3, linestyle="--")
pcm = ax.pcolormesh(
eke_mean.longitude,
eke_mean.latitude,
eke_mean.values * 1e4, # convert to cm²/s²
cmap="plasma",
transform=ccrs.PlateCarree(),
vmin=0,
vmax=500,
)
plt.colorbar(pcm, ax=ax, label="EKE (cm²/s²)", shrink=0.8)
ax.set_title("Annual Mean Eddy Kinetic Energy – North Atlantic 2023")
plt.tight_layout()
plt.savefig("eke_north_atlantic_2023.png", dpi=150)
plt.show()