Esempio n. 1
0
 def __init__(self, a, b, K):
     from operator import mul
     self._a = a
     self._b = b
     self._K = K
     theta = 1. / b
     self.gamma_dist = gamma_dist(a, 0, theta)
Esempio n. 2
0
def produce_gomes_exfig1(coeffs: list, add_hist=False, n_bins=3, x_values=50, plot_upper_limit=3.0):
    """
    Produce figure equivalent to Extended Data Fig 1 of Aguas et al pre-print as a check
    """

    # Prelims
    x_values = np.linspace(0.1, plot_upper_limit, x_values)  # Can't go to zero under some coeffs
    gamma_plot = plt.figure()
    axis = gamma_plot.add_subplot(111)

    # For each requested coefficient of variation
    for coeff in coeffs:
        gamma_distri = gamma_dist(coeff ** -2.0, scale=coeff ** 2.0)

        # Line graph of the raw function
        y_values = [gamma_distri.pdf(i) for i in x_values]
        axis.plot(x_values, y_values, color="k")

        # Numeric integration over parts of the function domain
        if add_hist:
            lower_terminals, _, _, normalised_heights, bin_width = get_gamma_data(
                plot_upper_limit, n_bins, coeff
            )
            axis.bar(lower_terminals, normalised_heights, width=bin_width, align="edge")

    # Return the figure
    return gamma_plot
Esempio n. 3
0
def get_gamma_data(tail_start_point, n_bins, coeff):
    """
    Compute a discretised version of a gamma distribution with mean 1 and a given coefficient of variation (sd/mean).
    The discretisation involves numerical solving to ensure the coefficient of variation is preserved. However, the mean
    of the discrete ditribution may be different to 1.
    :param tail_start_point: the last lower terminal
    :param n_bins: number of bins (including tail)
    :param coeff: requested coefficient of variation
    :return:
    """
    # First address a few singular scenarios
    if n_bins == 1 and coeff > 0.0:
        raise ValueError("Cannot compute a positive coefficient of variation using a single bin")
    elif n_bins > 1 and coeff == 0.0:
        raise ValueError("Cannot compute a null coefficient of variation using multiple bins")
    elif n_bins == 1:
        return [0.0], [float("inf")], 1.0, 1.0, float("inf")

    n_finite_bins = n_bins - 1
    # Prelims
    lower_terminal, lower_terminals, upper_terminals, heights = 0.0, [], [], []
    bin_width = tail_start_point / n_finite_bins

    for i_bin in range(n_finite_bins):

        # Record the upper and lower terminals
        lower_terminals.append(lower_terminal)
        upper_terminals.append(lower_terminal + bin_width)

        gamma_distri = gamma_dist(coeff ** -2.0, scale=coeff ** 2.0)
        heights.append(
            gamma_distri.cdf(upper_terminals[-1]) - gamma_distri.cdf(lower_terminals[-1])
        )

        # Move to the next value
        lower_terminal = upper_terminals[-1]

    # the last height is the remaining area under the curve (tail)
    heights.append(1.0 - sum(heights))

    # Find mid-points as the representative values
    mid_points = [(lower + upper) / 2.0 for lower, upper in zip(lower_terminals, upper_terminals)]

    # add the last representative point such that modelled_CV = input_CV
    last_point, last_height = find_last_representative_point(mid_points, heights, coeff)
    mid_points.append(last_point)
    heights[-1] = last_height

    # rescale heights
    heights = [h / sum(heights) for h in heights]

    lower_terminals.append(upper_terminals[-1])
    upper_terminals.append(float("inf"))

    # Return everything just in case
    return lower_terminals, upper_terminals, mid_points, heights, bin_width
# Model Parameters to sample from Gamma Distributions
gamma_inv, gamma_inv_shape = 7, 0.1  # From report (mean, shape)
sigma_inv, sigma_inv_shape = 5.1, 0.1  # From report (mean, shape)
r0, r0_shape = 2.28, 0.1  # From report (mean, shape)

# For gamma pdf plots
x = np.linspace(1E-6, 10, 1000)
num_samples = 1000

#### Gamma distributed samples for gamma_inv ####
#### --> This might be wrong?!?!?
k = 1
loc = gamma_inv
theta = gamma_inv_shape
gamma_inv_dist = gamma_dist(k, loc, theta)
gamma_inv_samples = gamma_inv_dist.rvs(num_samples)

# Plot gamma samples and pdf
count, bins, ignored = plt.hist(gamma_inv_samples, 50, density=True)
plt.plot(x,
         gamma_inv_dist.pdf(x),
         'r',
         label=r'$k=%.1f,\ \theta=%.1f$' % (k, theta))

#### Gamma distributed samples for sigma_inv ####
k = 1
loc = sigma_inv
theta = sigma_inv_shape
sigma_inv_dist = gamma_dist(k, loc, theta)
sigma_inv_samples = sigma_inv_dist.rvs(num_samples)
def plotSIR_sampledParams(beta_samples, gamma_inv_samples, filename, *prob_params):
    fig, (ax1,ax2) = plt.subplots(1,2, constrained_layout=True)

    ###########################################################
    ################## Plot for Beta Samples ##################
    ###########################################################
    count, bins, ignored = ax1.hist(beta_samples, 30, density=True)

    if prob_params[0] == 'uniform':
        ax1.set_xlabel(r"$\beta \sim \mathcal{N}$", fontsize=15)        

    if prob_params[0] == 'gaussian':
        mu    = prob_params[1]
        sigma = prob_params[2] + 0.00001
        ax1.plot(bins, 1/(sigma * np.sqrt(2 * np.pi)) *
                       np.exp( - (bins - mu)**2 / (2 * sigma**2) ), linewidth=2, color='r')
        ax1.set_xlabel(r"$\beta \sim \mathcal{N}$", fontsize=15)    

    if prob_params[0] == 'gamma':
        g_dist    = gamma_dist(prob_params[2], prob_params[1], prob_params[3])
        # Plot gamma samples and pdf
        x = np.arange(0,1,0.001)
        ax1.plot(x, g_dist.pdf(x), 'r',label=r'$k = 1, \mu=%.1f,\ \theta=%.1f$' % (prob_params[1], prob_params[2]))


    for tick in ax1.xaxis.get_major_ticks():
        tick.label.set_fontsize(15) 
    for tick in ax1.yaxis.get_major_ticks():
            tick.label.set_fontsize(15) 
    plt.xlim(0, 1.0)            
    ax1.grid(True, alpha=0.3)
    ax1.set_title(r"Histogram of $\beta$ samples", fontsize=20)
    
    ###############################################################
    ################## Plot for Gamma^-1 Samples ##################
    ###############################################################
    count, bins, ignored = ax2.hist(gamma_inv_samples, 30, density=True)
    if prob_params[0] == 'gaussian':
        mu    = prob_params[3]
        sigma = prob_params[4] + 0.00001
        ax2.plot(bins, 1/(sigma * np.sqrt(2 * np.pi)) *
                       np.exp( - (bins - mu)**2 / (2 * sigma**2) ), linewidth=2, color='r')

        ax2.set_xlabel(r"$\gamma^{-1} \sim \mathcal{N}$", fontsize=15)
    
    if prob_params[0] == 'uniform':
        ax2.set_xlabel(r"$\gamma^{-1} \sim \mathcal{U}$", fontsize=15)          

    if prob_params[0] == 'gamma':
        g_dist    = gamma_dist(prob_params[5], prob_params[4], prob_params[6])
        # Plot gamma samples and pdf
        x = np.arange(1,15,0.1)
        ax2.plot(x, g_dist.pdf(x), 'r',label=r'$k = 1, \mu=%.1f,\ \theta=%.1f$' % (prob_params[3], prob_params[4]))


    for tick in ax2.xaxis.get_major_ticks():
        tick.label.set_fontsize(15) 
    for tick in ax2.yaxis.get_major_ticks():
            tick.label.set_fontsize(15)  
    plt.xlim(1, 17) 
    ax2.grid(True, alpha=0.3)    
    plt.title(r"Histogram of $\gamma^{-1}$ samples", fontsize=20)    

    fig.subplots_adjust(left=.12, bottom=.14, right=.93, top=0.93)
    fig.set_size_inches(20/2, 8/2, forward=True)    
    
    # Store plot
    plt.savefig(filename + ".png", bbox_inches='tight')
def rollout_SIR_sim_stoch(*prob_params, **kwargs):
    '''
        Run a single simulation of stochastic SIR dynamics
    '''
    verbose  = kwargs['verbose']
    N        = kwargs['N']
    days     = kwargs['days']

    # Sample from Uniform Distributions        
    if prob_params[0] == 'uniform':        
        if prob_params[1] == prob_params[2]:
            beta = prob_params[1]
        else:
            beta = np.random.uniform(prob_params[1],prob_params[2])
        if prob_params[3] == prob_params[4]:
            gamma_inv = prob_params[3]
        else:
            gamma_inv = np.random.uniform(prob_params[3],prob_params[4])

    # Sample from Gaussian Distributions        
    if prob_params[0] == 'gaussian':        
        beta_mean       = prob_params[1]
        beta_std        = prob_params[2]
        gamma_inv_mean  = prob_params[3]
        gamma_inv_std   = prob_params[4]
        
        # Sample from Gaussian Distributions
        beta = 0
        while beta < 0.02:
            beta            = np.random.normal(beta_mean, beta_std)
        gamma_inv = 0    
        while gamma_inv < 0.1:
            gamma_inv       = np.random.normal(gamma_inv_mean, gamma_inv_std)

    # Sample from Gaussian Distributions        
    if prob_params[0] == 'gamma':        
        beta_loc        = prob_params[1]
        beta_scale      = prob_params[2]
        beta_shape      = prob_params[3]
        gamma_inv_loc   = prob_params[4]
        gamma_inv_scale = prob_params[5]
        gamma_inv_shape = prob_params[6]

        # Sample from Gamma Distributions
        if beta_scale == 0:
            beta = beta_loc
        else:        
            beta_dist      = gamma_dist(beta_scale, beta_loc, beta_shape)
            beta           = beta_dist.rvs(1)[0]
        if gamma_inv_scale == 0:
            gamma_inv = gamma_inv_loc
        else:            
            gamma_inv_dist = gamma_dist(gamma_inv_scale, gamma_inv_loc, gamma_inv_shape)
            gamma_inv      = gamma_inv_dist.rvs(1)[0]

    # Derived values    
    gamma      = 1.0 / gamma_inv
    r0         = beta * gamma_inv

    if verbose:
        print('*****   SIMULATING SIR MODEL DYNAMICS *****')    
        print('*****         Hyper-parameters        *****')
        print('N=',N,'days=', days, 'r0=',r0, 'gamma_inv (days) = ',gamma_inv)
        print('*****         Model-parameters        *****')
        print('beta=',beta, 'gamma=',gamma)

    # Create Model
    model_kwargs = {}
    model_kwargs['r0']         = r0
    model_kwargs['inf_period'] = gamma_inv
    model_kwargs['I0']         = kwargs['I0']
    model_kwargs['R0']         = kwargs['R0']

    model   = SIR(N,**model_kwargs)
    S,I,R,t = model.project(days,'ode_int')

    return S, I, R, t, beta, gamma_inv