cases = cases.query("regency == 'Makassar'").dropna(subset = ["age"]) cases["age_bin"] = pd.cut(cases.age, [0, 20, 100], labels = ["school", "nonschool"]) cases = cases[cases.confirmed <= "Oct 25, 2020"] age_ts = cases[["age_bin", "confirmed"]].groupby(["age_bin", "confirmed"]).size().sort_index() (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.loc["school"], CI = CI, smoothing = smoothing, totals = False) school_Rt = np.mean(Rt_pred[-14:]) school_T_lb = T_CI_lower[-1] school_T_ub = T_CI_upper[-1] plt.Rt(dates, Rt_pred, Rt_CI_upper, Rt_CI_lower, CI)\ .title("\nMakassar: Reproductive Number Estimate: school-age population")\ .xlabel("\ndate")\ .ylabel("$R_t$\n", rotation=0, labelpad=30)\ .annotate(f"\n{window}-day smoothing window, gamma-prior Bayesian estimation method")\ .show() (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.loc["nonschool"], CI = CI, smoothing = smoothing, totals = False) plt.Rt(dates, Rt_pred, Rt_CI_upper, Rt_CI_lower, CI)\ .title("\nMakassar: Reproductive Number Estimate: non-school-age population")\ .xlabel("\ndate")\ .ylabel("$R_t$\n", rotation=0, labelpad=30)\ .annotate(f"\n{window}-day smoothing window, gamma-prior Bayesian estimation method")\ .show() nonschool_Rt = np.mean(Rt_pred[-14:]) nonschool_T_lb = T_CI_lower[-1]
window = 7 * days CI = 0.95 smooth = notched_smoothing(window) (dates_I, Rt_I, Rtu_I, Rtl_I, *_) = analytical_MPVS(df[state][:, "delta", "confirmed"], CI=CI, smoothing=smooth, totals=False) (dates_D, Rt_D, Rtu_D, Rtl_D, *_) = analytical_MPVS(df[state][:, "delta", "deceased"], CI=CI, smoothing=smooth, totals=False) plt.Rt(dates_I, Rt_I, Rtu_I, Rtl_I, CI)\ .title(f"{state} - $R_t(I)$ estimator") plt.figure() plt.Rt(dates_D, Rt_D, Rtu_D, Rtl_D, CI)\ .title(f"{state} - $R_t(D)$ estimator") plt.show() KA_dD = df["KA"][:, "delta", "deceased"] KA_D = KA_dD.cumsum() L = 14 dist = Exponential(scale=1 / L) pmf = dist.pdf(np.linspace(dist.ppf(0.005), dist.ppf(1 - 0.005))) pmf /= pmf.sum() D_deconv, _ = deconvolve(KA_D, pmf) D_deconv *= 1 / 0.02
province_cases = {province: load_province_timeseries(data, province) for province in provinces} bgn = min(cases.index.min() for cases in province_cases.values()) end = max(cases.index.max() for cases in province_cases.values()) idx = pd.date_range(bgn, end) province_cases = {province: cases.reindex(idx, method = "pad").fillna(0) for (province, cases) in province_cases.items()} natl_cases = sum(province_cases.values()) logger.info("running national-level Rt estimate") (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(natl_cases, CI = CI, smoothing = smoothing) plt.Rt(dates, Rt_pred, Rt_CI_upper, Rt_CI_lower, CI, ymin=0, ymax=4)\ .title("\nIndonesia: Reproductive Number Estimate")\ .xlabel("\ndate")\ .ylabel("$R_t$", rotation=0, labelpad=30)\ .annotate(f"\n{window}-day smoothing window, gamma-prior Bayesian estimation method")\ .show() logger.info("running case-forward prediction") IDN = SIR("IDN", 267.7e6, dT0 = T_pred[-1], Rt0 = Rt_pred[-1], mobility = 0, random_seed = 0).run(14) logger.info("province-level projections") migration = np.zeros((len(provinces), len(provinces))) estimates = [] max_len = 1 + max(map(len, provinces)) with tqdm(provinces) as progress: for (province, cases) in province_cases.items(): progress.set_description(f"{province :<{max_len}}") (dates, Rt_pred, Rt_CI_upper, Rt_CI_lower, *_) = analytical_MPVS(cases, CI = CI, smoothing = smoothing)
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, "-", color="dodgerblue", linewidth=2, zorder=11) anoms = plt.vlines(anomaly_dates, 0, 4, colors="red", linewidth=2, alpha=0.5) plt.legend([pd.markers["Rt"], sim_rt, anoms], ["Estimated $R_t$ (99% CI)", "simulated $R_t$", "anomalies"], **pd.legend_props) plt.show() # 2: naive MCMC model, trace, summary = parametric_scheme_mcmc(sir_model.dT,
] model = lambda: Model.single_unit(name=state, RR0=Rt_pred[-1], population=pop, infectious_period=infectious_period, I0=T_pred[-1], lower_CI=T_CI_lower[-1], upper_CI=T_CI_upper[-1], random_seed=33) forward_pred_period = 9 t_pred = [ dates[-1] + pd.Timedelta(days=i) for i in range(forward_pred_period + 1) ] current = model().run(forward_pred_period) target = simulate_PID_controller(model(), 0, forward_pred_period) plt.Rt(dates, Rt_pred, Rt_CI_upper, Rt_CI_lower, CI, ymin = 0, ymax = 5, yaxis_colors = False)\ .adjust(left = 0.10, right = 0.95, bottom = 0.15, top = 0.95)\ .xlabel("date")\ .ylabel("$R_t$")\ .show() plt.daily_cases(dates, T_pred, T_CI_upper, T_CI_lower, new_cases_ts, anomaly_dates, anomalies, CI, prediction_ts = [ (current[0].delta_T[1:], current[0].lower_CI[1:], current[0].upper_CI[1:], "orange", r"projection with current $R_t$"), (target[0].delta_T[1:], target[0].lower_CI[1:], target[0].upper_CI[1:], "green", r"projection with $R_t \rightarrow 0.9$") ])\ .adjust(left = 0.10, right = 0.95, bottom = 0.15, top = 0.95)\ .xlabel("date")\ .ylabel("cases")\ .show()
state_ts = state_cases["date_reported"].value_counts().sort_index() district_names, population_counts, _ = etl.district_migration_matrix( data / "Migration Matrix - District.csv") populations = dict(zip(district_names, population_counts)) # first, look at state level predictions (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( state_ts, CI=CI, smoothing=notched_smoothing(window=smoothing), totals=False) plt.Rt(dates, Rt_pred[1:], Rt_CI_upper[1:], Rt_CI_lower[1:], CI, ymin=0, ymax=4)\ .title("\nBihar: Reproductive Number Estimate")\ .annotate(f"data from {str(dates[0]).split()[0]} to {str(dates[-1]).split()[0]}")\ .xlabel("date")\ .ylabel("$R_t$", rotation=0, labelpad=20)\ .show() np.random.seed(33) Bihar = SIR("Bihar", 99_000_000, dT0=T_pred[-1], Rt0=Rt_pred[-1], lower_CI=T_CI_lower[-1], upper_CI=T_CI_upper[-1], mobility=0) Bihar.run(14) t_pred = [dates[-1] + pd.Timedelta(days=i) for i in range(len(Bihar.dT))]
cases = cases.dropna(subset=["age"]) cases["age_bin"] = pd.cut(cases.age, bins=[0] + list(range(20, 80, 10)) + [100]) age_ts = cases[["age_bin", "confirmed"]].groupby(["age_bin", "confirmed"]).size().sort_index() ss_max_rts = {} fig, axs = plt.subplots(4, 2, True, True) (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 = notched_smoothing(window = 5), totals = False) plt.sca(axs.flat[0]) plt.Rt(dates, Rt_pred, Rt_CI_upper, Rt_CI_lower, CI).annotate(f"all ages").adjust(left=0.04, right=0.96, top=0.95, bottom=0.05, hspace=0.3, wspace=0.15) r = pd.Series(Rt_pred, index=dates) ss_max_rts["all"] = r[r.index.month_name() == "April"].max() for (age_bin, ax) in zip(age_ts.index.get_level_values(0).categories, axs.flat[1:]): print(age_bin) (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.loc[age_bin], CI = CI, smoothing = smoothing, totals = False) plt.sca(ax) plt.Rt(dates, Rt_pred, Rt_CI_upper, Rt_CI_lower, CI).annotate(f"age bin: {age_bin}") ax.get_legend().remove()
gdf = gpd.read_file("data/gadm36_IDN_shp/gadm36_IDN_2.shp")\ .query("NAME_1 == 'Jakarta Raya'")\ .drop(columns=shp_drop_cols) bbox = shapely.geometry.box(minx = 106.65, maxx = 107.00, miny = -6.40, maxy=-6.05) gdf = gdf[gdf.intersects(bbox)] jakarta_districts = dkij.district.str.title().unique() jakarta_cases = dkij.groupby("date_positiveresult")["id"].count().rename("cases") logger.info("running province-level Rt estimate") (dates, RR_pred, RR_CI_upper, RR_CI_lower, T_pred, T_CI_upper, T_CI_lower, total_cases, new_cases_ts, anomalies, anomaly_dates)\ = analytical_MPVS(jakarta_cases, CI = CI, smoothing = smoothing, totals=False) plt.Rt(dates, RR_pred[1:], RR_CI_upper[1:], RR_CI_lower[1:], CI)\ .title("\nDKI Jakarta: Reproductive Number Estimate")\ .xlabel("\ndate")\ .ylabel("$R_t$\n", rotation=0, labelpad=30)\ .annotate(f"\n{window}-day smoothing window, gamma-prior Bayesian estimation method")\ .show() logger.info("running case-forward prediction") prediction_period = 14*days IDN = SIR(name = "IDN", population = 267.7e6, dT0 = T_pred[-1], Rt0 = RR_pred[-1], upper_CI = T_CI_upper[-1], lower_CI = T_CI_lower[-1], mobility = 0, random_seed = 0)\ .run(prediction_period) plt.daily_cases(dates, T_pred[1:], T_CI_upper[1:], T_CI_lower[1:], new_cases_ts[1:], anomaly_dates, anomalies, CI, prediction_ts = [ (IDN.dT[:-1], IDN.lower_CI[1:], IDN.upper_CI[1:], None, "predicted cases") ])\ .title("\nDKI Jakarta: Daily Cases")\ .xlabel("\ndate")\
print(state) print(" + running estimation...") state_ts_full = pd.Series(data = notched_smoothing(window = smoothing)(ts_full.loc[state].Hospitalized), index = ts_full.loc[state].Hospitalized.index) (dates, Rt_pred, RR_CI_upper, RR_CI_lower, T_pred, T_CI_upper, T_CI_lower, total_cases, new_cases_ts, anomalies, anomaly_dates)\ = analytical_MPVS(ts.loc[state].Hospitalized, CI = CI, smoothing = lambda x:x, totals = False) Rt = pd.DataFrame({"Rt": Rt_pred}, index = dates) Rt_m = np.mean(Rt[(Rt.index >= "31 March, 2020") & (Rt.index <= "17 May, 2020")])[0] Rt_v = np.mean(Rt[(Rt.index < "31 March, 2020")])[0] print(" + Rt today:", Rt_pred[-1]) print(" + Rt_m :", Rt_m) print(" + Rt_v :", Rt_v) historical = pd.DataFrame({"smoothed": new_cases_ts}, index = dates) plt.Rt(dates, Rt_pred, RR_CI_lower, RR_CI_upper, CI)\ .ylabel("$R_t$")\ .xlabel("date")\ .title(f"\n{state}: Reproductive Number Estimate")\ .annotate(f"public data from {str(dates[0]).split()[0]} to {str(dates[-1]).split()[0]}")\ .show() I0 = (ts.loc[state].Hospitalized - ts.loc[state].Recovered - ts.loc[state].Deceased).sum() state_model = SIR(name = state, population = pop, dT0 = T_pred[-1], Rt0 = Rt_pred[-1], mobility = 0, I0 = I0, upper_CI = T_CI_upper[-1], lower_CI = T_CI_lower[-1], random_seed = 0).run(10) empirical = state_ts_full[(state_ts_full.index >= "Oct 14, 2020") & (state_ts_full.index < "Oct 25, 2020")] plt.daily_cases(dates, T_pred, T_CI_upper, T_CI_lower, new_cases_ts, anomaly_dates, anomalies, CI, prediction_ts=[ (state_model.dT, state_model.lower_CI, state_model.upper_CI, plt.PRED_PURPLE, "predicted cases"), ] + [(empirical, empirical, empirical, "black", "empirical post-prediction cases")] if state != "Maharashtra" else [])\ .ylabel("cases")\ .xlabel("date")\ .title(f"\n{state}: Daily Cases")\