Core Utilities
The nereus.core module provides fundamental utilities for coordinate transformations, grid operations, mesh handling, spatial queries, and type definitions.
Type Definitions
Type aliases and protocols for nereus.
- class nereus.core.types.HasCoordinates(*args, **kwargs)[source]
Bases:
ProtocolProtocol for objects with lon/lat coordinates.
- __init__(*args, **kwargs)
- class nereus.core.types.HasArea(*args, **kwargs)[source]
Bases:
ProtocolProtocol for objects with cell area.
- __init__(*args, **kwargs)
- class nereus.core.types.MeshProtocol(*args, **kwargs)[source]
Bases:
HasCoordinates,HasArea,ProtocolProtocol for model mesh objects.
- nereus.core.types.is_dask_array(x)[source]
Check if array is a dask array.
- Parameters:
x (array_like) – Input array (numpy, dask, or xarray).
- Returns:
True if the underlying data is a dask array.
- Return type:
- nereus.core.types.wrap_as_xarray(result, source_data, default_name, *, skip_dims=1)[source]
Wrap a reduced result as an xarray DataArray.
After a spatial reduction (e.g. nansum over trailing axes), the result has a subset of the input’s dimensions. This helper preserves dimension names, coordinates, variable name, and attributes when the input is an xarray DataArray.
- Parameters:
result (float or ndarray) – The reduced result (scalar or array with leading dims).
source_data (array_like) – The original input data (used to extract dimension metadata).
default_name (str) – Variable name to use when the input has no name (e.g. numpy).
skip_dims (int) – Number of trailing dimensions of
source_datathat were consumed by the reduction and should not appear in the output. Default 1 (spatial-only reduction like ice_area). Use 2 for reductions over (nlevels, npoints) like volume_mean.
- nereus.core.types.get_array_data(x)[source]
Extract underlying array data, preserving dask arrays.
This function extracts the underlying array from xarray DataArrays while preserving dask arrays (no eager computation).
- Parameters:
x (array_like) – Input array (numpy, dask, or xarray).
- Returns:
The underlying array data.
- Return type:
ndarray or dask.array
Type Aliases
The following type aliases are defined for convenience:
ArrayLike:
Union[NDArray[np.floating], xr.DataArray]- Array-like data typeFloatArray:
NDArray[np.floating]- Float array typeIntArray:
NDArray[np.integer]- Integer array typeBoolArray:
NDArray[np.bool_]- Boolean array type
Mesh Utilities
Core mesh utilities for nereus.
This module provides utilities for creating, validating, and normalizing mesh datasets. Meshes are represented as xr.Dataset objects with standardized variable names.
- nereus.core.mesh.should_use_dask(npoints, use_dask=None)[source]
Determine whether to use dask arrays based on mesh size.
- nereus.core.mesh.normalize_lon(lon, convention='pm180')[source]
Normalize longitude to specified convention.
- Parameters:
lon (array_like) – Longitude values in degrees.
convention ({"pm180", "0360"}) – Target convention: - “pm180”: [-180, 180] - “0360”: [0, 360]
- Returns:
Normalized longitude values.
- Return type:
ndarray
- nereus.core.mesh.ensure_lon_pm180(ds)[source]
Ensure longitude is normalized to [-180, 180].
- Parameters:
ds (xr.Dataset) – Mesh dataset with ‘lon’ variable.
- Returns:
Dataset with normalized longitude.
- Return type:
xr.Dataset
- nereus.core.mesh.validate_mesh(ds, strict=False)[source]
Validate mesh dataset against nereus conventions.
- Parameters:
ds (xr.Dataset) – Dataset to validate.
strict (bool) – If True, raise ValueError on validation errors.
- Returns:
List of validation warnings/errors.
- Return type:
- Raises:
ValueError – If strict=True and validation fails.
- nereus.core.mesh.add_mesh_metadata(ds, mesh_type, source_path=None, use_dask=False)[source]
Add nereus mesh metadata to dataset.
- nereus.core.mesh.is_nereus_mesh(ds)[source]
Check if dataset is a nereus mesh.
- Parameters:
ds (xr.Dataset) – Dataset to check.
- Returns:
True if dataset has nereus mesh metadata.
- Return type:
- nereus.core.mesh.get_mesh_type(ds)[source]
Get mesh type from nereus mesh dataset.
- Parameters:
ds (xr.Dataset) – Mesh dataset.
- Returns:
Mesh type, or None if not a nereus mesh.
- Return type:
str or None
- nereus.core.mesh.create_lonlat_mesh(resolution, *, lon_bounds=(-180, 180), lat_bounds=(-90, 90), use_dask=None)[source]
Create regular lon-lat mesh.
- Parameters:
- Returns:
Mesh dataset with flattened lon, lat, area.
- Return type:
xr.Dataset
- nereus.core.mesh.mesh_from_arrays(lon, lat, *, area=None, use_dask=None)[source]
Create mesh from existing coordinate arrays.
Handles 1D, 2D, and regular grid side coordinates. If lon and lat are both 1D but have different sizes, they are treated as regular grid side coordinates and expanded via meshgrid before flattening. 2D arrays are flattened directly.
- Parameters:
lon (array_like) – Longitude coordinates in degrees.
lat (array_like) – Latitude coordinates in degrees.
area (array_like, optional) – Cell areas in m^2. If None, estimates from grid spacing.
use_dask (bool, optional) – Whether to use dask arrays. Auto-detects if None.
- Returns:
Mesh dataset with lon, lat, area.
- Return type:
xr.Dataset
Mesh Creation
- nereus.core.mesh.create_lonlat_mesh(resolution, *, lon_bounds=(-180, 180), lat_bounds=(-90, 90), use_dask=None)[source]
Create regular lon-lat mesh.
- Parameters:
- Returns:
Mesh dataset with flattened lon, lat, area.
- Return type:
xr.Dataset
- nereus.core.mesh.mesh_from_arrays(lon, lat, *, area=None, use_dask=None)[source]
Create mesh from existing coordinate arrays.
Handles 1D, 2D, and regular grid side coordinates. If lon and lat are both 1D but have different sizes, they are treated as regular grid side coordinates and expanded via meshgrid before flattening. 2D arrays are flattened directly.
- Parameters:
lon (array_like) – Longitude coordinates in degrees.
lat (array_like) – Latitude coordinates in degrees.
area (array_like, optional) – Cell areas in m^2. If None, estimates from grid spacing.
use_dask (bool, optional) – Whether to use dask arrays. Auto-detects if None.
- Returns:
Mesh dataset with lon, lat, area.
- Return type:
xr.Dataset
Mesh Validation
- nereus.core.mesh.validate_mesh(ds, strict=False)[source]
Validate mesh dataset against nereus conventions.
- Parameters:
ds (xr.Dataset) – Dataset to validate.
strict (bool) – If True, raise ValueError on validation errors.
- Returns:
List of validation warnings/errors.
- Return type:
- Raises:
ValueError – If strict=True and validation fails.
Coordinate Normalization
- nereus.core.mesh.normalize_lon(lon, convention='pm180')[source]
Normalize longitude to specified convention.
- Parameters:
lon (array_like) – Longitude values in degrees.
convention ({"pm180", "0360"}) – Target convention: - “pm180”: [-180, 180] - “0360”: [0, 360]
- Returns:
Normalized longitude values.
- Return type:
ndarray
Dask Support
- nereus.core.mesh.should_use_dask(npoints, use_dask=None)[source]
Determine whether to use dask arrays based on mesh size.
- nereus.core.mesh.DASK_THRESHOLD_POINTS
Number of points above which dask arrays are automatically used:
1_000_000
Spatial Functions
Spatial query functions for nereus.
Standalone functions for spatial operations on coordinate arrays.
- nereus.core.spatial.find_nearest(lon, lat, query_lon, query_lat, k=1, *, return_distance=False)[source]
Find nearest mesh points to query locations.
Uses a KDTree built on Cartesian coordinates for efficient spherical nearest-neighbor search.
- Parameters:
lon (array_like) – Longitude coordinates of mesh points in degrees.
lat (array_like) – Latitude coordinates of mesh points in degrees.
query_lon (float or array_like) – Query longitude(s) in degrees.
query_lat (float or array_like) – Query latitude(s) in degrees.
k (int) – Number of nearest neighbors to find.
return_distance (bool) – If True, also return distances in meters.
- Returns:
indices (ndarray) – Indices of nearest mesh points. Shape depends on inputs: - Scalar query, k=1: scalar int - Scalar query, k>1: (k,) array - Array query, k=1: (n_queries,) array - Array query, k>1: (n_queries, k) array
distances (ndarray, optional) – Distances in meters. Returned only if return_distance=True. Same shape as indices.
- Return type:
ndarray[tuple[Any, …], dtype[int64]] | tuple[ndarray[tuple[Any, …], dtype[int64]], ndarray[tuple[Any, …], dtype[floating]]]
Examples
>>> mesh = nr.fesom.load_mesh(path) >>> idx = nr.find_nearest(mesh["lon"].values, mesh["lat"].values, -30.5, 60.2) >>> print(f"Nearest point: ({mesh['lon'].values[idx]}, {mesh['lat'].values[idx]})")
>>> # Find 3 nearest neighbors with distances >>> indices, distances = nr.find_nearest( ... mesh["lon"].values, mesh["lat"].values, ... [-30, -31], [60, 61], ... k=3, ... return_distance=True, ... )
- nereus.core.spatial.subset_by_bbox(lon, lat, lon_min, lon_max, lat_min, lat_max)[source]
Get mask for points within bounding box.
- Parameters:
- Returns:
mask – Boolean mask of points within bounds.
- Return type:
ndarray
Examples
>>> mesh = nr.fesom.load_mesh(path) >>> mask = nr.subset_by_bbox( ... mesh["lon"].values, mesh["lat"].values, ... lon_min=-10, lon_max=10, ... lat_min=-5, lat_max=5, ... ) >>> equatorial_area = mesh["area"].values[mask].sum()
- nereus.core.spatial.points_in_polygon(lon, lat, polygon_lon, polygon_lat)[source]
Get mask for points inside polygon.
Uses matplotlib.path for point-in-polygon testing.
- Parameters:
lon (array_like) – Longitude coordinates of mesh points in degrees.
lat (array_like) – Latitude coordinates of mesh points in degrees.
polygon_lon (array_like) – Longitude coordinates of polygon vertices.
polygon_lat (array_like) – Latitude coordinates of polygon vertices.
- Returns:
mask – Boolean mask of points inside polygon.
- Return type:
ndarray
Notes
The polygon is assumed to be defined in Cartesian lon-lat space (not geodesic). For large-scale polygons crossing the dateline, consider normalizing longitudes first.
Examples
>>> # Select points in a triangular region >>> poly_lon = [-10, 10, 0, -10] >>> poly_lat = [0, 0, 10, 0] >>> mask = nr.points_in_polygon(lon, lat, poly_lon, poly_lat)
- nereus.core.spatial.haversine_distance(lon1, lat1, lon2, lat2)[source]
Compute great-circle distance between points using Haversine formula.
- Parameters:
- Returns:
distance – Distance in meters.
- Return type:
float or ndarray
Examples
>>> d = nr.haversine_distance(-74.0, 40.7, 2.3, 48.9) # NYC to Paris >>> print(f"Distance: {d/1000:.0f} km")
Point Queries
- nereus.core.spatial.find_nearest(lon, lat, query_lon, query_lat, k=1, *, return_distance=False)[source]
Find nearest mesh points to query locations.
Uses a KDTree built on Cartesian coordinates for efficient spherical nearest-neighbor search.
- Parameters:
lon (array_like) – Longitude coordinates of mesh points in degrees.
lat (array_like) – Latitude coordinates of mesh points in degrees.
query_lon (float or array_like) – Query longitude(s) in degrees.
query_lat (float or array_like) – Query latitude(s) in degrees.
k (int) – Number of nearest neighbors to find.
return_distance (bool) – If True, also return distances in meters.
- Returns:
indices (ndarray) – Indices of nearest mesh points. Shape depends on inputs: - Scalar query, k=1: scalar int - Scalar query, k>1: (k,) array - Array query, k=1: (n_queries,) array - Array query, k>1: (n_queries, k) array
distances (ndarray, optional) – Distances in meters. Returned only if return_distance=True. Same shape as indices.
- Return type:
ndarray[tuple[Any, …], dtype[int64]] | tuple[ndarray[tuple[Any, …], dtype[int64]], ndarray[tuple[Any, …], dtype[floating]]]
Examples
>>> mesh = nr.fesom.load_mesh(path) >>> idx = nr.find_nearest(mesh["lon"].values, mesh["lat"].values, -30.5, 60.2) >>> print(f"Nearest point: ({mesh['lon'].values[idx]}, {mesh['lat'].values[idx]})")
>>> # Find 3 nearest neighbors with distances >>> indices, distances = nr.find_nearest( ... mesh["lon"].values, mesh["lat"].values, ... [-30, -31], [60, 61], ... k=3, ... return_distance=True, ... )
- nereus.core.spatial.haversine_distance(lon1, lat1, lon2, lat2)[source]
Compute great-circle distance between points using Haversine formula.
- Parameters:
- Returns:
distance – Distance in meters.
- Return type:
float or ndarray
Examples
>>> d = nr.haversine_distance(-74.0, 40.7, 2.3, 48.9) # NYC to Paris >>> print(f"Distance: {d/1000:.0f} km")
Geographic Subsetting
- nereus.core.spatial.subset_by_bbox(lon, lat, lon_min, lon_max, lat_min, lat_max)[source]
Get mask for points within bounding box.
- Parameters:
- Returns:
mask – Boolean mask of points within bounds.
- Return type:
ndarray
Examples
>>> mesh = nr.fesom.load_mesh(path) >>> mask = nr.subset_by_bbox( ... mesh["lon"].values, mesh["lat"].values, ... lon_min=-10, lon_max=10, ... lat_min=-5, lat_max=5, ... ) >>> equatorial_area = mesh["area"].values[mask].sum()
- nereus.core.spatial.points_in_polygon(lon, lat, polygon_lon, polygon_lat)[source]
Get mask for points inside polygon.
Uses matplotlib.path for point-in-polygon testing.
- Parameters:
lon (array_like) – Longitude coordinates of mesh points in degrees.
lat (array_like) – Latitude coordinates of mesh points in degrees.
polygon_lon (array_like) – Longitude coordinates of polygon vertices.
polygon_lat (array_like) – Latitude coordinates of polygon vertices.
- Returns:
mask – Boolean mask of points inside polygon.
- Return type:
ndarray
Notes
The polygon is assumed to be defined in Cartesian lon-lat space (not geodesic). For large-scale polygons crossing the dateline, consider normalizing longitudes first.
Examples
>>> # Select points in a triangular region >>> poly_lon = [-10, 10, 0, -10] >>> poly_lat = [0, 0, 10, 0] >>> mask = nr.points_in_polygon(lon, lat, poly_lon, poly_lat)
Coordinate Functions
Coordinate utilities for nereus.
Functions for converting between geographic and Cartesian coordinates, and for computing distances on the sphere.
- nereus.core.coordinates.lonlat_to_cartesian(lon, lat, radius=1.0)[source]
Convert longitude/latitude to Cartesian coordinates.
- Parameters:
lon (array_like) – Longitude in degrees.
lat (array_like) – Latitude in degrees.
radius (float, optional) – Radius of the sphere. Default is 1.0 (unit sphere).
- Returns:
x, y, z – Cartesian coordinates.
- Return type:
tuple of ndarrays
Notes
Uses the convention where: - x points towards (lon=0, lat=0) - y points towards (lon=90, lat=0) - z points towards the North Pole (lat=90)
- nereus.core.coordinates.cartesian_to_lonlat(x, y, z)[source]
Convert Cartesian coordinates to longitude/latitude.
- Parameters:
x (array_like) – Cartesian coordinates.
y (array_like) – Cartesian coordinates.
z (array_like) – Cartesian coordinates.
- Returns:
lon, lat – Longitude and latitude in degrees.
- Return type:
tuple of ndarrays
- nereus.core.coordinates.meters_to_chord(meters, radius=6371000.0)[source]
Convert distance in meters to chord distance on unit sphere.
The chord distance is the straight-line distance through the sphere between two points, normalized by the sphere radius. This is useful for KDTree queries on unit sphere coordinates.
- Parameters:
- Returns:
Chord distance on unit sphere.
- Return type:
Notes
The formula converts arc length to chord length: chord = 2 * sin(arc_length / (2 * radius))
For small distances, chord ≈ arc_length / radius.
- nereus.core.coordinates.chord_to_meters(chord, radius=6371000.0)[source]
Convert chord distance on unit sphere to meters.
- nereus.core.coordinates.great_circle_distance(lon1, lat1, lon2, lat2, radius=6371000.0)[source]
Compute great-circle distance between two points using Haversine formula.
- Parameters:
lon1 (array_like) – Longitude and latitude of first point(s) in degrees.
lat1 (array_like) – Longitude and latitude of first point(s) in degrees.
lon2 (array_like) – Longitude and latitude of second point(s) in degrees.
lat2 (array_like) – Longitude and latitude of second point(s) in degrees.
radius (float, optional) – Earth radius in meters. Default is 6,371,000 m.
- Returns:
Distance in meters.
- Return type:
ndarray
- nereus.core.coordinates.great_circle_path(start_lon, start_lat, end_lon, end_lat, n_points=100)[source]
Generate points along a great circle path.
- Parameters:
- Returns:
lon, lat – Coordinates of points along the great circle path.
- Return type:
tuple of ndarrays
- nereus.core.coordinates.compute_element_centers(lon, lat, triangles)[source]
Compute element center coordinates, handling cyclic triangles.
For triangular meshes, computes the center of each triangle. Handles triangles that cross the dateline (±180°) by shifting longitudes before averaging.
- Parameters:
lon (array_like) – Longitude coordinates of mesh nodes in degrees.
lat (array_like) – Latitude coordinates of mesh nodes in degrees.
triangles (array_like) – Triangle connectivity array of shape (3, nelem) or (nelem, 3). Contains indices into lon/lat arrays.
- Returns:
lon_elem, lat_elem – Longitude and latitude of element centers.
- Return type:
tuple of ndarrays
Examples
>>> lon_elem, lat_elem = compute_element_centers(mesh.lon, mesh.lat, mesh.face_nodes)
Constants
EARTH_RADIUS: Earth’s mean radius in meters (WGS84):
6_371_000.0
Grid Functions
Grid utilities for nereus.
Functions for creating regular grids for regridding and plotting.
- nereus.core.grids.extract_coordinates(data)[source]
Extract longitude and latitude coordinates from an xarray DataArray.
This function attempts to automatically detect coordinate variables by looking for common naming conventions used in geophysical data.
- Parameters:
data (xr.DataArray or array_like) – The data array to extract coordinates from. If not an xarray DataArray, returns (None, None).
- Returns:
lon (ndarray or None) – Longitude coordinates if found, None otherwise.
lat (ndarray or None) – Latitude coordinates if found, None otherwise.
- Return type:
tuple[NDArray | None, NDArray | None]
Notes
The function looks for coordinates with these common names:
Longitude: lon, longitude, x, nav_lon, glon, xt_ocean, xu_ocean, xh, xq, nod2d_lon Latitude: lat, latitude, y, nav_lat, glat, yt_ocean, yu_ocean, yh, yq, nod2d_lat
Examples
>>> import xarray as xr >>> data = xr.DataArray( ... np.random.rand(10, 20), ... coords={"lat": np.arange(10), "lon": np.arange(20)}, ... dims=["lat", "lon"] ... ) >>> lon, lat = extract_coordinates(data) >>> lon.shape, lat.shape ((20,), (10,))
- nereus.core.grids.prepare_input_arrays(data, lon, lat)[source]
Prepare and validate input arrays, converting to 1D if necessary.
This function handles various input formats and transforms them to 1D arrays suitable for plotting and regridding. It issues warnings when transformations are applied.
- Parameters:
data (array_like) – Data values, can be 1D or 2D.
lon (array_like) – Longitude coordinates, can be 1D or 2D.
lat (array_like) – Latitude coordinates, can be 1D or 2D.
- Returns:
data_1d (ndarray) – 1D array of data values.
lon_1d (ndarray) – 1D array of longitude coordinates.
lat_1d (ndarray) – 1D array of latitude coordinates.
- Raises:
ValueError – If array dimensions are incompatible or sizes don’t match.
- Return type:
tuple[NDArray, NDArray[np.floating], NDArray[np.floating]]
Notes
Supported input combinations:
All 1D arrays of same size: used directly (no warning)
2D data with 2D lon/lat (same shape): all raveled to 1D
1D data with 2D lon/lat: lon/lat raveled to match data
2D data with 1D lon/lat: meshgrid created, then all raveled
Examples
>>> # 2D data with 1D coordinates (regular grid) >>> data = np.random.rand(180, 360) >>> lon = np.linspace(-179.5, 179.5, 360) >>> lat = np.linspace(-89.5, 89.5, 180) >>> data_1d, lon_1d, lat_1d = prepare_input_arrays(data, lon, lat) >>> data_1d.shape (64800,)
- nereus.core.grids.prepare_coordinates(lon, lat, data_shape=None)[source]
Prepare and validate coordinate arrays, converting to 1D if necessary.
This function handles various coordinate formats and transforms them to 1D arrays. It issues warnings when transformations are applied.
- Parameters:
- Returns:
lon_1d (ndarray) – 1D array of longitude coordinates.
lat_1d (ndarray) – 1D array of latitude coordinates.
- Raises:
ValueError – If array dimensions are incompatible or sizes don’t match.
- Return type:
tuple[ndarray[tuple[Any, …], dtype[floating]], ndarray[tuple[Any, …], dtype[floating]]]
Examples
>>> # 2D coordinates >>> lon_2d, lat_2d = np.meshgrid(np.arange(10), np.arange(5)) >>> lon_1d, lat_1d = prepare_coordinates(lon_2d, lat_2d) >>> lon_1d.shape (50,)
>>> # 1D coordinates with data shape >>> lon = np.arange(10) >>> lat = np.arange(5) >>> lon_1d, lat_1d = prepare_coordinates(lon, lat, data_shape=(5, 10)) >>> lon_1d.shape (50,)
- nereus.core.grids.flatten_spatial(data)[source]
Flatten the last two spatial dimensions of an array into one.
Reshapes
(..., nlat, nlon)to(..., npoints)wherenpoints = nlat * nlon. Works with both NumPy and dask arrays.- Parameters:
data (array_like) – Array with at least 2 dimensions.
- Returns:
Reshaped array with the last two dimensions merged.
- Return type:
array_like
- Raises:
ValueError – If data has fewer than 2 dimensions.
- nereus.core.grids.create_regular_grid(resolution=1.0, lon_bounds=(-180.0, 180.0), lat_bounds=(-90.0, 90.0), center='cell')[source]
Create a regular lon/lat grid.
- Parameters:
resolution (float or tuple of int) – Grid resolution. If float, specifies degrees per grid cell. If tuple (nlon, nlat), specifies number of grid points.
lon_bounds (tuple of float) – Longitude bounds (lon_min, lon_max) in degrees.
lat_bounds (tuple of float) – Latitude bounds (lat_min, lat_max) in degrees.
center ({"cell", "node"}) – Whether coordinates are at cell centers or nodes. “cell” means coordinates at center of grid boxes. “node” means coordinates at corners.
- Returns:
lon, lat – 2D arrays of longitude and latitude coordinates.
- Return type:
tuple of ndarrays
Examples
>>> lon, lat = create_regular_grid(1.0) # 1 degree resolution >>> lon.shape (180, 360)
>>> lon, lat = create_regular_grid((360, 180)) # 360x180 grid >>> lon.shape (180, 360)
- nereus.core.grids.grid_cell_area(lon, lat, radius=6371000.0)[source]
Compute area of regular grid cells.
- Parameters:
lon (ndarray) – 2D array of longitude coordinates (cell centers).
lat (ndarray) – 2D array of latitude coordinates (cell centers).
radius (float) – Earth radius in meters.
- Returns:
2D array of cell areas in square meters.
- Return type:
ndarray
Notes
Assumes uniform spacing in lon and lat. Area of a spherical rectangle: A = R^2 * |sin(lat1) - sin(lat2)| * |lon2 - lon1|