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
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
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
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)