{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "collapsed": false,
    "id": "M5NFqaGdb0pI",
    "outputId": "6cb93a7a-06ee-4bc6-fee7-edf15a26245c",
    "pycharm": {
     "is_executing": true,
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Defaulting to user installation because normal site-packages is not writeable\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: COVID19Py in ./.local/lib/python3.8/site-packages (0.3.0)\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Defaulting to user installation because normal site-packages is not writeable\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: lmfit in /usr/local/lib/python3.8/dist-packages (1.0.1)\r\n",
      "Requirement already satisfied: uncertainties>=3.0.1 in /usr/local/lib/python3.8/dist-packages (from lmfit) (3.1.4)\r\n",
      "Requirement already satisfied: asteval>=0.9.16 in /usr/local/lib/python3.8/dist-packages (from lmfit) (0.9.18)\r\n",
      "Requirement already satisfied: scipy>=1.2 in /usr/local/lib/python3.8/dist-packages (from lmfit) (1.7.3)\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: numpy>=1.16 in /usr/local/lib/python3.8/dist-packages (from lmfit) (1.21.5)\r\n",
      "Requirement already satisfied: future in /usr/lib/python3/dist-packages (from uncertainties>=3.0.1->lmfit) (0.18.2)\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Defaulting to user installation because normal site-packages is not writeable\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: covid-seird in ./.local/lib/python3.8/site-packages (0.0.8)\r\n",
      "Requirement already satisfied: lmfit in /usr/local/lib/python3.8/dist-packages (from covid-seird) (1.0.1)\r\n",
      "Requirement already satisfied: requests in /usr/local/lib/python3.8/dist-packages (from covid-seird) (2.27.1)\r\n",
      "Requirement already satisfied: pandas in /usr/local/lib/python3.8/dist-packages (from covid-seird) (1.4.2)\r\n",
      "Requirement already satisfied: matplotlib in /usr/local/lib/python3.8/dist-packages (from covid-seird) (3.5.1)\r\n",
      "Requirement already satisfied: scipy in /usr/local/lib/python3.8/dist-packages (from covid-seird) (1.7.3)\r\n",
      "Requirement already satisfied: numpy in /usr/local/lib/python3.8/dist-packages (from covid-seird) (1.21.5)\r\n",
      "Requirement already satisfied: COVID19Py in ./.local/lib/python3.8/site-packages (from covid-seird) (0.3.0)\r\n",
      "Requirement already satisfied: asteval>=0.9.16 in /usr/local/lib/python3.8/dist-packages (from lmfit->covid-seird) (0.9.18)\r\n",
      "Requirement already satisfied: uncertainties>=3.0.1 in /usr/local/lib/python3.8/dist-packages (from lmfit->covid-seird) (3.1.4)\r\n",
      "Requirement already satisfied: pyparsing>=2.2.1 in /usr/local/lib/python3.8/dist-packages (from matplotlib->covid-seird) (2.4.7)\r\n",
      "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/lib/python3/dist-packages (from matplotlib->covid-seird) (1.0.1)\r\n",
      "Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.8/dist-packages (from matplotlib->covid-seird) (2.8.1)\r\n",
      "Requirement already satisfied: pillow>=6.2.0 in /usr/local/lib/python3.8/dist-packages (from matplotlib->covid-seird) (9.1.0)\r\n",
      "Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.8/dist-packages (from matplotlib->covid-seird) (4.25.2)\r\n",
      "Requirement already satisfied: cycler>=0.10 in /usr/lib/python3/dist-packages (from matplotlib->covid-seird) (0.10.0)\r\n",
      "Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.8/dist-packages (from matplotlib->covid-seird) (21.3)\r\n",
      "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.8/dist-packages (from pandas->covid-seird) (2021.3)\r\n",
      "Requirement already satisfied: charset-normalizer~=2.0.0 in /usr/local/lib/python3.8/dist-packages (from requests->covid-seird) (2.0.2)\r\n",
      "Requirement already satisfied: urllib3<1.27,>=1.21.1 in /usr/local/lib/python3.8/dist-packages (from requests->covid-seird) (1.26.7)\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.8/dist-packages (from requests->covid-seird) (2021.10.8)\r\n",
      "Requirement already satisfied: idna<4,>=2.5 in /usr/lib/python3/dist-packages (from requests->covid-seird) (2.8)\r\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.8/dist-packages (from python-dateutil>=2.7->matplotlib->covid-seird) (1.15.0)\r\n",
      "Requirement already satisfied: future in /usr/lib/python3/dist-packages (from uncertainties>=3.0.1->lmfit->covid-seird) (0.18.2)\r\n"
     ]
    }
   ],
   "source": [
    "!pip install COVID19Py\n",
    "!pip install lmfit\n",
    "!pip install covid-seird"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## Simulation\n",
    "\n",
    "We implement three models SIR, SEIR and SEIRD to predict confirmed cases and plot curves for susceptible, exposed, recovered and dead cases. We divide our implementation into three parts. The first part is data preparation. We utilize COVID19Py library to fetch global COVID\\-19 data from Johns Hopkins University database. We store useful information i.e. confirmed cases, date and country population into data.json file. Users can select the model, define the country and set the number of prediction days. Our algorithm splits the total data into two parts. One part is for fitting the models and the other is for comparing with predicted data. The second part of our simulator is to fit the model. We define our model with differential equations and set initial parameters for $\\alpha$, $\\beta$,$\\gamma$, $\\delta$ and $\\rho$. By passing fitting data to the chosen model, we update the parameters. The third part is the prediction part. We utilize the model with parameters obtained from the last step to make predictions for infected cases.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "collapsed": false,
    "id": "kcRKot20cFOz",
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
   ],
   "source": [
    "from typing import Dict\n",
    "import COVID19Py\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "from lmfit import Model, Parameters\n",
    "from scipy.integrate import odeint\n",
    "from scipy.stats import linregress"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false,
    "id": "yebd2NQpz_E3",
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
   ],
   "source": [
    "\"\"\"\n",
    "Global Variables\n",
    "\"\"\"\n",
    "prediction_days = 100\n",
    "country = \"US\"\n",
    "modelName = \"SEIRD\"\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false,
    "id": "fyQr6yRTYYDM",
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
   ],
   "source": [
    "def get_covid_data(code: str):\n",
    "    CovidData = COVID19Py.COVID19(data_source=\"jhu\")\n",
    "    CovidDataForOneCountry = CovidData.getLocationByCountryCode(code.upper(), timelines=True)\n",
    "#     print(CovidDataForOneCountry)\n",
    "\n",
    "    timespan = 825\n",
    "    # get date\n",
    "    date = list(CovidDataForOneCountry[0][\"timelines\"][\"confirmed\"][\"timeline\"].keys())[-timespan:]\n",
    "    # get confirmed cumulative cases\n",
    "    confirmed_cumulative_cases = list(CovidDataForOneCountry[0][\"timelines\"][\"confirmed\"][\"timeline\"].values())[-timespan:]\n",
    "    # get death cumulative cases\n",
    "    death_cumulative_cases = list(CovidDataForOneCountry[0][\"timelines\"][\"deaths\"][\"timeline\"].values())[-timespan:]\n",
    "    # get country population\n",
    "    country_population = CovidDataForOneCountry[0][\"country_population\"]\n",
    "\n",
    "    # generate dict to store covid data for one specific country\n",
    "    CovidDataForOneCountryDict = {\"date\": date, \"country_population\": country_population, \"confirmed\": confirmed_cumulative_cases, \"deaths\": death_cumulative_cases}\n",
    "#     print(CovidDataForOneCountryDict)\n",
    "\n",
    "    import json\n",
    "    # create json object from dictionary\n",
    "    json = json.dumps(CovidDataForOneCountryDict)\n",
    "\n",
    "    # open file for writing, \"w\" \n",
    "    f = open(str(country)+\"_data.json\",\"w\")\n",
    "\n",
    "    # write json object to file\n",
    "    f.write(json)\n",
    "\n",
    "    # close file\n",
    "    f.close()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false,
    "id": "Doo8o1K-pbYZ",
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
   ],
   "source": [
    "def get_fit_data():\n",
    "  import json\n",
    "  # Opening JSON file\n",
    "  f = open(str(country)+\"_data.json\")\n",
    "\n",
    "  # returns JSON object as a dictionary\n",
    "  data = json.load(f);\n",
    "  fit_days = len(data[\"date\"]) - prediction_days\n",
    "  # print(len(data[\"date\"]))\n",
    "  data[\"date\"] = data[\"date\"][0:fit_days];\n",
    "  data[\"confirmed\"] = data[\"confirmed\"][0:fit_days];\n",
    "  # print(len(data[\"date\"]))\n",
    "  # print(data)\n",
    "\n",
    "\n",
    "  # Closing file\n",
    "  f.close()\n",
    "\n",
    "\n",
    "  # create json object from dictionary\n",
    "  json = json.dumps(data)\n",
    "\n",
    "  # open file for writing, \"w\"\n",
    "  f = open(\"fit_\"+str(country)+\"_data.json\",\"w\")\n",
    "\n",
    "  # write json object to file\n",
    "  f.write(json)\n",
    "\n",
    "  # close file\n",
    "  f.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false,
    "id": "e_fJKtj8ppgc",
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
   ],
   "source": [
    "# Get and save data\n",
    "get_covid_data(country);\n",
    "get_fit_data();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false,
    "id": "4tKL_Z-pDGK2",
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
   ],
   "source": [
    "\"\"\"\n",
    "Disease Prediction Model\n",
    "(SIR, SEIR, SEIRD)\n",
    "\n",
    "S: number of susceptible people on day t\n",
    "E: number of exposed people on day t\n",
    "I: number of infected people on day t\n",
    "R: number of recovered people on day t\n",
    "D: number of dead people on day t\n",
    "\n",
    "beta: expected amount of people an infected person infects per day\n",
    "gamma: the proportion of infected recovering per day\n",
    "ro: the total number of people an infected person infects \n",
    "\n",
    "\"\"\"\n",
    "\n",
    "\n",
    "\n",
    "def model_we_use(x, r0, gamma, delta, alpha, rho, population, fit, initial_infected):\n",
    "    def deriv(y, x, r0, gamma, delta, alpha, rho):\n",
    "      beta = r0 * gamma\n",
    "      if modelName == \"SIR\":\n",
    "        S, I, R = y\n",
    "        dSdt = -beta * S * I / population\n",
    "        dIdt = beta * S* I / population - gamma * I\n",
    "        dRdt = gamma * I\n",
    "        return dSdt,  dIdt, dRdt\n",
    "      elif modelName == \"SEIR\":\n",
    "        S, E, I, R = y\n",
    "        dSdt = -beta * S * I / population\n",
    "        dEdt = beta * S* I / population - delta * E\n",
    "        dIdt = delta * E - gamma * I\n",
    "        dRdt = gamma * I\n",
    "        return dSdt, dEdt, dIdt, dRdt\n",
    "\n",
    "      elif modelName == \"SEIRD\":\n",
    "        S, E, I, R, D = y\n",
    "        dSdt = -beta * S * I / population\n",
    "        dEdt = beta * S * I / population - delta * E\n",
    "        dIdt = delta * E - (1 - alpha) * gamma * I - alpha * rho * I\n",
    "        dRdt = (1 - alpha) * gamma * I\n",
    "        dDdt = alpha * rho * I\n",
    "        return dSdt, dEdt, dIdt, dRdt, dDdt\n",
    "\n",
    "    if modelName == \"SIR\":\n",
    "      I0 = initial_infected \n",
    "      S0 = population - I0\n",
    "      R0 = 0.0\n",
    "      y0 = [S0, I0, R0]\n",
    "      S, I, R = odeint(deriv, y0, x, args=(r0, gamma, delta, alpha, rho)).T  \n",
    "      return I if fit==True else [S,I,R]\n",
    "    elif modelName == \"SEIR\":\n",
    "      I0 = initial_infected \n",
    "      R0 = 0.0\n",
    "      E0 = I0\n",
    "      S0 = population - I0 - R0\n",
    "      y0 = [S0, E0, I0, R0]\n",
    "      S, E, I, R = odeint(deriv, y0, x, args=(r0, gamma, delta, alpha, rho)).T  \n",
    "      return I if fit==True else [S, E, I, R]\n",
    "    elif modelName == \"SEIRD\":\n",
    "      I0 = initial_infected \n",
    "      R0 = 0.0\n",
    "      S0 = population - R0 - I0\n",
    "      E0 = I0\n",
    "      D0 = 0.0\n",
    "      y0 = [S0, E0, I0, R0, D0]\n",
    "      S, E, I, R, D= odeint(deriv, y0, x, args=(r0, gamma, delta, alpha, rho)).T  \n",
    "      return I if fit ==True else [S,E,I,R,D]\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false,
    "id": "bQAwTJmyZQsj",
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
   ],
   "source": [
    "\"\"\"Fit the real data into the model.\"\"\"\n",
    "\n",
    "\n",
    "import json\n",
    "\n",
    "def fit(init_r0, init_gamma, init_delta, init_alpha, init_rho, plot=True):\n",
    "\n",
    "    # Opening JSON file\n",
    "    f = open(\"fit_\"+str(country)+\"_data.json\")\n",
    "    # returns JSON object as a dictionary\n",
    "    data = json.load(f);\n",
    "\n",
    "    # Closing file\n",
    "    f.close()\n",
    "\n",
    "    x = np.linspace(0.0, len(np.array(data[\"confirmed\"])), len(np.array(data[\"confirmed\"])))\n",
    "\n",
    "    params = Parameters()\n",
    "    params.add(\"r0\", value= init_r0, min=0.0)\n",
    "    params.add(\"gamma\", value=init_gamma, min=0.0, max=1)\n",
    "    params.add(\"delta\", value=init_delta, min=0.0, max=1)\n",
    "    params.add(\"alpha\", value=init_alpha, min=0.0, max=1)\n",
    "    params.add(\"rho\", value=init_rho, min=0.0, max=1)\n",
    "    params.add(\"population\", value=data[\"country_population\"], vary=False)\n",
    "    params.add(\"fit\", value=True, vary=False)\n",
    "    params.add(\"initial_infected\", value=1000, vary = False) \n",
    "     \n",
    "    model_return = Model(model_we_use)\n",
    "    model_return = model_return.fit(np.array(data[\"confirmed\"]), params, x=x)\n",
    "    \n",
    "    if plot:\n",
    "        plt.figure(figsize=(12, 6))\n",
    "        plt.plot_date(pd.to_datetime(data[\"date\"]), data[\"confirmed\"], \"-\")\n",
    "        plt.plot(pd.to_datetime(data[\"date\"]), model_return.best_fit)\n",
    "        # print(model_return.best_fit)\n",
    "        plt.legend([\"real data\", \"fit data\",])\n",
    "        if modelName == \"SIR\":\n",
    "            plt.title(\"SIR model fit\")\n",
    "        elif modelName == \"SEIR\":\n",
    "            plt.title(\"SEIR model fit\")\n",
    "        else:\n",
    "            plt.title(\"SEIRD model fit\")\n",
    "\n",
    "        plt.xlabel(\"time\")\n",
    "        plt.ylabel(\"population\")\n",
    "        plt.show()\n",
    "        plt.close()\n",
    "        \n",
    "#     print(\"r0 \"+str(model_return.best_values[\"r0\"]) + \"  gamma \"+ str(model_return.best_values[\"gamma\"])+ \"  delta \"+str(model_return.best_values[\"delta\"])+ \"  alpha \" + str(model_return.best_values[\"alpha\"]) +  \" rho \"+ str(model_return.best_values[\"rho\"]))\n",
    "    return {\"r0\":model_return.best_values[\"r0\"] , \"gamma\": model_return.best_values[\"gamma\"], \"delta\": model_return.best_values[\"delta\"], \"alpha\": model_return.best_values[\"alpha\"], \"rho\": model_return.best_values[\"rho\"]}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false,
    "id": "oQy5B7DLaW6A",
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
   ],
   "source": [
    "def simulation(fit_model,plot=True):\n",
    "    # Opening JSON file\n",
    "    f_sim = open(str(country)+\"_data.json\")\n",
    "    f_fit = open(\"fit_\"+str(country)+\"_data.json\")\n",
    "\n",
    "    # returns JSON object as a dictionary\n",
    "    data = json.load(f_sim);\n",
    "    fit_data = json.load(f_fit)\n",
    "    \n",
    "    # Closing file\n",
    "    f_sim.close()\n",
    "    f_fit.close()\n",
    "\n",
    "    # normalized_cases = np.divide(np.array(data[\"confirmed\"]), data[\"country_population\"])\n",
    "    x = np.linspace(0.0, len(np.array(data[\"confirmed\"])), len(np.array(data[\"confirmed\"])))\n",
    "    if modelName == \"SEIRD\":\n",
    "        S, E, I, R, D = model_we_use(\n",
    "            x,\n",
    "            fit_model[\"r0\"],\n",
    "            fit_model[\"gamma\"],\n",
    "            fit_model[\"delta\"],\n",
    "            fit_model[\"alpha\"],\n",
    "            fit_model[\"rho\"],\n",
    "            population = data[\"country_population\"],\n",
    "            fit=False,\n",
    "            initial_infected = 1000 # fit_data[\"confirmed\"][-1]\n",
    "        )\n",
    "\n",
    "        # return {\"S\": S, \"E\": E, \"I\": I, \"R\": R, \"D\": D}\n",
    "    elif modelName == \"SEIR\":\n",
    "        S, E, I, R = model_we_use(\n",
    "            x,\n",
    "            fit_model[\"r0\"],\n",
    "            fit_model[\"gamma\"],\n",
    "            fit_model[\"delta\"],\n",
    "            fit_model[\"alpha\"],\n",
    "            fit_model[\"rho\"],\n",
    "            population = data[\"country_population\"],\n",
    "            fit=False,\n",
    "            initial_infected = 1000\n",
    "        )\n",
    "\n",
    "        # return {\"S\": S, \"E\": E, \"I\": I, \"R\": R}\n",
    "    else:\n",
    "        S, I, R = model_we_use(\n",
    "            x,\n",
    "            fit_model[\"r0\"],\n",
    "            fit_model[\"gamma\"],\n",
    "            fit_model[\"delta\"],\n",
    "            fit_model[\"alpha\"],\n",
    "            fit_model[\"rho\"],\n",
    "            population = data[\"country_population\"],\n",
    "            fit=False,\n",
    "            initial_infected = 1000\n",
    "\n",
    "        )\n",
    "        # return {\"S\": S, \"I\": I, \"R\": R}\n",
    "        \n",
    "        \n",
    "    if plot == True:\n",
    "        plt.figure(figsize=(12, 6))\n",
    "        plt.plot_date(pd.to_datetime(data[\"date\"]), S, \"-\")\n",
    "        if modelName != \"SIR\":\n",
    "            plt.plot_date(pd.to_datetime(data[\"date\"]), E, \"-\")\n",
    "        plt.plot_date(pd.to_datetime(data[\"date\"]), I, \"-\")\n",
    "        plt.plot_date(pd.to_datetime(data[\"date\"]), R, \"-\")\n",
    "        if modelName == \"SEIRD\":\n",
    "            plt.plot_date(pd.to_datetime(data[\"date\"]), D, \"-\")\n",
    "        plt.plot_date(pd.to_datetime(data[\"date\"]), data[\"confirmed\"], \"-\")\n",
    "\n",
    "\n",
    "        if modelName == \"SIR\":\n",
    "            plt.title(\"SIR model prediction\")\n",
    "            plt.legend([\"Susceptible\",\"Infected\",\"Recovered\",\"Real Confirmed\"],loc='upper right')\n",
    "        elif modelName == \"SEIR\":\n",
    "            plt.title(\"SEIR model prediction\")\n",
    "            plt.legend([\"Susceptible\",\"Exposed\",\"Infected\",\"Recovered\",\"Real Confirmed\"],loc='upper right')\n",
    "        else:\n",
    "            plt.title(\"SEIRD model prediction\")\n",
    "            plt.legend([\"Susceptible\",\"Exposed\",\"Infected\",\"Recovered\", \"Death\",\"Real Confirmed\"],loc='upper right')\n",
    "\n",
    "        plt.xlabel(\"time\")\n",
    "        plt.ylabel(\"population\")\n",
    "        plt.show()\n",
    "        plt.close()\n",
    "        print()\n",
    "#         plot_error(I, data[\"confirmed\"], data[\"date\"])\n",
    "\n",
    "    # return average prediction error\n",
    "#     print(cal_error(I, data[\"confirmed\"]))\n",
    "    return np.mean(cal_error(I, data[\"confirmed\"]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## 2. Experimental Results and Validation\n",
    "\n",
    "To compare the performance of these three models \\(SIR, SEIR, SEIRD\\),  we defined an indicator, average prediction error, to measure the degree of deviation between the predicted number of confirmed cases and the actual number of confirmed cases as below:\n",
    "$$Error = { \\frac {Predicted Cases - Actual Cases} {Actual Cases} }* 100\\%$$\n",
    "\n",
    "$$Average Error = \\frac{1}{Prediction Duration}\\Sigma Error$$\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
   ],
   "source": [
    "\"\"\"\n",
    "Calculate the prediction error\n",
    "\"\"\"\n",
    "\n",
    "def cal_error(predicted, real):\n",
    "    return np.abs(np.array(predicted[100:]) - np.array(real[100:]))/np.array(real[100:])*100\n",
    "\n",
    "\n",
    "\"\"\"\n",
    "Plot the error between real confirmed cases and predicted infected cases\n",
    "\"\"\"\n",
    "\n",
    "def plot_error(predicted, real, date):\n",
    "    plt.figure(1)\n",
    "    error = cal_error(predicted, real)\n",
    "    plt.plot_date(pd.to_datetime(date[100:]), error, \"-\")\n",
    "    plt.title(\"model prediction error\")\n",
    "    plt.xlabel(\"time\")\n",
    "    plt.ylabel(\"predict error %\")\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "### 2.1 Best Initial Parameter Searching\n",
    "\n",
    "As we introduced in previous section, there are several significant parameters in our model, which can influence the fitting and prediction performance. Although in the fit process, the best parameters will be searched again based on the initially set parameters, we found that the initial parameter configuration can also make a great difference on the final parameters. Therefore, it's still necessary to roughly search the best initial parameter vector for each model.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
   ],
   "source": [
    "\"\"\"\n",
    "Search the best initial parameters\n",
    "\"\"\"\n",
    "\n",
    "def search_param(countryName=\"US\", model=\"SEIRD\"):\n",
    "    global country\n",
    "    global modelName\n",
    "    \n",
    "    country =countryName\n",
    "    modelName =model\n",
    "    \n",
    "    test_r0s = np.arange(0.5, 1, 0.1)\n",
    "    test_gammas = np.arange(0.01, 0.1, 0.01)\n",
    "    test_deltas = np.arange(0.1, 1, 0.1)\n",
    "    test_alphas = np.arange(0.1, 1, 0.1)\n",
    "    test_rhos = np.arange(0.01, 0.1, 0.01)\n",
    "    \n",
    "    if model != \"SEIRD\":\n",
    "        test_alphas = [0.01]\n",
    "        test_rhos = [0.01]\n",
    "        if model == \"SIR\":\n",
    "            test_deltas = [0.01]\n",
    "            \n",
    "    # try to minimize the average prediction error\n",
    "    min_error = 100.0\n",
    "    best_param = [0.0, 0.0, 0.0, 0.0, 0.0]\n",
    "    \n",
    "    for r0 in test_r0s:\n",
    "        for gamma in test_gammas:\n",
    "            for delta in test_deltas:\n",
    "                for alpha in test_alphas:\n",
    "                    for rho in test_rhos:\n",
    "\n",
    "                        fit_model = fit(r0, gamma, delta, alpha, rho,False)\n",
    "                        error = simulation(fit_model,False)\n",
    "                        if min_error > error:\n",
    "                            min_error = error\n",
    "                            print(\"error:\",error, \"r0:\", r0, \"gamma:\", gamma, \"delta:\", delta, \"alpha:\", alpha, \"rho:\", rho)\n",
    "                            best_param = [r0, gamma, delta, alpha, rho]\n",
    "                            print()\n",
    "\n",
    "    return best_param\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 65.94654679771348 r0: 0.5 gamma: 0.01 delta: 0.01 alpha: 0.01 rho: 0.01\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 65.94650685773392 r0: 0.5 gamma: 0.03 delta: 0.01 alpha: 0.01 rho: 0.01\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 65.94647140920604 r0: 0.5 gamma: 0.060000000000000005 delta: 0.01 alpha: 0.01 rho: 0.01\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 65.94640058787472 r0: 0.6 gamma: 0.060000000000000005 delta: 0.01 alpha: 0.01 rho: 0.01\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 65.94639332694793 r0: 0.6 gamma: 0.09 delta: 0.01 alpha: 0.01 rho: 0.01\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 65.94244399181021 r0: 0.7 gamma: 0.02 delta: 0.01 alpha: 0.01 rho: 0.01\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Search best initial parameters for SIR model\n",
    "best_init_param_SIR = search_param(model=\"SIR\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 70.9282468032794 r0: 0.5 gamma: 0.01 delta: 0.1 alpha: 0.01 rho: 0.01\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 26.472188710182913 r0: 0.5 gamma: 0.01 delta: 0.2 alpha: 0.01 rho: 0.01\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 21.156536940757597 r0: 0.5 gamma: 0.02 delta: 0.30000000000000004 alpha: 0.01 rho: 0.01\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 21.044419333993826 r0: 0.5 gamma: 0.02 delta: 0.6 alpha: 0.01 rho: 0.01\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 21.002886801675174 r0: 0.5 gamma: 0.03 delta: 0.2 alpha: 0.01 rho: 0.01\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 20.89974947910221 r0: 0.5 gamma: 0.05 delta: 0.5 alpha: 0.01 rho: 0.01\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 19.98658043399132 r0: 0.5 gamma: 0.09 delta: 0.1 alpha: 0.01 rho: 0.01\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 19.893678450968938 r0: 0.5 gamma: 0.09 delta: 0.7000000000000001 alpha: 0.01 rho: 0.01\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 19.889468676697003 r0: 0.6 gamma: 0.060000000000000005 delta: 0.2 alpha: 0.01 rho: 0.01\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 19.878476813783216 r0: 0.7 gamma: 0.04 delta: 0.4 alpha: 0.01 rho: 0.01\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Search best initial parameters for SEIR model\n",
    "best_init_param_SEIR = search_param(model=\"SEIR\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 80.95613563169357 r0: 0.5 gamma: 0.01 delta: 0.1 alpha: 0.1 rho: 0.01\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 66.81990041719857 r0: 0.5 gamma: 0.01 delta: 0.1 alpha: 0.1 rho: 0.02\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 65.3500083850997 r0: 0.5 gamma: 0.01 delta: 0.1 alpha: 0.1 rho: 0.03\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 64.56906356686343 r0: 0.5 gamma: 0.01 delta: 0.1 alpha: 0.1 rho: 0.05\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 64.56815372782133 r0: 0.5 gamma: 0.01 delta: 0.1 alpha: 0.2 rho: 0.04\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 19.851047163137373 r0: 0.5 gamma: 0.01 delta: 0.1 alpha: 0.30000000000000004 rho: 0.01\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 19.848887912938146 r0: 0.5 gamma: 0.01 delta: 0.1 alpha: 0.30000000000000004 rho: 0.06999999999999999\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 19.829181295663084 r0: 0.5 gamma: 0.01 delta: 0.1 alpha: 0.4 rho: 0.02\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 19.82886158860554 r0: 0.5 gamma: 0.01 delta: 0.1 alpha: 0.5 rho: 0.08\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 19.828610160373415 r0: 0.5 gamma: 0.01 delta: 0.1 alpha: 0.7000000000000001 rho: 0.08\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Search best initial parameters for SEIRD model\n",
    "best_init_param_SERID = search_param(model=\"SEIRD\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "From the above searching, we get the best parameter vector \\[r0, gamma\\] = \\[0.7, 0.02\\] for SIR model, \\[r0, gamma, delta\\] = \\[0.7, 0.04, 0.4\\] for SEIR model, and \\[r0, gamma, delta, alpha, rho\\] = \\[0.5, 0.01, 0.1, 0.7, 0.08\\] for SEIRD model, which will be used in the following experiments.\n",
    "\n",
    "### 2.2 Comparison of Different Models\n",
    "\n",
    "With the best initial parameters found above, we implemented an experiment to compare the performance of different models. Here, we only executed the comparison on the Covid\\-19 data in United States, but similar comparison can be easy to do on any other countries. Some configuration of the experiment is shown below.\n",
    "\n",
    "| **Parameter** |**Value** |\n",
    "| :------------------: | :----------------------: |\n",
    "| Total Population |        327167434 |\n",
    "| Initial Infecteds |1000 |\n",
    "| Initial Exposeds |1000 |\n",
    "| Initial Recovereds |0 |\n",
    "| Initial Deads |0 |\n",
    "| Initial Susceptibles |Total Population - 1000 |\n",
    "| Prediction Duration |100 |\n",
    "\n",
    "Firstly, we set the prediction duration to 100 days, and the prediction duration actually is always the duration of past 100 days prior to today so that we will have real confirmed cases to measure the prediction performance. It should be noted that this part of the real data will not be used for data fitting.\n",
    "\n",
    "Before predicting the Covid-19 future trend, we will use the model we defined in the previous section to fit past Covid infection trends. In this process, the model parameters will be updated based on our initial parameters and the best parameters will be saved and used in the prediction. Then in the prediction step, we will use all of these 3 models and their corresponding best parameters to predict the \"susceptibles,\" \"infecteds,\" and \"recovereds\" in the future 100 days. In addition, the SEIR model will also predict the \"exposeds\", and SEIRD model will predict both \"exposeds\" and \"deads\" cases. As we introduced above, average predition error is used to measure and compare the performance of different models. The experiment result is shown below.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
   ],
   "source": [
    "\n",
    "\"\"\"\n",
    "Test 3 different model on any country's COVID-19 data\n",
    "\"\"\"\n",
    "\n",
    "def test_model(countryName=\"US\"):\n",
    "    global country\n",
    "    global modelName\n",
    "\n",
    "    prediction_days = 100\n",
    "    modelList = [\"SIR\", \"SEIR\", \"SEIRD\"]\n",
    "    country = countryName\n",
    "\n",
    "    \n",
    "    for j in range(3):\n",
    "        modelName = modelList[j]\n",
    "        if modelName == \"SIR\":\n",
    "            initial_param = best_init_param_SIR\n",
    "        elif modelName == \"SEIR\":\n",
    "            initial_param = best_init_param_SEIR\n",
    "        elif modelName == \"SEIRD\":\n",
    "            initial_param = best_init_param_SEIRD\n",
    "        print(\"                   Country: \" + country + \"  Model: \" + modelName+\"                     \")\n",
    "        print(\"#####################################################################\")\n",
    "        \n",
    "        fit_model = fit(initial_param[0],initial_param[1],initial_param[2],initial_param[3],initial_param[4])\n",
    "        error = simulation(fit_model)\n",
    "        print(\"Average Prediction Error of \"+modelName +\": \" + str(error)+\"%\\n\\n\")\n",
    "        print(\"#####################################################################\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "#####               Country: US  Model: SIR                     \n",
      "#####################################################################\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 70912 characters]",
      "text/plain": [
       "<Figure size 864x432 with 1 Axes>"
      ]
     },
     "execution_count": 30,
     "metadata": {
      "image/png": {
       "height": 386,
       "width": 710
      },
      "needs_background": "light"
     },
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 100404 characters]",
      "text/plain": [
       "<Figure size 864x432 with 1 Axes>"
      ]
     },
     "execution_count": 30,
     "metadata": {
      "image/png": {
       "height": 386,
       "width": 720
      },
      "needs_background": "light"
     },
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Average Prediction Error of SIR: 65.94244399181021%\n",
      "\n",
      "\n",
      "#####################################################################\n",
      "#####               Country: US  Model: SEIR                     \n",
      "#####################################################################\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 68412 characters]",
      "text/plain": [
       "<Figure size 864x432 with 1 Axes>"
      ]
     },
     "execution_count": 30,
     "metadata": {
      "image/png": {
       "height": 386,
       "width": 710
      },
      "needs_background": "light"
     },
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 93084 characters]",
      "text/plain": [
       "<Figure size 864x432 with 1 Axes>"
      ]
     },
     "execution_count": 30,
     "metadata": {
      "image/png": {
       "height": 386,
       "width": 720
      },
      "needs_background": "light"
     },
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Average Prediction Error of SEIR: 19.878476813783216%\n",
      "\n",
      "\n",
      "#####################################################################\n",
      "#####               Country: US  Model: SEIRD                     \n",
      "#####################################################################\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 68788 characters]",
      "text/plain": [
       "<Figure size 864x432 with 1 Axes>"
      ]
     },
     "execution_count": 30,
     "metadata": {
      "image/png": {
       "height": 386,
       "width": 710
      },
      "needs_background": "light"
     },
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 94332 characters]",
      "text/plain": [
       "<Figure size 864x432 with 1 Axes>"
      ]
     },
     "execution_count": 30,
     "metadata": {
      "image/png": {
       "height": 386,
       "width": 720
      },
      "needs_background": "light"
     },
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Average Prediction Error of SEIRD: 19.82870181822331%\n",
      "\n",
      "\n",
      "#####################################################################\n"
     ]
    }
   ],
   "source": [
    "best_init_param_SIR = [0.7, 0.02, 0.01, 0.01, 0.01]\n",
    "best_init_param_SEIR = [0.7, 0.04, 0.4, 0.01, 0.01]\n",
    "best_init_param_SEIRD = [1.0, 0.01, 0.1, 0.7, 0.08]\n",
    "\n",
    "# Experiment\n",
    "test_model(\"US\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "From the experiment results, it's obvious that the SEIRD has the best performance among these models and SIR is the worst model. The comparison of three models' average prediction error is shown in below table.\n",
    "\n",
    "| **Model** |SIR |SEIR|SEIRD|\n",
    "| :---------------------: | :---: | :---: | :---: |\n",
    "| **Average Error (%)** |     65.94|     19.88 |     19.83|\n",
    "\n",
    "Such results is easy to understand because SEIRD model is closest to the real situation among the three models. While the SIR model even cannot fit the known data very well, so the poor performance on the prediction duration is reasonable. \n",
    "\n",
    "However, even the SERID model cannot predict the future trends with complete accuracy, One of the main reasons is the new coronavirus is still in constant mutation, and the infectivity of different mutated virus subtypes is also changing. For example, since the emergence of the Omicron mutation, the infectivity of the virus has increased significantly, resulting in an accelerated growth in the number of confirmed cases, making the our model generated by fitting previous data unable to predict the its expanding trend accurately.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## 3. Conclusions\n",
    "\n",
    "We notice obvious decrease in the average prediction error by comparing three models. Thus, we conclude that using SEIRD model to simulate COVID\\-19 is a credible approach. Although there are many factors which might influence the prediction accuracy, through trade\\-off between prediction accuracy and computation time, we believe using SEIRD model is a good choice.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## 4. References\n",
    "\n",
    "\\[1\\] World Health Organization. \\(n.d.\\). Coronavirus disease \\(covid\\-19\\): How is it transmitted? World Health Organization. Retrieved April 29, 2022, from https://www.who.int/news\\-room/questions\\-and\\-answers/item/coronavirus\\-disease\\-covid\\-19\\-how\\-is\\-it\\-transmitted \n",
    "\n",
    "\\[2\\] Tolles J, Luong T. Modeling Epidemics With Compartmental Models. JAMA. 2020;323\\(24\\):2515–2516. doi:10.1001/jama.2020.8420\n",
    "\n",
    "\\[3\\] Harko T, Lobo FS, Mak MK \\(2014\\). \"Exact analytical solutions of the Susceptible\\-Infected\\-Recovered \\(SIR\\) epidemic model and of the SIR model with equal death and birth rates\". Applied Mathematics and Computation. 236: 184–194. arXiv:1403.2160. Bibcode:2014arXiv1403.2160H. doi:10.1016/j.amc.2014.03.030. S2CID 14509477\n",
    "\n",
    "\\[4\\] Beckley R, Weatherspoon C, Alexander M, Chandler M, Johnson A, Bhatt GS \\(2013\\). \"Modeling epidemics with differential equations\" \\(PDF\\). Tennessee State University Internal Report. Retrieved July 19, 2020.\n",
    "\n",
    "\\[5\\] Kröger M, Schlickeiser R \\(2020\\). \"Analytical solution of the SIR\\-model for the temporal evolution of epidemics. Part A: Time\\-independent reproduction factor\". Journal of Physics A. 53 \\(50\\): 505601. Bibcode:2020JPhA...53X5601K. doi:10.1088/1751\\-8121/abc65d. S2CID 225555567.\n",
    "\n",
    "\\[6\\] Schlickeiser R, Kröger M \\(2021\\). \"Analytical solution of the SIR\\-model for the temporal evolution of epidemics. Part B: Semi\\-time case\". Journal of Physics A. 54 \\(17\\): 175601. Bibcode:2021JPhA...54X5601S. doi:10.1088/1751\\-8121/abed66.\n",
    "\n",
    "\\[7\\] Real Python. \\(2022, March 30\\). Python GUI programming with Tkinter. Real Python. Retrieved April 29, 2022, from https://realpython.com/python\\-gui\\-tkinter/ \n",
    "\n",
    "\\[8\\] Moein, S., Nickaeen, N., Roointan, A. et al. Inefficiency of SIR models in forecasting COVID\\-19 epidemic: a case study of Isfahan. Sci Rep 11, 4725 \\(2021\\). [https://doi.org/10.1038/s41598\\-021\\-84055\\-6](https://doi.org/10.1038/s41598-021-84055-6).\n",
    "\n",
    "\\[9\\] J. Ge, L. Zhang, Z. Chen, G. Chen and J. Peng, \"Simulation Analysis of Epidemic Trend for COVID\\-19 Based on SEIRS Model,\" 2020 IEEE 19th International Conference on Cognitive Informatics & Cognitive Computing \\(ICCI\\*CC\\), 2020, pp. 158\\-161, doi: 10.1109/ICCICC50026.2020.9450226.\n",
    "\n",
    "\\[10\\] A. Sedaghat, S. Band, A. Mosavi and L. Nadai, \"Predicting COVID\\-19 \\(Coronavirus Disease\\) Outbreak Dynamics Using SIR\\-based Models: Comparative Analysis of SIRD and Weibull\\-SIRD,\" 2020 IEEE 3rd International Conference and Workshop in Óbuda on Electrical and Power Engineering \\(CANDO\\-EPE\\), 2020, pp. 000283\\-000288, doi: 10.1109/CANDO\\-EPE51100.2020.9337791.\n",
    "\n",
    "\\[11\\] N. Darapaneni et al., \"Coronavirus Outburst Prediction in India using SEIRD, Logistic Regression and ARIMA Model,\" 2020 11th IEEE Annual Ubiquitous Computing, Electronics & Mobile Communication Conference \\(UEMCON\\), 2020, pp. 0649\\-0655, doi: 10.1109/UEMCON51285.2020.9298097.\n",
    "\n",
    "\\[12\\] K. Joshi and Y. Prasad, \"An Improved ISEIRD Model for COVID\\-19 Trend Simulations,\" 2021 IEEE 2nd International Conference on Smart Technologies for Power, Energy and Control \\(STPEC\\), 2021, pp. 1\\-5, doi: 10.1109/STPEC52385.2021.9718677.\n",
    "\n",
    "\\[13\\] Froese, H. \\(2020, April 22\\). Infectious disease modelling: Beyond the basic sir model. Medium. Retrieved April 29, 2022, from https://towardsdatascience.com/infectious\\-disease\\-modelling\\-beyond\\-the\\-basic\\-sir\\-model\\-216369c584c4 \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 0,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
   ],
   "source": [
   ]
  }
 ],
 "metadata": {
  "colab": {
   "collapsed_sections": [
   ],
   "name": "covid_seird",
   "provenance": [
   ]
  },
  "kernelspec": {
   "display_name": "Python 3 (system-wide)",
   "language": "python",
   "metadata": {
    "cocalc": {
     "description": "Python 3 programming language",
     "priority": 100,
     "url": "https://www.python.org/"
    }
   },
   "name": "python3",
   "resource_dir": "/ext/jupyter/kernels/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.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}