diff --git a/Jupyter_Notebooks/conditional_quantile_plot.ipynb b/Jupyter_Notebooks/conditional_quantile_plot.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..01922a48122017c03e1121f4a6bcc4d72884cbdc
--- /dev/null
+++ b/Jupyter_Notebooks/conditional_quantile_plot.ipynb
@@ -0,0 +1,389 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "id": "under-cooler",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import os, sys\n",
+    "import glob\n",
+    "import datetime as dt\n",
+    "import numpy as np\n",
+    "import xarray as xr\n",
+    "\n",
+    "import time "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 79,
+   "id": "becoming-dover",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "8440\n",
+      "Data variables:\n",
+      "    2t_in                   (in_hour, lat, lon) float32 ...\n",
+      "    tcc_in                  (in_hour, lat, lon) float32 ...\n",
+      "    t_850_in                (in_hour, lat, lon) float32 ...\n",
+      "    2t_ref                  (fcst_hour, lat, lon) float32 ...\n",
+      "    tcc_ref                 (fcst_hour, lat, lon) float32 ...\n",
+      "    t_850_ref               (fcst_hour, lat, lon) float32 ...\n",
+      "    2t_savp_fcst            (fcst_hour, lat, lon) float32 ...\n",
+      "    tcc_savp_fcst           (fcst_hour, lat, lon) float32 ...\n",
+      "    t_850_savp_fcst         (fcst_hour, lat, lon) float32 ...\n",
+      "    2t_persistence_fcst     (fcst_hour, lat, lon) float64 ...\n",
+      "    tcc_persistence_fcst    (fcst_hour, lat, lon) float64 ...\n",
+      "    t_850_persistence_fcst  (fcst_hour, lat, lon) float64 ...\n"
+     ]
+    }
+   ],
+   "source": [
+    "forecast_path = \"/p/home/jusers/langguth1/juwels/video_prediction_shared_folder/results/era5-Y2007-2019M01to12-80x48-3960N0180E-2t_tcc_t_850_langguth1/savp/20210505T131220_mache1_karim_savp_smreg_cv3_3\"\n",
+    "fnames= os.path.join(forecast_path, \"vfp_date_*sample_ind_*.nc\" )\n",
+    "\n",
+    "fnames = glob.glob(fnames)\n",
+    "print(len(fnames))\n",
+    "\n",
+    "dfile = xr.open_dataset(fnames[99])\n",
+    "\n",
+    "print(dfile.data_vars)\n",
+    "#print(dfile[\"init_time\"])\n",
+    "#print(dfile[\"2t_savp_fcst\"][2])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 80,
+   "id": "editorial-bunny",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def non_interst_vars(ds):\n",
+    "    \"\"\"\n",
+    "    Creates list of variables that are not of interest. For this, vars2proc must be defined at global scope\n",
+    "    :param ds: the dataset\n",
+    "    :return: list of variables in dataset that are not of interest\n",
+    "    \"\"\"\n",
+    "    return [v for v in ds.data_vars\n",
+    "            if v not in vars2proc]\n",
+    "#\n",
+    "# ====================================================================================================\n",
+    "\n",
+    "\n",
+    "def get_relevant_vars(ds):\n",
+    "    \"\"\"\n",
+    "    Drops variables that are not of interest from dataset and also shrinks data to cells of interest.\n",
+    "    For this, ncells must be a dimension of the dataset and dmask_ref_inds must be defined at gloabl scope\n",
+    "    :param ds: the dataset\n",
+    "    :return: dataset with non-interesting variables dropped and data shrinked to region of interest\n",
+    "    \"\"\"\n",
+    "    return ds.drop(non_interst_vars(ds)).isel(fcst_hour=11)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 81,
+   "id": "great-metro",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Registering and loading data took 1057.31 seconds\n"
+     ]
+    }
+   ],
+   "source": [
+    "vars2proc = [\"2t_savp_fcst\", \"2t_ref\"]\n",
+    "\n",
+    "time0 = time.time()\n",
+    "with xr.open_mfdataset(fnames, decode_cf=True, combine=\"nested\", concat_dim=[\"init_time\"], compat=\"broadcast_equals\", preprocess=get_relevant_vars) as dfiles:\n",
+    "    data = dfiles.load()\n",
+    "    #times0 = dfiles[\"time_forecast\"]\n",
+    "    print(\"Registering and loading data took {0:.2f} seconds\".format(time.time()- time0))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 82,
+   "id": "hindu-wesley",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "<xarray.Dataset>\n",
+      "Dimensions:       (init_time: 8440, lat: 48, lon: 80)\n",
+      "Coordinates:\n",
+      "  * init_time     (init_time) datetime64[ns] 2010-08-20T05:00:00 ... 2010-03-...\n",
+      "  * lat           (lat) float64 53.7 53.4 53.1 52.8 52.5 ... 40.5 40.2 39.9 39.6\n",
+      "  * lon           (lon) float64 1.8 2.1 2.4 2.7 3.0 ... 24.3 24.6 24.9 25.2 25.5\n",
+      "    fcst_hour     int64 12\n",
+      "Data variables:\n",
+      "    2t_savp_fcst  (init_time, lat, lon) float32 291.3 291.8 ... 288.5 288.2\n",
+      "    2t_ref        (init_time, lat, lon) float32 292.2 292.1 ... 288.5 288.6\n"
+     ]
+    }
+   ],
+   "source": [
+    "data_correct = xr.Dataset({\"2t_savp_fcst\": data[\"2t_savp_fcst\"], \"2t_ref\": data[\"2t_ref\"]})\n",
+    "print(data_correct)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 83,
+   "id": "sweet-happening",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313]\n"
+     ]
+    }
+   ],
+   "source": [
+    "data_fcst, data_ref = data_correct[\"2t_savp_fcst\"], data_correct[\"2t_ref\"]\n",
+    "\n",
+    "fcst_min, fcst_max = np.floor(np.min(data_fcst)), np.ceil(np.max(data_fcst))\n",
+    "x_bins = list(np.arange(int(fcst_min), int(fcst_max) + 1))\n",
+    "x_bins_c = 0.5*(np.asarray(x_bins[0:-1]) + np.asarray(x_bins[1:]))\n",
+    "nbins = len(x_bins) - 1\n",
+    "\n",
+    "print(x_bins)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 84,
+   "id": "incorporate-flooring",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import matplotlib.pyplot as plt\n",
+    "\n",
+    "quantiles = [0.05, 0.5, 0.95]\n",
+    "nquantiles = len(quantiles)\n",
+    "quantile_panel = xr.DataArray(np.full((nbins, nquantiles), np.nan), coords={\"bin_center\": x_bins_c, \"quantile\": quantiles},\n",
+    "                              dims=[\"bin_center\", \"quantile\"])\n",
+    "for i in np.arange(nbins):\n",
+    "    data_cropped = data_correct[\"2t_ref\"].where(np.logical_and(data_correct[\"2t_savp_fcst\"] >= x_bins[i],\n",
+    "                                                               data_correct[\"2t_savp_fcst\"] < x_bins[i+1]))\n",
+    "    quantile_panel.loc[dict(bin_center=x_bins_c[i])] = data_cropped.quantile([0.05, 0.5, 0.95])\n",
+    "    \n",
+    "x_bins_c = x_bins_c - 273.15\n",
+    "quantile_panel = quantile_panel - 273.15"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 85,
+   "id": "brilliant-aberdeen",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "image/png": "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\n",
+      "text/plain": [
+       "<Figure size 648x432 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "fig, ax = plt.subplots(figsize=(9,6))\n",
+    "\n",
+    "ls_all = [\"--\", \"-\", \"--\"]\n",
+    "lw_all = [2., 1.5, 2.]\n",
+    "ax.plot(x_bins_c, x_bins_c, color='k', label='reference 1:1', linewidth=1.)\n",
+    "for i in np.arange(3):\n",
+    "    ax.plot(x_bins_c, quantile_panel.isel(quantile=i), ls=ls_all[i], color=\"k\", lw=lw_all[i])\n",
+    "    \n",
+    "ax.set_ylabel(\"2m temperature from ERA5 [°C]\", fontsize=16)\n",
+    "ax.set_xlabel(\"Predicted 2m temperature from SAVP [°C]\", fontsize=16)\n",
+    "\n",
+    "ax.tick_params(axis=\"both\", labelsize=14)\n",
+    "\n",
+    "fig.savefig(\"./first_cond_quantile.png\")\n",
+    "    "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "id": "relevant-freight",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#data_grouped = data_correct.groupby_bins(\"2t_savp_fcst\", x_bins)#.groups"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 148,
+   "id": "ordered-cambridge",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[[[22 22 22 ... 18 18 18]\n",
+      "  [22 22 22 ... 18 18 18]\n",
+      "  [22 22 22 ... 19 19 19]\n",
+      "  ...\n",
+      "  [29 29 29 ... 30 30 30]\n",
+      "  [29 30 29 ... 31 31 31]\n",
+      "  [29 30 29 ... 31 31 31]]\n",
+      "\n",
+      " [[21 21 21 ... 20 20 20]\n",
+      "  [20 21 21 ... 20 20 20]\n",
+      "  [20 21 21 ... 20 20 20]\n",
+      "  ...\n",
+      "  [30 30 30 ... 31 31 31]\n",
+      "  [30 30 30 ... 31 31 31]\n",
+      "  [30 30 30 ... 31 31 31]]\n",
+      "\n",
+      " [[21 21 21 ... 21 21 21]\n",
+      "  [21 21 21 ... 21 21 21]\n",
+      "  [21 21 21 ... 21 21 21]\n",
+      "  ...\n",
+      "  [28 28 28 ... 31 31 31]\n",
+      "  [28 28 28 ... 32 32 31]\n",
+      "  [28 29 29 ... 32 32 32]]\n",
+      "\n",
+      " ...\n",
+      "\n",
+      " [[22 22 22 ... 20 20 20]\n",
+      "  [22 22 22 ... 20 20 20]\n",
+      "  [22 21 21 ... 20 20 20]\n",
+      "  ...\n",
+      "  [29 29 29 ... 31 31 31]\n",
+      "  [29 29 29 ... 32 32 32]\n",
+      "  [30 30 29 ... 32 32 32]]\n",
+      "\n",
+      " [[21 21 21 ... 20 20 20]\n",
+      "  [20 21 21 ... 20 20 20]\n",
+      "  [20 20 21 ... 20 20 20]\n",
+      "  ...\n",
+      "  [30 30 30 ... 31 31 31]\n",
+      "  [30 30 29 ... 31 31 31]\n",
+      "  [30 30 30 ... 31 31 31]]\n",
+      "\n",
+      " [[22 22 22 ... 24 24 24]\n",
+      "  [22 22 22 ... 24 23 24]\n",
+      "  [22 22 22 ... 24 24 24]\n",
+      "  ...\n",
+      "  [27 27 27 ... 31 31 31]\n",
+      "  [28 28 28 ... 32 32 32]\n",
+      "  [28 28 28 ... 32 32 32]]]\n"
+     ]
+    }
+   ],
+   "source": [
+    "inds_of_bins = np.digitize(data_fcst, x_bins, right=True)\n",
+    "\n",
+    "print(inds_of_bins)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 149,
+   "id": "furnished-customer",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "<xarray.DataArray '2t_ref' (2t_savp_fcst_bins: 37)>\n",
+      "array([259.60351562, 264.13945557, 264.74759033, 265.45030518,\n",
+      "       266.47970703, 267.3628302 , 268.44342804, 269.80157959,\n",
+      "       270.4291217 , 271.22656982, 272.41841827, 274.18320801,\n",
+      "       274.74815369, 275.68839111, 276.3840918 , 277.0491394 ,\n",
+      "       277.99171387, 279.1111615 , 280.24440918, 281.56947693,\n",
+      "       282.817146  , 284.15313873, 285.25139038, 286.46736084,\n",
+      "       287.11281006, 287.56309875, 288.39205322, 289.28383789,\n",
+      "       290.12092529, 291.00213623, 291.93958588, 292.7901001 ,\n",
+      "       294.50114746, 295.28106201, 295.7451416 , 296.17975464,\n",
+      "       295.94475342])\n",
+      "Coordinates:\n",
+      "  * 2t_savp_fcst_bins  (2t_savp_fcst_bins) object (260, 261] ... (296, 297]\n",
+      "    quantile           float64 0.99\n",
+      "<xarray.DataArray '2t_savp_fcst' (2t_savp_fcst_bins: 37)>\n",
+      "array([260.51538086, 261.99571045, 262.96671509, 263.99466095,\n",
+      "       264.98212372, 265.99100769, 266.99321747, 267.99145386,\n",
+      "       268.99003754, 269.9897348 , 270.99363922, 271.99260651,\n",
+      "       272.98925781, 273.99296265, 274.99265747, 275.9934906 ,\n",
+      "       276.99263123, 277.99108887, 278.98980103, 279.99055573,\n",
+      "       280.98829712, 281.99064941, 282.98851074, 283.98887085,\n",
+      "       284.99008545, 285.99044281, 286.99019897, 287.9892334 ,\n",
+      "       288.98918335, 289.98908264, 290.98603363, 291.96720215,\n",
+      "       292.98072205, 293.98917358, 294.99038391, 295.9605835 ,\n",
+      "       296.59046722])\n",
+      "Coordinates:\n",
+      "  * 2t_savp_fcst_bins  (2t_savp_fcst_bins) object (260, 261] ... (296, 297]\n",
+      "    quantile           float64 0.99\n"
+     ]
+    }
+   ],
+   "source": [
+    "def calc_quantile(x, dim =\"init_time\"):\n",
+    "    return x.quantile(0.99)\n",
+    "\n",
+    "cond_quantile1 = data_grouped.map(calc_quantile)\n",
+    "#cond_quantile2 = data_grouped.map(calc_quantile)\n",
+    "\n",
+    "\n",
+    "print(cond_quantile1[\"quantile\"])\n",
+    "print(cond_quantile1[\"2t_savp_fcst\"])\n",
+    "\n",
+    "#print(cond_quantile2[\"2t_ref\"])\n",
+    "#print(cond_quantile2[\"2t_savp_fcst\"])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "electrical-evening",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "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.8.5"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/Jupyter_Notebooks/first_cond_quantile.png b/Jupyter_Notebooks/first_cond_quantile.png
new file mode 100644
index 0000000000000000000000000000000000000000..6ff3a7a8a081c4a874d2e2a8c8d3d0d2e47d1fb5
Binary files /dev/null and b/Jupyter_Notebooks/first_cond_quantile.png differ
diff --git a/Jupyter_Notebooks/juwels_juwelsbooster_compare_old.ipynb b/Jupyter_Notebooks/juwels_juwelsbooster_compare_old.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..d788742d00cb9054dd90557edc674e481cf1c77b
--- /dev/null
+++ b/Jupyter_Notebooks/juwels_juwelsbooster_compare_old.ipynb
@@ -0,0 +1,684 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 16,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import os, glob\n",
+    "import math\n",
+    "import pickle\n",
+    "import numpy as np\n",
+    "import xarray as xr\n",
+    "import matplotlib\n",
+    "matplotlib.use('Agg')\n",
+    "from matplotlib.transforms import Affine2D\n",
+    "from matplotlib.patches import Polygon\n",
+    "import matplotlib.pyplot as plt\n",
+    "%matplotlib inline\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "base = \"/p/project/deepacf/deeprain/video_prediction_shared_folder/models/\"+ \\\n",
+    "       \"era5-Y2010toY2222M01to12-160x128-2970N1500W-T2_MSL_gph500/convLSTM/\"\n",
+    "fname_timing_train = \"/timing_training_time.pkl\"\n",
+    "fname_timing_total = \"/timing_total_time.pkl\"\n",
+    "\n",
+    "fname_timing_iter = \"timing_per_iteration_time.pkl\""
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# some auxiliary functions\n",
+    "def orderOfMagnitude(number):\n",
+    "    return np.floor(np.log(number, 10))\n",
+    "\n",
+    "def total_times(infile):\n",
+    "    with open(infile,'rb') as tfile:\n",
+    "        #print(\"Opening pickle time: '{0}'\".format(infile))\n",
+    "        total_time_sec = pickle.load(tfile)\n",
+    "    return np.asarray(total_time_sec/60)\n",
+    "\n",
+    "def log_total_times(infile):\n",
+    "    total_time_min = total_times(infile)\n",
+    "    return np.log(total_time_min)\n",
+    "\n",
+    "\n",
+    "def get_time_dict(base, wildcardspec, tfilename, gpu_id_str=\"gpu\", llog = False):\n",
+    "    time_dict = {}\n",
+    "    flist_hpc = sorted(glob.glob(base + wildcardspec))\n",
+    "    wrapper = total_times\n",
+    "    if llog: wrapper = log_total_times\n",
+    "    for tfile in flist_hpc: \n",
+    "        ngpus = get_ngpus(tfile, gpu_id_str)\n",
+    "        time_dict[\"{0:d} GPU(s)\".format(ngpus)] = wrapper(tfile + tfilename)\n",
+    "    return time_dict\n",
+    "\n",
+    "def get_ngpus(fname, search_str, max_order=3):\n",
+    "    \"\"\"\n",
+    "    Tries to get numbers in the vicinty of search_str which is supposed to be a substring in fname.\n",
+    "    First seaches for numbers right before the occurence of search_str, then afterwards.\n",
+    "    :param fname: file name from which number should be inferred\n",
+    "    :param search_str: seach string for which number identification is considered to be possible\n",
+    "    :param max_order: maximum order of retrieved number (default: 3 -> maximum number is 999 then)\n",
+    "    :return num_int: integer of number in the vicintity of search string. \n",
+    "    \"\"\"\n",
+    "    \n",
+    "    ind_gpu_info = fname.lower().find(search_str)\n",
+    "    if ind_gpu_info == -1:\n",
+    "        raise ValueError(\"Unable to find search string '{0}' in file name '{1}'\".format(search_str, fname))\n",
+    "    \n",
+    "    # init loops\n",
+    "    fname_len = len(fname)\n",
+    "    success, flag = False, True\n",
+    "    indm = 1\n",
+    "    ind_sm, ind_sp = 0, 0\n",
+    "\n",
+    "    # check occurence of numbers in front of search string\n",
+    "    while indm < max_order and flag:\n",
+    "        if ind_gpu_info - indm > 0:\n",
+    "            if fname[ind_gpu_info - indm].isnumeric():\n",
+    "                ind_sm += 1\n",
+    "                success = True\n",
+    "            else:\n",
+    "                flag = False\n",
+    "        else:\n",
+    "            flag = False\n",
+    "        indm += 1\n",
+    "  \n",
+    "\n",
+    "    if not success: # check occurence of numbers after search string\n",
+    "        ind_gpu_info = ind_gpu_info + len(search_str)\n",
+    "        flag = True\n",
+    "        indm = 0\n",
+    "        while indm < max_order and flag: \n",
+    "            if ind_gpu_info + indm < fname_len:\n",
+    "                if fname[ind_gpu_info + indm].isnumeric():\n",
+    "                    ind_sp += 1\n",
+    "                    success = True\n",
+    "                else:\n",
+    "                    flag = False\n",
+    "            else:\n",
+    "                flag = False\n",
+    "            indm += 1\n",
+    "            \n",
+    "        if success:\n",
+    "            return(int(fname[ind_gpu_info:ind_gpu_info+ind_sp]))\n",
+    "        else:\n",
+    "            raise ValueError(\"Search string found in fname, but unable to infer number of GPUs.\")\n",
+    "\n",
+    "    else:\n",
+    "        return(int(fname[ind_gpu_info-ind_sm:ind_gpu_info]))\n",
+    "        \n",
+    "        \n",
+    "    "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Total computation with 16 GPU(s): 152.50984706878663\n",
+      "Total computation with 32 GPU(s): 81.80640578667322\n",
+      "Total computation with 4 GPU(s): 554.5182513117791\n",
+      "Total computation with 64 GPU(s): 45.01537701288859\n",
+      "Total computation with 8 GPU(s): 287.91878341039023\n"
+     ]
+    }
+   ],
+   "source": [
+    "# Juwels\n",
+    "wildcard_juwels = '20210115T135325_langguth1_test_venv_juwels_container*old'\n",
+    "total_time_min_juwels = get_time_dict(base, wildcard_juwels, fname_timing_total, \"gpus\")\n",
+    "training_time_min_juwels = get_time_dict(base, wildcard_juwels, fname_timing_train, \"gpus\")\n",
+    "for key in training_time_min_juwels.keys():\n",
+    "    print(\"Total computation with {0}: {1}\".format(key, training_time_min_juwels[key]))\n",
+    "\n",
+    "overhead_time_juwels = {}\n",
+    "for key in training_time_min_juwels.keys() & total_time_min_juwels.keys():\n",
+    "    overhead_time_juwels[key] = total_time_min_juwels[key] - training_time_min_juwels[key]\n",
+    "    \n",
+    "#print('Juwels total time in minutes', get_time_d)\n",
+    "#print('Juwels total training time in minutes', training_time_min_juwels)\n",
+    "#overhead_time_juwels = np.array(total_time_min_juwels) - np.array(training_time_min_juwels)\n",
+    "#print('Juwels overhead time in minutes', overhead_time_juwels)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Total computation with 1 GPU(s): 566.7376739541689\n",
+      "Total computation with 4 GPU(s): 159.4931242307027\n",
+      "Total computation with 8 GPU(s): 92.15467914342881\n",
+      "Total computation with 16 GPU(s): 46.11619712909063\n",
+      "Total computation with 32 GPU(s): 33.09077355464299\n",
+      "Total computation with 64 GPU(s): 23.24405464331309\n"
+     ]
+    }
+   ],
+   "source": [
+    "# Juwels booster\n",
+    "wildcard_booster = '2020*gong1_booster_gpu*'\n",
+    "total_time_min_booster = get_time_dict(base, wildcard_booster, fname_timing_total)\n",
+    "training_time_min_booster = get_time_dict(base, wildcard_booster, fname_timing_train)\n",
+    "for key in training_time_min_booster.keys():\n",
+    "    print(\"Total computation with {0}: {1}\".format(key, training_time_min_booster[key]))\n",
+    "\n",
+    "#print('Juwels Booster total time in minutes', list_times(base, wildcard_booster, filename_timing_total))\n",
+    "#print('Juwels Booster total training time in minutes', list_times(base, wildcard_booster, filename_timing_train))\n",
+    "overhead_time_booster = {}\n",
+    "for key in training_time_min_booster.keys() & total_time_min_booster.keys():\n",
+    "    overhead_time_booster[key] = total_time_min_booster[key] - training_time_min_booster[key]\n",
+    "#print('Juwels overhead time in minutes', overhead_time_booster)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def time_per_iteration_mean_std(infile):\n",
+    "    with open(infile, 'rb') as tfile:\n",
+    "        time_per_iteration_list = pickle.load(tfile) \n",
+    "        \n",
+    "    time_per_iteration = np.array(time_per_iteration_list)\n",
+    "    return np.mean(time_per_iteration), np.std(time_per_iteration)\n",
+    "\n",
+    "def iter_stat(base, wildcardspec, gpu_id_str=\"gpu\"):\n",
+    "    stat_iter_dict = {}\n",
+    "    flist_hpc = sorted(glob.glob(base + wildcardspec))\n",
+    "    for tdir in flist_hpc: \n",
+    "        ngpus = get_ngpus(tdir, gpu_id_str)\n",
+    "        ftname = os.path.join(tdir, fname_timing_iter)\n",
+    "        mean_loc, std_loc = time_per_iteration_mean_std(ftname)\n",
+    "        stat_iter_dict[\"{0:d} GPU(s)\".format(ngpus)] = {\"mean\": mean_loc , \"std\": std_loc}\n",
+    "    return stat_iter_dict\n",
+    "\n",
+    "def time_per_iteration_all(infile):\n",
+    "    with open(infile,'rb') as tfile:\n",
+    "        time_per_iteration_list = pickle.load(tfile)\n",
+    "    return np.asarray(time_per_iteration_list)\n",
+    "\n",
+    "def all_iter(base, wildcardspec, gpu_id_str=\"gpu\"):\n",
+    "    iter_dict = {}\n",
+    "    flist_hpc = sorted(glob.glob(base + wildcardspec))\n",
+    "    for tdir in flist_hpc: \n",
+    "        ngpus = get_ngpus(tdir, gpu_id_str)\n",
+    "        ftname = os.path.join(tdir, fname_timing_iter)\n",
+    "        iter_dict[\"{0:d} GPU(s)\".format(ngpus)] = time_per_iteration_all(ftname)\n",
+    "    return iter_dict    \n",
+    "    "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 30,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "JUWELS (0.6151515198034729, 0.20104178037750603)\n",
+      "Booster (0.3521572324468615, 0.3656996619706779)\n"
+     ]
+    }
+   ],
+   "source": [
+    "# Juwels\n",
+    "print('JUWELS', time_per_iteration_mean_std('/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2010toY2222M01to12-160x128-2970N1500W-T2_MSL_gph500/convLSTM/20201210T140958_stadtler1_comparison_1node_1gpu/timing_per_iteration_time.pkl'))\n",
+    "# Booster\n",
+    "print('Booster', time_per_iteration_mean_std('/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2010toY2222M01to12-160x128-2970N1500W-T2_MSL_gph500/convLSTM/20201210T141910_gong1_booster_gpu1/timing_per_iteration_time.pkl'))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 31,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Juwels mean and standart deviation {'16 GPU(s)': {'mean': 0.8209993402058342, 'std': 0.2627643291319852}, '32 GPU(s)': {'mean': 0.8590118098249986, 'std': 0.4078450977768068}, '4 GPU(s)': {'mean': 0.7445914211655112, 'std': 0.13789611351045}, '64 GPU(s)': {'mean': 0.9353915504630987, 'std': 0.6640973670265782}, '8 GPU(s)': {'mean': 0.7804724221628322, 'std': 0.21824334555299446}}\n"
+     ]
+    }
+   ],
+   "source": [
+    "# Juwels\n",
+    "print('Juwels mean and standart deviation',iter_stat(base, wildcard_juwels))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Booster mean and standart deviation {'1 GPU(s)': {'mean': 0.3521572324468615, 'std': 0.3656996619706779}, '4 GPU(s)': {'mean': 0.41844419631014446, 'std': 0.5273198599590724}, '8 GPU(s)': {'mean': 0.48867375665101026, 'std': 0.4378652997442439}, '16 GPU(s)': {'mean': 0.4786909431320202, 'std': 0.49638173862734053}, '32 GPU(s)': {'mean': 0.6439339113469129, 'std': 1.4395666886291258}, '64 GPU(s)': {'mean': 0.8176603168024377, 'std': 2.1044189535471185}}\n"
+     ]
+    }
+   ],
+   "source": [
+    "# Booster\n",
+    "print('Booster mean and standart deviation',iter_stat(base, wildcard_booster))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 34,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Plotting \n",
+    "# Bar plot of total time and training time --> overhead time\n",
+    "\n",
+    "# dictionaries with the total times\n",
+    "tot_time_juwels_dict = get_time_dict(base, wildcard_juwels, fname_timing_total)\n",
+    "tot_time_booster_dict= get_time_dict(base, wildcard_booster, fname_timing_total)\n",
+    "\n",
+    "# dictionaries with the training times\n",
+    "train_time_juwels_dict = get_time_dict(base, wildcard_juwels, fname_timing_train)\n",
+    "train_time_booster_dict = get_time_dict(base, wildcard_booster, fname_timing_train)\n",
+    "\n",
+    "# get sorted arrays\n",
+    "# Note: The times for Juwels are divided by 2, since the experiments have been performed with an epoch number of 20\n",
+    "#       instead of 10 (as Bing and Scarlet did)\n",
+    "ngpus_sort = sorted([int(ngpu.split()[0]) for ngpu in tot_time_juwels_dict.keys()])\n",
+    "nexps = len(ngpus_sort)\n",
+    "tot_time_juwels = np.array([tot_time_juwels_dict[\"{0:d} GPU(s)\".format(key)] for key in ngpus_sort])/2.\n",
+    "tot_time_booster = np.array([tot_time_booster_dict[\"{0:d} GPU(s)\".format(key)] for key in ngpus_sort])\n",
+    "\n",
+    "train_time_juwels = np.array([train_time_juwels_dict[\"{0:d} GPU(s)\".format(key)] for key in ngpus_sort])/2.\n",
+    "train_time_booster = np.array([train_time_booster_dict[\"{0:d} GPU(s)\".format(key)] for key in ngpus_sort])\n",
+    "\n",
+    "overhead_juwels = tot_time_juwels - train_time_juwels \n",
+    "overhead_booster= tot_time_booster - train_time_booster\n",
+    "\n",
+    "names = [\"Juwels\", \"Juwels Booster\"]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 31,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "400.0\n",
+      "278.0\n",
+      "100.0\n",
+      "2.0\n"
+     ]
+    }
+   ],
+   "source": [
+    "plot_computation_times(tot_time_juwels, tot_time_booster, labels, [\"Juwels\", \"Juwels Booster\"], \\\n",
+    "                       \"./total_computation_time\", log_yvals=False)\n",
+    "\n",
+    "plot_computation_times(overhead_juwels, overhead_booster, labels, [\"Juwels\", \"Juwels Booster\"], \\\n",
+    "                       \"./overhead_time\")"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#print(labels)\n",
+    "#raise ValueError(\"Stop!\")\n",
+    "#x = np.arange(len(labels))  # the label locations\n",
+    "#width = 0.35  # the width of the bars\n",
+    "\n",
+    "#fig, ax = plt.subplots()\n",
+    "#rects1 = ax.bar(x - width/2, np.round(tot_time_juwels, 2), width, label='Juwels')\n",
+    "#rects2 = ax.bar(x + width/2, np.round(tot_time_booster, 2), width, label='Booster')\n",
+    "\n",
+    "def plot_computation_times(times1, times2, ngpus, names, plt_fname, log_yvals = False):\n",
+    "    \n",
+    "    nlabels = len(ngpus)\n",
+    "    x_pos = np.arange(nlabels)\n",
+    "    \n",
+    "    bar_width = 0.35\n",
+    "    ytitle = \"Time\"\n",
+    "    ymax = np.ceil(np.maximum(np.max(times1)/100. + 0.5, np.max(times2)/100. + 0.5))*100.\n",
+    "    print(ymax)    \n",
+    "    if log_yvals: \n",
+    "        times1, times2 = np.log(times1), np.log(times2)\n",
+    "        ytitle = \"LOG(Time) [min]\"\n",
+    "        ymax = np.ceil(np.maximum(np.max(times1)+0.5, np.max(times2) + 0.5))\n",
+    "    \n",
+    "    # create plot object\n",
+    "    fig, ax = plt.subplots()\n",
+    "    # create data bars\n",
+    "    rects1 = ax.bar(x_pos - bar_width/2, np.round(times1, 2), bar_width, label=names[0])\n",
+    "    rects2 = ax.bar(x_pos + bar_width/2, np.round(times2, 2), bar_width, label=names[1])\n",
+    "    # customize plot appearance\n",
+    "    # Add some text for labels, title and custom x-axis tick labels, etc.\n",
+    "    ax.set_ylabel(ytitle)\n",
+    "    ax.set_title('Comparison {0} and {1} with convLSTM model'.format(*names))\n",
+    "    ax.set_xticks(x_pos)\n",
+    "    ax.set_xticklabels(labels)\n",
+    "    ax.set_xlabel('# GPUs')\n",
+    "    print(np.ceil(np.maximum(np.max(times1)+0.5, np.max(times2) + 0.5)))\n",
+    "    ax.set_ylim(0., ymax)\n",
+    "    ax.legend()\n",
+    "                \n",
+    "    # add labels\n",
+    "    autolabel(ax, rects1)\n",
+    "    autolabel(ax, rects2)\n",
+    "    plt.savefig(plt_fname+\".png\")\n",
+    "    plt.close()\n",
+    "    \n",
+    "\n",
+    "def autolabel(ax, rects):\n",
+    "    \"\"\"Attach a text label above each bar in *rects*, displaying its height.\"\"\"\n",
+    "    for rect in rects:\n",
+    "        height = rect.get_height()\n",
+    "        ax.annotate('{}'.format(height),\n",
+    "                    xy=(rect.get_x() + rect.get_width() / 2, height),\n",
+    "                    xytext=(0, 3),  # 3 points vertical offset\n",
+    "                    textcoords=\"offset points\",\n",
+    "                    ha='center', va='bottom')\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Plot mean + std \n",
+    "# Juwels\n",
+    "dict_stat_juwels = iter_stat(base, wildcard_juwels, gpu_id_str=\"gpu\")\n",
+    "#print(dict_stat_juwels)\n",
+    "iter_mean_juwels = np.array([dict_stat_juwels[\"{0:d} GPU(s)\".format(key)][\"mean\"] for key in labels])\n",
+    "iter_std_juwels = np.array([dict_stat_juwels[\"{0:d} GPU(s)\".format(key)][\"std\"] for key in labels])\n",
+    "\n",
+    "dict_stat_booster = iter_stat(base, wildcard_booster, gpu_id_str=\"gpu\")\n",
+    "iter_mean_booster = np.array([dict_stat_booster[\"{0:d} GPU(s)\".format(key)][\"mean\"] for key in labels])\n",
+    "iter_std_booster = np.array([dict_stat_booster[\"{0:d} GPU(s)\".format(key)][\"std\"] for key in labels])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 29,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(21225,)\n"
+     ]
+    }
+   ],
+   "source": [
+    "iter_time_juwels = all_iter(base, wildcard_juwels)\n",
+    "iter_time_booster= all_iter(base, wildcard_booster)\n",
+    "\n",
+    "max_iter_juwels = np.shape(iter_time_booster[\"{0:d} GPU(s)\".format(labels[0])])[0]\n",
+    "max_iter_booster = np.shape(iter_time_booster[\"{0:d} GPU(s)\".format(labels[0])])[0]\n",
+    "\n",
+    "arr_iter_juwels = np.full((nexps, max_iter_juwels), np.nan)\n",
+    "arr_iter_booster= np.full((nexps, max_iter_booster), np.nan)\n",
+    "\n",
+    "\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 37,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# box plot instead of errorbar plot\n",
+    "# Juwels\n",
+    "#data_juwels = list_time_per_iteration_all_runs(base, wildcard_juwels)\n",
+    "data_juwels = all_iter(base, wildcard_juwels, gpu_id_str=\"gpu\")\n",
+    "# Booster\n",
+    "#data_booster = list_time_per_iteration_all_runs(base, wildcard_booster)\n",
+    "data_booster = all_iter(base, wildcard_booster, gpu_id_str=\"gpu\")\n",
+    "def simple_boxplot(time_per_iteration_data, title):\n",
+    "    # Multiple box plots on one Axes\n",
+    "    fig, ax = plt.subplots()\n",
+    "    ax.set_title(title)\n",
+    "    ax.boxplot(time_per_iteration_data, showfliers=False) # Outliers for initialization are disturbing \n",
+    "    plt.xticks([1, 2, 3, 4, 5 ,6], ['1', '4', '8', '16', '32', '64'])\n",
+    "    #plt.savefig('boxplot_'+title)\n",
+    "    #plt.close()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 86,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "886\n",
+      "64.08639097213745\n",
+      "31.232596397399902\n",
+      "(1326,)\n",
+      "***********\n",
+      "2100\n",
+      "4.405388832092285\n",
+      "29.095214366912842\n",
+      "(2653,)\n",
+      "***********\n",
+      "36981\n",
+      "7.751298189163208\n",
+      "26.409477949142456\n",
+      "(42450,)\n",
+      "***********\n",
+      "3843\n",
+      "66.00082683563232\n",
+      "29.385547637939453\n",
+      "(21225,)\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(np.argmax(data_booster[\"64 GPU(s)\"]))\n",
+    "print(np.max(data_booster[\"64 GPU(s)\"]))\n",
+    "print(data_booster[\"64 GPU(s)\"][0])\n",
+    "print(np.shape(data_booster[\"64 GPU(s)\"]))\n",
+    "print(\"***********\")\n",
+    "\n",
+    "print(np.argmax(data_juwels[\"64 GPU(s)\"][1::]))\n",
+    "print(np.max(data_juwels[\"64 GPU(s)\"][1::]))\n",
+    "print(data_juwels[\"64 GPU(s)\"][0])\n",
+    "print(np.shape(data_juwels[\"64 GPU(s)\"]))\n",
+    "print(\"***********\")\n",
+    "\n",
+    "print(np.argmax(data_juwels[\"4 GPU(s)\"][1::]))\n",
+    "print(np.max(data_juwels[\"4 GPU(s)\"][1::]))\n",
+    "print(data_juwels[\"4 GPU(s)\"][0])\n",
+    "print(np.shape(data_juwels[\"4 GPU(s)\"]))\n",
+    " \n",
+    "print(\"***********\")\n",
+    "print(np.argmax(data_booster[\"4 GPU(s)\"][1::]))\n",
+    "print(np.max(data_booster[\"4 GPU(s)\"][1::]))\n",
+    "print(data_booster[\"4 GPU(s)\"][0])\n",
+    "print(np.shape(data_booster[\"4 GPU(s)\"]))\n",
+    "\n",
+    "#simple_boxplot(data_juwels, 'Juwels')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "simple_boxplot(data_booster, 'Booster')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 81,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# Try more fancy box plot \n",
+    "def more_fancy_boxplot(time_per_iteration_data1, time_per_iteration_data2, ngpu_list, title):\n",
+    "    nexps = len(ngpu_list)\n",
+    "    # Shuffle data: EXPECT JUWELS FIRST FOR THE LEGEND! NOT GENERIC!\n",
+    "    data = []\n",
+    "    for i in np.arange(nexps):\n",
+    "        data.append(time_per_iteration_data1[\"{0} GPU(s)\".format(ngpu_list[i])])\n",
+    "        data.append(time_per_iteration_data2[\"{0} GPU(s)\".format(ngpu_list[i])])\n",
+    "     \n",
+    "    # trick to get list with duplicated entries\n",
+    "    xlabels = [val for val in ngpu_list for _ in (0, 1)]\n",
+    "\n",
+    "    # Multiple box plots on one Axes\n",
+    "    #fig, ax = plt.subplots()\n",
+    "    fig = plt.figure(figsize=(6,4))\n",
+    "    ax = plt.axes([0.1, 0.15, 0.75, 0.75])   \n",
+    "    \n",
+    "    ax.set_title(title)\n",
+    "    bp = ax.boxplot(data, notch=0, sym='+', vert=1, whis=1.5, showfliers=False) # Outliers for initialization are disturbing\n",
+    "    plt.xticks(np.arange(1, nexps*2 +1), xlabels)\n",
+    "    ax.set_xlabel('# GPUs')\n",
+    "    ax.set_ylabel('Seconds')\n",
+    "    \n",
+    "    # Reference: https://matplotlib.org/3.1.1/gallery/statistics/boxplot_demo.html \n",
+    "    box_colors = ['darkkhaki', 'royalblue']\n",
+    "    num_boxes = len(data)\n",
+    "    medians = np.empty(num_boxes)\n",
+    "    for i in range(num_boxes):\n",
+    "        box = bp['boxes'][i]\n",
+    "        boxX = []\n",
+    "        boxY = []\n",
+    "        for j in range(5):\n",
+    "            boxX.append(box.get_xdata()[j])\n",
+    "            boxY.append(box.get_ydata()[j])\n",
+    "        box_coords = np.column_stack([boxX, boxY])\n",
+    "        # Alternate between Dark Khaki and Royal Blue\n",
+    "        ax.add_patch(Polygon(box_coords, facecolor=box_colors[i % 2]))\n",
+    "        # Now draw the median lines back over what we just filled in\n",
+    "        med = bp['medians'][i]\n",
+    "        medianX = []\n",
+    "        medianY = []\n",
+    "        for j in range(2):\n",
+    "            medianX.append(med.get_xdata()[j])\n",
+    "            medianY.append(med.get_ydata()[j])\n",
+    "            ax.plot(medianX, medianY, 'k')\n",
+    "        medians[i] = medianY[0]\n",
+    "        # Finally, overplot the sample averages, with horizontal alignment\n",
+    "        # in the center of each box\n",
+    "        ax.plot(np.average(med.get_xdata()), np.average(data[i]),\n",
+    "                color='w', marker='*', markeredgecolor='k')\n",
+    "    \n",
+    "    # Finally, add a basic legend\n",
+    "    fig.text(0.9, 0.15, 'Juwels',\n",
+    "             backgroundcolor=box_colors[0], color='black', weight='roman',\n",
+    "             size='small')\n",
+    "    fig.text(0.9, 0.09, 'Booster',\n",
+    "             backgroundcolor=box_colors[1],\n",
+    "             color='white', weight='roman', size='small')\n",
+    "    #fig.text(0.90, 0.015, '*', color='white', backgroundcolor='silver',\n",
+    "    #         weight='roman', size='medium')\n",
+    "    fig.text(0.9, 0.03, '* Mean', color='white', backgroundcolor='silver',\n",
+    "             weight='roman', size='small')\n",
+    "\n",
+    "    \n",
+    "    plt.savefig('fancy_boxplot_'+title.replace(' ', '_'))\n",
+    "    plt.close()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 82,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "more_fancy_boxplot(data_juwels, data_booster, ngpus_sort, 'Time needed to iterate one step')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "flist_hpc1 = sorted(glob.glob(base + wildcard_juwels))\n",
+    "flist_hpc2 = sorted(glob.glob(base + wildcard_booster))\n",
+    "\n",
+    "\n",
+    "        \n",
+    "\n",
+    "print(get_ngpus(flist_hpc1[2], \"gpu\"))\n",
+    "print(get_ngpus(flist_hpc1[0], \"gpu\"))\n",
+    "\n",
+    "print(get_ngpus(flist_hpc2[2], \"gpu\"))\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "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.8.5"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/Jupyter_Notebooks/performance_check.ipynb b/Jupyter_Notebooks/performance_check.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..3caf9018e91049c7ef7ee826382871dc5168a27a
--- /dev/null
+++ b/Jupyter_Notebooks/performance_check.ipynb
@@ -0,0 +1,724 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 108,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "## import all required modules\n",
+    "import os, glob\n",
+    "import numpy as np\n",
+    "import pickle\n",
+    "# for plotting\n",
+    "import matplotlib\n",
+    "matplotlib.use('Agg')\n",
+    "from matplotlib.transforms import Affine2D\n",
+    "from matplotlib.patches import Polygon\n",
+    "import matplotlib.pyplot as plt\n",
+    "%matplotlib inline"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 144,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "## some auxiliary functions\n",
+    "#\n",
+    "#colors = ['darkkhaki', 'royalblue']\n",
+    "colors = [\"midnightblue\", \"darkorange\"]\n",
+    "\n",
+    "def val_order(number):\n",
+    "    return int(np.floor(np.log10(number)))\n",
+    "#\n",
+    "# ****************************************************************************************************\n",
+    "#\n",
+    "def get_ngpus(fname, search_str, max_order=3):\n",
+    "    \"\"\"\n",
+    "    Tries to get numbers in the vicinty of search_str which is supposed to be a substring in fname.\n",
+    "    First seaches for numbers right before the occurence of search_str, then afterwards.\n",
+    "    :param fname: file name from which number should be inferred\n",
+    "    :param search_str: seach string for which number identification is considered to be possible\n",
+    "    :param max_order: maximum order of retrieved number (default: 3 -> maximum number is 999 then)\n",
+    "    :return num_int: integer of number in the vicintity of search string. \n",
+    "    \"\"\"\n",
+    "    \n",
+    "    ind_gpu_info = fname.lower().find(search_str)\n",
+    "    if ind_gpu_info == -1:\n",
+    "        raise ValueError(\"Unable to find search string '{0}' in file name '{1}'\".format(search_str, fname))\n",
+    "    \n",
+    "    # init loops\n",
+    "    fname_len = len(fname)\n",
+    "    success, flag = False, True\n",
+    "    indm = 1\n",
+    "    ind_sm, ind_sp = 0, 0\n",
+    "    # check occurence of numbers in front of search string\n",
+    "    while indm < max_order and flag:\n",
+    "        if ind_gpu_info - indm > 0:\n",
+    "            if fname[ind_gpu_info - indm].isnumeric():\n",
+    "                ind_sm += 1\n",
+    "                success = True\n",
+    "            else:\n",
+    "                flag = False\n",
+    "        else:\n",
+    "            flag = False\n",
+    "        indm += 1\n",
+    "    # end while-loop\n",
+    "    if not success: # check occurence of numbers after search string\n",
+    "        ind_gpu_info = ind_gpu_info + len(search_str)\n",
+    "        flag = True\n",
+    "        indm = 0\n",
+    "        while indm < max_order and flag: \n",
+    "            if ind_gpu_info + indm < fname_len:\n",
+    "                if fname[ind_gpu_info + indm].isnumeric():\n",
+    "                    ind_sp += 1\n",
+    "                    success = True\n",
+    "                else:\n",
+    "                    flag = False\n",
+    "            else:\n",
+    "                flag = False\n",
+    "            indm += 1\n",
+    "        # end while-loop    \n",
+    "        if success:\n",
+    "            return(int(fname[ind_gpu_info:ind_gpu_info+ind_sp]))\n",
+    "        else:\n",
+    "            raise ValueError(\"Search string found in fname, but unable to infer number of GPUs.\")\n",
+    "\n",
+    "    else:\n",
+    "        return(int(fname[ind_gpu_info-ind_sm:ind_gpu_info]))\n",
+    "#\n",
+    "# ****************************************************************************************************\n",
+    "#\n",
+    "# functions for computing time\n",
+    "def compute_time_tot(infile):\n",
+    "    with open(infile,'rb') as tfile:\n",
+    "        #print(\"Opening pickle time: '{0}'\".format(infile))\n",
+    "        total_time_sec = pickle.load(tfile)\n",
+    "    return np.asarray(total_time_sec/60)\n",
+    "#\n",
+    "# ****************************************************************************************************\n",
+    "#\n",
+    "def compute_time_tot_log(infile):\n",
+    "    total_time_min = compute_time_tot(infile)\n",
+    "    return np.log(total_time_min)\n",
+    "#\n",
+    "# ****************************************************************************************************\n",
+    "#\n",
+    "def get_time_dict(base, wildcardspec, tfilename, gpu_id_str=\"gpu\", llog = False):\n",
+    "    time_dict = {}\n",
+    "    flist_hpc = sorted(glob.glob(base + wildcardspec))\n",
+    "    print(flist_hpc)\n",
+    "    wrapper = compute_time_tot\n",
+    "    if llog: wrapper = compute_time_tot_log\n",
+    "    for tfile in flist_hpc: \n",
+    "        ngpus = get_ngpus(tfile, gpu_id_str)\n",
+    "        time_dict[\"{0:d} GPU(s)\".format(ngpus)] = wrapper(tfile + tfilename)\n",
+    "    return time_dict\n",
+    "#\n",
+    "def calc_speedup(comp_time, ngpus, l_ideal= False):\n",
+    "    nn = np.shape(ngpus)[0]\n",
+    "    if l_ideal:\n",
+    "        spd_data = np.array(ngpus, dtype=float)\n",
+    "    else:\n",
+    "        spd_data = comp_time\n",
+    "\n",
+    "    spd_up = spd_data[0:nn-1]/spd_data[1::]\n",
+    "    \n",
+    "    if l_ideal: spd_up = 1./spd_up\n",
+    "\n",
+    "    return spd_up\n",
+    "#\n",
+    "# ****************************************************************************************************\n",
+    "#\n",
+    "# functions for iteration time data    \n",
+    "def iter_time_mean_std(infile):\n",
+    "    with open(infile, 'rb') as tfile:\n",
+    "        time_per_iteration_list = pickle.load(tfile) \n",
+    "        \n",
+    "    time_per_iteration = np.array(time_per_iteration_list)\n",
+    "    return np.mean(time_per_iteration), np.std(time_per_iteration)\n",
+    "#\n",
+    "# ****************************************************************************************************\n",
+    "#\n",
+    "def iter_stat(base, wildcardspec, gpu_id_str=\"gpu\"):\n",
+    "    stat_iter_dict = {}\n",
+    "    flist_hpc = sorted(glob.glob(base + wildcardspec))\n",
+    "    for tdir in flist_hpc: \n",
+    "        ngpus = get_ngpus(tdir, gpu_id_str)\n",
+    "        ftname = os.path.join(tdir, fname_timing_iter)\n",
+    "        mean_loc, std_loc = iter_time_mean_std(ftname)\n",
+    "        stat_iter_dict[\"{0:d} GPU(s)\".format(ngpus)] = {\"mean\": mean_loc , \"std\": std_loc}\n",
+    "    return stat_iter_dict\n",
+    "#\n",
+    "# ****************************************************************************************************\n",
+    "#\n",
+    "def read_iter_time(infile):\n",
+    "    with open(infile,'rb') as tfile:\n",
+    "        time_per_iteration_list = pickle.load(tfile)\n",
+    "    return np.asarray(time_per_iteration_list)\n",
+    "#\n",
+    "# ****************************************************************************************************\n",
+    "#\n",
+    "def get_iter_time_all(base, wildcardspec, gpu_id_str=\"gpu\"):\n",
+    "    iter_dict = {}\n",
+    "    flist_hpc = sorted(glob.glob(base + wildcardspec))\n",
+    "    for tdir in flist_hpc: \n",
+    "        ngpus = get_ngpus(tdir, gpu_id_str)\n",
+    "        ftname = os.path.join(tdir, fname_timing_iter)\n",
+    "        iter_dict[\"{0:d} GPU(s)\".format(ngpus)] = read_iter_time(ftname)\n",
+    "    return iter_dict   \n",
+    "#\n",
+    "# ****************************************************************************************************\n",
+    "#\n",
+    "# functions for plotting\n",
+    "def autolabel(ax, rects, rot=45):\n",
+    "    \"\"\"Attach a text label above each bar in *rects*, displaying its height.\"\"\"\n",
+    "    scal = 1\n",
+    "    if rot <0.:\n",
+    "        scal = -1\n",
+    "    for rect in rects:\n",
+    "        height = rect.get_height()\n",
+    "        ax.annotate('{}'.format(height),\n",
+    "                    xy=(rect.get_x() + rect.get_width()*scal, height),\n",
+    "                    xytext=(0, 3),  # 3 points vertical offset\n",
+    "                    textcoords=\"offset points\",\n",
+    "                    ha='center', va='bottom', rotation=rot)\n",
+    "#\n",
+    "# ****************************************************************************************************\n",
+    "#\n",
+    "def plot_computation_time(times1, times2, ngpus, names, plt_fname, log_yvals = False):\n",
+    "    \n",
+    "    nlabels = len(ngpus)\n",
+    "    x_pos = np.arange(nlabels)\n",
+    "    \n",
+    "    bar_width = 0.35\n",
+    "    ytitle = \"Time [min]\"\n",
+    "    max_time = np.maximum(np.max(times1), np.max(times2))\n",
+    "    time_order = val_order(max_time)\n",
+    "    ymax = np.ceil(max_time/(10**time_order) + 0.5)*(10**time_order) + 10**time_order\n",
+    "   # np.ceil(np.maximum(np.max(times1)/100. + 0.5, np.max(times2)/100. + 0.5))*100.\n",
+    "    if log_yvals: \n",
+    "        times1, times2 = np.log(times1), np.log(times2)\n",
+    "        ytitle = \"LOG(Time) [min]\"\n",
+    "        ymax = np.ceil(np.maximum(np.max(times1)+0.5, np.max(times2) + 0.5))\n",
+    "    \n",
+    "    # create plot object\n",
+    "    fig, ax = plt.subplots()\n",
+    "    # create data bars\n",
+    "    rects1 = ax.bar(x_pos - bar_width/2, np.round(times1, 2), bar_width, label=names[0], color=colors[0])\n",
+    "    rects2 = ax.bar(x_pos + bar_width/2, np.round(times2, 2), bar_width, label=names[1], color=colors[1])\n",
+    "    # customize plot appearance\n",
+    "    # Add some text for labels, title and custom x-axis tick labels, etc.\n",
+    "    ax.set_ylabel(ytitle)\n",
+    "    ax.set_title('Comparison {0} and {1} with convLSTM model'.format(*names))\n",
+    "    ax.set_xticks(x_pos)\n",
+    "    ax.set_xticklabels(ngpus)\n",
+    "    ax.set_xlabel('# GPUs')\n",
+    "    ax.set_ylim(0., ymax)\n",
+    "    ax.legend()\n",
+    "                \n",
+    "    # add labels\n",
+    "    autolabel(ax, rects1)\n",
+    "    autolabel(ax, rects2)\n",
+    "    print(\"Saving plot in file: {0}.png ...\".format(plt_fname))\n",
+    "    plt.savefig(plt_fname+\".png\")\n",
+    "    plt.close()\n",
+    "#\n",
+    "# ****************************************************************************************************\n",
+    "#\n",
+    "def plot_speedup(comp_time_hpc1, comp_time_hpc2, ngpus, names):\n",
+    "    fig = plt.figure(figsize=(6,4))\n",
+    "    ax = plt.axes([0.1, 0.15, 0.75, 0.75])   \n",
+    "    \n",
+    "    spd_up1 = calc_speedup(comp_time_hpc1, ngpus)\n",
+    "    spd_up2 = calc_speedup(comp_time_hpc2, ngpus)\n",
+    "    spd_ideal= calc_speedup(comp_time_hpc2, ngpus, l_ideal=True)\n",
+    "    \n",
+    "    plt.plot(spd_up1/spd_ideal, label= names[0], c=colors[0], lw=1.5)\n",
+    "    plt.plot(spd_up2/spd_ideal, label= names[1], c=colors[1], lw=1.5)\n",
+    "    plt.plot(spd_ideal/spd_ideal, label= \"Ideal\", c=\"r\", lw=3.)\n",
+    "    \n",
+    "    xlabels = []\n",
+    "    for i in np.arange(len(ngpus)-1):\n",
+    "        xlabels.append(\"{0} -> {1}\".format(ngpus[i], ngpus[i+1]))\n",
+    "    plt.xticks(np.arange(0, len(ngpus)-1), xlabels)\n",
+    "    ax.set_xlim(-0.5, len(ngpus)-1.5)\n",
+    "    ax.set_ylim(0.5, 1.5)\n",
+    "    legend = ax.legend(loc='upper left')\n",
+    "    ax.set_xlabel('GPU usage')\n",
+    "    ax.set_ylabel('Ratio Speedup factor') \n",
+    "    \n",
+    "    plt_fname = \"speed_up_{0}_vs_{1}.png\".format(*names)\n",
+    "    print(\"Saving plot in file: {0}.png ...\".format(plt_fname))\n",
+    "    plt.savefig(\"speed_up_{0}_vs_{1}.png\".format(*names))\n",
+    "#\n",
+    "# ****************************************************************************************************\n",
+    "#\n",
+    "def boxplot_iter_time(time_per_iteration_data1, time_per_iteration_data2, ngpu_list, names):\n",
+    "    nexps = len(ngpu_list)\n",
+    "    # create data lists for boxplot-routine\n",
+    "    data = []\n",
+    "    for i in np.arange(nexps):\n",
+    "        data.append(time_per_iteration_data1[\"{0} GPU(s)\".format(ngpu_list[i])])\n",
+    "        data.append(time_per_iteration_data2[\"{0} GPU(s)\".format(ngpu_list[i])])\n",
+    "     \n",
+    "    # trick to get list with duplicated entries\n",
+    "    xlabels = [val for val in ngpu_list for _ in (0, 1)]\n",
+    "\n",
+    "    # Multiple box plots on one Axes\n",
+    "    #fig, ax = plt.subplots()\n",
+    "    fig = plt.figure(figsize=(6,4))\n",
+    "    ax = plt.axes([0.1, 0.15, 0.75, 0.75])   \n",
+    "    \n",
+    "    ax.set_title(\"Time per iteration step\")\n",
+    "    bp = ax.boxplot(data, notch=0, sym='+', vert=1, whis=1.5, showfliers=False) # Outliers for initialization are disturbing\n",
+    "    plt.xticks(np.arange(1, nexps*2 +1), xlabels)\n",
+    "    ax.set_xlabel('# GPUs')\n",
+    "    ax.set_ylabel('Time [s]')\n",
+    "    \n",
+    "    # Reference: https://matplotlib.org/3.1.1/gallery/statistics/boxplot_demo.html \n",
+    "    box_colors = colors\n",
+    "    num_boxes = len(data)\n",
+    "    medians = np.empty(num_boxes)\n",
+    "    for i in range(num_boxes):\n",
+    "        box = bp['boxes'][i]\n",
+    "        boxX = []\n",
+    "        boxY = []\n",
+    "        for j in range(5):\n",
+    "            boxX.append(box.get_xdata()[j])\n",
+    "            boxY.append(box.get_ydata()[j])\n",
+    "        box_coords = np.column_stack([boxX, boxY])\n",
+    "        # Alternate between Dark Khaki and Royal Blue\n",
+    "        ax.add_patch(Polygon(box_coords, facecolor=box_colors[i % 2]))\n",
+    "        # Now draw the median lines back over what we just filled in\n",
+    "        med = bp['medians'][i]\n",
+    "        medianX = []\n",
+    "        medianY = []\n",
+    "        for j in range(2):\n",
+    "            medianX.append(med.get_xdata()[j])\n",
+    "            medianY.append(med.get_ydata()[j])\n",
+    "            ax.plot(medianX, medianY, 'k')\n",
+    "        medians[i] = medianY[0]\n",
+    "        # Finally, overplot the sample averages, with horizontal alignment\n",
+    "        # in the center of each box\n",
+    "        ax.plot(np.average(med.get_xdata()), np.average(data[i]),\n",
+    "                color='w', marker='*', markeredgecolor='k', markersize=10)\n",
+    "    \n",
+    "    # Finally, add a basic legend\n",
+    "    fig.text(0.86, 0.15, names[0],\n",
+    "             backgroundcolor=box_colors[0], color='white', weight='roman',\n",
+    "             size='small')\n",
+    "    fig.text(0.86, 0.09, names[1],\n",
+    "             backgroundcolor=box_colors[1],\n",
+    "             color='white', weight='roman', size='small')\n",
+    "    #fig.text(0.90, 0.015, '*', color='white', backgroundcolor='silver',\n",
+    "    #         weight='roman', size='medium')\n",
+    "    #fig_transform =  ax.figure.transFigure #+ ax.transAxes.inverted() #+ ax.figure.transFigure.inverted()\n",
+    "    #ax.plot(0.1, 0.03, marker='*', markersize=30, color=\"w\", markeredgecolor=\"k\", transform=fig_transform)\n",
+    "    fig.text(0.86, 0.03, '* Mean', color='black', backgroundcolor='white', \n",
+    "             weight='roman', size='small', bbox=dict(facecolor='none', edgecolor='k'))\n",
+    "\n",
+    "    plt_fname = \"boxplot_iter_time_{0}_vs_{1}\".format(*names)\n",
+    "    print(\"Saving plot in file: {0}.png ...\".format(plt_fname))\n",
+    "    plt.savefig(plt_fname+\".png\")\n",
+    "    plt.close()\n",
+    "    \n",
+    "    "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 110,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "## some basic settings\n",
+    "base_dir = \"/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/\"\n",
+    "\n",
+    "wildcard_hpc1 = '20210325T095504_langguth1_juwels_container_[1-9]*gpu*'  # search pattern for finding the experiments\n",
+    "wildcard_hpc2 = '20210325T095504_langguth1_jwb_container_[1-9]*gpu*'\n",
+    "\n",
+    "gpu_id_str = [\"gpu\", \"gpu\"]               # search substring to get the number of GPUs used in the experiments,\n",
+    "                                          # e.g. \"gpu\" if '64gpu' is a substring in the experiment directory\n",
+    "                                          # or \"ngpu\" if 'ngpu64' is a substring in the experiment directory\n",
+    "                                          # -> see wilcard-variables above\n",
+    "names_hpc = [\"Juwels\", \"Booster\"]\n",
+    "\n",
+    "# name of pickle files tracking computing time\n",
+    "fname_timing_train = \"/timing_training_time.pkl\"\n",
+    "fname_timing_total = \"/timing_total_time.pkl\"\n",
+    "\n",
+    "fname_timing_iter = \"timing_per_iteration_time.pkl\"\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 111,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "['/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_juwels_container_16gpus', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_juwels_container_1gpu', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_juwels_container_32gpus', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_juwels_container_4gpus', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_juwels_container_64gpus', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_juwels_container_8gpus']\n",
+      "['/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_jwb_container_16gpus', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_jwb_container_1gpu', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_jwb_container_32gpus', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_jwb_container_4gpus', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_jwb_container_64gpus', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_jwb_container_8gpus']\n",
+      "{'16 GPU(s)': array(53.40843068), '1 GPU(s)': array(930.4968381), '32 GPU(s)': array(45.96871045), '4 GPU(s)': array(217.45655225), '64 GPU(s)': array(35.7369519), '8 GPU(s)': array(106.4218419)}\n",
+      "{'16 GPU(s)': array(34.26928383), '1 GPU(s)': array(492.70926997), '32 GPU(s)': array(35.05492661), '4 GPU(s)': array(100.99109779), '64 GPU(s)': array(30.98471271), '8 GPU(s)': array(49.63896298)}\n",
+      "['/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_juwels_container_16gpus', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_juwels_container_1gpu', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_juwels_container_32gpus', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_juwels_container_4gpus', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_juwels_container_64gpus', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_juwels_container_8gpus']\n",
+      "['/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_jwb_container_16gpus', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_jwb_container_1gpu', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_jwb_container_32gpus', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_jwb_container_4gpus', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_jwb_container_64gpus', '/p/project/deepacf/deeprain/video_prediction_shared_folder/models/era5-Y2007-2019M01to12-92x56-3840N0000E-2t_tcc_t_850/convLSTM_container/20210325T095504_langguth1_jwb_container_8gpus']\n"
+     ]
+    }
+   ],
+   "source": [
+    "## evaluate computing time\n",
+    "# dictionaries with the total times\n",
+    "tot_time_hpc1_dict = get_time_dict(base_dir, wildcard_hpc1, fname_timing_total, gpu_id_str=gpu_id_str[0])\n",
+    "tot_time_hpc2_dict= get_time_dict(base_dir, wildcard_hpc2, fname_timing_total, gpu_id_str=gpu_id_str[1])\n",
+    "\n",
+    "print(tot_time_hpc1_dict)\n",
+    "print(tot_time_hpc2_dict)\n",
+    "\n",
+    "# dictionaries with the training times\n",
+    "train_time_hpc1_dict = get_time_dict(base_dir, wildcard_hpc1, fname_timing_train, gpu_id_str=gpu_id_str[0])\n",
+    "train_time_hpc2_dict = get_time_dict(base_dir, wildcard_hpc2, fname_timing_train, gpu_id_str=gpu_id_str[1])\n",
+    "\n",
+    "# get sorted arrays\n",
+    "# Note: The times for Juwels are divided by 2, since the experiments have been performed with an epoch number of 20\n",
+    "#       instead of 10 (as Bing and Scarlet did)\n",
+    "ngpus_sort = sorted([int(ngpu.split()[0]) for ngpu in tot_time_hpc1_dict.keys()])\n",
+    "nexps = len(ngpus_sort)\n",
+    "tot_time_hpc1 = np.array([tot_time_hpc1_dict[\"{0:d} GPU(s)\".format(key)] for key in ngpus_sort])\n",
+    "tot_time_hpc1[0] = tot_time_hpc1[0]#*2.\n",
+    "tot_time_hpc2 = np.array([tot_time_hpc2_dict[\"{0:d} GPU(s)\".format(key)] for key in ngpus_sort])\n",
+    "\n",
+    "train_time_hpc1 = np.array([train_time_hpc1_dict[\"{0:d} GPU(s)\".format(key)] for key in ngpus_sort])\n",
+    "train_time_hpc1[0] = train_time_hpc1[0]#*2.\n",
+    "train_time_hpc2 = np.array([train_time_hpc2_dict[\"{0:d} GPU(s)\".format(key)] for key in ngpus_sort])\n",
+    "\n",
+    "overhead_hpc1 = tot_time_hpc1 - train_time_hpc1\n",
+    "overhead_hpc2= tot_time_hpc2 - train_time_hpc2"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 112,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[492.70926997 100.99109779  49.63896298  34.26928383  35.05492661\n",
+      "  30.98471271]\n",
+      "Saving plot in file: ./total_computation_time_Juwels_vs_Booster.png ...\n",
+      "Saving plot in file: ./overhead_time_Juwels_vs_Booster.png ...\n",
+      "Saving plot in file: speed_up_Juwels_vs_Booster.png.png ...\n"
+     ]
+    },
+    {
+     "data": {
+      "image/png": "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\n",
+      "text/plain": [
+       "<Figure size 432x288 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "# plot the computing time\n",
+    "print(tot_time_hpc2)\n",
+    "plot_computation_time(tot_time_hpc1, tot_time_hpc2, ngpus_sort, names_hpc, \\\n",
+    "                       \"./total_computation_time_{0}_vs_{1}\".format(*names_hpc), log_yvals=False)\n",
+    "\n",
+    "plot_computation_time(overhead_hpc1, overhead_hpc2, ngpus_sort, names_hpc, \\\n",
+    "                       \"./overhead_time_{0}_vs_{1}\".format(*names_hpc))\n",
+    "# plot speed-up factors\n",
+    "plot_speedup(tot_time_hpc1, tot_time_hpc2, ngpus_sort, names_hpc)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 113,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "## evaluate iteration time\n",
+    "# get iteration times\n",
+    "iter_data_hpc1 = get_iter_time_all(base_dir, wildcard_hpc1, gpu_id_str=gpu_id_str[0])\n",
+    "iter_data_hpc2 = get_iter_time_all(base_dir, wildcard_hpc2, gpu_id_str=gpu_id_str[1])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 114,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Saving plot in file: boxplot_iter_time_Juwels_vs_Booster.png ...\n"
+     ]
+    }
+   ],
+   "source": [
+    "# plot the iteration time in box plots\n",
+    "boxplot_iter_time(iter_data_hpc1, iter_data_hpc2, ngpus_sort, names_hpc)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 115,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def get_slowiter(iter_time, threshold):\n",
+    "    inds_slow = np.where(iter_time > threshold)[0]\n",
+    "    return iter_time[inds_slow], np.shape(inds_slow)[0]\n",
+    "\n",
+    "def ana_slowiter(itertime1, itertime2, thres, names):\n",
+    "    slowt1, nslow1 = get_slowiter(itertime1, thres)\n",
+    "    slowt2, nslow2 = get_slowiter(itertime2, thres)\n",
+    "    \n",
+    "    if nslow1 > 0:\n",
+    "        print(\"{0:d} slow iteration steps on {1} with averaged time of {2:5.2f}s (max: {3:5.2f}s)\"\\\n",
+    "              .format(nslow1, names[0], np.mean(slowt1), np.max(slowt1)))\n",
+    "    else: \n",
+    "        print(\"No slow iterations on {0}\".format(names[0]))\n",
+    "        \n",
+    "    if nslow2 > 0:\n",
+    "        print(\"{0:d} slow iteration steps on {1} with averaged time of {2:5.2f}s (max: {3:5.2f}s)\"\\\n",
+    "              .format(nslow2, names[1], np.mean(slowt2), np.max(slowt2)))\n",
+    "    else: \n",
+    "        print(\"No slow iterations on {0}\".format(names[1]))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 116,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "***** Analyse single GPUs experiments *****\n",
+      "1 slow iteration steps on Juwels with averaged time of  5.18s (max:  5.18s)\n",
+      "No slow iterations on Booster\n",
+      "***** Analyse 4 GPUs experiments *****\n",
+      "No slow iterations on Juwels\n",
+      "No slow iterations on Booster\n",
+      "***** Analyse 8 GPUs experiments *****\n",
+      "No slow iterations on Juwels\n",
+      "No slow iterations on Booster\n",
+      "***** Analyse 32 GPUs experiments *****\n",
+      "No slow iterations on Juwels\n",
+      "No slow iterations on Booster\n",
+      "***** Analyse 32 GPUs experiments *****\n",
+      "No slow iterations on Juwels\n",
+      "No slow iterations on Booster\n",
+      "***** Analyse 64 GPUs experiments *****\n",
+      "No slow iterations on Juwels\n",
+      "No slow iterations on Booster\n"
+     ]
+    }
+   ],
+   "source": [
+    "    \n",
+    "## settings\n",
+    "names = [\"Juwels\", \"Booster\"]\n",
+    "slowiter_time = 5.       # arbitrary threshold for slow iteration steps\n",
+    "\n",
+    "# analyze single GPU experiments\n",
+    "print(\"***** Analyse single GPUs experiments *****\")\n",
+    "itertime_juwels = iter_data_hpc1[\"1 GPU(s)\"]\n",
+    "itertime_booster = iter_data_hpc2[\"1 GPU(s)\"]\n",
+    "\n",
+    "ana_slowiter(itertime_juwels[1:], itertime_booster[1:], slowiter_time, names)\n",
+    "\n",
+    "# analyze 4 GPUs experiments\n",
+    "print(\"***** Analyse 4 GPUs experiments *****\")\n",
+    "itertime_juwels = iter_data_hpc1[\"4 GPU(s)\"]\n",
+    "itertime_booster = iter_data_hpc2[\"4 GPU(s)\"]\n",
+    "\n",
+    "ana_slowiter(itertime_juwels[1:], itertime_booster[1:], slowiter_time, names)\n",
+    "\n",
+    "# analyze 8 GPUs experiments\n",
+    "print(\"***** Analyse 8 GPUs experiments *****\")\n",
+    "itertime_juwels = iter_data_hpc1[\"8 GPU(s)\"]\n",
+    "itertime_booster = iter_data_hpc2[\"8 GPU(s)\"]\n",
+    "\n",
+    "ana_slowiter(itertime_juwels[1:], itertime_booster[1:], slowiter_time, names)\n",
+    "\n",
+    "# analyze 16 GPUs experiments\n",
+    "print(\"***** Analyse 32 GPUs experiments *****\")\n",
+    "itertime_juwels = iter_data_hpc1[\"16 GPU(s)\"]\n",
+    "itertime_booster = iter_data_hpc2[\"16 GPU(s)\"]\n",
+    "\n",
+    "ana_slowiter(itertime_juwels[1:], itertime_booster[1:], slowiter_time, names)\n",
+    "\n",
+    "# analyze 32 GPUs experiments\n",
+    "print(\"***** Analyse 32 GPUs experiments *****\")\n",
+    "itertime_juwels = iter_data_hpc1[\"32 GPU(s)\"]\n",
+    "itertime_booster = iter_data_hpc2[\"32 GPU(s)\"]\n",
+    "\n",
+    "ana_slowiter(itertime_juwels[1:], itertime_booster[1:], slowiter_time, names)\n",
+    "\n",
+    "# analyze 64 GPUs experiments\n",
+    "print(\"***** Analyse 64 GPUs experiments *****\")\n",
+    "itertime_juwels = iter_data_hpc1[\"64 GPU(s)\"]\n",
+    "itertime_booster = iter_data_hpc2[\"64 GPU(s)\"]\n",
+    "\n",
+    "ana_slowiter(itertime_juwels[1:], itertime_booster[1:], slowiter_time, names)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Summary\n",
+    "- Occasionally, a few iteration steps are slow\n",
+    "- However, performance degradation seems to be much worser on Booster than on Juwels\n",
+    "- Higher chance for slow iteration steps on Booster in general"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 157,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def boxplot_iter_total_time(iteration_time, total_time, ngpu_list, name, log_yvals=False):\n",
+    "    nexps = len(ngpu_list)\n",
+    "    bar_width = 0.35\n",
+    "    # create data lists for boxplot-routine\n",
+    "    iter_time_all = []\n",
+    "    for i in np.arange(nexps):\n",
+    "        iter_time_all.append(iteration_time[\"{0} GPU(s)\".format(ngpu_list[i])])\n",
+    "     \n",
+    "    # trick to get list with duplicated entries\n",
+    "    xlabels = [val for val in ngpu_list for _ in (0, 1)]\n",
+    "    nlabels = len(xlabels)\n",
+    "\n",
+    "    # Multiple box plots on one Axes\n",
+    "    #fig, ax = plt.subplots()\n",
+    "    fig = plt.figure(figsize=(6,4))\n",
+    "    ax = plt.axes([0.1, 0.15, 0.75, 0.75])   \n",
+    "    \n",
+    "    bp = ax.boxplot(iter_time_all, positions=np.arange(0, nlabels, 2), notch=0, sym='+', vert=1, showfliers=False, widths=bar_width) # Outliers for initialization are disturbing\n",
+    "    ax.set_xlabel('# GPUs')\n",
+    "    ax.set_ylabel('Time [s]')\n",
+    "    \n",
+    "    # Reference: https://matplotlib.org/3.1.1/gallery/statistics/boxplot_demo.html \n",
+    "    num_boxes = len(iter_time_all)\n",
+    "    medians = np.empty(num_boxes)\n",
+    "    for i in range(num_boxes):\n",
+    "        box = bp['boxes'][i]\n",
+    "        boxX = []\n",
+    "        boxY = []\n",
+    "        for j in range(5):\n",
+    "            boxX.append(box.get_xdata()[j])\n",
+    "            boxY.append(box.get_ydata()[j])\n",
+    "        box_coords = np.column_stack([boxX, boxY])\n",
+    "        ax.add_patch(Polygon(box_coords, facecolor=colors[1]))\n",
+    "        # Now draw the median lines back over what we just filled in\n",
+    "        med = bp['medians'][i]\n",
+    "        medianX = []\n",
+    "        medianY = []\n",
+    "        for j in range(2):\n",
+    "            medianX.append(med.get_xdata()[j])\n",
+    "            medianY.append(med.get_ydata()[j])\n",
+    "            ax.plot(medianX, medianY, 'k')\n",
+    "        medians[i] = medianY[0]\n",
+    "        # Finally, overplot the sample averages, with horizontal alignment\n",
+    "        # in the center of each box\n",
+    "        ax.plot(np.average(med.get_xdata()), np.average(iter_time_all[i]),\n",
+    "                color='w', marker='*', markeredgecolor='k', markersize=10)\n",
+    "    \n",
+    "    ax2 = ax.twinx()\n",
+    "    x_pos = np.arange(1, nlabels+1 ,2)\n",
+    "    \n",
+    "    ytitle = \"Time [min]\"\n",
+    "    max_time = np.max(total_time)\n",
+    "    time_order = val_order(max_time)\n",
+    "    ymax = np.ceil(max_time/(10**time_order) + 0.5)*(10**time_order) + 10**time_order\n",
+    "    # np.ceil(np.maximum(np.max(times1)/100. + 0.5, np.max(times2)/100. + 0.5))*100.\n",
+    "    if log_yvals: \n",
+    "        total_time = np.log(total_time)\n",
+    "        ytitle = \"LOG(Time) [min]\"\n",
+    "        ymax = np.ceil(np.max(total_time) + 0.5)\n",
+    "    \n",
+    "    # create data bars\n",
+    "    rects = ax2.bar(x_pos, np.round(total_time, 2), bar_width, label=names, color=colors[0])\n",
+    "    # customize plot appearance\n",
+    "    # Add some text for labels, title and custom x-axis tick labels, etc.\n",
+    "    ax2.set_ylabel(ytitle)\n",
+    "    ax2.set_xticks(np.arange(0, nlabels))\n",
+    "    ax2.set_xticklabels(xlabels)\n",
+    "    ax2.set_xlabel('# GPUs')\n",
+    "    ax2.set_ylim(0., ymax)\n",
+    "                \n",
+    "    # add labels\n",
+    "    autolabel(ax2, rects, rot=45)     \n",
+    "\n",
+    "    plt_fname = \"iter+tot_time_{0}_vs_{1}\".format(*names)\n",
+    "    print(\"Saving plot in file: {0}.png ...\".format(plt_fname))\n",
+    "    #plt.show()\n",
+    "    plt.savefig(plt_fname+\".png\")\n",
+    "    plt.close()\n",
+    "    \n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 158,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Saving plot in file: iter+tot_time_Juwels_vs_Booster.png ...\n"
+     ]
+    }
+   ],
+   "source": [
+    "boxplot_iter_total_time(iter_data_hpc2, tot_time_hpc2, ngpus_sort, names_hpc[1])"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "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.8.5"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}