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 VirusUtilTest(unittest.TestCase): """ Test case to test the Virus class """ def setUp(self) -> None: logging.basicConfig( format='\n%(asctime)s:%(module)s:%(levelname)s:%(message)s', level=logging.DEBUG) logging.info('Testing virus util class.....') self.config_util = ConfigUtil('config/test_config.ini') self.k = self.config_util.getFloatValue("virus.stats", "k_value") self.r = self.config_util.getFloatValue("virus.stats", "r_value") self.size = 10 self.min_age = self.config_util.getIntegerValue( "people.stats", "min_age") self.max_age = self.config_util.getIntegerValue( "people.stats", "min_age") self.mortality_rate = self.config_util.getDictionary( "virus.stats", "mortality_rate") self.social_distance_per = self.config_util.getFloatValue( "people.stats", "social_distancing_percent") self.infection_range = self.config_util.getFloatValue( "virus.stats", "infection_range") self.recovery_time = self.config_util.getFloatValue( "virus.stats", "recovery_time") self.total_healthcare_capacity = self.size * ( self.config_util.getIntegerValue( "area.stats", "healthcare_capacity_ratio") / 100) self.mask_effectiveness = self.config_util.getDictionary( "virus.stats", "mask_effectiveness") self.speed = self.config_util.getFloatValue("people.stats", "speed") self.x_bounds = [0, 1] self.y_bounds = [0, 1] self.population = Population(self.size) 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.virus_util = Virus(1, self.recovery_time, self.total_healthcare_capacity) self.population.persons[:, 7] = 1 self.population.persons[:, 10] = 0.1 self.population.persons[:, 11] = 0.1 self.movement = Movement() def test_infect(self): """ Test to test the infect() method; compares the number of infected people before and after calling the infect method to see if healthy people within the infection range get infected """ before_infect_population = self.population.get_all_infected() self.population.persons = self.movement.update_persons( self.population.persons, self.size, self.speed, 1) self.infected_person = np.random.randint(0, self.size) self.population.persons[self.infected_person, index.g_value] = 3 self.population.set_infected_at(1, 0) self.population.persons[self.infected_person, index.social_distance] = 0 self.population.persons[self.infected_person, 9] = 1 _xbounds = np.array([[0, 1]] * self.size) _ybounds = np.array([[0, 1]] * self.size) for i in range(1, self.size): self.population.persons = self.movement.out_of_bounds( self.population.persons, _xbounds, _ybounds) self.population.persons = self.movement.update_persons( self.population.persons, self.size, self.speed, 1) self.population.persons = self.movement.update_pop( self.population.persons) self.population = self.virus_util.infect(self.population, i) self.assertTrue( len(before_infect_population[:, 9]) != len( self.population.get_all_infected()[:, 9]) and len(self.population.get_all_infected()[:, 9]) > 1, "Test failed, infect did not work") def test_die_or_immune(self): """ Test case to test the die_or_immune() method; check if the people passing the recovery time die or recover according to their mortality rate chance """ dead_frame_1 = self.population.get_all_dead() self.assertEqual(len(dead_frame_1), 0) self.population.persons = self.movement.update_persons( self.population.persons, self.size, self.speed, 1) self.infected_person = np.random.randint(0, self.size) self.population.persons[self.infected_person, index.g_value] = 3 self.population.set_infected_at(1, 0) self.population.persons[self.infected_person, index.social_distance] = 0 self.population.persons[self.infected_person, 9] = 1 _xbounds = np.array([[0, 1]] * self.size) _ybounds = np.array([[0, 1]] * self.size) for i in range(1, self.size): self.population.persons = self.movement.out_of_bounds( self.population.persons, _xbounds, _ybounds) self.population.persons = self.movement.update_persons( self.population.persons, self.size, self.speed, 1) self.population.persons = self.movement.update_pop( self.population.persons) self.population = self.virus_util.infect(self.population, i) self.population.persons[:, index.mortality_rate] = 1.00 self.virus_util.die_or_immune( self.population, int(self.population.get_all_infected()[0][0])) self.assertNotEqual(len(self.population.get_all_dead()), 0)
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)