def MLE(thetas, BaseModel, data, states, parNames, checkpoints=None, samples=None): """ A function to return the maximum likelihood estimator given a model object and a dataset Parameters ----------- BaseModel: model object correctly initialised model to be fitted to the dataset thetas: np.array vector containing estimated parameter values thetas: list names of parameters to be fitted data: list list containing dataseries states: list list containg the names of the model states to be fitted to data Returns ----------- MLE : float total sum of squared errors Notes ----------- An explanation of the difference between SSE and MLE can be found here: https://emcee.readthedocs.io/en/stable/tutorials/line/ Brief summary: if measurement noise is unbiased, Gaussian and independent than the MLE and SSE are identical. Example use ----------- MLE = MLE(model,thetas,data,parNames,positions) """ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # assign estimates to correct variable # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ initN, Nc_home, Nc_work, Nc_schools, Nc_transport, Nc_leisure, Nc_others, Nc_total = polymod.get_interaction_matrices( ) # by defenition, if N is the number of data timeseries then the first N parameters are the estimated variances of these timeseries! i = 0 sigma = [] for param in parNames: if param == 'extraTime': # don't know if there's a way to make this function more general due to the 'extraTime', can this be abstracted in any way? setattr(BaseModel, param, int(round(thetas[i]))) elif param == 'prevention': checkpoints.update({ 'Nc': [ thetas[i] * (1.0 * Nc_home + (1 - 0.60) * Nc_work + (1 - 0.70) * Nc_transport + (1 - 0.30) * Nc_others + (1 - 0.80) * Nc_leisure) ] }) # The following section is needed to perform a recalibration of beta #elif param == 'beta': # estimate_beta = thetas[i] # checkpoints.update( # {'beta': # [ # np.random.choice(samples[param]), # thetas[i], # thetas[i], # thetas[i], # thetas[i], # thetas[i], # thetas[i] # ] # }) else: if i < len(data): sigma.append(thetas[i]) else: BaseModel.parameters.update({param: thetas[i]}) i = i + 1 # ~~~~~~~~~~~~~~ # Run simulation # ~~~~~~~~~~~~~~ # number of dataseries n = len(data) # Compute simulation time data_length = [] for i in range(n): data_length.append(data[i].size) T = max(data_length) + BaseModel.extraTime - 1 # Use previous samples if samples: for param in samples: if param == 'prevention': prevention = np.random.choice(samples[param]) checkpoints.update({ 'Nc': [ prevention * (1.0 * Nc_home + (1 - 0.60) * Nc_work + (1 - 0.70) * Nc_transport + (1 - 0.30) * Nc_others + (1 - 0.80) * Nc_leisure), prevention * (1.0 * Nc_home + (1 - 0.50) * Nc_work + (1 - 0.60) * Nc_transport + (1 - 0.30) * Nc_others + (1 - 0.70) * Nc_leisure), prevention * (1.0 * Nc_home + (1 - 0.40) * Nc_work + (1 - 0.55) * Nc_transport + (1 - 0.25) * Nc_others + (1 - 0.65) * Nc_leisure), prevention * (1.0 * Nc_home + (1 - 0.30) * Nc_work + (1 - 0.50) * Nc_transport + (1 - 0.20) * Nc_others + (1 - 0.60) * Nc_leisure), prevention * (1.0 * Nc_home + (1 - 0.30) * Nc_work + (1 - 0.45) * Nc_transport + (1 - 0.85) * Nc_schools + (1 - 0.15) * Nc_others + (1 - 0.50) * Nc_leisure), prevention * (1.0 * Nc_home + (1 - 0.25) * Nc_work + (1 - 0.35) * Nc_transport + (1 - 0.35) * Nc_schools + (1 - 0.10) * Nc_others + (1 - 0.30) * Nc_leisure), prevention * (1.0 * Nc_home + (1 - 0.20) * Nc_work + (1 - 0.15) * Nc_transport + (1 - 0.00) * Nc_others + (1 - 0.00) * Nc_leisure) ] }) #checkpoints.update({'Nc': [prevention*(1.3*Nc_home + (1-0.60)*Nc_work + (1-0.70)*Nc_transport + (1-0.30)*Nc_others + (1-0.80)*Nc_leisure)]}) else: BaseModel.parameters[param] = np.random.choice(samples[param], 1, replace=False) # Perform simulation out = BaseModel.sim(T, checkpoints=checkpoints) # ------------- # calculate MLE # ------------- ymodel = [] MLE = 0 for i in range(n): som = 0 # sum required states for j in range(len(states[i])): som = som + out[states[i][j]].sum(dim="stratification").values ymodel.append(som[BaseModel.extraTime:]) # calculate simga2 and log-likelihood function MLE = MLE - 0.5 * np.sum( (data[i] - ymodel[i])**2 / sigma[i]**2 + np.log(sigma[i]**2)) return abs(MLE) # must be positive for pso
def get_COVID19_SEIRD_parameters(stratified=True): """ Extracts and returns the parameters for the age-stratified deterministic model This function returns all parameters needed to run the age-stratified model. This function was created to group all parameters in one centralised location. Parameters ---------- stratified : boolean If True: returns parameters stratified by age, for agestructured model If False: returns parameters for non-agestructured model Returns ----------- A dictionary with following keys and values: Nc: np.array 9x9 social interaction matrix; by default, the total interaction matrix Nc_total from the Polymod study is assigned to the parameters dictionary h : np.array fraction of the cases that require hospitalisation (-) icu: np.array fraction of the hospitalized in ICU c: np.array fraction of the hospitalized in Cohort, calculated as (c = 1 - icu) (-) m0: np.array fraction of the patients in ICU who die (-) a: np.array fraction of asymptomatic cases (-) m: np.array fraction of (mild) symptomatic cases (-) da: float64 length of infectiousness in case of asymptomatic infection (days) dm: float64 length of infectiousness in case of mild symptomatic infection (days) dc: float64 length of stay in Cohort when symptoms don't worsen (days) dICU: float64 length of stay in ICU (days) dICUrec: float64 length of recovery stay in Cohort after stay in ICU (days) dhospital: float64 time between first symptom and hospitalization (days) beta: float64 chance of transmission when coming into contact with an infectious person (-) sigma: float64 length of latent period (days) omega: float64 length of pre-symptomatic infectious period (days) dq: float64 length of quarantine when patient does not develop symptoms (days) Example use ----------- parameters = get_COVID19_SEIRD_parameters() """ abs_dir = os.path.dirname(__file__) par_path = os.path.join(abs_dir, "../../../data/raw/model_parameters/") # Initialize parameters dictionary pars_dict = {} if stratified == True: # Assign Nc_total from the Polymod study to the parameters dictionary Nc_total = polymod.get_interaction_matrices()[-1] pars_dict['Nc'] = Nc_total # Verity_etal df = pd.read_csv(os.path.join(par_path, "verity_etal.csv"), sep=',', header='infer') pars_dict['h'] = np.array( df.loc[:, 'symptomatic_hospitalized'].astype(float).tolist()) / 100 pars_dict['icu'] = np.array( df.loc[:, 'hospitalized_ICU'].astype(float).tolist()) / 100 # Molenberghs_etal df = pd.read_csv(os.path.join(par_path, "molenberghs_etal.csv"), sep=',', header='infer') pars_dict['m0'] = np.array(df.loc[:, 'IFR_general_population'].astype( float).tolist()) / 100 / pars_dict['h'] # Wu_etal df_asymp = pd.read_csv(os.path.join(par_path, "wu_etal.csv"), sep=',', header='infer') pars_dict['a'] = np.array( df_asymp.loc[:, 'fraction asymptomatic'].astype(float).tolist()) else: pars_dict['Nc'] = np.array([11.2]) non_strat = pd.read_csv(os.path.join(par_path, "non_stratified.csv"), sep=',', header='infer') pars_dict.update({ key: np.array(value) for key, value in non_strat.to_dict(orient='list').items() }) # deduced parameters pars_dict['c'] = 1 - pars_dict['icu'] pars_dict['m'] = 1 - pars_dict['a'] # Other parameters df_other_pars = pd.read_csv(os.path.join(par_path, "others.csv"), sep=',', header='infer') pars_dict.update(df_other_pars.T.to_dict()[0]) # Fitted parameters pars_dict['beta'] = 0.03492 return pars_dict
import math import xarray as xr import emcee import json import corner from covid19model.optimization import objective_fcns from covid19model.optimization import MCMC from covid19model.models import models from covid19model.data import google from covid19model.data import sciensano from covid19model.data import polymod from covid19model.data import model_parameters from covid19model.visualization.optimization import traceplot initN, Nc_home, Nc_work, Nc_schools, Nc_transport, Nc_leisure, Nc_others, Nc_total = polymod.get_interaction_matrices( ) def full_calibration(model, timeseries, spatial_unit, start_date, end_beta, end_ramp, fig_path, samples_path, maxiter=50, popsize=50, steps_mcmc=10000): """ model : object