"""Implementation of the ARIS-lite model package."""
__version__ = "0.3.0"
from collections.abc import Iterable
from typing import TYPE_CHECKING, Literal
from aris_lite.deprecation import warn_legacy_python_api
if TYPE_CHECKING:
import xarray as xr
CROPS = [
"winter wheat",
"spring barley",
"maize",
"soybean",
"norm potato",
"grassland",
]
type T_crop_names = Literal[
"winter wheat",
"spring barley",
"maize",
"soybean",
"norm potato",
"grassland",
]
[docs]
def run_1go(
ds: "xr.Dataset",
crops: Iterable[T_crop_names],
) -> "xr.Dataset":
"""
Run the in-memory 1go ARIS-lite workflow on a single dataset.
This routine computes snow, phenology, soil-water outputs, and top-layer
waterstress. It intentionally does not compute yield outputs.
"""
import xarray as xr
from aris_lite.phenology import compute_phenology_variables
from aris_lite.water_budget import calc_snow, calc_soil_water
def _load_resample_apply(input_ds, func, *args, **kwargs):
return (
input_ds.load()
.resample(time="YE")
.map(func, args=args, **kwargs)
.assign_coords(time=("time", input_ds.time.data))
)
out = xr.merge(
[
ds,
calc_snow(
ds.assign(
initial_snowcover=xr.zeros_like(ds.precipitation.isel(time=0))
)
).persist(),
]
)
out = xr.merge(
[
out,
(
xr.coding.calendar_ops.convert_calendar( # pyright: ignore[reportAttributeAccessIssue]
out.air_temperature.where(~(out.snowcover > 0)), "gregorian"
).pipe(
_load_resample_apply,
compute_phenology_variables,
crops,
)
).persist(),
]
)
out = xr.merge(
[
out,
out.map_blocks(
_load_resample_apply,
args=(calc_soil_water,),
template=xr.Dataset(
{
var: xr.zeros_like(out.Kc_factor.broadcast_like(out.TAW))
.transpose(*out.Kc_factor.dims, ...)
.chunk(out.chunks)
for var in ["evapotranspiration", "evapo_ETC", "soil_depletion"]
}
),
)
.chunk(out.chunks)
.persist(),
]
)
out = out.assign(
waterstress=(out.soil_depletion * 100 / out.TAW)
.sel(layer="top")
.persist()
)
return out.map(lambda da: da.astype("float32") if da.dtype.kind == "f" else da)
[docs]
def aris_1go(
ds: "xr.Dataset",
crops: Iterable[T_crop_names],
) -> "xr.Dataset":
"""Legacy alias for :func:`run_1go`."""
warn_legacy_python_api("aris_lite.aris_1go", "aris_lite.run_1go")
return run_1go(ds=ds, crops=crops)
[docs]
def main_cli(argv: list[str] | None = None) -> int:
"""Legacy CLI alias for `aris-1go`; use `aris 1go`."""
warn_legacy_python_api("aris_lite.main_cli", "aris_lite.cli.main:main_cli")
from aris_lite.cli.legacy_wrappers import legacy_1go_cli
return legacy_1go_cli(argv=argv, emit_warning=False)
[docs]
def cli(argv: list[str] | None = None) -> int:
"""Legacy CLI alias for `aris-1go`; use `aris 1go`."""
warn_legacy_python_api("aris_lite.cli", "aris_lite.cli.main:main_cli")
from aris_lite.cli.legacy_wrappers import legacy_1go_cli
return legacy_1go_cli(argv=argv, emit_warning=False)
__all__ = [
"CROPS",
"T_crop_names",
"run_1go",
"aris_1go",
"main_cli",
"cli",
"extract_point_data",
]