9 jupytext_version: 1.3.4
11 display_name: Python 3
16 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)
24 from scipy.stats import gmean
27 import matplotlib as mpl
28 import matplotlib.pyplot as plt
33 DEATH_COUNT_THRESHOLD = 10
34 COUNTRIES_CORE = 'IT DE UK ES IE FR'.split()
35 COUNTRIES_NORDIC = 'SE NO DK FI UK'.split()
36 COUNTRIES_FRIENDS = 'IT UK ES BE SI MX'.split()
37 COUNTRIES_OF_INTEREST = list(set(COUNTRIES_CORE + COUNTRIES_FRIENDS))
38 COUNTRIES_ALL = list(set(COUNTRIES_CORE + COUNTRIES_FRIENDS + COUNTRIES_NORDIC))
42 !curl https://opendata.ecdc.europa.eu/covid19/casedistribution/csv/ > covid.csv
46 # First col is a date, treat geoId of NA as 'Namibia', not "NA" value
47 raw_data = pd.read_csv('covid.csv', parse_dates=[0], keep_default_na=False, dayfirst=True)
63 base_data = raw_data.set_index(['geoId', 'dateRep'])
64 base_data.sort_index(inplace=True)
73 base_data.loc['UK', '2020-04-17']
77 countries = raw_data[['geoId', 'countriesAndTerritories', 'popData2018']]
78 countries = countries[countries['popData2018'] != '']
79 countries = countries.drop_duplicates()
80 countries.set_index('geoId', inplace=True)
81 countries = countries.astype({'popData2018': 'int64'})
90 countries[countries.countriesAndTerritories == 'Finland']
94 countries.loc[COUNTRIES_OF_INTEREST]
98 data_by_date = base_data[['cases', 'deaths']]
103 data_by_date.loc['UK']
107 data_by_date.groupby(level=0).cumsum()
111 data_by_date = data_by_date.merge(
112 data_by_date.groupby(level=0).cumsum(),
113 suffixes=('', '_culm'),
114 left_index=True, right_index=True)
119 data_by_date = data_by_date.merge(
120 data_by_date[['cases', 'deaths']].groupby(level=0).diff(),
121 suffixes=('', '_diff'),
122 left_index=True, right_index=True)
127 data_by_date.loc['UK', '2020-04-17']
131 data_by_date.loc['UK']
135 # data_by_date[data_by_date.deaths_culm > DEATH_COUNT_THRESHOLD]
139 # days_since_threshold = data_by_date[data_by_date.deaths_culm > DEATH_COUNT_THRESHOLD].groupby(level=0).cumcount()
140 # days_since_threshold.rename('since_threshold', inplace=True)
144 dbd = data_by_date[data_by_date.deaths_culm > DEATH_COUNT_THRESHOLD].reset_index(level=1)
145 dbd['since_threshold'] = dbd.dateRep
146 dbd.set_index('dateRep', append=True, inplace=True)
147 dbd.sort_index(inplace=True)
148 days_since_threshold = dbd.groupby(level=0).diff().since_threshold.dt.days.fillna(0).astype(int).groupby(level=0).cumsum()
149 # days_since_threshold.groupby(level=0).cumsum()
151 # days_since_threshold = dbd.rename('since_threshold')
156 # days_since_threshold = (data_by_date[data_by_date.deaths_culm > DEATH_COUNT_THRESHOLD]
157 # .reset_index(level=1).groupby(level=0)
158 # .diff().dateRep.dt.days
159 # .groupby(level=0).cumcount()
161 # days_since_threshold.rename('since_threshold', inplace=True)
162 # days_since_threshold
166 data_since_threshold = data_by_date.merge(days_since_threshold,
167 left_index=True, right_index=True)
172 data_since_threshold = data_since_threshold.set_index('since_threshold', append=True
173 ).reorder_levels(['since_threshold', 'geoId', 'dateRep']
174 ).reset_index('dateRep')
179 data_since_threshold.loc[(slice(None), ['UK', 'DE', 'IT']), :]
183 data_since_threshold.loc[(slice(None), ['UK', 'DE', 'IT']), ['deaths_culm']].unstack().plot(logy=True)
187 # deaths = data_since_threshold.loc[(slice(None), ['UK', 'DE', 'IT', 'IE']), ['deaths_culm']].unstack().xs('deaths_culm', axis=1, drop_level=True)
191 deaths = data_since_threshold.loc[(slice(None), COUNTRIES_ALL), ['deaths_culm']].unstack().sort_index().xs('deaths_culm', axis=1, drop_level=True)
195 data_since_threshold.reset_index().merge(countries, on='geoId').set_index(['since_threshold', 'geoId'])
199 data_since_threshold.reset_index().merge(countries, on='geoId').set_index(['since_threshold', 'geoId']).sort_index(inplace=True)
203 data_since_threshold_per_capita = data_since_threshold.reset_index().merge(countries, on='geoId').set_index(['since_threshold', 'geoId'])
204 data_since_threshold_per_capita['cases_culm_pc'] = data_since_threshold_per_capita.cases_culm / data_since_threshold_per_capita.popData2018
205 data_since_threshold_per_capita['deaths_culm_pc'] = data_since_threshold_per_capita.deaths_culm / data_since_threshold_per_capita.popData2018
206 data_since_threshold_per_capita
210 deaths_pc = data_since_threshold_per_capita.loc[(slice(None), ['UK', 'DE', 'IT', 'IE']), ['deaths_culm_pc']].unstack().sort_index().xs('deaths_culm_pc', axis=1, drop_level=True)
222 deaths_pc = data_since_threshold_per_capita.loc[(slice(None), COUNTRIES_ALL), ['deaths_culm_pc']].unstack().xs('deaths_culm_pc', axis=1, drop_level=True)
226 deaths[COUNTRIES_CORE].plot()
230 deaths[COUNTRIES_FRIENDS].plot()
234 ax = deaths[COUNTRIES_CORE].plot(figsize=(10, 6), title="Total deaths, linear")
235 for c in COUNTRIES_CORE:
236 lvi = deaths[c].last_valid_index()
237 ax.text(x = lvi + 1, y = deaths[c][lvi], s = c)
238 plt.savefig('covid_deaths_total_linear.png')
242 ax = deaths[COUNTRIES_NORDIC].plot(figsize=(10, 6), title="Total deaths, linear")
243 for c in COUNTRIES_NORDIC:
244 lvi = deaths[c].last_valid_index()
245 ax.text(x = lvi + 1, y = deaths[c][lvi], s = c)
246 # plt.savefig('covid_deaths_total_linear.png')
250 ax = deaths[COUNTRIES_OF_INTEREST].plot(figsize=(10, 6), title="Total deaths, linear")
251 for c in COUNTRIES_OF_INTEREST:
252 lvi = deaths[c].last_valid_index()
253 ax.text(x = lvi + 1, y = deaths[c][lvi], s = c)
254 # plt.savefig('covid_deaths_total_linear.png')
258 ax = deaths[COUNTRIES_CORE].plot(logy=True, figsize=(10, 6), title="Total deaths, log")
259 for c in COUNTRIES_CORE:
260 lvi = deaths[c].last_valid_index()
261 ax.text(x = lvi + 1, y = deaths[c][lvi], s = c)
263 plt.savefig('covid_deaths_total_log.png')
267 ylim = (5*10**3, 5*10**4)
268 ax = deaths[COUNTRIES_CORE].plot(logy=True, figsize=(10, 6), ylim=ylim, title="Total deaths, log")
269 for c in COUNTRIES_CORE:
270 lvi = deaths[c].last_valid_index()
271 if ylim[0] < deaths[c][lvi] < ylim[1]:
272 ax.text(x = lvi + 1, y = deaths[c][lvi], s = c)
274 # plt.savefig('covid_deaths_total_log.png')
278 ax = deaths[COUNTRIES_FRIENDS].plot(logy=True, figsize=(10, 6), title="Total deaths, log")
279 for c in COUNTRIES_FRIENDS:
280 lvi = deaths[c].last_valid_index()
281 ax.text(x = lvi + 1, y = deaths[c][lvi], s = c)
283 # plt.savefig('covid_deaths_total_log.png')
287 ax = deaths[COUNTRIES_NORDIC].plot(logy=True, figsize=(10, 6), title="Total deaths, log")
288 for c in COUNTRIES_NORDIC:
289 lvi = deaths[c].last_valid_index()
290 ax.text(x = lvi + 1, y = deaths[c][lvi], s = c)
292 # plt.savefig('covid_deaths_total_log.png')
296 ax = deaths[COUNTRIES_OF_INTEREST].plot(logy=True, figsize=(10, 6), title="Total deaths, log")
297 for c in COUNTRIES_OF_INTEREST:
298 lvi = deaths[c].last_valid_index()
299 ax.text(x = lvi + 1, y = deaths[c][lvi], s = c)
301 plt.savefig('covid_deaths_total_log.png')
305 ax = deaths_pc.plot(figsize=(10, 6), title="Deaths per capita, linear")
306 for c in deaths_pc.columns:
307 lvi = deaths_pc[c].last_valid_index()
308 ax.text(x = lvi + 1, y = deaths_pc[c][lvi], s = c)
309 plt.savefig('covid_deaths_per_capita_linear.png')
313 ax = deaths_pc.plot(logy=True, figsize=(10, 6), title="Deaths per capita, log")
314 for c in deaths_pc.columns:
315 lvi = deaths_pc[c].last_valid_index()
316 ax.text(x = lvi + 1, y = deaths_pc[c][lvi], s = c)
320 deaths_pc[['UK', 'IE']].plot( figsize=(10, 6), title="Deaths per capita, linear")
324 deaths_pc[['UK', 'IE']].plot(logy=True, figsize=(10, 6), title="Deaths per capita, log")
328 deaths[['UK', 'ES', 'IT']].plot(logy=True, figsize=(10, 6), title="Deaths, log")
329 plt.savefig('covid_deaths_selected_log.png')
333 deaths[['UK', 'ES', 'IT', 'MX']].plot(logy=True, figsize=(10, 6), title="Deaths, log")
337 data_since_threshold.loc[(slice(None), ['UK', 'DE', 'IT']), :]
341 data_since_threshold['deaths_m4'] = data_since_threshold.groupby(level=1)['deaths'].transform(lambda x: x.rolling(4, 1).mean())
342 data_since_threshold['deaths_m7'] = data_since_threshold.groupby(level=1)['deaths'].transform(lambda x: x.rolling(7, 1).mean())
343 # data_since_threshold['deaths_diff_m4'] = data_since_threshold.groupby(level=1)['deaths_diff'].transform(lambda x: x.rolling(4, 1).mean())
344 # data_since_threshold['deaths_diff_m7'] = data_since_threshold.groupby(level=1)['deaths_diff'].transform(lambda x: x.rolling(7, 1).mean())
345 data_since_threshold.loc[(slice(None), ['UK', 'DE', 'IT']), :]
349 deaths_m4 = (data_since_threshold.loc[(slice(None), COUNTRIES_ALL), ['deaths_m4']]
350 .unstack().sort_index().xs('deaths_m4', axis=1, drop_level=True))
354 deaths_m7 = (data_since_threshold.loc[(slice(None), COUNTRIES_ALL), ['deaths_m7']]
355 .unstack().sort_index().xs('deaths_m7', axis=1, drop_level=True))
359 ax = deaths_m4.plot(figsize=(10, 6), title="Deaths per day, 4 day moving average")
360 for c in deaths_m4.columns:
361 lvi = deaths_m4[c].last_valid_index()
362 ax.text(x = lvi + 1, y = deaths_m4[c][lvi], s = c)
363 plt.savefig('covid_deaths_per_day.png')
367 ax = deaths_m4[COUNTRIES_CORE].plot(figsize=(10, 6), title="Deaths per day, 4 day moving average")
368 for c in COUNTRIES_CORE:
369 lvi = deaths_m4[c].last_valid_index()
370 ax.text(x = lvi + 1, y = deaths_m4[c][lvi], s = c)
371 plt.savefig('covid_deaths_per_day-core.png')
375 ax = deaths_m4[COUNTRIES_FRIENDS].plot(figsize=(10, 6), title="Deaths per day, 4 day moving average")
376 for c in COUNTRIES_FRIENDS:
377 lvi = deaths_m4[c].last_valid_index()
378 ax.text(x = lvi + 1, y = deaths_m4[c][lvi], s = c)
379 plt.savefig('covid_deaths_per_day-friends.png')
383 C7s = 'ES FR IT UK'.split()
384 ax = deaths_m7[C7s].plot(figsize=(10, 6), title="Deaths per day, 7 day moving average")
386 lvi = deaths_m7[c].last_valid_index()
387 ax.text(x = lvi + 1, y = deaths_m7[c][lvi], s = c)
388 # plt.savefig('covid_deaths_per_day-friends.png')
392 ax = deaths_m7[COUNTRIES_CORE].plot(figsize=(10, 6), title="Deaths per day, 7 day moving average")
393 for c in COUNTRIES_CORE:
394 lvi = deaths_m7[c].last_valid_index()
395 ax.text(x = lvi + 1, y = deaths_m7[c][lvi], s = c)
396 plt.savefig('covid_deaths_per_day_7.png')
400 ax = deaths_m7[COUNTRIES_FRIENDS].plot(figsize=(10, 6), title="Deaths per day, 7 day moving average")
401 for c in COUNTRIES_FRIENDS:
402 lvi = deaths_m7[c].last_valid_index()
403 ax.text(x = lvi + 1, y = deaths_m7[c][lvi], s = c)
404 plt.savefig('covid_deaths_per_day_friends_7.png')
408 def gmean_scale(items):
409 return gmean(items) / items[-1]
413 def doubling_time(df):
414 return np.log(2) / np.log((df.deaths_culm + df.deaths_g4) / df.deaths_culm)
416 def doubling_time_7(df):
417 return np.log(2) / np.log((df.deaths_culm + df.deaths_g7) / df.deaths_culm)
421 # data_since_threshold['deaths_g4'] = data_since_threshold.groupby(level=1)['deaths'].transform(lambda x: x.rolling(4, 1).apply(gmean_scale, raw=True))
422 # data_since_threshold.loc[(slice(None), ['UK', 'DE', 'IT']), :]
426 data_since_threshold['deaths_g4'] = data_since_threshold.groupby(level=1)['deaths'].transform(lambda x: x.rolling(4, 1).apply(gmean, raw=True))
427 data_since_threshold['deaths_g7'] = data_since_threshold.groupby(level=1)['deaths'].transform(lambda x: x.rolling(7, 1).apply(gmean, raw=True))
428 data_since_threshold.loc[(slice(None), ['UK', 'DE', 'IT']), :]
432 data_since_threshold['doubling_time'] = data_since_threshold.groupby(level=1).apply(doubling_time).reset_index(level=0, drop=True)
433 data_since_threshold['doubling_time_7'] = data_since_threshold.groupby(level=1).apply(doubling_time_7).reset_index(level=0, drop=True)
434 # data_since_threshold.loc[(slice(None), 'UK'), :]
438 doubling_times = (data_since_threshold.loc[(slice(None), COUNTRIES_OF_INTEREST), ['doubling_time']]
439 .unstack().sort_index().xs('doubling_time', axis=1, drop_level=True))
440 doubling_times.replace([np.inf, -np.inf], np.nan, inplace=True)
444 doubling_times_7 = (data_since_threshold.loc[(slice(None), COUNTRIES_OF_INTEREST), ['doubling_time_7']]
445 .unstack().sort_index().xs('doubling_time_7', axis=1, drop_level=True))
446 doubling_times_7.replace([np.inf, -np.inf], np.nan, inplace=True)
450 ax = doubling_times.plot(figsize=(10, 6), title="Doubling times, 4 day average")
451 for c in doubling_times.columns:
452 lvi = doubling_times[c].last_valid_index()
453 ax.text(x = lvi + 1, y = doubling_times[c][lvi], s = c)
454 # plt.savefig('covid_deaths_per_day.png')
458 ax = doubling_times_7[COUNTRIES_CORE].plot(figsize=(10, 6), title="Doubling times, 7 day average")
459 for c in COUNTRIES_CORE:
460 lvi = doubling_times_7[c].last_valid_index()
461 ax.text(x = lvi + 1, y = doubling_times_7[c][lvi], s = c)
462 plt.savefig('covid_doubling_times_7.png')
466 ax = doubling_times[COUNTRIES_CORE].plot(figsize=(10, 6), title="Doubling times, 4 day average")
467 for c in COUNTRIES_CORE:
468 lvi = doubling_times[c].last_valid_index()
469 ax.text(x = lvi + 1, y = doubling_times[c][lvi], s = c)
470 plt.savefig('covid_doubling_times.png')
474 ax = doubling_times[COUNTRIES_FRIENDS].plot(figsize=(10, 6), title="Doubling times")
475 for c in COUNTRIES_FRIENDS:
476 lvi = doubling_times[c].last_valid_index()
477 ax.text(x = lvi + 1, y = doubling_times[c][lvi], s = c)
478 plt.savefig('covid_doubling_times_friends.png')
482 ax = doubling_times[C7s].plot(figsize=(10, 6), title="Doubling times")
484 lvi = doubling_times[c].last_valid_index()
485 ax.text(x = lvi + 1, y = doubling_times[c][lvi], s = c)
486 # plt.savefig('covid_doubling_times_friends.png')
490 # deaths_diff_m4 = (data_since_threshold.loc[(slice(None), COUNTRIES_ALL), ['deaths_diff_m4']]
491 # .unstack().sort_index().xs('deaths_diff_m4', axis=1, drop_level=True))
495 # deaths_diff_m7 = (data_since_threshold.loc[(slice(None), COUNTRIES_ALL), ['deaths_diff_m7']]
496 # .unstack().sort_index().xs('deaths_diff_m7', axis=1, drop_level=True))
504 data_since_threshold.replace([np.inf, -np.inf], np.nan).groupby(level=1).last().loc[COUNTRIES_ALL]#, [doubling_time]]
508 data_since_threshold.replace([np.inf, -np.inf], np.nan).groupby(level=1).last().loc[['UK', 'DE', 'IT']]#, [doubling_time]]
512 it_since_threshold = data_since_threshold.replace([np.inf, -np.inf], np.nan).loc[(slice(None), ['IT']), :]
513 s_end = it_since_threshold.index.max()[0]
518 uk_projection = data_since_threshold.replace([np.inf, -np.inf], np.nan).loc[(slice(None), ['UK']), :]
519 s_start = uk_projection.index.max()[0] + 1
524 proj = it_since_threshold.loc[(slice(s_start, s_end), slice(None)), ['cases', 'deaths']]
525 proj.index = pd.MultiIndex.from_tuples([(n, 'UK') for n, _ in proj.index], names=proj.index.names)
529 Projected deaths, UK following IT trend from now.
532 uk_projection = uk_projection.append(proj, sort=True)
533 uk_projection.deaths.sum()
537 it_since_threshold.deaths.sum()
541 with open('excess_deaths.json') as f:
542 excess_deaths_data = json.load(f)
547 excess_deaths_upto = '2020-05-08'
548 excess_deaths = 54500
552 excess_deaths_upto = excess_deaths_data['end_date']
553 excess_deaths = excess_deaths_data['excess_deaths']
556 Recorded deaths in period where ONS has reported total deaths
559 reported_deaths = base_data.loc['UK'][:excess_deaths_upto]['deaths'].sum()
564 excess_deaths / reported_deaths
567 True deaths to date, if we follow the scaling of excess deaths over reported deaths so far.
570 uk_covid_deaths = data_since_threshold.replace([np.inf, -np.inf], np.nan).loc[(slice(None), ['UK']), 'deaths_culm'].iloc[-1]
575 data_since_threshold.replace([np.inf, -np.inf], np.nan).loc[(slice(None), ['IT']), 'dateRep'].iloc[-1] + pd.Timedelta(s_end - s_start, unit='days')
579 data_since_threshold.replace([np.inf, -np.inf], np.nan).loc[(slice(None), ['UK']), 'dateRep'].iloc[-1].strftime("%Y-%m-%d")
583 uk_covid_deaths * excess_deaths / reported_deaths
587 uk_projection.deaths.sum() * excess_deaths / reported_deaths
590 # Write results to summary file
593 with open('covid_summary.md', 'w') as f:
594 f.write('% Covid death data summary\n')
595 f.write('% Neil Smith\n')
596 f.write(f'% Created on {datetime.datetime.now().strftime("%Y-%m-%d")}\n')
599 last_uk_date = data_since_threshold.replace([np.inf, -np.inf], np.nan).loc[(slice(None), ['UK']), 'dateRep'].iloc[-1]
600 f.write(f'> Last UK data from {last_uk_date.strftime("%Y-%m-%d")}\n')
604 with open('covid_summary.md', 'a') as f:
606 f.write('## Headlines\n')
608 f.write('| []() | |\n')
609 f.write('|:---|---:|\n')
610 f.write(f'| Deaths reported so far | {reported_deaths} | \n')
611 f.write(f'| Total Covid deaths to date | {uk_covid_deaths * excess_deaths / reported_deaths:.0f} |\n')
612 projection_date = data_since_threshold.replace([np.inf, -np.inf], np.nan).loc[(slice(None), ['IT']), 'dateRep'].iloc[-1] + pd.Timedelta(s_end - s_start, unit='days')
613 f.write(f'| Projected total deaths up to {projection_date.strftime("%Y-%m-%d")} | {uk_projection.deaths.sum() * excess_deaths / reported_deaths:.0f} | \n')
618 with open('covid_summary.md', 'a') as f:
620 f.write('## Total deaths\n')
621 f.write(f'Time based on days since {DEATH_COUNT_THRESHOLD} deaths\n')
623 f.write('![Total deaths](covid_deaths_total_linear.png)\n')
625 f.write('| Country ID | Country name | Total deaths |\n')
626 f.write('|:-----------|:-------------|-------------:|\n')
627 for c in sorted(COUNTRIES_CORE):
628 lvi = deaths[c].last_valid_index()
629 f.write(f'| {c} | {countries.loc[c].countriesAndTerritories} | {int(deaths[c][lvi])} |\n')
634 with open('covid_summary.md', 'a') as f:
636 f.write('## All-causes deaths, UK\n')
638 f.write('![All-causes deaths](deaths-radar.png)\n')
640 f.write('### Excess deaths\n')
642 f.write(f'From week ending 20 March 2020, there have been approximately **{excess_deaths:.0f}** excess deaths, over the average for the previous five years.\n')
647 with open('covid_summary.md', 'a') as f:
648 f.write(f'In that period, the UK reported {reported_deaths} Covid deaths.\n')
649 f.write(f'That means the actual number of Covid death is about {excess_deaths / reported_deaths:.2f} times higher than the reported figures.\n')
651 f.write(f'The UK has reported {uk_covid_deaths} deaths so far.\n')
652 f.write(f'Using the scaling factor above, I infer that there have been **{uk_covid_deaths * excess_deaths / reported_deaths:.0f}** total deaths so far.\n')
657 with open('covid_summary.md', 'a') as f:
659 f.write('## Deaths per day\n')
660 f.write(f'Based on a 7-day moving average\n')
662 f.write('![Deaths per day](covid_deaths_per_day_7.png)\n')
667 with open('covid_summary.md', 'a') as f:
669 f.write('## Projected deaths\n')
670 f.write(f"The UK's daily deaths data is very similar to Italy's.\n")
671 f.write(f'If I use the Italian data for the next {s_end - s_start - 1} days,')
672 f.write(f' the UK will report {uk_projection.deaths.sum()} deaths on day {s_end} of the epidemic.\n')
674 f.write('Using the excess deaths scaling from above, that will translate into ')
675 f.write(f'**{(uk_projection.deaths.sum() * excess_deaths / reported_deaths):.0f}** Covid deaths total.\n')
680 with open('covid_summary.md', 'a') as f:
682 f.write('## Deaths doubling times\n')
683 f.write(f'Based on a 7-day moving average\n')
685 f.write('![Deaths doubling times](covid_doubling_times_7.png)\n')
690 with open('covid_summary.md', 'a') as f:
691 f.write('# Data sources\n')
693 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')
695 f.write("""> Population data from:
697 * [Office of National Statistics](https://www.ons.gov.uk/peoplepopulationandcommunity/birthsdeathsandmarriages/deaths/datasets/weeklyprovisionalfiguresondeathsregisteredinenglandandwales) (Endland and Wales) Weeks start on a Saturday.
698 * [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.
699 * [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.""")
702 f.write('> [Souce code available](https://git.njae.me.uk/?p=covid19.git;a=tree)\n')
708 !pandoc -s covid_summary.md > covid_summary.html
712 !scp covid_summary.html neil@ogedei:/var/www/scripts.njae.me.uk/covid/index.html
713 !scp covid_deaths_total_linear.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/
714 !scp deaths-radar.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/
715 !scp covid_deaths_per_day_7.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/
716 !scp covid_doubling_times_7.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/