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 intervention_build_sequence(self, day_list, intervention_list): my_sequence = cv.sequence(days=day_list, interventions=intervention_list) self.interventions = my_sequence
def test_interventions(do_plot=False, do_show=True, do_save=False, fig_path=None): sc.heading('Test of testing interventions') sc.heading('Setting up...') sc.tic() n_runs = 3 verbose = 1 base_pars = { 'pop_size': 1000, 'pop_type': 'hybrid', } base_sim = cv.Sim(base_pars) # create sim object n_people = base_sim['pop_size'] npts = base_sim.npts # Define overall testing assumptions # Remember that this is the daily % of the population that gets tested. S Korea (one of the highest-testing places) tested # an average of 10000 people/day over March, or 270,000 in total. This is ~200 people per million every day (0.02%).... max_optimistic_testing = 0.1 # ... which means that this is an artificially high number, for testing purposes only!! optimistic_daily_tests = [ max_optimistic_testing * n_people ] * npts # Very best-case scenario for asymptomatic testing # Define the scenarios scenarios = { 'baseline': { 'name': 'Status quo, no testing', 'pars': { 'interventions': None, } }, 'test_skorea': { 'name': 'Assuming South Korea testing levels of 0.02% daily (untargeted); isolate positives', 'pars': { 'interventions': cv.test_num(daily_tests=optimistic_daily_tests) } }, 'floating': { 'name': 'Test with constant probability based on symptoms', 'pars': { 'interventions': cv.test_prob(symp_prob=max_optimistic_testing, asymp_prob=0.0) } }, 'sequence': { 'name': 'Historical switching to probability', 'pars': { 'interventions': cv.sequence( days=[10, 51], interventions=[ cv.test_num(daily_tests=optimistic_daily_tests), cv.test_prob(symp_prob=0.2, asymp_prob=0.002), ]) } }, } metapars = {'n_runs': n_runs} scens = cv.Scenarios(sim=base_sim, metapars=metapars, scenarios=scenarios) scens.run(verbose=verbose, debug=debug) to_plot = ['cum_infections', 'n_infectious', 'new_tests', 'new_diagnoses'] fig_args = dict(figsize=(20, 24)) if do_plot: scens.plot(do_save=do_save, do_show=do_show, fig_path=fig_path, interval=7, fig_args=fig_args, to_plot=to_plot) return scens
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 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
i00 = cv.test_prob(start_day=5, symp_prob=0.3) i01 = cv.dynamic_pars({ 'beta': { 'days': [40, 50], 'vals': [0.005, 0.015] }, 'diag_factor': { 'days': 30, 'vals': 0.0 } }) # 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))
def test_interventions(do_plot=False, do_show=True, do_save=False, fig_path=None): sc.heading('Test of testing interventions') sc.heading('Setting up...') sc.tic() n_runs = 3 verbose = 1 base_pars = { 'pop_size': 1000, 'use_layers': True, } base_sim = cv.Sim(base_pars) # create sim object n_people = base_sim['pop_size'] npts = base_sim.npts # Define overall testing assumptions # As the most optimistic case, we assume countries could get to South Korea's testing levels. S Korea has tested # an average of 10000 people/day over March, or 270,000 in total. This is ~200 people per million every day (0.02%). max_optimistic_testing = 0.0002 optimistic_daily_tests = [ max_optimistic_testing * n_people ] * npts # Very best-case scenario for asymptomatic testing # Define the scenarios scenarios = { 'baseline': { 'name': 'Status quo, no testing', 'pars': { 'interventions': None, } }, 'test_skorea': { 'name': 'Assuming South Korea testing levels of 0.02% daily (untargeted); isolate positives', 'pars': { 'interventions': cv.test_num(daily_tests=optimistic_daily_tests) } }, 'tracing': { 'name': 'Assuming South Korea testing levels of 0.02% daily (with contact tracing); isolate positives', 'pars': { 'interventions': [ cv.test_num(daily_tests=optimistic_daily_tests), cv.dynamic_pars({ 'quar_eff': { 'days': 20, 'vals': [{ 'h': 0.1, 's': 0.1, 'w': 0.1, 'c': 0.1 }] } }) ] # This means that people who've been in contact with known positives isolate with 90% effectiveness } }, 'floating': { 'name': 'Test with constant probability based on symptoms', 'pars': { 'interventions': cv.test_prob(symp_prob=max_optimistic_testing, asymp_prob=0.0) } }, # 'historical': { # 'name': 'Test a known number of positive cases', # 'pars': { # 'interventions': cv.test_historical(n_tests=[100]*npts, n_positive = [1]*npts) # } # }, 'sequence': { 'name': 'Historical switching to probability', 'pars': { 'interventions': cv.sequence(days=[10, 51], interventions=[ cv.test_num(daily_tests=[1000] * npts), cv.test_prob(symp_prob=0.2, asymp_prob=0.002), ]) } }, } metapars = {'n_runs': n_runs} scens = cv.Scenarios(sim=base_sim, metapars=metapars, scenarios=scenarios) scens.run(verbose=verbose, debug=debug) if do_plot: scens.plot(do_save=do_save, do_show=do_show, fig_path=fig_path) return scens
def modify_sim(sim, scenpars, label=None, runinfo=None): ''' Modify the simulation for the scenarios ''' print( f' Note: modifying simulation {label} at day={sim.t}, date={sim.date(sim.t)}, scenpars:\n{scenpars}' ) sim.sceninfo.scen_start = '2020-06-01' sim.sceninfo.scale_down = '2020-07-01' last_calib_day = sim.day(sim.sceninfo.calib_end) first_scen_day = sim.day(sim.sceninfo.scen_start) scale_down_day = sim.day(sim.sceninfo.scale_down) n_days = 5 scale_range = np.arange(n_days) ramp_up = np.linspace(0, 1, n_days) ramp_down = 1 - ramp_up for ilabel in ['clip_w', 'clip_c']: interv = sim.get_interventions(ilabel) valid_days = sc.findinds(interv.days <= last_calib_day) # Do reopening: modify clip_edges v0 = interv.changes[valid_days[-1]] v1 = scenpars['reopen'][0] v2 = scenpars['reopen'][1] scale_up = ramp_down * v0 + ramp_up * v1 scale_down = ramp_down * v1 + ramp_up * v2 scale_days = np.append(scale_range + first_scen_day, scale_range + scale_down_day) scale_vals = np.append(scale_up, scale_down) interv.days = np.append(interv.days[valid_days], scale_days) interv.changes = np.append(interv.changes[valid_days], scale_vals) # Change iso_factor and quar_factor sim.pars['iso_factor'] = sc.dcp(scenpars['i_factor']) sim.pars['quar_factor'] = sc.dcp(scenpars['q_factor']) # Implement testing & tracing interventions ctpars = {k: scenpars[k] for k in ['trace_probs', 'trace_time']} tn = sim.get_interventions('tn') if scenpars['which'] == 'actual': tn.test_delay = scenpars.test_delay sim['interventions'] += [ cv.contact_tracing(start_day=first_scen_day, label='contact_tracing', **ctpars) ] elif scenpars['which'] == 'low': offset = 7 # So it's constant tn.daily_tests[first_scen_day - tn.start_day - offset:] = scenpars['n_tests'] sim['interventions'] += [ cv.contact_tracing(start_day=first_scen_day, label='contact_tracing', **ctpars) ] elif scenpars['which'] == 'high': cv.set_seed( sim['rand_seed']) # Just in case since we use a random number tn.end_day = last_calib_day # End the test_num intervention n_weeks = 4 # Ramp up the test_prob and contact_tracing interventions days = first_scen_day + np.arange(n_weeks) * 7 tpramp = np.maximum( 0, np.linspace(0.2, 0.7, n_weeks + 1)[1:] + np.random.randn(n_weeks) * 0.1 ) # Don't start from 0 and don't make it a perfectly smooth ramp ctramp = np.linspace(0.0, 0.7, n_weeks + 1)[1:] # Don't start from 0 tppars = { k: scenpars[k] for k in [ 'symp_prob', 'asymp_prob', 'symp_quar_prob', 'asymp_quar_prob', 'test_delay' ] } tplist = [] ctlist = [] for w in range(n_weeks): tp = cv.test_prob(quar_policy=[0], **tppars, label=f'tp_{w}') ct = cv.contact_tracing(label=f'ct_{w}', **ctpars) tp.symp_prob *= tpramp[w] tp.asymp_prob *= tpramp[w] ct.trace_probs = sc.dcp(ct.trace_probs) for key in ct.trace_probs.keys(): ct.trace_probs[key] *= ctramp[w] tplist.append(tp) ctlist.append(ct) print(f'I AM {w} {ct.trace_probs}') tpseq = cv.sequence(days=days, interventions=tplist) ctseq = cv.sequence(days=days, interventions=ctlist) tpseq.initialize(sim) ctseq.initialize(sim) sim['interventions'] += [tpseq, ctseq] # Final tidying sim.label = label sim.runinfo = runinfo sim.sceninfo.scenpars = scenpars return sim