d2ef00a689a33efbe6d0d4730cbac11486771c03
[covid19.git] / test_and_case_data.py
1 #!/usr/bin/env python
2 # coding: utf-8
3 # %%
4 import itertools
5 import collections
6 import json
7 import pandas as pd
8 import numpy as np
9 from scipy.stats import gmean
10 import datetime
11 import os
12 import sqlalchemy
13
14 import matplotlib as mpl
15 import matplotlib.pyplot as plt
16 import matplotlib.animation as ani
17 plt.ioff()
18 # # %matplotlib inline
19
20
21 # %%
22 chart_start_date = '2020-09-15'
23
24
25 # %%
26 connection_string = 'postgresql://covid:3NbjJTkT63@localhost/covid'
27
28
29 # %%
30 engine = sqlalchemy.create_engine(connection_string)
31
32 # %%
33 query_string = '''select uk_data.date,
34 uk_data.new_cases, uk_data_7.new_cases as new_cases_7,
35 uk_data.new_tests, uk_data_7.new_tests as new_tests_7,
36 uk_data.new_pcr_tests, uk_data_7.new_pcr_tests as new_pcr_7,
37 uk_data.new_pillar_1_2_tests as new_pillar_12, uk_data_7.new_pillar_1_2_tests as new_pillar_12_7,
38 uk_data.new_cases::float / uk_data.new_tests as fraction_positive,
39 uk_data_7.new_cases / uk_data_7.new_tests as fraction_positive_7
40 from uk_data left outer join uk_data_7 using (date)
41 order by uk_data.date'''
42 tests_data = pd.read_sql_query(query_string, engine,
43 index_col='date',
44 parse_dates = ['date'])
45
46 # %%
47 pri_y_max = int((tests_data.dropna().loc[chart_start_date: , 'new_tests_7'].max() * 1.1) / 100 ) * 100
48 ax = tests_data.dropna().loc[chart_start_date: , 'new_tests_7'].plot(figsize=(10, 8),
49 style=['k-'],
50 legend=False,
51 ylim=(0, pri_y_max))
52 ax.set_title('Tests done and new cases (7 day moving average)')
53 ax.legend(['Tests, 7 day moving average'], loc='lower left')
54 ax.set_ylabel('Tests')
55 sec_y_max = int((tests_data.dropna().loc[chart_start_date:, 'new_cases_7'].max() * 1.1) / 100) * 100
56 ax = tests_data.dropna().loc[chart_start_date:, 'new_cases_7'].plot(ax=ax, secondary_y=True, style='r--')
57 ax.set_ylim((0, sec_y_max))
58 ax.legend(['Cases (7 day moving average)'], loc='lower right')
59 ax.set_ylabel('New cases')
60 plt.savefig('tests_and_cases.png')
61
62
63 # %%
64 ax = (tests_data.loc[chart_start_date: , ['fraction_positive', 'fraction_positive_7']] * 100).plot(figsize=(10, 8),
65 style=['b:', 'k-'], legend=False)
66 ax.set_title('Fraction of tests with positive results')
67 ax.legend(['Fraction positive (%)', 'Fraction positive (%), 7 day moving average'], loc='upper left')
68 ax.set_ylabel('Fraction positive')
69 cases_axis_max = (1.0 * tests_data.loc[chart_start_date:].new_cases_7.max()
70 * tests_data.loc[chart_start_date:].fraction_positive.max()
71 / tests_data.loc[chart_start_date:].fraction_positive_7.max()
72 )
73
74 ax2 = ax.twinx()
75 ax2 = tests_data.loc[chart_start_date:, 'new_cases_7'].plot(ax=ax2, secondary_y=True, style='r--')
76 ax2.set_ylim(-1000, cases_axis_max)
77 ax2.legend(['Cases (7 day moving average)'], loc='center left')
78 ax2.set_ylabel('New cases')
79 plt.savefig('fraction_positive_tests.png')
80
81
82 # %%
83 ax = tests_data.dropna().loc[chart_start_date:].plot(x='fraction_positive_7', y='new_tests_7',
84 figsize=(8, 8),
85 legend=None)
86 ax.set_xlabel("Fraction of tests that are positive")
87 ax.set_ylabel("Number of tests")
88 for d in tests_data.dropna().loc[chart_start_date::15].index:
89 ax.plot(tests_data.loc[d, 'fraction_positive_7'], tests_data.loc[d, 'new_tests_7'], 'o',
90 markersize=8)#, markerfacecolor=marker_col, markeredgecolor=marker_col)
91 ax.text(tests_data.loc[d, 'fraction_positive_7'] + 0.0002, tests_data.loc[d, 'new_tests_7'],
92 s = d.strftime("%d %B %Y"))
93 plt.savefig('fraction_positive_tests_vs_tests.png')
94
95
96 # %%
97 fig = plt.figure(figsize=(8, 8))
98 plt.ylabel('Number of tests')
99 plt.xlabel('Fraction of tests that are positive')
100 all_data = tests_data.dropna().loc[chart_start_date:]
101
102
103 minx = all_data.fraction_positive_7.min() * 0.9
104 maxx = all_data.fraction_positive_7.max() * 1.1
105 miny = all_data.new_tests_7.min() * 0.9
106 maxy = all_data.new_tests_7.max() * 1.1
107
108 plt.xlim(minx, maxx)
109 plt.ylim(miny, maxy)
110 # plt.legend(None)
111
112 def build_state_frame(i):
113 this_data = all_data[:i]
114 plt.clf()
115 plt.ylabel('Number of tests')
116 plt.xlabel('Fraction of tests that are positive')
117 plt.xlim(minx, maxx)
118 plt.ylim(miny, maxy)
119 p = plt.plot(this_data.fraction_positive_7, this_data.new_tests_7)
120 p[0].set_color('r')
121 for d in this_data[::15].index:
122 plt.plot(this_data.loc[d, 'fraction_positive_7'],
123 this_data.loc[d, 'new_tests_7'], 'o',
124 markersize=8, markerfacecolor='r', markeredgecolor='r')
125 plt.text(this_data.loc[d, 'fraction_positive_7'] + 0.0002,
126 this_data.loc[d, 'new_tests_7'],
127 s = d.strftime("%d %B %Y"))
128
129 animator = ani.FuncAnimation(fig, build_state_frame,
130 frames=all_data.shape[0]+1,
131 interval=100,
132 repeat_delay=200,
133 repeat=True)
134 animator.save('tests_vs_fraction_positive.mp4')
135 # plt.show()
136
137
138 # %%
139 os.system('rm tests_vs_fraction_positive_animation.png')
140 os.system('ffmpeg -i tests_vs_fraction_positive.mp4 -plays 0 -final_delay 1 -f apng tests_vs_fraction_positive_animation.png')
141
142
143 # %%
144
145
146
147