class Plot: def __init__(self, win): pygame.init() self.win = win self.printr = Printr(self.win) self.set = Settings() self.c1 = self.set.ultra_light_grey self.c2 = self.set.grey self.c3 = self.set.dark_grey def draw(self, points): self.draw_axes() self.draw_x_axis_labels() self.draw_y_axis_labels() self.draw_observations(points) def draw_observations(self, points): for point in points: point.draw() def draw_axes(self): x, y = self.pixel_origin right = x + self.pixel_w top = y - self.pixel_h pygame.draw.line(self.win, self.c3, (x, y), (x, top), 2) pygame.draw.line(self.win, self.c3, (x, y), (right, y), 2) def draw_x_axis_labels(self): y = self.pixel_origin[1] for i in range(len(self.pixel_scale)): x = self.pixel_scale[i, 0] arr = self.arr_scale[i, 0] self.draw_axis_labels(x - 5, y + 10, arr, x) pygame.draw.circle(self.win, self.c1, (x, y + 1), 2, 0) def draw_y_axis_labels(self): x = self.pixel_origin[0] for i in range(len(self.pixel_scale)): y = self.pixel_scale[i, 1] arr = self.arr_scale[i, 1] self.draw_axis_labels(x - 35, y - 8, arr, y) pygame.draw.circle(self.win, self.set.grey, (x + 1, y), 2, 0) def draw_axis_labels(self, x, y, arr_label, pixel_label): self.printr.axis_label_printr(round(arr_label, 1), x, y, self.c1) self.printr.axis_label_printr(int(pixel_label), x, y + 12, self.set.blue) """ UTILITY """ def configure_scales(self, arr, px, w, h): self.arr_scale = arr self.pixel_scale = px self.pixel_origin = (px[0, 0], px[0, 1]) self.pixel_w = w self.pixel_h = h
def __init__(self, win, arr): pygame.init() self.win = win self.set = Settings() self.arr = arr self.printr = Printr(self.win, self.set) self.c1 = self.set.light_grey self.c2 = self.set.light_blue
def __init__(self, win): pygame.init() super().__init__() self.win = win self.printr = Printr(self.win, self.set) self.show_centroid = False self.c0 = self.set.grey self.c1 = self.set.light_grey ## Arr coord's self.c2 = self.set.light_blue ## Pixel coords
def __init__(self, win): pygame.init() self.win = win self.printr = Printr(self.win) self.set = Settings() self.c1 = self.set.ultra_light_grey self.c2 = self.set.grey self.c3 = self.set.dark_grey
class DrawLine: def __init__(self, win, arr): pygame.init() self.win = win self.set = Settings() self.arr = arr self.printr = Printr(self.win, self.set) self.c1 = self.set.light_grey self.c2 = self.set.light_blue def draw_line(self, pixel_points, arr_points): self.pixel_start, self.pixel_mid, self.pixel_end = pixel_points self.arr_start, self.arr_mid = arr_points pygame.draw.line(self.win, self.c1, tuple(self.pixel_start), tuple(self.pixel_end), 2) ## Draw mid circle pygame.draw.circle(self.win, self.c1, self.pixel_mid, 6, 2) pygame.draw.circle(self.win, self.set.white, self.pixel_mid, 4, 0) ## Draw start circle pygame.draw.circle(self.win, self.set.object2_538, self.pixel_start, 6, 0) self.draw_mid_coord() def draw_mid_coord(self): arr_x, arr_y = self.arr_mid pixel_x, pixel_y = self.pixel_mid x, y = self.pixel_mid arr_text = str((round(arr_x, 1), round(arr_y, 1))) pixel_text = str((x, y)) y -= 11 self.printr.coord_printr(arr_text, x + 15, y, self.c1) #self.printr.coord_printr(pixel_text, x+15, y+15, self.c2) def draw_intercepts(self, show_intercepts, intercepts, error): if show_intercepts: arr_intercepts, pixel_intercepts, pixels_of_array = intercepts for i in range(len(pixel_intercepts)): x, y1 = pixels_of_array[i] x, y2 = pixel_intercepts[i] pygame.draw.circle(self.win, self.set.red, (x, y2), 3, 0) pygame.draw.line(self.win, self.set.red, (x, y1), (x, y2), 1) y = int((y2 - y1) / 2 + y1) error_text = m.sqrt(error[i]) error_text = "error: " + str(round(error_text, 2)) self.printr.coord_printr(error_text, x + 15, y, self.set.red)
def __init__(self, win, pixels): pygame.init() self.win = win self.printr = Printr(self.win) self.set = Settings() self.pixels = pixels self.c0 = self.set.grey self.c1 = self.set.light_grey self.c2 = self.set.ultra_light_grey
def __init__(self): pygame.init() super().__init__() self.win_w, self.win_h = 1900, 950 self.win = pygame.display.set_mode((self.win_w, self.win_h), pygame.RESIZABLE) self.printr = Printr(self.win) self.nodes = [] self.queue = [] self.algo_wait = False ## Object flags self.hover_node = False self.edge_start_node = False self.algo_start_node = False self.algo_end_node = False
def __init__(self, win): super().__init__() pygame.init() self.win = win self.printr = Printr(self.win, self.set) self.drawline = DrawLine(self.win, self.arr) self.show_intercepts = False ## Agnostic units self.degrees = 30 self.slope = 1 ## Pixel units self.pixel_mid = [800, 400] self.pixel_length = self.pixel_w / 2 + 10 self.update_end_points() ## Array units self.arr_start = (1, 1) self.arr_mid = (1, 1) self.y_intercept = 1 self.update_RSS()
def __init__(self, win): super().__init__() pygame.init() self.win = win self.printr = Printr(self.win) self.draw = Draw(self.win, self.pixels) self.max_k = int(len(self.arr)) self.k = self.init_k() ## Flags self.moving = False self.draw_outer_circle = False self.survived = True ### Circle ### self.pixel_mid = [800, 400] self.pixel_radius = 110 #self.configure_draw() self.convert(True) ## Initialize self.arr_mid
class FitLine(Arr): def __init__(self, win): super().__init__() pygame.init() self.win = win self.printr = Printr(self.win, self.set) self.drawline = DrawLine(self.win, self.arr) self.show_intercepts = False ## Agnostic units self.degrees = 30 self.slope = 1 ## Pixel units self.pixel_mid = [800, 400] self.pixel_length = self.pixel_w / 2 + 10 self.update_end_points() ## Array units self.arr_start = (1, 1) self.arr_mid = (1, 1) self.y_intercept = 1 self.update_RSS() def update(self, moving, rotating, show_intercepts): self.move(moving) self.rotate(rotating) self.show_intercepts = show_intercepts def update_coords(self): ## If I move or rotate, recalculate everything ## self.update_end_points() self.convert() self.update_coefficients() self.update_RSS() def draw(self): ### Draw line ### pixel_points = [self.pixel_start, self.pixel_mid, self.pixel_end] arr_points = [self.arr_start, self.arr_mid] self.drawline.draw_line(pixel_points, arr_points) ### Draw intercepts on the line ### intercepts = [ self.arr_y_on_line, self.pixel_y_on_line, self.pixels_of_arr ] self.drawline.draw_intercepts(self.show_intercepts, intercepts, self.error) self.printr.print_instructions(self.b0, self.b1, self.SSE, self.y_intercept, self.slope, self.sse) """ UPDATES """ def move(self, moving): if moving: mx, my = pygame.mouse.get_rel() self.pixel_mid[0] += mx self.pixel_mid[1] += my self.update_coords() """ Rotating stuff """ def rotate(self, rotating): def wrap_angle(angle): if angle > 360: return 1 if angle < 0: return 360 return angle if rotating: self.degrees += rotating self.degrees = wrap_angle(self.degrees) self.update_coords() def update_end_points(self): """ Update the start and end points if line moves/rotates""" midx, midy = self.pixel_mid hyp = self.pixel_length theta = m.radians(self.degrees) ## Do trig opp = m.sin(theta) * hyp adj = m.cos(theta) * hyp ## Get start/end by applying deltas to mid coord start_x = int(midx - adj) start_y = int(midy + opp) end_x = int(midx + adj) end_y = int(midy - opp) # account for pygame negative stupidity self.pixel_start = [start_x, start_y] self.pixel_end = [end_x, end_y] def convert(self): self.arr_start = self.convert_to_arr(self.pixel_start) self.arr_mid = self.convert_to_arr(self.pixel_mid) def update_coefficients(self): ## Slope x1, y1 = self.arr_mid x2, y2 = self.arr_start if x2 - x1 != 0: self.slope = (y2 - y1) / (x2 - x1) ## Y intercept self.y_intercept = y2 - self.slope * x2 b0_mid = y1 - self.slope * x1 def update_RSS(self): self.arr_y_on_line = [] self.pixel_y_on_line = [] self.error = [] self.sse = 0 for coord in self.arr: x, y = coord y_on_line = self.y_intercept + x * self.slope ## line equation error = (y - y_on_line)**2 self.sse += error self.error.append(error) intercept_coord = [x, y_on_line] self.arr_y_on_line.append(intercept_coord) self.pixel_y_on_line.append( self.convert_to_pixels(intercept_coord))
class Algo(Arr): def __init__(self, win): super().__init__() pygame.init() self.win = win self.printr = Printr(self.win) self.draw = Draw(self.win, self.pixels) self.max_k = int(len(self.arr)) self.k = self.init_k() ## Flags self.moving = False self.draw_outer_circle = False self.survived = True ### Circle ### self.pixel_mid = [800, 400] self.pixel_radius = 110 #self.configure_draw() self.convert(True) ## Initialize self.arr_mid def configure_draw(self): self.draw.configure_scales(self.arr_scale, self.pixel_scale) def update(self, moving, draw_outer): self.moving = moving self.draw_outer_circle = draw_outer self.move() self.convert(self.moving) self.knn() def draw_things(self, win_w, win_h): self.draw.draw_plot(self.norm_arr) radius = 0 if self.draw_outer_circle: radius = self.pixel_radius self.draw.draw_circle(self.arr_mid, self.pixel_mid, radius, self.survived) self.printr.print_instructions(self.k, self.survived, win_w, win_h) """ UPDATES """ def move(self): if self.moving: mx, my = pygame.mouse.get_rel() ## Move circle if the mouse is anywhere on the graph if pygame.mouse.get_pos()[0] < self.pixel_origin[0] + self.pixel_w: self.pixel_mid[0] += mx self.pixel_mid[1] += my def convert(self, moving): if moving: self.norm_arr_mid = self.convert_pixel_to_norm_arr(self.pixel_mid) self.arr_mid = self.convert_norm_arr_to_arr(self.norm_arr_mid) def update_k(self, delta_k): new_k = self.k + delta_k if new_k > 0 and new_k < self.max_k: self.k = new_k """ KNN ENGINE """ def knn(self): ## Reset the distances and nn self.norm_arr[:, 3:] = 0 ## Calculate the distances and nn -- note, need to vectorize """ Need to vectorize this """ for i, coord in enumerate(self.norm_arr[:, :2]): euclid = np.sqrt(np.sum(np.square(self.norm_arr_mid - coord))) self.norm_arr[i:, 3] = euclid ## partition the array into smallest / largest K part = np.argpartition(self.norm_arr[:, 3], self.k) self.norm_arr[part[:self.k], 4] = 1 self.update_radius(self.norm_arr[part[:self.k]]) self.update_survived(self.norm_arr[part[:self.k]]) def update_survived(self, part): self.survived = True if part[:, 2].sum() < (len(part) / 2): self.survived = False def update_radius(self, part): ### Set radius as equal to length of furthest nn # Get index of the furthest nn coordinate in norm_arr mx = part[:, 3].max() index = np.where(self.norm_arr == mx)[0][0] # Get the pixel equivalent x1, y1 = self.pixels[index, :2] ## euclidian distance x2, y2 = self.pixel_mid self.pixel_radius = m.sqrt((x2 - x1)**2 + (y2 - y1)**2) """ Run once """ def init_k(self): ### k should be odd so you can make a clear prediction k = int(m.sqrt(self.max_k)) if k % 2 == 0: k += 1 return k
class Main(PygameBasics): def __init__(self): pygame.init() super().__init__() self.win_w, self.win_h = 1900, 950 self.win = pygame.display.set_mode((self.win_w, self.win_h), pygame.RESIZABLE) self.printr = Printr(self.win) self.nodes = [] self.queue = [] self.algo_wait = False ## Object flags self.hover_node = False self.edge_start_node = False self.algo_start_node = False self.algo_end_node = False """ EVENTS """ def left_click_events(self): pygame.mouse.get_rel() ## Reset pygame relative mouse position self.start_moving() self.make_node() def right_click_events(self): self.make_edge() def mouse_button_up_events(self): self.stop_moving() def keydown_events(self, event): if event.key == pygame.K_SPACE: self.make_node() if event.key == pygame.K_e: self.make_edge() if event.key == pygame.K_s: self.update_algo_start_node() if event.key == pygame.K_x: self.update_algo_end_node() if event.key == pygame.K_d: self.dijkstra() ## Tracer if event.key == pygame.K_p: for nb in self.algo_start_node.neighbours: print(nb.ID, nb.total_cost) if event.key == pygame.K_q: pygame.quit(), quit() def keyup_events(self, event): pass """ Conditional events """ def make_node(self): if not self.hover_node: id = self.set.get_node_id() mx, my = pygame.mouse.get_pos() node = Node(self.win, id, mx, my) self.nodes.append(node) def start_moving(self): for node in self.nodes: node.start_moving() def stop_moving(self): for node in self.nodes: node.stop_moving() def make_edge(self): """ Called by pressing 'e' """ ## If we haven't yet picked the start of our edge if not self.edge_start_node: if self.hover_node: self.hover_node.set_edge_start_node() self.edge_start_node = self.hover_node ## If we previously picked a start node, look for an end node else: if self.hover_node: self.edge_start_node.add_neighbour(self.hover_node) self.edge_start_node.cancel_edge_start() self.edge_start_node = False def update_algo_start_node(self): if self.hover_node: if self.algo_start_node: self.algo_start_node.cancel_algo_start() self.algo_start_node = False else: self.hover_node.set_algo_start() self.algo_start_node = self.hover_node def update_algo_end_node(self): if self.hover_node: if self.algo_end_node: self.algo_end_node.cancel_algo_end() self.algo_end_node = False else: self.hover_node.set_algo_end() self.algo_end_node = self.hover_node """ ******************** """ def dijkstra(self): if not self.algo_start_node: return self.queue = [(0, self.algo_start_node)] print("Before loop: ", self.queue) while self.queue: self.curr_node = self.queue.pop(0)[1] self.curr_node.set_visiting() for self.nb in self.curr_node.get_neighbours(): pygame.time.delay(1500) if self.nb.get_unvisited(): self.nb.set_looking_as_neighbour() trial_weight = self.curr_node.get_total_cost() + self.get_euclid(self.curr_node, self.nb) if trial_weight < self.nb.get_total_cost(): self.nb.set_total_cost(trial_weight) self.nb.set_parent(self.curr_node) self.queue.append( (trial_weight, self.nb)) self.queue.sort() ## Slow, but fine for less than a few thousand items self.draw() pygame.time.delay(1500) self.nb.cancel_looking_as_neighbour() self.draw() self.curr_node.set_unvisited() self.curr_node.cancel_visiting() def get_euclid(self, start, end): x1, y1 = start.get_coords() x2, y2 = end.get_coords() return math.sqrt( (x2-x1)**2 + (y2-y1)**2 ) """ UPDATES """ def updates(self): self.update_hovering() self.move() self.draw() def update_hovering(self): self.hover_node = False mx, my = pygame.mouse.get_pos() for node in self.nodes: node.update_hovering(mx, my) if node.get_hovering(): self.hover_node = node def move(self): for node in self.nodes: node.move() def draw(self): self.win.fill(self.set.background) self.draw_page_border() self.draw_working_area_border() self.printr.print_instructions(self.edge_start_node, self.hover_node, self.queue) self.draw_edges() self.draw_nodes() pygame.display.update() def draw_edges(self): c = self.set.grey for node in self.nodes: start_coord = node.get_coords() neighbours = node.get_neighbours() for end_node in neighbours: end_coord = end_node.get_coords() pygame.draw.line(self.win, c, start_coord, end_coord, 1) def draw_nodes(self): for node in self.nodes: node.draw() """ MAIN """ def main(self): while True: self.set.clock.tick(self.set.FPS) self.win.fill(self.set.background) self.events() self.updates()
class Draw: def __init__(self, win, pixels): pygame.init() self.win = win self.printr = Printr(self.win) self.set = Settings() self.pixels = pixels self.c0 = self.set.grey self.c1 = self.set.light_grey self.c2 = self.set.ultra_light_grey def draw_plot(self, norm_arr): self.draw_axes() self.draw_x_axis_labels() self.draw_y_axis_labels() self.draw_array(norm_arr) #self.draw_origin() """ DRAW PLOT """ def draw_array(self, norm_arr): for i, arr_coord in enumerate(norm_arr): x, y, survived, euclid, nn = arr_coord ## Last two cols track nn status px_coord = self.pixels[i] text = "X" if survived: text = "O" c = self.c1 if nn: c = self.set.red if survived: c = self.set.blue text = self.set.small_font.render(text, True, c) self.win.blit(text, px_coord) def draw_axes(self): x, y = self.false_axes_origin right = x + self.false_axis_w top = y - self.false_axis_h pygame.draw.line(self.win, self.c1, (x, y), (x, top), 2) pygame.draw.line(self.win, self.c1, (x, y), (right, y), 2) def draw_x_axis_labels(self): ### Draw x scale y = self.false_axes_origin[1] origin_x = self.pixel_origin[0] for i in range(len(self.pixel_scale)): pixel_x = self.pixel_scale[i, 0] ### Draw dot on axis pygame.draw.circle(self.win, self.set.grey, (pixel_x, y + 1), 2, 0) ### Draw labels offset_x = pixel_x - 12 arr_label = "£" + str(int(self.arr_scale[i, 0])) pixel_label = str(int(self.pixel_scale[i, 0])) self.printr.coord_printr(arr_label, offset_x, y + 10, self.c0) #self.printr.coord_printr(pixel_label, offset_x, y + 25, self.set.blue) def draw_y_axis_labels(self): ### Print y scale x = self.false_axes_origin[0] origin_y = self.pixel_origin[1] for i in range(len(self.pixel_scale)): pixel_y = self.pixel_scale[i, 1] ### Draw dot on axis pygame.draw.circle(self.win, self.set.grey, (x + 1, pixel_y), 2, 0) ### Draw labels offset_y = pixel_y - 8 arr_label = "Age: " + str(int(self.arr_scale[i, 1])) pixel_label = str(int(self.pixel_scale[i, 1])) self.printr.coord_printr(arr_label, x - 45, offset_y, self.c0) #self.printr.coord_printr(pixel_label, x - 40, offset_y + 12, self.set.blue) """ DRAW CIRCLE """ def draw_circle(self, arr_mid, pixel_mid, radius, survived): pygame.draw.circle(self.win, self.c2, pixel_mid, radius, 1) pygame.draw.circle(self.win, self.set.dark_grey, pixel_mid, 3, 0) self.draw_circle_coord(arr_mid, pixel_mid, radius, survived) def draw_circle_coord(self, arr_mid, pixel_mid, radius, survived): arr_x, arr_y = arr_mid px_x, px_y = pixel_mid arr_x = "Fare: £" + str(int(arr_x)) arr_y = "Age: " + str(int(arr_y)) survive_text = "Prediction: Die" if survived: survive_text = "Prediction: Live" px_coord = "(" + str(px_x) + ", " + str(px_y) + ")" y = px_y - 23 x = px_x + radius + 12 ## Draw white rect pygame.draw.rect(self.win, self.set.background, pygame.Rect(x - 7, y - 5, 92, 53), 0) self.printr.coord_printr(arr_x, x, y, self.set.grey) self.printr.coord_printr(arr_y, x, y + 15, self.set.grey) self.printr.coord_printr(survive_text, x, y + 30, self.set.grey) #self.printr.coord_printr(px_coord, x, y + 30, self.set.blue) """ Meh """ """ UTILITY """ def configure_scales(self, arr, px): self.arr_scale = arr self.pixel_scale = px self.pixel_origin = (px[0, 0], px[0, 1]) self.configure_false_axes() def configure_false_axes(self): buffer = 50 x, y = self.pixel_origin self.pixel_w = self.pixel_scale[-1, 0] - self.pixel_scale[0, 0] self.pixel_h = self.pixel_scale[0, 1] - self.pixel_scale[-1, 1] self.false_axes_origin = (x - buffer, y + buffer) self.false_axis_w = self.pixel_w + (2 * buffer) self.false_axis_h = self.pixel_h + (2 * buffer)
class Plot(Arr): def __init__(self, win): pygame.init() super().__init__() self.win = win self.printr = Printr(self.win, self.set) self.show_centroid = False self.c0 = self.set.grey self.c1 = self.set.light_grey ## Arr coord's self.c2 = self.set.light_blue ## Pixel coords def update(self, show_centroid): self.show_centroid = show_centroid def draw(self): self.draw_axes() self.draw_x_axes_labels() self.draw_y_axes_labels() self.draw_centroid() self.draw_array() def draw_array(self): for arr_coord in self.arr: px_coord = self.convert_to_pixels(arr_coord) pygame.draw.circle(self.win, self.c2, px_coord, 5, 0) x, y = px_coord arr_text = str((round(arr_coord[0], 1), round(arr_coord[1], 1))) pixel_text = str((x, y)) self.printr.coord_printr(arr_text, x - 35, y + 5, self.c2) def draw_centroid(self): if self.show_centroid: c = self.set.object2_538 x, y = self.arr_centroid text = "Centroid: " + str((round(x, 1), round(y, 1))) x, y = self.pixel_centroid ### Draw horizontal line, vertical lines pygame.draw.line(self.win, c, (self.pixel_x_min, y), (self.pixel_x_max, y), 1) pygame.draw.line(self.win, c, (x, self.pixel_y_max), (x, self.pixel_y_min), 1) ### Draw centroid circle and coordinates pygame.draw.circle(self.win, c, self.pixel_centroid, 5, 0) self.printr.coord_printr(text, x + 10, y - 18, self.c1) def draw_axes(self): c = self.set.light_grey x, y = self.false_axes_origin right = x + self.false_axis_w top = y - self.false_axis_h pygame.draw.line(self.win, self.c1, (x, y), (x, top), 2) pygame.draw.line(self.win, self.c1, (x, y), (right, y), 2) def draw_x_axes_labels(self): ### Draw x scale y = self.false_axes_origin[1] origin_x = self.pixel_origin[0] for i in range(self.x_num_labels): pixel_x = self.pixel_x_scale[i] ### Draw dot on axis pygame.draw.circle(self.win, self.set.grey, (pixel_x, y + 1), 2, 0) ### Draw labels offset_x = pixel_x - 12 arr_label = str(round(self.arr_x_scale[i], 1)) #pixel_label = str( int(self.pixel_x_scale[i]) ) self.printr.coord_printr(arr_label, offset_x, y + 10, self.c0) #self.printr.coord_printr(pixel_label, offset_x, y + 25, self.set.blue) def draw_y_axes_labels(self): ### Print y scale x = self.false_axes_origin[0] origin_y = self.pixel_origin[1] for i in range(self.y_num_labels): pixel_y = self.pixel_y_scale[i] ### Draw dot on axis pygame.draw.circle(self.win, self.set.grey, (x + 1, pixel_y), 2, 0) ### Draw labels offset_y = pixel_y - 9 arr_label = str(round(self.arr_y_scale[i], 1)) #pixel_label = str( int(self.pixel_y_scale[i]) ) self.printr.coord_printr(arr_label, x - 30, offset_y, self.c0)