tracmass.seagrid#

Retrieve and store daily ocean reanalysis data from Mercator Ocean.

tracmass.seagrid.glorys.mask_fill(da)[source]#

Replace the fill values (land) in a GLORYS variable (lazy).

Masked points hold the fill value: no flow through land (velocities uvel / vvel / wvel → 0); tracers have no land value (→ NaN).

Parameters:

da (xr.DataArray) – A variable from open_dataset(), named by its key ("uvel", "temp", …).

Returns:

xr.DataArray – Same shape and Dask chunks.

tracmass.seagrid.glorys.datadir(dtm='2020-01-01')[source]#

Return the local data directory for a given date, creating it if needed.

Parameters:

dtm (str or datetime-like) – Date string or datetime-like object.

Returns:

pathlib.Path – Path to the year-specific data directory.

tracmass.seagrid.glorys.filename(dtm='2020-01-01', data_var='uvel')[source]#

Build the Zarr filename for a given dat and variable.

Parameters:
  • dtm (str or datetime-like) – Date string or datetime-like object.

  • data_var (str) – Variable key (one of ‘uvel’, ‘vvel’, ‘wvel’, ‘temp’, ‘salt’).

Returns:

str – Filename string in the form GLORYS12V1_<date>_grid<X>.zarr.

tracmass.seagrid.glorys.retrieve(dtm='2020-01-01', data_var='uvel', force=False)[source]#

Download a single daily field from the Mercator THREDDS server and save it as Zarr.

Opens the remote dataset via OPeNDAP, selects the time step closest to dtm, and writes the result to a local Zarr store.

Parameters:
  • dtm (str or datetime-like) – Date string or datetime-like object for the desired time step.

  • data_var (str) – Variable key (one of ‘uvel’, ‘vvel’, ‘wvel’, ‘temp’, ‘salt’).

  • force (bool) – If True, re-download the file even if it already exists locally.

tracmass.seagrid.glorys.landmask(k=1)[source]#

GLORYS12 land mask on the T-cells of grid_definition().

Parameters:

k (int, optional) – 1-based model level. Default 1 (surface): land is kmt == 0. Deeper, the sea floor counts as land too (kmt < k).

Returns:

xr.DataArray – bool (y, x), True on land, with lon / lat coordinates. See tracmass.seagrid.coast.landmask().

Return type:

DataArray

tracmass.seagrid.glorys.distance_to_land(k=1)[source]#

Distance (km) from each GLORYS12 T-cell centre to the nearest land cell.

Parameters:

k (int, optional) – 1-based model level whose land mask is used (see landmask()). Default 1 (surface).

Returns:

xr.DataArray – float32 (y, x) great-circle distance in km, 0 on land, with lon / lat coordinates. See tracmass.seagrid.coast.distance_to_land().

Return type:

DataArray

tracmass.seagrid.glorys.open_dataset(dtm='2020-01-01', data_var=None, force=False, dask=True, mask=True)[source]#

Open a mercator dataset, downloading it first if necessary.

Parameters:
  • dtm (str or datetime-like) – Date string or datetime-like object for the desired time step.

  • data_var (str) – Variable key (one of ‘uvel’, ‘vvel’, ‘wvel’, ‘temp’, ‘salt’).

  • force (bool) – If True, re-download the file even if it already exists locally.

  • mask (bool, optional) – Replace fill values (land) with 0 for velocities and NaN for tracers. Default True. False leaves them in, for callers that first cut out a region and then mask just that with mask_fill() (masking a whole Zarr chunk to keep a small part of it is several times slower).

Returns:

xarray.Dataset – Dataset containing the requested variable for the given date.

tracmass.seagrid.glorys.rechunk_wvel(dtm1, dtm2=None, depth_chunk=10, path=None)[source]#

Rewrite cached wvel Zarr stores with depth_chunk-level chunks.

wvel stores downloaded before 2026-10-08 hold each 1000 x 1000 tile as one 50-level chunk (the download chunked deptht but wvel is on depthw), so reading a few levels decompresses all 50 in one thread. The x/y chunks are kept. Each store is written next to the original, checked to hold identical values, and only then swapped in; stores that already have depth_chunk levels per chunk are skipped.

Do not run it on days a tracking run is reading at the same time. A run opens each day’s store (and its chunk layout) a window before it reads the data; if the store is swapped in between, the read fails with cannot reshape array of size 10000000 into shape (50,1000,1000). A run is usually faster than the rechunk, so a run that starts behind it catches up. Rechunk first, or rechunk days the run has already passed.

Parameters:
  • dtm1 (str or datetime-like) – First day.

  • dtm2 (str or datetime-like or None, optional) – Last day (inclusive). Default: only dtm1.

  • depth_chunk (int, optional) – Levels per chunk. Default 10, as uvel / vvel.

  • path (str or pathlib.Path or None, optional) – Rechunk this one store instead of the cached wvel of dtm1 .. dtm2 (for testing on a copy).

Returns:

list of pathlib.Path – The stores that were rewritten.

Raises:

RuntimeError – If a rewritten store does not match its original; the original is then left untouched.

Return type:

list

Examples

>>> rechunk_wvel("2010-06-01", "2011-06-01")
tracmass.seagrid.glorys.open_dataarray(dtm='2020-01-01', data_var='uvel', force=False, mask=True)[source]#

Open a mercator dataarray, downloading it first if necessary.

Parameters:
  • dtm (str or datetime-like) – Date string or datetime-like object for the desired time step.

  • data_var (str) – Variable key (one of ‘uvel’, ‘vvel’, ‘wvel’, ‘temp’, ‘salt’).

  • force (bool) – If True, re-download the file even if it already exists locally.

  • mask (bool, optional) – Mask fill values, see open_dataset(). Default True.

Returns:

xarray.Dataset – Dataset containing the requested variable for the given date.

Retrieve and store daily ECCO2 cube92 ocean state estimate data.

Unlike the GLORYS12/Mercator THREDDS archive (one file per day, per variable, discovered through a rolling filename), the APDRC GDS server exposes each ECCO2 cube92 variable as a single OPeNDAP dataset spanning the full 1992-01-04 – 2025-12-31 daily record. A requested date is selected from that record by nearest-neighbour lookup on the remote time coordinate and cached locally as a single-day Zarr store so repeated access does not re-hit the network.

ECCO2 cube92 is also a plain regular lat/lon grid (0.25 deg, global), not a curvilinear NEMO grid, so there are no separate mesh_hgr/mesh_zgr files to derive geometry from. grid_definition() instead computes cell areas analytically from the lat/lon spacing and derives the bottom level index kmt from the land/below-seafloor pattern of a reference uvel snapshot (see calc_kmt_dzt()).

The server’s native lon runs 0.125..359.875 (Prime Meridian at the array seam); _center_on_prime_meridian() rolls every cached field to -179.875..179.875 so 0 deg sits at the array centre, matching the convention used elsewhere in the codebase.

tracmass.seagrid.ecco2.datadir(dtm='2020-01-01')[source]#

Return the local data directory for a given date, creating it if needed.

Parameters:

dtm (str or datetime-like) – Date string or datetime-like object.

Returns:

pathlib.Path – Path to the year-specific data directory.

tracmass.seagrid.ecco2.filename(dtm='2020-01-01', data_var='uvel')[source]#

Build the Zarr filename for a given date and variable.

Parameters:
  • dtm (str or datetime-like) – Date string or datetime-like object.

  • data_var (str) – Variable key (one of ‘uvel’, ‘vvel’, ‘wvel’, ‘temp’, ‘salt’).

Returns:

str – Filename string in the form CUBE92_<date>_<data_var>.zarr.

tracmass.seagrid.ecco2.retrieve(dtm='2020-01-01', data_var='uvel', force=False)[source]#

Download a single daily field from the APDRC GDS server and save it as Zarr.

Opens the remote ECCO2 cube92 dataset via OPeNDAP, selects the time step closest to dtm, and writes the result to a local Zarr store.

Parameters:
  • dtm (str or datetime-like) – Date string or datetime-like object for the desired time step.

  • data_var (str) – Variable key (one of ‘uvel’, ‘vvel’, ‘wvel’, ‘temp’, ‘salt’).

  • force (bool) – If True, re-download the file even if it already exists locally.

tracmass.seagrid.ecco2.calc_grid_spacing(lat, lon)[source]#

Compute T-cell face widths on a regular lat/lon grid.

Parameters:
  • lat (np.ndarray) – 1-D array of cell-centre latitudes in degrees, shape (jmt,).

  • lon (np.ndarray) – 1-D array of cell-centre longitudes in degrees, shape (imt,).

Returns:

  • dxv (np.ndarray) – Zonal cell width in meters (face crossed by meridional flux), shape (jmt, imt).

  • dyu (np.ndarray) – Meridional cell width in meters (face crossed by zonal flux), shape (jmt, imt).

tracmass.seagrid.ecco2.calc_kmt_dzt(uvel0, lev)[source]#

Derive bottom-level index and layer thickness from a reference snapshot.

ECCO2 cube92 has no separate bathymetry file; land and below-seafloor cells carry an exact-zero velocity (see Notes), so the ocean depth at each column is recovered by counting non-zero levels.

Parameters:
  • uvel0 (np.ndarray) – Zonal velocity at a single reference time, shape (km, jmt, imt).

  • lev (np.ndarray) – 1-D array of depth-level centres in meters, shape (km,).

Returns:

  • kmt (np.ndarray) – 1-based bottom level index per column, shape (jmt, imt).

  • dzt (np.ndarray) – Layer thickness, zeroed below the seafloor, shape (km, jmt, imt).

Notes

The APDRC GDS gateway declares missing_value/_FillValue as -1e23 but actually serves exact 0.0 for land and below-seafloor cells (verified against known land and shallow-shelf columns), so the mask is built from exact equality rather than NaN/CF decoding.

tracmass.seagrid.ecco2.grid_definition(dtm='2020-01-01', dask=True, force=False)[source]#

Build (and cache) the ECCO2 cube92 grid geometry.

Parameters:
  • dtm (str or datetime-like, optional) – Reference date used to derive kmt from the land/underwater NaN pattern of a single uvel snapshot. Default "2020-01-01".

  • dask (bool, optional) – If True (default), open the cached grid file with Dask chunking.

  • force (bool, optional) – If True, rebuild the grid file even if it already exists.

Returns:

xarray.Dataset – Dataset with dxdy, dxv, dyu, dzt, kmt, lon, lat.

tracmass.seagrid.ecco2.landmask(k=1)[source]#

ECCO2 land mask on the T-cells of grid_definition().

Parameters:

k (int, optional) – 1-based model level. Default 1 (surface): land is kmt == 0. Deeper, the sea floor counts as land too (kmt < k).

Returns:

xr.DataArray – bool (y, x), True on land, with lon / lat coordinates. See tracmass.seagrid.coast.landmask().

Return type:

DataArray

tracmass.seagrid.ecco2.distance_to_land(k=1)[source]#

Distance (km) from each ECCO2 T-cell centre to the nearest land cell.

Parameters:

k (int, optional) – 1-based model level whose land mask is used (see landmask()). Default 1 (surface).

Returns:

xr.DataArray – float32 (y, x) great-circle distance in km, 0 on land, with lon / lat coordinates. See tracmass.seagrid.coast.distance_to_land().

Return type:

DataArray

tracmass.seagrid.ecco2.open_dataset(dtm='2020-01-01', data_var=None, force=False, dask=True)[source]#

Open an ECCO2 cube92 dataset, downloading it first if necessary.

Parameters:
  • dtm (str or datetime-like) – Date string or datetime-like object for the desired time step.

  • data_var (str) – Variable key (one of ‘uvel’, ‘vvel’, ‘wvel’, ‘temp’, ‘salt’). If None, both velocity components are fetched and merged.

  • force (bool) – If True, re-download the file even if it already exists locally.

  • dask (bool) – If True (default), open the cached Zarr with Dask chunking.

Returns:

xarray.Dataset – Dataset containing the requested variable(s) for the given date, with dims renamed to (z, y, x).

tracmass.seagrid.ecco2.open_dataarray(dtm='2020-01-01', data_var='uvel', force=False, dask=True)[source]#

Open an ECCO2 cube92 dataarray, downloading it first if necessary.

Parameters:
  • dtm (str or datetime-like) – Date string or datetime-like object for the desired time step.

  • data_var (str) – Variable key (one of ‘uvel’, ‘vvel’, ‘wvel’, ‘temp’, ‘salt’).

  • force (bool) – If True, re-download the file even if it already exists locally.

  • dask (bool) – If True (default), open the cached Zarr with Dask chunking.

Returns:

xarray.DataArray – Data array for the requested variable and date.

Retrieve and store daily Scripps Gulf of Guinea (GoG) MITgcm output.

The Scripps GoG regional MITgcm configuration (GG_i001) is served as plain NetCDF files over HTTPS from https://sose.ucsd.edu/GoG/DATA/, one file per day and variable group, e.g. daily/GG_i001_2024-01-02_1day_UVEL_VVEL_top200m.nc. Unlike ECCO2 there is no OPeNDAP server, so retrieve() downloads whole files and caches them unchanged under datadir(); open_dataset() opens the cached copy.

The model uses an MITgcm Arakawa C-grid on a regular 1/64 deg lat/lon mesh (1376 x 385 T-cells, 11W–10.5E, 1–7N). The velocity files cover only the 320 T-cell rows 2–7N, keep MITgcm’s staggered dimensions (UVEL on (Z, YC, XG): the west face of each T-cell; VVEL on (Z, YG, XC): the south face, plus one extra row for the northernmost north face), and carry their own face metrics (dyG, dxG) and open fractions (hFacW, hFacS). Moving those faces onto TRACMASS’s east/north convention is done in tracmass.gcm.scrippsgog.

There is no hFacC in the velocity files. grid_definition() rebuilds it from the binary Depth and delR grid files with MITgcm’s partial-cell rule (hFacMin, see calc_hfac()) and checks the result against the files’ hFacW/hFacS.

tracmass.seagrid.scrippsgog.basedir()[source]#

Return the local root directory for the configured product.

Returns:

pathlib.Path – /data/<disk>/scrippsgog/<product>, created if needed.

tracmass.seagrid.scrippsgog.datadir(dtm='2024-01-02')[source]#

Return the local data directory for a given date.

Parameters:

dtm (str or datetime-like) – Date string or datetime-like object.

Returns:

pathlib.Path – Path to the year-specific daily data directory.

tracmass.seagrid.scrippsgog.griddir()[source]#

Return the local directory holding the binary grid files.

tracmass.seagrid.scrippsgog.filename(dtm='2024-01-02', data_var='uvel')[source]#

Build the remote (and cached) filename for a given date and variable.

Parameters:
  • dtm (str or datetime-like) – Date string or datetime-like object.

  • data_var (str) – Variable key (one of ‘uvel’, ‘vvel’, ‘temp’, ‘salt’). uvel and vvel live in the same file.

Returns:

str – e.g. GG_i001_2024-01-02_1day_UVEL_VVEL_top200m.nc.

tracmass.seagrid.scrippsgog.url(dtm='2024-01-02', data_var='uvel')[source]#

Return the download URL of a daily file.

Parameters:
  • dtm (str or datetime-like) – Date string or datetime-like object.

  • data_var (str) – Variable key (one of ‘uvel’, ‘vvel’, ‘temp’, ‘salt’).

Returns:

str – Full HTTPS URL.

tracmass.seagrid.scrippsgog.available_dates(data_var='uvel')[source]#

List the dates the server has files for.

Parameters:

data_var (str) – Variable key (one of ‘uvel’, ‘vvel’, ‘temp’, ‘salt’).

Returns:

pandas.DatetimeIndex – Sorted dates parsed from the server’s directory listing.

tracmass.seagrid.scrippsgog.retrieve(dtm='2024-01-02', data_var='uvel', force=False)[source]#

Download a single daily file and cache it locally.

Parameters:
  • dtm (str or datetime-like) – Date of the daily file.

  • data_var (str) – Variable key (one of ‘uvel’, ‘vvel’, ‘temp’, ‘salt’). uvel and vvel share one file.

  • force (bool) – If True, re-download even if the file is already cached.

Returns:

pathlib.Path – Path to the cached file.

Raises:

FileNotFoundError – If the server has no file for dtm (see available_dates()).

Examples

>>> from tracmass.seagrid import scrippsgog
>>> for dtm in pd.date_range("2024-01-02", "2024-01-31"):
...     scrippsgog.retrieve(dtm)
tracmass.seagrid.scrippsgog.retrieve_grid(force=False)[source]#

Download the binary MITgcm grid files (XC, YC, Depth, …).

Parameters:

force (bool) – If True, re-download even if the files are already cached.

Returns:

pathlib.Path – The local grid directory (griddir()).

tracmass.seagrid.scrippsgog.read_grid_field(name)[source]#

Read one binary MITgcm grid field (XC, YC, Depth, RC).

Parameters:

name (str) – Field name; <name>.data / <name>.meta must be in griddir() (see retrieve_grid()).

Returns:

np.ndarray – float32 array, shape (385, 1376) for 2-D fields (y first).

tracmass.seagrid.scrippsgog.calc_hfac(depth, drf, hfac_min=0.2, hfac_min_dr=0.0)[source]#

Rebuild MITgcm’s T-cell open fraction hFacC from bathymetry.

Parameters:
  • depth (np.ndarray) – Ocean depth (positive, m), shape (jmt, imt); 0 on land.

  • drf (np.ndarray) – Layer thicknesses (m), shape (km,), surface first.

  • hfac_min (float, optional) – MITgcm hFacMin / hFacMinDr.

  • hfac_min_dr (float, optional) – MITgcm hFacMin / hFacMinDr.

Returns:

np.ndarray – hFacC, shape (km, jmt, imt), in [0, 1].

Notes

Follows MITgcm ini_masks_etc: the raw fraction of each layer above the sea floor is rounded to 0 below half the minimum size, and up to the minimum size below it.

tracmass.seagrid.scrippsgog.calc_kmt_dzt(hfac, drf)[source]#

Derive bottom-level index and layer thickness from hFacC.

Parameters:
  • hfac (np.ndarray) – Open fraction, shape (km, jmt, imt).

  • drf (np.ndarray) – Layer thicknesses (m), shape (km,).

Returns:

  • kmt (np.ndarray) – Number of open layers per column, shape (jmt, imt), int32. Land is 0.

  • dzt (np.ndarray) – drf * hfac (partial bottom cells), shape (km, jmt, imt).

tracmass.seagrid.scrippsgog.grid_definition(dtm=None, dask=True, force=False)[source]#

Build (and cache) the GoG grid geometry on the velocity files’ T-cells.

Parameters:
  • dtm (str or datetime-like or None, optional) – Date of the reference velocity file whose rows, layers and face metrics define the grid. Default: the first file on the server’s start date (2024-01-02).

  • dask (bool, optional) – If True (default), open the cached grid file with Dask chunking.

  • force (bool, optional) – If True, rebuild the grid file even if it already exists.

Returns:

xarray.Dataset – Dataset on (z, y, x) T-cells with kmt, dzt, hfac, dxdy, dxv, dyu, the 2-D lons/lats and 1-D lon/lat/z coordinates.

Raises:

ValueError – If the rebuilt hFacC does not reproduce the velocity file’s hFacW/hFacS (wrong settings["hfac_min"] or misaligned rows).

tracmass.seagrid.scrippsgog.landmask(k=1)[source]#

GoG land mask on the T-cells of grid_definition().

Parameters:

k (int, optional) – 1-based model level. Default 1 (surface): land is kmt == 0. Deeper, the sea floor counts as land too (kmt < k).

Returns:

xr.DataArray – bool (y, x), True on land, with lon / lat coordinates. See tracmass.seagrid.coast.landmask().

Return type:

DataArray

tracmass.seagrid.scrippsgog.distance_to_land(k=1)[source]#

Distance (km) from each GoG T-cell centre to the nearest land cell.

Parameters:

k (int, optional) – 1-based model level whose land mask is used (see landmask()). Default 1 (surface).

Returns:

xr.DataArray – float32 (y, x) great-circle distance in km, 0 on land, with lon / lat coordinates. See tracmass.seagrid.coast.distance_to_land().

Return type:

DataArray

Notes

The GoG domain is regional: land outside it is unknown, so distances near the open boundaries can be too large.

tracmass.seagrid.scrippsgog.open_dataset(dtm='2024-01-02', data_var=None, force=False, dask=True)[source]#

Open a cached daily GoG file, downloading it first if necessary.

Parameters:
  • dtm (str or datetime-like) – Date of the daily file.

  • data_var (str or None) – Variable key (one of ‘uvel’, ‘vvel’, ‘temp’, ‘salt’). None (default) opens the velocity file with both uvel and vvel.

  • force (bool) – If True, re-download the file even if it already exists locally.

  • dask (bool) – If True (default), open with Dask chunking (the file’s own chunks).

Returns:

xarray.Dataset – The file’s single time step, with the data variable(s) renamed to their keys and Z renamed to z. MITgcm’s staggered horizontal dims (XC/XG, YC/YG) and face metrics are kept as is.

tracmass.seagrid.scrippsgog.open_dataarray(dtm='2024-01-02', data_var='uvel', force=False, dask=True)[source]#

Open one variable of a daily GoG file, downloading it if necessary.

Parameters:
  • dtm (str or datetime-like) – Date of the daily file.

  • data_var (str) – Variable key (one of ‘uvel’, ‘vvel’, ‘temp’, ‘salt’).

  • force (bool) – If True, re-download the file even if it already exists locally.

  • dask (bool) – If True (default), open with Dask chunking.

Returns:

xarray.DataArray – Data array for the requested variable and date.

Land mask and distance to land on a seagrid model’s T-cells.

Shared by the per-model landmask / distance_to_land functions in tracmass.seagrid.glorys, tracmass.seagrid.ecco2 and tracmass.seagrid.scrippsgog. Each model passes its grid_definition() dataset; everything else is grid-independent.

tracmass.seagrid.coast.landmask(grid, k=1)[source]#

Land mask of a grid_definition() dataset.

Parameters:
  • grid (xr.Dataset) – A seagrid grid_definition() with kmt (the number of ocean levels per column; 0 on land) and lon / lat coordinates.

  • k (int, optional) – 1-based model level. Default 1 (the surface): land is kmt == 0. At deeper levels the sea floor counts as land too: kmt < k.

Returns:

xr.DataArray – bool, (y, x), True on land, with the grid’s lon / lat coordinates. NumPy-backed.

Raises:

ValueError – If k is below 1.

Return type:

DataArray

tracmass.seagrid.coast.distance_to_land(mask)[source]#

Great-circle distance from every cell centre to the nearest land cell.

Parameters:

mask (xr.DataArray) – A land mask from landmask() (bool, (y, x), True on land, with lon / lat coordinates in degrees).

Returns:

xr.DataArray – float32, (y, x), in km, with the mask’s coordinates. 0 on land; NaN everywhere when the grid has no land cell.

Return type:

DataArray

Notes

Distances run between cell centres: an ocean cell next to the coast is about one cell width from land, not half. The search uses a KD-tree on unit-sphere coordinates, so it is exact on curvilinear grids and across the date line. Only land cells with an ocean neighbour (8-neighbour) go into the tree: any other land cell is farther from the ocean. On a regional grid, land outside the domain is unknown, so distances near the open boundaries can be too large.

Debugging utilities for tracmass.seagrid.

tracmass.seagrid.debug.trace_lines(func)[source]#

Decorator that prints each source line of func as it executes.

Sub-function calls are not traced — only the lines of the decorated function itself are printed.

Examples

>>> @trace_lines
... def open_dataset(...):
...     ...