def figure_tracing(): iseries = [] rseries = [] model = SEIRCTODEMem for eta in np.linspace(0.0, 1.0, 11): log.info("Figure: tracing -- eta = {}".format(eta)) cfg = basic_config() cfg["meta"]["model"] = model cfg["parameters"]["theta"] = 0.0714 cfg["parameters"]["eta"] = eta cfg["parameters"]["chi"] = 0.5 t, traj = runModel(**cfg["meta"], **cfg) E = traj[:, model.colindex("EU")] I = traj[:, model.colindex("IU")] R = traj[:, -1] iseries.append(E + I) rseries.append(R) iseries.insert(0, t) rseries.insert(0, t) np.savetxt("tracing-theta.tsv", np.vstack(iseries).T, delimiter="\t") np.savetxt("tracing-r.tsv", np.vstack(rseries).T, delimiter="\t")
def obj(x): ## we do not allow negative parameters, very bad if np.any(x[1:] < 0): return np.inf ## set time t0 = x[0] cfg["meta"]["t0"] = t0 ## register interventions against the reference times def regiv(iv): niv = iv.copy() niv["time"] += t0 return niv cfg["interventions"] = [regiv(iv) for iv in interventions] ## set the parameters setp(cfg, x[1:]) ## run the model t, traj, _, _ = runModel(**cfg["meta"], **cfg) M = interp1d(t, getm(traj), kind="previous", bounds_error=False, fill_value=0)(times) ## measure the result dist = np.sqrt(np.sum((M - dead)**2, where=dead >= 0)) log.info("Distance: {}".format(dist)) return dist
def compare_abm(cfg, out): t = [np.loadtxt(f, delimiter="\t") for f in glob("{}*.t".format(out))][0] trajectories = [ np.loadtxt(f, delimiter="\t") for f in glob("{}*.traj".format(out)) ] avg = np.average(trajectories, axis=0) std = np.std(trajectories, axis=0) np.savetxt(out.format("abm-avg"), np.vstack([t, avg.T]).T, delimiter="\t") np.savetxt(out.format("abm-std+1"), np.vstack([t, avg.T + std.T]).T, delimiter="\t") np.savetxt(out.format("abm-std-1"), np.vstack([t, avg.T - std.T]).T, delimiter="\t") np.savetxt(out.format("abm-std+2"), np.vstack([t, avg.T + 2 * std.T]).T, delimiter="\t") np.savetxt(out.format("abm-std-2"), np.vstack([t, avg.T - 2 * std.T]).T, delimiter="\t") cfg["meta"]["model"] = SEIRCTODEMem t, traj = runModel(**cfg["meta"], **cfg) np.savetxt(out.format("ode"), np.vstack([t, traj.T]).T, delimiter="\t")
def _runabm(arg): cfg, seed = arg cfg["meta"]["seed"] = seed log.info("Starting sample {}".format(cfg["meta"]["seed"])) t, traj = runModel(**cfg["meta"], **cfg) log.info("Done sample {}".format(cfg["meta"]["seed"])) return t, traj
def runSample(arg): i, cfg = arg # set random seed for the benefit of stochastic simulations cfg["meta"]["seed"] = i t, traj = runModel(**cfg["meta"], **cfg) tseries = np.vstack([t, traj.T]).T return tseries
def figure_c_testing(): model = SEIRCTODEMem with open("c-testing.tsv", "w") as fp: for theta in np.linspace(0.0, 0.55, 25): for c in np.linspace(0.0, 20.0, 25): log.info("Figure: c testing -- theta = {}, c = {}".format( theta, c)) cfg = basic_config() cfg["meta"]["model"] = model cfg["parameters"]["theta"] = theta cfg["parameters"]["c"] = c t, traj = runModel(**cfg["meta"], **cfg) R30 = traj[30, -1] line = "%e\t%e\t%e\n" % (theta, c, R30) fp.write(line) fp.write("\n")
def runSample(arg): i, cfg = arg # set random seed for the benefit of stochastic simulations cfg["meta"]["seed"] = i # for indexed samples, select the right parameter: for k, v in cfg["parameters"].copy().items(): if isinstance(v, list): cfg["parameters"][k] = v[i] for iv in cfg["interventions"]: for k, v in iv.copy().items(): if isinstance(v, list): iv[k] = v[i] t, traj, events, paramtraj = runModel(**cfg["meta"], **cfg) tseries = np.concatenate([t[:, None], traj], axis=1) return tseries, events, paramtraj
def figure_testing_tracing(): model = SEIRCTODEMem with open("testing-tracing.tsv", "w") as fp: for theta in np.linspace(0.0, 0.55, 25): for eta in np.linspace(0.0, 1.0, 25): log.info( "Figure: testing tracing -- theta = {}, eta = {}".format( theta, eta)) cfg = basic_config() cfg["meta"]["model"] = model cfg["parameters"]["theta"] = theta cfg["parameters"]["eta"] = eta cfg["parameters"]["chi"] = 0.5 t, traj = runModel(**cfg["meta"], **cfg) R30 = traj[30, -1] line = "%e\t%e\t%e\n" % (theta, eta, R30) fp.write(line) fp.write("\n")
def cachedRun(*av, **kw): t, traj, events, paramtraj = runModel(*av, **kw) tseries = np.concatenate([t[:, None], traj], axis=1) return tseries, events, paramtraj
def command(): logging.basicConfig( stream=sys.stdout, level=logging.INFO, format='%(asctime)s - %(name)s:%(levelname)s - %(message)s') parser = argparse.ArgumentParser("fit") parser.add_argument("-y", "--yaml", default=None, help="Config file") parser.add_argument("-m", "--mask", nargs="*", default=[], help="Variables to mask") parser.add_argument("-e", "--end", default=None, help="Truncate the data at end date") parser.add_argument("-t", "--time", default=0, type=float, help="Shift dataset time by given amount") parser.add_argument( "--dgu", default=None, help= "coronavirus.data.gov.uk format for the dead\n\t\thttps://coronavirus.data.gov.uk/downloads/csv/coronavirus-deaths_latest.csv" ) parser.add_argument("--data", default=None, help="generic YYYY-MM-DD,dead format for data") args = parser.parse_args() if args.yaml is None: log.error("--yaml is a required argument") dead = None if args.data: dead = data(args.data) elif args.dgu: dead = dgu(args.dgu) if dead is None: log.error("There are no dead. Need a data file of some sort") if args.end: end = time.strptime(args.end, "%Y-%m-%d") idx = np.sum(dead[:, 0] <= end.tm_yday) dead = dead[:idx] cfg = config_load(args.yaml) model = SEIRCTODEMem cfg["meta"]["model"] = model def getm(traj): return traj[:, model.colindex("M")] getp, setp = paramArray(cfg, args.mask) ## the times of the dead dead_t = dead[:, 0] + args.time ## these are the actual counts of the dead dead_d = dead[:, 1] ## this is the last day of data tmax = max(dead_t) ## one output point per day steps = int(tmax) ## we want a time-series of times = np.linspace(0, tmax, steps) ## interpolate the dead onto this time support dead_i = interp1d(dead_t, dead_d, kind="previous", bounds_error=False, fill_value=np.nan)(times) ## set to run for the specific required time at the specific step cfg["meta"]["tmax"] = tmax cfg["meta"]["steps"] = steps + 1 interventions = cfg.get("interventions", []) ## perform a stochastic gradient descent t0, params = optimise(cfg, getm, setp, getp(cfg), times, dead_i, interventions) cfg["meta"]["t0"] = t0 setp(cfg, params) save_human(cfg, "{}-fit.yaml".format(cfg["meta"]["output"])) t, traj, _, _ = runModel(**cfg["meta"], **cfg) M = getm(traj) fig, (ax1, ax2) = plt.subplots(2, 1) ax1.set_xlabel("Days since outbreak start") ax1.set_ylabel("Cumulative infections") ax1.set_xlim(0, tmax) ax1.plot(t, M, label="Simulated") ax1.plot(times, dead_i, label="Data") for e in interventions: ax1.axvline(e["time"], c=(0, 0, 0), lw=0.5, ls='--') ax1.legend() ax2.set_xlabel("Days since outbreak start") ax2.set_ylabel("Cumulative infections") ax2.set_xlim(0, tmax) ax2.set_yscale("log") ax2.plot(t, M, label="Simulated") ax2.plot(times, dead_i, label="Data") for e in interventions: ax2.axvline(e["time"], c=(0, 0, 0), lw=0.5, ls='--') ax2.legend() plt.savefig("{}-fit.png".format(cfg["meta"]["output"]))
{ "time": 75, "parameters": { "c": 10 } }, # 16th March 2020 voluntary distancing { "time": 82, "parameters": { "c": 4 } } # 23rd March 2020 lockdown ] model = SEIRCTODEMem t, traj, events = runModel(model, t0, tmax, steps, params, initial, interventions) RU = traj[:, model.colindex("RU")] RD = traj[:, model.colindex("RD")] t += offset cases = RU + RD deaths = ifr * cases ukm = uk_mortality("uk_mortality.csv") ukt = ukm[:, 0] ukdeaths_Economist = ukm[:, 1] ukdeaths_Excess = ukm[:, 2] fig, (ax1, ax2) = plt.subplots(2, 1) ax1.set_xlabel("Days since outbreak start") ax1.set_ylabel("Cases")
import sys logging.basicConfig( stream=sys.stdout, level=logging.INFO, format='%(asctime)s - %(name)s:%(levelname)s - %(message)s') initial = { "N": 1e6, "IU": 100, } interventions = [{ "time": 10, "parameters": { "c": 5 } }, { "time": 11, "parameters": { "c": 10 } }] t, traj, e, p = runModel(SEIRCTODEMem, t0=0, tmax=20, steps=20, initial=initial, interventions=interventions) assert np.all(t == np.linspace(0., 20., 21))