Validation & Coordinates¶
Coordinate-system hygiene for incoming datasets: validate longitude / latitude / time axes, decode CF time, rename coordinates and variables to or from CF standard names, and measure grid resolution.
CF standard names
RenameToCFStandardNames / RenameFromCFStandardNames use the curated
Variable registry that now lives in
xrproducts.types — the same
registry that drives the colormap lookup in xrops.viz.
Coordinate validation¶
ValidateLongitude
¶
Bases: Operator
Validate and CF-normalise the longitude coordinate.
Renames a recognised longitude alias to lon and checks the values
lie in range, raising on malformed input.
Returns:
| Type | Description |
|---|---|
|
The input dataset with a validated |
ValidateLatitude
¶
Bases: Operator
Validate and CF-normalise the latitude coordinate.
Renames a recognised latitude alias to lat and checks the values
lie in [-90, 90], raising on malformed input.
Returns:
| Type | Description |
|---|---|
|
The input dataset with a validated |
ValidateCoords
¶
Bases: Operator
Validate both longitude and latitude in one pass.
Applies :class:ValidateLongitude then :class:ValidateLatitude.
Returns:
| Type | Description |
|---|---|
|
The input dataset with validated |
ValidateTime
¶
Bases: Operator
Validate and standardise a time coordinate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
time
|
str
|
Name of the time coordinate. |
'time'
|
unit
|
str | None
|
Expected time unit; |
None
|
origin
|
str
|
Reference epoch for numeric times (default |
'unix'
|
Returns:
| Type | Description |
|---|---|
|
The input dataset with a validated |
Source code in packages/xrtoolz-ops/src/xrops/cf/operators.py
DecodeCFTime
¶
Bases: Operator
Decode a CF-encoded time coordinate to datetime64.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
time
|
str
|
Name of the time coordinate to decode. |
'time'
|
units
|
str | None
|
CF time units (e.g. |
None
|
Returns:
| Type | Description |
|---|---|
|
The input dataset with |
Source code in packages/xrtoolz-ops/src/xrops/cf/operators.py
Renaming & CF standard names¶
RenameCoords
¶
Bases: Operator
Rename coordinates by an explicit mapping.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mapping
|
dict[str, str]
|
|
required |
Returns:
| Type | Description |
|---|---|
|
The input dataset with the coordinates renamed. |
Source code in packages/xrtoolz-ops/src/xrops/cf/operators.py
RenameVariables
¶
Bases: Operator
Rename data variables by an explicit mapping.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mapping
|
dict[str, str]
|
|
required |
Returns:
| Type | Description |
|---|---|
|
The input dataset with the data variables renamed. |
Source code in packages/xrtoolz-ops/src/xrops/cf/operators.py
RenameToCFStandardNames
¶
Bases: Operator
Wrap :func:xrops.cf.rename_to_cf_standard_names.
Renames each variable / coord that carries a standard_name attr
to that attr value. Raises ValueError on collision (two source
vars mapping to the same standard_name).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
include_coords
|
bool
|
If |
True
|
Source code in packages/xrtoolz-ops/src/xrops/cf/operators.py
RenameFromCFStandardNames
¶
RenameFromCFStandardNames(*, fallback: Literal['passthrough', 'raise'] = 'passthrough', include_coords: bool = True)
Bases: Operator
Wrap :func:xrops.cf.rename_from_cf_standard_names.
Renames CF standard_name-shaped variables to their xrops
canonical names using the :mod:xrproducts.types.Variable registry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fallback
|
Literal['passthrough', 'raise']
|
|
'passthrough'
|
include_coords
|
bool
|
If |
True
|
Source code in packages/xrtoolz-ops/src/xrops/cf/operators.py
Functional primitives (Layer 0)¶
These pure functions back the operators above; each takes xr.DataArray/xr.Dataset and a dim: argument.
check_dataset_coords
¶
check_dataset_coords(ds: Dataset, *, require: tuple[str, ...] = ('time', 'lat', 'lon'), validate: bool = True) -> None
Assert that required coordinates are present and (optionally) valid.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ds
|
Dataset
|
Dataset to check. |
required |
require
|
tuple[str, ...]
|
Names that must appear in |
('time', 'lat', 'lon')
|
validate
|
bool
|
When |
True
|
Raises:
| Type | Description |
|---|---|
AssertionError
|
If any name in |
Source code in packages/xrtoolz-ops/src/xrops/cf/_src/validation.py
validate_longitude
¶
Normalize the longitude coordinate.
Renames longitude to lon if present, wraps values into the
[-180, 180) range, and assigns CF units, standard_name,
and long_name attributes (preserving any pre-existing attrs).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ds
|
Dataset
|
Input dataset. |
required |
Returns:
| Type | Description |
|---|---|
Dataset
|
Dataset with a harmonized |
Source code in packages/xrtoolz-ops/src/xrops/cf/_src/validation.py
validate_latitude
¶
Normalize the latitude coordinate.
Renames latitude to lat if present, wraps values into the
[-90, 90) range, and assigns CF units, standard_name,
and long_name attributes (preserving any pre-existing attrs).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ds
|
Dataset
|
Input dataset. |
required |
Returns:
| Type | Description |
|---|---|
Dataset
|
Dataset with a harmonized |
Source code in packages/xrtoolz-ops/src/xrops/cf/_src/validation.py
validate_time
¶
validate_time(ds: Dataset, *, time: str = 'time', unit: str | None = None, origin: str = 'unix') -> Dataset
Coerce the time coordinate to pandas datetime.
Strings and datetime64 arrays pass through unchanged. For
numeric inputs, unit and origin must be supplied so the
values can be interpreted unambiguously — otherwise
:func:pandas.to_datetime defaults to nanoseconds since the Unix
epoch, which silently mangles common "seconds since 1970-01-01"
encodings.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ds
|
Dataset
|
Input dataset. |
required |
time
|
str
|
Name of the time coordinate. |
'time'
|
unit
|
str | None
|
Forwarded to :func: |
None
|
origin
|
str
|
Forwarded to :func: |
'unix'
|
Returns:
| Type | Description |
|---|---|
Dataset
|
Dataset with the time coordinate cast to |
Dataset
|
preserving the original dims and attrs. |
Source code in packages/xrtoolz-ops/src/xrops/cf/_src/validation.py
decode_cf_time
¶
Assign a CF units attribute and decode the time coordinate.
Useful when raw integer / float time values and their epoch string arrive separately (e.g. CMEMS NetCDF or older OPeNDAP feeds).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ds
|
Dataset
|
Input dataset. |
required |
time
|
str
|
Name of the time coordinate. |
'time'
|
units
|
str | None
|
CF |
None
|
Returns:
| Type | Description |
|---|---|
Dataset
|
Dataset with the time coordinate decoded to |
Source code in packages/xrtoolz-ops/src/xrops/cf/_src/validation.py
rename_coords
¶
Rename any coordinates or variables that match mapping.
Keys not present in ds are silently ignored, so this helper is
safe to use as a first-pass harmonizer without pre-checking names.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ds
|
Dataset
|
Input dataset. |
required |
mapping
|
dict[str, str]
|
|
required |
Returns:
| Type | Description |
|---|---|
Dataset
|
Dataset with matching names renamed. |
Source code in packages/xrtoolz-ops/src/xrops/cf/_src/validation.py
rename_variables
¶
Rename data variables that match mapping.
Companion to :func:rename_coords: rename_variables only acts on
entries in ds.data_vars so a typo in mapping doesn't silently
rename a coordinate. Keys not present in ds.data_vars are
ignored.
Source code in packages/xrtoolz-ops/src/xrops/cf/_src/validation.py
rename_to_cf_standard_names
¶
Rename variables to their declared CF standard_name attribute.
For every variable / coord with a non-empty standard_name attr,
rename to that value. Variables without the attr are left unchanged.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ds
|
Dataset
|
Input dataset. |
required |
include_coords
|
bool
|
If |
True
|
Returns:
| Type | Description |
|---|---|
Dataset
|
Dataset with matching variables renamed to their CF |
Dataset
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If two source variables resolve to the same CF
|
Source code in packages/xrtoolz-ops/src/xrops/cf/_src/validation.py
rename_from_cf_standard_names
¶
rename_from_cf_standard_names(ds: Dataset, *, fallback: Literal['passthrough', 'raise'] = 'passthrough', include_coords: bool = True) -> Dataset
Rename CF standard_name-shaped variables to xrops canonical names.
Uses the :mod:xrproducts.types.Variable registry as the authoritative
standard_name → canonical_name mapping. Variables / coords whose
name is not a registered CF standard_name pass through unchanged
(fallback="passthrough", default) or raise KeyError
(fallback="raise").
Single-word names (e.g. "ssh") are never flagged as unknown — they
are already canonical and pass through silently regardless of
fallback.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ds
|
Dataset
|
Input dataset. |
required |
fallback
|
Literal['passthrough', 'raise']
|
|
'passthrough'
|
include_coords
|
bool
|
If |
True
|
Returns:
| Type | Description |
|---|---|
Dataset
|
Dataset with CF-named variables renamed to their canonical |
Dataset
|
xrops names. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
KeyError
|
If |
Source code in packages/xrtoolz-ops/src/xrops/cf/_src/validation.py
calc_latlon
¶
Add 2-D latitude / longitude coords computed from x/y.
Assumes ds has 1-D x and y coordinates and a CRS attached
(ds.rio.crs). Inf values from the transform are replaced with
NaN so that downstream masking handles them cleanly. This is the
inverse direction of :func:assign_local_xy for gridded rasters:
projected x/y axes in, geographic coordinates out.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ds
|
Dataset
|
Input dataset. |
required |
Returns:
| Type | Description |
|---|---|
Dataset
|
Dataset with additional 2-D |
Dataset
|
coordinates along |
Source code in packages/xrtoolz-ops/src/xrops/geom/_src/crs.py
get_dataset_resolution
¶
get_dataset_resolution(ds: Dataset, *, lon: str = 'lon', lat: str = 'lat', rtol: float = 0.05) -> GridResolution
Classify a regular lat/lon grid against canonical OceanBench resolutions.
Returns one of "one_degree", "quarter_degree",
"twelfth_degree", or "other" (no canonical resolution
matches within rtol of both axes). Useful for dispatch — e.g.
picking the right MDT URL or the right reference dataset for a
given grid.
The classifier checks the median absolute spacing of the lon
and lat coordinates independently — an anisotropic grid
(e.g. dlon=1.1 but dlat=0.9) is rejected even though its
averaged spacing would round to 1°. Curvilinear (2-D) lon/lat
coordinates are rejected with a ValueError: np.diff on a
multi-dim array would silently mix endpoints across rows and
misclassify the grid.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ds
|
Dataset
|
Dataset carrying 1-D |
required |
lon
|
str
|
Longitude coordinate name. |
'lon'
|
lat
|
str
|
Latitude coordinate name. |
'lat'
|
rtol
|
float
|
Relative tolerance for the canonical-resolution match, applied per-axis. |
0.05
|
Returns:
| Type | Description |
|---|---|
GridResolution
|
Resolution label as a |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in packages/xrtoolz-ops/src/xrops/geom/_src/crs.py
median_dx_km
¶
Median geodesic spacing between consecutive points in kilometres.
The inputs must be 1-D — a flattened multi-track array would mix
endpoints from unrelated tracks into the spacing estimate, biasing
the inferred FIR cutoff. For multi-track datasets, derive spacing
per track or pass spacing_km to :func:bandpass_wavelength
explicitly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lon
|
ArrayLike
|
1-D longitude samples in degrees. |
required |
lat
|
ArrayLike
|
1-D latitude samples in degrees, same shape as |
required |
Returns:
| Type | Description |
|---|---|
float
|
Median WGS-84 geodesic segment length in kilometres. |
Source code in packages/xrtoolz-ops/src/xrops/wavelets/_src/along_track.py
geometric_scales
¶
geometric_scales(s0: float, *, octaves: float, voices_per_octave: int = 8, name: str = 'scale') -> DataArray
Return a geometric wavelet scale grid.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
s0
|
float
|
Smallest positive scale. |
required |
octaves
|
float
|
Number of octaves to span from |
required |
voices_per_octave
|
int
|
Number of samples per octave. |
8
|
name
|
str
|
Scale dimension and DataArray name. |
'scale'
|
Returns:
| Type | Description |
|---|---|
DataArray
|
DataArray with one dimension named |
Source code in packages/xrtoolz-ops/src/xrops/wavelets/_src/wavelet_utils.py
scale_to_wavenumber
¶
scale_to_wavenumber(scales: DataArray | ndarray, *, x0: float, k0: float = 1.0) -> DataArray | ndarray
Convert Morlet scales to central wavenumber k = k0 / (s x0).
Source code in packages/xrtoolz-ops/src/xrops/wavelets/_src/wavelet_utils.py
wavenumber_to_scale
¶
wavenumber_to_scale(wavenumber: DataArray | ndarray, *, x0: float, k0: float = 1.0) -> DataArray | ndarray
Convert central wavenumber to Morlet scale.