Introduction to Precipitation-based Climate Indices¶
This notebook demonstrates how to compute and visualize precipitation-based climate indices from CMIP6 datasets using the earthkit-climate and xclim packages.
We use:
Precipitation-based indices:
SDII: Simple Daily Intensity Index (average precipitation on wet days)
CWD: Consecutive Wet Days (max number of wet days in a row)
We load ACCESS-CM2 CMIP6 data for both historical and SSP585 scenarios.
[3]:
import warnings
from typing import Any, List, Union
import cartopy.crs as ccrs
import earthkit.data as ekd
import earthkit.plots as ekp
import matplotlib.pyplot as plt
import xarray as xr
from earthkit.climate.atmos import precipitation
warnings.filterwarnings("ignore")
plt.rcParams["figure.figsize"] = (8, 5)
def plot_climatology(
figure: Any, data: xr.DataArray, row: int, col: int, title: str, cmap: Union[str, List[str]], units: str
) -> None:
"""
Compute and plot the temporal mean of a dataset on a map.
Parameters
----------
figure : Any
The figure or layout object where the map will be added.
data : xarray.DataArray
The input data containing a 'time' dimension to calculate the climatology.
row : int
Row index in the figure grid.
col : int
Column index in the figure grid.
title : str
Title for the specific map plot.
cmap : str or list of str
Color map name or list of colors for the plot style.
units : str
Units of the data for styling and legend labeling.
Returns
-------
None
The function modifies the `figure` object in place and does not return a value.
"""
# Compute climatology (mean over time)
climatology: xr.DataArray = data.mean("time")
# Define style and plot
# 'ekp' seems to be the library providing the Style and mapping tools
style = ekp.styles.Style(colors=cmap, units=units)
# The domain is now explicitly defined within the function
map_plot = figure.add_map(row=row, column=col, domain=[-7.5, 0, 35.8, 40.2])
map_plot.quickplot(climatology, style=style)
map_plot.coastlines()
map_plot.gridlines()
map_plot.title(title)
map_plot.legend(location="right")
Loading CMIP6 data¶
We’ll use daily gridded data from the ACCESS-CM2 model for precipitation (pr), for both historical and SSP585 future scenarios.
[4]:
# Load precipitation
pr_hist = ekd.from_source("earthkit-climate-sample", "pr_ACCESS-CM2_historical_reference").to_xarray()
pr_ssp585 = ekd.from_source("earthkit-climate-sample", "pr_ACCESS-CM2_ssp585_far_future").to_xarray()
Inspect and visualize the raw data¶
Before computing indices, let’s plot an example grid to see how the raw precipitation looks.
[5]:
# Create the figure with 2x1 maps
figure = ekp.Figure(
crs=ccrs.NearsidePerspective(central_longitude=-3.75, central_latitude=38.0), rows=2, columns=1, size=(15, 10)
)
# HISTORICAL (row 0)
plot_climatology(figure, pr_hist, 0, 0, "pr Climatology (Historical)", "winter_r", "mm/day")
# SSP585 (row 1)
plot_climatology(figure, pr_ssp585, 1, 0, "pr Climatology (SSP585)", "winter_r", "mm/day")
# Final layout
figure.show()
Compute Simple Daily Intensity Index (SDII)¶
SDII measures the average precipitation amount on wet days (days with precipitation ≥ 1mm). We’ll compute it for the SSP585 far-future scenario.
[6]:
# Compute SDII
sdii = precipitation.daily_pr_intensity(pr_ssp585)
sdii
[6]:
<xarray.DataArray 'sdii' (time: 30, lat: 88, lon: 150)> Size: 3MB
array([[[ nan, nan, nan, ..., nan,
nan, nan],
[ nan, nan, nan, ..., nan,
nan, nan],
[ nan, nan, nan, ..., nan,
nan, nan],
...,
[ nan, nan, nan, ..., 6.63561452,
6.55609233, 6.48983358],
[ nan, nan, nan, ..., 6.29743819,
6.24785406, 6.42913342],
[ nan, nan, nan, ..., 6.31784566,
6.33416147, 6.35642543]],
[[ nan, nan, nan, ..., nan,
nan, nan],
[ nan, nan, nan, ..., nan,
nan, nan],
[ nan, nan, nan, ..., nan,
nan, nan],
...
[ nan, nan, nan, ..., 4.61072597,
4.21700033, 4.31832412],
[ nan, nan, nan, ..., 4.64442117,
4.38835551, 4.43652395],
[ nan, nan, nan, ..., 4.53679368,
4.46416016, 4.61755739]],
[[ nan, nan, nan, ..., nan,
nan, nan],
[ nan, nan, nan, ..., nan,
nan, nan],
[ nan, nan, nan, ..., nan,
nan, nan],
...,
[ nan, nan, nan, ..., 8.2550745 ,
8.18688679, 8.16620064],
[ nan, nan, nan, ..., 8.58276272,
8.57730961, 8.65119648],
[ nan, nan, nan, ..., 8.66877937,
8.74799538, 8.83212852]]], shape=(30, 88, 150))
Coordinates:
* time (time) datetime64[ns] 240B 2071-01-01 2072-01-01 ... 2100-01-01
* lat (lat) float64 704B 35.82 35.87 35.92 35.97 ... 40.07 40.12 40.17
* lon (lon) float64 1kB -7.475 -7.425 -7.375 ... -0.125 -0.075 -0.025
height float64 8B 2.0
Attributes:
units: mm d-1
cell_methods:
history: [2026-06-02 16:39:07] sdii: SDII(pr=pr, thresh='1 mm/day'...
standard_name: lwe_thickness_of_precipitation_amount
long_name: Average precipitation during days with daily precipitatio...
description: Annual simple daily intensity index (sdii) or annual aver...Compute Consecutive Wet Days (CWD)¶
CWD calculates the maximum number of consecutive days with precipitation ≥ 1mm per period (annually in this case).
[7]:
# Compute CWD
cwd = precipitation.maximum_consecutive_wet_days(pr_ssp585)
cwd
[7]:
<xarray.DataArray 'cwd' (time: 30, lat: 88, lon: 150)> Size: 2MB
array([[[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
...,
[nan, nan, nan, ..., 4., 4., 4.],
[nan, nan, nan, ..., 5., 5., 5.],
[nan, nan, nan, ..., 5., 5., 5.]],
[[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
...,
[nan, nan, nan, ..., 5., 5., 5.],
[nan, nan, nan, ..., 5., 5., 5.],
[nan, nan, nan, ..., 5., 5., 5.]],
[[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
...,
...
[nan, nan, nan, ..., 6., 6., 6.],
[nan, nan, nan, ..., 5., 5., 5.],
[nan, nan, nan, ..., 5., 5., 5.]],
[[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
...,
[nan, nan, nan, ..., 3., 3., 3.],
[nan, nan, nan, ..., 3., 3., 3.],
[nan, nan, nan, ..., 3., 3., 3.]],
[[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
...,
[nan, nan, nan, ..., 5., 5., 5.],
[nan, nan, nan, ..., 5., 5., 5.],
[nan, nan, nan, ..., 5., 5., 5.]]],
shape=(30, 88, 150), dtype=float32)
Coordinates:
* time (time) datetime64[ns] 240B 2071-01-01 2072-01-01 ... 2100-01-01
* lat (lat) float64 704B 35.82 35.87 35.92 35.97 ... 40.07 40.12 40.17
* lon (lon) float64 1kB -7.475 -7.425 -7.375 ... -0.125 -0.075 -0.025
height float64 8B 2.0
Attributes:
units: days
cell_methods: time: sum over days
history: [2026-06-02 16:39:11] cwd: CWD(pr=pr, thresh='1 mm/day', ...
standard_name: number_of_days_with_lwe_thickness_of_precipitation_amount...
long_name: Maximum consecutive days with daily precipitation at or a...
description: Annual maximum number of consecutive days with daily prec...Visualization of Precipitation Indices¶
Let’s visualize the climatologies (average across years) of these precipitation indices.
[8]:
# Create the figure with 1x2 maps
figure = ekp.Figure(
crs=ccrs.NearsidePerspective(central_longitude=-5, central_latitude=43), rows=1, columns=2, size=(12, 6)
)
# Plot SDII
plot_climatology(figure, sdii, 0, 0, "SDII Climatology (SSP585)", "YlGnBu", "mm d-1")
# Plot CWD
plot_climatology(figure, cwd, 0, 1, "CWD Climatology (SSP585)", "Blues", "days")
# Final layout
figure.show()