Example #1
0
    def _fit_seir(R0, t0, eps):
        model = SEIRModel(R0=R0,
                          suppression_policy=suppression_policies.
                          generate_empirical_distancing_policy(
                              t_list, fips, future_suppression=eps),
                          **SEIR_params)
        model.run()

        predicted_cases = model.gamma * np.interp(
            times, t_list + t0, model.results['total_new_infections'])
        predicted_deaths = np.interp(times, t_list + t0,
                                     model.results['direct_deaths_per_day'])

        # Assume the error on the case count could be off by a massive factor 50.
        # Basically we don't want to use it if there appreciable mortality data available.
        # Longer term there is a better procedure.
        cases_variance = 1e10 * observed_new_cases.copy(
        )**2  # Make the stdev N times larger x the number of cases
        deaths_variance = observed_new_deaths.copy()  # Poisson dist error

        # Zero inflated poisson Avoid floating point errors..
        cases_variance[cases_variance == 0] = 1e10
        deaths_variance[deaths_variance == 0] = 1e10

        # Compute Chi2
        chi2_cases = np.sum(
            (observed_new_cases - predicted_cases)**2 / cases_variance)
        if observed_new_deaths.sum() > 5:
            chi2_deaths = np.sum(
                (observed_new_deaths - predicted_deaths)**2 / deaths_variance)
        else:
            chi2_deaths = 0
        return chi2_deaths + chi2_cases
Example #2
0
    def _run_single_simulation(parameter_set):
        """
        Run a single simulation instance.

        Parameters
        ----------
        parameter_set: dict
            Params passed to the SEIR model

        Returns
        -------
        model: SEIRModel
            Executed model.
        """
        model = SEIRModel(**parameter_set)
        model.run()
        return model
Example #3
0
    def run_model(self, R0, eps, t_break, log10_I_initial):
        """
        Generate the model and run.

        Parameters
        ----------
        R0: float
            Basic reproduction number
        eps: float
            Fraction of reduction in contact rates as result of  to suppression
            policy projected into future.
        t_break: float
            Timing for the switch in suppression policy.
        log10_I_initial:
            log10 initial infections.

        Returns
        -------
        model: SEIRModel
            The SEIR model that has been run.
        """
        # Leaving this block since we likely want to switch back shortly.
        # if by == 'fips':
        #     suppression_policy = \
        #         suppression_policies.generate_empirical_distancing_policy(
        #             fips=fips, future_suppression=eps, **suppression_policy_params)
        # elif by == 'state':
        #     # TODO: This takes > 200ms which is 10x the model run time. Can be optimized...
        #     suppression_policy = \
        #         suppression_policies.generate_empirical_distancing_policy_by_state(
        #             state=state, future_suppression=eps, **suppression_policy_params)
        suppression_policy = suppression_policies.generate_two_step_policy(
            self.t_list, eps, t_break)

        # Load up some number of initial exposed so the initial flow into infected is stable.
        self.SEIR_kwargs[
            'E_initial'] = self.steady_state_exposed_to_infected_ratio * 10**log10_I_initial

        model = SEIRModel(R0=R0,
                          suppression_policy=suppression_policy,
                          I_initial=10**log10_I_initial,
                          **self.SEIR_kwargs)
        model.run()
        return model
def create_standard_model(r0, sup, days=100, ratios=None):
    """
    Creates a standard model for testing purposes. Supports 
    - customization of r0 and suppresssion policy
    - optionally supply ratios for (non infection) compartments that matter
    """
    hosp_rate_general = 0.025
    initial_infected = 1000
    N = 10000000

    if ratios is None:
        model = SEIRModel(
            N=N,
            t_list=make_tlist(days),
            suppression_policy=sup,
            R0=r0,
            # gamma=0.7,
            # hospitalization_rate_general=hosp_rate_general,
            # hospitalization_rate_icu=0.3 * hosp_rate_general,
            A_initial=0.7 * initial_infected,
            I_initial=initial_infected,
            beds_general=N / 1000,
            beds_ICU=N / 1000,
            ventilators=N / 1000,
        )
    else:
        (E, I, A, HGen, HICU, HVent, D) = ratios
        model = SEIRModel(
            N=N,
            t_list=make_tlist(days),
            suppression_policy=sup,
            R0=r0,
            E_initial=E * initial_infected,
            A_initial=A * initial_infected,
            I_initial=initial_infected,
            HGen_initial=HGen * initial_infected,
            HICU_initial=HICU * initial_infected,
            HICUVent_initial=HVent * initial_infected,
            beds_general=N / 1000,
            beds_ICU=N / 1000,
            ventilators=N / 1000,
        )
    return model
Example #5
0
def plot_inferred_result(fit_results):
    """
    Plot the results of an MLE inference
    """
    fips = fit_results['fips']
    county_metadata = load_data.load_county_metadata().set_index(
        'fips').loc[fips].to_dict()
    times, observed_new_cases, observed_new_deaths = load_data.load_new_case_data_by_fips(
        fips, t0=ref_date)
    if observed_new_cases.sum() < 5:
        logging.warning(
            f"{county_metadata['county']} has fewer than 5 cases. Aborting plot."
        )
        return
    else:
        logging.info(f"Plotting MLE Fits for {county_metadata['county']}")

    R0, t0, eps = fit_results['R0'], fit_results['t0'], fit_results['eps']

    model = SEIRModel(R0=R0,
                      suppression_policy=suppression_policies.
                      generate_empirical_distancing_policy(
                          t_list, fips, future_suppression=eps),
                      **get_average_SEIR_parameters(fit_results['fips']))
    model.run()

    data_dates = [ref_date + timedelta(days=t) for t in times]
    model_dates = [
        ref_date + timedelta(days=t + fit_results['t0']) for t in t_list
    ]
    plt.figure(figsize=(10, 8))
    plt.errorbar(data_dates,
                 observed_new_cases,
                 marker='o',
                 linestyle='',
                 label='Observed Cases Per Day')
    plt.errorbar(data_dates,
                 observed_new_deaths,
                 yerr=np.sqrt(observed_new_deaths),
                 marker='o',
                 linestyle='',
                 label='Observed Deaths')
    plt.plot(model_dates,
             model.results['total_new_infections'],
             label='Estimated Total New Infections Per Day')
    plt.plot(model_dates,
             model.gamma * model.results['total_new_infections'],
             label='Symptomatic Model Cases Per Day')
    plt.plot(model_dates,
             model.results['direct_deaths_per_day'],
             label='Model Deaths Per Day')
    plt.yscale('log')
    plt.ylim(.9e0)
    plt.xlim(data_dates[0], data_dates[-1] + timedelta(days=90))

    plt.xticks(rotation=30)
    plt.legend(loc=1)
    plt.grid(which='both', alpha=.3)
    plt.title(county_metadata['county'])
    for i, (k, v) in enumerate(fit_results.items()):
        if k not in ('fips', 't0_date', 'county', 'state'):
            plt.text(.025,
                     .97 - 0.04 * i,
                     f'{k}={v:1.3f}',
                     transform=plt.gca().transAxes,
                     fontsize=12)
        else:
            plt.text(.025,
                     .97 - 0.04 * i,
                     f'{k}={v}',
                     transform=plt.gca().transAxes,
                     fontsize=12)

    output_file = os.path.join(
        OUTPUT_DIR, fit_results['state'].title(), 'reports',
        f'{fit_results["state"]}__{fit_results["county"]}__{fit_results["fips"]}__mle_fit_results.pdf'
    )
    plt.savefig(output_file)