def test_functional_seniors_residence():
    """ Run a simulation of 1 infection in a seniors residence, and perform some sanity checks """

    with tempfile.TemporaryDirectory() as output_dir:

        rng = np.random.RandomState(42)

        # Config
        start_time = datetime.datetime(2020, 2, 28, 0, 0)
        simulation_days = 100
        city_x_range = (0, 1000)
        city_y_range = (0, 1000)

        # Find the test_configs directory, and load the required config yaml
        conf = get_test_conf("naive_local.yaml")
        conf['simulation_days'] = simulation_days
        conf['COVID_SPREAD_START_TIME'] = start_time
        conf['INTERVENTION_START_TIME'] = start_time
        conf['_MEAN_DAILY_UNKNOWN_CONTACTS'] = 0.5

        env = Env(start_time)
        city = EmptyCity(env, rng, city_x_range, city_y_range, conf)
        sr = Household(
                        env=env,
                        rng=np.random.RandomState(rng.randint(2 ** 16)),
                        conf=conf,
                        name=f"SENIOR_RESIDENCE:0",
                        location_type="SENIOR_RESIDENCE",
                        lat=rng.randint(*city_x_range),
                        lon=rng.randint(*city_y_range),
                        area=1000,
                        capacity=None,
                    )
        city.senior_residences.append(sr)

        N = 10

        # Create humans
        ages = city.rng.randint(*(65, 100), size=N)

        infection = [None] * N
        # One initial infection
        infection[0] = city.start_time
        city.n_init_infected = 1

        humans = [
            Human(
                env=city.env,
                city=city,
                name=i,
                age=ages[i],
                rng=rng,
                conf=conf,
            )
            for i in range(N)
        ]

        for human in humans:
            human.assign_household(sr)
            sr.residents.append(human)
            human.mobility_planner.initialize()

        # pick some humans and make sure they cannot recover (for later checks)
        for i in range(N):
            humans[i].never_recovers = True
        # Infect one of the humans
        humans[np.random.randint(N)]._get_infected(1)

        city.humans = humans
        city.hd = {h.name: h for h in humans}
        city.initWorld()

        outfile = os.path.join(output_dir, "test1")

        env.process(city.run(SECONDS_PER_HOUR, outfile))

        for human in city.humans:
            env.process(human.run())

        with unittest.mock.patch.object(
                City, "run_app",
                new=fake_run_app) as mock:
            env.run(until=env.ts_initial+simulation_days*SECONDS_PER_DAY)

        # Check dead humans are removed from the residence
        assert sum([h.is_dead for h in city.humans]) == N - len(sr.residents)

        # Check there are some dead
        assert sum([h.is_dead for h in city.humans]) > 0

        # Check there are no humans that are infectious
        assert not any([h.is_infectious for h in city.humans])
Example #2
0
def simulate(
    n_people: int = 1000,
    init_fraction_sick: float = 0.01,
    start_time: datetime.datetime = datetime.datetime(2020, 2, 28, 0, 0),
    simulation_days: int = 30,
    outfile: typing.Optional[typing.AnyStr] = None,
    out_chunk_size: typing.Optional[int] = None,
    seed: int = 0,
    conf: typing.Optional[typing.Dict] = None,
    logfile: str = None,
):
    """
    Runs a simulation.

    Args:
        n_people (int, optional): population size in simulation. Defaults to 1000.
        init_fraction_sick (float, optional): population fraction initialized with Covid-19. Defaults to 0.01.
        start_time (datetime, optional):  Initial calendar date. Defaults to February 28, 2020.
        simulation_days (int, optional): Number of days to run the simulation. Defaults to 10.
        outfile (str, optional): Location to write logs. Defaults to None.
        out_chunk_size (int, optional): size of chunks to write in logs. Defaults to None.
        seed (int, optional): [description]. Defaults to 0.
        conf (dict): yaml configuration of the experiment.
        logfile (str): filepath where the console output and final tracked metrics will be logged. Prints to the console only if None.

    Returns:
        city (covid19sim.locations.city.City): The city object referencing people, locations, and the tracker post-simulation.
    """

    if conf is None:
        conf = {}

    conf["n_people"] = n_people
    conf["init_fraction_sick"] = init_fraction_sick
    conf["start_time"] = start_time
    conf["simulation_days"] = simulation_days
    conf["outfile"] = outfile
    conf["out_chunk_size"] = out_chunk_size
    conf["seed"] = seed
    conf['logfile'] = logfile

    # set days and mixing constants
    conf['_MEAN_DAILY_UNKNOWN_CONTACTS'] = conf['MEAN_DAILY_UNKNOWN_CONTACTS']
    conf['_ENVIRONMENTAL_INFECTION_KNOB'] = conf['ENVIRONMENTAL_INFECTION_KNOB']
    conf['_CURRENT_PREFERENTIAL_ATTACHMENT_FACTOR'] = conf['BEGIN_PREFERENTIAL_ATTACHMENT_FACTOR']
    start_time_offset_days = conf['COVID_START_DAY']
    intervention_start_days = conf['INTERVENTION_DAY']

    # start of COVID spread
    conf['COVID_SPREAD_START_TIME'] = start_time

    # start of intervention
    conf['INTERVENTION_START_TIME'] = None
    if intervention_start_days >= 0:
        conf['INTERVENTION_START_TIME'] = start_time + datetime.timedelta(days=intervention_start_days)

    # start of simulation without COVID
    start_time -= datetime.timedelta(days=start_time_offset_days)
    conf['SIMULATION_START_TIME'] = str(start_time)

    # adjust the simulation days
    conf['simulation_days'] += conf['COVID_START_DAY']
    simulation_days = conf['simulation_days']

    console_logger = ConsoleLogger(frequency=SECONDS_PER_DAY, logfile=logfile, conf=conf)
    logging.root.setLevel(getattr(logging, conf["LOGGING_LEVEL"].upper()))

    rng = np.random.RandomState(seed)
    env = Env(start_time)
    city_x_range = (0, 1000)
    city_y_range = (0, 1000)
    city = City(
        env, n_people, init_fraction_sick, rng, city_x_range, city_y_range, conf, logfile
    )

    # we might need to reset the state of the clusters held in shared memory (server or not)
    if conf.get("RESET_INFERENCE_SERVER", False):
        if conf.get("USE_INFERENCE_SERVER"):
            inference_frontend_address = conf.get("INFERENCE_SERVER_ADDRESS", None)
            print("requesting cluster reset from inference server...")
            from covid19sim.inference.server_utils import InferenceClient

            temporary_client = InferenceClient(
                server_address=inference_frontend_address
            )
            temporary_client.request_reset()
        else:
            from covid19sim.inference.heavy_jobs import DummyMemManager

            DummyMemManager.global_cluster_map = {}

    # Initiate city process, which runs every hour
    env.process(city.run(SECONDS_PER_HOUR, outfile))

    # initiate humans
    for human in city.humans:
        env.process(human.run())

    env.process(console_logger.run(env, city=city))

    # Run simulation until termination
    env.run(until=env.ts_initial + simulation_days * SECONDS_PER_DAY)

    return city