Calculate the Averaged Temperature Anomaly#

Averaged Temperature Anomaly 2081-2100 vs 1971-2000 SSP585#

This example calculates the averaged temperature anomaly (using the TG indicator) for the period 2081-2100 compared to the reference 1971-2000 for SSP585 and several climate models.

We assume to have the tas variable in netCDF files in a ./data folder. The data can be dowloaded using the metalink provided with this notebook. The data described in a .metalink file can be dowloaded with tools such as aria2 or a browser plugin such as DownThemAll! If you wish to use a different dataset, you can use the climate 4 impact portal to search and select the data you wish to use and a metalink file to the ESGF data will be provided.

The data is read using xarray and a plot of the time series averaged over Europe is generated, as well as an average spatial map. Several output types examples are shown.

The datasets that are expected for this notebook are tas parameter (needed to calculate the TG indicator) for several climate models, for the historical (1971-2000) and ssp585 (2081-2100) experiments and for one member. Daily data is used. In C4I, you can find all of the data needed in the CMIP6 project, at the esgf-data3.ceda.ac.uk and esgf3.dkrz.de mirrors.

Preparation of the needed modules#

[2]:
%pip install icclim matplotlib nc_time_axis
Requirement already satisfied: icclim in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (6.6.0)
Requirement already satisfied: matplotlib in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (3.8.2)
Collecting nc_time_axis
  Downloading nc_time_axis-1.4.1-py3-none-any.whl (17 kB)
Requirement already satisfied: numpy>=1.16 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from icclim) (1.26.2)
Requirement already satisfied: xarray>=2022.6 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from icclim) (2023.10.1)
Requirement already satisfied: xclim<=0.47,>=0.45 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from icclim) (0.47.0)
Requirement already satisfied: cf_xarray>=0.7.4 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from icclim) (0.8.6)
Requirement already satisfied: cftime>=1.4.1 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from icclim) (1.6.3)
Requirement already satisfied: dask[array] in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from icclim) (2023.12.1)
Requirement already satisfied: netCDF4>=1.5.7 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from icclim) (1.6.5)
Requirement already satisfied: psutil in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from icclim) (5.9.7)
Requirement already satisfied: zarr in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from icclim) (2.16.1)
Requirement already satisfied: rechunker!=0.4,>=0.3 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from icclim) (0.5.2)
Requirement already satisfied: fsspec in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from icclim) (2023.12.2)
Requirement already satisfied: pandas>=1.3 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from icclim) (2.1.4)
Requirement already satisfied: dateparser in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from icclim) (1.2.0)
Requirement already satisfied: pint in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from icclim) (0.19.2)
Requirement already satisfied: jinja2 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from icclim) (3.1.2)
Requirement already satisfied: contourpy>=1.0.1 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from matplotlib) (1.2.0)
Requirement already satisfied: cycler>=0.10 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from matplotlib) (0.12.1)
Requirement already satisfied: fonttools>=4.22.0 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from matplotlib) (4.46.0)
Requirement already satisfied: kiwisolver>=1.3.1 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from matplotlib) (1.4.5)
Requirement already satisfied: packaging>=20.0 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from matplotlib) (23.2)
Requirement already satisfied: pillow>=8 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from matplotlib) (10.1.0)
Requirement already satisfied: pyparsing>=2.3.1 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from matplotlib) (3.1.1)
Requirement already satisfied: python-dateutil>=2.7 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from matplotlib) (2.8.2)
Requirement already satisfied: certifi in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from netCDF4>=1.5.7->icclim) (2023.11.17)
Requirement already satisfied: pytz>=2020.1 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from pandas>=1.3->icclim) (2023.3.post1)
Requirement already satisfied: tzdata>=2022.1 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from pandas>=1.3->icclim) (2023.3)
Requirement already satisfied: six>=1.5 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from python-dateutil>=2.7->matplotlib) (1.16.0)
Requirement already satisfied: mypy-extensions in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from rechunker!=0.4,>=0.3->icclim) (1.0.0)
Requirement already satisfied: boltons>=20.1 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from xclim<=0.47,>=0.45->icclim) (23.0.0)
Requirement already satisfied: bottleneck>=1.3.1 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from xclim<=0.47,>=0.45->icclim) (1.3.7)
Requirement already satisfied: Click>=8.1 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from xclim<=0.47,>=0.45->icclim) (8.1.7)
Requirement already satisfied: jsonpickle in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from xclim<=0.47,>=0.45->icclim) (3.0.2)
Requirement already satisfied: lmoments3>=1.0.5 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from xclim<=0.47,>=0.45->icclim) (1.0.6)
Requirement already satisfied: numba in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from xclim<=0.47,>=0.45->icclim) (0.58.1)
Requirement already satisfied: pyyaml in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from xclim<=0.47,>=0.45->icclim) (6.0.1)
Requirement already satisfied: scikit-learn>=0.21.3 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from xclim<=0.47,>=0.45->icclim) (1.3.2)
Requirement already satisfied: scipy>=1.2 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from xclim<=0.47,>=0.45->icclim) (1.11.4)
Requirement already satisfied: statsmodels in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from xclim<=0.47,>=0.45->icclim) (0.14.1)
Requirement already satisfied: cloudpickle>=1.5.0 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from dask[array]->icclim) (3.0.0)
Requirement already satisfied: partd>=1.2.0 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from dask[array]->icclim) (1.4.1)
Requirement already satisfied: toolz>=0.10.0 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from dask[array]->icclim) (0.12.0)
Requirement already satisfied: importlib-metadata>=4.13.0 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from dask[array]->icclim) (7.0.0)
Requirement already satisfied: asciitree in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from zarr->icclim) (0.3.3)
Requirement already satisfied: fasteners in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from zarr->icclim) (0.17.3)
Requirement already satisfied: numcodecs>=0.10.0 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from zarr->icclim) (0.12.1)
Requirement already satisfied: regex!=2019.02.19,!=2021.8.27 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from dateparser->icclim) (2023.10.3)
Requirement already satisfied: tzlocal in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from dateparser->icclim) (5.2)
Requirement already satisfied: MarkupSafe>=2.0 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from jinja2->icclim) (2.1.3)
Requirement already satisfied: zipp>=0.5 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from importlib-metadata>=4.13.0->dask[array]->icclim) (3.17.0)
Requirement already satisfied: locket in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from partd>=1.2.0->dask[array]->icclim) (1.0.0)
Requirement already satisfied: joblib>=1.1.1 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from scikit-learn>=0.21.3->xclim<=0.47,>=0.45->icclim) (1.3.2)
Requirement already satisfied: threadpoolctl>=2.0.0 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from scikit-learn>=0.21.3->xclim<=0.47,>=0.45->icclim) (3.2.0)
Requirement already satisfied: bokeh>=2.4.2 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from dask[array,diagnostics]->rechunker!=0.4,>=0.3->icclim) (3.3.2)
Requirement already satisfied: llvmlite<0.42,>=0.41.0dev0 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from numba->xclim<=0.47,>=0.45->icclim) (0.41.1)
Requirement already satisfied: patsy>=0.5.4 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from statsmodels->xclim<=0.47,>=0.45->icclim) (0.5.4)
Requirement already satisfied: tornado>=5.1 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from bokeh>=2.4.2->dask[array,diagnostics]->rechunker!=0.4,>=0.3->icclim) (6.3.3)
Requirement already satisfied: xyzservices>=2021.09.1 in /home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages (from bokeh>=2.4.2->dask[array,diagnostics]->rechunker!=0.4,>=0.3->icclim) (2023.10.1)
Installing collected packages: nc_time_axis
Successfully installed nc_time_axis-1.4.1
Note: you may need to restart the kernel to use updated packages.
[2]:
import datetime
import sys
from pathlib import Path

import icclim

# provides cftime axis in matplotlib
import numpy as np
import pandas as pd
import xarray as xr

print("python: ", sys.version)
print("numpy: ", np.__version__)
print("xarray: ", xr.__version__)
print("pandas: ", pd.__version__)
print("icclim: ", icclim.__version__)
python:  3.11.7 | packaged by conda-forge | (main, Dec 15 2023, 08:38:37) [GCC 12.3.0]
numpy:  1.26.2
xarray:  2023.10.1
pandas:  2.1.4
icclim:  6.6.0

Datasets#

The metafile associated with this notebook describes how to download the dataset we use here.
We reccomend to use aria2 to parse the metafile and download the dataset it describes.
On ubuntu, aria2 can be installed with sudo apt install -y aria2.

Specification of the parameters and period of interest#

The time period of interest as well as the reference period are defined here. A list of models is listed here as an example. Here we used Monthly data (Amon) but daily data could also be used. The corresponding datafiles must have been selected by the user, containing both the studied and referenced periods.

icclim is then executed for both periods for each climate model separately.

[8]:
# studied period
dt1 = datetime.datetime(2081, 1, 1, tzinfo=datetime.timezone.utc)
dt2 = datetime.datetime(2100, 12, 31, tzinfo=datetime.timezone.utc)

# reference period
dtr1 = datetime.datetime(1971, 1, 1, tzinfo=datetime.timezone.utc)
dtr2 = datetime.datetime(2000, 12, 31, tzinfo=datetime.timezone.utc)

models = ["CMCC-ESM2", "GFDL-ESM4"]
out_f = {}
out_hist_f = {}
for model in models:
    print(f"Processing model: {model}")
    out_f[model] = f"data/tg_icclim_{model}.nc"
    out_hist_f[model] = f"data/tg_icclim_{model}_hist.nc"
    filenames_hist = Path("data").glob(f"tas_day_{model}_historical_*.nc")
    filenames = Path("data").glob(f"tas_day_{model}_ssp585_*.nc")
    icclim.index(
        index_name="TG",
        in_files=[str(f) for f in filenames],
        var_name="tas",
        slice_mode="year",
        time_range=[dt1, dt2],
        out_file=out_f[model],
        logs_verbosity="LOW",
    )
    icclim.index(
        index_name="TG",
        in_files=[str(f) for f in filenames_hist],
        var_name="tas",
        slice_mode="year",
        time_range=[dtr1, dtr2],
        out_file=out_hist_f[model],
        logs_verbosity="LOW",
    )
2024-01-19 09:56:34,358 --- icclim 6.6.0
2024-01-19 09:56:34,359 --- BEGIN EXECUTION
2024-01-19 09:56:34,360 Processing: 0%
Processing model: CMCC-ESM2
/home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages/xclim/core/cfchecks.py:41: UserWarning: Variable does not have a `cell_methods` attribute.
  _check_cell_methods(
/home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages/xclim/core/cfchecks.py:45: UserWarning: Variable does not have a `standard_name` attribute.
  check_valid(vardata, "standard_name", data["standard_name"])
2024-01-19 09:56:50,956 Processing: 100%
2024-01-19 09:56:50,957 --- icclim 6.6.0
2024-01-19 09:56:50,958 --- CPU SECS = 28.970
2024-01-19 09:56:50,958 --- END EXECUTION
2024-01-19 09:56:50,971 --- icclim 6.6.0
2024-01-19 09:56:50,972 --- BEGIN EXECUTION
2024-01-19 09:56:50,973 Processing: 0%
/home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages/xclim/core/cfchecks.py:41: UserWarning: Variable does not have a `cell_methods` attribute.
  _check_cell_methods(
/home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages/xclim/core/cfchecks.py:45: UserWarning: Variable does not have a `standard_name` attribute.
  check_valid(vardata, "standard_name", data["standard_name"])
2024-01-19 09:57:14,403 Processing: 100%
2024-01-19 09:57:14,404 --- icclim 6.6.0
2024-01-19 09:57:14,405 --- CPU SECS = 61.512
2024-01-19 09:57:14,406 --- END EXECUTION
2024-01-19 09:57:14,424 --- icclim 6.6.0
2024-01-19 09:57:14,425 --- BEGIN EXECUTION
2024-01-19 09:57:14,426 Processing: 0%
Processing model: GFDL-ESM4
/home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages/xclim/core/cfchecks.py:41: UserWarning: Variable does not have a `cell_methods` attribute.
  _check_cell_methods(
/home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages/xclim/core/cfchecks.py:45: UserWarning: Variable does not have a `standard_name` attribute.
  check_valid(vardata, "standard_name", data["standard_name"])
2024-01-19 09:57:29,710 Processing: 100%
2024-01-19 09:57:29,711 --- icclim 6.6.0
2024-01-19 09:57:29,712 --- CPU SECS = 82.298
2024-01-19 09:57:29,713 --- END EXECUTION
2024-01-19 09:57:29,726 --- icclim 6.6.0
2024-01-19 09:57:29,727 --- BEGIN EXECUTION
2024-01-19 09:57:29,727 Processing: 0%
/home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages/xclim/core/cfchecks.py:41: UserWarning: Variable does not have a `cell_methods` attribute.
  _check_cell_methods(
/home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages/xclim/core/cfchecks.py:45: UserWarning: Variable does not have a `standard_name` attribute.
  check_valid(vardata, "standard_name", data["standard_name"])
2024-01-19 09:57:53,531 Processing: 100%
2024-01-19 09:57:53,531 --- icclim 6.6.0
2024-01-19 09:57:53,532 --- CPU SECS = 114.398
2024-01-19 09:57:53,533 --- END EXECUTION

Data preparation#

Here all data is loaded in 2 separate variables, one containing all the historical periods for all the models, and the same for the future time period.

An example is shown on how to select a specific data location. But this is not used.

[9]:
# Open datasets
tg = []
tg_hist = []
ds = []
ds_hist = []
xr.set_options(enable_cftimeindex=False)
for model in models:
    dsl = xr.open_dataset(out_f[model], decode_times=False)
    dsl["time"] = xr.decode_cf(dsl).time
    dsl = dsl.assign_coords({"model_id": model})
    tg.append(dsl["TG"])

    dshl = xr.open_dataset(out_hist_f[model], decode_times=False)
    dshl["time"] = xr.decode_cf(dshl).time
    dshl = dshl.assign_coords({"model_id": model})
    tg_hist.append(dshl["TG"])

# Select a single x,y combination from the data
longitude = tg[0]["lon"].sel(lon=3.5, method="nearest").values
latitude = tg[0]["lat"].sel(lat=44.2, method="nearest").values

print("Long, Lat values:", longitude, latitude)
Long, Lat values: 3.75 43.8219895287958
/home/bzah/micromamba/envs/icclim-dev/lib/python3.11/site-packages/xarray/core/options.py:117: FutureWarning: The enable_cftimeindex option is now a no-op and will be removed in a future version of xarray.
  warnings.warn(

Perform spacial average on all the geographical domain#

[10]:
# Average different grids
for ii in range(len(tg)):
    tg[ii] = tg[ii].sel(lat=[0.0, 90.0], method="nearest").mean(dim=["lon", "lat"])
for ii in range(len(tg_hist)):
    tg_hist[ii] = (
        tg_hist[ii].sel(lat=[0.0, 90.0], method="nearest").mean(dim=["lon", "lat"])
    )

Define a function to align all different calendar types#

[11]:
# Define function to align different calendars using annual data
def to_pandas_dt(da):
    """Takes an annual DataArray. Change the calendar to a pandas datetime."""
    val = da.copy()
    # val.resample(time='Y').mean('time')
    timev = []
    years = [int(val) for val in da.time.dt.strftime("%Y")]
    for itime in range(val.sizes["time"]):
        timev.append(years[itime])

    timevp = pd.to_datetime(timev, format="%Y")
    time1 = xr.DataArray(data=timevp, dims=["time"])
    time1.name = "time"
    # We rename the time dimension and coordinate to time360 to make it clear it isn't
    # the original time coordinate.
    val = val.rename({"time": "timepd"})
    time1 = time1.rename({"time": "timepd"})
    return val.assign_coords({"timepd": time1})

Align calendars of all input data#

[12]:
# Convert all calendars to annual precision (we have configured icclim to output yearly
# data)

ll = [to_pandas_dt(da) for da in tg]
ll_hist = [to_pandas_dt(da) for da in tg_hist]

# Concatenate all models into one
full_tg = xr.concat(ll, "model_id", join="outer")
full_tg_hist = xr.concat(ll_hist, "model_id", join="outer")
full_tg_anomaly = full_tg - full_tg_hist.mean(dim="timepd")

Plot a multi-model time series for the future time period#

Temperature for SSP585 of the period 2080-2100.

The multi-model average is shown in bold black line.

[13]:
# Plot future time period and superimpose multi-model average in bold black line
full_tg.plot(hue="model_id")
full_tg.mean(dim="model_id").plot(color="black", linewidth=4)
[13]:
[<matplotlib.lines.Line2D at 0x7f4969ec6b50>]
../../_images/tutorials_notebooks_averaged_tas_anomaly_15_1.png

Plot a time series of the anomaly of temperature#

Anomaly of temperature for SSP585 of the period 2080-2100 compared to 1971-2000.

The multi-model average is shown in bold black line.

[14]:
# Plot temperature anomaly compared to historical period and superimpose multi-model
# average in bold black line
full_tg_anomaly.plot(hue="model_id")
full_tg_anomaly.mean(dim="model_id").plot(color="black", linewidth=4)
[14]:
[<matplotlib.lines.Line2D at 0x7f492256d350>]
../../_images/tutorials_notebooks_averaged_tas_anomaly_17_1.png