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_xyfinds the nearest ocean-cell centre with a great-circle KD-tree, then refines the position inside the cell. It is the exact inverse ofxy_to_lonlat. Points on land fall back to the centre of the nearest ocean cell.xy_to_lonlatinterpolates 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_offsetandgrid.j_offset, or useseed.latlon_list, which does this for you.tracmass.load(..., lonlat=True)callsxy_to_lonlatfor 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
lonandlatcan be 1-D (lonof lengthimt,latof lengthjmt, a regular grid) or 2-D in either axis order. 2-D arrays that look like(jmt, imt), as fromnp.meshgrid(lon, lat), are transposed to(imt, jmt)with a warning. Passnp.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=Trueorperiodic=Falseto override it.On non-periodic edges, positions in the outer half cell are extrapolated linearly from the two edge centres.