def plot_mobility(series, label, stringency = None, until = None, annotation = "Google Mobility Data; baseline mobility measured from Jan 3 - Feb 6"): plt.plot(series.date, smoothed(series.retail_and_recreation_percent_change_from_baseline), label = "Retail/Recreation") plt.plot(series.date, smoothed(series.grocery_and_pharmacy_percent_change_from_baseline), label = "Grocery/Pharmacy") plt.plot(series.date, smoothed(series.parks_percent_change_from_baseline), label = "Parks") plt.plot(series.date, smoothed(series.transit_stations_percent_change_from_baseline), label = "Transit Stations") plt.plot(series.date, smoothed(series.workplaces_percent_change_from_baseline), label = "Workplaces") plt.plot(series.date, smoothed(series.residential_percent_change_from_baseline), label = "Residential") if until: right = pd.Timestamp(until) elif stringency is not None: right = stringency.Date.max() else: right = series.date.iloc[-1] lax = plt.gca() if stringency is not None: plt.sca(lax.twinx()) stringency_IN = stringency.query("CountryName == 'India'") stringency_US = stringency.query("(CountryName == 'United States') & (RegionName.isnull())", engine = "python") plt.plot(stringency_IN.Date, stringency_IN.StringencyIndex, 'k--', alpha = 0.6, label = "IN Measure Stringency") plt.plot(stringency_US.Date, stringency_US.StringencyIndex, 'k.' , alpha = 0.6, label = "US Measure Stringency") plt.PlotDevice().ylabel("lockdown stringency index", rotation = -90, labelpad = 50) plt.legend() plt.sca(lax) plt.legend(loc = "lower right") plt.fill_betweenx((-100, 60), pd.to_datetime("March 24, 2020"), pd.to_datetime("June 1, 2020"), color = "black", alpha = 0.05, zorder = -1) plt.text(s = "national lockdown", x = pd.to_datetime("April 27, 2020"), y = -90, fontdict = plt.theme.note, ha = "center", va = "top") plt.PlotDevice()\ .xlabel("\ndate")\ .ylabel("% change in mobility\n") # .title(f"\n{label}: Mobility & Lockdown Trends")\ # .annotate(annotation)\ plt.ylim(-100, 60) plt.xlim(left = series.date.iloc[0], right = right)
def demand_curves(ranking_provider, vax_policy, phis=[25, 50, 100, 200], phi_benchmark=25, N_state=N_TN): wtp_rankings = {phi: ranking_provider(phi, vax_policy) for phi in phis} figure = plt.figure() lines = [] # benchmark benchmark = wtp_rankings[phi_benchmark] x_pop = list( chain(*zip(benchmark.loc[0]["num_vax"].shift(1).fillna(0), benchmark.loc[0]["num_vax"]))) y_wtp = list( chain(*zip(benchmark.loc[0]["wtp_pc_usd"], benchmark.loc[0] ["wtp_pc_usd"]))) lines.append( plt.plot(x_pop, y_wtp, figure=figure, color="black", linewidth=2)[0]) lines.append(plt.plot(0, 0, color="white")[0]) # plot dynamic curve for (phi, all_wtp) in wtp_rankings.items(): daily_doses = phi * percent * annually * N_state distributed_doses = 0 x_pop = [] y_wtp = [] t_vax = [] ranking = 0 for t in range(simulation_range): wtp = all_wtp.loc[t].reset_index() ranking = wtp[(wtp.index >= ranking) & (wtp.num_vax > distributed_doses)].index.min() if np.isnan(ranking): break x_pop += [distributed_doses, distributed_doses + daily_doses] t_vax += [t, t + 1] y_wtp += [wtp.iloc[ranking].wtp_pc_usd] * 2 distributed_doses += daily_doses lines.append( plt.plot(x_pop, y_wtp, label=f"dynamic, {vax_policy}, $\phi = ${phi}%", figure=figure)[0]) plt.legend(lines, [f"static, t = 0, $\phi = ${phi_benchmark}%", ""] + [f"dynamic, {vax_policy}, $\phi = ${phi}%" for phi in phis], title="allocation", title_fontsize="24", fontsize="20") plt.xticks(fontsize="20") plt.yticks(fontsize="20") plt.PlotDevice().ylabel("WTP (USD)\n").xlabel("\nnumber vaccinated") plt.ylim(0, 350) plt.xlim(left=0, right=N_TN) plt.show()
def plot_district_age_distribution(percentiles, ylabel, fmt, phi=50, vax_policy="random", N_jk=None, n=5, district_spacing=1.5, age_spacing=0.1, rotation=0): fig = plt.figure() district_ordering = list(districts_to_run.index)[:n] for (i, district) in enumerate(district_ordering): ylls = percentiles[district, phi, vax_policy] for j in range(7): plt.errorbar(x=[district_spacing * i + age_spacing * (j - 3)], y=ylls[1, 6 - j] * USD / (N_jk[f"N_{6-j}"][district] if N_jk else 1), yerr=[[(ylls[1, 6 - j] - ylls[0, 6 - j]) * USD / (N_jk[f"N_{6-j}"][district] if N_jk else 1)], [(ylls[2, 6 - j] - ylls[1, 6 - j]) * USD / (N_jk[f"N_{6-j}"][district] if N_jk else 1)]], fmt=fmt, color=age_group_colors[6 - j], figure=fig, label=None if i > 0 else age_bin_labels[6 - j], ms=12, elinewidth=5) plt.xticks([1.5 * _ for _ in range(n)], district_ordering, rotation=rotation, fontsize="20") plt.yticks(fontsize="20") plt.legend(title="age bin", title_fontsize="20", fontsize="20", ncol=7, loc="lower center", bbox_to_anchor=(0.5, 1)) ymin, ymax = plt.ylim() plt.vlines(x=[0.75 + 1.5 * _ for _ in range(n - 1)], ymin=ymin, ymax=ymax, color="gray", alpha=0.5, linewidths=2) plt.ylim(ymin, ymax) plt.gca().grid(False, axis="x") plt.PlotDevice().title(f"\n{vax_policy} demand curves").ylabel( f"{ylabel}\n")
def plot_state_age_distribution(percentiles, ylabel, fmt, district_spacing=1.5, n=5, age_spacing=0.1, rotation=0, ymin=0, ymax=1000): fig = plt.figure() state_ordering = list( sorted(percentiles.keys(), key=lambda k: percentiles[k][0].max(), reverse=True)) for (i, state) in enumerate(state_ordering[:n]): ylls = percentiles[state] for j in range(7): plt.errorbar(x=[district_spacing * i + age_spacing * (j - 3)], y=ylls[0, 6 - j], yerr=[[(ylls[0, 6 - j] - ylls[1, 6 - j])], [(ylls[2, 6 - j] - ylls[0, 6 - j])]], fmt=fmt, color=agebin_colors[6 - j], figure=fig, label=None if i > 0 else agebin_labels[6 - j], ms=12, elinewidth=5) plt.xticks([1.5 * _ for _ in range(n)], state_ordering, rotation=rotation, fontsize="20") plt.yticks(fontsize="20") # plt.legend(title = "age bin", title_fontsize = "20", fontsize = "20", ncol = 7, plt.legend(fontsize="20", ncol=7, loc="lower center", bbox_to_anchor=(0.5, 1)) plt.vlines(x=[0.75 + 1.5 * _ for _ in range(n - 1)], ymin=ymin, ymax=ymax, color="gray", alpha=0.5, linewidths=4) plt.ylim(ymin, ymax) plt.gca().grid(False, axis="x") plt.PlotDevice().ylabel(f"{ylabel}\n")
def outcomes_per_policy(percentiles, metric_label, fmt, phis=[25, 50, 100, 200], reference=(25, "no_vax"), reference_color=no_vax_color, vax_policies=["contact", "random", "mortality"], policy_colors=[ contactrate_vax_color, random_vax_color, mortality_vax_color ], policy_labels=[ "contact rate priority", "random assignment", "mortality priority" ], spacing=0.2): fig = plt.figure() md, lo, hi = percentiles[reference] *_, bars = plt.errorbar(x=[0], y=[md], yerr=[[md - lo], [hi - md]], figure=fig, fmt=fmt, color=reference_color, label="no vaccination", ms=12, elinewidth=5) [_.set_alpha(0.5) for _ in bars] plt.hlines(md, xmin=-1, xmax=5, linestyles="dotted", colors=reference_color) for (i, phi) in enumerate(phis, start=1): for (j, (vax_policy, color, label)) in enumerate( zip(vax_policies, policy_colors, policy_labels)): md, lo, hi = death_percentiles[phi, vax_policy] *_, bars = plt.errorbar(x=[i + spacing * (j - 1)], y=[md], yerr=[[md - lo], [hi - md]], figure=fig, fmt=fmt, color=color, label=label if i == 0 else None, ms=12, elinewidth=5) [_.set_alpha(0.5) for _ in bars] plt.legend(ncol=4, fontsize="20", loc="lower center", bbox_to_anchor=(0.5, 1)) plt.xticks(range(len(phis) + 1), [f"$\phi = {phi}$%" for phi in ([0] + phis)], fontsize="20") plt.yticks(fontsize="20") plt.PlotDevice().ylabel(f"{metric_label}\n") plt.gca().grid(False, axis="x") ymin, ymax = plt.ylim() plt.vlines(x=[0.5 + _ for _ in range(len(phis))], ymin=ymin, ymax=ymax, color="gray", alpha=0.5, linewidths=2) plt.ylim(ymin, ymax) plt.xlim(-0.5, len(phis) + 1.5)
plt.yticks(fontsize="20") plt.legend([scatter_TN, plot_TN, scatter_TT, plot_TT], [ "Tamil Nadu (raw)", "Tamil Nadu (smoothed)", "India (raw)", "India (smoothed)" ], fontsize="20", ncol=4, framealpha=1, handlelength=0.75, loc="lower center", bbox_to_anchor=(0.5, 1)) plt.gca().xaxis.set_major_formatter(plt.bY_FMT) plt.gca().xaxis.set_minor_formatter(plt.bY_FMT) plt.xlim(left=pd.Timestamp("March 1, 2020"), right=pd.Timestamp("April 15, 2021")) plt.ylim(bottom=0) plt.PlotDevice().ylabel("per-capita infection rate\n").xlabel("\ndate") plt.show() # 1B: per capita vaccination rates vax = load_vax_data()\ .reindex(pd.date_range(start = pd.Timestamp("Jan 1, 2021"), end = simulation_start, freq = "D"), fill_value = 0)\ [pd.Timestamp("Jan 1, 2021"):simulation_start]\ .drop(labels = [pd.Timestamp("2021-03-15")]) # handle NAN plt.plot(vax.index, vax["Tamil Nadu"] / N_TN, color=TN_color, label="Tamil Nadu", linewidth=2) plt.plot(vax.index,
data = Path("./data") download_data(data, 'timeseries.json', "https://api.covid19india.org/v3/") # data prep with (data/'timeseries.json').open("rb") as fp: df = flat_table.normalize(pd.read_json(fp)).fillna(0) df.columns = df.columns.str.split('.', expand = True) dates = np.squeeze(df["index"][None].values) df = df.drop(columns = "index").set_index(dates).stack([1, 2]).drop("UN", axis = 1) series = mobility[mobility.sub_region_1.isna()] plt.plot(series.date, smoothed(series.retail_and_recreation_percent_change_from_baseline), label = "Retail/Recreation") plt.fill_betweenx((-100, 60), pd.to_datetime("March 24, 2020"), pd.to_datetime("June 1, 2020"), color = "black", alpha = 0.05, zorder = -1) plt.text(s = "national lockdown", x = pd.to_datetime("April 27, 2020"), y = -20, fontdict = plt.note_font, ha = "center", va = "top") plt.ylim(-100, 10) plt.xlim(series.date.min(), series.date.max()) plt.legend(loc = 'upper right') lax = plt.gca() plt.sca(lax.twinx()) plt.plot(df["TT"][:, "delta", "confirmed"].index, smoothed(df["TT"][:, "delta", "confirmed"].values), label = "Daily Cases", color = plt.PRED_PURPLE) plt.legend(loc = 'lower right') plt.PlotDevice().ylabel("new cases", rotation = -90, labelpad = 50) plt.sca(lax) plt.PlotDevice().title("\nIndia Mobility and Case Count Trends")\ .annotate("Google Mobility Data + Covid19India.org")\ .xlabel("\ndate")\ .ylabel("% change in mobility\n") plt.show() plt.plot(series.date, smoothed(series.retail_and_recreation_percent_change_from_baseline), label = "Retail/Recreation")
for (R0, t) in schedule: R0_timeseries += [R0] * t sir_model.Rt0 = R0 sir_model.run(t) total_t += t plt.plot(sir_model.dT) plt.show() plt.plot(R0_timeseries, "-", color="black", label="$R_0$") plt.plot(sir_model.Rt, "-", color="dodgerblue", label="$R_t$") plt.legend(framealpha=1, handlelength=1, loc="best") plt.PlotDevice().xlabel("time").ylabel("reproductive rate").adjust(left=0.10, bottom=0.15, right=0.99, top=0.99) plt.ylim(0.5, 1.5) plt.show() # 1: parametric scheme: dates, Rt, Rt_lb, Rt_ub, *_, anomalies, anomaly_dates = analytical_MPVS( pd.DataFrame(sir_model.dT), smoothing=convolution("uniform", 2), CI=0.99, totals=False) pd = plt.Rt(dates, Rt, Rt_ub, Rt_lb, ymin = 0.5, ymax = 2.5, CI = 0.99, yaxis_colors = False, format_dates = False, critical_threshold = False)\ .xlabel("time")\ .ylabel("reproductive rate")\ .adjust(left = 0.11, bottom = 0.15, right = 0.98, top = 0.98) plt.plot(sir_model.Rt, "-", color="white", linewidth=3, zorder=10) sim_rt, = plt.plot(sir_model.Rt, "-",
label=f"dynamic, {vax_policy}, $phi = ${phi}%", figure=figure)[0] ] plt.legend( lines, # ["static, t = 0, $\phi = $50%", ""] + [f"dynamic, {vax_policy}, $\phi = ${phi}%" for phi in phis], ["static, t = 0, $phi = $50%", ""] + [f"dynamic, {vax_policy}, $phi = ${phi}%" for phi in phis], title="allocation", title_fontsize="24", fontsize="20") plt.xticks(fontsize="20") plt.yticks(fontsize="20") plt.PlotDevice().ylabel("TEV (USD)\n").xlabel( "\npercentage of country vaccinated") plt.ylim(0, 1600) plt.xlim(left=0, right=100) plt.show() # 3C: YLL per million choropleth if "3C" in figs_to_run or run_all: india = gpd.read_file(data/"india.geojson")\ .drop(columns = ["id", "dt_code", "st_code", "year"])\ .rename(columns = {"st_nm": "state"})\ .set_index(["state", "district"])\ .rename(index = lambda s: s.replace(" and ", " And "))\ .assign( dissolve_state = lambda _:_.index.get_level_values(0), dissolve_district = lambda _:np.where( _.index.isin(coalesce_states, level = 0), _.index.get_level_values(0),
plt.vlines(x=pd.Timestamp("March 1, 2021"), ymin=-60, ymax=10, linewidths=2, color="grey", linestyles="dotted") plt.text(x=pd.Timestamp("March 2, 2021"), y=-40, s=" $2^{nd}$\n wave\n starts", ha="left", va="bottom", color="grey", font_properties=FontProperties(family=plt.theme.note["family"], size=14)) plt.xlim(MH_mob.index[0] - one_day, MH_mob.index[-1] + one_day) plt.ylim(-60, 10) plt.legend([IN_marker, MH_marker], ["all India", "Maharashtra"], handlelength=0.5, framealpha=0, prop={'size': 16}, loc="upper center", ncol=2) plt.show() # fig 5: variants mutations = pd.read_json(data/"outbreakinfo_mutation_report_data_2021-04-18.json")\ .set_index("date_time") \ .loc["October 1, 2020":] \ .drop(columns = "source") \ * 100
estimates = pd.DataFrame(estimates) estimates.columns = ["regency", "Rt", "Rt_CI_lower", "Rt_CI_upper", "Rt_proj"] estimates.set_index("regency", inplace=True) estimates.to_csv("data/SULSEL_Rt_projections.csv") print(estimates) gdf = gpd.read_file("data/gadm36_IDN_shp/gadm36_IDN_2.shp")\ .query("NAME_1 == 'Sulawesi Selatan'")\ .merge(estimates, left_on = "NAME_2", right_on = "regency") choro = plt.choropleth(gdf, mappable=plt.get_cmap(0.4, 1.4, "viridis")) for ax in choro.figure.axes[:-1]: plt.sca(ax) plt.xlim(left=119, right=122) plt.ylim(bottom=-7.56, top=-1.86) plt.show() logger.info("adaptive control") (dates, Rt_pred, Rt_CI_upper, Rt_CI_lower, T_pred, T_CI_upper, T_CI_lower, total_cases, new_cases_ts, anomalies, anomaly_dates)\ = analytical_MPVS(new_cases, CI = CI, smoothing = smoothing, totals = False) Rt = pd.DataFrame(data={"Rt": Rt_pred[1:]}, index=dates) Rt_current = Rt_pred[-1] Rt_m = np.mean(Rt[(Rt.index >= "April 21, 2020") & (Rt.index <= "May 22, 2020")])[0] Rt_v = np.mean(Rt[(Rt.index <= "April 14, 2020")])[0] Rt_m_scaled = Rt_current + 0.75 * (Rt_m - Rt_current) Rt_v_scaled = Rt_current + 0.75 * (Rt_v - Rt_current)
sulsel = pd.read_csv("data/3 OCT 2020 Data collection template update South Sulawesi_CASE.csv", usecols = schema.keys())\ .rename(columns = schema)\ .dropna(how = 'all') parse_datetimes(sulsel.loc[:, "confirmed"]) sulsel = sulsel.confirmed.value_counts().sort_index() plt.plot(dkij.index, dkij.values, color="royalblue", label="private") plt.plot(dkij_public.diff(), color="firebrick", label="public") plt.legend() plt.PlotDevice()\ .title("\nJakarta: public vs private case counts")\ .xlabel("date")\ .ylabel("cases") plt.xlim(right=dkij.index.max()) plt.ylim(top=800) plt.show() plt.plot(sulsel, color="royalblue", label="private", linewidth=3) plt.plot(sulsel_public.diff(), color="firebrick", label="public") plt.legend() plt.PlotDevice()\ .title("\nSouth Sulawesi: public vs private case counts")\ .xlabel("date")\ .ylabel("cases") plt.xlim(right=sulsel.index.max()) plt.show() # correlation: dkij dkij_diff = dkij_public.diff().dropna() dkij_pub_clipped = dkij_diff[dkij_diff.index <= dkij.index.max()].iloc[1:]
(dates, Rt_pred, Rt_CI_upper, Rt_CI_lower, T_pred, T_CI_upper, T_CI_lower, total_cases, new_cases_ts, anomalies, anomaly_dates)\ = analytical_MPVS(age_ts.sum(level = 1), CI = CI, smoothing = smoothing, totals = False) MAK = SIR(name="MAK", population=1.339e6, dT0=T_pred[-1], Rt0=Rt_pred[-1], upper_CI=T_CI_upper[-1], lower_CI=T_CI_lower[-1], mobility=0, random_seed=0, I0=age_ts.sum(level=1).sum()).run(30) plt.daily_cases(dates, T_pred, T_CI_upper, T_CI_lower, new_cases_ts, anomaly_dates, anomalies, CI, prediction_ts = [ (MAK.dT[:-1], MAK.lower_CI[1:], MAK.upper_CI[1:], plt.PRED_PURPLE, "current social distancing"), (*rt1_10x, "orange", "10% increase in school-age $R_t$"), (*rt1_25x, "mediumseagreen", "25% increase in school-age $R_t$"), (*rt1_50x, "hotpink", "50% increase in school-age $R_t$"), ])\ .xlabel("\ndate")\ .ylabel("cases\n") # .title("\nMakassar Daily Cases - school reopening scenarios")\ # .annotate("\nBayesian training process on empirical data, with anomalies identified") (_, r) = plt.xlim() plt.xlim(left=pd.Timestamp("Sep 1, 2020"), right=r) plt.ylim(bottom=10, top=1000) plt.vlines(dates[-1], ymin=1, ymax=1000, color="black", linestyles="solid") plt.semilogy() plt.show()
framealpha=1, handlelength=1) plt.xlim(right=pd.Timestamp("Jan 01, 2022")) plt.PlotDevice()\ .xlabel("\nDate")\ .ylabel("Probability\n") plt.subplots_adjust(left=0.12, bottom=0.12, right=0.94, top=0.96) plt.gca().xaxis.set_minor_locator(mpl.ticker.NullLocator()) plt.gca().xaxis.set_minor_formatter(mpl.ticker.NullFormatter()) plt.gca().xaxis.set_major_locator(mdates.AutoDateLocator()) plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%b %d')) plt.xticks(fontsize="16") plt.yticks(fontsize="16") plt.gca().xaxis.grid(True, which="major") plt.semilogy() plt.ylim(bottom=1e-7) plt.show() PrD = pd.DataFrame(prob_death).set_index( pd.date_range(start=simulation_start, freq="D", periods=len(prob_death))) plt.plot(PrD, color=TN_color, linewidth=2, label="probability of death") plt.xlim(left=pd.Timestamp("Jan 01, 2021"), right=pd.Timestamp("Jan 01, 2022")) plt.PlotDevice().ylabel("log-probability\n") # plt.subplots_adjust(left = 0.12, bottom = 0.12, right = 0.94, top = 0.96) plt.gca().xaxis.set_minor_locator(mpl.ticker.NullLocator()) plt.gca().xaxis.set_minor_formatter(mpl.ticker.NullFormatter()) plt.gca().xaxis.set_major_locator(mdates.AutoDateLocator()) plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%b %y')) plt.xticks(fontsize="20", rotation=45) plt.yticks(fontsize="20") plt.gca().xaxis.grid(True, which="major")