Now using py files, for automation
[covid19.git] / publish.ipynb
diff --git a/publish.ipynb b/publish.ipynb
new file mode 100644 (file)
index 0000000..99b4bef
--- /dev/null
@@ -0,0 +1,823 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "source": [
+    "Data from [European Centre for Disease Prevention and Control](https://www.ecdc.europa.eu/en/publications-data/download-todays-data-geographic-distribution-covid-19-cases-worldwide)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 192,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "The sql extension is already loaded. To reload it, use:\n",
+      "  %reload_ext sql\n"
+     ]
+    }
+   ],
+   "source": [
+    "import itertools\n",
+    "import collections\n",
+    "import json\n",
+    "import pandas as pd\n",
+    "import numpy as np\n",
+    "from scipy.stats import gmean\n",
+    "import datetime\n",
+    "\n",
+    "import matplotlib as mpl\n",
+    "import matplotlib.pyplot as plt\n",
+    "%matplotlib inline\n",
+    "%load_ext sql"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 193,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "connection_string = 'postgresql://covid:3NbjJTkT63@localhost/covid'"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 194,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'Connected: covid@covid'"
+      ]
+     },
+     "execution_count": 194,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "%sql $connection_string"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 195,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "# DEATH_COUNT_THRESHOLD = 10\n",
+    "COUNTRIES_CORE = tuple('IT DE UK ES IE FR BE'.split())\n",
+    "# COUNTRIES_NORDIC = 'SE NO DK FI UK'.split()\n",
+    "# COUNTRIES_FRIENDS = 'IT UK ES BE SI MX'.split()\n",
+    "# # COUNTRIES_FRIENDS = 'IT UK ES BE SI PT'.split()\n",
+    "\n",
+    "# COUNTRIES_AMERICAS = ['AG', 'AR', 'AW', 'BS', 'BB', 'BZ', 'BM', 'BO', 'BR', 'VG', 'KY', # excluding Canada and USA\n",
+    "#        'CL', 'CO', 'CR', 'CU', 'CW', 'DM', 'DO', 'EC', 'SV', 'GL', 'GD', 'GT',\n",
+    "#        'GY', 'HT', 'HN', 'JM', 'MX', 'MS', 'NI', 'PA', 'PY', 'PE', 'PR', 'KN',\n",
+    "#        'LC', 'VC', 'SX', 'SR', 'TT', 'TC', 'VI', 'UY', 'VE']\n",
+    "# COUNTRIES_OF_INTEREST = list(set(COUNTRIES_CORE + COUNTRIES_FRIENDS))\n",
+    "# COUNTRIES_ALL = list(set(COUNTRIES_CORE + COUNTRIES_FRIENDS + COUNTRIES_NORDIC + COUNTRIES_AMERICAS))"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "source": [
+    "# Write results to summary file"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 196,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      " * postgresql://covid:***@localhost/covid\n",
+      "1 rows affected.\n"
+     ]
+    },
+    {
+     "data": {
+      "text/plain": [
+       "datetime.date(2021, 1, 26)"
+      ]
+     },
+     "execution_count": 196,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "last_uk_date = %sql select date from uk_data order by date desc limit 1\n",
+    "last_uk_date = last_uk_date[0][0]\n",
+    "last_uk_date"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 197,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      " * postgresql://covid:***@localhost/covid\n",
+      "1 rows affected.\n"
+     ]
+    },
+    {
+     "data": {
+      "text/plain": [
+       "datetime.date(2021, 1, 18)"
+      ]
+     },
+     "execution_count": 197,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "last_intl_date = %sql select report_date from weekly_cases order by report_date desc limit 1\n",
+    "last_intl_date = last_intl_date[0][0]\n",
+    "last_intl_date"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 198,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      " * postgresql://covid:***@localhost/covid\n",
+      "390 rows affected.\n",
+      "Returning data to local variable results\n"
+     ]
+    }
+   ],
+   "source": [
+    "%%sql results << select date, new_cases, new_deaths \n",
+    "from uk_data \n",
+    "order by date"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 199,
+   "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>new_cases</th>\n",
+       "      <th>new_deaths</th>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>date</th>\n",
+       "      <th></th>\n",
+       "      <th></th>\n",
+       "    </tr>\n",
+       "  </thead>\n",
+       "  <tbody>\n",
+       "    <tr>\n",
+       "      <th>2021-01-17</th>\n",
+       "      <td>28875.0</td>\n",
+       "      <td>671</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2021-01-18</th>\n",
+       "      <td>44732.0</td>\n",
+       "      <td>599</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2021-01-19</th>\n",
+       "      <td>39311.0</td>\n",
+       "      <td>1610</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2021-01-20</th>\n",
+       "      <td>35015.0</td>\n",
+       "      <td>1820</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2021-01-21</th>\n",
+       "      <td>31430.0</td>\n",
+       "      <td>1290</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2021-01-22</th>\n",
+       "      <td>29094.0</td>\n",
+       "      <td>1401</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2021-01-23</th>\n",
+       "      <td>20495.0</td>\n",
+       "      <td>1348</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2021-01-24</th>\n",
+       "      <td>14266.0</td>\n",
+       "      <td>610</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2021-01-25</th>\n",
+       "      <td>4482.0</td>\n",
+       "      <td>592</td>\n",
+       "    </tr>\n",
+       "    <tr>\n",
+       "      <th>2021-01-26</th>\n",
+       "      <td>NaN</td>\n",
+       "      <td>1631</td>\n",
+       "    </tr>\n",
+       "  </tbody>\n",
+       "</table>\n",
+       "</div>"
+      ],
+      "text/plain": [
+       "            new_cases  new_deaths\n",
+       "date                             \n",
+       "2021-01-17    28875.0         671\n",
+       "2021-01-18    44732.0         599\n",
+       "2021-01-19    39311.0        1610\n",
+       "2021-01-20    35015.0        1820\n",
+       "2021-01-21    31430.0        1290\n",
+       "2021-01-22    29094.0        1401\n",
+       "2021-01-23    20495.0        1348\n",
+       "2021-01-24    14266.0         610\n",
+       "2021-01-25     4482.0         592\n",
+       "2021-01-26        NaN        1631"
+      ]
+     },
+     "execution_count": 199,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "uk_data = results.DataFrame()\n",
+    "uk_data['date'] = uk_data.date.astype('datetime64[ns]')\n",
+    "uk_data.set_index('date', inplace=True)\n",
+    "uk_data.tail(10)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 200,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      " * postgresql://covid:***@localhost/covid\n",
+      "1 rows affected.\n"
+     ]
+    },
+    {
+     "data": {
+      "text/plain": [
+       "datetime.date(2021, 1, 26)"
+      ]
+     },
+     "execution_count": 200,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "most_recent_uk_date = %sql select max(date) from uk_data\n",
+    "most_recent_uk_date = most_recent_uk_date[0][0]\n",
+    "most_recent_uk_date"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 201,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      " * postgresql://covid:***@localhost/covid\n",
+      "7 rows affected.\n",
+      "Returning data to local variable results\n"
+     ]
+    }
+   ],
+   "source": [
+    "%%sql results << select geo_id, country_name, culm_deaths \n",
+    "from weekly_cases join countries using (geo_id)\n",
+    "where geo_id in :COUNTRIES_CORE \n",
+    "    and (geo_id, report_date) in (select geo_id, max(report_date) from weekly_cases group by geo_id)\n",
+    "order by geo_id"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 202,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "datetime.date(2020, 12, 27)"
+      ]
+     },
+     "execution_count": 202,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "thirty_days_ago = most_recent_uk_date - datetime.timedelta(days=30)\n",
+    "thirty_days_ago"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 203,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      " * postgresql://covid:***@localhost/covid\n",
+      "1 rows affected.\n",
+      " * postgresql://covid:***@localhost/covid\n",
+      "1 rows affected.\n",
+      " * postgresql://covid:***@localhost/covid\n",
+      "1 rows affected.\n"
+     ]
+    },
+    {
+     "data": {
+      "text/plain": [
+       "(100184, 29366, 1283174)"
+      ]
+     },
+     "execution_count": 203,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "# thirty_days_ago = most_recent_uk_date - datetime.interval(days=30)\n",
+    "total_uk_deaths = %sql select sum(new_deaths) from uk_data\n",
+    "total_uk_deaths = total_uk_deaths[0][0]\n",
+    "deaths_in_past_month = %sql select sum(new_deaths) from uk_data where date > :thirty_days_ago\n",
+    "deaths_in_past_month = deaths_in_past_month[0][0]\n",
+    "cases_in_past_month = %sql select sum(new_cases) from uk_data where date > :thirty_days_ago\n",
+    "cases_in_past_month = cases_in_past_month[0][0]\n",
+    "total_uk_deaths, deaths_in_past_month, cases_in_past_month"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 204,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "with open('covid_summary.md', 'w') as f:\n",
+    "    f.write('% Covid death data summary\\n')\n",
+    "    f.write('% Neil Smith\\n')\n",
+    "    f.write(f'% Created on {datetime.datetime.now().strftime(\"%Y-%m-%d\")}\\n')\n",
+    "    f.write('\\n')       \n",
+    "    f.write(f'> Last UK data from {last_uk_date.strftime(\"%d %b %Y\")}. ')\n",
+    "    f.write(f' Last international data from {last_intl_date.strftime(\"%d %b %Y\")}.\\n')\n",
+    "    f.write('\\n')    "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 205,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "with open('covid_summary.md', 'a') as f:\n",
+    "    f.write('## Headlines (UK data)\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('| []() | |\\n')\n",
+    "    f.write('|:---|---:|\\n')\n",
+    "    f.write(f'| Deaths reported so far | {total_uk_deaths} | \\n')\n",
+    "    f.write(f'| Deaths in last 30 days | {deaths_in_past_month} | \\n')\n",
+    "    f.write(f'| Cases in last 30 days  | {cases_in_past_month} | \\n')\n",
+    "#     f.write(f'| Total Covid deaths to date (estimated) | {uk_deaths_to_date:.0f} |\\n')\n",
+    "    f.write('\\n')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 206,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "with open('covid_summary.md', 'a') as f:\n",
+    "    f.write('## International comparison\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write(f'Based on weekly data. Last data from {last_intl_date.strftime(\"%d %b %Y\")}\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('### Total deaths\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('![Total deaths](covid_deaths_total_linear.png)\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('| Country ID | Country name | Total deaths |\\n')\n",
+    "    f.write('|:-----------|:-------------|-------------:|\\n')\n",
+    "    for c_id, c_name, t_deaths in results:\n",
+    "        f.write(f'| {c_id} | {c_name} | {t_deaths} |\\n')\n",
+    "    f.write('\\n')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 207,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "# with open('covid_summary.md', 'a') as f:\n",
+    "#     f.write('## All-causes deaths, UK\\n')\n",
+    "#     f.write('\\n')\n",
+    "#     f.write('![All-causes deaths](deaths-radar.png)\\n')\n",
+    "#     f.write('\\n')\n",
+    "#     f.write('### True deaths\\n')\n",
+    "#     f.write('\\n')\n",
+    "#     f.write(f'The number of deaths reported in official statistics, {uk_covid_deaths}, is an underestimate '\n",
+    "#             'of the true number of Covid deaths.\\n'\n",
+    "#             'This is especially true early in the pandemic, approximately March to May 2020.\\n')\n",
+    "#     f.write('We can get a better understanding of the impact of Covid by looking at the number of deaths, '\n",
+    "#             'over and above what would be expected at each week of the year.\\n')\n",
+    "#     f.write(f'The ONS (and other bodies in Scotland and Northern Ireland) have released data on the number of deaths '\n",
+    "#             f'up to {pd.to_datetime(excess_deaths_data[\"end_date\"]).strftime(\"%d %B %Y\")}.\\n\\n')\n",
+    "#     f.write('If, for each of those weeks, I take the largest of the excess deaths or the reported Covid deaths, ')\n",
+    "#     f.write(f'I estimate there have been **{uk_deaths_to_date}** total deaths so far.\\n')\n",
+    "#     f.write('\\n')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 208,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "with open('covid_summary.md', 'a') as f:\n",
+    "    f.write('### Deaths per week\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('![Deaths per week](covid_deaths_per_week.png)\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('![Deaths per week, last 6 weeks](deaths_by_date_last_6_weeks.png)\\n')\n",
+    "    f.write('\\n')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 209,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "with open('covid_summary.md', 'a') as f:\n",
+    "    f.write('## UK data\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('### Total deaths\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write(f'Deaths reported up to {last_uk_date.strftime(\"%d %b %Y\")}: {total_uk_deaths}\\n')\n",
+    "    f.write('\\n')    \n",
+    "    f.write('![Total deaths](cases_and_deaths.png)\\n')\n",
+    "    f.write('\\n')    \n",
+    "    f.write('![Cases and deaths in last 60 days](cases_and_deaths_last_60_days.png)\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('![Deaths compared to past five years](deaths-radar-2020.png)\\n')\n",
+    "    f.write('\\n')\n",
+    "    "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 210,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "with open('hospital_normalisation_date.json') as f:\n",
+    "    hospital_normalisation_date_data = json.load(f)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 211,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "with open('covid_summary.md', 'a') as f:\n",
+    "    f.write('### Hospital care\\n')\n",
+    "    f.write(f'Based on a 7-day moving average\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('![Cases, admissions, deaths](cases_admissions_deaths.png)\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('Due to the large scale differences between the three '\n",
+    "            'measures, they are all normalised to show changes ')\n",
+    "    f.write(f'since {pd.to_datetime(hospital_normalisation_date_data[\"hospital_normalisation_date\"]).strftime(\"%d %B %Y\")}.\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('People in hospital, and on mechanical ventilators\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('![People in hospital and on mechancial ventilators](people_in_hospital.png)\\n')\n",
+    "    f.write('\\n')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 212,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "with open('covid_summary.md', 'a') as f:\n",
+    "    f.write('### Testing effectiveness\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('A question about testing is whether more detected cases is a result of more tests being '\n",
+    "            'done or is because the number of cases is increasing. One way of telling the differeence '\n",
+    "            'is by looking at the fraction of tests that are positive.\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('![Positive tests and cases](tests_and_cases.png)\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('Numbers of positive tests and cases, '\n",
+    "            '7-day moving average.\\n'\n",
+    "            'Note the different y-axes\\n')\n",
+    "    f.write('\\n')    \n",
+    "    f.write('![Fraction of tests with positive result](fraction_positive_tests.png)\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('Fraction of tests with a positive result, both daily figures and '\n",
+    "            '7-day moving average.\\n')\n",
+    "    f.write('\\n')    \n",
+    "    f.write('\\n')\n",
+    "    f.write('![Tests against fraction positive, trajectory](fraction_positive_tests_vs_tests.png)\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('The trajectory of tests done vs fraction positive tests.\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('Points higher indicate more tests; points to the right indicate more positive tests.'\n",
+    "            'More tests being done with the same infection prevelance will move the point up '\n",
+    "            'and to the left.\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('![Tests against fraction positive, trajectory](tests_vs_fraction_positive_animation.png)\\n')\n",
+    "    f.write('\\n')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 213,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "with open('covid_summary.md', 'a') as f:\n",
+    "    f.write('# Data sources\\n')\n",
+    "    f.write('\\n')\n",
+    "    f.write('> Covid data from [European Centre for Disease Prevention and Control](https://www.ecdc.europa.eu/en/publications-data/download-todays-data-geographic-distribution-covid-19-cases-worldwide)\\n')\n",
+    "    f.write('\\n')    \n",
+    "    f.write(\"\"\"> Population data from:\n",
+    "\n",
+    "* [Office of National Statistics](https://www.ons.gov.uk/peoplepopulationandcommunity/birthsdeathsandmarriages/deaths/datasets/weeklyprovisionalfiguresondeathsregisteredinenglandandwales) (Endland and Wales) Weeks start on a Saturday.\n",
+    "* [Northern Ireland Statistics and Research Agency](https://www.nisra.gov.uk/publications/weekly-deaths) (Northern Ireland). Weeks start on a Saturday. Note that the week numbers don't match the England and Wales data.\n",
+    "* [National Records of Scotland](https://www.nrscotland.gov.uk/statistics-and-data/statistics/statistics-by-theme/vital-events/general-publications/weekly-and-monthly-data-on-births-and-deaths/weekly-data-on-births-and-deaths) (Scotland). Note that Scotland uses ISO8601 week numbers, which start on a Monday.\"\"\")\n",
+    "    \n",
+    "    f.write('\\n\\n')\n",
+    "    f.write('> [Source code available](https://git.njae.me.uk/?p=covid19.git;a=tree)\\n')\n",
+    "    f.write('\\n') \n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 214,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "!pandoc --toc -s covid_summary.md > covid_summary.html"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 215,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "covid_summary.html                            100%   10KB 287.3KB/s   00:00    \n",
+      "covid_deaths_total_linear.png                 100%   45KB   1.8MB/s   00:00    \n",
+      "cases_and_deaths.png                          100%   62KB   5.3MB/s   00:00    \n",
+      "cases_and_deaths_last_60_days.png             100%   62KB   8.4MB/s   00:00    \n",
+      "deaths-radar-2020.png                         100%  199KB   5.4MB/s   00:00    \n",
+      "covid_deaths_per_week.png                     100%   61KB   8.0MB/s   00:00    \n",
+      "fraction_positive_tests.png                   100%   59KB   2.8MB/s   00:00    \n",
+      "tests_and_cases.png                           100%   40KB   5.4MB/s   00:00    \n",
+      "deaths_by_date_last_6_weeks.png               100%   33KB   5.4MB/s   00:00    \n",
+      "fraction_positive_tests_vs_tests.png          100%   41KB   7.7MB/s   00:00    \n",
+      "tests_vs_fraction_positive_animation.png      100% 1982KB  10.3MB/s   00:00    \n",
+      "people_in_hospital.png                        100%   42KB   8.0MB/s   00:00    \n",
+      "cases_admissions_deaths.png                   100%   44KB   2.3MB/s   00:00    \n"
+     ]
+    }
+   ],
+   "source": [
+    "!scp covid_summary.html neil@ogedei:/var/www/scripts.njae.me.uk/covid/index.html\n",
+    "!scp covid_deaths_total_linear.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/\n",
+    "!scp cases_and_deaths.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/\n",
+    "!scp cases_and_deaths_last_60_days.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/\n",
+    "# !scp deaths-radar.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/\n",
+    "!scp deaths-radar-2020.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/\n",
+    "!scp covid_deaths_per_week.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/\n",
+    "!scp fraction_positive_tests.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/    \n",
+    "!scp tests_and_cases.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/\n",
+    "!scp deaths_by_date_last_6_weeks.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/\n",
+    "!scp fraction_positive_tests_vs_tests.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/\n",
+    "!scp tests_vs_fraction_positive_animation.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/   \n",
+    "!scp people_in_hospital.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/\n",
+    "!scp cases_admissions_deaths.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 216,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "with open('uk_covid_deaths.js', 'w') as f:\n",
+    "    f.write(f\"document.write('{total_uk_deaths}');\")\n",
+    "    \n",
+    "with open('uk_deaths_30_days.js', 'w') as f:\n",
+    "    f.write(f\"document.write('{deaths_in_past_month}');\")\n",
+    "\n",
+    "with open('uk_cases_30_days.js', 'w') as f:\n",
+    "    f.write(f\"document.write('{cases_in_past_month}');\")    \n",
+    "    \n",
+    "# with open('estimated_total_deaths.js', 'w') as f:\n",
+    "#     f.write(f\"document.write('{uk_deaths_to_date:.0f}');\")\n",
+    "\n",
+    "# edut = pd.to_datetime(excess_deaths_data[\"end_date\"]).strftime('%d %B %Y')\n",
+    "# with open('excess_deaths_upto.js', 'w') as f:\n",
+    "#     f.write(f\"document.write('{edut}');\")\n",
+    "    \n",
+    "with open('last_uk_date.js', 'w') as f:\n",
+    "    f.write(f\"document.write('{pd.to_datetime(last_uk_date).strftime('%d %B %Y')}');\")\n",
+    "\n",
+    "with open('last_intl_date.js', 'w') as f:\n",
+    "    f.write(f\"document.write('{pd.to_datetime(last_intl_date).strftime('%d %B %Y')}');\")\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 217,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "# pd.to_datetime(excess_deaths_upto).strftime('%d %B %Y')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 218,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "uk_covid_deaths.js                            100%   25     2.0KB/s   00:00    \n",
+      "uk_deaths_30_days.js                          100%   24     1.2KB/s   00:00    \n",
+      "uk_cases_30_days.js                           100%   26    21.3KB/s   00:00    \n",
+      "last_uk_date.js                               100%   34     2.4KB/s   00:00    \n",
+      "last_intl_date.js                             100%   34     3.8KB/s   00:00    \n",
+      "hospital_normalisation_date.js                100%   33    29.1KB/s   00:00    \n"
+     ]
+    }
+   ],
+   "source": [
+    "!scp uk_covid_deaths.js neil@ogedei:/var/www/scripts.njae.me.uk/covid/\n",
+    "!scp uk_deaths_30_days.js neil@ogedei:/var/www/scripts.njae.me.uk/covid/\n",
+    "!scp uk_cases_30_days.js neil@ogedei:/var/www/scripts.njae.me.uk/covid/\n",
+    "# !scp estimated_total_deaths.js neil@ogedei:/var/www/scripts.njae.me.uk/covid/\n",
+    "# !scp excess_deaths_upto.js neil@ogedei:/var/www/scripts.njae.me.uk/covid/\n",
+    "!scp last_uk_date.js neil@ogedei:/var/www/scripts.njae.me.uk/covid/\n",
+    "!scp last_intl_date.js neil@ogedei:/var/www/scripts.njae.me.uk/covid/\n",
+    "!scp hospital_normalisation_date.js neil@ogedei:/var/www/scripts.njae.me.uk/covid/"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "jupytext": {
+   "formats": "ipynb,md"
+  },
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.8.5"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}