diff --git a/Notebooks/eval_precipitation.ipynb b/Notebooks/eval_precipitation.ipynb
index 91b8a838c93d6a05ba2c9dd3d649227d720fc7f9..a0c652dda560784498e2cc1dfd4b58131faf2703 100644
--- a/Notebooks/eval_precipitation.ipynb
+++ b/Notebooks/eval_precipitation.ipynb
@@ -55,10 +55,12 @@
     "PREDICTAND = 'pr'\n",
     "MODEL = 'USegNet'\n",
     "PPREDICTORS = 'ztuvq'\n",
+    "# PPREDICTORS = ''\n",
     "PLEVELS = ['500', '850']\n",
+    "# PLEVELS = []\n",
     "SPREDICTORS = 'p'\n",
-    "DEM = 'dem'\n",
-    "DEM_FEATURES = ''\n",
+    "DEM = ''\n",
+    "DEM_FEATURES = 'dem'\n",
     "DOY = ''\n",
     "WET_DAY_THRESHOLD = '2'\n",
     "# LOSS = 'MSELoss'\n",
@@ -265,12 +267,13 @@
    "outputs": [],
    "source": [
     "# align datasets and mask missing values in model predictions\n",
-    "y_true, y_refe, y_pred = xr.align(y_true, y_refe, y_pred, join='override')\n",
-    "y_pred_pr = y_pred.precipitation.where(~np.isnan(y_true.precipitation), other=np.nan)\n",
     "if LOSS == 'BernoulliGammaLoss':\n",
-    "    y_pred_prob = y_pred.prob.where(~np.isnan(y_true.precipitation), other=np.nan)\n",
-    "y_refe = y_refe.precipitation.where(~np.isnan(y_true.precipitation), other=np.nan)\n",
-    "y_true = y_true.precipitation"
+    "    y_true, y_refe, y_pred_pr, y_pred_prob = xr.align(y_true.precipitation, y_refe.precipitation, y_pred.precipitation, y_pred.prob, join='override')\n",
+    "    y_pred_prob = y_pred_prob.where(~np.isnan(y_true), other=np.nan)\n",
+    "else:\n",
+    "    y_true, y_refe, y_pred_pr = xr.align(y_true.precipitation, y_refe.precipitation, y_pred.precipitation, join='override')\n",
+    "y_pred_pr = y_pred_pr.where(~np.isnan(y_true), other=np.nan)    \n",
+    "y_refe = y_refe.where(~np.isnan(y_true), other=np.nan)"
    ]
   },
   {
@@ -1046,7 +1049,7 @@
    "outputs": [],
    "source": [
     "# minimum precipitation (mm / day) defining a wet day\n",
-    "WET_DAY_THRESHOLD = 1"
+    "WET_DAY_THRESHOLD = float(WET_DAY_THRESHOLD)"
    ]
   },
   {
@@ -1274,7 +1277,7 @@
    "outputs": [],
    "source": [
     "# true and predicted probability of precipitation\n",
-    "p_true = (y_true > WET_DAY_THRESHOLD).values.flatten()\n",
+    "p_true = (y_true > float(WET_DAY_THRESHOLD)).values.flatten()\n",
     "p_pred = y_pred_prob.values.flatten()"
    ]
   },
diff --git a/Notebooks/eval_precipitation_sensitivity.ipynb b/Notebooks/eval_precipitation_sensitivity.ipynb
index eb55dd81cbd8018807b939e5e1214a69a230c94e..8bbfdb4d779ef99bc369fbc5a4627587d54d026f 100644
--- a/Notebooks/eval_precipitation_sensitivity.ipynb
+++ b/Notebooks/eval_precipitation_sensitivity.ipynb
@@ -46,7 +46,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 1,
    "id": "d75e3627-13c4-46b8-b749-d582e4b802ac",
    "metadata": {},
    "outputs": [],
@@ -56,7 +56,7 @@
     "MODEL = 'USegNet'\n",
     "PPREDICTORS = 'ztuvq'\n",
     "PLEVELS = ['500', '850']\n",
-    "SPREDICTORS = 'mslp'\n",
+    "SPREDICTORS = 'p'\n",
     "DEM = 'dem'\n",
     "DEM_FEATURES = ''\n",
     "DOY = ''\n",
@@ -74,7 +74,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 2,
    "id": "01ed9fbc-49c2-4028-a3f3-692a014dcf89",
    "metadata": {},
    "outputs": [],
@@ -101,7 +101,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 3,
    "id": "073dfc6a-8b33-4aca-ab71-c06ef92bbb80",
    "metadata": {},
    "outputs": [],
@@ -120,7 +120,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 4,
    "id": "030c221d-e0ad-4e67-b742-db34de549983",
    "metadata": {},
    "outputs": [],
@@ -135,10 +135,26 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 5,
    "id": "7106fed2-9f63-453b-a9af-b5d490efbbb4",
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "['USegNet_pr_ztuvq_500_850_p_dem_0mm_BernoulliGammaLoss',\n",
+       " 'USegNet_pr_ztuvq_500_850_p_dem_05mm_BernoulliGammaLoss',\n",
+       " 'USegNet_pr_ztuvq_500_850_p_dem_1mm_BernoulliGammaLoss',\n",
+       " 'USegNet_pr_ztuvq_500_850_p_dem_2mm_BernoulliGammaLoss',\n",
+       " 'USegNet_pr_ztuvq_500_850_p_dem_3mm_BernoulliGammaLoss',\n",
+       " 'USegNet_pr_ztuvq_500_850_p_dem_5mm_BernoulliGammaLoss']"
+      ]
+     },
+     "execution_count": 5,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
    "source": [
     "# file pattern for different wet day thresholds\n",
     "PATTERNS = ['_'.join([PATTERN, '{}mm_{}'.format(str(t).replace('.', ''), LOSS)]) for t in WET_DAY_THRESHOLD]\n",
@@ -147,7 +163,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 6,
    "id": "0069c5d8-ee28-49a3-84f0-8af6b3bcb05d",
    "metadata": {},
    "outputs": [],
@@ -158,7 +174,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 7,
    "id": "316a35e3-49e6-4d02-b865-25710a621daa",
    "metadata": {},
    "outputs": [],
@@ -170,7 +186,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 8,
    "id": "58177982-7f86-4c9e-9980-563cf5d48852",
    "metadata": {},
    "outputs": [],
@@ -200,7 +216,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 9,
    "id": "9758d58b-82e9-47b2-9cf7-1c93d5ed04a7",
    "metadata": {},
    "outputs": [],
@@ -211,10 +227,23 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 10,
    "id": "57ca80c6-2c02-44d1-87eb-35c8a78ec71f",
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(0.0 mm), r2: -1.11\n",
+      "(0.5 mm), r2: -1.43\n",
+      "(1.0 mm), r2: -0.72\n",
+      "(2.0 mm), r2: -1.22\n",
+      "(3.0 mm), r2: 0.30\n",
+      "(5.0 mm), r2: -0.32\n"
+     ]
+    }
+   ],
    "source": [
     "# calculate predicted monthly mean precipitation (mm / month)\n",
     "for k, v in y_pred.items():\n",
@@ -248,7 +277,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 11,
    "id": "02c99a93-530c-4570-a7ed-4cbf1940222f",
    "metadata": {},
    "outputs": [],
@@ -259,10 +288,35 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 12,
    "id": "bc85224d-68d8-4791-8eec-ab39e16898b7",
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(0.0 mm), relative bias = -50.56%\n",
+      "(0.0 mm), MAE = 1.50 mm\n",
+      "(0.0 mm), RMSE = 2.88 mm\n",
+      "(0.5 mm), relative bias = -53.85%\n",
+      "(0.5 mm), MAE = 1.60 mm\n",
+      "(0.5 mm), RMSE = 3.08 mm\n",
+      "(1.0 mm), relative bias = -44.11%\n",
+      "(1.0 mm), MAE = 1.32 mm\n",
+      "(1.0 mm), RMSE = 2.24 mm\n",
+      "(2.0 mm), relative bias = -48.03%\n",
+      "(2.0 mm), MAE = 1.43 mm\n",
+      "(2.0 mm), RMSE = 2.52 mm\n",
+      "(3.0 mm), relative bias = -14.26%\n",
+      "(3.0 mm), MAE = 0.62 mm\n",
+      "(3.0 mm), RMSE = 0.70 mm\n",
+      "(5.0 mm), relative bias = -30.53%\n",
+      "(5.0 mm), MAE = 0.97 mm\n",
+      "(5.0 mm), RMSE = 1.39 mm\n"
+     ]
+    }
+   ],
    "source": [
     "# yearly average bias over reference period\n",
     "for k, v in y_pred.items():\n",
@@ -344,10 +398,23 @@
   },
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 13,
    "id": "92733418-8840-46c2-bf33-adf93b78c646",
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(0.0 mm), ROCSS = 0.52\n",
+      "(0.5 mm), ROCSS = 0.58\n",
+      "(1.0 mm), ROCSS = 0.60\n",
+      "(2.0 mm), ROCSS = 0.52\n",
+      "(3.0 mm), ROCSS = 0.62\n",
+      "(5.0 mm), ROCSS = 0.63\n"
+     ]
+    }
+   ],
    "source": [
     "# true and predicted probability of precipitation\n",
     "for k, v in y_pred.items():\n",
@@ -365,6 +432,14 @@
     "    rocss = 2 * area - 1 # ROC skill score (cf. https://journals.ametsoc.org/view/journals/clim/16/24/1520-0442_2003_016_4145_otrsop_2.0.co_2.xml)\n",
     "    print('({:.1f} mm), ROCSS = {:.2f}'.format(k, rocss))"
    ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "d3fac03c-4215-465d-a0c5-358de4dd57f2",
+   "metadata": {},
+   "outputs": [],
+   "source": []
   }
  ],
  "metadata": {
diff --git a/Notebooks/eval_temperature.ipynb b/Notebooks/eval_temperature.ipynb
index 1cf81452ea1033837a45a51e786d686b2d368081..1193bc382af8e39191bdc3768c303c4ac4cbafd6 100644
--- a/Notebooks/eval_temperature.ipynb
+++ b/Notebooks/eval_temperature.ipynb
@@ -52,7 +52,7 @@
    "outputs": [],
    "source": [
     "# define the model parameters\n",
-    "PREDICTAND = 'tasmin'\n",
+    "PREDICTAND = 'tasmax'\n",
     "MODEL = 'USegNet'\n",
     "PPREDICTORS = 'ztuvq'\n",
     "PLEVELS = ['500', '850']\n",
@@ -97,6 +97,7 @@
     "import xarray as xr\n",
     "import numpy as np\n",
     "import matplotlib.pyplot as plt\n",
+    "from mpl_toolkits.axes_grid1.inset_locator import inset_axes\n",
     "import scipy.stats as stats\n",
     "from IPython.display import Image\n",
     "from sklearn.metrics import r2_score\n",
@@ -179,7 +180,7 @@
    "outputs": [],
    "source": [
     "# model predictions and observations NetCDF\n",
-    "y_pred = xr.open_dataset(search_files(TARGET_PATH.joinpath(PREDICTAND), '(.*)'.join([PATTERN, '.nc$'])).pop())\n",
+    "y_pred = xr.open_dataset(search_files(TARGET_PATH.joinpath(PREDICTAND), '.'.join([PATTERN, 'nc$'])).pop())\n",
     "if PREDICTAND == 'tas':\n",
     "    # read both tasmax and tasmin\n",
     "    tasmax = xr.open_dataset(search_files(OBS_PATH.joinpath('tasmax'), '.nc$').pop())\n",
@@ -200,16 +201,59 @@
     "y_true = y_true.sel(time=y_pred.time)"
    ]
   },
+  {
+   "cell_type": "markdown",
+   "id": "06dcb26f-f8e0-4365-9279-871bc35492f9",
+   "metadata": {},
+   "source": [
+    "### Load ERA-5 reference dataset"
+   ]
+  },
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "966d85fb-9185-408f-ac2b-1e4ca829ccd1",
+   "id": "8f20564f-3f1b-4da6-b625-f2d0c6392249",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# search ERA-5 reference dataset\n",
+    "y_refe = xr.open_dataset(search_files(ERA5_PATH.joinpath('ERA5', '2m_{}_temperature'.format(PREDICTAND.lstrip('tas'))), '.nc$').pop())"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "f7b2fe84-131d-485a-a6e7-3c47135447e1",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# convert to °C\n",
+    "y_refe = y_refe - 273.15"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "6be4c268-df97-4bd0-948a-cc1943a3c0fb",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# subset to time period covered by predictions\n",
+    "y_refe = y_refe.sel(time=y_pred.time).drop_vars('lambert_azimuthal_equal_area')\n",
+    "y_refe = y_refe.rename({'t2m': PREDICTAND})"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "9c7efab4-0cd2-4f6d-afbd-5e284d2bda9d",
    "metadata": {},
    "outputs": [],
    "source": [
     "# align datasets and mask missing values in model predictions\n",
-    "y_true, y_pred = xr.align(y_true, y_pred, join='override')\n",
-    "y_pred = y_pred.where(~np.isnan(y_true), other=np.nan)"
+    "y_true, y_pred, y_refe = xr.align(y_true, y_pred, y_refe, join='override')\n",
+    "y_pred = y_pred.where(~np.isnan(y_true), other=np.nan)\n",
+    "y_refe = y_refe.where(~np.isnan(y_true), other=np.nan)"
    ]
   },
   {
@@ -228,6 +272,18 @@
     "### Coefficient of determination"
    ]
   },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "bb8223e0-c5cb-477c-8c31-3dfb94b20ce1",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# group timeseries by month and calculate mean over time and space\n",
+    "y_pred_ac = y_pred.groupby('time.month').mean(dim=('time', 'y', 'x'))\n",
+    "y_true_ac = y_true.groupby('time.month').mean(dim=('time', 'y', 'x'))"
+   ]
+  },
   {
    "cell_type": "code",
    "execution_count": null,
@@ -236,8 +292,8 @@
    "outputs": [],
    "source": [
     "# get predicted and observed values over entire time series and grid points\n",
-    "y_pred_values = y_pred[PREDICTAND].values.flatten()\n",
-    "y_true_values = y_true[PREDICTAND].values.flatten()"
+    "y_pred_values = y_pred[PREDICTAND].groupby('time.month').mean(dim='time').values.flatten()\n",
+    "y_true_values = y_true[PREDICTAND].groupby('time.month').mean(dim='time').values.flatten()"
    ]
   },
   {
@@ -263,7 +319,8 @@
    "outputs": [],
    "source": [
     "# calculate coefficient of determination\n",
-    "r2 = r2_score(y_true_values, y_pred_values)"
+    "r2 = r2_score(y_true_values, y_pred_values)\n",
+    "r2"
    ]
   },
   {
@@ -277,29 +334,45 @@
     "fig, ax = plt.subplots(1, 1, figsize=(10, 10))\n",
     "\n",
     "# plot only a subset of data: otherwise plot is overloaded ...\n",
-    "subset = np.random.choice(np.arange(0, len(y_pred_values)), size=int(1e7), replace=False)\n",
-    "ax.plot(y_true_values[subset], y_pred_values[subset], 'o', alpha=.5, markeredgecolor='grey', markerfacecolor='none', markersize=3);\n",
+    "# subset = np.random.choice(np.arange(0, len(y_pred_values)), size=int(1e7), replace=False)\n",
+    "# ax.plot(y_true_values[subset], y_pred_values[subset], 'o', alpha=.5, markeredgecolor='grey', markerfacecolor='none', markersize=3);\n",
     "\n",
     "# plot entire dataset\n",
-    "# ax.plot(y_true_values, y_pred_values, 'o', alpha=.5, markeredgecolor='grey', markerfacecolor='none', markersize=3);\n",
+    "ax.plot(y_true_values, y_pred_values, 'o', alpha=.5, markeredgecolor='grey', markerfacecolor='none', markersize=3);\n",
     "\n",
     "# plot 1:1 mapping line\n",
-    "interval = np.arange(-40, 45, 5)\n",
+    "interval = np.arange(-15, 45, 5)\n",
+    "#interval = np.arange(-30, 35, 5)\n",
     "ax.plot(interval, interval, color='k', lw=2, ls='--')\n",
     "\n",
     "# add coefficient of determination: calculated on entire dataset!\n",
-    "ax.text(interval[-1] - 1, interval[0] + 1, s='Coefficient of determination R$^2$ = {:.2f}'.format(r2), ha='right', fontsize=14)\n",
+    "ax.text(interval[-1] - 0.5, interval[0] + 0.5, s='Coefficient of determination R$^2$ = {:.2f}'.format(r2), ha='right', fontsize=18)\n",
     "\n",
     "# format axes\n",
     "ax.set_ylim(interval[0], interval[-1])\n",
     "ax.set_xlim(interval[0], interval[-1])\n",
     "ax.set_xticks(interval)\n",
-    "ax.set_xticklabels(interval, fontsize=14)\n",
+    "ax.set_xticklabels(interval, fontsize=16)\n",
     "ax.set_yticks(interval)\n",
-    "ax.set_yticklabels(interval, fontsize=14)\n",
-    "ax.set_xlabel('Observed', fontsize=14)\n",
-    "ax.set_ylabel('Predicted', fontsize=14)\n",
-    "ax.set_title('{} (°C): 1991 - 2010'.format(NAMES[PREDICTAND].capitalize()), fontsize=16, pad=10);\n",
+    "ax.set_yticklabels(interval, fontsize=16)\n",
+    "ax.set_xlabel('Observed', fontsize=18)\n",
+    "ax.set_ylabel('Predicted', fontsize=18)\n",
+    "ax.set_title('Monthly mean {} (°C)'.format(NAMES[PREDICTAND]), fontsize=20, pad=10);\n",
+    "\n",
+    "# add axis for annual cycle\n",
+    "axins = inset_axes(ax, width=\"30%\", height=\"40%\", loc=2, borderpad=1)\n",
+    "axins.plot(y_pred_ac[PREDICTAND].values, ls='--', color='k', label='Predicted')\n",
+    "axins.plot(y_true_ac[PREDICTAND].values, ls='-', color='k', label='Observed')\n",
+    "axins.legend(frameon=False, fontsize=12, loc='lower center');\n",
+    "axins.yaxis.tick_right()\n",
+    "#axins.set_yticks(np.arange(-10, 11, 2))\n",
+    "#axins.set_yticklabels(np.arange(-10, 11, 2), fontsize=12)\n",
+    "axins.set_yticks(np.arange(-0, 22, 2))\n",
+    "axins.set_yticklabels(np.arange(0, 22, 2), fontsize=12)\n",
+    "axins.set_xticks(np.arange(0, 12))\n",
+    "axins.set_xticklabels([calendar.month_name[i + 1] for i in np.arange(0, 12)], rotation=90, fontsize=12)\n",
+    "# axins.set_ylabel('{} / (°C)'.format(NAMES[PREDICTAND].capitalize()), fontsize=14)\n",
+    "# axins.set_xlabel('Month', fontsize=14);\n",
     "\n",
     "# save figure\n",
     "fig.savefig('../Notebooks/Figures/{}_r2.png'.format(PREDICTAND), dpi=300, bbox_inches='tight')"
@@ -330,36 +403,43 @@
    "source": [
     "# yearly average bias over reference period\n",
     "y_pred_yearly_avg = y_pred.groupby('time.year').mean(dim='time')\n",
+    "y_refe_yearly_avg = y_refe.groupby('time.year').mean(dim='time')\n",
     "y_true_yearly_avg = y_true.groupby('time.year').mean(dim='time')\n",
     "bias_yearly_avg = y_pred_yearly_avg - y_true_yearly_avg\n",
+    "bias_yearly_avg_ref = y_refe_yearly_avg - y_true_yearly_avg\n",
     "for var in bias_yearly_avg:\n",
-    "    print('Yearly average bias of {}: {:.2f}'.format(var, bias_yearly_avg[var].mean().item()))"
+    "    print('(Model) Yearly average bias of {}: {:.2f}°C'.format(var, bias_yearly_avg[var].mean().item()))\n",
+    "    print('(ERA-5) Yearly average bias of {}: {:.2f}°C'.format(var, bias_yearly_avg_ref.mean().to_array().values.item()))"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "2ef19dce-29ac-4f6f-9999-e67745a4afd1",
+   "id": "fa14fadb-0f76-4962-80cb-e69cd7f5fac5",
    "metadata": {},
    "outputs": [],
    "source": [
     "# mean absolute error over reference period\n",
     "mae_avg = np.abs(y_pred_yearly_avg - y_true_yearly_avg).mean()\n",
+    "mae_avg_ref = np.abs(y_refe_yearly_avg - y_true_yearly_avg).mean()\n",
     "for var in mae_avg:\n",
-    "    print('Yearly average MAE of {}: {:.2f}'.format(var, mae_avg[var].item()))"
+    "    print('(Model) Yearly average MAE of {}: {:.2f}°C'.format(var, mae_avg[var].item()))\n",
+    "    print('(ERA-5) Yearly average MAE of {}: {:.2f}°C'.format(var, mae_avg_ref.mean().to_array().values.item()))"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "4c4dd156-f763-482c-84e6-c4329bfd3fe4",
+   "id": "d2c50119-3cee-43c5-838b-e84639af55db",
    "metadata": {},
    "outputs": [],
    "source": [
     "# root mean squared error over reference period\n",
     "rmse_avg = ((y_pred_yearly_avg - y_true_yearly_avg) ** 2).mean()\n",
+    "rmse_avg_ref = ((y_refe_yearly_avg - y_true_yearly_avg) **2).mean()\n",
     "for var in rmse_avg:\n",
-    "    print('Yearly average RMSE of {}: {:.2f}'.format(var, rmse_avg[var].item()))"
+    "    print('(Model) Yearly average RMSE of {}: {:.2f}°C'.format(var, rmse_avg[var].item()))\n",
+    "    print('(ERA-5) Yearly average RMSE of {}: {:.2f}°C'.format(var, rmse_avg_ref.mean().to_array().values.item()))"
    ]
   },
   {
@@ -463,27 +543,42 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "24aadff5-b19d-4f4b-a4c5-32ee656e64cd",
+   "id": "8b781300-2639-437d-9875-f57306715c80",
    "metadata": {},
    "outputs": [],
    "source": [
     "# group data by season: (DJF, MAM, JJA, SON)\n",
     "y_true_snl = y_true.groupby('time.season').mean(dim='time')\n",
     "y_pred_snl = y_pred.groupby('time.season').mean(dim='time')\n",
-    "bias_snl = y_pred_snl - y_true_snl"
+    "y_refe_snl = y_refe.groupby('time.season').mean(dim='time')\n",
+    "bias_snl = y_pred_snl - y_true_snl\n",
+    "bias_snl_ref = y_refe_snl - y_true_snl"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "2d0d5a46-0652-4289-9e1c-6d47aafcfef0",
+   "id": "b148ec7e-f832-40f2-b287-c0351e7e1aad",
    "metadata": {},
    "outputs": [],
    "source": [
-    "# print average bias per season\n",
+    "# print average bias per season: ERA-5\n",
+    "for var in bias_snl_ref.data_vars:\n",
+    "    for season in bias_snl_ref[PREDICTAND].season:\n",
+    "        print('(ERA-5) Average bias of mean {} for season {}: {:.1f}°C'.format(var, season.values.item(), bias_snl_ref[var].sel(season=season).mean().item()))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "e54daae8-ea32-431f-8a34-f92d95e7627e",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# print average bias per season: model\n",
     "for var in bias_snl.data_vars:\n",
     "    for season in bias_snl[PREDICTAND].season:\n",
-    "        print('Average bias of {} for season {}: {:.2f}'.format(var, season.values.item(), bias_snl[var].sel(season=season).mean().item()))"
+    "        print('(Model) Average bias of mean {} for season {}: {:.1f}°C'.format(var, season.values.item(), bias_snl[var].sel(season=season).mean().item()))"
    ]
   },
   {
@@ -612,7 +707,7 @@
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "c3da76d3-7261-4084-b5ec-f65682fd6596",
+   "id": "8fd82b83-0824-4663-846c-53fc3afbc7d1",
    "metadata": {},
    "outputs": [],
    "source": [
@@ -620,46 +715,116 @@
     "with warnings.catch_warnings():\n",
     "    warnings.simplefilter('ignore', category=RuntimeWarning)\n",
     "    y_pred_ex = y_pred.groupby('time.year').quantile(quantile, dim='time')\n",
-    "    y_true_ex = y_true.groupby('time.year').quantile(quantile, dim='time')"
+    "    y_true_ex = y_true.groupby('time.year').quantile(quantile, dim='time')\n",
+    "    y_refe_ex = y_refe.groupby('time.year').quantile(quantile, dim='time')"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "20db96c8-e04f-4acb-886b-abb740863fbb",
+   "id": "822984f8-cdaa-410b-96e8-e58da39ba40d",
    "metadata": {},
    "outputs": [],
    "source": [
     "# calculate bias in extreme quantile for each year\n",
     "bias_ex = y_pred_ex - y_true_ex\n",
+    "bias_ex_ref = y_refe_ex - y_true_ex"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "efd902ee-1154-4b0c-bfbd-a64ace625e76",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# bias of extreme quantile: ERA-5\n",
+    "for var in bias_ex_ref:\n",
+    "    print('(ERA-5) Yearly average bias for P{:.0f} of {}: {:.1f}°C'.format(quantile * 100, var, bias_ex_ref[var].mean().item()))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "9343d8a4-07a6-4c9c-85f6-f670efe7c6cd",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# bias of extreme quantile: Model\n",
     "for var in bias_ex:\n",
-    "    print('Yearly average bias for P{:.0f} of {}: {:.2f}'.format(quantile * 100, var, bias_ex[var].mean().item()))"
+    "    print('(Model) Yearly average bias for P{:.0f} of {}: {:.1f}°C'.format(quantile * 100, var, bias_ex[var].mean().item()))"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "c7aeff55-deef-4d3c-a251-eac877c9afd9",
+   "id": "ba38c293-6a6c-4ce4-b5a2-8e468e69cb44",
    "metadata": {},
    "outputs": [],
    "source": [
     "# mean absolute error in extreme quantile\n",
     "mae_ex = np.abs(y_pred_ex - y_true_ex).mean()\n",
+    "mae_ex_ref = np.abs(y_refe_ex - y_true_ex).mean()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "d71dd376-f445-4c27-8ffc-7ec9f1583b52",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# mae of extreme quantile: ERA-5\n",
+    "for var in mae_ex_ref:\n",
+    "    print('(ERA-5) Yearly average MAE for P{:.0f} of {}: {:.1f}°C'.format(quantile * 100, var, mae_ex_ref[var].item()))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "440cbb08-5a06-4708-baa5-3ca3bdb0675a",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# mae of extreme quantile: Model\n",
     "for var in mae_ex:\n",
-    "    print('Yearly average MAE for P{:.0f} of {}: {:.2f}'.format(quantile * 100, var, mae_ex[var].item()))"
+    "    print('(Model) Yearly average MAE for P{:.0f} of {}: {:.1f}°C'.format(quantile * 100, var, mae_ex[var].item()))"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": null,
-   "id": "2dc6b7cf-7ae1-4b0e-8483-376eab59f5dd",
+   "id": "fd263446-b57f-4f4a-86fd-5b5596aa32ee",
    "metadata": {},
    "outputs": [],
    "source": [
-    "# root mean squared error over reference period\n",
+    "# root mean squared error in extreme quantile\n",
     "rmse_ex = ((y_pred_ex - y_true_ex) ** 2).mean()\n",
+    "rmse_ex_ref = ((y_refe_ex - y_true_ex) ** 2).mean()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "90245a82-992f-4592-8749-d7a21c1f3a21",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# rmse of extreme quantile: ERA-5\n",
+    "for var in rmse_ex_ref:\n",
+    "    print('(ERA-5) Yearly average RMSE for P{:.0f} of {}: {:.1f}°C'.format(quantile * 100, var, rmse_ex_ref[var].item()))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "92591caa-8ed4-4f91-a5ea-32f6b095cdfe",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# rmse of extreme quantile: Model\n",
     "for var in rmse_ex:\n",
-    "    print('Yearly average RMSE for P{:.0f} of {}: {:.2f}'.format(quantile * 100, var, rmse_ex[var].item()))"
+    "    print('(Model) Yearly average RMSE for P{:.0f} of {}: {:.1f}°C'.format(quantile * 100, var, rmse_ex[var].item()))"
    ]
   },
   {
@@ -728,6 +893,111 @@
     "# save figure\n",
     "fig.savefig('../Notebooks/Figures/{}_average_bias_p{:.0f}.png'.format(PREDICTAND, quantile * 100), dpi=300, bbox_inches='tight')"
    ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "b1550618-1314-4d45-a6b7-2f853dce3eb1",
+   "metadata": {},
+   "source": [
+    "### Compute ERA-5 daily minimum and maximum 2m temperature"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "6a1a7bc8-2edf-46f3-9fb9-9f97ed262877",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# search ERA-5 hourly 2m temperature data\n",
+    "y_refe_list = sorted(search_files(ERA5_PATH.joinpath('Downloads', '2m_temperature'), '.nc$'))\n",
+    "y_refe_list"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "b6d6e195-85e9-4ac0-9e50-79fd20042665",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "y_refe = xr.open_mfdataset(y_refe_list)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "7cbdf926-9f01-49a7-9e61-d864af4a3c38",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "t_max = y_refe.resample(time='D').max(dim='time')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "71b38603-5ee3-4fd8-8360-67bdcb2b8f47",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "t_min = y_refe.resample(time='D').min(dim='time')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "33c09067-9060-4432-b33a-831b4ec59c66",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "t_max.to_netcdf('./tmax_tmp.nc', engine='h5netcdf')\n",
+    "t_min.to_netcdf('./tmin_tmp.nc', engine='h5netcdf')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "a3a8d0fe-3d14-4a10-8314-59a5319551ee",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "grid = '/mnt/CEPH_PROJECTS/FACT_CLIMAX/OBS_DATA/grid_1km_laea'"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "bb0de3d6-b4ef-4228-a2c5-a06b0e540af9",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import pathlib\n",
+    "target = pathlib.Path('/mnt/CEPH_PROJECTS/FACT_CLIMAX/REANALYSIS/ERA5/2m_{}_temperature/ERA5_2m_{}_temperature_1981_2010.nc')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "9083153e-bde5-4c06-88f8-a55ba693fdda",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from climax.core.utils import reproject_cdo"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "cc973c07-0a24-4b3f-a5c8-5b9fc8347cdc",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "for name, ds in zip(['min', 'max'], ['./tmin_tmp.nc', './tmax_tmp.nc']):\n",
+    "    out = pathlib.Path(str(target).format(name, name))\n",
+    "    #out.parent.mkdir(parents=True, exist_ok=True)\n",
+    "    reproject_cdo(grid, ds, out, mode='bilinear', overwrite=True)"
+   ]
   }
  ],
  "metadata": {