示例#1
0
    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])}')
示例#2
0
    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])}')