terraflow.cmip6¶
CMIP6 NetCDF scenario ingest behind the optional [cmip6] install extra.
The module opens climate scenario NetCDFs (typically daily tas or pr
cubes), samples them at station coordinates, and returns the long-format
station time-series that the terraflow.temporal aggregation engine
consumes.
Install¶
This installs xarray>=2024.1 and netcdf4>=1.7. They are imported lazily
inside each callable so users on the historical CSV path never pay the
import cost.
Overview¶
cmip6_metadata(path)— SHA-256 + size + CMIP6 global attrs (variant_label, source_id, experiment_id, institution_id, table_id). Exposed as a public helper so callers can fold NetCDF provenance into their own manifest. The mainterraflow runpipeline does not yet ingest NetCDFs directly — users today convert each NetCDF to a long-format station CSV viacmip6_to_station_timeseries(...)and the CSV's SHA-256 enters the run fingerprint via the existing_collect_input_pathspath. First-classclimate.cmip6_scenarios:config support (per-NetCDF SHA-256 + unit conversion + calendar handling inside the pipeline) ships in v0.6.0 — see issue #148.load_cmip6_scenario(path, variable, period)— opens a NetCDF lazily and slices the time axis by an inclusive(year_min, year_max)window. Handles non-Gregorian calendars (365_day,noleap,360_day) via the calendar-awaredt.yearpath.extract_station_timeseries(da, stations, output_variable)— vectorised nearest-neighbour selection at station coordinates. Returns a DataFrame in the shape(station_id, lat, lon, date, <output_variable>).cmip6_to_station_timeseries(path, stations, ...)— one-call wrapper around the previous two.
Tolerates both lat/lon and latitude/longitude coord names commonly
seen across CMIP6 sources.
Quick example¶
import pandas as pd
from terraflow.cmip6 import cmip6_to_station_timeseries
stations = pd.DataFrame({
"station_id": ["KS01", "KS02", "KS03"],
"lat": [38.5, 39.0, 39.5],
"lon": [-100.5, -100.0, -99.5],
})
ts = cmip6_to_station_timeseries(
"data/cmip6/tas_day_MPI-ESM1-2-HR_historical_19910101-20201231.nc",
stations,
period=(1991, 2020),
output_variable="temperature_c",
)
API Reference¶
cmip6
¶
CMIP6 NetCDF scenario ingest (flagship #138c).
Reads a CMIP6 scenario NetCDF (typically a CF-compliant daily-or-monthly
temperature_c or precipitation_mm cube) and samples it at station
coordinates, producing the long-format DataFrame shape that the
:mod:terraflow.temporal aggregation engine consumes.
The module is gated behind the optional [cmip6] install extra so the
default install stays lean::
pip install "terraflow-agro[cmip6]"
Imports xarray and netCDF4 lazily inside each callable so users
who only run the historical CSV path never pay the import cost.
Expected NetCDF shape (CF convention):
- Dimensions: time, lat / latitude, lon / longitude.
- A single primary data variable (e.g. tas for near-surface
temperature, pr for precipitation).
- Global attributes optionally containing variant_label,
source_id, and experiment_id (folded into the run fingerprint
by the pipeline in #138e).
The module deliberately does NOT depend on terraflow.config — it is
a thin adapter so the temporal engine can stay format-agnostic.
cmip6_metadata(path)
¶
Extract CMIP6 provenance attributes from a NetCDF file.
Returns a dict with keys sha256 (file content hash),
size_bytes, and a subset of variant_label, source_id,
experiment_id, institution_id, table_id when those
global attributes are set on the file.
The pipeline (in #138e) folds this dict into the run fingerprint so different CMIP6 variants of the same SSP scenario yield distinct cache directories.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
Path to a CMIP6-conformant NetCDF file. The file is opened twice — once for SHA-256 hashing of bytes, once via xarray to read global attrs. |
required |
Source code in terraflow/cmip6.py
cmip6_to_station_timeseries(path, stations, *, variable=None, period=None, output_variable)
¶
Convenience: open a CMIP6 NetCDF and return a station time-series.
One-call wrapper around :func:load_cmip6_scenario +
:func:extract_station_timeseries. Yields a DataFrame in the shape
:mod:terraflow.temporal consumes.
Source code in terraflow/cmip6.py
extract_station_timeseries(da, stations, *, output_variable)
¶
Sample a CMIP6 DataArray at each station's (lat, lon) coordinates.
Uses nearest-neighbour selection on the lat/lon coordinates. The
output is a long-format DataFrame in the shape consumed by
:mod:terraflow.temporal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
da
|
Any
|
An xarray DataArray with |
required |
stations
|
DataFrame
|
DataFrame with at minimum |
required |
output_variable
|
str
|
Name of the climate variable column in the output (e.g.
|
required |
Returns:
| Type | Description |
|---|---|
pd.DataFrame:
|
Columns |
Source code in terraflow/cmip6.py
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 | |
load_cmip6_scenario(path, *, variable=None, period=None)
¶
Open a CMIP6 NetCDF and return the requested DataArray (lazy).
The result is an xarray DataArray indexed by time, lat, lon
(or time, latitude, longitude). The underlying data is loaded
lazily — pulling a station's full time-series is what materialises
values from disk.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str | Path
|
Path to a CMIP6 NetCDF file. |
required |
variable
|
str | None
|
Data variable name to extract. Optional when the file contains exactly one variable. |
None
|
period
|
tuple[int, int] | None
|
|
None
|