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])
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