def __init__(self): super().__init__() plt.ioff() self.DPI = MainConfiguration().DPI self.ani = None self.fig = plt.figure(figsize=(self.width / self.DPI, self.height / self.DPI), dpi=self.DPI) self.fig.subplots_adjust(left=0, bottom=0.05, right=0.95, top=1, wspace=0, hspace=0) self.fig.patch.set_facecolor(Theme().default_bg) self.ax = self.fig.add_subplot() for spine in self.ax.spines.values(): spine.set_visible(False) self.days = 0 self.ax.set_facecolor(Theme().plot_bg) self.fig.set_edgecolor(Theme().plot_bg) self.ax.set_xticks([]) self.ax.set_yticks([]) self.last_core_radius = MainConfiguration().SUBJECT_SIZE * 2 self.last_infection_radius = ( MainConfiguration().SUBJECT_INFECTION_RADIUS + MainConfiguration().SUBJECT_SIZE) * 2 self.ax.plot() self.draw_standby_pattern()
def __init__(self, root=None): super().__init__() self.width, self.height = MainConfiguration().get_frame_dimensions_of( "GraphFrame") self.width = self.width - 3 * MainConfiguration().INNER_PADDING self.DPI = MainConfiguration().DPI self.frames = 0 self.init_log() self.y_axis_width = 50 self.are_chart_height = self.height - 20 self.fig = tk.Canvas(root, width=self.width - self.y_axis_width, height=self.are_chart_height, bg=self.theme.default_bg, highlightthickness=0, bd=0, relief='ridge') self.init_area_chart() self.y_axis = tk.Canvas(root, width=self.y_axis_width, height=self.height, bg=self.theme.default_bg, highlightthickness=0, bd=0, relief='ridge') self.init_y_axis()
def move_guys(self, timestamp): self.init_counts() new_cells = [set() for _ in range(self.cell_count)] self.r_rate = 0 frames_per_day = MainConfiguration().get_frames_per_day() count_r = False if timestamp % frames_per_day == 0: count_r = True for cell in self.subjects_in_cells: x_sorted = sorted( cell, key=lambda s: s.get_particle_component().position_x) for i, subject in enumerate(x_sorted): if subject.already_in_quarantine: subject.get_particle_component().update_location(timestamp) elif self.do_i_quarantine and ( subject.get_infection_status(timestamp) == InfectionStatuses.INFECTED or subject.on_my_way_to_quarantine): self._quarantine_handler.guide_subject_journey(subject) subject.get_particle_component().update_location_guided( timestamp) else: if not subject.travelling: chance = np.random.uniform(0, 1) if chance < MainConfiguration( ).COMMUNITIES_VISIT_CHANCE / 1000: self._community_handler.set_direction_to_destination( subject) subject.get_particle_component( ).update_location_guided(timestamp) else: self._infection_handler.one_to_many( subject, x_sorted, i, timestamp) subject.get_particle_component().update_location( timestamp) else: self._community_handler.guide_subject_journey( subject, timestamp) status_key = subject.get_infection_status(timestamp).name #self.positions_by_status[status_key][0].append(int(subject.get_particle_component().position_vector[0])) #self.positions_by_status[status_key][1].append(int(subject.get_particle_component().position_vector[1])) """self.positions_by_status[status_key] = \ np.concatenate( (self.positions_by_status[status_key], subject.get_particle_component().position_vector), axis=0)""" self.counts[status_key].add(subject) new_cells[subject.cell_id].add(subject) if count_r: self.r_rate += subject.estimate_total_infections(timestamp) if count_r: divisor = len(self.counts["INFECTED"]) + len( self.counts["ASYMPTOMATIC"]) self.r_rate = self.r_rate / divisor if divisor > 0 else 0 self.subjects_in_cells = new_cells
def build(self): # master grid components # self.components["MasterHeaderFrame"] = MasterHeaderFrame(self.window) frames = [ ScenarioFrame, ConstantsParametersFrame, LiveParametersFrame, GraphFrame, StatsFrame, SimulationFrame ] # ButtonsFrame has been removed # child components for f in frames: name = f.__name__ frame_settings = MainConfiguration().GRID_SETTINGS[name] parent = self.columns[frame_settings["column"]] self.components[name] = f(parent) self.components[name].grid() # The plot observing the simulation self.components["GraphFrame"].ViewBox.observe( self.components["SimulationFrame"].ViewBox) self.components["StatsFrame"].ViewBox.observe( self.components["SimulationFrame"].ViewBox) self.columns[0].grid(**MainConfiguration(). GRID_SETTINGS["MasterLeftFrame"]["grid_kwargs"]) self.columns[1].grid(**MainConfiguration(). GRID_SETTINGS["MasterRightFrame"]["grid_kwargs"]) self.add_tooltips()
def __init__(self, root): super().__init__(root) self.components = [] self.buttons = {} self.checkboxes = {} self.buttons_container = Frame(self) for i, tup in enumerate(MainConfiguration().CHECKBOX_CONFIG.items()): k, v = tup constructor = getattr(tk, v[0]) var = tk.BooleanVar(master=self, name=k, value=getattr(MainConfiguration(), k)) cb = constructor(self, variable=var, **v[1]) self.checkboxes[k] = cb self.components.append(cb) setattr(MainConfiguration(), k, var) cb.grid(row=0, column=i, sticky="we") for i, tup in enumerate(MainConfiguration().BUTTONS_CONFIG.items()): k, v = tup b = Button(self.buttons_container, **v) self.components.append(b) self.buttons[k] = b b.grid(row=0, column=i, sticky="we") self.buttons_container.grid(row=1, column=0, columnspan=3)
def populate_subjects(self): limit = int(MainConfiguration().SUBJECT_NUMBER / self.cell_count) remainder = MainConfiguration( ).SUBJECT_NUMBER - self.cell_count * limit for c in range(self.cell_count): self.populate_cell(c, limit) self.populate_cell(c, remainder)
def __init__(self, root, **kwargs): super().__init__(root, kwargs) help = Menu(self, tearoff=0) help.add_command(label="About", command=AboutWindow) var = BooleanVar() var.set(MainConfiguration().TOOLTIPS_ON) MainConfiguration().TOOLTIPS_ON = var help.add_checkbutton(label="Tooltips", variable=var) self.add_cascade(label="Help", menu=help)
def __init__(self): self.config = MainConfiguration() self.theme = Theme() self.subject_number = MainConfiguration().SUBJECT_NUMBER self.log = dict() self.default_keys = [ "INFECTED", "SUSCEPTIBLE", "IMMUNE", "ASYMPTOMATIC" ] self.frames = 0
def __init__(self, window=None): self.window = tk.TK() if not window else window self.components = {} self.columns = [ MasterLeftFrame(self.window), MasterRightFrame(self.window) ] self.tooltips_data_dict = MainConfiguration().get_tooltips_dict()
def __init__(self): self._infection_handler = AxisBased() self.contents = set() self._particle_radius = MainConfiguration().SUBJECT_SIZE self._infection_radius = MainConfiguration( ).SUBJECT_INFECTION_RADIUS + MainConfiguration().SUBJECT_SIZE self.counts = dict() self.count_keys = ["SUSCEPTIBLE", "ASYMPTOMATIC", "INFECTED", "IMMUNE"] self.positions_by_status = {v: [] for v in self.count_keys} self.init_counts() self.r_rate = 0
def __init__(self): super().__init__() self.cell_count = MainConfiguration( ).COMMUNITIES_COLUMNS * MainConfiguration().COMMUNITIES_ROWS self.cell_coordinates = MainConfiguration( ).get_community_cells_border_bounds() self.subjects_in_cells = [set() for _ in range(self.cell_count)] self.populate_subjects() self._community_handler = CommunityHandler() self.do_i_quarantine = MainConfiguration().QUARANTINE_MODE.get() if self.do_i_quarantine: self._quarantine_handler = QuarantineHandler()
def populate_subjects(self): constructor = Subject limit = MainConfiguration().SUBJECT_NUMBER for i in range(0, int(limit)): j = 0 position = AbstractContainerOfSubjects.get_evenly_spaced_coordinates( i, n_of_subjects=limit, bounds=MainConfiguration().get_particle_movement_bounds()) s = constructor(position=position) self.contents.add(s) self.add_subject_to_cell(s, self.subjects_in_cells)
def reset_to_defaults(self, event): scales = list( self.view_builder.get_component( "ConstantsParametersFrame").sliders.values()) scales.extend( list( self.view_builder.get_component( "LiveParametersFrame").sliders.values())) MainConfiguration().load_defaults() for scale in scales: attr_name = scale.get_my_name() attr_value = getattr(MainConfiguration(), attr_name) scale.set(attr_value)
def __init__(self, animated_object): self.funcs = {} self.paused = False self.stop = animated_object.reset self.pause = animated_object.pause self.resume = animated_object.resume self.start = animated_object.start self.funcs["Start"] = self.handle_start self.funcs[MainConfiguration().BUTTONS_CONFIG["START"] ["text"]] = self.handle_start self.funcs[MainConfiguration().BUTTONS_CONFIG["STOP"] ["text"]] = self.handle_clear self.running = False
def populate_cell(self, c, limit): constructor = Subject for i in range(limit): current_cell = self.subjects_in_cells[c] movement_boundaries = np.array(self.cell_coordinates[c]) movement_boundaries[:, 0] += MainConfiguration().SUBJECT_SIZE movement_boundaries[:, 1] -= MainConfiguration().SUBJECT_SIZE position = AbstractContainerOfSubjects\ .get_evenly_spaced_coordinates(i, n_of_subjects=limit, bounds=movement_boundaries) s = constructor(boundaries=movement_boundaries, position=position) s.cell_id = c current_cell.add(s) self.contents.add(s)
def update_location(self, timestamp: int) -> None: if self.last_location_update == timestamp: return self.last_location_update = timestamp self.position_vector = self.position_vector + self.velocity_vector * MainConfiguration( ).SUBJECT_VELOCITY_MULTIPLIER self.bounce_back_if_needed()
def showtip(self, text): "Display text in tooltip window" if MainConfiguration().TOOLTIPS_ON.get(): self.text = text if self.tipwindow or not self.text: return try: x, y, cx, cy = self.widget.bbox("insert") except: x, y, cx, cy = self.widget.bbox(ALL) y -= 100 x = x + self.widget.winfo_rootx() y = y + cy + self.widget.winfo_rooty() + 30 self.tipwindow = tw = Toplevel(self.widget) tw.wm_overrideredirect(1) tw.wm_geometry("+%d+%d" % (x, y)) label = Label(tw, text=self.text, justify=LEFT, anchor="e", bg=Theme().default_text, fg=Theme().default_bg, relief=SOLID, borderwidth=1, font=("Roboto", "12", "normal"), padx=3, pady=3) label.grid(row=0, column=0, sticky="nwse")
def __init__(self, after_function): super().__init__() MainConfiguration().MAIN_CANVAS_SIZE = [self.winfo_screenwidth(), self.winfo_screenheight()] self.geometry(MainConfiguration().get_main_canvas_size_tkinter()) self.wm_overrideredirect(1) bg_image = ImageTk.PhotoImage(Image.open(os.path.join(".", "assets", "virus_closeup.jpg"))) bg_container = Label(self, image=bg_image) app_title = Label(self, text="Pandemic simulator", font=("Roboto", 44), bg="white") app_subtitle = Label(self, text="version "+MainConfiguration().VERSION, font=("Roboto", 16), bg="white") bg_container.place(x=0, y=0, relwidth=2, relheight=2) app_title.place(relx=0.08, rely=0.15) app_subtitle.place(relx=0.08, rely=0.23) self.after(3000, after_function, self) mainloop()
def build(self): self.splash_screen.destroy() window = self window.title(MainConfiguration().APPLICATION_TITLE) window.configure({"bg": Theme().default_bg}) print( os.path.isfile(os.path.join(".", "assets", "pandemic_app_icon.png"))) icon = PhotoImage(master=window, file=os.path.join(".", "assets", "pandemic_app_icon.png")) window.iconphoto(True, icon) window.geometry(MainConfiguration().get_main_canvas_size_tkinter()) self.view_builder = TkinterPLTBuilder(window=window) self.view_builder.build() self.buttons_controller = Controllers.TkinterButtons( self.view_builder.get_component( "SimulationFrame").get_animated_object()) self.sliders_controller = Controllers.TkinterSimulationSettings() action = '<Button>' element = self.view_builder.get_component( "ScenarioFrame").buttons["RESET"] self.reset_settings_controller = Controllers.LambdaController() self.reset_settings_controller.bind_functions(element, action, self.reset_to_defaults) self.buttons_controller.bind_functions( self.view_builder.components["ScenarioFrame"].buttons) self.sliders_controller.bind_functions( self.view_builder.get_component( "ConstantsParametersFrame").sliders) self.sliders_controller.bind_functions( self.view_builder.get_component("LiveParametersFrame").sliders) m = MyMenu(window) window.configure(menu=m) window.protocol("WM_DELETE_WINDOW", MainWindow.handle_close_event)
def draw_standby_pattern(self): self.ax.set_xticks([]) self.ax.set_yticks([]) self.ax.set_xlim(0, self.width) self.ax.set_ylim(0, self.height) q_dims = MainConfiguration().get_simulation_canvas_total_bounds() self.ax.add_patch( patches.Rectangle( (q_dims[0, 0] + MainConfiguration().INNER_PADDING, q_dims[1, 0] + MainConfiguration().INNER_PADDING), q_dims[0, 1] - q_dims[0, 0] - 2 * MainConfiguration().INNER_PADDING, q_dims[1, 1] - q_dims[1, 0] - 2 * MainConfiguration().INNER_PADDING, facecolor="none", linewidth=1, edgecolor=Theme().infected, linestyle="--")) width = MainConfiguration().get_simulation_canvas_total_bounds()[0][1] self.ax.text(width - 330, 2 * MainConfiguration().INNER_PADDING, "Simulation area - standby".upper(), color=Theme().infected, fontsize="x-large", rotation=0)
def draw_quarantine_boundaries(ax): if MainConfiguration().QUARANTINE_MODE.get(): q_dims = MainConfiguration().get_quarantine_dimensions() inner_padding = MainConfiguration().INNER_PADDING ax.text(q_dims["x"] + inner_padding, q_dims["y"] + inner_padding, "QUARANTINE", color=Theme().infected, fontsize="large", rotation=90) ax.add_patch( patches.Rectangle((q_dims["x"], q_dims["y"]), q_dims["width"], q_dims["height"], facecolor="none", linewidth=1, edgecolor=Theme().infected, linestyle="--"))
def estimate_total_infections(self, timestamp: int) -> float: current_status = self.get_infection_status(timestamp) if current_status == InfectionStatuses.SUSCEPTIBLE or current_status == InfectionStatuses.IMMUNE: return 0 span = (timestamp - self._got_infected_at) if span == 0: span = 1 return self.total_sickness_time * MainConfiguration( ).get_frames_per_day() * self.n_infected / span
def draw_main_simulation_canvas_movement_bounds(ax): q_dims = MainConfiguration().get_particle_movement_border_bounds() ax.add_patch( patches.Rectangle((q_dims[0, 0], q_dims[1, 0]), q_dims[0, 1] - q_dims[0, 0], q_dims[1, 1] - q_dims[1, 0], facecolor="none", linewidth=1, edgecolor=Theme().infected, linestyle="--"))
def __init__(self): super().__init__() self.subjects_in_cells = [] self.rows = 6 self.columns = 12 self.cell_count = self.rows * self.columns self.init_cells() self.populate_subjects() self.do_i_quarantine = MainConfiguration().QUARANTINE_MODE.get() if self.do_i_quarantine: self._quarantine_handler = QuarantineHandler()
def reset(self): self._marker_radius = MainConfiguration().SUBJECT_SIZE self._infection_zone_radius = MainConfiguration( ).SUBJECT_INFECTION_RADIUS + MainConfiguration().SUBJECT_SIZE self.pause() if self.ani is not None: self.ani._stop() self.ani = None del self._box_of_particles #self.ani = None self._box_of_particles = DefaultContainer() if MainConfiguration().COMMUNITY_MODE.get() is not True\ else CommunitiesContainer() for x in self.fig.axes: x.clear() self.ax.set_xticks([]) self.ax.set_yticks([]) #self.start() self.notify(None) self.draw_standby_pattern() self.ax.plot() self.fig.canvas.draw()
def start(self): for x in self.fig.axes: x.clear() init_func = self.get_init_func() animation_function = self.get_animation_function() self.ani = FuncAnimation(self.fig, animation_function, init_func=init_func, interval=1000 / MainConfiguration().FRAMES_PER_SECOND, blit=True) return self.ani
def add_subject_to_cell(self, s: Subject, cells: list[set[Subject]] = None): subject_radius = MainConfiguration().SUBJECT_SIZE + MainConfiguration( ).SUBJECT_INFECTION_RADIUS left = int( (s.get_particle_component().position_vector[0] - subject_radius) / (MainConfiguration().MAIN_CANVAS_SIZE[0] / self.columns)) right = int( (s.get_particle_component().position_vector[0] + subject_radius) / (MainConfiguration().MAIN_CANVAS_SIZE[0] / self.columns)) bottom = int( (s.get_particle_component().position_vector[1] - subject_radius) / (MainConfiguration().MAIN_CANVAS_SIZE[1] / self.rows)) top = int( (s.get_particle_component().position_vector[1] + subject_radius) / (MainConfiguration().MAIN_CANVAS_SIZE[1] / self.rows)) top = top if top < self.rows else self.rows - 1 bottom = bottom if bottom >= 0 else 0 right = right if right < self.columns else self.columns - 1 left = left if left >= 0 else 0 try: cells[top][left].add(s) cells[top][right].add(s) cells[bottom][left].add(s) cells[bottom][right].add(s) except: print("Oooops")
def __init__(self, config=MainConfiguration()): super().__init__() self.config = config self.theme = Theme() self.width, self.height = config.get_frame_dimensions_of( "SimulationFrame") self._marker_radius = config.SUBJECT_SIZE self._infection_zone_radius = config.SUBJECT_INFECTION_RADIUS + config.SUBJECT_SIZE self._box_of_particles = CommunitiesContainer( ) if self.config.COMMUNITY_MODE.get() else DefaultContainer() self.previous_infected = 0 self.previous_r = 0
def update_stats(self, data): self.subject_number = MainConfiguration().SUBJECT_NUMBER if data: for k, v in data.items(): if k == "R_GROWTH": stop = True data = len(v) if isinstance(v, set) or isinstance(v, list) else v self.data_value[k].configure({"text": data}) else: for v in self.data_value.values(): v.configure({"text": "-"})
def update(self, new_data): if not new_data: self.subject_number = MainConfiguration().SUBJECT_NUMBER self.frames = 0 self.init_log() self.fig.delete("all") self.init_area_chart() else: self.frames += 1 self.update_logs(new_data) self.fig.delete("all") self.init_area_chart() self.redraw_verts()