def make_safegraph(sim, mobility_file): ''' Create interventions representing SafeGraph data ''' # Load data.values if mobility_file is None: fn = safegraph_file else: fn = mobility_file df = pd.read_csv(fn) week = df['week'] w = c = df['p.tot'].values # w = df['p.emp'].values # c = df['p.cust'].values # Do processing npts = len(week) start_date = sc.readdate(week[0], dateformat='%Y-%m-%d') start_day = sim.day(start_date) sg_days = start_day + 7 * np.arange(npts) # Create interventions interventions = [ cv.clip_edges(days=sg_days, changes=w, layers='w', label='clip_w'), cv.clip_edges(days=sg_days, changes=c, layers='c', label='clip_c'), ] return interventions
def make_safegraph(sim): ''' Create interventions representing SafeGraph data ''' # Load data.values fn = safegraph_file df = pd.read_excel(fn) week = df['week'] s = df['p.tot.schools'].values w = df['merged'].values c = sc.dcp(w) # Not different enough to warrant different values # Do processing days = sim.day([pd.Timestamp(v) for v in week.values]) last_day = days[-1] + 1 i_days = np.arange(days[0], last_day) s = np.interp(i_days, days, s) w = np.interp(i_days, days, w) c = np.interp(i_days, days, c) days = i_days # Create interventions interventions = [ cv.clip_edges(days=days, changes=s, layers='s', label='clip_s'), cv.clip_edges(days=days, changes=w, layers='w', label='clip_w'), cv.clip_edges(days=days, changes=c, layers='c', label='clip_c'), ] return interventions
def make_safegraph(sim): ''' Create interventions representing SafeGraph data ''' # Load data.values fn = safegraph_file df = pd.read_csv(fn) week = df['week'] s = df['p.tot.schools'].values w = df['p.tot.no.schools'].values c = sc.dcp(w) # Not different enough to warrant different values # Do processing days = sim.day(week.values.tolist()) last_day = days[-1] + 1 i_days = np.arange(days[0], last_day) s = np.interp(i_days, days, s) w = np.interp(i_days, days, w) c = np.interp(i_days, days, c) days = i_days # Create interventions interventions = [ cv.clip_edges(days=days, changes=s, layers='s', label='clip_s'), cv.clip_edges(days=days, changes=w, layers='w', label='clip_w'), cv.clip_edges(days=days, changes=c, layers='c', label='clip_c'), ] sim.intervention_info.ce = sc.objdict({'days': days, 'changes': w}) return interventions
def test_plotting(): sc.heading('Testing plotting') fig_paths = ['plotting_test1.png', 'plotting_test2.png'] # Create sim with data and interventions ce = cv.clip_edges(**{'days': 10, 'changes': 0.5}) sim = cv.Sim(pop_size=100, n_days=60, datafile=csv_file, interventions=ce, verbose=verbose) sim.run(do_plot=True) # Handle lesser-used plotting options sim.plot(to_plot=['cum_deaths', 'new_infections'], sep_figs=True, log_scale=['Number of new infections'], do_save=True, fig_path=fig_paths) # Handle Plotly functions try: cv.plotly_sim(sim) cv.plotly_people(sim) cv.plotly_animate(sim) except Exception as E: print( f'Plotly plotting failed ({str(E)}), but not essential so continuing' ) # Tidy up remove_files(*fig_paths) return
def test_plotting(): sc.heading('Testing plotting') fig_path = 'plotting_test.png' # Create sim with data and interventions ce = cv.clip_edges(**{'start_day': 10, 'change': 0.5}) sim = cv.Sim(pop_size=100, n_days=60, datafile=csv_file, interventions=ce, verbose=verbose) sim.run(do_plot=True) # Handle lesser-used plotting options sim.plot(to_plot=['cum_deaths', 'new_infections'], sep_figs=True, font_family='Arial', log_scale=['Number of new infections'], interval=5, do_save=True, fig_path=fig_path) print('↑ May print a warning about zero values') # Handle Plotly functions cv.plotly_sim(sim) cv.plotly_people(sim) cv.plotly_animate(sim) # Tidy up remove_files(fig_path) return
def test_beta_edges(do_plot=False, do_show=True, do_save=False, fig_path=None): pars = dict( pop_size=1000, pop_infected=20, pop_type='hybrid', ) start_day = 25 # Day to start the intervention end_day = 40 # Day to end the intervention change = 0.3 # Amount of change sims = sc.objdict() sims.b = cv.Sim(pars) # Beta intervention sims.e = cv.Sim(pars) # Edges intervention beta_interv = cv.change_beta(days=[start_day, end_day], changes=[change, 1.0]) edge_interv = cv.clip_edges(start_day=start_day, end_day=end_day, change=change, verbose=True) sims.b.update_pars(interventions=beta_interv) sims.e.update_pars(interventions=edge_interv) for sim in sims.values(): sim.run() if do_plot: sim.plot(do_save=do_save, do_show=do_show, fig_path=fig_path) sim.plot_result('r_eff') return sims
def increased_mobility(sim, scen, test): # Modify scen with test for stype, spec in scen.items(): if spec is not None: spec[ 'testing'] = test # dcp probably not needed because deep copied in new_schools sm = cvsch.schools_manager(scen) sim['interventions'] += [sm] # Different random path if ce not placed in the right order try: ce_idx = next(idx for idx, i in enumerate(sim['interventions']) if i.label == 'close_work_community') except StopIteration: print( 'Error: could not find intervetion with name "close_work_community" in list of interventions' ) exit() # TODO: Dig out date and changes from previous intervention instead of hard coding ce = cv.clip_edges(days=['2020-09-01', '2020-11-02'], changes=[0.65, 0.80], layers=['w', 'c'], label='close_and_reopen_work_community') sim['interventions'][ce_idx] = ce
def smart_working(periods: pd.Series, parameters: Dict[str, float]) -> cv.Intervention: defaults = dict(init_work_contacts=1., summer_work_contacts=1., yellow_work_contacts=1., orange_work_contacts=1., red_work_contacts=parameters.get('work_contacts')) defaults.update(parameters) assert defaults[ 'red_work_contacts'] is not None, 'red_work_contacts is required' v = get_values(periods, defaults, postfix='_work_contacts') return cv.clip_edges(days=v.index.values, changes=v.values, layers='w')
def lockdown_interactions(periods: pd.Series, parameters: Dict[str, float]) -> cv.Intervention: defaults = dict(init_casual_contacts=1., summer_casual_contacts=1., yellow_casual_contacts=parameters.get('casual_contacts'), orange_casual_contacts=parameters.get('casual_contacts'), red_casual_contacts=0.) defaults.update(parameters) assert defaults[ 'yellow_casual_contacts'] is not None, 'yellow_casual_contacts is required' assert defaults[ 'orange_casual_contacts'] is not None, 'orange_casual_contacts is required' v = get_values(periods, defaults, postfix='_casual_contacts') return cv.clip_edges(days=v.index.values, changes=v.values, layers='c')
def make_safegraph(sim, use_interp=True): ''' Create interventions representing SafeGraph data ''' # Load data.values fn = safegraph_file df = pd.read_csv(fn) week = df['week'] w = df["p.emp.no.schools"].values c = df["p.cust.no.schools"].values s = df["p.tot.schools"].values # Do processing npts = len(week) start_date = sc.readdate(week[0], dateformat='%Y-%m-%d') start_day = sim.day(start_date) sg_days = start_day + 7 * np.arange(npts) # Create interventions interventions = [ cv.clip_edges(days=sg_days, changes=w, layers='w', label='clip_w'), cv.clip_edges(days=sg_days, changes=c, layers='c', label='clip_c'), cv.clip_edges(days=sg_days, changes=s, layers='s', label='clip_s'), ] return interventions
def create_sim(pars=None, use_safegraph=True, label=None, show_intervs=False): ''' Create a single simulation for further use ''' p = sc.objdict( sc.mergedicts(define_pars(which='best', use_safegraph=use_safegraph), pars)) if 'rand_seed' not in p: seed = 1 print(f'Note, could not find random seed in {pars}! Setting to {seed}') p['rand_seed'] = seed # Ensure this exists # Basic parameters and sim creation pars = { 'pop_size': 225e3, 'pop_scale': 10, 'pop_type': 'synthpops', 'pop_infected': 300, 'beta': p.beta, 'start_day': '2020-01-27', 'end_day': '2020-06-08', 'rescale': True, 'rescale_factor': 1.1, 'verbose': p.get('verbose', 0.01), 'rand_seed': int(p.rand_seed), 'analyzers': cv.age_histogram(datafile=age_data_file), 'beta_layer': dict(h=3.0, s=0.6, w=0.6, c=0.3, l=1.5), } # Create and initialize the sim if pars['verbose']: print(f'Creating sim! safegraph={use_safegraph}, seed={p.rand_seed}') sim = cv.Sim(pars, label=label, popfile=get_popfile(pars), load_pop=True, datafile=epi_data_file ) # Create this here so can be used for test numbers etc. # Define testing interventions -- 97% sensitivity from https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7177629/ test_kwargs = dict(daily_tests=sim.data['new_tests'], test_delay=2, sensitivity=0.97, subtarget=test_num_subtarg) tn = cv.test_num(symp_test=p.tn, start_day='2020-01-27', end_day=None, **test_kwargs, label='tn') interventions = [tn] # Define beta interventions sim.intervention_info = sc.objdict() hwc_days = ['2020-02-24', '2020-03-23', '2020-05-31'] # Change date here, 04-27 or 05-04 hwc_days = sim.day(hwc_days) b_wc_ch = [1.0, p.bc_wc1, p.get('bc_wc2', p.bc_wc1) ] # To allow either one or two beta change parameters b_h_ch = [1.0, 1.1, 1.1] # Optional household all_b_days = np.arange(hwc_days[0], hwc_days[-1] + 1) # Full time series all_ch_wc = np.interp(all_b_days, hwc_days, b_wc_ch) # Linearly interpolate all_ch_h = np.interp(all_b_days, hwc_days, b_h_ch) # Linearly interpolate interventions += [ cv.change_beta(days=all_b_days, changes=all_ch_h, layers='h', label='beta_h') ] lkeys = ['w', 'c', 's'] if use_safegraph else [ 'w', 'c' ] # Skip schools if not using SafeGraph for lkey in lkeys: # Assume schools also use masks, etc. so have same non-movement beta change cb = cv.change_beta(days=all_b_days, changes=all_ch_wc, layers=lkey, label=f'beta_{lkey}') interventions += [cb] sim.intervention_info.bc = sc.objdict({ 'days': all_b_days, 'changes': all_ch_wc }) # Store for plotting later # LTCF beta change b_l_days = ['2020-02-24', '2020-03-23'] b_l_days = np.arange(sim.day(b_l_days[0]), sim.day(b_l_days[1])) b_l_ch = np.linspace(1.0, p.bc_lf, len(b_l_days)) interventions += [ cv.change_beta(days=b_l_days, changes=b_l_ch, layers='l', label='beta_l') ] sim.people.contacts['c'] = remove_ltcf_community( sim) # Remove community contacts from LTCF # SafeGraph intervention & tidy up if use_safegraph: interventions += make_safegraph(sim) else: interventions += [ cv.clip_edges(days='2020-03-12', changes=0.1, layers='s', label='clip_s') ] sim['interventions'] = interventions # Don't show interventions in plots, there are too many for interv in sim['interventions']: interv.do_plot = False # These are copied from parameters.py -- modified to capture change in work status at age 65 sim['prognoses']['age_cutoffs'] = np.array( [0, 10, 20, 30, 40, 50, 65, 70, 80, 90]) # Age cutoffs (upper limits) return sim
def make_lucknow(p=None, pop_infected=None, beta=None, rel_symp_prob=None, symp_prob=None, start_day=None, end_day=None, data_path=None, seed=None, verbose=0, debug=1, meta=None): # Create parameters total_pop = 3.5e6 if p is not None: pop_infected = p.pop_infected beta = p.beta rel_symp_prob = p.rel_symp_prob symp_prob = p.symp_prob pars = sc.objdict( pop_size=[100e3, 5e3][debug], pop_infected=pop_infected, rescale=True, pop_type='hybrid', start_day=start_day, end_day=end_day, rand_seed=seed, verbose=verbose, beta=beta, rel_symp_prob=rel_symp_prob, iso_factor=dict(h=0.5, s=0.4, w=0.4, c=0.5), # default: dict(h=0.3, s=0.1, w=0.1, c=0.1) quar_factor=dict(h=0.9, s=0.5, w=0.5, c=0.7), # default: dict(h=0.6, s=0.2, w=0.2, c=0.2) ) pars.pop_scale = int(total_pop / pars.pop_size) # Create interventions interventions = [] # Beta interventions interventions += [ cv.clip_edges(days=['2020-03-22', '2020-09-01', '2021-02-01'], changes=[0.1, 3 / 12, 1], layers=['s']), cv.change_beta(['2020-03-22'], [0.8], layers=['s']), cv.clip_edges( days=['2020-03-22', '2020-04-16', '2020-08-01', '2021-02-01'], changes=[0.1, 0.5, 0.9, 1.0], layers=['w']), cv.change_beta(['2020-03-22'], [0.8], layers=['w']), cv.change_beta(['2020-03-22', '2020-08-01', '2021-02-01'], [0.6, 0.7, 0.8], layers=['c']), ] # Testing interventions interventions += [ cv.test_prob(symp_prob=symp_prob, start_day=0, test_delay=5), ] # Create sim sim = cv.Sim(pars=pars, interventions=interventions, datafile=data_path, location='india') for intervention in sim['interventions']: intervention.do_plot = False sim.label = f'Lucknow {seed}' # Store metadata sim.meta = meta return sim
def test_all_interventions(): ''' Test all interventions supported by Covasim ''' pars = sc.objdict( pop_size=1e3, pop_infected=10, pop_type='hybrid', n_days=90, ) #%% Define the interventions # 1. Dynamic pars i00 = cv.test_prob(start_day=5, symp_prob=0.3) i01 = cv.dynamic_pars({ 'beta': { 'days': [40, 50], 'vals': [0.005, 0.015] }, 'rel_death_prob': { 'days': 30, 'vals': 2.0 } }) # Starting day 30, make diagnosed people stop transmitting # 2. Sequence i02 = cv.sequence(days=[15, 30, 45], interventions=[ cv.test_num(daily_tests=[20] * pars.n_days), cv.test_prob(symp_prob=0.0), cv.test_prob(symp_prob=0.2), ]) # 3. Change beta i03 = cv.change_beta([30, 50], [0.0, 1], layers='h') i04 = cv.change_beta([30, 40, 60], [0.0, 1.0, 0.5]) # 4. Clip edges -- should match the change_beta scenarios i05 = cv.clip_edges(start_day=30, end_day=50, change={'h': 0.0}) i06 = cv.clip_edges(start_day=30, end_day=40, change=0.0) i07 = cv.clip_edges(start_day=60, end_day=None, change=0.5) # 5. Test number i08 = cv.test_num(daily_tests=[100, 100, 100, 0, 0, 0] * (pars.n_days // 6)) # 6. Test probability i09 = cv.test_prob(symp_prob=0.1) # 7. Contact tracing i10 = cv.test_prob(start_day=20, symp_prob=0.01, asymp_prob=0.0, symp_quar_prob=1.0, asymp_quar_prob=1.0, test_delay=0) i11 = cv.contact_tracing(start_day=20, trace_probs=dict(h=0.9, s=0.7, w=0.7, c=0.3), trace_time=dict(h=0, s=1, w=1, c=3)) # 8. Combination i12 = cv.clip_edges(start_day=18, change={'s': 0.0}) # Close schools i13 = cv.clip_edges(start_day=20, end_day=32, change={ 'w': 0.7, 'c': 0.7 }) # Reduce work and community i14 = cv.clip_edges(start_day=32, end_day=45, change={ 'w': 0.3, 'c': 0.3 }) # Reduce work and community more i15 = cv.clip_edges(start_day=45, end_day=None, change={ 'w': 0.9, 'c': 0.9 }) # Reopen work and community more i16 = cv.test_prob(start_day=38, symp_prob=0.01, asymp_prob=0.0, symp_quar_prob=1.0, asymp_quar_prob=1.0, test_delay=2) # Start testing for TTQ i17 = cv.contact_tracing(start_day=40, trace_probs=dict(h=0.9, s=0.7, w=0.7, c=0.3), trace_time=dict(h=0, s=1, w=1, c=3)) # Start tracing for TTQ #%% Create and run the simulations sims = sc.objdict() sims.dynamic = cv.Sim(pars=pars, interventions=[i00, i01]) sims.sequence = cv.Sim(pars=pars, interventions=i02) sims.change_beta1 = cv.Sim(pars=pars, interventions=i03) sims.clip_edges1 = cv.Sim( pars=pars, interventions=i05) # Roughly equivalent to change_beta1 sims.change_beta2 = cv.Sim(pars=pars, interventions=i04) sims.clip_edges2 = cv.Sim( pars=pars, interventions=[i06, i07]) # Roughly euivalent to change_beta2 sims.test_num = cv.Sim(pars=pars, interventions=i08) sims.test_prob = cv.Sim(pars=pars, interventions=i09) sims.tracing = cv.Sim(pars=pars, interventions=[i10, i11]) sims.combo = cv.Sim(pars=pars, interventions=[i12, i13, i14, i15, i16, i17]) for key, sim in sims.items(): sim.label = key sim.run(verbose=verbose) #%% Plotting if do_plot: for sim in sims.values(): print(f'Running {sim.label}...') sim.plot() fig = pl.gcf() fig.axes[0].set_title(f'Simulation: {sim.label}') return
def make_wcape(p=None, start_day=None, end_day=None, data_path=None, seed=None, verbose=0, debug=1, meta=None): # print(f'Making sim {meta.inds} ({meta.count} of {meta.n_sims})...') # Create parameters total_pop = 7e6 pars = sc.objdict( pop_size=[100e3, 5e3][debug], pop_infected=100, rescale=True, pop_type='hybrid', start_day=start_day, end_day=end_day, rand_seed=seed, verbose=verbose, beta=p.beta, rel_symp_prob=p.rel_symp_prob, iso_factor=dict(h=0.5, s=0.4, w=0.4, c=0.5), # default: dict(h=0.3, s=0.1, w=0.1, c=0.1) quar_factor=dict(h=0.9, s=0.5, w=0.5, c=0.7), # default: dict(h=0.6, s=0.2, w=0.2, c=0.2) ) pars.pop_scale = int(total_pop / pars.pop_size) # Create interventions interventions = [] # Beta interventions interventions += [ cv.clip_edges( days=['2020-03-18', '2020-06-09', '2020-07-27', '2020-08-24'], changes=[0.1, 0.8, 0.1, 0.8], layers=['s']), cv.change_beta(['2020-06-09'], [0.35], layers=['s']), cv.clip_edges(days=[ '2020-03-27', '2020-05-01', '2020-06-01', '2020-08-17', '2020-09-20' ], changes=[0.65, 0.70, 0.72, 0.74, 0.92], layers=['w']), cv.change_beta(['2020-04-10'], [0.75], layers=['w']), cv.change_beta(['2020-04-10'], [0.75], layers=['c'], do_plot=False), # Mandatory masks, then enforced ] # Testing interventions interventions += [ cv.test_prob(symp_prob=p.symp_prob, start_day=0, test_delay=7), cv.contact_tracing(start_day='2020-03-01', trace_probs={ 'h': 1, 's': 0.5, 'w': 0.5, 'c': 0.1 }, trace_time={ 'h': 1, 's': 3, 'w': 7, 'c': 14 }) ] # Create sim sim = cv.Sim(pars=pars, interventions=interventions, datafile=data_path, location='south africa') for intervention in sim['interventions']: intervention.do_plot = False # Store metadata sim.meta = meta return sim
def make_sim(seed, beta, change=0.42, policy='remain', threshold=5, symp_prob=0.01, end_day=None): start_day = '2020-06-15' if end_day is None: end_day = '2021-04-30' total_pop = 11.9e6 # Population of central Vietnam n_agents = 100e3 pop_scale = total_pop / n_agents # Calibration parameters pars = { 'pop_size': n_agents, 'pop_infected': 0, 'pop_scale': pop_scale, 'rand_seed': seed, 'beta': beta, 'start_day': start_day, 'end_day': end_day, 'verbose': 0, 'rescale': True, 'iso_factor': dict(h=0.5, s=0.01, w=0.01, c=0.1), # Multiply beta by this factor for people in isolation 'quar_factor': dict(h=1.0, s=0.2, w=0.2, c=0.2), # Multiply beta by this factor for people in quarantine 'location': 'vietnam', 'pop_type': 'hybrid', 'age_imports': [50, 80], 'rel_crit_prob': 1.75, # Calibration parameter due to hospital outbreak 'rel_death_prob': 2., # Calibration parameter due to hospital outbreak } # Make a sim without parameters, just to load in the data to use in the testing intervention and to get the sim days sim = cv.Sim(start_day=start_day, datafile="vietnam_data.csv") # Set up import assumptions pars['dur_imports'] = sc.dcp(sim.pars['dur']) pars['dur_imports']['exp2inf'] = { 'dist': 'lognormal_int', 'par1': 0.0, 'par2': 0.0 } pars['dur_imports']['inf2sym'] = { 'dist': 'lognormal_int', 'par1': 0.0, 'par2': 0.0 } pars['dur_imports']['sym2sev'] = { 'dist': 'lognormal_int', 'par1': 0.0, 'par2': 2.0 } pars['dur_imports']['sev2crit'] = { 'dist': 'lognormal_int', 'par1': 1.0, 'par2': 3.0 } pars['dur_imports']['crit2die'] = { 'dist': 'lognormal_int', 'par1': 3.0, 'par2': 3.0 } # Define import array import_end = sim.day('2020-07-15') border_start = sim.day('2020-11-30') # Open borders for one month border_end = sim.day('2020-12-31') # Then close them again final_day_ind = sim.day('2021-04-30') imports = np.concatenate(( np.array([ 1, 0, 0, 0, 2, 2, 8, 4, 1, 1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 3, 1, 1, 3, 0, 3, 0, 1, 6, 1, 5, 0, 0 ]), # Generated from cv.n_neg_binomial(1, 0.25) but then hard-copied to remove variation when calibrating pl.zeros( border_start - import_end ), # No imports from the end of the 1st importation window to the border reopening cv.n_neg_binomial( 1, 0.25, border_end - border_start ), # Negative-binomial distributed importations each day pl.zeros(final_day_ind - border_end))) pars['n_imports'] = imports # Add testing and tracing interventions trace_probs = {'h': 1, 's': 0.95, 'w': 0.8, 'c': 0.05} trace_time = {'h': 0, 's': 2, 'w': 2, 'c': 5} pars['interventions'] = [ # Testing and tracing cv.test_num(daily_tests=sim.data['new_tests'].rolling(3).mean(), start_day=2, end_day=sim.day('2020-08-22'), symp_test=80, quar_test=80, do_plot=False), cv.test_prob(start_day=sim.day('2020-08-23'), end_day=sim.day('2020-11-30'), symp_prob=0.05, asymp_quar_prob=0.5, do_plot=False), cv.test_prob(start_day=sim.day('2020-12-01'), symp_prob=symp_prob, asymp_quar_prob=0.5, trigger=cv.trigger('date_diagnosed', 5), triggered_vals={'symp_prob': 0.2}, do_plot=False), cv.contact_tracing(start_day=0, trace_probs=trace_probs, trace_time=trace_time, do_plot=False), # Change death and critical probabilities cv.dynamic_pars( { 'rel_death_prob': { 'days': sim.day('2020-08-31'), 'vals': 1.0 }, 'rel_crit_prob': { 'days': sim.day('2020-08-31'), 'vals': 1.0 } }, do_plot=False ), # Assume these were elevated due to the hospital outbreak but then would return to normal # Increase precautions (especially mask usage) following the outbreak, which are then abandoned after 40 weeks of low case counts cv.change_beta(days=0, changes=change, trigger=cv.trigger('date_diagnosed', 5)), # Close schools and workplaces cv.clip_edges(days=['2020-07-28', '2020-09-14'], changes=[0.1, 1.], layers=['s'], do_plot=True), cv.clip_edges(days=['2020-07-28', '2020-09-05'], changes=[0.1, 1.], layers=['w'], do_plot=False), # Dynamically close them again if cases go over the threshold cv.clip_edges(days=[170], changes=[0.1], layers=['s'], trigger=cv.trigger('date_diagnosed', threshold)), cv.clip_edges(days=[170], changes=[0.1], layers=['w'], trigger=cv.trigger('date_diagnosed', threshold)), ] if policy != 'remain': pars['interventions'] += [ cv.change_beta(days=160, changes=1.0, trigger=cv.trigger('date_diagnosed', 2, direction='below', smoothing=28)) ] if policy == 'dynamic': pars['interventions'] += [ cv.change_beta(days=170, changes=change, trigger=cv.trigger('date_diagnosed', threshold)), ] sim = cv.Sim(pars=pars, datafile="vietnam_data.csv") sim.initialize() return sim
popfile_new = popfile_stem_change + str( pars['rand_seed'] % n_popfiles) + '.ppl' if scen == 'as_normal': popfile = popfile else: popfile = popfile_new sim = cv.Sim(pars, popfile=popfile, load_pop=True, label=scen) day_schools_reopen = sim.day('2020-09-01') interventions = [ cv.test_prob(start_day='2020-07-01', **tp), cv.contact_tracing(start_day='2020-07-01', **ct), cv.clip_edges(days='2020-08-01', changes=p['clip_edges'], layers='w', label='close_work'), cv.clip_edges(days='2020-08-01', changes=p['clip_edges'], layers='c', label='close_community'), cv.change_beta(days='2020-08-01', changes=0.75, layers='c', label='NPI_community'), cv.change_beta(days='2020-08-01', changes=0.75, layers='w', label='NPI_work'), cv.close_schools(day_schools_closed=day_schools_close, start_day=day_schools_open[i],
interv_eff_60 = 0.4 interv_eff_70 = 0.3 interv_eff_80 = 0.2 scenarios = {'baseline': { 'name':'Baseline', 'pars': { 'interventions': None, } }, 'Distance only': { 'name':'Distancing Only', 'pars': { 'interventions': [ cv.change_beta(days=interv_day, changes=interv_eff_60, layers='c'), cv.clip_edges(start_day=interv_day, change={'w':0.4}), cv.clip_edges(start_day=s_close, change={'s':0.2}), ] } }, 't&qSymptomatic': { 'name':'Test-and-quarantine Symptomatic', 'pars': { 'interventions': [ cv.change_beta(days=interv_day, changes=interv_eff_60, layers='c'), cv.clip_edges(start_day=interv_day, change={'w':0.4}), cv.clip_edges(start_day=s_close, change={'s':0.2}), cv.test_prob(start_day=test_day, symp_prob=0.1, asymp_prob=0.01, test_sensitivity=0.9, test_delay=1.0), ] } },
def create_sim(params=None, pop_size=2.25e5, rand_seed=1, folder=None, popfile_stem=None, children_equally_sus=False, alternate_symptomaticity=False, max_pop_seeds=5, load_pop=True, save_pop=False, people=None, label=None, verbose=0, **kwargs): ''' Create the simulation for use with schools. This is the main function used to create the sim object. Args: params (dict): the parameters to use for the simulation pop_size (int): the number of people (merged into parameters) rand_seed (int): the random seed to use (merged into parameters) folder (str): where to look for the population file popfile_stem (str): filename of population file, minus random seed (which gets added) children_equally_sus (bool): whether children should be equally susceptible as adults (for sensitivity) alternate_symptomaticity (bool): whether to use symptoms by age from Table 1 in https://arxiv.org/pdf/2006.08471.pdf max_pop_seeds (int): maximum number of populations to generate (for use with different random seeds) load_pop (bool): whether to load people from disk (otherwise, use supplied or create afresh) save_pop (bool): if a population is being generated, whether to save people (People): if supplied, use instead of loading from file label (str): a name for the simulation verbose (float): level of verbosity to use (merged into parameters) kwargs (dict): merged with params Returns: A sim instance ''' # Handle parameters and merge together different sets of defaults default_pars = dict( pop_size = pop_size, pop_scale = 1, pop_type = 'synthpops', rescale = False, # True causes problems verbose = verbose, start_day = '2020-09-01', end_day = '2021-01-31', rand_seed = rand_seed ) p = sc.objdict(sc.mergedicts(default_pars, define_pars(which='best', kind='both'), params, kwargs)) # Get default parameter values #%% Define interventions symp_prob = p.pop('symp_prob') change_beta = p.pop('change_beta') tp_pars = dict( symp_prob = symp_prob, # 0.10 asymp_prob = 0.0022, symp_quar_prob = symp_prob, # 0.10 asymp_quar_prob = 0.001, test_delay = 2.0, ) ct_pars = dict( trace_probs = {'w': 0.1, 'c': 0, 'h': 0.9, 's': 0.8}, # N.B. 's' will be ignored if using the Schools class trace_time = {'w': 2, 'c': 0, 'h': 1, 's': 2}, ) cb_pars = dict( changes=change_beta, layers=['w', 'c'], label='NPI_work_community', ) ce_pars = dict( changes=0.65, layers=['w', 'c'], label='close_work_community' ) interventions = [ cv.test_prob(start_day=p.start_day, **tp_pars), cv.contact_tracing(start_day=p.start_day, **ct_pars), cv.change_beta(days=p.start_day, **cb_pars), cv.clip_edges(days=p.start_day, **ce_pars), # N.B. Schools are not closed in create_sim, must be handled outside this function ] for interv in interventions: interv.do_plot = False #%% Handle population -- NB, although called popfile, might be a People object if load_pop: # Load from disk -- normal usage if popfile_stem is None: popfile_stem = os.path.join('inputs', f'kc_synthpops_clustered_{int(pop_size)}_withstaff_seed') if folder is not None: popfile_stem = os.path.join(folder, popfile_stem) # Prepend user folder pop_seed = p.rand_seed % max_pop_seeds popfile = popfile_stem + str(pop_seed) + '.ppl' print(f'Note: loading population from {popfile}') elif people is not None: # People is supplied; use that popfile = people print('Note: using supplied people') else: # Generate print('Note: population not supplied; regenerating...') popfile = cvsch.make_population(pop_size=p.pop_size, rand_seed=p.rand_seed, max_pop_seeds=max_pop_seeds, do_save=False) # Create sim sim = cv.Sim(p, popfile=popfile, load_pop=True, label=label, interventions=interventions) # Modify sim if children_equally_sus: prog = sim.pars['prognoses'] ages = prog['age_cutoffs'] sus_ORs = prog['sus_ORs'] sus_ORs[ages<=20] = 1 prog['sus_ORs'] = sus_ORs if alternate_symptomaticity: prog = sim.pars['prognoses'] ages = prog['age_cutoffs'] symp_probs = prog['symp_probs'] # Source: table 1 from https://arxiv.org/pdf/2006.08471.pdf symp_probs[:] = 0.6456 symp_probs[ages<80] = 0.3546 symp_probs[ages<60] = 0.3054 symp_probs[ages<40] = 0.2241 symp_probs[ages<20] = 0.1809 prog['symp_probs'] = symp_probs return sim
''' Test Plotly plotting outside of the webapp. ''' import plotly.io as pio import covasim as cv pio.renderers.default = "browser" # Or can use a Jupyter notebook ce = cv.clip_edges(**{'start_day': 10, 'change': 0.5}) sim = cv.Sim(pop_size=100, n_days=60, datafile='../example_data.csv', interventions=ce, verbose=0) sim.run() f1list = cv.plotly_sim(sim, do_show=True) f2 = cv.plotly_people(sim, do_show=True) f3 = cv.plotly_animate(sim, do_show=True)
def test_all_interventions(): ''' Test all interventions supported by Covasim ''' pars = sc.objdict( pop_size=1e3, pop_infected=10, pop_type='hybrid', n_days=90, ) #%% Define the interventions # 1. Dynamic pars i1a = cv.test_prob(start_day=5, symp_prob=0.3) i1b = cv.dynamic_pars({ 'beta': { 'days': [40, 50], 'vals': [0.005, 0.015] }, 'rel_death_prob': { 'days': 30, 'vals': 2.0 } }) # Starting day 30, make diagnosed people stop transmitting # 2. Sequence i2 = cv.sequence(days=[15, 30, 45], interventions=[ cv.test_num(daily_tests=[20] * pars.n_days), cv.test_prob(symp_prob=0.0), cv.test_prob(symp_prob=0.2), ]) # 3. Change beta i3a = cv.change_beta([30, 50], [0.0, 1.0], layers='h') i3b = cv.change_beta([30, 40, 60], [0.0, 1.0, 0.5]) # 4. Clip edges -- should match the change_beta scenarios -- note that intervention i07 was removed i4a = cv.clip_edges([30, 50], [0.0, 1.0], layers='h') i4b = cv.clip_edges([30, 40, 60], [0.0, 1.0, 0.5]) # 5. Test number i5 = cv.test_num(daily_tests=[100, 100, 100, 0, 0, 0] * (pars.n_days // 6)) # 6. Test probability i6 = cv.test_prob(symp_prob=0.1) # 7. Contact tracing i7a = cv.test_prob(start_day=20, symp_prob=0.01, asymp_prob=0.0, symp_quar_prob=1.0, asymp_quar_prob=1.0, test_delay=0) i7b = cv.contact_tracing(start_day=20, trace_probs=dict(h=0.9, s=0.7, w=0.7, c=0.3), trace_time=dict(h=0, s=1, w=1, c=3)) # 8. Combination i8a = cv.clip_edges(days=18, changes=0.0, layers='s') # Close schools i8b = cv.clip_edges(days=[20, 32, 45], changes=[0.7, 0.3, 0.9], layers=['w', 'c']) # Reduce work and community i8c = cv.test_prob(start_day=38, symp_prob=0.01, asymp_prob=0.0, symp_quar_prob=1.0, asymp_quar_prob=1.0, test_delay=2) # Start testing for TTQ i8d = cv.contact_tracing(start_day=40, trace_probs=dict(h=0.9, s=0.7, w=0.7, c=0.3), trace_time=dict(h=0, s=1, w=1, c=3)) # Start tracing for TTQ #%% Create and run the simulations sims = sc.objdict() sims.dynamic = cv.Sim(pars=pars, interventions=[i1a, i1b]) sims.sequence = cv.Sim(pars=pars, interventions=i2) sims.change_beta1 = cv.Sim(pars=pars, interventions=i3a) sims.clip_edges1 = cv.Sim( pars=pars, interventions=i4a) # Roughly equivalent to change_beta1 sims.change_beta2 = cv.Sim(pars=pars, interventions=i3b) sims.clip_edges2 = cv.Sim( pars=pars, interventions=i4b) # Roughly equivalent to change_beta2 sims.test_num = cv.Sim(pars=pars, interventions=i5) sims.test_prob = cv.Sim(pars=pars, interventions=i6) sims.tracing = cv.Sim(pars=pars, interventions=[i7a, i7b]) sims.combo = cv.Sim(pars=pars, interventions=[i8a, i8b, i8c, i8d]) for key, sim in sims.items(): sim.label = key sim.run(verbose=verbose) #%% Plotting if do_plot: for sim in sims.values(): print(f'Running {sim.label}...') sim.plot() fig = pl.gcf() fig.axes[0].set_title(f'Simulation: {sim.label}') return
def make_ints(make_future_ints=True, mask_uptake=None, venue_trace_prob=None, future_test_prob=None, mask_eff=0.3): # Make historical interventions initresponse = '2020-03-15' lockdown = '2020-03-23' reopen1 = '2020-05-01' # Two adults allowed to visit a house reopen2 = '2020-05-15' # Up to 5 adults can visit a house; food service and non-essential retail start to resume reopen3 = '2020-06-01' # Pubs and regional travel open, plus more social activities reopen4 = '2020-07-01' # large events, cinemas, museums, open; fewer restrictions on cafes/pubs/etc, school_dates = ['2020-05-11', '2020-05-18', '2020-05-25'] comm_beta_aug = 0.7 ints = [cv.clip_edges(days=[initresponse,lockdown]+school_dates, changes=[0.75, 0.05, 0.8, 0.9, 1.0], layers=['S'], do_plot=False), cv.clip_edges(days=[lockdown, reopen2, reopen3, reopen4], changes=[0.5, 0.65, 0.75, 0.85], layers=['W'], do_plot=False), cv.clip_edges(days=[lockdown, reopen2, reopen4], changes=[0, 0.5, 1.0], layers=['pSport'], do_plot=False), cv.clip_edges(days=[lockdown, '2020-06-22'], changes=[0, 1.0], layers=['cSport'], do_plot=False), cv.change_beta(days=[lockdown, reopen2, reopen4], changes=[1.2, 1.1, 1.], layers=['H'], do_plot=True), cv.change_beta(days=[lockdown, reopen2], changes=[0, comm_beta_aug], layers=['church'], do_plot=False), cv.change_beta(days=[lockdown, reopen1, reopen2, reopen3, reopen4], changes=[0.0, 0.3, 0.4, 0.5, comm_beta_aug], layers=['social'], do_plot=False), # Dynamic layers ['C', 'entertainment', 'cafe_restaurant', 'pub_bar', 'transport', 'public_parks', 'large_events'] cv.change_beta(days=[lockdown], changes=[comm_beta_aug], layers=['C'], do_plot=True), cv.change_beta(days=[lockdown, reopen4], changes=[0, comm_beta_aug], layers=['entertainment'], do_plot=False), cv.change_beta(days=[lockdown, reopen2], changes=[0, comm_beta_aug], layers=['cafe_restaurant'], do_plot=False), cv.change_beta(days=[lockdown, reopen3, reopen4], changes=[0, 0.5, comm_beta_aug], layers=['pub_bar'], do_plot=False), cv.change_beta(days=[lockdown, reopen2, reopen4], changes=[0.2, 0.3, comm_beta_aug], layers=['transport'], do_plot=False), cv.change_beta(days=[lockdown, reopen2, reopen4], changes=[0.4, 0.5, comm_beta_aug], layers=['public_parks'], do_plot=False), cv.change_beta(days=[lockdown, reopen4], changes=[0.0, comm_beta_aug], layers=['large_events'], do_plot=False), ] # Approximate a mask intervention by changing beta in all layers where people would wear masks - assuming not in schools, sport, social gatherings, or home mask_uptake_aug = 0.15 mask_uptake_sep = 0.3 mask_beta_change_aug = (1-mask_uptake_aug)*comm_beta_aug + mask_uptake_aug*mask_eff*comm_beta_aug mask_beta_change_sep = (1-mask_uptake_sep)*comm_beta_aug + mask_uptake_sep*mask_eff*comm_beta_aug ints += [cv.change_beta(days=['2020-08-01', '2020-08-31'] * 8, changes=[mask_beta_change_aug, 0.7] * 8, layers=['church', 'C', 'entertainment', 'cafe_restaurant', 'pub_bar', 'transport', 'public_parks', 'large_events']), cv.change_beta(days=['2020-09-01', today] * 8, changes=[mask_beta_change_sep, 0.7] * 8, layers=['church', 'C', 'entertainment', 'cafe_restaurant', 'pub_bar', 'transport', 'public_parks', 'large_events']) ] if make_future_ints: ints += [cv.change_beta(days=[today] * 8, changes=[(1 - mask_uptake) * comm_beta_aug + mask_uptake * mask_eff * comm_beta_aug] * 8, layers=['church', 'C', 'entertainment', 'cafe_restaurant', 'pub_bar', 'transport', 'public_parks', 'large_events'])] # Testing symp_prob_prelockdown = 0.04 # Limited testing pre lockdown symp_prob_lockdown = 0.07 # 0.065 #Increased testing during lockdown symp_prob_postlockdown = 0.19 # 0.165 # Testing since lockdown asymp_quar_prob_postlockdown = (1-(1-symp_prob_postlockdown)**10) future_asymp_test_prob = (1-(1-future_test_prob)**10)/2 ints += [cv.test_prob(start_day=0, end_day=lockdown, symp_prob=symp_prob_prelockdown, asymp_quar_prob=0.01, do_plot=False), cv.test_prob(start_day=lockdown, end_day=reopen2, symp_prob=symp_prob_lockdown, asymp_quar_prob=0.01,do_plot=False), cv.test_prob(start_day=reopen2, end_day=today, symp_prob=symp_prob_postlockdown, asymp_quar_prob=asymp_quar_prob_postlockdown,do_plot=True)] if make_future_ints: ints += [cv.test_prob(start_day=tomorrow, symp_prob=future_test_prob, asymp_quar_prob=future_asymp_test_prob, do_plot=True)] # Tracing trace_probs = {'H': 1, 'S': 0.95, # Home and school 'W': 0.8, 'pSport': 0.8, 'cSport': 0.8, 'social': 0.8, # Work and social 'C': 0.05, 'public_parks': 0.05, # Non-venue-based 'church': 0.5, 'entertainment': 0.5, 'cafe_restaurant': 0.5, 'pub_bar': 0.5, 'large_events': 0.5, # Venue-based 'transport': 0.1, # Transport } trace_time = {'H': 0, 'S': 0.5, # Home and school 'W': 1, 'pSport': 1, 'cSport': 1, 'social': 1, # Work and social: [0.29, 0.59, 0.74, 0.78, 0.80, 0.80, 0.80, 0.80] 'C': 2, 'public_parks': 2, # Non-venue-based: [0.0068, 0.0203, 0.0338, 0.0429, 0.0474, 0.0492, 0.0498, 0.0499] 'church': 1, 'entertainment': 1, 'cafe_restaurant': 1, 'pub_bar': 1, 'large_events': 1, # Venue-based: [0.068, 0.203, 0.338, 0.429, 0.474, 0.492, 0.498, 0.499] 'transport': 1, # Transport: [0.014, 0.041, 0.068, 0.086, 0.095, 0.098, 0.100, 0.100] } trace_time_f = {'H': 0, 'S': 0.5, # Home and school 'W': 1, 'pSport': 1, 'cSport': 1, 'social': 1, # Work and social: [0.29, 0.59, 0.74, 0.78, 0.80, 0.80, 0.80, 0.80] 'C': 2, 'public_parks': 2, # Non-venue-based: [0.0068, 0.0203, 0.0338, 0.0429, 0.0474, 0.0492, 0.0498, 0.0499] 'church': 1, 'entertainment': 1, 'cafe_restaurant': 1, 'pub_bar': 1, 'large_events': 1, # Venue-based: [0.068, 0.203, 0.338, 0.429, 0.474, 0.492, 0.498, 0.499] 'transport': 2, # Transport: [0.014, 0.041, 0.068, 0.086, 0.095, 0.098, 0.100, 0.100] } ints += [cv.contact_tracing(trace_probs=trace_probs, trace_time=trace_time, distribute_times=True, start_day=0, end_day=today, do_plot=False)] if make_future_ints: ints += [cv.contact_tracing(trace_probs={'H': 1, 'S': 0.95, 'W': 0.8, 'pSport': 0.8, 'cSport': 0.8, 'social': 0.8, 'C': 0.05, 'public_parks': 0.05, 'church': venue_trace_prob, 'entertainment': venue_trace_prob, 'cafe_restaurant': venue_trace_prob, 'pub_bar': venue_trace_prob, 'large_events': venue_trace_prob, 'transport': 0.1}, trace_time=trace_time_f, distribute_times=True, start_day=tomorrow, do_plot=False)] # Close borders, then open them again to account for Victorian imports and leaky quarantine ints += [cv.dynamic_pars({'n_imports': {'days': [14, 112, 116], 'vals': [0, 8, 0]}}, do_plot=False)] return ints
def create_sim(beta,n0,rd1,rd2,rd3,seed): beta = beta pop_infected = n0 # initial cases of infection start_day = '2020-02-01' end_day = '2020-11-30' data_file = df # Set the parameters total_pop = 5.8e6 # Denmark population size pop_size = 100e3 # Actual simulated population pop_scale = int(total_pop/pop_size) pop_type = 'hybrid' asymp_factor = 2 pars = sc.objdict( pop_size = pop_size, pop_infected = pop_infected, pop_scale = pop_scale, pop_type = pop_type, start_day = start_day, end_day = end_day, beta = beta, asymp_factor = asymp_factor, rescale = True, verbose = 0.1, rand_seed = seed, ) # Create the baseline simulation sim = cv.Sim(pars=pars, datafile=data_file, location='denmark') relative_death = cv.dynamic_pars(rel_death_prob=dict(days=[1,130,230], vals=[rd1,rd2,rd3])) interventions = [relative_death] ### beta changes ### beta_days = ['2020-03-15','2020-04-15','2020-05-10','2020-06-22','2020-07-20','2020-08-22','2020-09-01','2020-09-22','2020-10-01','2020-10-15','2020-11-01', '2020-11-20'] h_beta_changes = [1.10, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.10, 1.10, 1.10, 1.20] s_beta_changes = [0.80, 0.50, 0.50, 0.40, 0.60, 0.60, 1.00, 0.80, 0.80, 1.00, 0.80, 0.90] w_beta_changes = [0.80, 0.50, 0.50, 0.40, 0.60, 0.60, 1.00, 0.80, 0.80, 1.00, 0.80, 0.90] c_beta_changes = [0.90, 0.60, 0.50, 0.70, 0.90, 0.80, 1.00, 0.70, 0.70, 1.00, 0.80, 1.10] # Define the beta changes h_beta = cv.change_beta(days=beta_days, changes=h_beta_changes, layers='h') s_beta = cv.change_beta(days=beta_days, changes=s_beta_changes, layers='s') w_beta = cv.change_beta(days=beta_days, changes=w_beta_changes, layers='w') c_beta = cv.change_beta(days=beta_days, changes=c_beta_changes, layers='c') ### edge clipping ### clip_days = ['2020-03-15','2020-04-15','2020-05-10','2020-06-08','2020-06-22','2020-08-17','2020-09-01','2020-09-15','2020-10-05', '2020-11-05','2020-11-20','2020-12-07','2020-12-19','2020-12-25'] s_clip_changes = [0.01, 0.20, 0.40, 0.70, 0.05, 0.10, 0.90, 0.80, 0.70, 0.70, 0.70, 0.60, 0.15, 0.05] w_clip_changes = [0.10, 0.30, 0.50, 0.70, 0.60, 0.80, 1.00, 0.80, 0.70, 0.70, 0.70, 0.70, 0.70, 0.10] c_clip_changes = [0.20, 0.40, 0.60, 0.85, 1.00, 1.00, 1.00, 0.80, 0.80, 0.90, 0.90, 0.90, 1.00, 0.30] # Define the edge clipping s_clip = cv.clip_edges(days=clip_days, changes=s_clip_changes, layers='s') w_clip = cv.clip_edges(days=clip_days, changes=w_clip_changes, layers='w') c_clip = cv.clip_edges(days=clip_days, changes=c_clip_changes, layers='c') interventions += [h_beta, w_beta, s_beta, c_beta, w_clip, s_clip, c_clip] # import infections from 2020-02-20 to 2020-03-01 imports1 = cv.dynamic_pars(n_imports=dict(days=[25, 35], vals=[2,0])) imports2 = cv.dynamic_pars(n_imports=dict(days=[171, 190], vals=[2,0])) interventions += [imports1,imports2] iso_vals = [{'h': 0.5, 's': 0.05, 'w': 0.05, 'c': 0.1}] #dict(h=0.5, s=0.05, w=0.05, c=0.1) interventions += [cv.dynamic_pars({'iso_factor': {'days': sim.day('2020-03-15'), 'vals': iso_vals }})] # From May 12, starting tracing and isolation strategy tracing_prob = dict(h=1.0, s=0.5, w=0.5, c=0.2) trace_time = {'h':0, 's':1, 'w':1, 'c':2} interventions += [cv.contact_tracing(trace_probs=tracing_prob, trace_time=trace_time, start_day='2020-05-12')] interventions += [cv.test_num(daily_tests=sim.data['new_tests'], start_day=0, end_day=sim.day(end_day), test_delay=1, symp_test=50, sensitivity=0.97,subtarget= prior_test)] sim.update_pars(interventions=interventions) for intervention in sim['interventions']: intervention.do_plot = False sim.initialize() return sim
}) # 2. Sequence i02 = cv.sequence(days=[20, 40, 60], interventions=[ cv.test_num(daily_tests=[20] * n_days), cv.test_prob(symp_prob=0.0), cv.test_prob(symp_prob=0.2), ]) # 3. Change beta i03 = cv.change_beta([30, 50], [0.0, 1], layers='h') i04 = cv.change_beta([30, 40, 60], [0.0, 1.0, 0.5]) # 4. Clip edges -- should match the change_beta scenarios i05 = cv.clip_edges(days=[30, 50], changes={'h': 0.0}) i06 = cv.clip_edges(days=[30, 40], changes=0.0) i07 = cv.clip_edges(days=[60, None], changes=0.5) # 5. Test number i08 = cv.test_num(daily_tests=[100, 100, 100, 0, 0, 0] * (n_days // 6)) # 6. Test probability i09 = cv.test_prob(symp_prob=0.1) # 7. Contact tracing i10 = cv.test_prob(start_day=20, symp_prob=0.01, asymp_prob=0.0, symp_quar_prob=1.0, asymp_quar_prob=1.0,
def run_sim(params): p = sc.objdict( sc.mergedicts(define_pars(which='best', kind='both'), params)) if 'rand_seed' not in p: seed = 1 print( f'Note, could not find random seed in {params}! Setting to {seed}') p['rand_seed'] = seed # Ensure this exists popfile_stem = f'inputs/kc_synthpops_clustered_withstaff_seed' tp = sc.objdict( symp_prob=0.03, asymp_prob=0.001, symp_quar_prob=0.01, asymp_quar_prob=0.001, test_delay=5.0, ) ct = sc.objdict( trace_probs={ 'w': 0.1, 'c': 0, 'h': 0.8, 's': 0.8 }, trace_time=5.0, ) pars = { 'pop_size': 225e3, 'pop_scale': 10, 'pop_type': 'synthpops', 'pop_infected': p.pop_infected, 'rescale': True, 'rescale_factor': 1.1, 'verbose': 0, 'start_day': '2020-07-01', 'end_day': '2020-12-01', 'rand_seed': p.rand_seed, } n_popfiles = 5 popfile = popfile_stem + str(params['rand_seed'] % n_popfiles) + '.ppl' sim = cv.Sim(pars, popfile=popfile, load_pop=True) interventions = [ cv.test_prob(start_day='2020-07-01', **tp), cv.contact_tracing(start_day='2020-07-01', **ct), cv.clip_edges(days='2020-08-01', changes=p.clip_edges, layers='w', label='close_work'), cv.clip_edges(days='2020-08-01', changes=p.clip_edges, layers='c', label='close_community'), cv.change_beta(days='2020-08-01', changes=0.75, layers='c', label='NPI_community'), cv.change_beta(days='2020-08-01', changes=0.75, layers='w', label='NPI_work'), cv.close_schools(day_schools_closed='2020-07-01', start_day=None, label='close_schools') ] sim['interventions'] = interventions for interv in sim['interventions']: interv.do_plot = False sim.run() return (sim)
def create_sim(seed, ratio): beta = 0.014 pop_infected = 10 start_day = '2020-02-01' #end_day = '2020-11-30' end_day = '2021-03-31' data_file = df # Set the parameters total_pop = 5.8e6 # Denmark population size pop_size = 100e3 # Actual simulated population pop_scale = int(total_pop / pop_size) pop_type = 'hybrid' asymp_factor = 2 pars = sc.objdict( pop_size=pop_size, pop_infected=pop_infected, pop_scale=pop_scale, pop_type=pop_type, start_day=start_day, end_day=end_day, beta=beta, asymp_factor=asymp_factor, rescale=True, verbose=0.1, rand_seed=seed, ) # Create the baseline simulation sim = cv.Sim(pars=pars, datafile=data_file, location='denmark') relative_death = cv.dynamic_pars(rel_death_prob=dict(days=[ sim.day('2020-02-01'), sim.day('2020-06-09'), sim.day('2020-09-17') ], vals=[1.3, 0.8, 0.4])) interventions = [relative_death] ### Change beta ### beta_days = [ '2020-03-15', '2020-04-15', '2020-05-10', '2020-06-22', '2020-07-20', '2020-08-22', '2020-09-01', '2020-09-22', '2020-10-01', '2020-10-15', '2020-11-01', '2020-11-20', '2020-11-30', '2020-12-14', '2021-01-01', '2021-03-01' ] h_beta_changes = [ 1.10, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.10, 1.10, 1.10, 1.20, 1.30, 1.20, 1.10, 1.00 ] s_beta_changes = [ 0.80, 0.50, 0.50, 0.40, 0.60, 0.60, 1.00, 0.80, 0.80, 1.00, 0.80, 1.00, 1.20, 1.00, 0.80, 0.70 ] w_beta_changes = [ 0.80, 0.50, 0.50, 0.40, 0.60, 0.60, 1.00, 0.80, 0.80, 1.00, 0.80, 1.00, 1.20, 1.00, 0.80, 0.70 ] c_beta_changes = [ 0.90, 0.60, 0.50, 0.70, 0.90, 0.80, 1.00, 0.70, 0.70, 1.00, 0.80, 1.10, 1.30, 1.10, 1.00, 0.80 ] # Define the beta changes h_beta = cv.change_beta(days=beta_days, changes=h_beta_changes, layers='h') s_beta = cv.change_beta(days=beta_days, changes=s_beta_changes, layers='s') w_beta = cv.change_beta(days=beta_days, changes=w_beta_changes, layers='w') c_beta = cv.change_beta(days=beta_days, changes=c_beta_changes, layers='c') ### edge clipping ### clip_days = [ '2020-03-15', '2020-04-15', '2020-05-10', '2020-06-08', '2020-06-22', '2020-08-17', '2020-09-01', '2020-09-15', '2020-10-05', '2020-11-05', '2020-11-20', '2020-12-09', '2020-12-19', '2020-12-25', '2021-01-04', '2021-02-01', '2021-03-01' ] s_clip_changes = [ 0.01, 0.20, 0.40, 0.70, 0.05, 0.10, 0.90, 0.80, 0.70, 0.70, 0.70, 0.40, 0.05, 0.05, 0.05, 0.30, 0.50 ] w_clip_changes = [ 0.10, 0.30, 0.50, 0.70, 0.60, 0.80, 1.00, 0.80, 0.70, 0.70, 0.70, 0.60, 0.40, 0.10, 0.50, 0.60, 0.60 ] c_clip_changes = [ 0.20, 0.40, 0.60, 0.85, 1.00, 1.00, 1.00, 0.80, 0.80, 0.90, 0.90, 0.70, 0.80, 0.50, 0.60, 0.70, 0.80 ] # Define the edge clipping s_clip = cv.clip_edges(days=clip_days, changes=s_clip_changes, layers='s') w_clip = cv.clip_edges(days=clip_days, changes=w_clip_changes, layers='w') c_clip = cv.clip_edges(days=clip_days, changes=c_clip_changes, layers='c') interventions += [h_beta, w_beta, s_beta, c_beta, w_clip, s_clip, c_clip] # Add a new change in beta to represent the takeover of the new variant B.1.1.7 nv_days = np.linspace(sim.day('2020-12-14'), sim.day('2021-03-28'), 15 * 7) nv_prop = 0.952 / (1 + np.exp(-0.099 * (nv_days - sim.day('2020-12-14') - 59))) nv_change = nv_prop * ratio + (1 - nv_prop) * 1.0 #r = 1.5 nv_beta = cv.change_beta(days=nv_days, changes=nv_change) c = np.r_[0.8 * np.ones(sim.day('2021-02-13') - sim.day('2020-12-14')), 0.4 * np.ones(sim.day('2021-03-29') - sim.day('2021-02-13'))] relative_severe = cv.dynamic_pars(rel_severe_prob=dict( days=nv_days, vals=nv_prop * 1.0 + (1 - nv_prop) * 1)) relative_critical = cv.dynamic_pars(rel_crit_prob=dict( days=nv_days, vals=nv_prop * 1.0 + (1 - nv_prop) * 1)) relative_death_nv = cv.dynamic_pars(rel_death_prob=dict( days=nv_days, vals=nv_prop * c * 1.0 + (1 - nv_prop) * c)) interventions += [ nv_beta, relative_severe, relative_critical, relative_death_nv ] # import infections from 2020-02-20 to 2020-03-01 imports1 = cv.dynamic_pars(n_imports=dict(days=[25, 35], vals=[2, 0])) imports2 = cv.dynamic_pars(n_imports=dict(days=[171, 190], vals=[2, 0])) interventions += [imports1, imports2] iso_vals = [{ 'h': 0.5, 's': 0.05, 'w': 0.05, 'c': 0.1 }] #dict(h=0.5, s=0.05, w=0.05, c=0.1) interventions += [ cv.dynamic_pars( {'iso_factor': { 'days': sim.day('2020-03-15'), 'vals': iso_vals }}) ] # From May 12, starting tracing and isolation strategy tracing_prob = dict(h=1.0, s=0.5, w=0.5, c=0.2) trace_time = {'h': 0, 's': 1, 'w': 1, 'c': 2} interventions += [ cv.contact_tracing(trace_probs=tracing_prob, trace_time=trace_time, start_day='2020-05-12') ] interventions += [ cv.test_num(daily_tests=sim.data['new_tests'], start_day=0, end_day=sim.day(end_day), test_delay=1, symp_test=50, sensitivity=0.97, subtarget=prior_test) ] vaccine1 = vaccine_plan(daily1, start_day='2021-01-06', end_day='2021-01-24', delay=22, rel_symp=0.5, rel_sus=0.2, subtarget=vaccinate_by_age) vaccine2 = vaccine_plan(daily2, start_day='2021-01-25', end_day='2021-02-15', delay=27, rel_symp=0.5, rel_sus=0.2, subtarget=vaccinate_by_age) vaccine3 = vaccine_plan(daily3, start_day='2021-02-16', end_day='2021-03-07', delay=24, rel_symp=0.5, rel_sus=0.2, subtarget=vaccinate_by_age) vaccine4 = vaccine_plan(daily4, start_day='2021-03-08', end_day='2021-04-10', delay=37, rel_symp=0.5, rel_sus=0.2, subtarget=vaccinate_by_age) interventions += [vaccine1, vaccine2, vaccine3, vaccine4] sim.update_pars(interventions=interventions) for intervention in sim['interventions']: intervention.do_plot = False sim.initialize() return sim
def test_all_interventions(do_plot=False): ''' Test all interventions supported by Covasim ''' sc.heading('Testing default interventions') # Default parameters, using the random layer pars = sc.objdict( pop_size=1e3, scaled_pop=10e3, pop_infected=10, n_days=90, verbose=verbose, ) hpars = sc.mergedicts( pars, {'pop_type': 'hybrid'}) # Some, but not all, tests require layers rsim = cv.Sim(pars) hsim = cv.Sim(hpars) def make_sim(which='r', interventions=None): ''' Helper function to avoid having to recreate the sim each time ''' if which == 'r': sim = sc.dcp(rsim) elif which == 'h': sim = sc.dcp(hsim) sim['interventions'] = interventions sim.initialize() return sim #%% Define the interventions # 1. Dynamic pars i1a = cv.test_prob(start_day=5, symp_prob=0.3) i1b = cv.dynamic_pars({ 'beta': { 'days': [40, 50], 'vals': [0.005, 0.015] }, 'rel_death_prob': { 'days': 30, 'vals': 2.0 } }) # Starting day 30, make diagnosed people stop transmitting # 2. Sequence i2 = cv.sequence(days=[15, 30, 45], interventions=[ cv.test_num(daily_tests=[20] * pars.n_days), cv.test_prob(symp_prob=0.0), cv.test_prob(symp_prob=0.2), ]) # 3. Change beta i3a = cv.change_beta([30, 50], [0.0, 1.0], layers='h') i3b = cv.change_beta([30, 40, 60], [0.0, 1.0, 0.5]) # 4. Clip edges -- should match the change_beta scenarios -- note that intervention i07 was removed i4a = cv.clip_edges([30, 50], [0.0, 1.0], layers='h') i4b = cv.clip_edges([30, 40, 60], [0.0, 1.0, 0.5]) # 5. Test number i5 = cv.test_num(daily_tests=[100, 100, 100, 0, 0, 0] * (pars.n_days // 6)) # 6. Test probability i6 = cv.test_prob(symp_prob=0.1) # 7. Contact tracing i7a = cv.test_prob(start_day=20, symp_prob=0.01, asymp_prob=0.0, symp_quar_prob=1.0, asymp_quar_prob=1.0, test_delay=0) i7b = cv.contact_tracing(start_day=20, trace_probs=dict(h=0.9, s=0.7, w=0.7, c=0.3), trace_time=dict(h=0, s=1, w=1, c=3)) # 8. Combination, with dynamically set days def check_inf(interv, sim, thresh=10, close_day=18): days = close_day if sim.people.infectious.sum() > thresh else np.nan return days i8a = cv.clip_edges(days=check_inf, changes=0.0, layers='s') # Close schools i8b = cv.clip_edges(days=[20, 32, 45], changes=[0.7, 0.3, 0.9], layers=['w', 'c']) # Reduce work and community i8c = cv.test_prob(start_day=38, symp_prob=0.01, asymp_prob=0.0, symp_quar_prob=1.0, asymp_quar_prob=1.0, test_delay=2) # Start testing for TTQ i8d = cv.contact_tracing(start_day=40, trace_probs=dict(h=0.9, s=0.7, w=0.7, c=0.3), trace_time=dict(h=0, s=1, w=1, c=3)) # Start tracing for TTQ # 9. Vaccine i9a = cv.simple_vaccine(days=20, prob=1.0, rel_sus=1.0, rel_symp=0.0) i9b = cv.simple_vaccine(days=50, prob=1.0, rel_sus=0.0, rel_symp=0.0) #%% Create the simulations sims = sc.objdict() sims.dynamic = make_sim('r', [i1a, i1b]) sims.sequence = make_sim('r', i2) sims.change_beta1 = make_sim('h', i3a) sims.clip_edges1 = make_sim('h', i4a) # Roughly equivalent to change_beta1 sims.change_beta2 = make_sim('r', i3b) sims.clip_edges2 = make_sim('r', i4b) # Roughly equivalent to change_beta2 sims.test_num = make_sim('r', i5) sims.test_prob = make_sim('r', i6) sims.tracing = make_sim('h', [i7a, i7b]) sims.combo = make_sim('h', [i8a, i8b, i8c, i8d]) sims.vaccine = make_sim('r', [i9a, i9b]) # Run the simualations for key, sim in sims.items(): sim.label = key sim.run() # Test intervention retrieval methods sim = sims.combo ce1, ce2 = sim.get_interventions(cv.clip_edges) ce, tp = sim.get_interventions([0, 2]) inds = sim.get_interventions(cv.clip_edges, as_inds=True) # Returns [0,1] assert inds == [0, 1] sim.get_interventions('summary') # Prints a summary # Test other intervention methods ce.disp() ce.shrink() #%% Plotting if do_plot: for sim in sims.values(): print(f'Running {sim.label}...') sim.plot() fig = pl.gcf() try: fig.axes[0].set_title(f'Simulation: {sim.label}') except: pass return