diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 378447b8e14467f468c87d5243df6c0f82d420ea..457c851e260d0c8db83689072f94e219e10cb9c1 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -20,6 +20,7 @@ build:
   script:
     #- ls /pool/data
     - cd docs 
+    - chmod 755 ./leave_required_nbooks.sh && ./leave_required_nbooks.sh
     - make html
   after_script:
     #- conda deactivate
@@ -42,8 +43,11 @@ imageupdate:
   script:
     - docker build --tag gitlabci_notebook .
   only:
+    refs:
+      - branches
     changes:
       - Dockerfile
+      - environment.yaml
 
 pages:
   stage: deploy
diff --git a/Dockerfile b/Dockerfile
index 526a53e1c5962eeec49408b708b6d7f25e507f53..eed74d67b713d3a5cd9e6678033e7616e9399090 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -8,6 +8,7 @@ RUN micromamba install -y -n base -f /tmp/env.yaml && \
 ENV PATH=$PATH:/micromamba/pcondabin:/micromamba/bin
 USER root
 RUN apt-get update && apt-get install build-essential -y
+RUN apt-get install git -y
 
 RUN python -m ipykernel install --name python3 --display-name "python3" --user 
 
diff --git a/docs/leave_required_nbooks.sh b/docs/leave_required_nbooks.sh
new file mode 100755
index 0000000000000000000000000000000000000000..10dc004a9d0bcfd27f9ce0d9f3ec422833dba1a4
--- /dev/null
+++ b/docs/leave_required_nbooks.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+if [ "${CI_COMMIT_BRANCH}" != "master" ]; then
+  a=$(git diff --name-only $CI_COMMIT_BEFORE_SHA $CI_COMMIT_SHA | grep ipynb | rev | cut -d '/' -f -1 | rev | tr '\n' ' ')
+  rm source/*.ipynb
+  for file in $a;
+  do
+    echo $file
+    git checkout source/$file ;
+  done
+fi
+
diff --git a/docs/source/use-case_climate-extremes-indices_cdo.ipynb b/docs/source/use-case_climate-extremes-indices_cdo.ipynb
new file mode 120000
index 0000000000000000000000000000000000000000..625ec91ff9e2a60e80782c4847d8e9dbae22ef3a
--- /dev/null
+++ b/docs/source/use-case_climate-extremes-indices_cdo.ipynb
@@ -0,0 +1 @@
+../../notebooks/demo/use-case_climate-extremes-indices_cdo.ipynb
\ No newline at end of file
diff --git a/docs/source/use-cases.rst b/docs/source/use-cases.rst
index a45d4f29d630fe04e0996e55181e12dbf2ceb998..8fcde02c84597a0293ecc8aa09b52a1cb9f8ba0e 100644
--- a/docs/source/use-cases.rst
+++ b/docs/source/use-cases.rst
@@ -16,3 +16,4 @@ Use-cases
    use-case_simple-vis_xarray-matplotlib_cmip6.ipynb
    use-case_global-yearly-mean-anomaly_xarray-hvplot_cmip6.ipynb
    use-case_convert-nc-to-tiff_rioxarray-xesmf_cmip.ipynb
+   use-case_climate-extremes-indices_cdo.ipynb
diff --git a/environment.yml b/environment.yml
index cfc84e467879852799fce4f2e06597ab37389cea..a3c27fe4624b0b1815a6fe0d84633a0b25b1bfd3 100644
--- a/environment.yml
+++ b/environment.yml
@@ -33,9 +33,12 @@ dependencies:
   - esmvalcore
   - requests
   - aiohttp
+  - wget
 #psyplot
   - psy-maps
   - psyplot
+  - cfchecker
+  - pyessv
 #
 #for psyplot on centos:
 #sudo ln -s /usr/lib64/libc.so.6 /usr/lib64/libc.musl-x86_64.so.1
@@ -46,3 +49,6 @@ dependencies:
   - pip:
     - sphinx-book-theme
     - pangeo-xesmf #for raster data
+    - git+https://github.com/cedadev/cc-yaml@master
+    - git+https://github.com/cedadev/compliance-check-lib@master
+    - git+https://github.com/AtMoDat/atmodat_data_checker@master
diff --git a/notebooks/demo/use-case_climate-extremes-indices_cdo.ipynb b/notebooks/demo/use-case_climate-extremes-indices_cdo.ipynb
new file mode 100755
index 0000000000000000000000000000000000000000..389c4fa7589b900eea62990cf4da96551c5d07bf
--- /dev/null
+++ b/notebooks/demo/use-case_climate-extremes-indices_cdo.ipynb
@@ -0,0 +1,601 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Climate Extremes Indices with CDOs according to the ETCCDI standard"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "A **climate index** is a calculated measure for the state and/or variations of the climate system. In the field of meteorology, many definitions for different types of climate indices exist. For example, the German Weather Service defines a **Klimakenntag**: If a climatological parameter exceeds a specific threshold at one day, the day is considered as a specific klimakenntag.\n",
+    "\n",
+    "The expert team ETCCDI has defined a core set of descriptive indices of extremes (Climate Extremes Indices, CEI) in order to\n",
+    "\n",
+    "> \"gain a **uniform perspective on observed changes in weather and climate extremes**.\n",
+    "\n",
+    "These indices have become a standard in the climate science community. They describe particular characteristics of extremes including *frequency, amplitude and persistence*."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Learning Objectives\n",
+    "\n",
+    "In this notebook, you will learn to \n",
+    "\n",
+    "- calculate 4 kinds of CEIs, **absolute**, **threshold**, **duration** and **percentile**-based indices according to the ETCCDI standard with CDOs\n",
+    "- calculate running window percentiles according to the ETCCDI standard with CDOs"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Requirements\n",
+    "\n",
+    "- intake\n",
+    "- cdo"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from IPython.display import HTML\n",
+    "HTML('<iframe src=\"https://slides.com/wachsylon/cdoetccdi/embed\" width=\"576\" height=\"420\" scrolling=\"no\" frameborder=\"0\" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>')"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## 0. Preparation\n",
+    "\n",
+    "In the following, \n",
+    "\n",
+    "- you will `import` packages required to run `cdo` in python. We use the `cdo` binary from the environment which was used to create the kernel. You might want to change that.\n",
+    "- you will get a time series of the variables `tasmin` and `pr` which can be used to calculate all types of indices. We choose a subset from the `historical` experiment form the recent model intercomparison project *CMIP6* for the time interval 1970-1989."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#set cdo binary to the one installed in the environment of the kernel\n",
+    "import sys\n",
+    "import os\n",
+    "cdobin=os.path.sep.join(sys.executable.split(os.path.sep)[:-1]+[\"cdo\"])\n",
+    "#\n",
+    "#import python cdo \n",
+    "from cdo import *\n",
+    "cdo = Cdo(cdobin)\n",
+    "cdo.debug=True\n",
+    "#This prohibits that existing files are created a second time\n",
+    "cdo.forceOutput = False"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import intake\n",
+    "# Path to master catalog on the DKRZ server\n",
+    "col_url = \"https://swift.dkrz.de/v1/dkrz_a44962e3ba914c309a7421573a6949a6/intake-esm/dkrz_data-pool_cloudcatalog.yaml\"\n",
+    "parent_col=intake.open_catalog(col_url)\n",
+    "list(parent_col)\n",
+    "\n",
+    "# Open the catalog with the intake package and name it \"col\" as short for \"collection\"\n",
+    "col=parent_col[\"dkrz_cmip6_disk_netcdf_fromcloud\"]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Store the name of the model we chose in a variable named \"climate_model\"\n",
+    "\n",
+    "source_id = \"MPI-ESM1-2-LR\" # here we choose Max-Plack Institute's Earth Sytem Model in high resolution\n",
+    "\n",
+    "query = dict(\n",
+    "    source_id      = source_id, # the model \n",
+    "    variable_id    = [\"tasmin\",\"pr\"],\n",
+    "    table_id       = \"day\", # daily\n",
+    "    experiment_id  = \"historical\", #\n",
+    "    member_id      = \"r10i1p1f1\", # \"r\" realization, \"i\" initialization, \"p\" physics, \"f\" forcing\n",
+    "    time_range     = \"19700101-19891231\"\n",
+    ")\n",
+    "\n",
+    "# Intake looks for the query we just defined in the catalog of the CMIP6 data pool at DKRZ\n",
+    "cat = col.search(**query)\n",
+    "\n",
+    "# Show query results\n",
+    "cat.df"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#download files\n",
+    "urlpr=cat.df[cat.df[\"variable_id\"] == \"pr\"][\"opendap_url\"].values[0].replace(\"dodsC\",\"fileServer\")\n",
+    "urltas=cat.df[cat.df[\"variable_id\"] == \"tasmin\"][\"opendap_url\"].values[0].replace(\"dodsC\",\"fileServer\")\n",
+    "!wget {urlpr}\n",
+    "!wget {urltas}"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#define temporary output files\n",
+    "prorig = cat.df[cat.df[\"variable_id\"] == \"pr\"][\"opendap_url\"].values[0].split('/')[-1]\n",
+    "tasorig = cat.df[cat.df[\"variable_id\"] == \"tasmin\"][\"opendap_url\"].values[0].split('/')[-1]\n",
+    "prHamburg    =\"pr_hamburg.nc\"\n",
+    "tasminHamburg=\"tasmin_hamburg.nc\""
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#Select a subarea because memory might not be large enough\n",
+    "#and change units\n",
+    "\n",
+    "prep_ts=\"-sellonlatbox,9,10,53,54 \"\n",
+    "prep_pr=\"-mulc,86400 \"+prep_ts\n",
+    "pr=cdo.mulc(\"1\",\n",
+    "              input=prep_pr+prorig,\n",
+    "              output=prHamburg)\n",
+    "tasmin=cdo.mulc(\"1\",\n",
+    "              input=prep_ts+tasorig,\n",
+    "              output=tasminHamburg)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## 1. Absolute indices\n",
+    "\n",
+    "***\n",
+    "- `txx`, `txn`, `tnx`, `tnn`\n",
+    "- daily temperature range `dtr`, intensity intdex `sdii`\n",
+    "- `rx1day`, `rx5day`, `prcptot`\n",
+    "***"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "While the other 3 categories of indices are defined in temporal *units*, the **absolute** indices have the same *units* as the input variable. The **absolute indices** are useful because its values\n",
+    "\n",
+    "> can often be related to extreme events that affect human society and the natural environment\n",
+    "\n",
+    "Absolute indices are easy to compute with basic CDOs. E.g., the minimum of daily minimum temperature can be calculated with\n",
+    "```bash\n",
+    "cdo yearmin tasmin tnn.nc\n",
+    "```\n",
+    "\n",
+    "However, the `etccdi_` indices produces variables named according to the ETCCDI standard. Also, you can specify an output frequency. When it comes to the *precipiation related* absolute indices, you cannot work with basic cdos anymore. In the following, we show you an example for the *highest five day precipitation sum*:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#Highest 5day percipitation sum\n",
+    "!export CDO_TIMESTAT_DATE=\"last\"\n",
+    "#$cdo eca_rx5day,50,freq=year -runsum,5\n",
+    "rx5day=\"rx5day_hamburg.nc\"\n",
+    "rx5day_values = cdo.etccdi_rx5day(input=\"-runsum,5 \"+prHamburg,\n",
+    "                                  output=\"rx5day_hamburg.nc\",\n",
+    "                                  returnCdf=True).variables[\n",
+    "    \"rx5dayETCCDI\"][:]\n",
+    "rx5day_values = rx5day_values.flatten()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import matplotlib.pyplot as plt\n",
+    "plt.plot(rx5day_values)\n",
+    "plt.grid()\n",
+    "plt.xlabel(\"Year\")\n",
+    "plt.ylabel(\"Precipitation sum over 5 days [mm]\")\n",
+    "plt.show()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## 2. Threshold exceedances\n",
+    "***\n",
+    "- frost days `fd`, ice days `id`, summer days `su`, tropical nights `tr`\n",
+    "- `r1mm`, `r10mm`, `r20mm`\n",
+    "***"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Threshold based CEIs are\n",
+    "\n",
+    "> Indices based on the count of days crossing certain **fixed thresholds** (for example, the 0°C threshold as used in the frost days index FD) can also be related to observed impacts, in particular if the thresholds refer to values of physical, hydrological or biological significance.\n",
+    "\n",
+    "We can calculate `frost days` with yearly frequency as follows:\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#frost days\n",
+    "# $cdo eca_fd,freq=year\n",
+    "fd_values = cdo.etccdi_fd(input=tasminHamburg,\n",
+    "                          output=\"fd_hamburg.nc\",\n",
+    "                          returnCdf=True).variables[\n",
+    "                          \"fdETCCDI\"][:]\n",
+    "fd_values = fd_values.flatten()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import matplotlib.pyplot as plt\n",
+    "plt.plot(fd_values)\n",
+    "plt.grid()\n",
+    "plt.xlabel(\"Year\")\n",
+    "plt.ylabel(\"Number of Frost days per year\")\n",
+    "plt.show()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## 3. Create Percentiles"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "In contrast to fixed thresholds based indices, for some indices individual grid cell percentiles for each day are used as thresholds. Using only one day per day results in a rather small sample size which is equal to the lenght of the base period. In climate science, this base period is usually 20 or 30 years long. In order to construct percentiles that are more *meaningful*, we use a running window around the target day to enlarge the sample size. We will run `ydrunpctl` which also requires `ydrunmin` and `ydrunmax`."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "The running minimum and running maximum are needed as input files for *ydrunpctl* so that the operator can create **bins** for a histogram. However, CEIs are based not on **bin-sorted** histograms but use a **value-sorted** histogram. Such a histogram can only be created if there is enough memory to save all values. This is only the case, if the environment parameter *CDO_PCTL_NBINS*  can be set to\n",
+    "\n",
+    "```bash\n",
+    "nbins=\"$((windowsize*(end_year-start_year+1)*2+2))\"\n",
+    "```\n",
+    "\n",
+    "which is in our case\n",
+    "\n",
+    "```bash\n",
+    "nbins=\"$((5*(1989-1970+1)*2+2))\"\n",
+    "nbins=202\n",
+    "#and\n",
+    "export CDO_PCTL_NBINS=202\n",
+    "```\n",
+    "\n",
+    "Whether this is possible depends on the system."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Two new arguments have been introduced for the `ydrun`* operators in comparison to older cdo versions for matching the requirements defined by the ETCCDI standard calculation methods:\n",
+    "\n",
+    "- **rm** : The **read_method** can be set to `c` for \"circular\" which takes into account the last time steps at the begin of the time period and vise versa. Otherwise, the first and last time steps are not used as often as the other time steps in the calculations. \n",
+    "- **pm** : Since a lot of methods exist to calculate a percentile, CDO will allow to set ***percentileMethod*** in the operator call. ETCCDI recommends a method implemented in the software language R as type8. This is right now the only option for the argument."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "The resulting command line calls of these operators required for CEIs look like:\n",
+    "```bash\n",
+    "cdo ydrunmin,5,rm=c tasmin_hamburg.nc tasmin_runmin.nc\n",
+    "cdo ydrunmax,5,rm=c tasmin_hamburg.nc tasmin_runmax.nc\n",
+    "cdo ydrunpctl,5,rm=c,pm=r8 tasmin_runmin.nc tasmin_runmax.nc tn10thresh.nc\n",
+    "```"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "windowsize=5\n",
+    "readMethod=\"circular\"\n",
+    "percentileMethod=\"rtype8\""
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#  $cdo ydrunmin,5,rm=c $tasminMerged $tasminrunmin\n",
+    "cdo.ydrunmin(windowsize,\"rm=\"+readMethod,\n",
+    "             input=tasminHamburg,\n",
+    "             output=\"tasmin_runmin.nc\")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#  $cdo ydrunmax,5,rm=c $tasminMerged $tasminrunmin\n",
+    "cdo.ydrunmax(windowsize,\"rm=\"+readMethod,\n",
+    "             input=tasminHamburg,\n",
+    "             output=\"tasmin_runmax.nc\")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#If you set this environment parameter,\n",
+    "#histograms are ordered values instead of bins\n",
+    "!export CDO_PCTL_NBINS=202\n",
+    "#  $cdo subc,273.15 -ydrunpctl,10,5,pm=r8,rm=c $tasminMerged ${tasminrunmin} ${tasminrunmax} ${tn10thresh}\n",
+    "cdo.ydrunpctl(10,windowsize,\"rm=\"+readMethod,\"pm=\"+percentileMethod,\n",
+    "             input=tasminHamburg+\" tasmin_runmin.nc tasmin_runmax.nc\",\n",
+    "             output=\"tn10thresh.nc\")\n",
+    "#  $cdo subc,273.15 -ydrunpctl,90,5,pm=r8,rm=c $tasminMerged ${tasminrunmin} ${tasminrunmax} ${tn10thresh}\n",
+    "cdo.ydrunpctl(90,windowsize,\"rm=\"+readMethod,\"pm=\"+percentileMethod,\n",
+    "             input=tasminHamburg+\" tasmin_runmin.nc tasmin_runmax.nc\",\n",
+    "             output=\"tn90thresh.nc\")"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## 4. Duration indices\n",
+    "\n",
+    "***\n",
+    "- cold spell duration index `csdi`, warm spell duration index `wsdi`\n",
+    "- consecutive dry days `cdd`, consecutive wet days `cwd`\n",
+    "- growing season lengths `gsl`\n",
+    "***"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Duration indices are self-explanatory. They allow to characterize periods of extremes. In comparison to older `eca_` indices, the `etccdi_` indices implemented in `cdo` have two major changes. They\n",
+    "\n",
+    "1. count periods over overlapping years (or month, depending on the output frequency) and the final period will get the time stamp of the last contributing day.\n",
+    "2. allow to have less time steps in the percentile threshold file than in the original time series file.\n",
+    "\n",
+    "The corresponding command line call looks like\n",
+    "\n",
+    "```bash\n",
+    "cdo eca_cwfi,6,freq=year tasminHamburg.nc tn10thresh.nc csdi_hamburg.nc\n",
+    "```"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#Cold spell duration index (cold wave index)\n",
+    "csdi=\"csdi_hamburg.nc\"\n",
+    "csdiValues = cdo.etccdi_csdi(6,\"freq=year\",\n",
+    "             input=tasminHamburg+\" tn10thresh.nc\",\n",
+    "             output=csdi,\n",
+    "            returnCdf=True).variables['csdiETCCDI'][:]\n",
+    "csdiValues = csdiValues.flatten()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "plt.plot(csdiValues)\n",
+    "plt.show()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#Consecutive Wet Days\n",
+    "#Precipitation threshold [mm]:\n",
+    "pt=1\n",
+    "#Minimum number of days exceeded for a second variable:\n",
+    "md=5\n",
+    "#!cdo eca_cwd,1,5,freq=year prHamburg.nc cwd_hamburg.nc"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "cwd_values = cdo.etccdi_cwd(input=prHamburg,\n",
+    "            output=\"cwdHamburg.nc\",\n",
+    "            returnCdf=True).variables[\n",
+    "            \"cwdETCCDI\"][:] \n",
+    "cwd_values = cwd_values.flatten()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "scrolled": true,
+    "tags": []
+   },
+   "outputs": [],
+   "source": [
+    "plt.hist(cwd_values,bins= [5.5,6.5,7.5,8.5,\n",
+    "                           9.5,10.5,11.5,12.5,13.5])\n",
+    "plt.grid()\n",
+    "plt.xlabel(\"Largest number of consecutive\"\n",
+    "           \" wet days per year\")\n",
+    "plt.ylabel(\"Frequency\")\n",
+    "plt.show()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## 5. Percentile based indices\n",
+    "***\n",
+    "tx10p tx90p tn10p tn90 r95p r99p\n",
+    "***"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "The reason for choosing mostly percentile thresholds rather than fixed thresholds is \n",
+    "\n",
+    "> the number of days exceeding percentile thresholds is more evenly distributed in space and is meaningful in every region”\n",
+    "\n",
+    "The temperature related percentile based indices (*tx90p, tx10p, tn90p, tn10p*) require a special percentile calculation method for years that lie *inside the base period*. For that years, **bootstrapping** must be applied where the base period is modified: the index year is taken from the base period and is replaced by another year. Then, the percentile as well as the index is calculated for the new 30 year base period. This is done 29 times so that each year from the base period will be accounted twice. In the end, the mean of 29 indices is taken.<br>\n",
+    "Therefore, the operators need input arguments:\n",
+    "1. The window size (5)\n",
+    "2. The start year of the bootstrapping interval (1970)\n",
+    "3. The end year of the bootstrapping interval (1989)\n",
+    "4. The output frequency\n",
+    "\n",
+    "The corresponding command line call looks like:\n",
+    "\n",
+    "```bash\n",
+    "cdo etccdi_tn10p,5,1970,1989,freq=year tasmin_hamburg.nc tasmin_runmin.nc tasmin_runmax.nc tn10p_hamburg.nc\n",
+    "```"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "!rm tn10p_hamburg.nc\n",
+    "!export CDO_PCTL_NBINS=302\n",
+    "tn10p_values = cdo.etccdi_tn10p(5,1970,1989,\"freq=year\",\n",
+    "                 input=tasminHamburg+\" tasmin_runmin.nc tasmin_runmax.nc\",\n",
+    "                output=\"tn10p_hamburg.nc\",\n",
+    "                returnCdf=True).variables[\"tn10pETCCDI\"][:]\n",
+    "tn10p_values = tn10p_values.flatten()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import matplotlib.pyplot as plt\n",
+    "plt.plot(tn10p_values)\n",
+    "plt.grid()\n",
+    "plt.xlabel(\"Year\")\n",
+    "plt.ylabel(\"Number of days with tmin < tmin90\")\n",
+    "plt.show()"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "### Used data\n",
+    "\n",
+    "- https://doi.org/10.22033/ESGF/CMIP6.6595"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "We acknowledge the CMIP community for providing the climate model data, retained and globally distributed in the framework of the ESGF. The CMIP data of this study were replicated and made available for this study by the DKRZ.”"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "taucenv",
+   "language": "python",
+   "name": "taucenv"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.9.7"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}