def infect(self, population: Population, frame): #Get the index of all the people who were infected in the previous step infected_idx = population.get_all_infected() persons = population.get_person() infected_counter = 0 for idx in infected_idx: infected_counter += 1 if (population.get_time_infected(int(idx[0]), frame) >= self.recovery_time): population = self.die_or_immune(population, int(idx[0])) x_bounds = [ persons[int(idx[0])][index.x_axis] - math.sqrt(self.infection_range), persons[int(idx[0])][index.x_axis] + math.sqrt(self.infection_range) ] y_bounds = [ persons[int(idx[0])][index.y_axis] - math.sqrt(self.infection_range), persons[int(idx[0])][index.y_axis] + math.sqrt(self.infection_range) ] # print(population.get_time_infected(int(idx[0]), frame)) tmp = self.find_nearby(persons, x_bounds, y_bounds) for i in tmp: chance = np.random.uniform(low=0.0001, high=1) if chance < persons[int(i)][index.susceptibility] and persons[ int(idx[0])][index.g_value] > 0: population.persons[int(i)][9] = 1 population.persons[int(i)][index.infected_by] = idx[0] population.set_infected_at(int(i), frame) population.persons[int(idx[0])][index.g_value] -= 1 if (len(population.persons[ population.persons[:, index.hospitalized] == 1]) < self.total_healthcare_capacity): population.persons[int(i)][index.hospitalized] = 1 return population
class MovementTest(unittest.TestCase): def setUp(self) -> None: self.pop = Population(size=10) logging.basicConfig( format='\n%(asctime)s:%(module)s:%(levelname)s:%(message)s', level=logging.DEBUG) logging.info('Testing Movements class') self.movement = Movement() def tearDown(self) -> None: self.pop = None self.movement = None pass def test_update_person(self) -> None: """ Tests update_person() method of Movement class and movements module to check data is getting updated randomly """ self.assertIsInstance( self.movement.update_persons(self.pop.get_person(), len(self.pop.get_person())), np.ndarray) self.pop.persons[:, idx.speed] = 0.1 self.assertNotEqual( self.movement.update_persons( self.pop.get_person(), len(self.pop.get_person()), heading_update_chance=1)[:, idx.y_dir].any(), 0) self.assertNotEqual( self.movement.update_persons( self.pop.get_person(), len(self.pop.get_person()), heading_update_chance=1)[:, idx.x_dir].any(), 0) self.assertNotEqual( self.movement.update_persons( self.pop.get_person(), len(self.pop.get_person()), heading_update_chance=1)[:, idx.speed].any(), 0.1) def test_out_of_bounds(self) -> None: """ Tests out_of_bounds() method of Movement class and movements module to check directions are updated accordingly to prevent a person from going out of bounds """ self.assertIsInstance( self.movement.out_of_bounds(self.pop.get_person(), np.array([[0, 1]] * 10), np.array([[0, 1]] * 10)), np.ndarray) self.pop.persons[:, idx.speed] = 1 self.pop.persons[:, idx.x_axis] = 1.1 self.pop.persons[:, idx.y_axis] = 1.1 self.pop.persons[:, idx.x_dir] = 0.5 self.pop.persons[:, idx.y_dir] = 0.5 self.assertLess( list( self.movement.out_of_bounds( self.pop.get_person(), np.array([[0, 1]] * 10), np.array([[0, 1]] * 10))[:, idx.x_dir]), [0] * 10) self.assertLess( list( self.movement.out_of_bounds( self.pop.get_person(), np.array([[0, 1]] * 10), np.array([[0, 1]] * 10))[:, idx.x_dir]), [0] * 10) self.pop.persons[:, idx.x_axis] = -0.1 self.pop.persons[:, idx.y_axis] = -0.1 self.pop.persons[:, idx.x_dir] = -0.5 self.pop.persons[:, idx.y_dir] = -0.5 self.assertGreater( list( self.movement.out_of_bounds( self.pop.get_person(), np.array([[0, 1]] * 10), np.array([[0, 1]] * 10))[:, idx.x_dir]), [0] * 10) self.assertGreater( list( self.movement.out_of_bounds( self.pop.get_person(), np.array([[0, 1]] * 10), np.array([[0, 1]] * 10))[:, idx.x_dir]), [0] * 10) def test_update_pop(self) -> None: """ Tests the update_pop() method of Movement class and movements module to check if the position of the population members are getting updated according to the arguments """ self.pop.persons[:, idx.x_dir] = 0.1 self.pop.persons[:, idx.y_dir] = 0.1 self.pop.persons[:, idx.speed] = 1 expectd_x = list(self.pop.persons[:, idx.x_axis] + 0.1) expectd_y = list(self.pop.persons[:, idx.y_axis] + 0.1) self.pop.persons = self.movement.update_pop(self.pop.persons) self.assertIsInstance(self.pop.get_person(), np.ndarray) self.assertListEqual(list(self.pop.get_x_axis()), expectd_x) self.assertListEqual(list(self.pop.get_y_axis()), expectd_y)
class PopulationUtil(object): """ Class representing the self.person.persons """ #_instance = Population() # def getInstance(): # return Population._instance def __init__(self, size: int, r: float, k: float, min_age: int, max_age: int, mortality_rate: int, social_distance_per: int, infection_range: float, recovery_time: int, total_healthcare_capacity: int, mask_effectiveness: dict, speed: float, social_distancing_at: int, mask_wearing_at: int): """ Constructor used for initializing the bound for the x axis, y axis, the k and R value for the particular population Parameters ---------- size : int Size of the population x_bounds : list The list containing the lower and upper bound for the x axis of the population map y_bounds : list The list containing the lower and upper bound for the y axis of the population map r : float Disease reproduction (R0) rate for the virus k : float The k value for the virus """ self.population = Population(size) self.virus = Virus(infection_range, recovery_time, total_healthcare_capacity) self.recovery_time = recovery_time self.total_healthcare_capacity = total_healthcare_capacity self.movement = Movement() self.size = size self.x_bounds = [0, 1] self.y_bounds = [0, 1] self.k = k self.r = r self.destinations = np.random.uniform(low=0, high=1, size=(self.size, 2)) self.min_age = min_age self.max_age = max_age self.mortality_rate = mortality_rate self.social_distance_per = social_distance_per self.mask_effectiveness = mask_effectiveness self.speed = speed self.persons = self.population.get_person() self.enforce_social_distance_at = social_distancing_at self.enforce_mask_wearing_at = mask_wearing_at self.social_distancing_enforced = False self.mask_wearing_enforced = False self.initialize_persons() def initialize_persons(self): """ Method which initializes the person list in the population and further calls another method to update other properties of the individual persons """ self.population.initialize_id(0, self.size) self.population.initialize_ages(self.min_age, self.max_age, self.size) self.population.initialize_positions(self.x_bounds, self.y_bounds, self.size) self.population.initialize_g_value(self.r, 1 / self.k, self.size) self.population.initialize_mortality_rate(self.size, self.mortality_rate) self.population.initialize_susceptibility() self.population.initialize_infected_by() self.persons[:, 7] = 1 self.persons[:, 10] = 0.1 self.persons[:, 11] = 0.1 #Update the destination each person is headed to and corresponding speed randomly self.persons = self.movement.update_persons(self.persons, self.size, self.speed, 1) self.infected_person = np.random.randint(0, self.size) self.persons[self.infected_person, index.g_value] = 3 self.population.set_infected_at(self.infected_person, 0) self.persons[self.infected_person, index.infected_by] = self.infected_person self.persons[self.infected_person, index.social_distance] = 0 self.persons[self.infected_person, 9] = 1 def move(self, frame): if frame == self.enforce_mask_wearing_at: self.population.initialize_mask_eff(self.size, self.mask_effectiveness) self.population.initialize_susceptibility() self.mask_wearing_enforced = True if frame == self.enforce_social_distance_at: self.population.initialize_social_distancing( self.social_distance_per) self.persons[self.infected_person, index.social_distance] = 0 self.social_distancing_enforced = True if frame >= self.enforce_social_distance_at and frame % 300 == 0 and self.enforce_social_distance_at >= 0: self.population.initialize_social_distancing( self.social_distance_per) _xbounds = np.array([[0, 1]] * self.size) _ybounds = np.array([[0, 1]] * self.size) self.persons = self.movement.out_of_bounds(self.persons, _xbounds, _ybounds) self.persons = self.movement.update_persons(self.persons, self.size, self.speed) self.persons = self.movement.update_pop(self.persons) self.population = self.virus.infect(self.population, frame)