예제 #1
0
def simulate(params, plt=None, plot_hourly=None, xlabel=None):

    if plot_hourly is None:
        plot_hourly = params['geometry']['n'] < 50000  # Hack, remove

    # Initialize a city's geography and its denizens
    num, num_initially_infected = int(params['geometry']['n']), int(
        params['geometry']['i'])
    num_times_of_day = int(params['motion']['t'])
    precision = int(params['geometry']['p'])
    home, work = home_and_work_locations(geometry_params=params['geometry'],
                                         num=num)
    positions = nudge(home, w=0.05 * params['motion']['w'])
    status = np.random.permutation([INFECTED] * num_initially_infected +
                                   [VULNERABLE] *
                                   (num - num_initially_infected))
    day_fraction = 1.0 / num_times_of_day

    # Population drifts to work and back, incurring viral load based on proximity to others who are infected
    day = 0
    while any(s in [INFECTED, POSITIVE, SYMPTOMATIC] for s in status):
        day = day + 1
        for step_no, time_of_day in enumerate(times_of_day(num_times_of_day)):
            stationary = [s in [DECEASED, POSITIVE] for s in status]
            attractors = destinations(status, time_of_day, home, work)
            positions = evolve_positions(positions=positions,
                                         motion_params=params['motion'],
                                         attractors=attractors,
                                         day_fraction=day_fraction,
                                         stationary=stationary)
            exposed = newly_exposed(positions=positions,
                                    status=status,
                                    precision=precision)
            status = contact_progression(status=status,
                                         health_params=params['health'],
                                         exposed=exposed)
            status = individual_progression(status,
                                            health_params=params['health'],
                                            day_fraction=day_fraction)

            if plt and (plot_hourly or step_no % 12 == 0):
                plt.clf()
                plot_points(plt=plt,
                            positions=positions,
                            status=status,
                            title="Day " + str(day) + ':' +
                            str(time_of_day * num_times_of_day))
                b = params['geometry']['b']
                plt.axis([-b, b, -b, b])
                if xlabel:
                    plt.xlabel(xlabel)
                plt.show(block=False)
                plt.pause(0.01)
            pprint(
                Counter([list(STATE_DESCRIPTIONS.values())[s]
                         for s in status]))
예제 #2
0
def homesick(params):
    """ To illustrate the OU process  """

    num, num_initially_infected = int(params['geometry']['n']),int(params['geometry']['i'])
    num_times_of_day = int(params['motion']['t'])
    day_fraction = 1.0/num_times_of_day
    home = [(0,0) for _ in range(num) ]
    w    = params['motion']['w']
    k    = params['motion']['k']
    R    = w/math.sqrt(2*k)
    b    = params['geometry']['b']
    positions = [ (x/2*b,y/2*b) for x,y in [ tuple( np.random.multivariate_normal(mean=[0,0],cov=[[1,0],[0,1]]) ) for _ in range(num)] ]
    status    = [VULNERABLE]*num

    fig, axs = plt.subplots(nrows=1, ncols=2)
    population_variances = list()
    rolling_variances = list()
    for day in range(10):
        for step_no, time_of_day in enumerate(times_of_day(num_times_of_day)):
            stationary = [ s in [DECEASED, POSITIVE] for s in status ]
            positions  = evolve_positions(positions=positions, motion_params=params['motion'], attractors=home,
                                          time_step=day_fraction, stationary=stationary)

            axs[0].clear()
            plot_points(plt=axs[0], positions=positions, status=status, sizes=[64]*6)
            b = params['geometry']['b']
            axs[0].axis([-b, b, -b, b])
            axs[0].set_title('Day '+str(day))

            circle_x, circle_y = circle(r=R)
            axs[0].scatter(x=circle_x,y=circle_y,c='g',s=1)

            axs[0].figure

            population_variance = np.mean( [ x*x+y*y for x,y in positions ])
            population_variances.append(population_variance)

            num_lagged = 5+int(0.25*len(rolling_variances))
            rolling_mean_variance = np.mean( population_variances[-num_lagged:] )
            rolling_variances.append(rolling_mean_variance)

            axs[1].clear()
            axs[1].plot([ math.sqrt(v) for v in population_variances],'+')
            axs[1].plot([ math.sqrt(v) for v in rolling_variances] )
            axs[1].plot(list(range(len(rolling_variances))),[R]*len(rolling_variances),'--')
            axs[1].axis([0,len(rolling_variances),0.75*R,1.5*max(rolling_variances[-1],R)])
            axs[1].legend(['Current','Avg last ('+str(num_lagged)+')','Theoretical'],loc='upper left')
            axs[1].set_title('Root mean square distance')
            axs[1].figure


            plt.show(block=False)
            plt.pause(0.01)
            if step_no==1 and day==0:
                plt.pause(20)
예제 #3
0
def simulate(params, plt=None, hourly=None, xlabel=None, callback=plot_callback, home=None, work=None, positions=None, stopping_i=None, stopping_t=None):
    """ OU Pandemic simulation
    :param params:       dict of dict as per pandemic.conventions
    :param plt:          Handle to matplotlib plot
    :param hourly:  Bool        Set False to speed up, True to see commuting
    :param xlabel:       str         Label for plot
    :param callback:     Any function taking home, work, day, params, positions, status (e.g. for plotting, saving etc)
    :return: None        Use the callback
    """
    if stopping_i is None:
        import math
        stopping_i = int(math.ceil(0.7 * params['geometry']['i']))
    if hourly is None:
        hourly = params['geometry']['n'] < 50000  # Hack, remove
    if stopping_t is None:
        stopping_t = 150

    # Initialize a city's geography and its denizens
    num, num_initially_infected = int(params['geometry']['n']),int(params['geometry']['i'])
    num_times_of_day = int(params['motion']['t'])
    precision  = int(params['geometry']['p'])
    if home is None or work is None:
        home, work = home_and_work_locations(geometry_params=params['geometry'],num=num)
    if positions is None:
        positions  = nudge(home,w=0.05*params['motion']['w'])
    status     = np.random.permutation([INFECTED]*num_initially_infected +[VULNERABLE]*(num-num_initially_infected))
    time_step  = 1.0/num_times_of_day

    day = 0
    killed = False
    while sum( s in [ INFECTED ] for s in status )>=stopping_i and day<stopping_t and not killed:
        day = day+1
        for step_no, day_fraction in enumerate(times_of_day(num_times_of_day)):
            stationary = [ s in [DECEASED, POSITIVE] for s in status ]
            attractors = destinations(status, day_fraction, home, work)
            positions  = evolve_positions(positions=positions, motion_params=params['motion'], attractors=attractors,
                                          time_step=time_step , stationary=stationary )
            exposed = newly_exposed(positions=positions, status=status, precision=precision)
            status = contact_progression(status=status, health_params=params['health'], exposed=exposed)
            status = individual_progression(status, health_params=params['health'], day_fraction=time_step )

            if callback:
                signal = callback(day=day, day_fraction=day_fraction, home=home, work=work, positions=positions, status=status, params=params, step_no=step_no, hourly=hourly, plt=plt, xlabel=xlabel)
                if signal is not None:
                    if 'kill' in signal:
                        killed = True
                    if 'lockdown' in signal:
                        work = [ h for h in home ]
                    if 'params' in signal:
                        params.update(signal['params'])
    pprint(Counter([list(STATE_DESCRIPTIONS.values())[s] for s in status]))
예제 #4
0
 def day(self):
     """ Step through a day """
     num_times_of_day = int(self.params['motion']['t'])
     assert num_times_of_day % 4 == 0, 'Must be multiple of four'
     day_times = times_of_day(num_times_of_day)
     num_quarter = int(num_times_of_day / 4)
     for quarter in range(4):
         self._intraday_callback()[quarter]()
         quarter_times = day_times[quarter * num_quarter:(quarter + 1) *
                                   num_quarter]
         for tod in quarter_times:
             self.state['clock']['time_of_day'] = tod
             self.step()
             self.step_callback()
         self.quarterly_callback()
예제 #5
0
def intensity(params):
    """ To illustrate the OU process with commuting  """

    num, num_initially_infected = int(params['geometry']['n']), int(
        params['geometry']['i'])
    assert num % 2 == 0

    HOME_1 = (-1.5, 1.5)
    HOME_2 = (-1.5, -1.5)
    HOME_3 = (1.5, 1.5)
    HOME_4 = (1.5, -1.5)
    HOMES = [HOME_1, HOME_2, HOME_3, HOME_4]
    WORK = (0, 0)
    home = [HOME_1] * int(num / 4) + [HOME_2] * int(num / 4) + [HOME_3] * int(
        num / 4) + [HOME_4] * int(num / 4)
    work = [WORK] * num

    def is_working(time_of_day):
        return time_of_day > 0.4 and time_of_day < 0.6

    def is_home(time_of_day):
        return time_of_day < 0.0 or time_of_day > 0.75

    num, num_initially_infected = int(params['geometry']['n']), int(
        params['geometry']['i'])
    num_times_of_day = int(params['motion']['t'])
    day_fraction = 1.0 / num_times_of_day
    w = params['motion']['w']
    k = params['motion']['k']
    R = w / math.sqrt(2 * k)
    b = params['geometry']['b']
    positions = [(x / 2 * b, y / 2 * b) for x, y in [
        tuple(np.random.multivariate_normal(mean=[0, 0], cov=[[1, 0], [0, 1]]))
        for _ in range(num)
    ]]
    status = [VULNERABLE] * num

    fig, axs = plt.subplots(nrows=2, ncols=2)

    population_variances = list()
    rolling_variances = list()
    collisions = list()
    rolling_mean_collisions = list()

    for day in range(50):
        for step_no, time_of_day in enumerate(times_of_day(num_times_of_day)):
            stationary = [s in [DECEASED, POSITIVE] for s in status]
            attractors = [w for w in work
                          ] if time_of_day < 0.5 else [h for h in home]
            positions = evolve_positions(positions=positions,
                                         motion_params=params['motion'],
                                         attractors=attractors,
                                         time_step=day_fraction,
                                         stationary=stationary)

            axs[0][0].clear()
            plot_points(plt=axs[0][0],
                        positions=positions,
                        status=status,
                        sizes=[16] * 6)
            b = params['geometry']['b']
            axs[0][0].axis([-b, b, -b, b])
            axs[0][0].axis([-b, b, -b, b])
            axs[0][0].set_title('Day ' + str(day) + ' ' + str(time_of_day))

            for offsets in HOMES + [WORK]:
                circle_x, circle_y = circle(r=R, offset=offsets)
                axs[0][0].scatter(x=circle_x, y=circle_y, c='g', s=1)

            axs[0][0].figure

            # Collision count
            locations = [
                encode(pos[0], pos[1], precision=6) for pos in positions
            ]
            num_collisions = num - len(set(locations))
            collisions.append(num_collisions)

            precision = 1.0 / (params['motion']['w']**2)
            inv_sqs = [
                np.mean([
                    1. / (0.00001 + sq_dist(positions[j], pos))
                    for k, pos in enumerate(positions) if not j == k
                ]) for j in range(num)
            ]

            population_variances.append(np.mean(inv_sqs))

            num_lagged = 4 * int(num_times_of_day / 30)
            rolling_mean_variance = np.mean(population_variances[-num_lagged:])
            rolling_mean_collisions.append(np.mean(collisions[-num_lagged:]))
            rolling_variances.append(rolling_mean_variance)

            axs[0][1].clear()
            axs[0][1].plot([math.sqrt(v) for v in population_variances], 'x')
            axs[0][1].plot([math.sqrt(v) for v in rolling_variances])
            axs[0][1].plot(list(range(len(rolling_variances))),
                           [R] * len(rolling_variances), '--')
            axs[0][1].legend(
                ['Current time step', 'Avg last (' + str(num_lagged) + ')'],
                loc='lower right')
            axs[0][1].set_title('Mean inverse squared distance)')
            axs[0][1].figure

            axs[1][1].plot(collisions, '+')
            axs[1][1].plot(rolling_mean_collisions, '--')
            axs[1][1].set_title('Collisions')
            axs[1][1].legend(
                ['Current time step', 'Avg last (' + str(num_lagged) + ')'],
                loc='upper left')
            axs[1][1].figure

            if day > 0:
                rmc = rolling_mean_collisions[num_times_of_day:]
                pv = population_variances[num_times_of_day:]
                axs[1][0].clear()
                axs[1][0].loglog(pv, rmc, '+')
                axs[1][0].set_xlabel('Mean inverse squared distance)')
                axs[1][0].set_ylabel('Mean collisions')
                b, m = polyfit(pv, rmc, 1)
                axs[1][0].plot(pv, [b + m * pv_ for pv_ in pv], '-')
                axs[1][0].set_title('Slope is ' + str(m))
                axs[1][0].figure

            if step_no % 2 == 0:
                plt.show(block=False)
                plt.pause(0.5)
                if step_no == 1 and day == 0:
                    plt.pause(5)
예제 #6
0
def commute(params):
    """ To illustrate the OU process with commuting  """

    num, num_initially_infected = int(params['geometry']['n']), int(
        params['geometry']['i'])
    assert num % 2 == 0

    HOME_1 = (-1.5, 1.5)
    HOME_2 = (-1.5, -1.5)
    WORK = (1.5, 0)
    home = [HOME_1] * int(num / 2) + [HOME_2] * int(num / 2)
    work = [WORK] * num

    def is_working(time_of_day):
        return time_of_day > 0.4 and time_of_day < 0.6

    def is_home(time_of_day):
        return time_of_day < 0.0 or time_of_day > 0.75

    num, num_initially_infected = int(params['geometry']['n']), int(
        params['geometry']['i'])
    num_times_of_day = int(params['motion']['t'])
    day_fraction = 1.0 / num_times_of_day
    w = params['motion']['w']
    k = params['motion']['k']
    R = w / math.sqrt(2 * k)
    b = params['geometry']['b']
    positions = [(x / 2 * b, y / 2 * b) for x, y in [
        tuple(np.random.multivariate_normal(mean=[0, 0], cov=[[1, 0], [0, 1]]))
        for _ in range(num)
    ]]
    status = [VULNERABLE] * num

    fig, axs = plt.subplots(nrows=1, ncols=2)

    population_variances = list()
    rolling_variances = list()

    for day in range(10):
        for step_no, time_of_day in enumerate(times_of_day(num_times_of_day)):
            stationary = [s in [DECEASED, POSITIVE] for s in status]
            attractors = [w for w in work
                          ] if time_of_day < 0.5 else [h for h in home]
            positions = evolve_positions(positions=positions,
                                         motion_params=params['motion'],
                                         attractors=attractors,
                                         day_fraction=day_fraction,
                                         stationary=stationary)

            axs[0].clear()
            plot_points(plt=axs[0],
                        positions=positions,
                        status=status,
                        sizes=[64] * 6)
            b = params['geometry']['b']
            axs[0].axis([-b, b, -b, b])
            axs[0].set_title('Day ' + str(day) + ' ' + str(time_of_day))

            for offsets in [HOME_1, HOME_2, WORK]:
                circle_x, circle_y = circle(r=R, offset=offsets)
                axs[0].scatter(x=circle_x, y=circle_y, c='g', s=1)

            axs[0].figure

            if is_home(time_of_day):
                population_variance = np.mean(
                    [sq_dist(pos, hm) for pos, hm in zip(positions, home)])

                population_variances.append(population_variance)

                num_lagged = 5 + int(0.25 * len(rolling_variances))
                rolling_mean_variance = np.mean(
                    population_variances[-num_lagged:])
                rolling_variances.append(rolling_mean_variance)

                axs[1].clear()
                axs[1].plot([math.sqrt(v) for v in population_variances], '+')
                axs[1].plot([math.sqrt(v) for v in rolling_variances])
                axs[1].plot(list(range(len(rolling_variances))),
                            [R] * len(rolling_variances), '--')
                axs[1].axis([
                    0,
                    len(rolling_variances), 0.75 * R,
                    1.5 * max(rolling_variances[-1], R)
                ])
                axs[1].legend([
                    'Current', 'Avg last (' + str(num_lagged) + ')',
                    'Theoretical'
                ],
                              loc='upper left')
                axs[1].set_title('RMS Distance to home after 6pm')
                axs[1].figure

            plt.show(block=False)
            plt.pause(0.01)
            if step_no == 1 and day == 0:
                plt.pause(20)
예제 #7
0
def simulate(params,
             plt=None,
             plot_hourly=None,
             xlabel=None,
             callback=plot_callback):
    """ OU Pandemic simulation
    :param params:       dict of dict as per pandemic.conventions
    :param plt:          Handle to matplotlib plot
    :param plot_hourly:  Bool        Set False to speed up, True to see commuting
    :param xlabel:       str         Label for plot
    :param callback:     Any function taking home, work, day, params, positions, status (e.g. for plotting, saving etc)
    :return: None        Use the callback
    """

    if plot_hourly is None:
        plot_hourly = params['geometry']['n'] < 50000  # Hack, remove

    # Initialize a city's geography and its denizens
    num, num_initially_infected = int(params['geometry']['n']), int(
        params['geometry']['i'])
    num_times_of_day = int(params['motion']['t'])
    precision = int(params['geometry']['p'])
    home, work = home_and_work_locations(geometry_params=params['geometry'],
                                         num=num)
    positions = nudge(home, w=0.05 * params['motion']['w'])
    status = np.random.permutation([INFECTED] * num_initially_infected +
                                   [VULNERABLE] *
                                   (num - num_initially_infected))
    time_step = 1.0 / num_times_of_day

    # Population drifts to work and back, incurring viral load based on proximity to others who are infected
    day = 0
    while any(s in [INFECTED] for s in status):
        day = day + 1
        for step_no, day_fraction in enumerate(times_of_day(num_times_of_day)):
            stationary = [s in [DECEASED, POSITIVE] for s in status]
            attractors = destinations(status, day_fraction, home, work)
            positions = evolve_positions(positions=positions,
                                         motion_params=params['motion'],
                                         attractors=attractors,
                                         time_step=time_step,
                                         stationary=stationary)
            exposed = newly_exposed(positions=positions,
                                    status=status,
                                    precision=precision)
            status = contact_progression(status=status,
                                         health_params=params['health'],
                                         exposed=exposed)
            status = individual_progression(status,
                                            health_params=params['health'],
                                            day_fraction=time_step)

            if callback:
                callback(day=day,
                         day_fraction=day_fraction,
                         home=home,
                         work=work,
                         positions=positions,
                         status=status,
                         params=params,
                         step_no=step_no,
                         plot_hourly=plot_hourly,
                         plt=plt)
    pprint(Counter([list(STATE_DESCRIPTIONS.values())[s] for s in status]))