{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pathlib import Path\n",
    "from shutil import copyfile\n",
    "import pickle"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Data manipulation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Plotting / Visualisation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "plt.rcParams[\"figure.figsize\"] = (15, 6)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Gaussian Process Regression"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "import gpflow\n",
    "import tensorflow as tf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "from gpflow.utilities import print_summary"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "gpflow.config.set_default_summary_fmt(\"notebook\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "MATLAB engine"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matlab.engine"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "eng = matlab.engine.start_matlab()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matlab.engine.futureresult.FutureResult at 0x7f678db02790>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "eng.load_system(\"../Simulink/polydome\", background = True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Load weather data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sample time (in seconds) of the resulting Gaussian Process"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "Tsample = 15*60"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Which experimental set to simulate:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "exp_id = 'Exp2'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Copy the corresponding WDB to the model input location:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'../Data/input_WDB.mat'"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "copyfile(f\"../Data/Experimental_data_WDB/{exp_id}_WDB.mat\", \"../Data/input_WDB.mat\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>time</th>\n",
       "      <th>timestamp</th>\n",
       "      <th>zenith</th>\n",
       "      <th>azimuth</th>\n",
       "      <th>dni</th>\n",
       "      <th>dhi</th>\n",
       "      <th>OutsideTemp</th>\n",
       "      <th>Tsky_rad</th>\n",
       "      <th>relative_humidity</th>\n",
       "      <th>precipitation</th>\n",
       "      <th>cloud_index</th>\n",
       "      <th>pressure</th>\n",
       "      <th>wind_speed</th>\n",
       "      <th>wind_direction</th>\n",
       "      <th>aoi</th>\n",
       "      <th>incidence_main</th>\n",
       "      <th>incidence_second</th>\n",
       "      <th>poa_direct</th>\n",
       "      <th>poa_diffuse</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0</td>\n",
       "      <td>201706101600</td>\n",
       "      <td>37.637775</td>\n",
       "      <td>244.184376</td>\n",
       "      <td>778.389320</td>\n",
       "      <td>153.014998</td>\n",
       "      <td>24.0</td>\n",
       "      <td>18.0</td>\n",
       "      <td>50</td>\n",
       "      <td>-9999</td>\n",
       "      <td>0.5</td>\n",
       "      <td>96300</td>\n",
       "      <td>0</td>\n",
       "      <td>-9999</td>\n",
       "      <td>37.637775</td>\n",
       "      <td>-9999</td>\n",
       "      <td>-9999</td>\n",
       "      <td>616.396540</td>\n",
       "      <td>153.014998</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>300</td>\n",
       "      <td>201706101605</td>\n",
       "      <td>38.415872</td>\n",
       "      <td>245.558388</td>\n",
       "      <td>779.663530</td>\n",
       "      <td>151.020217</td>\n",
       "      <td>24.0</td>\n",
       "      <td>18.0</td>\n",
       "      <td>50</td>\n",
       "      <td>-9999</td>\n",
       "      <td>0.5</td>\n",
       "      <td>96300</td>\n",
       "      <td>0</td>\n",
       "      <td>-9999</td>\n",
       "      <td>38.415872</td>\n",
       "      <td>-9999</td>\n",
       "      <td>-9999</td>\n",
       "      <td>610.883028</td>\n",
       "      <td>151.020217</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>600</td>\n",
       "      <td>201706101610</td>\n",
       "      <td>39.202383</td>\n",
       "      <td>246.896456</td>\n",
       "      <td>776.559233</td>\n",
       "      <td>150.272165</td>\n",
       "      <td>24.0</td>\n",
       "      <td>18.0</td>\n",
       "      <td>50</td>\n",
       "      <td>-9999</td>\n",
       "      <td>0.5</td>\n",
       "      <td>96300</td>\n",
       "      <td>0</td>\n",
       "      <td>-9999</td>\n",
       "      <td>39.202383</td>\n",
       "      <td>-9999</td>\n",
       "      <td>-9999</td>\n",
       "      <td>601.769888</td>\n",
       "      <td>150.272165</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>900</td>\n",
       "      <td>201706101615</td>\n",
       "      <td>39.996665</td>\n",
       "      <td>248.200516</td>\n",
       "      <td>767.177588</td>\n",
       "      <td>151.349615</td>\n",
       "      <td>24.0</td>\n",
       "      <td>18.0</td>\n",
       "      <td>50</td>\n",
       "      <td>-9999</td>\n",
       "      <td>0.5</td>\n",
       "      <td>96300</td>\n",
       "      <td>0</td>\n",
       "      <td>-9999</td>\n",
       "      <td>39.996665</td>\n",
       "      <td>-9999</td>\n",
       "      <td>-9999</td>\n",
       "      <td>587.720827</td>\n",
       "      <td>151.349615</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1200</td>\n",
       "      <td>201706101620</td>\n",
       "      <td>40.798119</td>\n",
       "      <td>249.472420</td>\n",
       "      <td>762.559533</td>\n",
       "      <td>150.949974</td>\n",
       "      <td>24.0</td>\n",
       "      <td>18.0</td>\n",
       "      <td>50</td>\n",
       "      <td>-9999</td>\n",
       "      <td>0.5</td>\n",
       "      <td>96300</td>\n",
       "      <td>0</td>\n",
       "      <td>-9999</td>\n",
       "      <td>40.798119</td>\n",
       "      <td>-9999</td>\n",
       "      <td>-9999</td>\n",
       "      <td>577.270157</td>\n",
       "      <td>150.949974</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   time     timestamp     zenith     azimuth         dni         dhi  \\\n",
       "0     0  201706101600  37.637775  244.184376  778.389320  153.014998   \n",
       "1   300  201706101605  38.415872  245.558388  779.663530  151.020217   \n",
       "2   600  201706101610  39.202383  246.896456  776.559233  150.272165   \n",
       "3   900  201706101615  39.996665  248.200516  767.177588  151.349615   \n",
       "4  1200  201706101620  40.798119  249.472420  762.559533  150.949974   \n",
       "\n",
       "   OutsideTemp  Tsky_rad  relative_humidity  precipitation  cloud_index  \\\n",
       "0         24.0      18.0                 50          -9999          0.5   \n",
       "1         24.0      18.0                 50          -9999          0.5   \n",
       "2         24.0      18.0                 50          -9999          0.5   \n",
       "3         24.0      18.0                 50          -9999          0.5   \n",
       "4         24.0      18.0                 50          -9999          0.5   \n",
       "\n",
       "   pressure  wind_speed  wind_direction        aoi  incidence_main  \\\n",
       "0     96300           0           -9999  37.637775           -9999   \n",
       "1     96300           0           -9999  38.415872           -9999   \n",
       "2     96300           0           -9999  39.202383           -9999   \n",
       "3     96300           0           -9999  39.996665           -9999   \n",
       "4     96300           0           -9999  40.798119           -9999   \n",
       "\n",
       "   incidence_second  poa_direct  poa_diffuse  \n",
       "0             -9999  616.396540   153.014998  \n",
       "1             -9999  610.883028   151.020217  \n",
       "2             -9999  601.769888   150.272165  \n",
       "3             -9999  587.720827   151.349615  \n",
       "4             -9999  577.270157   150.949974  "
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_wdb = pd.read_pickle(f\"../Data/Experimental_python/{exp_id}_WDB.pkl\")\n",
    "df_wdb.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Power</th>\n",
       "      <th>Setpoint</th>\n",
       "      <th>OutsideTemp</th>\n",
       "      <th>SupplyTemp</th>\n",
       "      <th>InsideTemp</th>\n",
       "      <th>SolRad</th>\n",
       "      <th>time_h</th>\n",
       "      <th>time_m</th>\n",
       "      <th>time</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>timestamp</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2017-06-10 16:00:00+02:00</th>\n",
       "      <td>5039.718391</td>\n",
       "      <td>20.500000</td>\n",
       "      <td>24.0</td>\n",
       "      <td>13.2</td>\n",
       "      <td>22.727778</td>\n",
       "      <td>761.015733</td>\n",
       "      <td>16</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-06-10 16:15:00+02:00</th>\n",
       "      <td>4563.979693</td>\n",
       "      <td>21.166667</td>\n",
       "      <td>24.0</td>\n",
       "      <td>13.4</td>\n",
       "      <td>22.650000</td>\n",
       "      <td>729.086933</td>\n",
       "      <td>16</td>\n",
       "      <td>15</td>\n",
       "      <td>900</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-06-10 16:30:00+02:00</th>\n",
       "      <td>4560.348659</td>\n",
       "      <td>21.500000</td>\n",
       "      <td>24.0</td>\n",
       "      <td>13.4</td>\n",
       "      <td>22.622222</td>\n",
       "      <td>699.066333</td>\n",
       "      <td>16</td>\n",
       "      <td>30</td>\n",
       "      <td>1800</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-06-10 16:45:00+02:00</th>\n",
       "      <td>4535.043678</td>\n",
       "      <td>21.500000</td>\n",
       "      <td>24.0</td>\n",
       "      <td>13.4</td>\n",
       "      <td>22.622222</td>\n",
       "      <td>664.059456</td>\n",
       "      <td>16</td>\n",
       "      <td>45</td>\n",
       "      <td>2700</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-06-10 17:00:00+02:00</th>\n",
       "      <td>4565.321839</td>\n",
       "      <td>21.500000</td>\n",
       "      <td>24.0</td>\n",
       "      <td>13.4</td>\n",
       "      <td>22.483333</td>\n",
       "      <td>630.548933</td>\n",
       "      <td>17</td>\n",
       "      <td>0</td>\n",
       "      <td>3600</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                 Power   Setpoint  OutsideTemp  SupplyTemp  \\\n",
       "timestamp                                                                    \n",
       "2017-06-10 16:00:00+02:00  5039.718391  20.500000         24.0        13.2   \n",
       "2017-06-10 16:15:00+02:00  4563.979693  21.166667         24.0        13.4   \n",
       "2017-06-10 16:30:00+02:00  4560.348659  21.500000         24.0        13.4   \n",
       "2017-06-10 16:45:00+02:00  4535.043678  21.500000         24.0        13.4   \n",
       "2017-06-10 17:00:00+02:00  4565.321839  21.500000         24.0        13.4   \n",
       "\n",
       "                           InsideTemp      SolRad  time_h  time_m  time  \n",
       "timestamp                                                                \n",
       "2017-06-10 16:00:00+02:00   22.727778  761.015733      16       0     0  \n",
       "2017-06-10 16:15:00+02:00   22.650000  729.086933      16      15   900  \n",
       "2017-06-10 16:30:00+02:00   22.622222  699.066333      16      30  1800  \n",
       "2017-06-10 16:45:00+02:00   22.622222  664.059456      16      45  2700  \n",
       "2017-06-10 17:00:00+02:00   22.483333  630.548933      17       0  3600  "
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = pd.read_pickle(f\"../Data/Experimental_python/{exp_id}_data.pkl\")\n",
    "# Resample the experimental measurements\n",
    "df = df.resample(f\"{Tsample}s\").mean()\n",
    "df['time_h'] = df.index.hour\n",
    "df['time_m'] = df.index.minute\n",
    "\n",
    "df.loc[:,'time'] = [0] + (df.index[1:] - df.index[:-1]).seconds.to_list()\n",
    "df.loc[:, 'time'] = df.loc[:, 'time'].cumsum()\n",
    "\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "def load_weather_data(exp_id):\n",
    "    copyfile(f\"../Data/Experimental_data_WDB/{exp_id}_WDB.mat\", \"../Data/input_WDB.mat\")\n",
    "    df_wdb = pd.read_pickle(f\"../Data/Experimental_python/{exp_id}_WDB.pkl\")\n",
    "    \n",
    "    df = pd.read_pickle(f\"../Data/Experimental_python/{exp_id}_data.pkl\")\n",
    "    # Resample the experimental measurements\n",
    "    df = df.resample(f\"{Tsample}s\").mean()\n",
    "    \n",
    "    df['time_h'] = df.index.hour\n",
    "    df['time_m'] = df.index.minute\n",
    "    \n",
    "    df.loc[:,'time'] = [0] + (df.index[1:] - df.index[:-1]).seconds.to_list()\n",
    "    df.loc[:, 'time'] = df.loc[:, 'time'].cumsum()\n",
    "\n",
    "    return df_wdb, df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Experiment runtime: 136500\n"
     ]
    }
   ],
   "source": [
    "runtime = df_wdb['time'].iloc[-1]\n",
    "print(f\"Experiment runtime: {runtime}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Simulink"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Set the CARNOT simulation initial temperature `t0`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "eng.workspace['t0'] = float(23)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Set the CARNOT simulation air exchange rate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "np_air = np.zeros([df_wdb.shape[0], 2])\n",
    "np_air[:, 0] = df_wdb['time']\n",
    "np_air[:, 1] = 2.75"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "eng.workspace['air_exchange_rate'] = matlab.double(np_air.tolist())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Generate Heat Random Input Signal"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "Pel_max = 6300\n",
    "COP_heating = 5.0\n",
    "COP_cooling = 5.0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": []
   },
   "source": [
    "Define a function for generating random signals:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def get_random_signal(nstep, a_range = (-1, 1), b_range = (2, 10), signal_type = 'analog'):\n",
    "\n",
    "    a = np.random.rand(nstep) * (a_range[1]-a_range[0]) + a_range[0] # range for amplitude\n",
    "    b = np.random.rand(nstep) *(b_range[1]-b_range[0]) + b_range[0] # range for frequency\n",
    "    b = np.round(b)\n",
    "    b = b.astype(int)\n",
    "\n",
    "    b[0] = 0\n",
    "\n",
    "    for i in range(1,np.size(b)):\n",
    "        b[i] = b[i-1]+b[i]\n",
    "        \n",
    "    if signal_type == 'analog':\n",
    "        random_signal = np.zeros(nstep)\n",
    "        # Random Signal\n",
    "        i=0\n",
    "        random_signal = np.zeros(nstep)\n",
    "        while b[i]<np.size(random_signal):\n",
    "            k = b[i]\n",
    "            random_signal[k:] = a[i]\n",
    "            i=i+1\n",
    "        return random_signal\n",
    "    elif signal_type == 'prbs':\n",
    "        \n",
    "        # PRBS\n",
    "        a = np.zeros(nstep)\n",
    "        j = 0\n",
    "        while j < nstep:\n",
    "            a[j] = a_range[1]\n",
    "            a[j+1] = a_range[0]\n",
    "            j = j+2\n",
    "\n",
    "        i=0\n",
    "        prbs = np.zeros(nstep)\n",
    "        while b[i]<np.size(prbs):\n",
    "            k = b[i]\n",
    "            prbs[k:] = a[i]\n",
    "            i=i+1\n",
    "            \n",
    "        return prbs\n",
    "    else:\n",
    "        raise ValueError(signal_type)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "len_signal = len(df)\n",
    "\n",
    "random_signal = get_random_signal(len_signal, a_range = (- COP_cooling * Pel_max, COP_heating * Pel_max), signal_type = 'analog')\n",
    "prbs = get_random_signal(len_signal, a_range = (0, 5), signal_type = 'prbs')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 16892 characters]\n",
      "text/plain": [
       "<Figure size 1080x432 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure() \n",
    "plt.subplot(2,1,1)\n",
    "plt.plot(random_signal, drawstyle='steps',label='Random Signal')\n",
    "plt.legend()\n",
    "plt.subplot(2,1,2)\n",
    "plt.plot(prbs, drawstyle='steps', label='PRBS')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "power = np.array([df['time'], random_signal]).T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "eng.workspace['power'] = matlab.double(power.tolist())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Set the simulation parameters and run it"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "eng.set_param('polydome', 'StopTime', str(runtime), nargout = 0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "eng.workspace['result'] = eng.sim('polydome')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Interpret the simulation results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "def carnot_to_series(eng, start_timestamp):\n",
    "\n",
    "    # Compile the simulation dict\n",
    "    dict_simulation = {}\n",
    "    dict_simulation['SimulatedTemp'] = np.asarray(eng.eval('result.SimulatedTemp.Data')).reshape(-1)\n",
    "    dict_simulation['time'] = np.asarray(eng.eval('result.SimulatedTemp.Time')).reshape(-1)\n",
    "    \n",
    "    # Create the dataframe from dict\n",
    "    df_simulation = pd.DataFrame(dict_simulation)\n",
    "    df_simulation.set_index('time', inplace = True, drop = True)\n",
    "    \n",
    "    # Define the timestamps and set it as index\n",
    "    df_simulation['timestamp'] = start_timestamp + df_simulation.index.map(lambda x: pd.Timedelta(seconds = x))\n",
    "    df_simulation = df_simulation.reset_index().set_index('timestamp')\n",
    "    \n",
    "    # Resample the dataframe to 5 min intervals\n",
    "    # Taking the mean when there are multiple points, padding with zero order when data is missing\n",
    "    df_simulation = df_simulation['SimulatedTemp'].resample(f'{Tsample}s').mean().pad()\n",
    "    \n",
    "    return df_simulation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_simulation = carnot_to_series(eng, df.index[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "df.loc[:,'SimulatedTemp'] = df_simulation\n",
    "df.loc[:,'SimulatedHeat'] = power[:, 1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 54188 characters]\n",
      "text/plain": [
       "<Figure size 1080x432 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure() \n",
    "plt.subplot(2,1,1)\n",
    "plt.plot(df['SimulatedTemp'], label = 'Simulated Temperature')\n",
    "plt.plot(df['OutsideTemp'], '-.', label = 'Outside Temperature')\n",
    "plt.title('Temperatures')\n",
    "plt.legend()\n",
    "plt.subplot(2,1,2)\n",
    "plt.plot(df['SimulatedHeat'], drawstyle = 'steps', label = 'Heat Input')\n",
    "plt.title('Heat Input')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Export the resampled data-set for further use"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_simulation.to_pickle(f\"../Data/CARNOT_output/{exp_id}_prbs_simulation_df.pkl\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "def simulate_carnot(df_wdb, df, power_signal):\n",
    "    \n",
    "    try:\n",
    "        power = np.array([df['time'], power_signal]).T\n",
    "    except:\n",
    "        import pdb; pdb.set_trace()\n",
    "        pass\n",
    "    runtime = df_wdb['time'].iloc[-1]\n",
    "    \n",
    "    eng.workspace['power'] = matlab.double(power.tolist())\n",
    "    eng.set_param('polydome', 'StopTime', str(runtime), nargout = 0)\n",
    "    eng.workspace['result'] = eng.sim('polydome')\n",
    "    df_simulation = carnot_to_series(eng, df.index[0])\n",
    "    \n",
    "    return df_simulation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_exps = ['Exp1', 'Exp3', 'Exp5', 'Exp6']\n",
    "test_exps = ['Exp2', 'Exp4', 'Exp7']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "t_cols = ['time_h', 'time_m']\n",
    "w_cols = ['SolRad', 'OutsideTemp']\n",
    "u_cols = ['SimulatedHeat']\n",
    "y_cols = ['SimulatedTemp']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "t_lags = 3\n",
    "w_lags = 1\n",
    "u_lags = 1\n",
    "y_lags = 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "dict_cols = {\n",
    "    't': (t_lags, t_cols),\n",
    "    'w': (w_lags, w_cols),\n",
    "    'u': (u_lags, u_cols),\n",
    "    'y': (y_lags, y_cols)\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "dfs_train = []\n",
    "dfs_test = []\n",
    "\n",
    "for exp in train_exps:\n",
    "    df_wdb, df = load_weather_data(exp)\n",
    "\n",
    "    len_signal = len(df)\n",
    "    rnd_power = get_random_signal(\n",
    "        len_signal,\n",
    "        a_range = (- COP_cooling * Pel_max, COP_heating * Pel_max),\n",
    "        signal_type = 'analog'\n",
    "    )\n",
    "\n",
    "    df_sim = simulate_carnot(df_wdb, df, rnd_power)\n",
    "    df.loc[:, 'SimulatedHeat'] = rnd_power\n",
    "    df.loc[:, 'SimulatedTemp'] = df_sim\n",
    "    \n",
    "    dfs_train.append(df)\n",
    "\n",
    "for exp in test_exps:\n",
    "    df_wdb, df = load_weather_data(exp)\n",
    "\n",
    "    len_signal = len(df)\n",
    "    rnd_power = get_random_signal(\n",
    "        len_signal,\n",
    "        a_range = (- COP_cooling * Pel_max, COP_heating * Pel_max),\n",
    "        signal_type = 'analog'\n",
    "    )\n",
    "\n",
    "    df_sim = simulate_carnot(df_wdb, df, rnd_power)\n",
    "    df.loc[:, 'SimulatedHeat'] = rnd_power\n",
    "    df.loc[:, 'SimulatedTemp'] = df_sim\n",
    "    \n",
    "    dfs_test.append(df)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "pickle.dump(dict_cols, open(Path(\"dict_cols.pkl\"), 'wb'))\n",
    "pickle.dump(dfs_train, open(Path(\"dfs_train.pkl\"), 'wb'))\n",
    "pickle.dump(dfs_test, open(Path(\"dfs_test.pkl\"), 'wb'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<AxesSubplot:xlabel='timestamp'>"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 46320 characters]\n",
      "text/plain": [
       "<Figure size 1080x432 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "dfs_train[0][['SimulatedTemp']].plot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Trim and scale the input data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.preprocessing import MinMaxScaler, RobustScaler\n",
    "from sklearn.exceptions import NotFittedError"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [],
   "source": [
    "scaler = MinMaxScaler(feature_range = (-1, 1))\n",
    "#scaler = RobustScaler()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_scaled_df(df, dict_cols, scaler):\n",
    "    \n",
    "    t_list = dict_cols['t'][1]\n",
    "    w_list = dict_cols['w'][1]\n",
    "    u_list = dict_cols['u'][1]\n",
    "    y_list = dict_cols['y'][1]\n",
    "    \n",
    "    df_local = df[t_list + w_list + u_list + y_list]\n",
    "    df_scaled = df_local.to_numpy()\n",
    "    \n",
    "    try:\n",
    "        df_scaled = scaler.transform(df_scaled)\n",
    "    except NotFittedError:\n",
    "        df_scaled = scaler.fit_transform(df_scaled)\n",
    "        \n",
    "    df_scaled = pd.DataFrame(df_scaled, index = df_local.index, columns = df_local.columns)\n",
    "    \n",
    "    return df_scaled"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_train = pd.concat(dfs_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "279119.2189692174"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.cond(df_train.to_numpy())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_train_sc = get_scaled_df(df_train, dict_cols, scaler)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4.58816888677789"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.cond(df_train_sc.to_numpy())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [],
   "source": [
    "dfs_train_sc = []\n",
    "dfs_test_sc = []\n",
    "for df in dfs_train:\n",
    "    df_sc = get_scaled_df(df, dict_cols, scaler)\n",
    "    dfs_train_sc.append(df_sc)\n",
    "    \n",
    "for df in dfs_test:\n",
    "    df_sc = get_scaled_df(df, dict_cols, scaler)\n",
    "    dfs_test_sc.append(df_sc)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/lib/python3.9/site-packages/pandas/plotting/_matplotlib/tools.py:400: MatplotlibDeprecationWarning: \n",
      "The is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.\n",
      "  if ax.is_first_col():\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([[<AxesSubplot:title={'center':'time_h'}>,\n",
       "        <AxesSubplot:title={'center':'time_m'}>],\n",
       "       [<AxesSubplot:title={'center':'SolRad'}>,\n",
       "        <AxesSubplot:title={'center':'OutsideTemp'}>],\n",
       "       [<AxesSubplot:title={'center':'SimulatedHeat'}>,\n",
       "        <AxesSubplot:title={'center':'SimulatedTemp'}>]], dtype=object)"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 22356 characters]\n",
      "text/plain": [
       "<Figure size 1080x432 with 6 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "dfs_train_sc[0].hist()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Gaussian Process Regression"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Compile training set"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [],
   "source": [
    "def data_to_gpr(df, dict_cols):\n",
    "    \n",
    "    t_list = dict_cols['t'][1]\n",
    "    w_list = dict_cols['w'][1]\n",
    "    u_list = dict_cols['u'][1]\n",
    "    y_list = dict_cols['y'][1]\n",
    "    \n",
    "    df_gpr = df[t_list + w_list + u_list + y_list].copy()\n",
    "    \n",
    "    for lags, names in dict_cols.values():\n",
    "        for name in names:\n",
    "            col_idx = df_gpr.columns.get_loc(name)\n",
    "            for lag in range(1, lags + 1):\n",
    "                df_gpr.insert(col_idx + lag, f\"{name}_{lag}\", df_gpr.loc[:, name].shift(lag))\n",
    "\n",
    "    df_gpr.dropna(inplace = True)\n",
    "    \n",
    "    return df_gpr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>time_h</th>\n",
       "      <th>time_h_1</th>\n",
       "      <th>time_h_2</th>\n",
       "      <th>time_h_3</th>\n",
       "      <th>time_m</th>\n",
       "      <th>time_m_1</th>\n",
       "      <th>time_m_2</th>\n",
       "      <th>time_m_3</th>\n",
       "      <th>SolRad</th>\n",
       "      <th>SolRad_1</th>\n",
       "      <th>OutsideTemp</th>\n",
       "      <th>OutsideTemp_1</th>\n",
       "      <th>SimulatedHeat</th>\n",
       "      <th>SimulatedHeat_1</th>\n",
       "      <th>SimulatedTemp</th>\n",
       "      <th>SimulatedTemp_1</th>\n",
       "      <th>SimulatedTemp_2</th>\n",
       "      <th>SimulatedTemp_3</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>timestamp</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2017-06-01 20:45:00+02:00</th>\n",
       "      <td>0.739130</td>\n",
       "      <td>0.739130</td>\n",
       "      <td>0.739130</td>\n",
       "      <td>0.739130</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.333333</td>\n",
       "      <td>-0.333333</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>-0.970807</td>\n",
       "      <td>-0.925970</td>\n",
       "      <td>0.058824</td>\n",
       "      <td>0.058824</td>\n",
       "      <td>0.438090</td>\n",
       "      <td>0.438090</td>\n",
       "      <td>0.248081</td>\n",
       "      <td>0.233535</td>\n",
       "      <td>0.214339</td>\n",
       "      <td>0.153839</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-06-01 21:00:00+02:00</th>\n",
       "      <td>0.826087</td>\n",
       "      <td>0.739130</td>\n",
       "      <td>0.739130</td>\n",
       "      <td>0.739130</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.333333</td>\n",
       "      <td>-0.333333</td>\n",
       "      <td>-0.980063</td>\n",
       "      <td>-0.970807</td>\n",
       "      <td>0.019608</td>\n",
       "      <td>0.058824</td>\n",
       "      <td>0.438090</td>\n",
       "      <td>0.438090</td>\n",
       "      <td>0.216876</td>\n",
       "      <td>0.248081</td>\n",
       "      <td>0.233535</td>\n",
       "      <td>0.214339</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-06-01 21:15:00+02:00</th>\n",
       "      <td>0.826087</td>\n",
       "      <td>0.826087</td>\n",
       "      <td>0.739130</td>\n",
       "      <td>0.739130</td>\n",
       "      <td>-0.333333</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.333333</td>\n",
       "      <td>-0.989906</td>\n",
       "      <td>-0.980063</td>\n",
       "      <td>-0.058824</td>\n",
       "      <td>0.019608</td>\n",
       "      <td>-0.470064</td>\n",
       "      <td>0.438090</td>\n",
       "      <td>0.062767</td>\n",
       "      <td>0.216876</td>\n",
       "      <td>0.248081</td>\n",
       "      <td>0.233535</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-06-01 21:30:00+02:00</th>\n",
       "      <td>0.826087</td>\n",
       "      <td>0.826087</td>\n",
       "      <td>0.826087</td>\n",
       "      <td>0.739130</td>\n",
       "      <td>0.333333</td>\n",
       "      <td>-0.333333</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>-0.991909</td>\n",
       "      <td>-0.989906</td>\n",
       "      <td>-0.058824</td>\n",
       "      <td>-0.058824</td>\n",
       "      <td>-0.470064</td>\n",
       "      <td>-0.470064</td>\n",
       "      <td>0.091034</td>\n",
       "      <td>0.062767</td>\n",
       "      <td>0.216876</td>\n",
       "      <td>0.248081</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-06-01 21:45:00+02:00</th>\n",
       "      <td>0.826087</td>\n",
       "      <td>0.826087</td>\n",
       "      <td>0.826087</td>\n",
       "      <td>0.826087</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.333333</td>\n",
       "      <td>-0.333333</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>-0.992483</td>\n",
       "      <td>-0.991909</td>\n",
       "      <td>-0.058824</td>\n",
       "      <td>-0.058824</td>\n",
       "      <td>0.577419</td>\n",
       "      <td>-0.470064</td>\n",
       "      <td>0.203306</td>\n",
       "      <td>0.091034</td>\n",
       "      <td>0.062767</td>\n",
       "      <td>0.216876</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                             time_h  time_h_1  time_h_2  time_h_3    time_m  \\\n",
       "timestamp                                                                     \n",
       "2017-06-01 20:45:00+02:00  0.739130  0.739130  0.739130  0.739130  1.000000   \n",
       "2017-06-01 21:00:00+02:00  0.826087  0.739130  0.739130  0.739130 -1.000000   \n",
       "2017-06-01 21:15:00+02:00  0.826087  0.826087  0.739130  0.739130 -0.333333   \n",
       "2017-06-01 21:30:00+02:00  0.826087  0.826087  0.826087  0.739130  0.333333   \n",
       "2017-06-01 21:45:00+02:00  0.826087  0.826087  0.826087  0.826087  1.000000   \n",
       "\n",
       "                           time_m_1  time_m_2  time_m_3    SolRad  SolRad_1  \\\n",
       "timestamp                                                                     \n",
       "2017-06-01 20:45:00+02:00  0.333333 -0.333333 -1.000000 -0.970807 -0.925970   \n",
       "2017-06-01 21:00:00+02:00  1.000000  0.333333 -0.333333 -0.980063 -0.970807   \n",
       "2017-06-01 21:15:00+02:00 -1.000000  1.000000  0.333333 -0.989906 -0.980063   \n",
       "2017-06-01 21:30:00+02:00 -0.333333 -1.000000  1.000000 -0.991909 -0.989906   \n",
       "2017-06-01 21:45:00+02:00  0.333333 -0.333333 -1.000000 -0.992483 -0.991909   \n",
       "\n",
       "                           OutsideTemp  OutsideTemp_1  SimulatedHeat  \\\n",
       "timestamp                                                              \n",
       "2017-06-01 20:45:00+02:00     0.058824       0.058824       0.438090   \n",
       "2017-06-01 21:00:00+02:00     0.019608       0.058824       0.438090   \n",
       "2017-06-01 21:15:00+02:00    -0.058824       0.019608      -0.470064   \n",
       "2017-06-01 21:30:00+02:00    -0.058824      -0.058824      -0.470064   \n",
       "2017-06-01 21:45:00+02:00    -0.058824      -0.058824       0.577419   \n",
       "\n",
       "                           SimulatedHeat_1  SimulatedTemp  SimulatedTemp_1  \\\n",
       "timestamp                                                                    \n",
       "2017-06-01 20:45:00+02:00         0.438090       0.248081         0.233535   \n",
       "2017-06-01 21:00:00+02:00         0.438090       0.216876         0.248081   \n",
       "2017-06-01 21:15:00+02:00         0.438090       0.062767         0.216876   \n",
       "2017-06-01 21:30:00+02:00        -0.470064       0.091034         0.062767   \n",
       "2017-06-01 21:45:00+02:00        -0.470064       0.203306         0.091034   \n",
       "\n",
       "                           SimulatedTemp_2  SimulatedTemp_3  \n",
       "timestamp                                                    \n",
       "2017-06-01 20:45:00+02:00         0.214339         0.153839  \n",
       "2017-06-01 21:00:00+02:00         0.233535         0.214339  \n",
       "2017-06-01 21:15:00+02:00         0.248081         0.233535  \n",
       "2017-06-01 21:30:00+02:00         0.216876         0.248081  \n",
       "2017-06-01 21:45:00+02:00         0.062767         0.216876  "
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dfs_gpr_train = []\n",
    "for df_sc in dfs_train_sc:\n",
    "    dfs_gpr_train.append(data_to_gpr(df_sc, dict_cols))\n",
    "df_gpr_train = pd.concat(dfs_gpr_train)\n",
    "df_gpr_train.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1696122339350262.8"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.cond(\n",
    "    df_gpr_train.to_numpy()\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_timestamps(start_timestamp, time_delta, n_steps):\n",
    "\n",
    "    # Define the timestamps and set it as index\n",
    "    timestamps = np.linspace(0, (n_steps-1)*time_delta, n_steps)\n",
    "    timestamps = start_timestamp + pd.Series(timestamps).map(lambda x: pd.Timedelta(seconds = x))\n",
    "    \n",
    "    return timestamps"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_gpr_train.to_pickle(\"df_gpr_train.pkl\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/lib/python3.9/site-packages/pandas/plotting/_matplotlib/tools.py:400: MatplotlibDeprecationWarning: \n",
      "The is_first_col function was deprecated in Matplotlib 3.4 and will be removed two minor releases later. Use ax.get_subplotspec().is_first_col() instead.\n",
      "  if ax.is_first_col():\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([[<AxesSubplot:title={'center':'time_h'}>,\n",
       "        <AxesSubplot:title={'center':'time_h_1'}>,\n",
       "        <AxesSubplot:title={'center':'time_h_2'}>,\n",
       "        <AxesSubplot:title={'center':'time_h_3'}>],\n",
       "       [<AxesSubplot:title={'center':'time_m'}>,\n",
       "        <AxesSubplot:title={'center':'time_m_1'}>,\n",
       "        <AxesSubplot:title={'center':'time_m_2'}>,\n",
       "        <AxesSubplot:title={'center':'time_m_3'}>],\n",
       "       [<AxesSubplot:title={'center':'SolRad'}>,\n",
       "        <AxesSubplot:title={'center':'SolRad_1'}>,\n",
       "        <AxesSubplot:title={'center':'OutsideTemp'}>,\n",
       "        <AxesSubplot:title={'center':'OutsideTemp_1'}>],\n",
       "       [<AxesSubplot:title={'center':'SimulatedHeat'}>,\n",
       "        <AxesSubplot:title={'center':'SimulatedHeat_1'}>,\n",
       "        <AxesSubplot:title={'center':'SimulatedTemp'}>,\n",
       "        <AxesSubplot:title={'center':'SimulatedTemp_1'}>],\n",
       "       [<AxesSubplot:title={'center':'SimulatedTemp_2'}>,\n",
       "        <AxesSubplot:title={'center':'SimulatedTemp_3'}>, <AxesSubplot:>,\n",
       "        <AxesSubplot:>]], dtype=object)"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 29196 characters]\n",
      "text/plain": [
       "<Figure size 1080x432 with 20 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "df_gpr_train.hist()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_input_train = df_gpr_train.drop(columns = dict_cols['u'][1] + dict_cols['y'][1])\n",
    "df_output_train = df_gpr_train[dict_cols['y'][1]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>time_h</th>\n",
       "      <th>time_h_1</th>\n",
       "      <th>time_h_2</th>\n",
       "      <th>time_h_3</th>\n",
       "      <th>time_m</th>\n",
       "      <th>time_m_1</th>\n",
       "      <th>time_m_2</th>\n",
       "      <th>time_m_3</th>\n",
       "      <th>SolRad</th>\n",
       "      <th>SolRad_1</th>\n",
       "      <th>OutsideTemp</th>\n",
       "      <th>OutsideTemp_1</th>\n",
       "      <th>SimulatedHeat_1</th>\n",
       "      <th>SimulatedTemp_1</th>\n",
       "      <th>SimulatedTemp_2</th>\n",
       "      <th>SimulatedTemp_3</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>timestamp</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2017-06-01 20:45:00+02:00</th>\n",
       "      <td>0.739130</td>\n",
       "      <td>0.739130</td>\n",
       "      <td>0.739130</td>\n",
       "      <td>0.739130</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.333333</td>\n",
       "      <td>-0.333333</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>-0.970807</td>\n",
       "      <td>-0.925970</td>\n",
       "      <td>0.058824</td>\n",
       "      <td>0.058824</td>\n",
       "      <td>0.438090</td>\n",
       "      <td>0.233535</td>\n",
       "      <td>0.214339</td>\n",
       "      <td>0.153839</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-06-01 21:00:00+02:00</th>\n",
       "      <td>0.826087</td>\n",
       "      <td>0.739130</td>\n",
       "      <td>0.739130</td>\n",
       "      <td>0.739130</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.333333</td>\n",
       "      <td>-0.333333</td>\n",
       "      <td>-0.980063</td>\n",
       "      <td>-0.970807</td>\n",
       "      <td>0.019608</td>\n",
       "      <td>0.058824</td>\n",
       "      <td>0.438090</td>\n",
       "      <td>0.248081</td>\n",
       "      <td>0.233535</td>\n",
       "      <td>0.214339</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-06-01 21:15:00+02:00</th>\n",
       "      <td>0.826087</td>\n",
       "      <td>0.826087</td>\n",
       "      <td>0.739130</td>\n",
       "      <td>0.739130</td>\n",
       "      <td>-0.333333</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.333333</td>\n",
       "      <td>-0.989906</td>\n",
       "      <td>-0.980063</td>\n",
       "      <td>-0.058824</td>\n",
       "      <td>0.019608</td>\n",
       "      <td>0.438090</td>\n",
       "      <td>0.216876</td>\n",
       "      <td>0.248081</td>\n",
       "      <td>0.233535</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-06-01 21:30:00+02:00</th>\n",
       "      <td>0.826087</td>\n",
       "      <td>0.826087</td>\n",
       "      <td>0.826087</td>\n",
       "      <td>0.739130</td>\n",
       "      <td>0.333333</td>\n",
       "      <td>-0.333333</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>-0.991909</td>\n",
       "      <td>-0.989906</td>\n",
       "      <td>-0.058824</td>\n",
       "      <td>-0.058824</td>\n",
       "      <td>-0.470064</td>\n",
       "      <td>0.062767</td>\n",
       "      <td>0.216876</td>\n",
       "      <td>0.248081</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-06-01 21:45:00+02:00</th>\n",
       "      <td>0.826087</td>\n",
       "      <td>0.826087</td>\n",
       "      <td>0.826087</td>\n",
       "      <td>0.826087</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.333333</td>\n",
       "      <td>-0.333333</td>\n",
       "      <td>-1.000000</td>\n",
       "      <td>-0.992483</td>\n",
       "      <td>-0.991909</td>\n",
       "      <td>-0.058824</td>\n",
       "      <td>-0.058824</td>\n",
       "      <td>-0.470064</td>\n",
       "      <td>0.091034</td>\n",
       "      <td>0.062767</td>\n",
       "      <td>0.216876</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                             time_h  time_h_1  time_h_2  time_h_3    time_m  \\\n",
       "timestamp                                                                     \n",
       "2017-06-01 20:45:00+02:00  0.739130  0.739130  0.739130  0.739130  1.000000   \n",
       "2017-06-01 21:00:00+02:00  0.826087  0.739130  0.739130  0.739130 -1.000000   \n",
       "2017-06-01 21:15:00+02:00  0.826087  0.826087  0.739130  0.739130 -0.333333   \n",
       "2017-06-01 21:30:00+02:00  0.826087  0.826087  0.826087  0.739130  0.333333   \n",
       "2017-06-01 21:45:00+02:00  0.826087  0.826087  0.826087  0.826087  1.000000   \n",
       "\n",
       "                           time_m_1  time_m_2  time_m_3    SolRad  SolRad_1  \\\n",
       "timestamp                                                                     \n",
       "2017-06-01 20:45:00+02:00  0.333333 -0.333333 -1.000000 -0.970807 -0.925970   \n",
       "2017-06-01 21:00:00+02:00  1.000000  0.333333 -0.333333 -0.980063 -0.970807   \n",
       "2017-06-01 21:15:00+02:00 -1.000000  1.000000  0.333333 -0.989906 -0.980063   \n",
       "2017-06-01 21:30:00+02:00 -0.333333 -1.000000  1.000000 -0.991909 -0.989906   \n",
       "2017-06-01 21:45:00+02:00  0.333333 -0.333333 -1.000000 -0.992483 -0.991909   \n",
       "\n",
       "                           OutsideTemp  OutsideTemp_1  SimulatedHeat_1  \\\n",
       "timestamp                                                                \n",
       "2017-06-01 20:45:00+02:00     0.058824       0.058824         0.438090   \n",
       "2017-06-01 21:00:00+02:00     0.019608       0.058824         0.438090   \n",
       "2017-06-01 21:15:00+02:00    -0.058824       0.019608         0.438090   \n",
       "2017-06-01 21:30:00+02:00    -0.058824      -0.058824        -0.470064   \n",
       "2017-06-01 21:45:00+02:00    -0.058824      -0.058824        -0.470064   \n",
       "\n",
       "                           SimulatedTemp_1  SimulatedTemp_2  SimulatedTemp_3  \n",
       "timestamp                                                                     \n",
       "2017-06-01 20:45:00+02:00         0.233535         0.214339         0.153839  \n",
       "2017-06-01 21:00:00+02:00         0.248081         0.233535         0.214339  \n",
       "2017-06-01 21:15:00+02:00         0.216876         0.248081         0.233535  \n",
       "2017-06-01 21:30:00+02:00         0.062767         0.216876         0.248081  \n",
       "2017-06-01 21:45:00+02:00         0.091034         0.062767         0.216876  "
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_input_train.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>SimulatedTemp</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>timestamp</th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2017-06-01 20:45:00+02:00</th>\n",
       "      <td>0.248081</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-06-01 21:00:00+02:00</th>\n",
       "      <td>0.216876</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-06-01 21:15:00+02:00</th>\n",
       "      <td>0.062767</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-06-01 21:30:00+02:00</th>\n",
       "      <td>0.091034</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2017-06-01 21:45:00+02:00</th>\n",
       "      <td>0.203306</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                           SimulatedTemp\n",
       "timestamp                               \n",
       "2017-06-01 20:45:00+02:00       0.248081\n",
       "2017-06-01 21:00:00+02:00       0.216876\n",
       "2017-06-01 21:15:00+02:00       0.062767\n",
       "2017-06-01 21:30:00+02:00       0.091034\n",
       "2017-06-01 21:45:00+02:00       0.203306"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_output_train.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [],
   "source": [
    "np_input_train = df_input_train.to_numpy()\n",
    "np_output_train = df_output_train.to_numpy().reshape(-1, 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(864, 16)"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np_input_train.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Define model and kernel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [],
   "source": [
    "nb_dims = np_input_train.shape[1]\n",
    "rational_dims = np.arange(0, (dict_cols['t'][0] + 1) * len(dict_cols['t'][1]), 1)\n",
    "nb_rational_dims = len(rational_dims)\n",
    "squared_dims = np.arange(nb_rational_dims, nb_dims, 1)\n",
    "nb_squared_dims = len(squared_dims)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [],
   "source": [
    "squared_l = [1] * nb_squared_dims\n",
    "rational_l = [1] * nb_rational_dims"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [],
   "source": [
    "variance = tf.math.reduce_variance(np_input_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {},
   "outputs": [],
   "source": [
    "variance = 10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {},
   "outputs": [],
   "source": [
    "k0 = gpflow.kernels.SquaredExponential(lengthscales = squared_l, active_dims = squared_dims, variance = variance)\n",
    "k1 = gpflow.kernels.Constant()\n",
    "k2 = gpflow.kernels.RationalQuadratic(lengthscales = rational_l, active_dims = rational_dims, variance = variance)\n",
    "k3 = gpflow.kernels.Periodic(k2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table>\n",
       "<thead>\n",
       "<tr><th>name                                      </th><th>class    </th><th>transform  </th><th>prior  </th><th>trainable  </th><th>shape  </th><th>dtype  </th><th>value         </th></tr>\n",
       "</thead>\n",
       "<tbody>\n",
       "<tr><td>Product.kernels[0].kernels[0].variance    </td><td>Parameter</td><td>Softplus   </td><td>       </td><td>True       </td><td>()     </td><td>float64</td><td>10.0          </td></tr>\n",
       "<tr><td>Product.kernels[0].kernels[0].lengthscales</td><td>Parameter</td><td>Softplus   </td><td>       </td><td>True       </td><td>(8,)   </td><td>float64</td><td>[1., 1., 1....</td></tr>\n",
       "<tr><td>Product.kernels[0].kernels[1].variance    </td><td>Parameter</td><td>Softplus   </td><td>       </td><td>True       </td><td>()     </td><td>float64</td><td>1.0           </td></tr>\n",
       "<tr><td>Product.kernels[1].variance               </td><td>Parameter</td><td>Softplus   </td><td>       </td><td>True       </td><td>()     </td><td>float64</td><td>10.0          </td></tr>\n",
       "<tr><td>Product.kernels[1].lengthscales           </td><td>Parameter</td><td>Softplus   </td><td>       </td><td>True       </td><td>(8,)   </td><td>float64</td><td>[1., 1., 1....</td></tr>\n",
       "<tr><td>Product.kernels[1].alpha                  </td><td>Parameter</td><td>Softplus   </td><td>       </td><td>True       </td><td>()     </td><td>float64</td><td>1.0           </td></tr>\n",
       "</tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "k = (k0 + k1) * k2\n",
    "print_summary(k)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table>\n",
       "<thead>\n",
       "<tr><th>name                                         </th><th>class    </th><th>transform       </th><th>prior  </th><th>trainable  </th><th>shape  </th><th>dtype  </th><th>value         </th></tr>\n",
       "</thead>\n",
       "<tbody>\n",
       "<tr><td>GPR.kernel.kernels[0].kernels[0].variance    </td><td>Parameter</td><td>Softplus        </td><td>       </td><td>True       </td><td>()     </td><td>float64</td><td>10.0          </td></tr>\n",
       "<tr><td>GPR.kernel.kernels[0].kernels[0].lengthscales</td><td>Parameter</td><td>Softplus        </td><td>       </td><td>True       </td><td>(8,)   </td><td>float64</td><td>[1., 1., 1....</td></tr>\n",
       "<tr><td>GPR.kernel.kernels[0].kernels[1].variance    </td><td>Parameter</td><td>Softplus        </td><td>       </td><td>True       </td><td>()     </td><td>float64</td><td>1.0           </td></tr>\n",
       "<tr><td>GPR.kernel.kernels[1].variance               </td><td>Parameter</td><td>Softplus        </td><td>       </td><td>True       </td><td>()     </td><td>float64</td><td>10.0          </td></tr>\n",
       "<tr><td>GPR.kernel.kernels[1].lengthscales           </td><td>Parameter</td><td>Softplus        </td><td>       </td><td>True       </td><td>(8,)   </td><td>float64</td><td>[1., 1., 1....</td></tr>\n",
       "<tr><td>GPR.kernel.kernels[1].alpha                  </td><td>Parameter</td><td>Softplus        </td><td>       </td><td>True       </td><td>()     </td><td>float64</td><td>1.0           </td></tr>\n",
       "<tr><td>GPR.likelihood.variance                      </td><td>Parameter</td><td>Softplus + Shift</td><td>       </td><td>True       </td><td>()     </td><td>float64</td><td>1.0           </td></tr>\n",
       "</tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "m = gpflow.models.GPR(\n",
    "    data = (np_input_train, np_output_train), \n",
    "    kernel = k,\n",
    "    mean_function = None\n",
    "    )\n",
    "print_summary(m)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Train model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {},
   "outputs": [],
   "source": [
    "opt = gpflow.optimizers.Scipy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [],
   "source": [
    "from datetime import datetime"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Finished fitting in 0:00:16.041917\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table>\n",
       "<thead>\n",
       "<tr><th>name                                         </th><th>class    </th><th>transform       </th><th>prior  </th><th>trainable  </th><th>shape  </th><th>dtype  </th><th>value                                          </th></tr>\n",
       "</thead>\n",
       "<tbody>\n",
       "<tr><td>GPR.kernel.kernels[0].kernels[0].variance    </td><td>Parameter</td><td>Softplus        </td><td>       </td><td>True       </td><td>()     </td><td>float64</td><td>680.0158754974991                              </td></tr>\n",
       "<tr><td>GPR.kernel.kernels[0].kernels[0].lengthscales</td><td>Parameter</td><td>Softplus        </td><td>       </td><td>True       </td><td>(8,)   </td><td>float64</td><td>[3879.61410136, 3611.74772391, 2705.86685632...</td></tr>\n",
       "<tr><td>GPR.kernel.kernels[0].kernels[1].variance    </td><td>Parameter</td><td>Softplus        </td><td>       </td><td>True       </td><td>()     </td><td>float64</td><td>0.0                                            </td></tr>\n",
       "<tr><td>GPR.kernel.kernels[1].variance               </td><td>Parameter</td><td>Softplus        </td><td>       </td><td>True       </td><td>()     </td><td>float64</td><td>2.5528463890805164                             </td></tr>\n",
       "<tr><td>GPR.kernel.kernels[1].lengthscales           </td><td>Parameter</td><td>Softplus        </td><td>       </td><td>True       </td><td>(8,)   </td><td>float64</td><td>[4756.27621398, 4614.06336408, 4742.18906451...</td></tr>\n",
       "<tr><td>GPR.kernel.kernels[1].alpha                  </td><td>Parameter</td><td>Softplus        </td><td>       </td><td>True       </td><td>()     </td><td>float64</td><td>2859.355412460411                              </td></tr>\n",
       "<tr><td>GPR.likelihood.variance                      </td><td>Parameter</td><td>Softplus + Shift</td><td>       </td><td>True       </td><td>()     </td><td>float64</td><td>0.0019562304623461906                          </td></tr>\n",
       "</tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "start_time = datetime.now()\n",
    "opt.minimize(m.training_loss, m.trainable_variables)\n",
    "print(f\"Finished fitting in {datetime.now() - start_time}\")\n",
    "print_summary(m)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Evaluate performance on training data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {},
   "outputs": [],
   "source": [
    "nb_plts = len(dfs_gpr_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 294412 characters]\n",
      "text/plain": [
       "<Figure size 1440x1440 with 4 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize = (20, 20))\n",
    "\n",
    "for idx, df_iter in enumerate(dfs_gpr_train):\n",
    "    plt.subplot(nb_plts, 1, idx + 1)\n",
    "    df_input_iter = df_iter.drop(columns = dict_cols['y'][1] + dict_cols['u'][1])\n",
    "    df_output_iter = df_iter[dict_cols['y'][1]]\n",
    "    np_input_iter = df_input_iter.to_numpy()\n",
    "    np_output_iter = df_output_iter.to_numpy().reshape(-1, 1)\n",
    "    \n",
    "    mean, var = m.predict_f(np_input_iter)\n",
    "    \n",
    "    plt.plot(df_iter.index, np_output_iter[:, :], label = 'Measured data')\n",
    "    plt.plot(df_iter.index, mean[:, :], label = 'Gaussian Process Prediction')\n",
    "    plt.fill_between(\n",
    "        df_iter.index, \n",
    "        mean[:, 0] - 1.96 * np.sqrt(var[:, 0]),\n",
    "        mean[:, 0] + 1.96 * np.sqrt(var[:, 0]),\n",
    "        alpha = 0.2\n",
    "    )\n",
    "    plt.title(f\"Model Performance on training data: {train_exps[idx]}\")\n",
    "    plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Evaluate performance on test data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {},
   "outputs": [],
   "source": [
    "dfs_gpr_test = []\n",
    "for df_sc in dfs_test_sc:\n",
    "    dfs_gpr_test.append(data_to_gpr(df_sc, dict_cols))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 239880 characters]\n",
      "text/plain": [
       "<Figure size 1440x1440 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize = (20, 20))\n",
    "\n",
    "for idx, df_iter in enumerate(dfs_gpr_test):\n",
    "    plt.subplot(nb_plts, 1, idx + 1)\n",
    "    df_input_iter = df_iter.drop(columns = dict_cols['y'][1] + dict_cols['u'][1])\n",
    "    df_output_iter = df_iter[dict_cols['y'][1]]\n",
    "    np_input_iter = df_input_iter.to_numpy()\n",
    "    np_output_iter = df_output_iter.to_numpy().reshape(-1, 1)\n",
    "    \n",
    "    mean, var = m.predict_f(np_input_iter)\n",
    "    \n",
    "    plt.plot(df_iter.index, np_output_iter[:, :], label = 'Measured data')\n",
    "    plt.plot(df_iter.index, mean[:, :], label = 'Gaussian Process Prediction')\n",
    "    plt.fill_between(\n",
    "        df_iter.index, \n",
    "        mean[:, 0] - 1.96 * np.sqrt(var[:, 0]),\n",
    "        mean[:, 0] + 1.96 * np.sqrt(var[:, 0]),\n",
    "        alpha = 0.2\n",
    "    )\n",
    "    plt.title(f\"Model Performance on test data: {test_exps[idx]}\")\n",
    "    plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [],
   "source": [
    "pickle.dump(dfs_gpr_train, open(Path(\"dfs_gpr_train.pkl\"), 'wb'))\n",
    "pickle.dump(dfs_gpr_test, open(Path(\"dfs_gpr_test.pkl\"), 'wb'))\n",
    "pickle.dump(scaler, open(Path(\"scaler.pkl\"), 'wb'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "432.87418821478263"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.cond(\n",
    "    np_input_train[:100, :]\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4.4999054032351606e+21"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.cond(\n",
    "    k(np_input_train[:, :])\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [],
   "source": [
    "def simulate_carnot_gp(df_wdb, df, power_signal, m):\n",
    "    \n",
    "    df_local = df.copy()\n",
    "    \n",
    "    power = np.array([df_wdb['time'], power_signal]).T\n",
    "    runtime = df_wdb['time'].iloc[-1]\n",
    "    \n",
    "    eng.workspace['power'] = matlab.double(power.tolist())\n",
    "    eng.set_param('polydome', 'StopTime', str(runtime), nargout = 0)\n",
    "    eng.workspace['result'] = eng.sim('polydome')\n",
    "    df_simulation = carnot_to_series(eng, df.index[0])\n",
    "    \n",
    "    df_local.loc[:,'SimulatedTemp'] = df_simulation\n",
    "    df_local.loc[:,'SimulatedHeat'] = power[:, 1]\n",
    "    \n",
    "    df_sc = get_scaled_df(df_local, w_list, u_list, y_list, scaler)\n",
    "    df_gpr = data_to_gpr(df_sc)\n",
    "\n",
    "    df_input = df_gpr.drop(columns = ['u', 'y'])\n",
    "    df_output = df_gpr['y']\n",
    "    \n",
    "    np_input_test = df_input.to_numpy()\n",
    "    #np_output_test = df_output.to_numpy().reshape(-1, 1)\n",
    "    \n",
    "    mean, var = m.predict_y(np_input_test)\n",
    "        \n",
    "    df_local.loc[3:, 'gpTemp'] = mean\n",
    "    df_local.loc[3:, 'gpVar'] = var\n",
    "    \n",
    "    return df_local"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [],
   "source": [
    "#df_sim = simulate_carnot_gp(df_wdb, df, random_signal, m)\n",
    "#df_sim.fillna(0, inplace = True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Export Gaussian Process Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [],
   "source": [
    "def export_gpr(path, m, w_scaler, u_scaler, y_scaler):\n",
    "    m_params = gpflow.utilities.parameter_dict(m)\n",
    "    pickle.dump(m_params, open(Path(path, 'gp_params.gpf'), 'wb'))\n",
    "    pickle.dump(m.data, open(Path(path, 'gp_data.gpf'), 'wb'))\n",
    "    pickle.dump(w_scaler, open(Path(path, 'w_scaler.pkl'), 'wb'))\n",
    "    pickle.dump(u_scaler, open(Path(path, 'u_scaler.pkl'), 'wb'))\n",
    "    pickle.dump(y_scaler, open(Path(path, 'y_scaler.pkl'), 'wb'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "PosixPath('/home/radu/Projects/Master-Project/Notebooks/model')"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "export_path = Path(Path.cwd(), 'model')\n",
    "export_path"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'w_scaler' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-79-1aca23412daa>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mexport_gpr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mexport_path\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mw_scaler\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mu_scaler\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my_scaler\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m: name 'w_scaler' is not defined"
     ]
    }
   ],
   "source": [
    "export_gpr(export_path, m, w_scaler, u_scaler, y_scaler)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from scipy.io import savemat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "table_cols = df_gpr_train.columns.to_list()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mdict = {\n",
    "    'table_cols': table_cols,\n",
    "    'gpr_train': dfs_gpr_train,\n",
    "    'gpr_test': dfs_gpr_test\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "savemat(\"test_mat.mat\", mdict)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Evaluate performance with new input and disturbances"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_wdb, df = load_weather_data(\"Exp7\")\n",
    "len_signal = len(df_wdb)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "random_signal = get_random_signal(len_signal, a_range = (- COP_cooling * Pel_max, COP_heating * Pel_max), signal_type = 'analog')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_sim = simulate_carnot_gp(df_wdb, df, random_signal, m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure() \n",
    "plt.subplot(2,1,1)\n",
    "plt.plot(df_sim.index, df_sim['SimulatedTemp'], label = 'Simulated Temperature')\n",
    "plt.plot(df.index, df['OutsideTemp'], '-.', label = 'Outside Temperature')\n",
    "plt.title('Temperatures')\n",
    "plt.legend()\n",
    "plt.subplot(2,1,2)\n",
    "plt.plot(df_sim['SimulatedHeat'], drawstyle = 'steps', label = 'Heat Input')\n",
    "plt.title('Heat Input')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize = (20, 5))\n",
    "plt.plot(df_sim.index, df_sim['SimulatedTemp'], label = 'Measured data')\n",
    "plt.plot(df_sim.index, df_sim['gpTemp'], label = 'Gaussian Process Prediction')\n",
    "plt.fill_between(\n",
    "    df_sim.index, \n",
    "    df_sim['gpTemp'] - 1.96 * np.sqrt(df_sim['gpVar']),\n",
    "    df_sim['gpTemp'] + 1.96 * np.sqrt(df_sim['gpVar']),\n",
    "    alpha = 0.2\n",
    ")\n",
    "plt.legend()\n",
    "plt.title(\"Gaussian Process Performance on new random input data/ new weather data\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "### Simulate the System with constant Zero Input"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "random_signal = get_random_signal(len_signal, a_range = [0,0], signal_type = 'analog')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_sim = simulate_carnot_gp(df_wdb, df, random_signal, m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_sim"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure() \n",
    "plt.subplot(2,1,1)\n",
    "plt.plot(df_sim.index, df_sim['SimulatedTemp'], label = 'Simulated Temperature')\n",
    "plt.plot(df.index, df['OutsideTemp'], '-.', label = 'Outside Temperature')\n",
    "plt.title('Temperatures')\n",
    "plt.legend()\n",
    "plt.subplot(2,1,2)\n",
    "plt.plot(df_sim['SimulatedHeat'], drawstyle = 'steps', label = 'Heat Input')\n",
    "plt.title('Heat Input')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize = (20, 5))\n",
    "plt.plot(df_sim.index, df_sim['SimulatedTemp'], label = 'Measured data')\n",
    "plt.plot(df_sim.index, df_sim['gpTemp'], label = 'Gaussian Process Prediction')\n",
    "plt.fill_between(\n",
    "    df_sim.index, \n",
    "    df_sim['gpTemp'] - 1.96 * np.sqrt(df_sim['gpVar']),\n",
    "    df_sim['gpTemp'] + 1.96 * np.sqrt(df_sim['gpVar']),\n",
    "    alpha = 0.2\n",
    ")\n",
    "plt.legend()\n",
    "plt.title(\"Gaussian Process Performance on new weather data with constant zero input\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "### GP prediction N steps ahead"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_sim"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_sim[['OutsideTemp', 'SolRad']]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_sc = get_scaled_df(df_sim, w_scaler, u_scaler, y_scaler)\n",
    "df_gpr = data_to_gpr(df_sc)\n",
    "\n",
    "df_input = df_gpr.drop(columns = ['u', 'y'])\n",
    "df_output = df_gpr['y']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_input = dfs_gpr_test[0].drop(columns = u_list + y_list)\n",
    "df_output = dfs_gpr_test[0][y_list]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "N_pred = 11"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "idx = 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_iter = df_input.iloc[idx:(idx + N_pred)].copy()\n",
    "df_iter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for idxx in range(N_pred - 1):\n",
    "    mean, var = m.predict_f(df_iter.iloc[idxx, :].to_numpy().reshape(1, -1))\n",
    "    df_iter.iloc[idxx + 1, 7] = mean.numpy().flatten()\n",
    "    df_iter.iloc[idxx + 1, 8] = df_iter.iloc[idxx, 7]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_iter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data_to_gpr(dfs_train[0], lags_list, col_lists)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_iter.index[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_iter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "u_lags"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mean_iter, var_iter = m.predict_f(df_iter.to_numpy())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure()\n",
    "plt.plot(df_iter.index, mean_iter.numpy(), 'o-', label = 'predicted', color = 'orange')\n",
    "plt.plot(df_output.iloc[idx:idx + N_pred], 'o-', label = 'measured', color = 'darkblue')\n",
    "plt.legend()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "nb_predictions = 10\n",
    "N_pred = 8"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure()\n",
    "plt.plot(df_output.iloc[:nb_predictions + N_pred], 'o-', label = 'measured', color = 'darkblue')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure()\n",
    "\n",
    "for idx in range(nb_predictions):\n",
    "    df_iter = df_input.iloc[idx:(idx + N_pred)].copy()\n",
    "    for idxx in range(N_pred - 1):\n",
    "        mean, var = m.predict_f(df_iter.iloc[idxx, :].to_numpy().reshape(1, -1))\n",
    "        df_iter.iloc[idxx + 1, 4] = mean.numpy().flatten()\n",
    "        mean, var = m.predict_f(df_iter.iloc[idxx, :].to_numpy().reshape(1, -1))\n",
    "        df_iter.iloc[idxx + 1, 7] = mean.numpy().flatten()\n",
    "        df_iter.iloc[idxx + 1, 8] = df_iter.iloc[idxx, 7]\n",
    "        \n",
    "    mean_iter, var_iter = m.predict_y(df_iter.to_numpy())\n",
    "    plt.plot(df_iter.index, mean_iter.numpy(), '.-', label = 'predicted', color = 'orange')\n",
    "plt.plot(df_output.iloc[:nb_predictions + N_pred], 'o-', label = 'measured', color = 'darkblue')\n",
    "plt.title(f\"Prediction over {N_pred} steps\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_input[['SolRad', 'OutsideTemp']].plot()"
   ]
  },
  {
   "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.9.4"
  },
  "toc-autonumbering": false,
  "toc-showmarkdowntxt": false,
  "toc-showtags": false
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
