Пример #1
0
    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
Пример #2
0
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)