tracmass.trajs#

Trajectory analysis utilities for TRACMASS-JAX.

Provides functions for computing physical properties from trajectory DataFrames produced by ParticleRecorder.

tracmass.trajs.speeds(df, dxdy)[source]#

Compute inter-snapshot speeds for all particles in a trajectory DataFrame.

For each consecutive pair of snapshots per particle, computes the physical displacement in metres and the speed in m/s.

The effective cell width used for displacement conversion is sqrt(dxdy_cell), which is exact for square cells and the geometric-mean approximation for non-square cells.

Parameters:
  • df (pd.DataFrame) – Trajectory data as produced by ParticleRecorder. Required columns: id, x, y, tt, window. If an event_type column is present, only "snapshot" rows are used. If dxdy is a 2-D array, ia and ja must also be present.

  • dxdy (float, array-like of shape (imt, jmt), or GridFields) –

    Cell area in m².

    • scalar — uniform grid; cell width is sqrt(dxdy) in both directions. Pass e.g. 250.0 ** 2 for 250 m Cartesian cells.

    • 2-D array — spatially varying grid; the cell area at the starting position of each interval is looked up using the 1-based ia/ja columns. Pass np.asarray(grid.dxdy) or any array-like of the right shape.

    • GridFields (or any object with a .dxdy attribute) — the .dxdy attribute is used as the 2-D array. Pass grid directly.

Returns:

pandas.DataFrame – One row per consecutive snapshot pair per particle, with columns:

id

Particle identifier.

window

Window index of the later snapshot.

dt

Time elapsed between snapshots in seconds.

dx_m

x-displacement in metres (signed).

dy_m

y-displacement in metres (signed).

speed

Euclidean speed in m/s.

Return type:

DataFrame

Examples

Uniform grid (e.g. Fabboni test case, 250 m cells):

>>> import pandas as pd
>>> from tracmass.trajs import speeds
>>> df = pd.read_parquet("traj.parquet")
>>> sp = speeds(df, dxdy=250.0 ** 2)
>>> sp["speed"].max()

Spatially varying grid from a GridFields object:

>>> import tracmass
>>> grid, lazy = tracmass.new_flux(tracmass.gcm.glorys.fluxes)
>>> sp = speeds(df, grid)

Coordinate conversion utilities for TRACMASS-JAX.

Provides xy_to_lonlat() and lonlat_to_xy() for converting between fractional TRACMASS grid positions and geographic lon/lat coordinates. Both functions are grid-agnostic: any object that exposes .lon and .lat arrays (and optionally .kmt) can be passed as the grid argument.

Both use the TRACMASS position convention: cell i (0-based, ia - 1) spans i <= x < i + 1 and its centre – where the grid’s lon/lat are defined – sits at x = i + 0.5; likewise for y. The coordinate arrays may be 1-D (lon (imt,), lat (jmt,)) or 2-D in either axis order — _orient_lonlat() normalises them to TRACMASS (imt, jmt) and transposes a (jmt, imt) layout with a warning.

tracmass.trajs.coords.xy_to_lonlat(x, y, grid, periodic=None)[source]#

Convert fractional TRACMASS (x, y) positions to longitude/latitude.

Bilinearly interpolates the grid’s cell-centre lon/lat at the fractional particle positions. Cell i spans i <= x < i + 1 with its centre at x = i + 0.5 (likewise y), so a particle at a cell centre maps exactly to that cell’s lon/lat and one on a cell wall maps half-way between the two neighbouring centres. Interpolation is performed in Cartesian (x, y, z) space on the unit sphere to handle the ±180° longitude seam correctly on curvilinear grids.

Parameters:
  • x (array-like) – Fractional 0-based grid positions as stored in the trajectory Parquet file (columns "x" and "y"). floor(x) is the cell (matching "ia" - 1 / "ja" - 1).

  • y (array-like) – Fractional 0-based grid positions as stored in the trajectory Parquet file (columns "x" and "y"). floor(x) is the cell (matching "ia" - 1 / "ja" - 1).

  • grid (object or tuple) –

    Provides the (imt, jmt) arrays of grid-cell centres in degrees:

    • Object with ``.lon`` and ``.lat`` attributes — e.g. a GridFields extended with coordinate arrays, or a types.SimpleNamespace(). A .kmt attribute is not required for this function and is ignored if present.

    • 2-tuple (lon_arr, lat_arr) — lon/lat arrays directly.

    • 3-tuple (lon_arr, lat_arr, kmt_arr) — kmt is ignored here.

    lon_arr/lat_arr may be 1-D (lon (imt,), lat (jmt,) — a regular lon/lat grid) or 2-D. 2-D arrays are used as (imt, jmt) (first axis zonal x, second meridional y); a (jmt, imt) layout — e.g. np.meshgrid(lon, lat) with the default indexing="xy" — is detected and transposed, with a warnings.warn.

  • periodic (bool or None, optional) – Whether x wraps around (a global grid): positions between the last and first cell centres then interpolate across the seam. None (default) detects it from the grid. Otherwise positions in the outermost half cell are linearly extrapolated.

Returns:

lon, lat (np.ndarray) – Longitude and latitude in degrees, same shape as x and y.

Return type:

tuple[ndarray, ndarray]

Examples

>>> import pandas as pd, types
>>> from tracmass.trajs import xy_to_lonlat
>>> grid = types.SimpleNamespace(lon=lon_arr, lat=lat_arr)
>>> df = pd.read_parquet("traj.parquet", columns=["x", "y"])
>>> lon, lat = xy_to_lonlat(df["x"], df["y"], grid)
tracmass.trajs.coords.lonlat_to_xy(lon, lat, grid, periodic=None)[source]#

Convert geographic coordinates to fractional TRACMASS (x, y) grid positions.

The exact inverse of xy_to_lonlat(): the returned position maps back to lon/lat, so a point off-centre within a cell gets the matching fractional offset rather than being snapped to the centre. Finds the nearest grid-cell centre by great-circle distance (a scipy.spatial.cKDTree on unit-sphere coordinates) as a starting guess, then refines it with Newton iterations on the bilinear map in the local tangent plane.

When a .kmt array is available on grid, the search is restricted to ocean cells (kmt > 0), and a point that falls in a land cell (or outside the grid) is placed at the centre of the nearest ocean cell instead, so seeded particles always start in the ocean.

The resulting (x, y) values can be passed directly to tracmass.seed.expand_sub() or used to initialise a ParticleState, with ia = floor(x) + 1, ja = floor(y) + 1 (1-based cell indices).

Parameters:
  • lon (array-like) – Longitude and latitude in degrees.

  • lat (array-like) – Longitude and latitude in degrees.

  • grid (object or tuple) –

    Provides the (imt, jmt) arrays of grid-cell centres in degrees, and optionally a land mask:

    • Object with ``.lon`` and ``.lat`` attributes — e.g. a GridFields extended with coordinate arrays, or a types.SimpleNamespace(). If the object also has a .kmt attribute, only ocean cells (kmt > 0) are included in the spatial index.

    • 2-tuple (lon_arr, lat_arr) — all cells are included.

    • 3-tuple (lon_arr, lat_arr, kmt_arr) — ocean-only index.

    As for xy_to_lonlat(), lon/lat may be 1-D or 2-D in either axis order; a (jmt, imt) 2-D layout is transposed to (imt, jmt) (along with kmt) with a warning.

  • periodic (bool or None, optional) – Whether x wraps around; see xy_to_lonlat(). With periodic, the returned x is wrapped into [0, imt).

Returns:

x, y (np.ndarray) – Fractional 0-based TRACMASS grid positions, same shape as lon/lat.

Return type:

tuple[ndarray, ndarray]

Examples

>>> import numpy as np, types
>>> from tracmass.trajs import lonlat_to_xy
>>> grid = types.SimpleNamespace(lon=lon_arr, lat=lat_arr, kmt=kmt_arr)
>>> x, y = lonlat_to_xy(np.array([-30.0, 10.0]), np.array([45.0, 55.0]), grid)