Coordinates#

Particle positions are in grid-cell units: cell i of a 0-based array covers i <= x < i + 1, with its centre at x = i + 0.5, and the same for y (see Grid). Saved positions are in the full-grid frame, whatever subset the run used.

With an adapter#

gcm.glorys, gcm.ecco2 and gcm.scrippsgog have the same three functions:

import numpy as np
import pandas as pd
from tracmass.gcm import glorys as model    # or ecco2, scrippsgog

# Geographic -> model positions, e.g. for seeding
lon = np.array([-30.0, 10.0, 5.0])
lat = np.array([45.0, 55.0, 60.0])
x, y = model.lonlat_to_xy(lon, lat)          # 0-based fractional, full grid

# Model positions -> geographic, e.g. for analysis
df = pd.read_parquet("trm_omi.parquet", columns=["x", "y"])
lon, lat = model.xy_to_lonlat(df["x"], df["y"])

# Cell-centre lon/lat of a run grid (follows the subset), each (imt, jmt)
lon2d, lat2d = model.lonlat_grid(grid)
  • lonlat_to_xy finds the nearest ocean-cell centre with a great-circle KD-tree, then refines the position inside the cell. It is the exact inverse of xy_to_lonlat. Points on land fall back to the centre of the nearest ocean cell.

  • xy_to_lonlat interpolates bilinearly between cell centres in Cartesian (unit-sphere) coordinates, which is correct on curvilinear grids and across the ±180° seam.

  • Both use full-grid indices. To seed on a subset grid, subtract grid.i_offset and grid.j_offset, or use seed.latlon_list, which does this for you.

  • tracmass.load(..., lonlat=True) calls xy_to_lonlat for you.

For any grid — tracmass.trajs#

The generic functions take any object with .lon and .lat attributes (optionally .kmt), or a plain (lon, lat[, kmt]) tuple:

import types
from tracmass.trajs import xy_to_lonlat, lonlat_to_xy

grid = types.SimpleNamespace(lon=lon_arr, lat=lat_arr, kmt=kmt_arr)
lon, lat = xy_to_lonlat(df["x"], df["y"], grid)
x, y = lonlat_to_xy(lon, lat, grid)          # round-trips xy_to_lonlat exactly
  • lon and lat can be 1-D (lon of length imt, lat of length jmt, a regular grid) or 2-D in either axis order. 2-D arrays that look like (jmt, imt), as from np.meshgrid(lon, lat), are transposed to (imt, jmt) with a warning. Pass np.meshgrid(lon, lat, indexing="ij") to avoid it.

  • Zonal periodicity (a global grid whose last column wraps onto the first) is detected automatically. Pass periodic=True or periodic=False to override it.

  • On non-periodic edges, positions in the outer half cell are extrapolated linearly from the two edge centres.