def test_seed_initial_infections_most_people_low_risk():
    npeople = 200
    snapshot = Snapshot.zeros(nplaces, npeople, nslots)

    # set all people as low risk
    snapshot.area_codes = np.full(npeople, "E02004187")  # low risk area code
    snapshot.not_home_probs = np.full(npeople, 0.0)

    # set 3 people to be high risk
    snapshot.area_codes[1:4] = "E02004143"  # high risk area code
    snapshot.not_home_probs[1:4] = 0.8

    num_seed_days = 5
    simulator = Simulator(snapshot, gpu=False, num_seed_days=num_seed_days)
    simulator.upload_all(snapshot.buffers)

    people_statuses_before = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_before)
    # assert that no people are infected before seeding
    assert not people_statuses_before.any()

    # run one step with seeding and check number of infections
    simulator.step_with_seeding()

    people_statuses_after = np.zeros(snapshot.npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_after)

    # only high risk people will get infected (eg. in a high risk area code and with a high not_home_prob)
    # so only the 3 high risk people should be infected by the seeding
    expected_num_infections = 3

    num_people_infected = np.count_nonzero(people_statuses_after)

    assert num_people_infected == expected_num_infections
Beispiel #2
0
def test_seed_initial_infections_some_low_risk():
    npeople = 200
    snapshot = Snapshot.random(nplaces, npeople, nslots)

    # set all people as high risk
    snapshot.area_codes = np.full(npeople, "E02004187")  # low risk area code
    snapshot.area_codes[1:4] = "E02004143"  # high risk area code
    snapshot.not_home_probs = np.full(npeople, 0.0)
    snapshot.not_home_probs[1:4] = 0.8

    num_seed_days = 5
    simulator = Simulator(snapshot, gpu=False, num_seed_days=num_seed_days)
    simulator.upload_all(snapshot.buffers)

    people_statuses_before = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_before)
    # assert that no people are infected before seeding
    assert not people_statuses_before.any()

    # run one step with seeding and check number of infections
    simulator.step_with_seeding()

    people_statuses_after = np.zeros(snapshot.npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_after)

    expected_num_infections = 3  # taken from devon_initial_cases.csv file

    num_people_infected = np.count_nonzero(people_statuses_after)

    assert num_people_infected == expected_num_infections
Beispiel #3
0
def test_susceptible_become_infected():
    snapshot = Snapshot.random(nplaces, npeople, nslots)

    test_hazard = 0.4

    people_hazards_test_data = np.full(npeople, test_hazard, dtype=np.float32)

    people_statuses_test_data = np.full(npeople, DiseaseStatus.Susceptible.value, dtype=np.uint32)

    people_transition_times_test_data = np.zeros(npeople, dtype=np.uint32)

    snapshot.buffers.people_hazards[:] = people_hazards_test_data
    snapshot.buffers.people_statuses[:] = people_statuses_test_data
    snapshot.buffers.people_transition_times[:] = people_transition_times_test_data

    simulator = Simulator(snapshot, gpu=False)
    simulator.upload_all(snapshot.buffers)

    people_statuses_before = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_before)

    assert np.array_equal(people_statuses_before, people_statuses_test_data)

    simulator.step_kernel("people_update_statuses")

    people_statuses_after = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_after)

    num_exposed = np.count_nonzero(people_statuses_after == DiseaseStatus.Exposed.value)
    proportion_exposed = num_exposed / npeople

    expected_proportion_infected = 1.0 - np.exp(-test_hazard)

    assert np.isclose(expected_proportion_infected, proportion_exposed, atol=0.01)
Beispiel #4
0
def test_transmission_times_decremented():
    snapshot = Snapshot.random(nplaces, npeople, nslots)

    people_transition_times_test_data = np.full(npeople, 3, dtype=np.uint32)
    snapshot.buffers.people_transition_times[:] = people_transition_times_test_data

    simulator = Simulator(snapshot, gpu=False)
    simulator.upload_all(snapshot.buffers)

    # check decremented after one step
    simulator.step_kernel("people_update_statuses")

    people_transmission_times_after = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_transition_times", people_transmission_times_after)

    expected_people_transition_times = np.full(npeople, 2, dtype=np.uint32)

    assert np.array_equal(expected_people_transition_times, people_transmission_times_after)

    # check decremented after another step
    simulator.step_kernel("people_update_statuses")

    people_transmission_times_after = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_transition_times", people_transmission_times_after)

    expected_people_transition_times = np.full(npeople, 1, dtype=np.uint32)

    assert np.array_equal(expected_people_transition_times, people_transmission_times_after)
def test_diabetes_higher_mortality():
    snapshot = Snapshot.random(nplaces, npeople, nslots)

    people_ages_test_data = np.full(npeople, 65, dtype=np.uint16)
    people_statuses_test_data = np.full(npeople,
                                        DiseaseStatus.Symptomatic.value,
                                        dtype=np.uint32)
    # set all people to diabetes=1
    people_diabetes_test_data = np.ones(npeople, dtype=np.uint8)
    people_transition_times_test_data = np.full(npeople, 1, dtype=np.uint32)

    snapshot.buffers.people_ages[:] = people_ages_test_data
    snapshot.buffers.people_statuses[:] = people_statuses_test_data
    snapshot.buffers.people_diabetes[:] = people_diabetes_test_data
    snapshot.buffers.people_transition_times[:] = people_transition_times_test_data

    params = Params()
    diabetes_multiplier = 1.4
    params.diabetes_multiplier = diabetes_multiplier
    snapshot.update_params(params)

    simulator = Simulator(snapshot, gpu=False)
    simulator.upload_all(snapshot.buffers)

    people_statuses_before = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_before)

    assert np.array_equal(people_statuses_before, people_statuses_test_data)

    # run two timesteps so statuses should change
    simulator.step_kernel("people_update_statuses")
    simulator.step_kernel("people_update_statuses")

    # assert that statuses change to either recovered or dead in the correct proportion
    people_statuses_after_two_steps = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_after_two_steps)

    num_recovered = np.count_nonzero(
        people_statuses_after_two_steps == DiseaseStatus.Recovered.value)
    proportion_recovered = num_recovered / npeople

    num_dead = np.count_nonzero(
        people_statuses_after_two_steps == DiseaseStatus.Dead.value)
    proportion_dead = num_dead / npeople

    # expected recovery probability for ages 60-70
    expected_proportion_dead = 0.0193
    expected_proportion_dead *= diabetes_multiplier
    expected_proportion_recovered = 1 - expected_proportion_dead

    assert np.isclose(expected_proportion_recovered,
                      proportion_recovered,
                      atol=0.01)
    assert np.isclose(expected_proportion_dead, proportion_dead, atol=0.01)
Beispiel #6
0
def test_correct_send_hazard():
    # Set up and upload the test data
    snapshot = Snapshot.random(nplaces, npeople, nslots)

    people_place_ids = np.full((npeople, nslots),
                               sentinel_value,
                               dtype=np.uint32)
    people_place_ids[0][0:4] = [0, 5, 7, 3]
    people_place_ids[1][0:4] = [1, 5, 6, 4]
    people_place_ids[2][0:4] = [2, 3, 7, 6]

    people_flows = np.zeros((npeople, nslots), dtype=np.float32)
    people_flows[0][0:4] = [0.8, 0.1, 0.06, 0.04]
    people_flows[1][0:4] = [0.7, 0.18, 0.09, 0.03]
    people_flows[2][0:4] = [0.6, 0.2, 0.16, 0.04]

    people_statuses = np.full(npeople,
                              DiseaseStatus.Symptomatic.value,
                              dtype=np.uint32)

    snapshot.buffers.people_flows[:] = people_flows.flatten()
    snapshot.buffers.people_place_ids[:] = people_place_ids.flatten()
    snapshot.buffers.people_statuses[:] = people_statuses
    snapshot.buffers.place_activities[:] = np.random.randint(4,
                                                             size=nplaces,
                                                             dtype=np.uint32)

    params = Params()
    params.place_hazard_multipliers = np.ones(5, dtype=np.float32)
    snapshot.update_params(params)

    simulator = Simulator(snapshot, gpu=False)
    simulator.upload_all(snapshot.buffers)

    # Run the kernel
    simulator.step_kernel("people_send_hazards")

    # Download the result
    place_hazards = np.zeros(nplaces, dtype=np.uint32)
    simulator.download("place_hazards", place_hazards)
    place_counts = np.zeros(nplaces, dtype=np.uint32)
    simulator.download("place_counts", place_counts)

    # Assert expected results
    expected_place_hazards_floats = np.array(
        [0.8, 0.7, 0.6, 0.24, 0.03, 0.28, 0.13, 0.22], dtype=np.float32)
    expected_place_hazards = (fixed_factor *
                              expected_place_hazards_floats).astype(np.uint32)
    expected_place_counts = np.array([1, 1, 1, 2, 1, 2, 2, 2], dtype=np.uint32)

    assert np.allclose(expected_place_hazards, place_hazards)
    assert np.array_equal(expected_place_counts, place_counts)
def test_places_are_reset_to_zero():
    snapshot = Snapshot.random(nplaces, npeople, nslots)

    hazards_test_data = np.array([4, 3, 5, 1, 6], dtype=np.uint32)
    counts_test_data = np.array([1, 4, 8, 10, 2], dtype=np.uint32)

    snapshot.buffers.place_hazards[:] = hazards_test_data
    snapshot.buffers.place_counts[:] = counts_test_data

    simulator = Simulator(snapshot, gpu=False)
    simulator.upload_all(snapshot.buffers)

    place_hazards_before = np.zeros(nplaces, dtype=np.uint32)
    simulator.download("place_hazards", place_hazards_before)

    place_counts_before = np.zeros(nplaces, dtype=np.uint32)
    simulator.download("place_counts", place_counts_before)

    assert np.array_equal(place_hazards_before, hazards_test_data)
    assert np.array_equal(place_counts_before, counts_test_data)

    simulator.step_kernel("places_reset")

    # initialise host buffers randomly so we know they are filled to zeros
    place_hazards_after = np.random.randint(0, 11, nplaces, dtype=np.uint32)
    simulator.download("place_hazards", place_hazards_after)

    place_counts_after = np.random.randint(0, 11, nplaces, dtype=np.uint32)
    simulator.download("place_counts", place_counts_after)

    assert np.array_equal(place_hazards_after,
                          np.zeros(nplaces, dtype=np.uint32))
    assert np.array_equal(place_counts_after, np.zeros(nplaces,
                                                       dtype=np.uint32))
def test_symptomatic_become_recovered_or_dead_old_age():
    snapshot = Snapshot.random(nplaces, npeople, nslots)

    people_ages_test_data = np.full(npeople, 92, dtype=np.uint16)
    people_statuses_test_data = np.full(npeople,
                                        DiseaseStatus.Symptomatic.value,
                                        dtype=np.uint32)
    people_transition_times_test_data = np.full(npeople, 1, dtype=np.uint32)

    snapshot.buffers.people_ages[:] = people_ages_test_data
    snapshot.buffers.people_statuses[:] = people_statuses_test_data
    snapshot.buffers.people_transition_times[:] = people_transition_times_test_data

    simulator = Simulator(snapshot, gpu=False)
    simulator.upload_all(snapshot.buffers)

    people_statuses_before = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_before)

    assert np.array_equal(people_statuses_before, people_statuses_test_data)

    # run two timesteps so statuses should change
    simulator.step_kernel("people_update_statuses")
    simulator.step_kernel("people_update_statuses")

    # assert that statuses change to either recovered or dead in the correct proportion
    people_statuses_after_two_steps = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_after_two_steps)

    num_recovered = np.count_nonzero(
        people_statuses_after_two_steps == DiseaseStatus.Recovered.value)
    proportion_recovered = num_recovered / npeople

    num_dead = np.count_nonzero(
        people_statuses_after_two_steps == DiseaseStatus.Dead.value)
    proportion_dead = num_dead / npeople

    # expected recovery probability for ages 80+
    expected_proportion_dead = 0.1737
    expected_proportion_recovered = 1 - expected_proportion_dead

    assert np.isclose(expected_proportion_recovered,
                      proportion_recovered,
                      atol=0.01)
    assert np.isclose(expected_proportion_dead, proportion_dead, atol=0.01)
Beispiel #9
0
def test_correct_send_hazard():
    # Set up and upload the test data
    snapshot = Snapshot.random(nplaces, npeople, nslots)

    place_hazards_floats = np.array([0.2, 0.0, 0.5, 0.03, 0.0123, 0.22, 0.0001, 0.73], dtype=np.float32)
    place_hazards = (fixed_factor * place_hazards_floats).astype(np.uint32)

    people_place_ids = np.full((npeople, nslots), sentinel_value, dtype=np.uint32)
    people_place_ids[0][0:4] = [1, 6, 0, 4]
    people_place_ids[1][0:4] = [2, 6, 7, 5]
    people_place_ids[2][0:4] = [3, 4, 0, 7]

    people_flows = np.zeros((npeople, nslots), dtype=np.float32)
    people_flows[0][0:4] = [0.6, 0.2, 0.16, 0.04]
    people_flows[1][0:4] = [0.7, 0.18, 0.09, 0.03]
    people_flows[2][0:4] = [0.8, 0.1, 0.06, 0.04]

    people_statuses = np.full(npeople, DiseaseStatus.Susceptible.value, dtype=np.uint32)
    people_statuses[0] = DiseaseStatus.Symptomatic.value

    people_hazards = np.zeros(npeople, dtype=np.float32)

    snapshot.buffers.people_flows[:] = people_flows.flatten()
    snapshot.buffers.people_place_ids[:] = people_place_ids.flatten()
    snapshot.buffers.people_statuses[:] = people_statuses
    snapshot.buffers.place_hazards[:] = place_hazards
    snapshot.buffers.people_hazards[:] = people_hazards

    simulator = Simulator(snapshot, gpu=False)
    simulator.upload_all(snapshot.buffers)

    # Run the kernel
    simulator.step_kernel("people_recv_hazards")

    # Download the result
    people_hazards = np.zeros(npeople, dtype=np.float32)
    simulator.download("people_hazards", people_hazards)

    # Assert expected results
    expected_people_hazards = np.array([0.0, 0.422318, 0.06643], dtype=np.float32)

    assert np.allclose(expected_people_hazards, people_hazards)
Beispiel #10
0
def test_all_asymptomatic_become_recovered():
    snapshot = Snapshot.random(nplaces, npeople, nslots)

    people_statuses_test_data = np.full(npeople, DiseaseStatus.Asymptomatic.value, dtype=np.uint32)

    people_transition_times_test_data = np.full(npeople, 1, dtype=np.uint32)

    snapshot.buffers.people_statuses[:] = people_statuses_test_data
    snapshot.buffers.people_transition_times[:] = people_transition_times_test_data

    simulator = Simulator(snapshot, gpu=False)
    simulator.upload_all(snapshot.buffers)

    people_statuses_before = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_before)

    assert np.array_equal(people_statuses_before, people_statuses_test_data)

    simulator.step_kernel("people_update_statuses")

    # check that statuses don't change after one step
    people_statuses_after_one_step = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_after_one_step)

    assert np.array_equal(people_statuses_after_one_step, people_statuses_test_data)

    # run another timestep, this time statuses should change
    simulator.step_kernel("people_update_statuses")

    # assert that all statuses change to presymptomatic after two timesteps
    people_statuses_after_two_steps = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_after_two_steps)

    assert np.all(people_statuses_after_two_steps == DiseaseStatus.Recovered.value)
Beispiel #11
0
def test_more_overweight_become_symptomatic():
    snapshot = Snapshot.random(nplaces, npeople, nslots)

    people_statuses_test_data = np.full(npeople, DiseaseStatus.Exposed.value, dtype=np.uint32)
    people_transition_times_test_data = np.full(npeople, 1, dtype=np.uint32)
    # set all people to obesity=2, corresponding to overweight
    people_obesity_test_data = np.full(npeople, 2, dtype=np.uint8)
    people_transition_times_test_data = np.full(npeople, 1, dtype=np.uint32)
    people_ages_test_data = np.full(npeople, 18, dtype=np.uint16)

    snapshot.buffers.people_statuses[:] = people_statuses_test_data
    snapshot.buffers.people_obesity[:] = people_obesity_test_data
    snapshot.buffers.people_transition_times[:] = people_transition_times_test_data
    snapshot.buffers.people_ages[:] = people_ages_test_data

    params = Params()
    base_proportion_asymptomatic = 0.79
    params.proportion_asymptomatic = base_proportion_asymptomatic
    overweight_sympt_mplier = 1.46
    params.overweight_sympt_mplier = overweight_sympt_mplier
    snapshot.update_params(params)

    simulator = Simulator(snapshot, gpu=False)
    simulator.upload_all(snapshot.buffers)

    people_statuses_before = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_before)

    assert np.array_equal(people_statuses_before, people_statuses_test_data)

    simulator.step_kernel("people_update_statuses")

    # check that statuses don't change after one step
    people_statuses_after_one_step = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_after_one_step)

    assert np.array_equal(people_statuses_after_one_step, people_statuses_test_data)

    # run another timestep, this time statuses should change
    simulator.step_kernel("people_update_statuses")

    # assert that statuses change to either symptomatic or asymptomatic in the correct proportion
    people_statuses_after_two_steps = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_after_two_steps)

    num_asymptomatic = np.count_nonzero(people_statuses_after_two_steps == DiseaseStatus.Asymptomatic.value)
    result_proportion_asymptomatic = num_asymptomatic / npeople

    num_presymptomatic = np.count_nonzero(people_statuses_after_two_steps == DiseaseStatus.Presymptomatic.value)
    result_proportion_presymptomatic = num_presymptomatic / npeople

    base_proportion_symptomatic = 1 - base_proportion_asymptomatic
    expected_proportion_presymptomatic = overweight_sympt_mplier * base_proportion_symptomatic
    expected_proportion_asymptomatic = 1 - expected_proportion_presymptomatic

    assert np.isclose(expected_proportion_asymptomatic, result_proportion_asymptomatic, atol=0.01)
    assert np.isclose(expected_proportion_presymptomatic, result_proportion_presymptomatic, atol=0.01)
def test_symptomatic_become_recovered_or_dead_young_age():
    # NB: run with more people since chance of young people dying is low
    npeople = 500000
    snapshot = Snapshot.random(nplaces, npeople, nslots)

    people_ages_test_data = np.full(npeople, 25, dtype=np.uint16)
    people_statuses_test_data = np.full(npeople,
                                        DiseaseStatus.Symptomatic.value,
                                        dtype=np.uint32)
    people_transition_times_test_data = np.full(npeople, 1, dtype=np.uint32)

    snapshot.buffers.people_ages[:] = people_ages_test_data
    snapshot.buffers.people_statuses[:] = people_statuses_test_data
    snapshot.buffers.people_transition_times[:] = people_transition_times_test_data

    simulator = Simulator(snapshot, gpu=False)
    simulator.upload_all(snapshot.buffers)

    people_statuses_before = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_before)

    assert np.array_equal(people_statuses_before, people_statuses_test_data)

    simulator.step_kernel("people_update_statuses")

    # check that statuses don't change after one step
    people_statuses_after_one_step = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_after_one_step)

    assert np.array_equal(people_statuses_after_one_step,
                          people_statuses_test_data)

    # run another timestep, this time statuses should change
    simulator.step_kernel("people_update_statuses")

    # assert that statuses change to either recovered or dead in the correct proportion
    people_statuses_after_two_steps = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_after_two_steps)

    num_recovered = np.count_nonzero(
        people_statuses_after_two_steps == DiseaseStatus.Recovered.value)
    proportion_recovered = num_recovered / npeople

    num_dead = np.count_nonzero(
        people_statuses_after_two_steps == DiseaseStatus.Dead.value)
    proportion_dead = num_dead / npeople

    # expected recovery probability for ages 20 to 29
    expected_proportion_dead = 0.0004
    expected_proportion_recovered = 1 - expected_proportion_dead

    assert np.isclose(expected_proportion_recovered,
                      proportion_recovered,
                      atol=0.0001)
    assert np.isclose(expected_proportion_dead, proportion_dead, atol=0.0001)
def test_correct_flow_calculation_with_lockdown():
    snapshot = Snapshot.random(nplaces, npeople, nslots)

    people_place_ids_test_data = np.full((npeople, nslots),
                                         sentinel_value,
                                         dtype=np.uint32)
    people_place_ids_test_data[0][0:4] = [0, 5, 7, 3]
    people_place_ids_test_data[1][0:4] = [1, 5, 6, 4]
    people_place_ids_test_data[2][0:4] = [2, 3, 7, 6]

    people_flows_test_data = np.zeros((npeople, nslots), dtype=np.float32)
    people_flows_test_data[0][0:4] = [0.8, 0.1, 0.06, 0.04]
    people_flows_test_data[1][0:4] = [0.7, 0.18, 0.09, 0.03]
    people_flows_test_data[2][0:4] = [0.6, 0.2, 0.16, 0.04]

    people_statuses_test_data = np.full(npeople,
                                        DiseaseStatus.Susceptible.value,
                                        dtype=np.uint32)
    symptomatic_person_id = 1
    people_statuses_test_data[symptomatic_person_id] = np.uint32(
        DiseaseStatus.Symptomatic.value)

    place_activities_test_data = np.full(nplaces,
                                         Activity.Retail.value,
                                         dtype=np.uint32)
    place_activities_test_data[:3] = Activity.Home.value

    snapshot.buffers.people_baseline_flows[:] = people_flows_test_data.flatten(
    )
    snapshot.buffers.people_flows[:] = people_flows_test_data.flatten()
    snapshot.buffers.people_place_ids[:] = people_place_ids_test_data.flatten()
    snapshot.buffers.people_statuses[:] = people_statuses_test_data
    snapshot.buffers.place_activities[:] = place_activities_test_data

    params = Params()
    params.set_lockdown_multiplier(lockdown_multipliers, 0)
    params.symptomatic_multiplier = 0.5
    snapshot.buffers.params[:] = params.asarray()

    simulator = Simulator(snapshot, gpu=False)
    simulator.upload_all(snapshot.buffers)

    people_flows_before = np.zeros(npeople * nslots, dtype=np.float32)
    simulator.download("people_flows", people_flows_before)

    expected_people_flows_before = people_flows_test_data.flatten()
    assert np.array_equal(people_flows_before, expected_people_flows_before)

    simulator.step_kernel("people_update_flows")

    people_flows_after = np.zeros(npeople * nslots, dtype=np.float32)
    simulator.download("people_flows", people_flows_after)

    assert not np.array_equal(people_flows_before, people_flows_after)

    # assert correct flows for symptomatic person
    expected_symptomatic_flows_after = np.array([0.85, 0.09, 0.045, 0.015])
    symptomatic_person_start_idx = symptomatic_person_id * nslots
    symptomatic_flows_after = people_flows_after[
        symptomatic_person_start_idx:symptomatic_person_start_idx + 4]

    assert np.allclose(expected_symptomatic_flows_after,
                       symptomatic_flows_after)

    # assert correct flows for person who is not symptomatic
    # adjustments calculated using first lockdown multiplier (approx. 0.9084687)
    expected_non_symptomatic_flows_after = np.array(
        [0.63661252, 0.18169374, 0.145354992, 0.036338748])
    non_symptomatic_person_id = 2
    person_start_idx = non_symptomatic_person_id * nslots
    non_symptomatic_flows_after = people_flows_after[
        person_start_idx:person_start_idx + 4]

    assert np.allclose(expected_non_symptomatic_flows_after,
                       non_symptomatic_flows_after)
def test_correct_flow_calculation_no_lockdown():
    snapshot = Snapshot.random(nplaces, npeople, nslots)

    people_place_ids_test_data = np.full((npeople, nslots),
                                         sentinel_value,
                                         dtype=np.uint32)
    people_place_ids_test_data[0][0:4] = [0, 5, 7, 3]
    people_place_ids_test_data[1][0:4] = [1, 5, 6, 4]
    people_place_ids_test_data[2][0:4] = [2, 3, 7, 6]

    people_flows_test_data = np.zeros((npeople, nslots), dtype=np.float32)
    people_flows_test_data[0][0:4] = [0.8, 0.1, 0.06, 0.04]
    people_flows_test_data[1][0:4] = [0.7, 0.18, 0.09, 0.03]
    people_flows_test_data[2][0:4] = [0.6, 0.2, 0.16, 0.04]

    people_statuses_test_data = np.full(npeople,
                                        DiseaseStatus.Susceptible.value,
                                        dtype=np.uint32)
    symptomatic_person_id = 1
    people_statuses_test_data[symptomatic_person_id] = np.uint32(
        DiseaseStatus.Symptomatic.value)

    place_activities_test_data = np.full(nplaces,
                                         Activity.Retail.value,
                                         dtype=np.uint32)
    place_activities_test_data[:3] = Activity.Home.value

    snapshot.buffers.people_baseline_flows[:] = people_flows_test_data.flatten(
    )
    snapshot.buffers.people_flows[:] = people_flows_test_data.flatten()
    snapshot.buffers.people_place_ids[:] = people_place_ids_test_data.flatten()
    snapshot.buffers.people_statuses[:] = people_statuses_test_data
    snapshot.buffers.place_activities[:] = place_activities_test_data

    params = Params()
    symptomatic_multiplier = 0.5
    params.symptomatic_multiplier = symptomatic_multiplier
    snapshot.update_params(params)

    simulator = Simulator(snapshot, gpu=False)
    simulator.upload_all(snapshot.buffers)

    people_flows_before = np.zeros(npeople * nslots, dtype=np.float32)
    simulator.download("people_flows", people_flows_before)

    expected_people_flows_before = people_flows_test_data.flatten()
    assert np.array_equal(people_flows_before, expected_people_flows_before)

    simulator.step_kernel("people_update_flows")

    people_flows_after = np.zeros(npeople * nslots, dtype=np.float32)
    simulator.download("people_flows", people_flows_after)

    # adjust symptomatic persons flows according to symptomatic multiplier
    expected_people_flows_after = people_flows_test_data
    expected_people_flows_after[symptomatic_person_id][0:4] = [
        0.85, 0.09, 0.045, 0.015
    ]
    expected_people_flows_after = expected_people_flows_after.flatten()

    assert not np.array_equal(people_flows_before, people_flows_after)
    assert np.array_equal(expected_people_flows_after, people_flows_after)
Beispiel #15
0
def test_asymptomatics_add_less_hazard():
    # Set up and upload the test data
    snapshot = Snapshot.random(nplaces, npeople, nslots)

    people_place_ids = np.full((npeople, nslots),
                               sentinel_value,
                               dtype=np.uint32)
    people_place_ids[0][0:4] = [0, 5, 7, 3]
    people_place_ids[1][0:4] = [1, 5, 6, 4]
    people_place_ids[2][0:4] = [2, 3, 7, 6]

    people_flows = np.zeros((npeople, nslots), dtype=np.float32)
    people_flows[0][0:4] = [0.8, 0.1, 0.06, 0.04]
    people_flows[1][0:4] = [0.7, 0.18, 0.09, 0.03]
    people_flows[2][0:4] = [0.6, 0.2, 0.16, 0.04]

    people_statuses = np.full(npeople,
                              DiseaseStatus.Symptomatic.value,
                              dtype=np.uint32)

    snapshot.buffers.people_flows[:] = people_flows.flatten()
    snapshot.buffers.people_place_ids[:] = people_place_ids.flatten()
    snapshot.buffers.people_statuses[:] = people_statuses
    snapshot.buffers.place_activities[:] = np.random.randint(4,
                                                             size=nplaces,
                                                             dtype=np.uint32)

    params = Params()
    params.place_hazard_multipliers = np.ones(5, dtype=np.float32)
    asymptomatic_multiplier = 0.5
    params.individual_hazard_multipliers = np.array(
        [1.0, asymptomatic_multiplier, 1.0])
    snapshot.update_params(params)

    simulator = Simulator(snapshot, gpu=False)
    simulator.upload_all(snapshot.buffers)

    # Run the kernel
    simulator.step_kernel("people_send_hazards")

    # Download the result
    place_hazards = np.zeros(nplaces, dtype=np.uint32)
    simulator.download("place_hazards", place_hazards)
    place_counts = np.zeros(nplaces, dtype=np.uint32)
    simulator.download("place_counts", place_counts)

    # Assert expected results
    expected_place_hazards_floats = np.array(
        [0.8, 0.7, 0.6, 0.24, 0.03, 0.28, 0.13, 0.22], dtype=np.float32)
    expected_place_hazards = (fixed_factor *
                              expected_place_hazards_floats).astype(np.uint32)

    assert np.allclose(expected_place_hazards, place_hazards)

    # Change statuses so all people are asymptomatic
    people_statuses_asymptomatic = np.full(npeople,
                                           DiseaseStatus.Asymptomatic.value,
                                           dtype=np.uint32)
    simulator.upload("people_statuses", people_statuses_asymptomatic)

    # reset place hazards to zero
    simulator.step_kernel("places_reset")

    # run kernel with asymptomatic population
    simulator.step_kernel("people_send_hazards")

    # Download the result
    place_hazards_asymptomatic = np.zeros(nplaces, dtype=np.uint32)
    simulator.download("place_hazards", place_hazards_asymptomatic)

    # Assert expected results
    expected_place_hazards_floats_asymptomatic = expected_place_hazards_floats * asymptomatic_multiplier
    expected_place_hazards_asymptomatic = (
        fixed_factor * expected_place_hazards_floats_asymptomatic).astype(
            np.uint32)

    assert np.allclose(expected_place_hazards_asymptomatic,
                       place_hazards_asymptomatic)
    assert place_hazards_asymptomatic.sum() < place_hazards.sum()
Beispiel #16
0
    def run(self):

        # If this is the first data assimilation window, we can just run the model as normal
        if self.start_day == 0:
            assert self.current_particle_pop_df is None  # Shouldn't have any preivously-created particles
            # load snapshot
            snapshot = Snapshot.load_full_snapshot(path=self.snapshot_file)
            # set params
            snapshot.update_params(self.params)
            # Can set the random seed to make it deterministic (None means np will choose one randomly)
            snapshot.seed_prngs(seed=None)

            # Create a simulator and upload the snapshot data to the OpenCL device
            simulator = Simulator(snapshot,
                                  opencl_dir=self.opencl_dir,
                                  gpu=self.use_gpu)
            simulator.upload_all(snapshot.buffers)

            if not self.quiet:
                # print(f"Running simulation {sim_number + 1}.")
                print(f"Running simulation")

            params = Params.fromarray(
                snapshot.buffers.params
            )  # XX Why extract Params? Can't just use PARAMS?

            summary = Summary(
                snapshot,
                store_detailed_counts=self.store_detailed_counts,
                max_time=self.run_length  # Total length of the simulation
            )

            # only show progress bar in quiet mode
            timestep_iterator = range(self.run_length) if self.quiet \
                else tqdm(range(self.quiet), desc="Running simulation")

            iter_count = 0  # Count the total number of iterations
            # Run for iterations days
            for _ in timestep_iterator:
                # Update parameters based on lockdown
                params.set_lockdown_multiplier(snapshot.lockdown_multipliers,
                                               iter_count)
                simulator.upload("params", params.asarray())

                # Step the simulator
                simulator.step()
                iter_count += 1

            # Update the statuses
            simulator.download("people_statuses",
                               snapshot.buffers.people_statuses)
            summary.update(iter_count, snapshot.buffers.people_statuses)

            if not self.quiet:
                for i in range(self.run_length):
                    print(f"\nDay {i}")
                    summary.print_counts(i)

            if not self.quiet:
                print("\nFinished")

            # Download the snapshot from OpenCL to host memory
            # XX This is 'None'.
            final_state = simulator.download_all(snapshot.buffers)

            pass
        else:  # Otherwise we need to restart previous models stored in the current_particle_pop_df
            # XXXX CAN GET OLD MODEL STATES, WITH ALL DISEASE STATUSES, FROM THE DF. TWO ISSUES
            # 1. But need to work out how to draw these appropriately; can't assume they are each as good as
            # each other. THIS SHOULD BE OK, surely there's a way to go from the final particles and weights
            # to the DF of state vectors. Particle ID? Just try it out.
            # 2. Also: what to do about stochasticity. For a given (global) parameter combination, we will
            # get quite different results depending on the mode state. - I DON'T THINK THIS IS A PROBLEM.
            # ABC Commonly used with stochastic models. E.g. https://eprints.lancs.ac.uk/id/eprint/80439/1/mainR1.pdf
            #
            raise Exception("Not implemented yet")

        # Return the current state of the model in a dictionary describing what it is
        #return {"simulator": simulator}
        return {"simulator": snapshot}
Beispiel #17
0
def test_infection_transition_times_distribution(visualize=False):
    npeople = 1000000
    snapshot = Snapshot.random(nplaces, npeople, nslots)

    test_hazard = 0.9

    people_hazards_test_data = np.full(npeople, test_hazard, dtype=np.float32)
    people_statuses_test_data = np.full(npeople, DiseaseStatus.Presymptomatic.value, dtype=np.uint32)
    people_transition_times_test_data = np.zeros(npeople, dtype=np.uint32)

    snapshot.buffers.people_hazards[:] = people_hazards_test_data
    snapshot.buffers.people_statuses[:] = people_statuses_test_data
    snapshot.buffers.people_transition_times[:] = people_transition_times_test_data

    params = Params()
    infection_log_scale = 0.75
    infection_mode = 7.0
    params.infection_log_scale = infection_log_scale
    params.infection_mode = infection_mode
    snapshot.update_params(params)

    simulator = Simulator(snapshot, gpu=False)
    simulator.upload_all(snapshot.buffers)

    simulator.step_kernel("people_update_statuses")

    people_statuses_after = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_statuses", people_statuses_after)

    people_transition_times_after = np.zeros(npeople, dtype=np.uint32)
    simulator.download("people_transition_times", people_transition_times_after)

    # Check that transition times are distributed with a log-normal distribution
    adjusted_transition_times = people_transition_times_after + 1
    mean = adjusted_transition_times.mean()
    std_dev = adjusted_transition_times.std()
    mode = scipy.stats.mode(adjusted_transition_times)[0][0]

    meanlog = infection_log_scale**2 + np.log(infection_mode)
    expected_samples = np.random.lognormal(mean=meanlog, sigma=infection_log_scale, size=npeople)
    # round samples to nearest integer
    expected_samples = np.rint(expected_samples)
    expected_mean = expected_samples.mean()
    expected_std_dev = expected_samples.std()
    expected_mode = scipy.stats.mode(expected_samples)[0][0]

    # Float to integer rounding and clamping at zero makes the original random numbers hard
    # to recover so we have slightly larger tolerances here to avoid false negatives.
    assert np.isclose(expected_mean, mean, atol=0.7)
    assert np.isclose(expected_std_dev, std_dev, atol=0.4)
    assert np.isclose(expected_mode, mode, atol=1.0)

    # check that mode is similar to original mode parameter
    assert np.isclose(infection_mode, mode, atol=1.0)

    if visualize:  # show histogram of distribution
        fig, ax = plt.subplots(1, 1)
        ax.hist(adjusted_transition_times, bins=50, range=[0, 60])
        plt.title("Result Samples")
        plt.show()
        fig, ax = plt.subplots(1, 1)
        ax.hist(expected_samples, bins=50, range=[0, 60])
        plt.title("Expected Samples")
        plt.show()