2021-01-15 00:09:25 +00:00
#!/usr/bin/python
# vim: set fileencoding=utf-8 :
2021-02-10 23:25:36 +00:00
# Copyright (C) Benedikt Bastin, 2021
# SPDX-License-Identifier: EUPL-1.2
2021-01-14 23:16:40 +00:00
import numpy as np
import matplotlib . pyplot as plt
import pandas as pd
import datetime
import re
2021-01-15 00:01:43 +00:00
import requests as req
2021-01-15 19:19:06 +00:00
import locale
2021-01-16 13:26:46 +00:00
import os . path
2021-01-17 01:34:49 +00:00
import shutil
2021-02-17 10:55:30 +00:00
import math
2021-03-20 12:15:38 +00:00
from functools import reduce
2021-01-15 19:19:06 +00:00
2021-03-20 12:15:38 +00:00
from matplotlib . dates import date2num , DateFormatter , WeekdayLocator
import matplotlib . dates as mdates
2021-01-31 22:44:50 +00:00
import matplotlib . ticker as mtick
2021-04-14 11:46:19 +00:00
from matplotlib . patches import Rectangle
2021-01-31 20:11:20 +00:00
2021-03-20 12:15:38 +00:00
from isoweek import Week
2021-01-15 19:19:06 +00:00
locale . setlocale ( locale . LC_ALL , ' de_DE.UTF-8 ' )
2021-01-15 00:01:43 +00:00
2021-01-17 01:34:49 +00:00
site_folder = ' site/ '
data_folder = ' data/ '
2021-01-14 23:16:40 +00:00
einwohner_deutschland = 83190556
2021-01-17 01:34:49 +00:00
herd_immunity = 0.7
2021-01-14 23:16:40 +00:00
2021-02-10 16:45:52 +00:00
2021-01-15 00:01:43 +00:00
today = datetime . date . today ( )
print_today = today . isoformat ( )
filename_now = datetime . datetime . now ( ) . strftime ( " % Y % m %d % H % M % S " )
2021-01-14 23:16:40 +00:00
2021-04-05 10:06:28 +00:00
force_renew_plots = False
force_renew_dashboard = False
2021-02-10 16:45:52 +00:00
# https://www.tagesschau.de/ausland/europa/ursula-von-der-leyen-zu-corona-impfstoffen-101.html
target_date_for_herd_immunity = datetime . date ( 2021 , 9 , 22 )
days_until_target = ( target_date_for_herd_immunity - today ) . days - 21
2021-01-14 23:16:40 +00:00
# DIN A4 Plots
plt . rcParams [ " figure.figsize " ] = [ 11.69 , 8.27 ]
2021-01-15 00:01:43 +00:00
# Download
2021-01-17 01:34:49 +00:00
data_filename = ' {} / {} _Impfquotenmonitoring.xlsx ' . format ( data_folder , filename_now )
2021-01-15 00:01:43 +00:00
r = req . get ( ' https://www.rki.de/DE/Content/InfAZ/N/Neuartiges_Coronavirus/Daten/Impfquotenmonitoring.xlsx?__blob=publicationFile ' )
2021-01-17 01:34:49 +00:00
with open ( data_filename , ' wb ' ) as outfile :
2021-01-15 00:01:43 +00:00
outfile . write ( r . content )
2021-01-31 19:57:02 +00:00
#data_filename = 'data/20210118151908_Impfquotenmonitoring.xlsx'
2021-01-15 00:01:43 +00:00
2021-01-17 01:34:49 +00:00
rki_file = pd . read_excel ( data_filename , sheet_name = None , engine = ' openpyxl ' )
2021-01-14 23:19:31 +00:00
raw_data = rki_file [ ' Impfungen_proTag ' ]
2021-01-14 23:16:40 +00:00
2021-04-14 08:56:17 +00:00
impfungen = raw_data [ : - 1 ] . dropna ( subset = [ ' Datum ' ] ) . fillna ( 0 )
2021-01-14 23:16:40 +00:00
2021-04-14 08:33:26 +00:00
impfungen . drop ( impfungen . tail ( 1 ) . index , inplace = True ) # remove Gesamt row
2021-02-04 16:30:40 +00:00
2021-01-14 23:16:40 +00:00
dates = impfungen [ ' Datum ' ]
2021-01-31 19:57:02 +00:00
start_of_reporting_date = dates . iloc [ 0 ] . date ( )
2021-01-14 23:16:40 +00:00
2021-01-31 19:57:02 +00:00
def calculate_vaccination_data ( data ) :
2021-01-17 01:34:49 +00:00
2021-01-31 19:57:02 +00:00
total = int ( np . sum ( data ) )
total_percentage = float ( total ) / einwohner_deutschland * 100
2021-01-17 01:34:49 +00:00
2021-01-31 19:57:02 +00:00
to_be_vaccinated = einwohner_deutschland - total
2021-01-17 01:34:49 +00:00
2021-01-31 19:57:02 +00:00
last_date = dates . iloc [ - 1 ] . date ( )
2021-01-31 22:33:03 +00:00
start_of_vaccination_index = ( data != 0 ) . argmax ( axis = 0 )
start_of_vaccination_date = dates [ start_of_vaccination_index ] . date ( )
2021-01-31 19:57:02 +00:00
days_since_start_of_vaccination = ( last_date - start_of_vaccination_date ) . days
days_since_start_of_reporting = ( last_date - start_of_reporting_date ) . days
2021-01-17 01:34:49 +00:00
2021-02-17 10:55:30 +00:00
valid_data = data [ start_of_vaccination_index : ]
cumulative = np . concatenate ( ( [ math . nan ] * ( days_since_start_of_reporting - days_since_start_of_vaccination ) , np . cumsum ( valid_data ) ) )
mean_all_time = np . mean ( valid_data )
2021-01-31 22:33:03 +00:00
mean_seven_days = np . mean ( data [ - 7 : ] )
2021-03-20 12:15:38 +00:00
vaccinations_by_week_map = map ( lambda x : ( Week . withdate ( x [ 0 ] ) , x [ 1 ] ) , zip ( dates , data ) )
vaccinations_by_week = { }
for w , v in vaccinations_by_week_map :
if w in vaccinations_by_week :
vaccinations_by_week [ w ] = vaccinations_by_week [ w ] + v
else :
vaccinations_by_week [ w ] = v
2021-01-31 19:57:02 +00:00
def extrapolate ( rate , to_be_vaccinated ) :
days_extrapolated = int ( np . ceil ( to_be_vaccinated / rate ) )
2021-04-12 11:38:30 +00:00
days_extrapolated_herd_immunity = int ( np . ceil ( ( einwohner_deutschland * 0.7 - total ) / rate ) )
2021-01-14 23:16:40 +00:00
2021-04-13 10:19:17 +00:00
weeks_extrapolated = int ( np . ceil ( days_extrapolated / 7 ) )
weeks_extrapolated_herd_immunity = int ( np . ceil ( days_extrapolated_herd_immunity / 7 ) )
2021-04-12 11:38:30 +00:00
date_done = today + datetime . timedelta ( days_extrapolated )
date_herd_immunity = today + datetime . timedelta ( days_extrapolated_herd_immunity )
2021-01-17 01:34:49 +00:00
2021-01-31 19:57:02 +00:00
extrapolated_vaccinations = total + rate * range ( - days_since_start_of_reporting , days_extrapolated - days_since_start_of_reporting )
2021-01-17 01:34:49 +00:00
2021-01-31 19:57:02 +00:00
return {
' rate ' : rate ,
' rate_int ' : int ( np . round ( rate ) ) ,
' days_extrapolated ' : days_extrapolated ,
2021-04-13 10:19:17 +00:00
' days_extrapolated_herd_immunity ' : days_extrapolated_herd_immunity ,
' weeks_extrapolated ' : weeks_extrapolated ,
' weeks_extrapolated_herd_immunity ' : weeks_extrapolated_herd_immunity ,
2021-01-31 19:57:02 +00:00
' date_done ' : date_done ,
' date_done_str ' : date_done . strftime ( ' %d . % B % Y ' ) ,
' date_herd_immunity ' : date_herd_immunity ,
' date_herd_immunity_str ' : date_herd_immunity . strftime ( ' %d . % B % Y ' ) ,
' extrapolated_vaccinations ' : extrapolated_vaccinations
}
2021-01-17 01:34:49 +00:00
2021-01-31 19:57:02 +00:00
extrapolation_mean_all_time = extrapolate ( mean_all_time , to_be_vaccinated )
extrapolation_last_rate = extrapolate ( data . iloc [ - 1 ] , to_be_vaccinated )
extrapolation_mean_seven_days = extrapolate ( mean_seven_days , to_be_vaccinated )
2021-01-17 01:34:49 +00:00
2021-01-31 19:57:02 +00:00
mean_vaccination_rates_daily = np . round ( cumulative / range ( 1 , len ( cumulative ) + 1 ) )
2021-02-17 10:55:30 +00:00
vaccination_rates_daily_rolling_average = data . rolling ( 7 ) . mean ( )
2021-02-10 16:45:52 +00:00
vaccinations_missing_until_target = einwohner_deutschland * 0.7 - total
vaccination_rate_needed_for_target = vaccinations_missing_until_target / days_until_target
vaccination_rate_needed_for_target_percentage = mean_all_time / vaccination_rate_needed_for_target * 100
2021-01-31 19:57:02 +00:00
return {
' daily ' : data ,
' cumulative ' : cumulative ,
' total ' : total ,
' total_percentage ' : total_percentage ,
' to_be_vaccinated ' : to_be_vaccinated ,
' last_date ' : last_date ,
' last_date_str ' : last_date . strftime ( ' %d . % B % Y ' ) ,
' days_since_start ' : days_since_start_of_vaccination + 1 , # Shift from zero to one-based-index
' start_of_vaccination_date ' : start_of_vaccination_date ,
' start_of_vaccination_date_str ' : start_of_vaccination_date . strftime ( ' %d . % B % Y ' ) ,
2021-03-20 12:15:38 +00:00
' vaccinations_by_week ' : vaccinations_by_week ,
2021-01-31 19:57:02 +00:00
' extrapolation_mean_all_time ' : extrapolation_mean_all_time ,
' extrapolation_last_rate ' : extrapolation_last_rate ,
' extrapolation_mean_seven_days ' : extrapolation_mean_seven_days ,
2021-02-10 16:45:52 +00:00
' mean_vaccination_rates_daily ' : mean_vaccination_rates_daily ,
2021-02-17 10:55:30 +00:00
' vaccination_rates_daily_rolling_average ' : vaccination_rates_daily_rolling_average ,
2021-02-10 16:45:52 +00:00
' vaccinations_missing_until_target ' : int ( np . floor ( vaccinations_missing_until_target ) ) ,
' vaccination_rate_needed_for_target ' : int ( np . floor ( vaccination_rate_needed_for_target ) ) ,
' vaccination_rate_needed_for_target_percentage ' : vaccination_rate_needed_for_target_percentage
2021-01-31 19:57:02 +00:00
}
2021-01-17 01:34:49 +00:00
2021-04-13 10:08:14 +00:00
if ' Erstimpfung ' in impfungen :
raw_first_vaccinations = impfungen [ ' Erstimpfung ' ]
elif ' Einmal geimpft ' in impfungen :
raw_first_vaccinations = impfungen [ ' Einmal geimpft ' ]
if ' Zweitimpfung ' in impfungen :
raw_second_vaccinations = impfungen [ ' Zweitimpfung ' ]
elif ' Vollständig geimpft ' in impfungen :
raw_second_vaccinations = impfungen [ ' Vollständig geimpft ' ]
data_first_vaccination = calculate_vaccination_data ( raw_first_vaccinations )
data_second_vaccination = calculate_vaccination_data ( raw_second_vaccinations )
2021-01-17 01:34:49 +00:00
2021-01-14 23:16:40 +00:00
# Stand aus Daten auslesen
#stand = dates.iloc[-1]
#print_stand = stand.isoformat()
# Stand aus offiziellen Angaben auslesen
2021-01-14 23:19:31 +00:00
stand = rki_file [ ' Erläuterung ' ] . iloc [ 1 ] [ 0 ]
2021-01-14 23:16:40 +00:00
2021-02-21 14:50:11 +00:00
stand_regex = re . compile ( ' ^Datenstand: ( \ d \ d. \ d \ d. \ d \ d \ d \ d, \ d? \ d: \ d \ d) Uhr$ ' )
2021-01-14 23:16:40 +00:00
m = stand_regex . match ( stand )
stand_date = datetime . datetime . strptime ( m . groups ( ) [ 0 ] , ' %d . % m. % Y, % H: % M ' )
print_stand = stand_date . isoformat ( )
filename_stand = stand_date . strftime ( " % Y % m %d % H % M % S " )
2021-04-14 08:49:56 +00:00
print ( f " Effective { stand_date } , last reported date { dates . iloc [ - 1 ] . date ( ) } " )
2021-01-17 01:34:49 +00:00
2021-01-31 19:57:02 +00:00
2021-01-17 01:34:49 +00:00
archive_folder = site_folder + ' archive/ ' + filename_stand
if os . path . isdir ( archive_folder ) :
print ( ' Archive folder {} already exists ' . format ( archive_folder ) )
else :
os . mkdir ( archive_folder )
2021-03-23 11:01:51 +00:00
def check_recreate_plot ( plot_name ) :
2021-01-31 19:57:02 +00:00
2021-03-23 11:01:51 +00:00
archive_plot_filename = ' {} / {} ' . format ( archive_folder , plot_name )
2021-03-23 10:51:07 +00:00
2021-03-23 11:14:50 +00:00
if os . path . isfile ( archive_plot_filename + ' .pdf ' ) and not force_renew_plots :
2021-03-23 11:01:51 +00:00
print ( ' Plot {} already exists ' . format ( plot_name ) )
return False
2021-03-23 10:51:07 +00:00
2021-03-23 11:01:51 +00:00
return True
2021-01-31 19:57:02 +00:00
2021-03-23 11:01:51 +00:00
def save_plot ( plot_name ) :
2021-01-31 19:57:02 +00:00
2021-03-23 11:01:51 +00:00
folders = [ archive_folder , site_folder ]
2021-03-23 11:14:50 +00:00
file_formats = [ ' pdf ' , ' png ' , ' svg ' ]
2021-03-23 11:01:51 +00:00
file_template = ' {folder} / {plot_name} . {format} '
2021-01-31 19:57:02 +00:00
2021-03-23 11:01:51 +00:00
for folder in folders :
for format in file_formats :
plt . savefig ( file_template . format ( folder = folder , plot_name = plot_name , format = format ) )
print ( ' Created plot {} as {} ' . format ( plot_name , file_formats ) )
2021-04-12 09:51:53 +00:00
def labeled_timeperiod ( ax , start , end , text , color = ' lightgrey ' , y_height = 100 ) :
2021-03-30 18:34:13 +00:00
centre = start + ( end - start ) / 2
ax . axvspan ( start , end , color = color , alpha = 0.5 )
2021-04-12 09:51:53 +00:00
ax . text ( centre , ax . get_ylim ( ) [ 1 ] * ( y_height / 100 ) , text , bbox = {
2021-03-23 11:39:25 +00:00
' boxstyle ' : ' square ' ,
2021-03-30 18:34:13 +00:00
' fc ' : color ,
2021-03-23 11:39:25 +00:00
' ec ' : ' black '
2021-03-30 18:34:13 +00:00
} , ha = ' center ' )
def add_annotations ( ax ) :
labeled_timeperiod ( ax , datetime . date ( 2021 , 3 , 15 ) , datetime . date ( 2021 , 3 , 19 ) , ' AZ-Stopp ' , ' silver ' )
2021-04-12 09:51:53 +00:00
labeled_timeperiod ( ax , datetime . date ( 2021 , 3 , 29 ) , today , ' AZ-Stopp u. 60 ' , ' lightgrey ' , 96 )
labeled_timeperiod ( ax , datetime . date ( 2021 , 4 , 6 ) , today , ' Arztpraxen impfen ' , ' lightgreen ' )
2021-03-30 18:34:13 +00:00
2021-03-23 11:39:25 +00:00
2021-03-23 11:01:51 +00:00
def plot_vaccination_bar_graph_total_time ( ) :
plot_name = ' vaccination_bar_graph_total_time '
if not check_recreate_plot ( plot_name ) :
2021-01-31 19:57:02 +00:00
return
fig , ax = plt . subplots ( 1 )
plt . title (
2021-01-31 20:11:20 +00:00
' Tägliche Impfrate (Erst- und Zweitimpfung übereinander) \n '
2021-01-31 19:57:02 +00:00
' Datenquelle: RKI, Stand: {} . Erstellung: {} , Ersteller: Benedikt Bastin, Lizenz: CC BY-SA 4.0 \n ' . format (
print_stand , print_today
)
)
ax . grid ( )
ax . bar ( dates , data_first_vaccination [ ' daily ' ] , label = ' Tägliche Erstimpfungen ' , color = ' blue ' )
ax . bar ( dates , data_second_vaccination [ ' daily ' ] , label = ' Tägliche Zweitimpfungen ' , color = ' lightblue ' , bottom = data_first_vaccination [ ' daily ' ] )
ax . set_ylim ( [ 0 , np . max ( data_first_vaccination [ ' daily ' ] ) + np . max ( data_second_vaccination [ ' daily ' ] ) ] )
ax . legend ( loc = ' upper left ' )
ax . get_yaxis ( ) . get_major_formatter ( ) . set_scientific ( False )
ax . set_xlabel ( ' Datum ' )
ax . set_ylabel ( ' Tägliche Impfungen ' )
2021-03-23 11:39:25 +00:00
add_annotations ( ax )
2021-03-23 11:01:51 +00:00
save_plot ( plot_name )
2021-01-31 19:57:02 +00:00
plt . close ( )
plot_vaccination_bar_graph_total_time ( )
2021-03-20 12:15:38 +00:00
def plot_vaccination_bar_graph_total_time_by_week ( ) :
2021-03-23 11:01:51 +00:00
plot_name = ' vaccination_bar_graph_total_time_by_week '
if not check_recreate_plot ( plot_name ) :
2021-03-20 12:15:38 +00:00
return
fig , ax = plt . subplots ( 1 )
plt . title (
' Wöchentliche Impfrate (Erst- und Zweitimpfung übereinander) \n '
' Datenquelle: RKI, Stand: {} . Erstellung: {} , Ersteller: Benedikt Bastin, Lizenz: CC BY-SA 4.0 \n ' . format (
print_stand , print_today
)
)
ax . grid ( )
w = [ w . day ( 3 ) for w in data_first_vaccination [ ' vaccinations_by_week ' ] . keys ( ) ]
f = list ( data_first_vaccination [ ' vaccinations_by_week ' ] . values ( ) )
s = list ( data_second_vaccination [ ' vaccinations_by_week ' ] . values ( ) )
2021-03-20 12:38:51 +00:00
bar1 = ax . bar ( w , f , label = ' Wöchentliche Erstimpfungen ' , color = ' blue ' , width = 6.8 )
bar2 = ax . bar ( w , s , label = ' Wöchentliche Zweitimpfungen ' , color = ' lightblue ' , width = 6.8 , bottom = f )
2021-03-20 12:15:38 +00:00
2021-03-23 10:49:14 +00:00
i = 0
2021-04-06 13:25:47 +00:00
nan_to_zero = lambda x : 0 if math . isnan ( x ) else x
2021-03-20 12:38:51 +00:00
for r1 , r2 in zip ( bar1 , bar2 ) :
x = r1 . get_x ( ) + r1 . get_width ( ) / 2.0
2021-04-06 13:25:47 +00:00
rh1 = nan_to_zero ( r1 . get_height ( ) )
rh2 = nan_to_zero ( r2 . get_height ( ) )
h1 = math . floor ( rh1 / 1000 )
h2 = math . floor ( rh2 / 1000 )
hg = math . floor ( ( rh1 + rh2 ) / 1000 )
2021-03-20 12:38:51 +00:00
if h1 > 30 :
plt . text ( x , h1 * 500 , f ' { h1 : 5n } k ' . replace ( ' . ' , ' ' ) , ha = ' center ' , va = ' center ' , color = ' white ' )
if h2 > 30 :
plt . text ( x , h1 * 1000 + h2 * 500 , f ' { h2 : 5n } k ' . replace ( ' . ' , ' ' ) , ha = ' center ' , va = ' center ' , color = ' black ' )
plt . text ( x , hg * 1000 , f ' { hg : 5n } k ' . replace ( ' . ' , ' ' ) , ha = ' center ' , va = ' bottom ' )
2021-03-20 12:15:38 +00:00
2021-03-23 10:49:14 +00:00
if i == 12 :
# Woche der AstraZeneca-Aussetzung
2021-03-23 11:39:25 +00:00
plt . annotate ( ' AZ-Stopp ' , ( x , hg * 1000 + 50000 ) ,
2021-03-23 10:49:14 +00:00
xytext = ( x , ax . get_ylim ( ) [ 1 ] ) ,
arrowprops = {
' arrowstyle ' : ' -> '
} ,
bbox = {
' boxstyle ' : ' square ' ,
' fc ' : ' white ' ,
' ec ' : ' black '
2021-03-23 11:39:25 +00:00
} ,
ha = ' center ' )
2021-03-23 11:42:51 +00:00
if i == len ( bar1 ) - 1 :
plt . annotate ( ' Diese Woche ' , ( x , hg * 1000 + 50000 ) ,
xytext = ( x , ax . get_ylim ( ) [ 1 ] ) ,
arrowprops = {
' arrowstyle ' : ' -> ' ,
' relpos ' : ( 0 , 0 )
} ,
bbox = {
' boxstyle ' : ' square ' ,
' fc ' : ' white ' ,
' ec ' : ' black '
} ,
ha = ' left ' )
2021-03-23 10:49:14 +00:00
i = i + 1
2021-03-20 12:15:38 +00:00
ax . legend ( loc = ' upper left ' )
ax . get_xaxis ( ) . set_major_formatter ( DateFormatter ( ' % Y-w % W ' ) )
ax . get_xaxis ( ) . set_major_locator ( WeekdayLocator ( 3 , 2 ) )
ax . get_yaxis ( ) . get_major_formatter ( ) . set_scientific ( False )
ax . set_xlabel ( ' Datum ' )
ax . set_ylabel ( ' Wöchentliche Impfungen ' )
2021-03-23 11:01:51 +00:00
save_plot ( plot_name )
2021-03-20 12:15:38 +00:00
plt . close ( )
plot_vaccination_bar_graph_total_time_by_week ( )
2021-01-31 20:11:20 +00:00
def plot_vaccination_bar_graph_total_time_two_bars ( ) :
2021-03-23 11:01:51 +00:00
plot_name = ' vaccination_bar_graph_total_time_two_bars '
if not check_recreate_plot ( plot_name ) :
2021-01-31 20:56:34 +00:00
return
2021-01-31 20:11:20 +00:00
fig , ax = plt . subplots ( 1 )
plt . title (
' Tägliche Impfrate (Erst- und Zweitimpfung nebeneinander) \n '
' Datenquelle: RKI, Stand: {} . Erstellung: {} , Ersteller: Benedikt Bastin, Lizenz: CC BY-SA 4.0 \n ' . format (
print_stand , print_today
)
)
ax . grid ( )
date_numbers = date2num ( dates )
ax . bar ( date_numbers - 0.2 , data_first_vaccination [ ' daily ' ] , width = 0.4 , label = ' Tägliche Erstimpfungen ' , color = ' blue ' )
ax . bar ( date_numbers + 0.2 , data_second_vaccination [ ' daily ' ] , width = 0.4 , label = ' Tägliche Zweitimpfungen ' , color = ' lightblue ' )
ax . set_ylim ( [ 0 , np . max ( data_first_vaccination [ ' daily ' ] ) + np . max ( data_second_vaccination [ ' daily ' ] ) ] )
ax . legend ( loc = ' upper left ' )
ax . xaxis_date ( )
ax . get_yaxis ( ) . get_major_formatter ( ) . set_scientific ( False )
ax . set_xlabel ( ' Datum ' )
ax . set_ylabel ( ' Tägliche Impfungen ' )
2021-03-23 11:39:25 +00:00
add_annotations ( ax )
2021-03-23 11:01:51 +00:00
save_plot ( plot_name )
2021-01-31 20:11:20 +00:00
plt . close ( )
plot_vaccination_bar_graph_total_time_two_bars ( )
2021-01-31 20:56:34 +00:00
def plot_vaccination_bar_graph_compare_both_vaccinations ( ) :
2021-03-23 11:01:51 +00:00
plot_name = ' vaccination_bar_graph_compare_both_vaccinations '
if not check_recreate_plot ( plot_name ) :
2021-01-31 20:56:34 +00:00
return
fig , ax = plt . subplots ( 1 )
plt . title (
' Tägliche Impfrate (Erst- und Zweitimpfung um 21 Tage versetzt) \n '
' Datenquelle: RKI, Stand: {} . Erstellung: {} , Ersteller: Benedikt Bastin, Lizenz: CC BY-SA 4.0 \n ' . format (
print_stand , print_today
)
)
ax . grid ( )
date_numbers_first = date2num ( dates + datetime . timedelta ( days = 21 ) )
date_numbers_second = date2num ( dates )
ax . bar ( date_numbers_first - 0.2 , data_first_vaccination [ ' daily ' ] , width = 0.4 , label = ' Tägliche Erstimpfungen ' , color = ' blue ' )
ax . bar ( date_numbers_second + 0.2 , data_second_vaccination [ ' daily ' ] , width = 0.4 , label = ' Tägliche Zweitimpfungen ' , color = ' lightblue ' )
ax . set_ylim ( [ 0 , np . max ( [ np . max ( data_first_vaccination [ ' daily ' ] ) , np . max ( data_second_vaccination [ ' daily ' ] ) ] ) ] )
ax . legend ( loc = ' upper left ' )
ax . xaxis_date ( )
ax . get_yaxis ( ) . get_major_formatter ( ) . set_scientific ( False )
ax . set_xlabel ( ' Datum ' )
ax . set_ylabel ( ' Tägliche Impfungen ' )
2021-03-23 11:01:51 +00:00
save_plot ( plot_name )
2021-01-31 20:56:34 +00:00
plt . close ( )
plot_vaccination_bar_graph_compare_both_vaccinations ( )
2021-01-31 21:12:03 +00:00
def plot_cumulative_two_vaccinations ( ) :
2021-03-23 11:01:51 +00:00
plot_name = ' cumulative_two_vaccinations '
if not check_recreate_plot ( plot_name ) :
2021-01-31 21:12:03 +00:00
return
fig , ax = plt . subplots ( 1 )
plt . title (
' Kumulative Impfrate (Erst- und Zweitimpfung) \n '
' Datenquelle: RKI, Stand: {} . Erstellung: {} , Ersteller: Benedikt Bastin, Lizenz: CC BY-SA 4.0 \n ' . format (
print_stand , print_today
)
)
ax . grid ( )
first_vaccinations_cumulative = data_first_vaccination [ ' cumulative ' ]
second_vaccinations_cumulative = data_second_vaccination [ ' cumulative ' ]
ax . fill_between ( dates , first_vaccinations_cumulative , label = ' Erstimpfungen ' , color = ' blue ' )
ax . fill_between ( dates , second_vaccinations_cumulative , label = ' Zweitimpfungen ' , color = ' lightblue ' )
2021-02-17 10:55:30 +00:00
ax . set_ylim ( [ 0 , first_vaccinations_cumulative [ - 1 ] ] )
2021-01-31 21:12:03 +00:00
ax . legend ( loc = ' upper left ' )
ax . xaxis_date ( )
ax . get_yaxis ( ) . get_major_formatter ( ) . set_scientific ( False )
ax . set_xlabel ( ' Datum ' )
2021-01-31 23:04:42 +00:00
ax . set_ylabel ( ' Kumulative Impfungen ' )
2021-01-31 21:12:03 +00:00
2021-03-23 11:39:25 +00:00
add_annotations ( ax )
2021-03-23 11:01:51 +00:00
save_plot ( plot_name )
2021-01-31 21:12:03 +00:00
plt . close ( )
plot_cumulative_two_vaccinations ( )
2021-01-31 22:44:50 +00:00
def plot_cumulative_two_vaccinations_percentage ( ) :
2021-03-23 11:01:51 +00:00
plot_name = ' cumulative_two_vaccinations_percentage '
if not check_recreate_plot ( plot_name ) :
2021-01-31 22:44:50 +00:00
return
fig , ax = plt . subplots ( 1 )
plt . title (
' Kumulative Impfrate (Erst- und Zweitimpfung) in Prozent der Bevökerung Deutschlands ( {} Einwohner) \n '
' Datenquelle: RKI, Stand: {} . Erstellung: {} , Ersteller: Benedikt Bastin, Lizenz: CC BY-SA 4.0 \n ' . format (
' {:n} ' . format ( einwohner_deutschland ) . replace ( ' . ' , ' ' ) ,
print_stand , print_today
)
)
ax . grid ( )
first_vaccinations_cumulative = data_first_vaccination [ ' cumulative ' ] / einwohner_deutschland
second_vaccinations_cumulative = data_second_vaccination [ ' cumulative ' ] / einwohner_deutschland
ax . fill_between ( dates , first_vaccinations_cumulative , label = ' Erstimpfungen ' , color = ' blue ' )
ax . fill_between ( dates , second_vaccinations_cumulative , label = ' Zweitimpfungen ' , color = ' lightblue ' )
ax . set_ylim ( [ 0 , 1 ] )
ax . legend ( loc = ' upper left ' )
ax . xaxis_date ( )
2021-04-12 13:28:56 +00:00
ax . yaxis . set_major_formatter ( mtick . PercentFormatter ( 1.0 , symbol = ' % ' ) )
2021-01-31 22:44:50 +00:00
ax . set_xlabel ( ' Datum ' )
2021-01-31 23:04:42 +00:00
ax . set_ylabel ( ' Kumulative Impfungen ' )
2021-01-31 22:44:50 +00:00
2021-03-23 11:39:25 +00:00
add_annotations ( ax )
2021-03-23 11:01:51 +00:00
save_plot ( plot_name )
2021-01-31 22:44:50 +00:00
plt . close ( )
plot_cumulative_two_vaccinations_percentage ( )
2021-02-04 18:14:12 +00:00
def plot_people_between_first_and_second ( ) :
2021-03-23 11:01:51 +00:00
plot_name = ' people_between_first_and_second '
if not check_recreate_plot ( plot_name ) :
2021-02-04 18:14:12 +00:00
return
fig , ax = plt . subplots ( 1 )
plt . title (
' Personen zwischen Erst- und Zweitimpfung \n '
' Datenquelle: RKI, Stand: {} . Erstellung: {} , Ersteller: Benedikt Bastin, Lizenz: CC BY-SA 4.0 \n ' . format (
print_stand , print_today
)
)
ax . grid ( )
first_vaccinations_cumulative = data_first_vaccination [ ' cumulative ' ]
2021-02-17 10:55:30 +00:00
second_vaccinations_cumulative = np . nan_to_num ( data_second_vaccination [ ' cumulative ' ] , nan = 0 )
2021-02-04 18:14:12 +00:00
people_between = first_vaccinations_cumulative - second_vaccinations_cumulative
ax . plot ( dates , people_between , label = ' Personen zwischen Erst- und Zweitimpfung ' , color = ' darkblue ' )
ax . bar ( dates , data_first_vaccination [ ' daily ' ] , color = ' blue ' , label = ' Erstimpfungen ' )
ax . bar ( dates , - data_second_vaccination [ ' daily ' ] , color = ' lightblue ' , label = ' Zweitimpfungen ' )
ax . legend ( loc = ' upper left ' )
ax . xaxis_date ( )
ax . get_yaxis ( ) . get_major_formatter ( ) . set_scientific ( False )
ax . set_xlabel ( ' Datum ' )
ax . set_ylabel ( ' Personen zwischen Erst- und Zweitimpfung ' )
2021-03-23 11:39:25 +00:00
add_annotations ( ax )
2021-03-23 11:01:51 +00:00
save_plot ( plot_name )
2021-02-04 18:14:12 +00:00
plt . close ( )
plot_people_between_first_and_second ( )
2021-02-17 10:55:30 +00:00
def plot_vaccination_rate ( ) :
2021-03-23 11:01:51 +00:00
plot_name = ' vaccination_rate '
if not check_recreate_plot ( plot_name ) :
2021-02-17 11:15:07 +00:00
return
2021-02-17 10:55:30 +00:00
fig , ax = plt . subplots ( 1 )
plt . title (
' Tägliche Impfrate sowie durchschnittliche Impfrate \n '
' Datenquelle: RKI, Stand: {} . Erstellung: {} , Ersteller: Benedikt Bastin, Lizenz: CC BY-SA 4.0 \n ' . format (
print_stand , print_today
)
)
ax . plot ( dates , data_first_vaccination [ ' daily ' ] , label = ' Tägliche Erstimpfrate ' , color = ' blue ' , linewidth = 0.5 )
ax . plot ( dates , data_second_vaccination [ ' daily ' ] , label = ' Tägliche Zweitimpfrate ' , color = ' lightblue ' , linewidth = 0.5 )
ax . plot ( dates , data_first_vaccination [ ' vaccination_rates_daily_rolling_average ' ] , color = ' blue ' , linewidth = 2 , label = ' Erstimpfrate über sieben Tage ' )
ax . plot ( dates , data_second_vaccination [ ' vaccination_rates_daily_rolling_average ' ] , color = ' lightblue ' , linewidth = 2 , label = ' Zweitimpfrate über sieben Tage ' )
ax . plot ( dates , data_first_vaccination [ ' mean_vaccination_rates_daily ' ] , color = ' violet ' , label = ' Durchschnittliche Erstimpfrate \n bis zu diesem Tag (inkl.) ' )
ax . plot ( dates , data_second_vaccination [ ' mean_vaccination_rates_daily ' ] , color = ' magenta ' , label = ' Durchschnittliche Zweitimpfrate \n bis zu diesem Tag (inkl.) ' )
ax . grid ( True )
ax . legend ( loc = ' upper left ' )
ax . get_yaxis ( ) . get_major_formatter ( ) . set_scientific ( False )
ax . set_xlabel ( ' Datum ' )
ax . set_ylabel ( ' Impfrate [Impfungen/Tag] ' )
2021-03-23 11:39:25 +00:00
add_annotations ( ax )
2021-03-23 11:01:51 +00:00
save_plot ( plot_name )
2021-02-17 10:55:30 +00:00
plt . close ( )
plot_vaccination_rate ( )
2021-02-04 18:14:12 +00:00
2021-03-09 15:24:13 +00:00
def plot_vaccination_done_days ( ) :
2021-03-23 11:01:51 +00:00
plot_name = ' vaccination_done_days '
if not check_recreate_plot ( plot_name ) :
2021-03-20 12:15:38 +00:00
return
2021-03-09 15:24:13 +00:00
fig , ax = plt . subplots ( 1 )
plt . title (
' Lin. Extrapolation der Erstimpfungen bis 70 % d er Bevölkerung anhand der durchschn. Impfrate (Anzahl Tage, Gesamt und 7 Tage) \n '
' Datenquelle: RKI, Stand: {} . Erstellung: {} , Ersteller: Benedikt Bastin, Lizenz: CC BY-SA 4.0 \n ' . format (
print_stand , print_today
)
)
d = data_first_vaccination
days_remaining_daily = np . ceil ( ( einwohner_deutschland * 0.7 - d [ ' cumulative ' ] ) / ( d [ ' mean_vaccination_rates_daily ' ] ) )
days_remaining_rolling = np . ceil ( ( einwohner_deutschland * 0.7 - d [ ' cumulative ' ] ) / ( d [ ' vaccination_rates_daily_rolling_average ' ] ) )
2021-04-14 11:33:24 +00:00
ax . set_xlim ( start_of_reporting_date , today )
2021-03-09 15:24:13 +00:00
ax . set_ylim ( 0 , 2500 )
2021-04-14 11:33:24 +00:00
ax . axhline ( days_until_target , label = ' Impfziel Ende Sommer ' )
2021-03-09 15:24:13 +00:00
ax . plot ( dates , days_remaining_daily , label = ' Durchschnitt Gesamt ' , linewidth = 0.5 )
ax . plot ( dates , days_remaining_rolling , label = ' Durchschnitt 7 Tage ' , linewidth = 2 )
ax . grid ( True )
2021-04-14 11:46:19 +00:00
d = datetime . date ( 2021 , 3 , 1 )
ax . add_patch ( Rectangle ( ( d , 0 ) , today - d , 52 * 7 , edgecolor = ' darkgrey ' , lw = 3 , fill = False , label = ' Detailansicht (s.u.) ' ) )
2021-03-09 15:24:13 +00:00
ax . legend ( loc = ' upper right ' )
ax . get_yaxis ( ) . get_major_formatter ( ) . set_scientific ( False )
ax . set_xlabel ( ' Datum ' )
ax . set_ylabel ( ' Tage, bis 70 % e rreicht sind ' )
2021-03-23 11:39:25 +00:00
add_annotations ( ax )
2021-03-23 11:01:51 +00:00
save_plot ( plot_name )
2021-03-09 15:24:13 +00:00
plt . close ( )
plot_vaccination_done_days ( )
2021-04-14 11:33:24 +00:00
def plot_vaccination_done_weeks ( ) :
plot_name = ' vaccination_done_weeks '
if not check_recreate_plot ( plot_name ) :
return
fig , ax = plt . subplots ( 1 )
plt . title (
' Lin. Extrapolation der Erstimpfungen bis 70 % d er Bevölkerung anhand der durchschn. Impfrate (Anzahl Wochen, Gesamt und 7 Tage) \n '
' Datenquelle: RKI, Stand: {} . Erstellung: {} , Ersteller: Benedikt Bastin, Lizenz: CC BY-SA 4.0 \n ' . format (
print_stand , print_today
)
)
d = data_first_vaccination
weeks_remaining_daily = np . ceil ( ( einwohner_deutschland * 0.7 - d [ ' cumulative ' ] ) / ( d [ ' mean_vaccination_rates_daily ' ] ) ) / 7
weeks_remaining_rolling = np . ceil ( ( einwohner_deutschland * 0.7 - d [ ' cumulative ' ] ) / ( d [ ' vaccination_rates_daily_rolling_average ' ] ) ) / 7
2021-04-14 11:46:19 +00:00
ax . set_xlim ( datetime . date ( 2021 , 3 , 1 ) , today )
2021-04-14 11:33:24 +00:00
ax . set_ylim ( 0 , 52 )
ax . axhline ( days_until_target / 7 , label = ' Impfziel Ende Sommer ' )
ax . plot ( dates , weeks_remaining_daily , label = ' Durchschnitt Gesamt ' , linewidth = 0.5 )
ax . plot ( dates , weeks_remaining_rolling , label = ' Durchschnitt 7 Tage ' , linewidth = 2 )
ax . grid ( True )
ax . legend ( loc = ' upper right ' )
ax . get_yaxis ( ) . get_major_formatter ( ) . set_scientific ( False )
ax . set_xlabel ( ' Datum ' )
ax . set_ylabel ( ' Wochen, bis 70 % e rreicht sind ' )
add_annotations ( ax )
save_plot ( plot_name )
plt . close ( )
plot_vaccination_done_weeks ( )
2021-03-09 15:24:13 +00:00
def plot_vaccination_done_dates ( ) :
2021-03-23 11:01:51 +00:00
plot_name = ' vaccination_done_dates '
if not check_recreate_plot ( plot_name ) :
2021-03-20 12:15:38 +00:00
return
2021-03-09 15:24:13 +00:00
fig , ax = plt . subplots ( 1 )
plt . title (
' Lin. Extrapolation der Erstimpfungen bis 70 % d er Bevölkerung anhand der durchschn. Impfrate (Datum, Gesamt und 7 Tage) \n '
' Datenquelle: RKI, Stand: {} . Erstellung: {} , Ersteller: Benedikt Bastin, Lizenz: CC BY-SA 4.0 \n ' . format (
print_stand , print_today
)
)
d = data_first_vaccination
#print(d['cumulative'])
#print(np.sum(d['daily']))
#print((einwohner_deutschland - d['cumulative'])[:-1] - d['to_be_vaccinated'])
days_remaining_daily = np . ceil ( ( einwohner_deutschland * 0.7 - d [ ' cumulative ' ] ) / ( d [ ' mean_vaccination_rates_daily ' ] ) )
days_remaining_rolling = np . ceil ( ( einwohner_deutschland * 0.7 - d [ ' cumulative ' ] ) / ( d [ ' vaccination_rates_daily_rolling_average ' ] ) )
dates_daily = [ today + datetime . timedelta ( days ) for days in days_remaining_daily ]
dates_rolling = [ today + datetime . timedelta ( days ) for days in days_remaining_rolling . dropna ( ) ]
#print(dates_rolling)
2021-04-14 11:33:24 +00:00
ax . set_xlim ( start_of_reporting_date , today )
2021-03-09 15:24:13 +00:00
ax . set_ylim ( today , today + datetime . timedelta ( int ( np . max ( days_remaining_rolling ) * 1.05 ) ) )
2021-04-14 11:33:24 +00:00
ax . axhline ( target_date_for_herd_immunity - datetime . timedelta ( 21 ) , label = ' Impfziel Ende Sommer ' )
2021-03-09 15:24:13 +00:00
ax . plot ( dates , dates_daily , label = ' Durchschnitt Gesamt ' , linewidth = 0.5 )
ax . plot ( dates [ 6 : ] , dates_rolling , label = ' Durchschnitt 7 Tage ' , linewidth = 2 )
ax . grid ( True )
ax . legend ( loc = ' upper right ' )
ax . set_xlabel ( ' Datum ' )
ax . set_ylabel ( ' Datum, an dem 70 % e rreicht sind ' )
2021-03-23 11:39:25 +00:00
add_annotations ( ax )
2021-03-23 11:01:51 +00:00
save_plot ( plot_name )
2021-03-09 15:24:13 +00:00
plt . close ( )
plot_vaccination_done_dates ( )
2021-01-17 01:34:49 +00:00
def render_dashboard ( ) :
dashboard_filename = ' site/index.xhtml '
dashboard_archive_filename = ' site/archive/ {} /index.xhtml ' . format ( filename_stand )
stylesheet_filename = ' site/rki-dashboard.css '
stylesheet_archive_filename = ' site/archive/ {} /rki-dashboard.css ' . format ( filename_stand )
2021-03-23 11:14:50 +00:00
if os . path . isfile ( dashboard_archive_filename ) and not force_renew_dashboard :
2021-01-17 01:34:49 +00:00
print ( ' Dashboard {} already exists ' . format ( dashboard_archive_filename ) )
return
from jinja2 import Template , Environment , FileSystemLoader , select_autoescape
env = Environment (
loader = FileSystemLoader ( ' ./ ' ) ,
autoescape = select_autoescape ( [ ' html ' , ' xml ' , ' xhtml ' ] )
)
german_text_date_format = ' %d . % B % Y '
df = german_text_date_format
german_text_datetime_format = ' %d . % B % Y, % H: % M: % S Uhr '
dtf = german_text_datetime_format
latest_dashboard_filename = site_folder + ' index.xhtml '
archive_dashboard_filename = archive_folder
template = env . get_template ( ' dashboard_template.xhtml ' )
template . stream (
stand = stand_date . strftime ( dtf ) ,
filename_stand = filename_stand ,
einwohner_deutschland = ' {:n} ' . format ( einwohner_deutschland ) . replace ( ' . ' , ' ' ) ,
herd_immunity = ' {:n} ' . format ( int ( herd_immunity * 100 ) ) ,
2021-02-10 16:45:52 +00:00
target_date_for_herd_immunity = target_date_for_herd_immunity ,
target_date_for_herd_immunity_str = target_date_for_herd_immunity . strftime ( ' %d . % B % Y ' ) ,
days_until_target = days_until_target ,
2021-01-31 19:57:02 +00:00
data_first_vaccination = data_first_vaccination ,
data_second_vaccination = data_second_vaccination ,
#details_per_land = dict(sorted(details_per_land_formatted.items(), key=lambda item: item[0])),
#details_total = details_total_formatted
2021-02-17 11:11:49 +00:00
figures = [
{
' index ' : 1 ,
' filename ' : ' vaccination_bar_graph_total_time ' ,
' caption ' : ' Tägliche Impfrate (Erst- und Zweitimpfung übereinander) '
} , {
2021-03-20 11:21:22 +00:00
' index ' : 2 ,
2021-03-20 12:15:38 +00:00
' filename ' : ' vaccination_bar_graph_total_time_by_week ' ,
' caption ' : ' Wöchentliche Impfrate (Erst- und Zweitimpfung übereinander) '
} , {
' index ' : 3 ,
2021-02-17 11:11:49 +00:00
' filename ' : ' vaccination_bar_graph_total_time_two_bars ' ,
' caption ' : ' Tägliche Impfrate (Erst- und Zweitimpfung nebeneinander) '
} , {
2021-03-20 12:15:38 +00:00
' index ' : 4 ,
2021-02-17 11:11:49 +00:00
' filename ' : ' vaccination_bar_graph_compare_both_vaccinations ' ,
' caption ' : ' Tägliche Impfrate (Erst- und Zweitimpfung nebeneinander) '
} , {
2021-03-20 12:15:38 +00:00
' index ' : 5 ,
2021-02-17 11:11:49 +00:00
' filename ' : ' cumulative_two_vaccinations ' ,
' caption ' : ' Kumulative Impfrate (Erst- und Zweitimpfung) '
} , {
2021-03-20 12:15:38 +00:00
' index ' : 6 ,
2021-02-17 11:11:49 +00:00
' filename ' : ' cumulative_two_vaccinations_percentage ' ,
' caption ' : ' Kumulative Impfrate (Erst- und Zweitimpfung) in Prozent der Bevölkerung Deutschlands '
} , {
2021-03-20 12:15:38 +00:00
' index ' : 7 ,
2021-02-17 11:11:49 +00:00
' filename ' : ' people_between_first_and_second ' ,
' caption ' : ' Anzahl der Personen zwischen Erst- und Zweitimpfung, also Personen, die die erste Impfung erhalten haben, die zweite aber noch nicht '
} , {
2021-03-20 12:15:38 +00:00
' index ' : 8 ,
2021-02-17 11:11:49 +00:00
' filename ' : ' vaccination_rate ' ,
' caption ' : ' Tägliche Impfrate sowie durchschnittliche Impfrate '
2021-03-09 15:24:13 +00:00
} , {
2021-03-20 12:15:38 +00:00
' index ' : 9 ,
2021-03-09 15:24:13 +00:00
' filename ' : ' vaccination_done_days ' ,
' caption ' : ' Lineare Extrapolation bis 70 % d er Bevölkerung anhand der Erstimpfungen der durchschnittlichen Impfrate (Anzahl Tage, Gesamt und 7 Tage) '
} , {
2021-03-20 12:15:38 +00:00
' index ' : 10 ,
2021-04-14 11:33:24 +00:00
' filename ' : ' vaccination_done_weeks ' ,
' caption ' : ' Lineare Extrapolation bis 70 % d er Bevölkerung anhand der Erstimpfungen der durchschnittlichen Impfrate (Anzahl Wochen, Gesamt und 7 Tage) '
} , {
' index ' : 11 ,
2021-03-09 15:24:13 +00:00
' filename ' : ' vaccination_done_dates ' ,
' caption ' : ' Lineare Extrapolation bis 70 % d er Bevölkerung anhand der Erstimpfungen der durchschnittlichen Impfrate (Datum, Gesamt und 7 Tage) '
2021-02-17 11:11:49 +00:00
}
]
2021-01-17 01:34:49 +00:00
) . dump ( ' site/index.xhtml ' )
shutil . copyfile ( dashboard_filename , dashboard_archive_filename )
shutil . copyfile ( stylesheet_filename , stylesheet_archive_filename )
print ( ' Created dashboard ' )
render_dashboard ( )