Beispiel #1
0
def test_class_Chain():
    """tests to ensure the behaviour class Chain"""
    test_model = Model('test_model')
    from_pop = Population('from_pop', 0.)
    to_pop = Population('to_pop', 0.)
    pop_a = Population('pop_a', 0.)
    pop_b = Population('pop_b', 0.)
    start = 100000
    from_pop.future = [start]

    mean = 10.
    sigma = 2.
    delay_pars = {'mean': Parameter('mean', mean, parameter_min=0.1, parameter_max=100.),
                  'sigma': Parameter('sigma', sigma, parameter_min=0.1, parameter_max=1000.)}
    delay = Delay('delay', 'norm', delay_pars, test_model)
    frac = 0.8
    fraction = Parameter('frac', frac)
    chain = []
    chain.append(Propagator('prop_0', from_pop, pop_a, fraction, delay))
    chain.append(Propagator('prop_1', pop_a, pop_b, fraction, delay))

    test_chain = Chain('test_chain', from_pop, to_pop, chain, fraction, delay, test_model)
    test_model.add_connector(test_chain)

    for time_step in [1., 1. / 4.]:
        test_model.set_time_step(time_step)
        for func in [test_chain.update_expectation, test_chain.update_data]:
            EPS = 0.02
            if func == test_chain.update_data:
                EPS = 0.2
            to_pop.reset()
            pop_a.reset()
            pop_b.reset()
            func()
            for pop in [to_pop, pop_b]:
                distribution = pop.future
                total = start * (1. - frac ** 2) * frac
                ave = mean
                std_dev = sigma
                if pop == pop_b:
                    total = start * frac ** 2
                    ave = 2. * mean
                    std_dev = np.sqrt(2.) * sigma
                sum_p = 0.
                sum_tp = 0.
                sum_ttp = 0.
                for i in range(len(distribution)):
                    sum_p += distribution[i]
                    sum_tp += i * distribution[i] * time_step
                    sum_ttp += i * i * distribution[i] * time_step ** 2
                assert np.abs(sum_p - total) < EPS * total
                est_mean = sum_tp / total
                assert np.abs(est_mean - ave) < EPS * ave
                est_sigma = np.sqrt(sum_ttp / total - est_mean ** 2)
                assert np.abs(est_sigma - std_dev) < EPS * std_dev
Beispiel #2
0
def test_class_Injector():
    """tests to ensure the behaviour class Injector"""
    test_model = Model('test_model')
    number = 50.
    inject = Parameter('inject', number, parameter_min=0., parameter_max=1000.)
    time = 5
    trans_time = Parameter('time', time, parameter_type='int', parameter_min=0, parameter_max=1000)
    to_pop = Population('to_pop', 0)
    test_injector = Injector('injector', 'rel_days', trans_time, to_pop, inject, model=test_model)
    test_model.add_transition(test_injector)
    for time_step in [1., 1. / 4.]:
        test_model.set_time_step(time_step)
        to_pop.reset()
        test_injector.take_action()
        assert to_pop.future[0] == number
        assert np.abs(test_injector.trigger_step - time / time_step) < 0.1
Beispiel #3
0
def test_class_Splitter():
    """tests to ensure the behaviour class Splitter"""
    test_model = Model('test_model')
    start = 100000
    from_pop = Population('from_pop', 0)
    from_pop.future = [start]
    to_pops = [Population('to_pop1', 0.), Population('to_pop2', 0.)]
    fracs = [0.4, 0.6]
    fraction = Parameter('frac', fracs[0])
    mean = 10.
    std_dev = 4.
    delay_pars = {
        'mean': Parameter('mean', mean, parameter_min=-100., parameter_max=100.),
        'sigma': Parameter('sigma', std_dev, parameter_min=-100., parameter_max=100.)
    }
    test_delay = Delay('test_delay', 'norm', delay_parameters=delay_pars, model=test_model)

    test_split = Splitter('test_prop', from_pop, to_pops, [fraction], test_delay)
    test_model.add_connector(test_split)
    for time_step in [1., 1. / 4.]:
        test_model.set_time_step(time_step)
        for func in [test_split.update_expectation, test_split.update_data]:
            EPS = 0.01
            if func == test_split.update_data:
                EPS = 0.1
            to_pops[0].reset()
            to_pops[1].reset()
            func()
            total = 0
            for i in range(2):
                distribution = to_pops[i].future
                frac = fracs[i]
                sum_p = 0.
                sum_tp = 0.
                sum_ttp = 0.
                for i in range(len(distribution)):
                    sum_p += distribution[i]
                    sum_tp += i * distribution[i] * time_step
                    sum_ttp += i * i * distribution[i] * time_step ** 2
                total += sum_p
                assert np.abs(sum_p - start * frac) < EPS * start * frac
                est_mean = sum_tp / (start * frac)
                assert np.abs(est_mean - mean) < EPS * mean
                est_sigma = np.sqrt(sum_ttp / (start * frac) - est_mean ** 2)
                assert np.abs(est_sigma - std_dev) < EPS * std_dev
            assert np.abs(total - start) < 0.1
Beispiel #4
0
def test_class_Multiplier():
    """tests to ensure the behaviour class Multiplier"""
    test_model = Model('test_model')
    EPS = 1.
    n1 = 50.
    n2 = 20.
    n3 = 2.
    scale = 0.1
    f_pops = [Population('f1_pop', n1), Population('f2_pop', n2), Population('f3_pop', n3)]
    to_pop = Population('to_pop', 0.)
    scale_par = Parameter('alpha', scale)
    delay = Delay('fast', 'fast')
    test_multiplier = Multiplier('test_multiplier', f_pops, to_pop, scale_par, delay, model=test_model)
    test_model.add_connector(test_multiplier)
    for time_step in [1., 1. / 4.]:
        test_model.set_time_step(time_step)
        # expectation:
        expected = n1 * n2 / n3 * scale * time_step
        to_pop.reset()
        test_multiplier.set_distribution('poisson', None)
        test_multiplier.update_expectation()
        assert to_pop.future[0] == expected

        # Poisson
        n_rep = 1000
        n_list = []
        for i in range(n_rep):
            to_pop.reset()
            test_multiplier.update_data()
            n_list.append(to_pop.future[0])
        assert np.abs(np.mean(n_list) - expected) < EPS
        assert np.abs(np.std(n_list) - np.sqrt(expected)) < EPS

        # Negative binomial
        p_nb = 0.2
        nbinom_par = Parameter('nb', p_nb)
        test_multiplier.set_distribution('nbinom', nbinom_par)

        n_rep = 1000
        n_list = []
        for i in range(n_rep):
            to_pop.reset()
            test_multiplier.update_data()
            n_list.append(to_pop.future[0])
        assert np.abs(np.mean(n_list) - expected) < EPS
        assert np.abs(np.std(n_list) - np.sqrt(expected / p_nb)) < EPS
Beispiel #5
0
def test_class_Propagator():
    """tests to ensure the behaviour class Propagator"""
    test_model = Model('test_model')
    start = 100000
    from_pop = Population('from_pop', 0)
    from_pop.future = [start]
    to_pop = Population('to_pop', 0.)
    frac = 0.4
    fraction = Parameter('frac', frac)
    mean = 10.
    std_dev = 4.
    delay_pars = {
        'mean': Parameter('mean', mean, parameter_min=-100., parameter_max=100.),
        'sigma': Parameter('sigma', std_dev, parameter_min=-100., parameter_max=100.)
    }
    test_delay = Delay('test_delay', 'norm', delay_parameters=delay_pars, model=test_model)

    test_prop = Propagator('test_prop', from_pop, to_pop, fraction, test_delay)
    test_model.add_connector(test_prop)
    for time_step in [1., 1. / 4.]:
        test_model.set_time_step(time_step)
        for func in [test_prop.update_expectation, test_prop.update_data]:
            EPS = 0.01
            if func == test_prop.update_data:
                EPS = 0.1
            to_pop.reset()
            func()
            distribution = to_pop.future
            sum_p = 0.
            sum_tp = 0.
            sum_ttp = 0.
            for i in range(len(distribution)):
                sum_p += distribution[i]
                sum_tp += i * distribution[i] * time_step
                sum_ttp += i * i * distribution[i] * time_step ** 2
            assert np.abs(sum_p - start * frac) < EPS * start * frac
            est_mean = sum_tp / (start * frac)
            assert np.abs(est_mean - mean) < EPS * mean
            est_sigma = np.sqrt(sum_ttp / (start * frac) - est_mean ** 2)
            assert np.abs(est_sigma - std_dev) < EPS * std_dev
Beispiel #6
0
def test_class_Delay():
    """tests to ensure the behaviour class Delay"""
    test_model = Model('test_model')
    EPS = 0.1
    mean = 10.
    std_dev = 4.
    half_width = float(std_dev * np.sqrt(12.) / 2.)
    k_vals = [1, 2, 3]
    for delay_type in ['norm', 'uniform', 'erlang', 'gamma']:
        k_s = [1]
        if delay_type == 'erlang':
            k_s = k_vals
        for k in k_s:
            delay_pars = {
                'mean': Parameter('mean', mean, parameter_min=-100., parameter_max=100.),
                'sigma': Parameter('sigma', std_dev, parameter_min=-100., parameter_max=100.),
                'half_width': Parameter('hw', half_width, parameter_min=-100., parameter_max=100.),
                'k': Parameter('k', k, parameter_type='int', parameter_min=1, parameter_max=100)
            }
            for time_step in [1., 1. / 4.]:
                test_model.set_time_step(time_step)
                # The delay is created after the model: since it is not associated with a connector, the model
                # does not know to call its update method. (The model does not have stand alone delays.)
                test_delay = Delay('test_delay', delay_type, delay_parameters=delay_pars, model=test_model)
                distribution = test_delay.future_expectations
                sum_p = 0.
                sum_tp = 0.
                sum_ttp = 0.
                for i in range(len(distribution)):
                    sum_p += distribution[i]
                    sum_tp += i * distribution[i] * time_step
                    sum_ttp += i * i * distribution[i] * time_step ** 2
                assert np.abs(sum_p - 1.) < EPS
                est_mean = sum_tp
                assert np.abs(est_mean - mean) < EPS
                est_sigma = np.sqrt(sum_ttp - sum_tp * sum_tp)
                if delay_type != 'erlang':
                    assert np.abs(est_sigma - std_dev) < EPS
                else:
                    assert np.abs(est_sigma - mean / np.sqrt(1. * k)) < EPS
Beispiel #7
0
def test_class_Modifier():
    """tests to ensure the behaviour class Modifier"""
    test_model = Model('test_model')
    mod_time = Parameter('time', 5, parameter_type='int', parameter_min=0, parameter_max=1000)
    par_val = 0.3
    par_0_val = 0.5
    par_1_val = 0.7
    parameter = Parameter('par', par_val)
    parameter_0 = Parameter('par_0', par_0_val)
    parameter_1 = Parameter('par_1', par_1_val)
    test_modifier = Modifier('test_modifier', 'rel_days', mod_time, parameter, parameter_0, parameter_1,
                             model=test_model)
    test_model.add_transition(test_modifier)
    for time_step in [1., 1. / 4.]:
        test_model.set_time_step(time_step)
        parameter.reset()
        assert parameter.get_value() == par_val
        test_modifier.take_action()
        assert parameter.get_value() == par_1_val
        test_modifier.reset()
        assert parameter.get_value() == par_0_val
        assert np.abs(test_modifier.trigger_step - 5 / time_step) < 0.1
Beispiel #8
0
 - more transitions
 - change linear modification to be start_value end_value, rather than start_value slope

Version 2.8:
 - more testing fraction transitions
 - add second infection cycle for B117 variant

@author: karlen
"""

from pypmca import Model, Population, Delay, Parameter, Multiplier, Propagator, \
    Splitter, Adder, Subtractor, Chain, Modifier, Injector

# Test by building a population model for BC

bc_model = Model('ref_model_2_8')
bc_model.set_t0(2020, 3, 1)

# Initialization

initial_pop_par = Parameter('N_0', 5000000, 5000, 50000000,
                            'Population of the region at t0', 'int')

total_pop = Population('total', initial_pop_par,
                       'total population of the region', color='black')
susceptible_pop = Population('susceptible', initial_pop_par,
                             'number of people who could become infected', color='cornflowerblue')
infected_pop = Population('infected', 0,
                          'total number of people ever infected', color='orange')

# Define the infection cycle
Beispiel #9
0
Version 2.6:
 - move most delay distributions from 'norm' to 'gamma'
 - add linear transition for reporting fraction
 - add reporting noise for deaths and hospitalization
 - set death reporting noise to be weekly

@author: karlen
"""

from pypmca import Model, Population, Delay, Parameter, Multiplier, Propagator, \
    Splitter, Adder, Subtractor, Chain, Modifier, Injector

# Test by building a population model for BC

bc_model = Model('ref_model_2_6')
bc_model.set_t0(2020, 3, 1)

# Initialization

initial_pop_par = Parameter('N_0', 5000000, 5000, 50000000,
                            'Population of the region at t0', 'int')

total_pop = Population('total',
                       initial_pop_par,
                       'total population of the region',
                       color='black')
susceptible_pop = Population('susceptible',
                             initial_pop_par,
                             'number of people who could become infected',
                             color='cornflowerblue')
Beispiel #10
0
pyPM.ca reference model #1

Includes a reporting chain. The default lag to reporting is longer than most regions, so the
effects of transitions (changes to social distancing, or outbreaks) on case reports may be delayed.

update: May 21, 2020. Fix error: need to remove "departed ventillator" from "in_icu"

@author: karlen
"""

from pypmca import Model, Population, Delay, Parameter, Multiplier, Propagator, \
    Splitter, Adder, Subtractor, Chain, Modifier, Injector

# Test by building a population model for BC

bc_model = Model('ref_model_1')
bc_model.set_t0(2020, 3, 1)

# Initialization

initial_pop_par = Parameter('N_0', 5000000, 5000, 50000000,
                            'Population of the region at t0', 'int')

total_pop = Population('total', initial_pop_par,
                       'total population of the region', color='black')
susceptible_pop = Population('susceptible', initial_pop_par,
                             'number of people who could become infected', color='cornflowerblue')
infected_pop = Population('infected', 0,
                          'total number of people ever infected', color='orange')

# Define the infection cycle
Beispiel #11
0
 - change default cont_0 from 55. to 10.
 - change initial boot population from 1. to 0.1
 - change default death delay sigma from 5. to 10.

Version 2.4:
 - add linear modifiers for recover_frac, icu_frac, non_icu_hosp_frac

@author: karlen
"""

from pypmca import Model, Population, Delay, Parameter, Multiplier, Propagator, \
    Splitter, Adder, Subtractor, Chain, Modifier, Injector

# Test by building a population model for BC

bc_model = Model('ref_model_2_4')
bc_model.set_t0(2020, 3, 1)

# Initialization

initial_pop_par = Parameter('N_0', 5000000, 5000, 50000000,
                            'Population of the region at t0', 'int')

total_pop = Population('total',
                       initial_pop_par,
                       'total population of the region',
                       color='black')
susceptible_pop = Population('susceptible',
                             initial_pop_par,
                             'number of people who could become infected',
                             color='cornflowerblue')
Beispiel #12
0
    - the size of the susceptible population is reduced as a result of both vaccinations and infections
        - to calculate the reduction from vaccination: must track the sub-population of vaccine candidates
          who are susceptible (or "susvaccan" for short). The expected reduction in susceptible population
          depends on the ratio of the sizes of the "susvaccan" and "vaccan" populations and the vaccine effectiveness
        - each infection reduces the susceptible population by 1. The expected reduction of "susvaccan" would be
          the ratio of the sizes of the susvaccan and susceptible populations

@author: karlen
"""

from pypmca import Model, Population, Delay, Parameter, Multiplier, Propagator, \
    Splitter, Adder, Subtractor, Chain, Modifier, Injector

# Test by building a population model for BC

bc_model = Model('ref_model_2_5')
bc_model.set_t0(2020, 3, 1)

# Initialization

initial_pop_par = Parameter('N_0', 5000000, 5000, 50000000,
                            'Population of the region at t0', 'int')

total_pop = Population('total', initial_pop_par,
                       'total population of the region', color='black')
susceptible_pop = Population('susceptible', initial_pop_par,
                             'number of people who could become infected', color='cornflowerblue')
infected_pop = Population('infected', 0,
                          'total number of people ever infected', color='orange')

# Define the infection cycle
Beispiel #13
0
def test_class_Model():
    """tests to ensure the behaviour class Model"""
    test_model = Model('test')
Beispiel #14
0
Reduced the lag time between contagious and reported, (as compared to reference model #1)
to better match the situation in BC and elsewhere - transitions now occur where they should

Add a contact tracing population, to allow another mechanism to remove people from
the contagious population early. Initial value has p=0, so it does not act until it
is switched on.

@author: karlen
"""

from pypmca import Model, Population, Delay, Parameter, Multiplier, Propagator, \
    Splitter, Adder, Subtractor, Chain, Modifier, Injector

# Test by building a population model for BC

bc_model = Model('ref_model_2')
bc_model.set_t0(2020, 3, 1)

# Initialization

initial_pop_par = Parameter('N_0', 5000000, 5000, 50000000,
                            'Population of the region at t0', 'int')

total_pop = Population('total',
                       initial_pop_par,
                       'total population of the region',
                       color='black')
susceptible_pop = Population('susceptible',
                             initial_pop_par,
                             'number of people who could become infected',
                             color='cornflowerblue')
Beispiel #15
0
 - add reporting noise for deaths and hospitalization
 - set death reporting noise to be weekly

Version 2.7:
 - more transitions
 - change linear modification to be start_value end_value, rather than start_value slope

@author: karlen
"""

from pypmca import Model, Population, Delay, Parameter, Multiplier, Propagator, \
    Splitter, Adder, Subtractor, Chain, Modifier, Injector

# Test by building a population model for BC

bc_model = Model('ref_model_2_7')
bc_model.set_t0(2020, 3, 1)

# Initialization

initial_pop_par = Parameter('N_0', 5000000, 5000, 50000000,
                            'Population of the region at t0', 'int')

total_pop = Population('total',
                       initial_pop_par,
                       'total population of the region',
                       color='black')
susceptible_pop = Population('susceptible',
                             initial_pop_par,
                             'number of people who could become infected',
                             color='cornflowerblue')
Beispiel #16
0
 - change default delay for icu: was (14,1) now: (4,2)
 - change default alpha_0 and alpha_1-n: was (0.385, 0.062) to: (0.4, 0.1)
 - change default transition time for alpha_0 -> alpha_1 from 16 to 20
 - change default cont_0 from 55. to 10.
 - change initial boot population from 1. to 0.1
 - change default death delay sigma from 5. to 10.

@author: karlen
"""

from pypmca import Model, Population, Delay, Parameter, Multiplier, Propagator, \
    Splitter, Adder, Subtractor, Chain, Modifier, Injector

# Test by building a population model for BC

bc_model = Model('ref_model_2_3')
bc_model.set_t0(2020, 3, 1)

# Initialization

initial_pop_par = Parameter('N_0', 5000000, 5000, 50000000,
                            'Population of the region at t0', 'int')

total_pop = Population('total',
                       initial_pop_par,
                       'total population of the region',
                       color='black')
susceptible_pop = Population('susceptible',
                             initial_pop_par,
                             'number of people who could become infected',
                             color='cornflowerblue')