Ejemplo n.º 1
0
def test_save_and_load_full_snapshot():
    nplaces = 10
    npeople = 100
    nslots = 16
    generated_snapshot = Snapshot.random(nplaces=nplaces,
                                         npeople=npeople,
                                         nslots=nslots)

    snapshot_path = "tests/opencl/random.npz"

    generated_snapshot.save(snapshot_path)

    loaded_snapshot = Snapshot.load_full_snapshot(snapshot_path)

    os.remove(snapshot_path)

    assert np.array_equal(generated_snapshot.buffers.people_ages,
                          loaded_snapshot.buffers.people_ages)
    assert np.all(
        np.isclose(generated_snapshot.buffers.place_coords,
                   loaded_snapshot.buffers.place_coords))

    assert loaded_snapshot.nplaces == nplaces
    assert loaded_snapshot.npeople == npeople
    assert loaded_snapshot.nslots == nslots
Ejemplo n.º 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
Ejemplo n.º 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)
Ejemplo n.º 4
0
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))
Ejemplo n.º 5
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)
Ejemplo n.º 6
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)
Ejemplo n.º 7
0
def test_load_existing_snapshot():
    # Load initial snapshot generated from the SnapshotConverter test
    loaded_snapshot = Snapshot.load_full_snapshot(
        "tests/opencl/test_snapshot.npz")

    expected_nplaces = 8
    expected_npeople = 3
    expected_nslots = 16

    assert loaded_snapshot.nplaces == expected_nplaces
    assert loaded_snapshot.npeople == expected_npeople
    assert loaded_snapshot.nslots == expected_nslots

    expected_people_place_ids = np.full((expected_npeople, expected_nslots),
                                        sentinel_value)
    expected_people_place_ids[0][0:4] = [0, 5, 7, 3]
    expected_people_place_ids[1][0:4] = [1, 5, 6, 4]
    expected_people_place_ids[2][0:4] = [2, 3, 7, 6]
    expected_people_place_ids = expected_people_place_ids.flatten()

    expected_people_flows = np.zeros((expected_npeople, expected_nslots))
    expected_people_flows[0][0:4] = [0.8, 0.1, 0.06, 0.04]
    expected_people_flows[1][0:4] = [0.7, 0.18, 0.09, 0.03]
    expected_people_flows[2][0:4] = [0.6, 0.2, 0.16, 0.04]
    expected_people_flows = expected_people_flows.flatten()

    assert np.array_equal(expected_people_place_ids,
                          loaded_snapshot.buffers.people_place_ids)
    assert np.all(
        np.isclose(expected_people_flows,
                   loaded_snapshot.buffers.people_baseline_flows))
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
Ejemplo n.º 9
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)
Ejemplo n.º 10
0
    def run_opencl_model(i: int,
                         iterations: int,
                         snapshot_filepath: str,
                         params,
                         opencl_dir: str,
                         use_gpu: bool,
                         use_healthier_pop: bool,
                         store_detailed_counts: bool = True,
                         quiet=False) -> (np.ndarray, np.ndarray):
        """
        Run the OpenCL model.

        :param i: Simulation number (i.e. if run as part of an ensemble)
        :param iterations: Number of iterations to ru the model for
        :param snapshot_filepath: Location of the snapshot (the model must have already been initialised)
        :param params: a Params object containing the parameters used to define how the model behaves
        :param opencl_dir: Location of the OpenCL code
        :param use_gpu: Whether to use the GPU to process it or not
        :param store_detailed_counts: Whether to store the age distributions for diseases (default True, if
          false then the model runs much more quickly).
        :param quiet: Whether to print a message when the model starts
        :return: A summary python array that contains the results for each iteration and a final state

        """

        # load snapshot
        snapshot = Snapshot.load_full_snapshot(path=snapshot_filepath)
        prev_obesity = np.copy(snapshot.buffers.people_obesity)
        if use_healthier_pop:
            snapshot.switch_to_healthier_population()

        print("testing obesity arrays not equal")
        print(np.mean(prev_obesity))
        print(np.mean(snapshot.buffers.people_obesity))
        # assert not np.array_equal(prev_obesity, snapshot.buffers.people_obesity)
        # print("arrays not equal")

        # set params
        snapshot.update_params(params)

        # set the random seed of the model for each repetition, otherwise it is completely deterministic
        snapshot.seed_prngs(i)

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

        if not quiet:
            print(f"Running simulation {i + 1}.")
        summary, final_state = run_headless(
            simulator,
            snapshot,
            iterations,
            quiet=True,
            store_detailed_counts=store_detailed_counts)
        return summary, final_state
Ejemplo n.º 11
0
def test_switch_to_healthier_population():
    snapshot = Snapshot.random(nplaces=50, npeople=8, nslots=5)
    snapshot.buffers.people_obesity[:] = np.array([0, 0, 1, 1, 2, 2, 4, 4])

    snapshot.switch_to_healthier_population()

    result_obesity = snapshot.buffers.people_obesity
    expected_obesity = np.array([0, 0, 1, 1, 1, 1, 3, 3])

    assert np.array_equal(result_obesity, expected_obesity)
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_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)
Ejemplo n.º 14
0
def test_copy_snapshot():
    snapshot = Snapshot.random(nplaces=50, npeople=8, nslots=5)
    snapshot_copy = copy.deepcopy(snapshot)

    # check buffer contents equal after copy
    assert np.array_equal(snapshot.buffers.people_baseline_flows,
                          snapshot_copy.buffers.people_baseline_flows)

    # mutate original snapshot and check that the copy is no longer equal
    snapshot.buffers.people_baseline_flows[:] = snapshot.buffers.people_baseline_flows * 2.5
    assert not np.array_equal(snapshot.buffers.people_baseline_flows,
                              snapshot_copy.buffers.people_baseline_flows)
Ejemplo n.º 15
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)
Ejemplo n.º 16
0
def test_seed_prngs():
    snapshot = Snapshot.random(nplaces=50, npeople=100, nslots=5)
    prngs_before = np.zeros(400, dtype=np.uint32)
    prngs_before[:] = snapshot.buffers.people_prngs

    snapshot.seed_prngs(46)
    prngs_after = np.zeros(400, dtype=np.uint32)
    prngs_after[:] = snapshot.buffers.people_prngs

    snapshot.seed_prngs(46)
    prngs_after_after = np.zeros(400, dtype=np.uint32)
    prngs_after_after[:] = snapshot.buffers.people_prngs

    assert np.any(prngs_before != prngs_after)
    assert np.all(prngs_after == prngs_after_after)
Ejemplo n.º 17
0
def test_generate_zeros_snapshot():
    nplaces = 10
    npeople = 100
    nslots = 16
    snapshot = Snapshot.zeros(nplaces=nplaces, npeople=npeople, nslots=nslots)

    assert snapshot.buffers.place_activities.shape[0] == nplaces
    assert snapshot.buffers.people_ages.shape[0] == npeople
    assert snapshot.buffers.people_place_ids.shape[0] == npeople * nslots
    assert snapshot.buffers.place_coords.shape[0] == nplaces * 2

    # check all zeros
    assert not snapshot.buffers.place_activities.any()
    assert not snapshot.buffers.people_ages.any()
    assert not snapshot.buffers.people_place_ids.any()
    assert not snapshot.buffers.place_coords.any()
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)
Ejemplo n.º 19
0
def run_opencl_model(individuals_df, activity_locations,
                     time_activity_multiplier, iterations, data_dir, base_dir,
                     use_gui, use_gpu, use_cache, initialise,
                     calibration_params, disease_params):
    snapshot_cache_filepath = base_dir + "/microsim/opencl/snapshots/cache.npz"

    # Choose whether to load snapshot file from cache, or create a snapshot from population data
    if not use_cache or not os.path.exists(snapshot_cache_filepath):
        print("\nGenerating Snapshot for OpenCL model")
        snapshot_converter = SnapshotConvertor(individuals_df,
                                               activity_locations,
                                               time_activity_multiplier,
                                               data_dir)
        snapshot = snapshot_converter.generate_snapshot()
        snapshot.save(snapshot_cache_filepath
                      )  # store snapshot in cache so we can load later
    else:  # load cached snapshot
        snapshot = Snapshot.load_full_snapshot(path=snapshot_cache_filepath)

    # set the random seed of the model
    snapshot.seed_prngs(42)

    # set params
    if calibration_params is not None and disease_params is not None:
        snapshot.update_params(
            create_params(calibration_params, disease_params))

        if disease_params["improve_health"]:
            print("Switching to healthier population")
            snapshot.switch_to_healthier_population()
    if initialise:
        print(
            "Have finished initialising model. -init flag is set so not running it. Exitting"
        )
        return

    run_mode = "GUI" if use_gui else "headless"
    print(f"\nRunning OpenCL model in {run_mode} mode")
    run_opencl(snapshot,
               iterations,
               data_dir,
               use_gui,
               use_gpu,
               num_seed_days=disease_params["seed_days"],
               quiet=False)
Ejemplo n.º 20
0
    def generate_snapshot(self):
        people_ages = self.get_people_ages()
        people_obesity = self.get_people_obesity()
        people_cvd = self.get_people_cvd()
        people_diabetes = self.get_people_diabetes()
        people_blood_pressure = self.get_people_blood_pressure()
        area_codes = self.get_people_area_codes()
        not_home_probs = self.get_not_home_probs()
        people_place_ids, people_flows = self.get_people_place_data()

        place_activities = self.get_place_data()
        place_coordinates = self.get_place_coordinates()
        return Snapshot.from_arrays(people_ages, people_obesity, people_cvd,
                                    people_diabetes, people_blood_pressure,
                                    people_place_ids, people_flows, area_codes,
                                    not_home_probs, place_activities,
                                    place_coordinates,
                                    self.lockdown_multipliers)
Ejemplo n.º 21
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)
Ejemplo n.º 22
0
 def draw_snapshots_window(self, width, height):
     imgui.set_next_window_size(width / 6, height / 4)
     imgui.set_next_window_position(width * 5 / 6, height * 3 / 4)
     imgui.begin("Snapshots", flags=default_flags)
     clicked, self.selected_snapshot = imgui.listbox(
         "", self.selected_snapshot, self.snapshots)
     if imgui.button("Load Selected"):
         self.snapshot = Snapshot.load_full_snapshot(
             f"snapshots/{self.snapshots[self.selected_snapshot]}")
         self.simulator.upload_all(self.snapshot.buffers)
         self.simulator.time = self.snapshot.time
         self.upload_hazards(self.snapshot.buffers.place_hazards)
         self.upload_locations(self.snapshot.buffers.place_coords)
         self.upload_links(self.snapshot.buffers.people_place_ids)
         self.current_snapshot = self.selected_snapshot
     if imgui.button("Save"):
         self.simulator.download_all(self.snapshot.buffers)
         self.snapshot.time = self.simulator.time
         self.snapshot.save(
             f"snapshots/{self.snapshots[self.current_snapshot]}")
     if imgui.button("Save As..."):
         self.show_saveas = True
     imgui.end()
Ejemplo n.º 23
0
def test_summary_update():
    npeople = 50 + 34 + 101 + 551
    summary = Summary(snapshot=Snapshot.random(nplaces=10, npeople=npeople, nslots=10), max_time=20)

    time = 10

    statuses = np.concatenate((
        np.full(50, 0),
        np.full(34, 1),
        np.full(101, 4),
        np.full(551, 6),
    ))
    np.random.shuffle(statuses)

    summary.update(time, statuses)

    assert summary.total_counts[0][time] == 50
    assert summary.total_counts[1][time] == 34
    assert summary.total_counts[2][time] == 0
    assert summary.total_counts[3][time] == 0
    assert summary.total_counts[4][time] == 101
    assert summary.total_counts[5][time] == 0
    assert summary.total_counts[6][time] == 551
Ejemplo n.º 24
0
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)
Ejemplo n.º 25
0
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)
Ejemplo n.º 26
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}
Ejemplo n.º 27
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()
Ejemplo n.º 28
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()