def add(self, *, simulation_info, country, area, measure_list, full_scale=True, test_update=None, seed_summary_path=None, set_calibrated_params_to=None, set_initial_seeds_to=None, expected_daily_base_expo_per100k=0, beacon_config=None, thresholds_roc=None, estimate_mobility_reduction=False, store_mob=False): # Set time window based on experiment start and end date sim_days = (pd.to_datetime(self.end_date) - pd.to_datetime(self.start_date)).days max_time = TO_HOURS * sim_days # in hours # extract lockdown period lockdown_start_date = pd.to_datetime( calibration_lockdown_dates[country]['start']) lockdown_end_date = pd.to_datetime( calibration_lockdown_dates[country]['end']) days_until_lockdown_start = (lockdown_start_date - pd.to_datetime(self.start_date)).days days_until_lockdown_end = (lockdown_end_date - pd.to_datetime(self.start_date)).days # Load mob settings mob_settings_file = calibration_mob_paths[country][area][ 1 if full_scale else 0] with open(mob_settings_file, 'rb') as fp: mob_settings = pickle.load(fp) num_age_groups = len(mob_settings['mob_rate_per_age_per_type']) # Obtain COVID19 case date for country and area to estimate testing capacity and heuristic seeds if necessary unscaled_area_cases = collect_data_from_df( country=country, area=area, datatype='new', start_date_string=self.start_date, end_date_string=self.end_date) assert (len(unscaled_area_cases.shape) == 2) # Scale down cases based on number of people in town and region sim_cases = downsample_cases(unscaled_area_cases, mob_settings) # Instantiate correct state transition distributions (estimated from literature) distributions = CovidDistributions(country=country) # Expected base rate infections if expected_daily_base_expo_per100k > 0.0: # Scale expectation to simulation size num_people = len(mob_settings['home_loc']) lambda_base_expo_population = expected_daily_base_expo_per100k * ( num_people / 100000) # Convert to individual base rate by dividing by population size; priority queue handles superposition lambda_base_expo_indiv = lambda_base_expo_population / num_people # Poisson process with rate lambda: interarrival times are Exponential r.v. with mean = 1 / lambda # Hence set rate of Expo r.v.s to 1 / (1 / lambda) = lambda distributions.lambda_0 = lambda_base_expo_indiv # Get initial seeds for simulation # (a) Define heuristically based on true cases and literature distribution estimates if seed_summary_path is None: # Generate initial seeds based on unscaled case numbers in town initial_seeds = gen_initial_seeds(sim_cases, day=0) if sum(initial_seeds.values()) == 0: print( 'No states seeded at start time; cannot start simulation.\n' 'Consider setting a later start date for calibration using the "--start" flag.' ) sys.exit(0) # (b) Define based state of previous batch of simulations, # using the random rollout that best matched the true cases in terms of squared error else: seed_summary_ = load_summary(seed_summary_path) seed_day_ = seed_summary_.max_time # take seeds at the end of simulation initial_seeds = extract_seeds_from_summary(seed_summary_, seed_day_, sim_cases) if set_initial_seeds_to is not None: initial_seeds = set_initial_seeds_to if set_calibrated_params_to is not None: calibrated_params = set_calibrated_params_to else: # Load calibrated model parameters for this area calibrated_params = get_calibrated_params( country=country, area=area, multi_beta_calibration=self.multi_beta_calibration, estimate_mobility_reduction=estimate_mobility_reduction) if self.multi_beta_calibration: betas = calibrated_params['betas'] else: betas = { 'education': calibrated_params['beta_site'], 'social': calibrated_params['beta_site'], 'bus_stop': calibrated_params['beta_site'], 'office': calibrated_params['beta_site'], 'supermarket': calibrated_params['beta_site'], } model_params = { 'betas': betas, 'beta_household': calibrated_params['beta_household'], } # Add standard measure of positives staying isolated measure_list += [ # standard behavior of positively tested: full isolation SocialDistancingForPositiveMeasure(t_window=Interval( 0.0, max_time), p_stay_home=1.0), SocialDistancingForPositiveMeasureHousehold(t_window=Interval( 0.0, max_time), p_isolate=1.0), ] measure_list = MeasureList(measure_list) testing_params = copy.deepcopy(calibration_testing_params) testing_params['testing_t_window'] = [0.0, max_time] if test_update: testing_params = test_update(testing_params) # store simulation sim_kwargs = dict( # Generic information experiment_info=self.experiment_info, simulation_info=simulation_info, start_date=self.start_date, end_date=self.end_date, sim_days=sim_days, country=country, area=area, random_repeats=self.random_repeats, # Mobility and measures mob_settings_file=mob_settings_file, full_scale=full_scale, measure_list=measure_list, testing_params=testing_params, store_mob=store_mob, # Model model_params=model_params, distributions=distributions, initial_seeds=initial_seeds, ) # Beacon # fields are added here (even though defaulting to `None`) to double check backwards compatibility # with stored `Result` objects prior to implementing beacon functionality if beacon_config is not None: sim_kwargs['beacon_config'] = beacon_config if thresholds_roc is not None: sim_kwargs['thresholds_roc'] = thresholds_roc sim = Simulation(**sim_kwargs) if self.continued_run and self.check_summary_existence(sim): if self.verbose: print(f'[Skipped Sim] {self.get_sim_path(sim)}') else: self.sims.append(sim) if self.verbose: print(f'[Added Sim] {self.get_sim_path(self.sims[-1])}')
def add(self, *, simulation_info, country, area, measure_list, lockdown_measures_active=True, full_scale=True, test_update=None, seed_summary_path=None, set_calibrated_params_to=None, set_initial_seeds_to=None, expected_daily_base_expo_per100k=0, store_mob=False): # Set time window based on experiment start and end date sim_days = (pd.to_datetime(self.end_date) - pd.to_datetime(self.start_date)).days max_time = TO_HOURS * sim_days # in hours # extract lockdown period lockdown_start_date = pd.to_datetime( calibration_lockdown_dates[country]['start']) lockdown_end_date = pd.to_datetime( calibration_lockdown_dates[country]['end']) days_until_lockdown_start = (lockdown_start_date - pd.to_datetime(self.start_date)).days days_until_lockdown_end = (lockdown_end_date - pd.to_datetime(self.start_date)).days # Load mob settings mob_settings_file = calibration_mob_paths[country][area][1 if full_scale else 0] with open(mob_settings_file, 'rb') as fp: mob_settings = pickle.load(fp) # Obtain COVID19 case date for country and area to estimate testing capacity and heuristic seeds if necessary unscaled_area_cases = collect_data_from_df(country=country, area=area, datatype='new', start_date_string=self.start_date, end_date_string=self.end_date) assert(len(unscaled_area_cases.shape) == 2) # Scale down cases based on number of people in town and region sim_cases = downsample_cases(unscaled_area_cases, mob_settings) # Instantiate correct state transition distributions (estimated from literature) distributions = CovidDistributions(country=country) # Expected base rate infections if expected_daily_base_expo_per100k > 0.0: # Scale expectation to simulation size num_people = len(mob_settings['home_loc']) lambda_base_expo_population = expected_daily_base_expo_per100k * (num_people / 100000) # Convert to individual base rate by dividing by population size; priority queue handles superposition lambda_base_expo_indiv = lambda_base_expo_population / num_people distributions.lambda_0 = lambda_base_expo_indiv # Get initial seeds for simulation # (a) Define heuristically based on true cases and literature distribution estimates if seed_summary_path is None: # Generate initial seeds based on unscaled case numbers in town initial_seeds = gen_initial_seeds( sim_cases, day=0) if sum(initial_seeds.values()) == 0: print('No states seeded at start time; cannot start simulation.\n' 'Consider setting a later start date for calibration using the "--start" flag.') sys.exit(0) # (b) Define based state of previous batch of simulations, # using the random rollout that best matched the true cases in terms of squared error else: seed_summary_ = load_summary(seed_summary_path) seed_day_ = seed_summary_.max_time # take seeds at the end of simulation initial_seeds = extract_seeds_from_summary( seed_summary_, seed_day_, sim_cases) if set_initial_seeds_to is not None: initial_seeds = set_initial_seeds_to # Load calibrated model parameters for this area calibrated_params = get_calibrated_params( country=country, area=area, multi_beta_calibration=self.multi_beta_calibration) if set_calibrated_params_to is not None: calibrated_params = set_calibrated_params_to p_stay_home_calibrated = calibrated_params['p_stay_home'] if self.multi_beta_calibration: betas = calibrated_params['betas'] else: betas = { 'education': calibrated_params['beta_site'], 'social': calibrated_params['beta_site'], 'bus_stop': calibrated_params['beta_site'], 'office': calibrated_params['beta_site'], 'supermarket': calibrated_params['beta_site'], } model_params = { 'betas': betas, 'beta_household': calibrated_params['beta_household'], } # Add standard measure of positives staying isolated measure_list += [ # standard behavior of positively tested: full isolation SocialDistancingForPositiveMeasure( t_window=Interval(0.0, max_time), p_stay_home=1.0), SocialDistancingForPositiveMeasureHousehold( t_window=Interval(0.0, max_time), p_isolate=1.0), ] # Add standard measures if simulation is happening during lockdown # Set lockdown_measures_active to False to explore counterfactual scenarios if lockdown_measures_active: measure_list += [ # social distancing factor during lockdown: calibrated SocialDistancingForAllMeasure( t_window=Interval(TO_HOURS * days_until_lockdown_start, TO_HOURS * days_until_lockdown_end), p_stay_home=p_stay_home_calibrated), # site specific measures: fixed in advance, outside of calibration BetaMultiplierMeasureByType( t_window=Interval(TO_HOURS * days_until_lockdown_start, TO_HOURS * days_until_lockdown_end), beta_multiplier=calibration_lockdown_beta_multipliers) ] measure_list = MeasureList(measure_list) # Set testing conditions scaled_test_capacity = get_test_capacity( country, area, mob_settings, end_date_string=self.end_date) testing_params = copy.deepcopy(calibration_testing_params) testing_params['tests_per_batch'] = scaled_test_capacity testing_params['testing_t_window'] = [0.0, max_time] if test_update: testing_params = test_update(testing_params) # store simulation self.sims.append(Simulation( # Generic information experiment_info=self.experiment_info, simulation_info=simulation_info, start_date=self.start_date, end_date=self.end_date, sim_days=sim_days, country=country, area=area, random_repeats=self.random_repeats, # Mobility and measures mob_settings_file=mob_settings_file, full_scale=full_scale, measure_list=measure_list, testing_params=testing_params, store_mob=store_mob, # Model model_params=model_params, distributions=distributions, initial_seeds=initial_seeds, )) if self.verbose: print(f'[Added Sim] {self.get_sim_path(self.sims[-1])}')