Skip to content

Climate Indices

The Open Climate Service exposes the full xclim indicator library — 179 peer-reviewed, CF-compliant climate extreme indices — as native openEO processes. Every indicator appears automatically in GET /processes and is callable by name from any openEO process graph or client, with no additional configuration.


What is available

All xclim indicator modules are covered:

Module Domain Examples
atmos Atmospheric SPI, CDD, CWD, TX days above, heat wave frequency, frost days, growing degree days, …
land Land surface Snow water equivalent, soil freeze/thaw, …
seaIce Sea ice Ice extent, concentration trends

Browse the full list from any connected client:

import openeo

conn = openeo.connect("http://your-instance:9000")
processes = conn.list_processes()
print([p.id for p in processes])

Or call GET /processes directly and search by keyword. In the openEO Web Editor, the search box filters by id and summary.


Standardized Precipitation Index (SPI)

SPI is the primary drought monitoring index. The window parameter selects the accumulation timescale:

Process call Timescale
spi(pr, window=1) SPI-1 — short-term moisture anomaly
spi(pr, window=3) SPI-3 — seasonal drought
spi(pr, window=6) SPI-6 — medium-term drought
spi(pr, window=12) SPI-12 — long-term / groundwater recharge

Python client

import openeo

conn = openeo.connect("http://your-instance:9000")

precip = conn.load_collection(
    "chirps_rainfall_daily",
    temporal_extent=["2000-01-01", "2023-12-31"],
)

spi3 = precip.process("spi", arguments={
    "pr": precip,
    "window": 3,
    "cal_start": "2000-01-01",
    "cal_end": "2020-12-31",
})

job = spi3.save_result("Zarr").create_job()
job.start_and_wait()

Process graph (JSON)

{
  "process_graph": {
    "load": {
      "process_id": "load_collection",
      "arguments": {
        "id": "chirps_rainfall_daily",
        "temporal_extent": ["2000-01-01", "2023-12-31"]
      }
    },
    "spi": {
      "process_id": "spi",
      "arguments": {
        "pr": { "from_node": "load" },
        "window": 3,
        "cal_start": "2000-01-01",
        "cal_end": "2020-12-31"
      },
      "result": true
    }
  }
}

Parameters

Parameter Type Default Description
pr datacube Daily precipitation (kg m⁻² s⁻¹ or mm/day)
window integer 1 Accumulation window in months (1=SPI-1, 3=SPI-3, 6=SPI-6)
cal_start string start of record Calibration period start (YYYY-MM-DD)
cal_end string end of record Calibration period end (YYYY-MM-DD)
freq string "MS" Output frequency — "MS" = monthly, None = pre-aggregated input

SPI values are standardised: 0 = climatological median, ±1 = moderate anomaly, ±2 = extreme anomaly.


Other common indices

Consecutive dry / wet days

# Annual maximum consecutive dry days (CDD)
precip.process("cdd", arguments={"pr": precip, "thresh": "1 mm/day", "freq": "YS"})

# Monthly maximum consecutive wet days (CWD)
precip.process("cwd", arguments={"pr": precip, "thresh": "1 mm/day", "freq": "MS"})

Days above temperature threshold

# TX days above 35°C per year
tmax.process("tx_days_above", arguments={"tasmax": tmax, "thresh": "35 degC", "freq": "YS"})

Heat wave frequency

# Annual count of heat waves (≥3 consecutive days with Tmax>35°C and Tmin>20°C)
tmax.process("heat_wave_frequency", arguments={
    "tasmin": tmin,
    "tasmax": tmax,
    "thresh_tasmin": "20 degC",
    "thresh_tasmax": "35 degC",
    "freq": "YS",
})

Derived meteorological variables (earthkit-meteo)

Alongside the xclim indicators, the thermodynamic functions of ECMWF's earthkit-meteo are auto-registered as processes. These are not indices but derivations — quantities computed from other quantities, useful as inputs to an index or a health model:

Process Computes
relative_humidity_from_dewpoint Relative humidity (%) from temperature and dewpoint
dewpoint_from_relative_humidity Dewpoint from temperature and relative humidity
specific_humidity_from_dewpoint Specific humidity from dewpoint and pressure
wet_bulb_temperature_from_dewpoint Wet-bulb temperature — a heat-stress input
saturation_vapour_pressure Saturation vapour pressure over water/ice/mixed phase
potential_temperature, virtual_temperature Thermodynamic temperatures

Relative humidity is the common case, since the ERA5-Land source carries temperature and dewpoint but not humidity directly:

t2m = conn.load_collection("era5land_temperature_daily")
d2m = conn.load_collection("era5land_dewpoint_daily")

rh = t2m.process("relative_humidity_from_dewpoint", arguments={"t": t2m, "td": d2m})

Two things worth noting. Both cubes are passed explicitly — the collection you call .process() on is only the entry point, not an implicit first argument. And era5land_dewpoint_daily is not a built-in: the shipped ERA5-Land templates cover temperature (t2m) and precipitation (tp) only. Dewpoint needs a template of its own, which is a copy of the temperature one with variable: d2m — the same one-plugin-many-templates pattern described in Architecture.

Browse the full set in GET /processes; every function earthkit-meteo documents with a single cube output is registered.

Units are converted for you

These functions expect ECMWF's native units — temperature in K, pressure in Pa — and do no checking of their own. Our stores are usually not in those units: ERA5-Land temperature is converted to degC at ingest. Passing degC where K is expected produces no error, just a wrong number.

The registered processes therefore enforce units on the way in. A cube in a compatible unit is converted (degCK, hPaPa); a cube whose units attribute is missing or incompatible is rejected with an explanatory error.

So the call above needs no change on a degC store: era5land_temperature_daily and era5land_dewpoint_daily are both converted to K on the way in, and the answer is correct without a manual conversion step.

If a cube is rejected for missing units, the fix is to declare units on the variable in its dataset template — that value is what gets CF-stamped at ingest.


Customising an index

The auto-registered xclim processes can be overridden per-instance by placing a @process-decorated function with the same id in plugins_dir/processes/. This is useful for adjusting default parameters or adding domain-specific documentation without modifying shared code.

# plugins/processes/climate_indices.py
import xarray as xr
import xclim.indicators.atmos as xclim_atmos
from open_climate_service.process import process

@process(summary="Consecutive dry days (Rwanda threshold)")
def cdd(pr: xr.DataArray, thresh: str = "0.5 mm/day", freq: str = "MS") -> xr.DataArray:
    """CDD with a lower threshold suited to Rwanda's dry season definition."""
    return xclim_atmos.maximum_consecutive_dry_days(pr, thresh=thresh, freq=freq)

See Extensibility — Processes for the full @process decorator reference.


References