diff --git a/config.py b/config.py index 1dada77..74adb28 100644 --- a/config.py +++ b/config.py @@ -3,12 +3,23 @@ ''' import numpy as np +import threading class config_error(Exception): pass class Configuration(): + + _instance_lock = threading.Lock() + + def __new__(cls, *args, **kwargs): + if not hasattr(Configuration,"_instance"): + with Configuration._instance_lock: + if not hasattr(Configuration,"_instance"): + Configuration._instance = object.__new__(cls) + return Configuration._instance + def __init__(self, *args, **kwargs): #simulation variables self.verbose = kwargs.get('verbose', True) #whether to print infections, recoveries and fatalities to the terminal diff --git a/environment.py b/environment.py index e48068b..6f84401 100644 --- a/environment.py +++ b/environment.py @@ -5,48 +5,37 @@ import numpy as np -def build_hospital(xmin, xmax, ymin, ymax, plt, addcross=True): - '''builds hospital - - Defines hospital and returns wall coordinates for - the hospital, as well as coordinates for a red cross - above it - - Keyword arguments - ----------------- - xmin : int or float - lower boundary on the x axis - - xmax : int or float - upper boundary on the x axis - - ymin : int or float - lower boundary on the y axis - - ymax : int or float - upper boundary on the y axis - - plt : matplotlib.pyplot object - the plot object to which to append the hospital drawing - if None, coordinates are returned - - Returns - ------- - None - ''' - - #plot walls - plt.plot([xmin, xmin], [ymin, ymax], color = 'black') - plt.plot([xmax, xmax], [ymin, ymax], color = 'black') - plt.plot([xmin, xmax], [ymin, ymin], color = 'black') - plt.plot([xmin, xmax], [ymax, ymax], color = 'black') +class environment: + def __init__(self, xmin, xmax, ymin, ymax, plt, addcross=True): + self.xmin = xmin + self.xmax = xmax + self.ymin = ymin + self.ymax = ymax + self.plt = plt + self.addcross = addcross - #plot red cross - if addcross: - xmiddle = xmin + ((xmax - xmin) / 2) - height = np.min([0.3, (ymax - ymin) / 5]) - plt.plot([xmiddle, xmiddle], [ymax, ymax + height], color='red', - linewidth = 3) - plt.plot([xmiddle - (height / 2), xmiddle + (height / 2)], - [ymax + (height / 2), ymax + (height / 2)], color='red', - linewidth = 3) \ No newline at end of file + def build_hospital(self): + # plot walls + self.plt.plot([self.xmin, self.xmin], [self.ymin, self.ymax], color='black') + self.plt.plot([self.xmax, self.xmax], [self.ymin, self.ymax], color='black') + self.plt.plot([self.xmin, self.xmax], [self.ymin, self.ymin], color='black') + self.plt.plot([self.xmin, self.xmax], [self.ymax, self.ymax], color='black') + + # plot red cross + if self.addcross: + xmiddle = self.xmin + ((self.xmax - self.xmin) / 2) + height = np.min([0.3, (self.ymax - self.ymin) / 5]) + self.plt.plot([xmiddle, xmiddle], [self.ymax, self.ymax + height], color='red', + linewidth=3) + self.plt.plot([xmiddle - (height / 2), xmiddle + (height / 2)], + [self.ymax + (height / 2), self.ymax + (height / 2)], color='red', + linewidth=3) + + def set(self, xmin, xmax, ymin, ymax, plt, addcross): + self.xmin = xmin + self.xmax = xmax + self.ymin = ymin + self.ymax = ymax + self.plt = plt + self.addcross = addcross + build_hospital() diff --git a/population.py b/population.py index 2879a8b..9741b2c 100644 --- a/population.py +++ b/population.py @@ -11,80 +11,40 @@ from motion import get_motion_parameters from utils import check_folder -def initialize_population(Config, mean_age=45, max_age=105, +class population(): + def __init__(self,Config,mean_age=45, max_age=105, xbounds=[0, 1], ybounds=[0, 1]): - '''initialized the population for the simulation - - the population matrix for this simulation has the following columns: - - 0 : unique ID - 1 : current x coordinate - 2 : current y coordinate - 3 : current heading in x direction - 4 : current heading in y direction - 5 : current speed - 6 : current state (0=healthy, 1=sick, 2=immune, 3=dead, 4=immune but infectious) - 7 : age - 8 : infected_since (frame the person got infected) - 9 : recovery vector (used in determining when someone recovers or dies) - 10 : in treatment - 11 : active destination (0 = random wander, 1, .. = destination matrix index) - 12 : at destination: whether arrived at destination (0=traveling, 1=arrived) - 13 : wander_range_x : wander ranges on x axis for those who are confined to a location - 14 : wander_range_y : wander ranges on y axis for those who are confined to a location + self.population = np.zeros((Config.pop_size, 15)) + # initalize unique IDs + self.population[:, 0] = [x for x in range(Config.pop_size)] - Keyword arguments - ----------------- - pop_size : int - the size of the population + # initialize random coordinates + self.population[:, 1] = np.random.uniform(low=xbounds[0] + 0.05, high=xbounds[1] - 0.05, + size=(Config.pop_size,)) + self.population[:, 2] = np.random.uniform(low=ybounds[0] + 0.05, high=ybounds[1] - 0.05, + size=(Config.pop_size,)) - mean_age : int - the mean age of the population. Age affects mortality chances + # initialize random headings -1 to 1 + self.population[:, 3] = np.random.normal(loc=0, scale=1 / 3, + size=(Config.pop_size,)) + self.population[:, 4] = np.random.normal(loc=0, scale=1 / 3, + size=(Config.pop_size,)) - max_age : int - the max age of the population - - xbounds : 2d array - lower and upper bounds of x axis - - ybounds : 2d array - lower and upper bounds of y axis - ''' + # initialize random speeds + self.population[:, 5] = np.random.normal(Config.speed, Config.speed / 3) - #initialize population matrix - population = np.zeros((Config.pop_size, 15)) + # initalize ages + self.std_age = (max_age - mean_age) / 3 + self.population[:, 7] = np.int32(np.random.normal(loc=mean_age, + scale=self.std_age, + size=(Config.pop_size,))) - #initalize unique IDs - population[:,0] = [x for x in range(Config.pop_size)] + self.population[:, 7] = np.clip(population[:, 7], a_min=0, + a_max=max_age) # clip those younger than 0 years - #initialize random coordinates - population[:,1] = np.random.uniform(low = xbounds[0] + 0.05, high = xbounds[1] - 0.05, - size = (Config.pop_size,)) - population[:,2] = np.random.uniform(low = ybounds[0] + 0.05, high = ybounds[1] - 0.05, - size=(Config.pop_size,)) + # build recovery_vector + self.population[:, 9] = np.random.normal(loc=0.5, scale=0.5 / 3, size=(Config.pop_size,)) - #initialize random headings -1 to 1 - population[:,3] = np.random.normal(loc = 0, scale = 1/3, - size=(Config.pop_size,)) - population[:,4] = np.random.normal(loc = 0, scale = 1/3, - size=(Config.pop_size,)) - - #initialize random speeds - population[:,5] = np.random.normal(Config.speed, Config.speed / 3) - - #initalize ages - std_age = (max_age - mean_age) / 3 - population[:,7] = np.int32(np.random.normal(loc = mean_age, - scale = std_age, - size=(Config.pop_size,))) - - population[:,7] = np.clip(population[:,7], a_min = 0, - a_max = max_age) #clip those younger than 0 years - - #build recovery_vector - population[:,9] = np.random.normal(loc = 0.5, scale = 0.5 / 3, size=(Config.pop_size,)) - - return population def initialize_destination_matrix(pop_size, total_destinations): @@ -234,4 +194,4 @@ def update_counts(self, population): else: self.susceptible.append(pop_size - (self.infectious[-1] + self.recovered[-1] + - self.fatalities[-1])) \ No newline at end of file + self.fatalities[-1])) diff --git a/simulation.py b/simulation.py index 9f6055f..8b06afd 100644 --- a/simulation.py +++ b/simulation.py @@ -168,7 +168,7 @@ def callback(self): self.population[0][10] = 1 - def run(self): + def run(self, simulation_ad): '''run simulation''' i = 0 @@ -200,6 +200,8 @@ def run(self): print('total infectious: %i' %len(self.population[(self.population[:,6] == 1) | (self.population[:,6] == 4)])) print('total unaffected: %i' %len(self.population[self.population[:,6] == 0])) + + simulation_ad.runad() def plot_sir(self, size=(6,3), include_fatalities=False, @@ -207,7 +209,17 @@ def plot_sir(self, size=(6,3), include_fatalities=False, plot_sir(self.Config, self.pop_tracker, size, include_fatalities, title) +class simulation_(): + def __init__(self): + pass + def run_(self): + pass +class adapter: + def __init__(self): + self.simulation_ = simulation_() + def runad(self): + self.simulation_.run_() if __name__ == '__main__': @@ -239,4 +251,5 @@ def plot_sir(self, size=(6,3), include_fatalities=False, #sim.population_init() #reinitialize population to enforce new roaming bounds #run, hold CTRL+C in terminal to end scenario early - sim.run() + adapter = adapter() + sim.run(adapter)