Skip to content

xarray

synthetic

Synthetic climate datasets shaped like open-climate-service stores.

Every generator returns an xr.Dataset with dims (time, y, x) — the normalized layout OCS writes to its zarr stores — daily time steps, lat/lon-like coordinates on a regular grid, and CF-style attrs (units, long_name). Deterministic for a given seed, so examples and tests are reproducible.

Functions:

temperature_dataset(days=30, ny=20, nx=30, seed=0)

Return a daily 2 m temperature dataset with dims (time, y, x).

Values are degrees Celsius: a base field with a north-south gradient, a seasonal-ish sine over time, and gaussian noise.

Parameters:

Name Type Description Default
days int

Number of daily time steps; must be at least 1.

30
ny int

Grid height; must be at least 1.

20
nx int

Grid width; must be at least 1.

30
seed int

Seed for the random noise component.

0

Returns:

Type Description
Dataset

A dataset with one data variable t2m and coords time/y/x.

Raises:

Type Description
ValueError

If days, ny, or nx is less than 1.

Source code in xarray/src/ocs_stack_xarray/synthetic.py
def temperature_dataset(days: int = 30, ny: int = 20, nx: int = 30, seed: int = 0) -> xr.Dataset:
    """Return a daily 2 m temperature dataset with dims (time, y, x).

    Values are degrees Celsius: a base field with a north-south gradient, a
    seasonal-ish sine over time, and gaussian noise.

    Args:
        days: Number of daily time steps; must be at least 1.
        ny: Grid height; must be at least 1.
        nx: Grid width; must be at least 1.
        seed: Seed for the random noise component.

    Returns:
        A dataset with one data variable ``t2m`` and coords time/y/x.

    Raises:
        ValueError: If days, ny, or nx is less than 1.
    """
    _validate(days, ny, nx)
    rng = np.random.default_rng(seed)
    time = pd.date_range("2024-01-01", periods=days, freq="D")
    y, x = _grid(ny, nx)

    gradient = np.linspace(2.0, -2.0, ny).reshape(1, ny, 1)
    season = 3.0 * np.sin(2 * np.pi * np.arange(days) / 365.25).reshape(days, 1, 1)
    noise = rng.normal(0.0, 0.8, size=(days, ny, nx))
    values = 26.0 + gradient + season + noise

    da = xr.DataArray(
        values,
        dims=("time", "y", "x"),
        coords={"time": time, "y": y, "x": x},
        name="t2m",
        attrs={"units": "degC", "long_name": "2 metre temperature"},
    )
    return da.to_dataset()

precipitation_dataset(days=30, ny=20, nx=30, seed=0)

Return a daily precipitation dataset with dims (time, y, x).

Values are mm/day: zero on dry days (roughly 60 percent of the field), gamma-distributed amounts otherwise — the zero-inflated shape real rainfall data has, which matters for masking and skipna examples.

Parameters:

Name Type Description Default
days int

Number of daily time steps; must be at least 1.

30
ny int

Grid height; must be at least 1.

20
nx int

Grid width; must be at least 1.

30
seed int

Seed for the random components.

0

Returns:

Type Description
Dataset

A dataset with one data variable tp and coords time/y/x.

Raises:

Type Description
ValueError

If days, ny, or nx is less than 1.

Source code in xarray/src/ocs_stack_xarray/synthetic.py
def precipitation_dataset(days: int = 30, ny: int = 20, nx: int = 30, seed: int = 0) -> xr.Dataset:
    """Return a daily precipitation dataset with dims (time, y, x).

    Values are mm/day: zero on dry days (roughly 60 percent of the field),
    gamma-distributed amounts otherwise — the zero-inflated shape real rainfall
    data has, which matters for masking and skipna examples.

    Args:
        days: Number of daily time steps; must be at least 1.
        ny: Grid height; must be at least 1.
        nx: Grid width; must be at least 1.
        seed: Seed for the random components.

    Returns:
        A dataset with one data variable ``tp`` and coords time/y/x.

    Raises:
        ValueError: If days, ny, or nx is less than 1.
    """
    _validate(days, ny, nx)
    rng = np.random.default_rng(seed)
    time = pd.date_range("2024-01-01", periods=days, freq="D")
    y, x = _grid(ny, nx)

    wet = rng.random(size=(days, ny, nx)) > 0.6
    amounts = rng.gamma(shape=2.0, scale=4.0, size=(days, ny, nx))
    values = np.where(wet, amounts, 0.0)

    da = xr.DataArray(
        values,
        dims=("time", "y", "x"),
        coords={"time": time, "y": y, "x": x},
        name="tp",
        attrs={"units": "mm/day", "long_name": "total precipitation"},
    )
    return da.to_dataset()