def run_model(param_updates, n_steps=200, lockdown_at=None): params = setup_params(param_updates) # Create an instance of the Model model = Model(params) m_out = [] for step in trange(n_steps): # Evaluate each step and save the results model.one_time_step() # LOGGER.info( # model.one_time_step_results() # ) # If we want to see the results as we go uncomment this block m_out.append(model.one_time_step_results()) if lockdown_at: if step == lockdown_at: model.update_running_params("lockdown_on", 1) LOGGER.info(f"turning on lock down at step {step}") LOGGER.info( f'lockdown_house_interaction_multiplier = {params.get_param("lockdown_house_interaction_multiplier")}' ) LOGGER.info( f'lockdown_random_network_multiplier = {params.get_param("lockdown_random_network_multiplier")}' ) for oc_net in OccupationNetworkEnum: LOGGER.info( f'lockdown_occupation_multiplier{oc_net.name} = {params.get_param(f"lockdown_occupation_multiplier{oc_net.name}")}' ) df = pd.DataFrame(m_out) model.write_output_files() return df
def test_set_params_occupation_network_by_age_check_used(self): p = Parameters( read_param_file=True, input_households="tests/data/baseline_household_demographics.csv", input_param_file="tests/data/baseline_parameters.csv", param_line_number=1, ) model = Model(p) non_scaled = [ model.get_param(f"daily_fraction_work_used{age.name}") for age in OccupationNetworkEnum ] model.update_running_params("lockdown_on", 1) scaled = [ model.get_param(f"daily_fraction_work_used{age.name}") for age in OccupationNetworkEnum ] for non_scaled_i, scaled_i in zip(non_scaled, scaled): assert non_scaled_i * 0.2 == scaled_i model.update_running_params( "lockdown_occupation_multiplier_primary_network", 10.0) scaled = [ model.get_param(f"daily_fraction_work_used{age.name}") for age in OccupationNetworkEnum ] for non_scaled_i, scaled_i, factor in zip(non_scaled, scaled, [ 10.0, 0.2, 0.2, 0.2, 0.2, ]): assert non_scaled_i * factor == scaled_i
def _worker( args: Tuple[Region, Mapping[Age10Y, float], multiprocessing.Queue], output_dir: str, parameters_path: str, household_demographics_path: str, total_individuals: int, lockdown_start: Optional[int], lockdown_end: int, end_time: int, ) -> None: region, populations, queue = args # Prepare output paths for each region output_file_name = pathlib.Path(output_dir).joinpath(f"{region.name}_ts.csv") detailed_output_dir = pathlib.Path(output_dir).joinpath(f"{region.name}_detailed") os.makedirs(detailed_output_dir, exist_ok=True) # Init parameters from repo baseline params = Parameters( parameters_path, 1, str(detailed_output_dir), household_demographics_path, ) # Set more simulation params params.set_param("n_total", total_individuals) params.set_param("end_time", end_time) # FIXME: not writing detailed output params.set_param("sys_write_individual", 1) # Set populations for k, v in populations.items(): params.set_param(k.value, v) # Activate lockdown if specified if lockdown_start is not None: for k, v in LOCKDOWN_PARMAETERS.items(): params.set_param(k, v) params.set_param("lockdown_time_on", lockdown_start) params.set_param("lockdown_time_off", lockdown_end) # Set up model model = simulation.COVID19IBM(model=Model(params)) agent = simulation.Agent() results = collections.defaultdict(list) # Set up simulation current_state = model.start_simulation() current_action = agent.start_simulation(current_state) # Run simulation for step in range(end_time): current_state = model.step(current_action) current_action = agent.step(current_state) for key, value in current_state.items(): results[key].append(value) queue.put((step, current_state)) # Extract and write outputs outputs = pd.DataFrame(results) outputs.drop(columns=["test_on_symptoms", "app_turned_on"]) outputs.to_csv(output_file_name, index=False)
def test_run_model_read_prama_file_false(self): all_params = pd.read_csv("tests/data/baseline_parameters.csv") p = Parameters( read_param_file=False, input_households="tests/data/baseline_household_demographics.csv", ) for key in all_params: value = all_params[key][0] try: p.set_param(key, float(value)) except TypeError: p.set_param(key, int(value)) m = Model(p) m.one_time_step() assert m.one_time_step_results()["time"] == 1
def test_set_params_manual_traceable_fraction(self): p = Parameters( read_param_file=True, input_households="tests/data/baseline_household_demographics.csv", input_param_file="tests/data/baseline_parameters.csv", param_line_number=1, ) p.set_param("manual_traceable_fraction_occupation", 0.8) assert p.get_param("manual_traceable_fraction_occupation") == 0.8 p.set_param("manual_traceable_fraction_household", 0.6) assert p.get_param("manual_traceable_fraction_household") == 0.6 assert p.get_param("manual_traceable_fraction_occupation") == 0.8 model = Model(p) model.update_running_params("manual_traceable_fraction_household", 0.4) assert model.get_param("manual_traceable_fraction_household") == 0.4
def get_simulation( params ): params.set_param( "end_time", 500 ) model = simulation.COVID19IBM(model = Model(params)) sim = simulation.Simulation(env = model, end_time = params.get_param( "end_time" ) ) return sim
from COVID19.model import Model, Parameters import COVID19.simulation as simulation import pandas as pd input_params = pd.read_csv('./tests/data/baseline_parameters.csv') input_households = pd.read_csv('./tests/data/baseline_household_demographics.csv') print(input_params) print(input_households) params = Parameters( input_param_file="./tests/data/baseline_parameters.csv", param_line_number=1, output_file_dir="./data_test", input_households="./tests/data/baseline_household_demographics.csv" ) params.set_param( "n_total", 10000) params.set_param( "app_turn_on_time", 10) model = simulation.COVID19IBM(model = Model(params)) sim = simulation.Simulation(env = model, end_time = 100 ) sim.steps( 1000 ) print( pd.DataFrame.from_dict(sim.results) )
def get_model_swig(params): """ Gets the Swig model object """ return Model(params)
def setup_model(d: dict = None): params = setup_parameters(d) params.set_param("sys_write_individual", 0) model = Model(params) return model
def free_abm( params, logger=dummy_logger(), input_parameter_file="./abm_params/baseline_parameters.csv", household_demographics_file="./abm_params/baseline_household_demographics.csv", parameter_line_number=1, name_file_res="res", output_dir="./output/", save_every_iter=5, stop_zero_I=True, data={}, callback=lambda data: None): ''' Simulate the openABM epidemic simulation with no intervention strategy input ----- params: Dict Dictonary with openABM to set results: print on file true configurations and transmission ''' params_model = Parameters(input_parameter_file, parameter_line_number, output_dir, household_demographics_file) fold_out = Path(output_dir) if not fold_out.exists(): fold_out.mkdir(parents=True) params_model = Parameters() for k, val in params.items(): params_model.set_param(k, val) model = simulation.COVID19IBM(model=Model(params_model)) T = params_model.get_param("end_time") N = params_model.get_param("n_total") sim = simulation.Simulation(env=model, end_time=T, verbose=False) for col_name in ["I", "IR"]: data[col_name] = np.full(T, np.nan) for t in range(T): sim.steps(1) status = np.array(covid19.get_state(model.model.c_model)) state = status_to_state(status) nS, nI, nR = (state == 0).sum(), (state == 1).sum(), (state == 2).sum() if nI == 0 and stop_zero_I: logger.info( "stopping simulation as there are no more infected individuals" ) break logger.info(f'time:{t}') data["I"][t] = nI data["IR"][t] = nI + nR callback(data) # print and import files sim.env.model.write_individual_file() df_indiv = pd.read_csv(output_dir + "individual_file_Run1.csv", skipinitialspace=True) df_indiv.to_csv(output_dir + name_file_res + "_individuals.gz") sim.env.model.write_transmissions() df_trans = pd.read_csv(output_dir + "transmission_Run1.csv") df_trans.to_csv(output_dir + name_file_res + "_transmissions.gz") print("End of Simulation") return
def loop_abm( params, inference_algo, logger=dummy_logger(), input_parameter_file="./abm_params/baseline_parameters.csv", household_demographics_file="./abm_params/baseline_household_demographics.csv", parameter_line_number=1, seed=1, initial_steps=0, num_test_random=50, num_test_algo=50, fraction_SM_obs=0.2, fraction_SS_obs=1, quarantine_HH=False, test_HH=False, name_file_res="res", output_dir="./output/", save_every_iter=5, stop_zero_I=True, adoption_fraction=1.0, fp_rate=0.0, fn_rate=0.0, smartphone_users_abm=False, # if True use app users fraction from OpenABM model callback=lambda x: None, data={}): ''' Simulate interventions strategy on the openABM epidemic simulation. input ----- params: Dict Dictonary with openABM to set inference_algo: Class (rank_template) Class for order the nodes according to the prob to be infected logger = logger for printing intermediate steps results: print on file true configurations and transmission ''' params_model = Parameters(input_parameter_file, parameter_line_number, output_dir, household_demographics_file) ### create output_dir if missing fold_out = Path(output_dir) if not fold_out.exists(): fold_out.mkdir(parents=True) ### initialize a separate random stream rng = np.random.RandomState() rng.seed(seed) ### initialize ABM model for k, val in params.items(): params_model.set_param(k, val) model = Model(params_model) model = simulation.COVID19IBM(model=model) T = params_model.get_param("end_time") N = params_model.get_param("n_total") sim = simulation.Simulation(env=model, end_time=T, verbose=False) house = covid19.get_house(model.model.c_model) housedict = listofhouses(house) has_app = covid19.get_app_users( model.model.c_model) if smartphone_users_abm else np.ones(N, dtype=int) has_app &= (rng.random(N) <= adoption_fraction) ### init data and data_states data_states = {} data_states["true_conf"] = np.zeros((T, N)) data_states["statuses"] = np.zeros((T, N)) data_states["tested_algo"] = [] data_states["tested_random"] = [] data_states["tested_SS"] = [] data_states["tested_SM"] = [] for name in [ "num_quarantined", "q_SS", "q_SM", "q_algo", "q_random", "q_all", "infected_free", "S", "I", "R", "IR", "aurI", "prec1%", "prec5%", "test_+", "test_-", "test_f+", "test_f-" ]: data[name] = np.full(T, np.nan) data["logger"] = logger ### init inference algo inference_algo.init(N, T) ### running variables indices = np.arange(N, dtype=int) excluded = np.zeros(N, dtype=bool) daily_obs = [] all_obs = [] all_quarantined = [] freebirds = 0 num_quarantined = 0 fp_num = 0 fn_num = 0 p_num = 0 n_num = 0 noise_SM = rng.random(N) noise_SS = rng.random(N) if fraction_SS_obs < 1 else None nfree = params_model.get_param("n_seed_infection") for t in range(T): ### advance one time step sim.steps(1) status = np.array(covid19.get_state(model.model.c_model)) state = status_to_state(status) data_states["true_conf"][t] = state nS, nI, nR = (state == 0).sum(), (state == 1).sum(), (state == 2).sum() if nI == 0 and stop_zero_I: logger.info( "stopping simulation as there are no more infected individuals" ) break if t == initial_steps: logger.info("\nobservation-based inference algorithm starts now\n") logger.info(f'time:{t}') ### extract contacts daily_contacts = covid19.get_contacts_daily(model.model.c_model, t) logger.info(f"number of unique contacts: {len(daily_contacts)}") ### compute potential test results for all if fp_rate or fn_rate: noise = rng.random(N) f_state = (state == 1) * (noise > fn_rate) + (state == 0) * ( noise < fp_rate) + 2 * (state == 2) else: f_state = state to_quarantine = [] all_test = [] excluded_now = excluded.copy() fp_num_today = 0 fn_num_today = 0 p_num_today = 0 n_num_today = 0 def test_and_quarantine(rank, num): nonlocal to_quarantine, excluded_now, all_test, fp_num_today, fn_num_today, p_num_today, n_num_today test_rank = [] for i in rank: if len(test_rank) == num: break if excluded_now[i]: continue test_rank += [i] if f_state[i] == 1: p_num_today += 1 if state[i] != 1: fp_num_today += 1 q = housedict[house[i]] if quarantine_HH else [i] excluded_now[q] = True to_quarantine += q excluded[q] = True if test_HH: all_test += q else: all_test += [i] else: n_num_today += 1 if state[i] == 1: fn_num_today += 1 excluded_now[i] = True all_test += [i] return test_rank ### compute rank from algorithm num_test_algo_today = num_test_algo if t < initial_steps: daily_obs = [] num_test_algo_today = 0 weighted_contacts = [(c[0], c[1], c[2], 2.0 if c[3] == 0 else 1.0) for c in daily_contacts if (has_app[c[0]] and has_app[c[1]])] if nfree == 0 and quarantine_HH: print("faster end") rank_algo = np.zeros((N, 2)) rank_algo[:, 0] = np.arange(N) rank_algo[:, 1] = np.random.rand(N) else: rank_algo = inference_algo.rank(t, weighted_contacts, daily_obs, data) rank = np.array(sorted(rank_algo, key=lambda tup: tup[1], reverse=True)) rank = [int(tup[0]) for tup in rank] ### test num_test_algo_today individuals test_algo = test_and_quarantine(rank, num_test_algo_today) ### compute roc now, only excluding past tests eventsI = events_list(t, [(i, 1, t) for (i, tf) in enumerate(excluded) if tf], data_states["true_conf"], check_fn=check_fn_I) xI, yI, aurI, sortlI = roc_curve(dict(rank_algo), eventsI, lambda x: x) ### test all SS if fraction_SS_obs < 1: SS = indices[(status == 4) & (noise_SS < fraction_SS_obs)] else: SS = indices[status == 4] SS = test_and_quarantine(SS, len(SS)) ### test a fraction of SM SM = indices[(status == 5) & (noise_SM < fraction_SM_obs)] SM = test_and_quarantine(SM, len(SM)) ### do num_test_random extra random tests test_random = test_and_quarantine(rng.permutation(N), num_test_random) ### quarantine infected individuals num_quarantined += len(to_quarantine) covid19.intervention_quarantine_list(model.model.c_model, to_quarantine, T + 1) ### update observations daily_obs = [(int(i), int(f_state[i]), int(t)) for i in all_test] all_obs += daily_obs ### exclude forever nodes that are observed recovered rec = [i[0] for i in daily_obs if f_state[i[0]] == 2] excluded[rec] = True ### update data data_states["tested_algo"].append(test_algo) data_states["tested_random"].append(test_random) data_states["tested_SS"].append(SS) data_states["tested_SM"].append(SM) data_states["statuses"][t] = status data["S"][t] = nS data["I"][t] = nI data["R"][t] = nR data["IR"][t] = nR + nI data["aurI"][t] = aurI prec = lambda f: yI[int(f / 100 * len(yI))] / int(f / 100 * len( yI)) if len(yI) else np.nan ninfq = sum(state[to_quarantine] > 0) nfree = int(nI - sum(excluded[state == 1])) data["aurI"][t] = aurI data["prec1%"][t] = prec(1) data["prec5%"][t] = prec(5) data["num_quarantined"][t] = num_quarantined data["test_+"][t] = p_num data["test_-"][t] = n_num data["test_f+"][t] = fp_num data["test_f-"][t] = fn_num data["q_SS"][t] = len(SS) data["q_SM"][t] = len(SM) sus_test_algo = sum(state[test_algo] == 0) inf_test_algo = sum(state[test_algo] == 1) rec_test_algo = sum(state[test_algo] == 2) inf_test_random = sum(state[test_random] == 1) data["q_algo"][t] = inf_test_algo data["q_random"][t] = sum(state[test_random] == 1) data["infected_free"][t] = nfree asbirds = 'a bird' if nfree == 1 else 'birds' fp_num += fp_num_today fn_num += fn_num_today n_num += n_num_today p_num += p_num_today ### show output logger.info(f"True : (S,I,R): ({nS:.1f}, {nI:.1f}, {nR:.1f})") logger.info( f"AUR_I : {aurI:.3f}, prec(1% of {len(yI)}): {prec(1):.2f}, prec5%: {prec(5):.2f}" ) logger.info( f"SS: {len(SS)}, SM: {len(SM)}, results test algo (S,I,R): ({sus_test_algo},{inf_test_algo},{rec_test_algo}), infected test random: {inf_test_random}/{num_test_random}" ) logger.info( f"false+: {fp_num} (+{fp_num_today}), false-: {fn_num} (+{fn_num_today})" ) logger.info( f"...quarantining {len(to_quarantine)} guys -> got {ninfq} infected, {nfree} free as {asbirds} ({nfree-freebirds:+d})" ) freebirds = nfree ### callback callback(data) if t % save_every_iter == 0: df_save = pd.DataFrame.from_records(data, exclude=["logger"]) df_save.to_csv(output_dir + name_file_res + "_res.gz") # save files df_save = pd.DataFrame.from_records(data, exclude=["logger"]) df_save.to_csv(output_dir + name_file_res + "_res.gz") with open(output_dir + name_file_res + "_states.pkl", mode="wb") as f_states: pickle.dump(data_states, f_states) sim.env.model.write_individual_file() df_indiv = pd.read_csv(output_dir + "individual_file_Run1.csv", skipinitialspace=True) df_indiv.to_csv(output_dir + name_file_res + "_individuals.gz") sim.env.model.write_transmissions() df_trans = pd.read_csv(output_dir + "transmission_Run1.csv") df_trans.to_csv(output_dir + name_file_res + "_transmissions.gz") return df_save
def get_model_swig(params): return Model(params)