def multi_draw(track_graphics: TrackGraphics, visitors, colours, threshold): assert len(colours) == len(visitors) assert threshold >= 1 min_x = visitors[0].min_x min_y = visitors[0].min_y granularity = visitors[0].granularity for yy in range(0, len(visitors[0].visits)): for xx in range(0, len(visitors[0].visits[0])): visits = [] for v in range(0, len(visitors)): visits.append(visitors[v].visits[yy][xx]) if sum(visits) >= threshold: target = max(visits) colour = "" for i, v in enumerate(visits): if v >= target: colour = colours[i] x = min_x + granularity * xx y = min_y + granularity * yy track_graphics.plot_box(x, y, x + granularity, y + granularity, colour)
def draw_visits(self, track_graphics: TrackGraphics, brightness: int, color_palette: ColorPalette): assert brightness in [-1, 0, 1, 2] visits, min_visits, max_visits = self.get_visits_and_scope_range(brightness) if not visits: return colour_multiplier = 255 / max_visits / max_visits * 2 if brightness == 1: colour_multiplier *= 2 elif brightness == 2: colour_multiplier *= 3.5 elif brightness == -1: colour_multiplier /= 2 for yy, visits in enumerate(visits): for xx, visit in enumerate(visits): if visit >= min_visits: x = self.min_x + self._granularity * xx y = self.min_y + self._granularity * yy data = min(1.0, 30/255 + colour_multiplier / 255 * visit * visit) colour = get_color_for_data(data, color_palette) track_graphics.plot_box(x, y, x + self._granularity, y + self._granularity, colour)
def draw_waypoints(self, track_graphics: TrackGraphics, colour: str, minor_size: int, major_size: int): assert major_size >= minor_size for (i, p) in enumerate(self._drawing_points): if i % 10 == 0: track_graphics.plot_dot(p.middle, major_size, colour) else: track_graphics.plot_dot(p.middle, minor_size, colour)
def draw_track_edges(self, track_graphics: TrackGraphics, colour: str): previous_left = self._drawing_points[-1].left previous_right = self._drawing_points[-1].right for p in self._drawing_points: track_graphics.plot_line(previous_left, p.left, 3, colour) previous_left = p.left track_graphics.plot_line(previous_right, p.right, 3, colour) previous_right = p.right
def draw_sector_labels(self, track_graphics: TrackGraphics, colour: str): for name in self.get_all_sector_names(): (start, finish) = self.get_sector_start_and_finish(name) label_waypoint = int((start + finish) / 2) point = self._drawing_points[label_waypoint].middle if self._is_vertical_at_waypoint(label_waypoint): track_graphics.plot_text(point, name, 20, colour, 14, 0) else: track_graphics.plot_text(point, name, 20, colour, 0, -14)
def draw_grid(self, track_graphics: TrackGraphics, colour: str): x = self._min_x while x < self._max_x: track_graphics.plot_line((x, self._min_y), (x, self._max_y), 1, colour) x += 1 y = self._min_y while y < self._max_y: track_graphics.plot_line((self._min_x, y), (self._max_x, y), 1, colour) y += 1
def draw(self, track_graphics: TrackGraphics, track_drawing_points, track_width): previous_point1 = None previous_point2 = None for p in self.route_points: route_point1 = get_exact_point_(track_drawing_points, track_width, p.waypoint_id, p.side1, p.distance1) route_point2 = get_exact_point_(track_drawing_points, track_width, p.waypoint_id, p.side2, p.distance2) if previous_point1: colour = p.colour if not colour: colour = self.default_colour track_graphics.plot_polygon([previous_point1, previous_point2, route_point2, route_point1], colour) previous_point1 = route_point1 previous_point2 = route_point2
def draw_section_highlight(self, track_graphics: TrackGraphics, colour: str, start: int, finish: int): previous_left = self._drawing_points[start].left_outer previous_right = self._drawing_points[start].right_outer if finish >= start: highlight_points = self._drawing_points[start + 1:finish + 1] else: highlight_points = self._drawing_points[ start:] + self._drawing_points[:finish + 1] for p in highlight_points: track_graphics.plot_line(previous_left, p.left_outer, 5, colour) previous_left = p.left_outer track_graphics.plot_line(previous_right, p.right_outer, 5, colour) previous_right = p.right_outer
def draw_waypoint_labels(self, track_graphics: TrackGraphics, colour: str, font_size: int): last_label_position = None for (i, p) in enumerate(self._drawing_points[:-2]): if self._is_vertical_at_waypoint(i): label = track_graphics.plot_text(p.middle, str(i), font_size, colour, -1.5 * font_size, 0.0) else: label = track_graphics.plot_text(p.middle, str(i), font_size, colour, 0.0, 1.5 * font_size) label_position = track_graphics.get_widget_position(label) if last_label_position is None: last_label_position = label_position elif geometry.get_distance_between_points( last_label_position, label_position) < 2.5 * font_size: track_graphics.delete_widget(label) else: last_label_position = label_position
def draw_brightness_statistic(self, track_graphics: TrackGraphics, adjust_brightness: int, color_palette: ColorPalette, visits_heatmap): assert adjust_brightness in [-1, 0, 1, 2] if adjust_brightness == 1: multiplier = 1.1 elif adjust_brightness == 2: multiplier = 1.2 elif adjust_brightness == -1: multiplier = 0.9 else: multiplier = 1.0 (stats, _, _) = self._get_stats_array(np.median, adjust_brightness, visits_heatmap) for yy, stats in enumerate(stats): for xx, stat in enumerate(stats): if not math.isnan(stat): x = self.min_x + self._granularity * xx y = self.min_y + self._granularity * yy colour = get_color_for_data(max(0.1, min(1, stat * multiplier)), color_palette) track_graphics.plot_box(x, y, x + self._granularity, y + self._granularity, colour)
def draw_statistic(self, track_graphics: TrackGraphics, brightness: int, color_palette: ColorPalette, visits_heatmap, forced_max_stat=-1, forced_min_stat=-1): assert brightness in [-1, 0, 1, 2] (stats, min_stat, max_stat) = self._get_stats_array(np.median, brightness, visits_heatmap) if max_stat == 0: return if forced_max_stat > 0: max_stat = forced_max_stat if forced_min_stat > 0: min_stat = forced_min_stat if brightness == 1: max_stat *= 0.93 elif brightness == 2: max_stat *= 0.85 min_stat *= 0.95 elif brightness == -1: min_stat *= 1.1 if min_stat >= max_stat: min_stat = 0.99 * max_stat stat_range = max_stat - min_stat for yy, stats in enumerate(stats): for xx, stat in enumerate(stats): if not math.isnan(stat): x = self.min_x + self._granularity * xx y = self.min_y + self._granularity * yy gap_from_best = max_stat - stat data = max(0.1, min(1, 1 - 0.9 * gap_from_best / stat_range)) colour = get_color_for_data(data, color_palette) track_graphics.plot_box(x, y, x + self._granularity, y + self._granularity, colour)
def draw(self, track_graphics: TrackGraphics, brightness: int, color_palette: ColorPalette): # self.print_debug() assert brightness in [-1, 0, 1, 2] max_visits = max(max(x) for x in self.visits) if max_visits == 0: return colour_multiplier = 255 / max_visits / max_visits * 2 min_visits = max_visits / 10 if brightness == 1: colour_multiplier *= 2 min_visits /= 2 elif brightness == 2: colour_multiplier *= 3.5 min_visits /= 3.5 elif brightness == -1: colour_multiplier /= 2 min_visits *= 1.5 for yy, visits in enumerate(self.visits): for xx, visit in enumerate(visits): if visit >= min_visits: x = self.min_x + self.granularity * xx y = self.min_y + self.granularity * yy data = min( 1.0, 30 / 255 + colour_multiplier / 255 * visit * visit) colour = get_color_for_data(data, color_palette) track_graphics.plot_box(x, y, x + self.granularity, y + self.granularity, colour)
def OLD_draw_for_route_plotting(self, track_graphics: TrackGraphics, colour): track_graphics.plot_line(self.drawing_points[0].left, self.drawing_points[0].right, 3, colour) self.draw_track_edges(track_graphics, colour) for (i, p) in enumerate(self.drawing_points): if i % 10 == 0: size = 4 else: size = 2 track_graphics.plot_dot(p.middle, size, colour) if p.is_divider: track_graphics.plot_line(p.left, p.right, 3, colour) if p.is_center: # self._plot_label(track_graphics, p.middle, p.section, 30) pass # NOT WORKING VERY WELL AT CHOOSING GOOD POSITION
class MainApp(tk.Frame): def __init__(self, root): # # Basic frame initialization # super().__init__(root) # # Initialise all internal settings not related to UI components # self.tracks = get_all_tracks() self.current_track = self.tracks["FS_June2020"] self.log = None self.filtered_episodes = None self.episode_filter = EpisodeFilter() self.view_manager = ViewManager() self.action_space_filter = ActionSpaceFilter() # # Go to the correct directory where the log files are located, ready to load or save them there # chdir(config.LOG_DIRECTORY) # # Create the high level UI components (the canvas, control frame and status frame) # self.status_frame = StatusFrame(self) self.track_canvas = tk.Canvas(self, bg="black", width=700, height=500) self.track_canvas.bind("<Configure>", self.redraw) self.track_canvas.bind("<Button-1>", self.left_button_pressed_on_track_canvas) self.track_canvas.bind("<Left>", self.left_or_down_key_pressed_on_track_canvas) self.track_canvas.bind("<Up>", self.right_or_up_key_pressed_on_track_canvas) self.track_canvas.bind("<Right>", self.right_or_up_key_pressed_on_track_canvas) self.track_canvas.bind("<Down>", self.left_or_down_key_pressed_on_track_canvas) self.control_frame = tk.Frame(root) # # Create the various "analyzers" and let them take control of the contents of the high level UI components # self.track_graphics = TrackGraphics(self.track_canvas) self.analyze_route = AnalyzeRoute(self.redraw, self.track_graphics, self.control_frame) self.analyze_convergence = AnalyzeConvergence(self.redraw, self.track_graphics, self.control_frame) self.analyzer = self.analyze_route self.all_analyzers = [self.analyze_route, self.analyze_convergence] self.analyzer.set_track(self.current_track) self.analyzer.take_control() if ss.SHOW_SS: self.secret_analyzers = ss.get_secret_analyzers( self.redraw, self.track_graphics, self.control_frame) else: self.secret_analyzers = None # # Define the layout of the high level UI components # self.status_frame.pack(side=tk.BOTTOM) self.track_canvas.pack(fill=tk.BOTH, expand=True, side=tk.LEFT) self.control_frame.pack(side=tk.RIGHT) self.pack(fill=tk.BOTH, expand=True) # # Configure the rest of the application window and then make it appear # self.master.title("Deep Racer Guru") self.menu_bar = MenuBar(root, self, False) # # All done, so display main window now # self.update() def menu_callback_switch_track(self, new_track): self.log = None self.filtered_episodes = None self.status_frame.reset() self.current_track = new_track for v in self.all_analyzers: v.set_track(new_track) self.analyzer.set_track(self.current_track) self.analyzer.set_filtered_episodes(self.filtered_episodes) self.redraw() def switch_analyzer(self, new_analyzer): self.analyzer = new_analyzer self.analyzer.set_track(self.current_track) self.analyzer.set_filtered_episodes(self.filtered_episodes) self.analyzer.take_control() self.redraw() def menu_callback_analyze_convergence(self): self.switch_analyzer(self.analyze_convergence) def menu_callback_analyze_route(self): self.switch_analyzer(self.analyze_route) def callback_open_this_file(self, file_name): # print("Loading ...", file_name) redraw_menu_afterwards = not self.log self.visitor_map = None self.log = Log() self.log.load_all(file_name) # Commented out now for public usage # self.log.log_meta.display_for_debug() # print("Loaded", file_name) self.status_frame.change_model_name(self.log.log_meta.model_name) self.apply_new_action_space() self.episode_filter.set_all_episodes(self.log.episodes) self.reapply_episode_filter() if redraw_menu_afterwards: self.menu_bar = MenuBar(root, self, True) self.update() def apply_new_action_space(self): self.action_space_filter.set_new_action_space( self.log.log_meta.action_space) for v in self.all_analyzers: v.set_action_space(self.log.log_meta.action_space) v.set_action_space_filter(self.action_space_filter) def reapply_action_space_filter(self): for v in self.all_analyzers: v.set_action_space_filter(self.action_space_filter) self.redraw() def reapply_episode_filter(self): self.filtered_episodes = self.episode_filter.get_filtered_episodes() for v in self.all_analyzers: v.set_filtered_episodes(self.filtered_episodes) self.status_frame.change_episodes(len(self.log.episodes), len(self.filtered_episodes)) self.analyzer.set_filtered_episodes(self.filtered_episodes) self.redraw() def redraw(self, event=None): self.view_manager.redraw(self.current_track, self.track_graphics, self.analyzer) def left_button_pressed_on_track_canvas(self, event): track_point = self.track_graphics.get_real_point_for_widget_location( event.x, event.y) self.analyzer.left_button_pressed(track_point) self.track_canvas.focus_set( ) # Set focus so we will now receive keyboard events too def right_or_up_key_pressed_on_track_canvas(self, event): track_point = self.track_graphics.get_real_point_for_widget_location( event.x, event.y) self.analyzer.go_forwards(track_point) def left_or_down_key_pressed_on_track_canvas(self, event): track_point = self.track_graphics.get_real_point_for_widget_location( event.x, event.y) self.analyzer.go_backwards(track_point) def menu_callback_episodes_all(self): self.episode_filter.reset() self.reapply_episode_filter() def menu_callback_episodes_all_from_start(self): self.episode_filter.reset() self.episode_filter.set_filter_from_start_line(True) self.reapply_episode_filter() def menu_callback_episodes_complete_laps(self): self.episode_filter.reset() self.episode_filter.set_filter_complete_laps(True) self.reapply_episode_filter() def menu_callback_episodes_fast_laps(self): es = self.log.log_meta.episode_stats target_steps = round((es.average_steps + es.best_steps) / 2) self.episode_filter.reset() self.episode_filter.set_filter_complete_laps(True) self.episode_filter.set_filter_max_steps(target_steps) self.reapply_episode_filter() def menu_callback_episodes_complete_laps_from_start(self): self.episode_filter.reset() self.episode_filter.set_filter_complete_laps(True) self.episode_filter.set_filter_from_start_line(True) self.reapply_episode_filter() def menu_callback_episodes_min_percent_10(self): self.episode_filter.reset() self.episode_filter.set_filter_min_percent(10) self.reapply_episode_filter() def menu_callback_episodes_min_percent_25(self): self.episode_filter.reset() self.episode_filter.set_filter_min_percent(25) self.reapply_episode_filter() def menu_callback_episodes_min_percent_33(self): self.episode_filter.reset() self.episode_filter.set_filter_min_percent(33) self.reapply_episode_filter() def menu_callback_episodes_min_percent_50(self): self.episode_filter.reset() self.episode_filter.set_filter_min_percent(50) self.reapply_episode_filter() def menu_callback_actions_all(self): self.action_space_filter.set_filter_all() self.reapply_action_space_filter() def menu_callback_actions_high_speed(self): self.action_space_filter.set_filter_high_speed() self.reapply_action_space_filter() def menu_callback_actions_medium_speed(self): self.action_space_filter.set_filter_medium_speed() self.reapply_action_space_filter() def menu_callback_actions_low_speed(self): self.action_space_filter.set_filter_low_speed() self.reapply_action_space_filter() def menu_callback_actions_straight(self): self.action_space_filter.set_filter_straight() self.reapply_action_space_filter() def menu_callback_grid_front(self): self.view_manager.set_grid_front() self.redraw() def menu_callback_grid_back(self): self.view_manager.set_grid_back() self.redraw() def menu_callback_grid_off(self): self.view_manager.set_grid_off() self.redraw() def menu_callback_track_front(self): self.view_manager.set_track_front() self.redraw() def menu_callback_track_back(self): self.view_manager.set_track_back() self.redraw() def menu_callback_track_grey(self): self.view_manager.set_track_colour_grey() self.redraw() def menu_callback_track_blue(self): self.view_manager.set_track_colour_blue() self.redraw() def menu_callback_waypoints_large(self): self.view_manager.set_waypoint_sizes_large() self.redraw() def menu_callback_waypoints_small(self): self.view_manager.set_waypoint_sizes_small() self.redraw() def menu_callback_waypoints_micro(self): self.view_manager.set_waypoint_sizes_micro() self.redraw() def menu_callback_waypoints_off(self): self.view_manager.set_waypoints_off() self.redraw() def menu_callback_analyze_front(self): self.view_manager.set_analyze_front() self.redraw() def menu_callback_analyze_back(self): self.view_manager.set_analyze_back() self.redraw()
def __init__(self, root): # # Basic frame initialization # super().__init__(root) # # Initialise all internal settings not related to UI components # self.tracks = get_all_tracks() self.current_track = self.tracks["FS_June2020"] self.log = None self.filtered_episodes = None self.episode_filter = EpisodeFilter() self.view_manager = ViewManager() self.action_space_filter = ActionSpaceFilter() # # Go to the correct directory where the log files are located, ready to load or save them there # chdir(config.LOG_DIRECTORY) # # Create the high level UI components (the canvas, control frame and status frame) # self.status_frame = StatusFrame(self) self.track_canvas = tk.Canvas(self, bg="black", width=700, height=500) self.track_canvas.bind("<Configure>", self.redraw) self.track_canvas.bind("<Button-1>", self.left_button_pressed_on_track_canvas) self.track_canvas.bind("<Left>", self.left_or_down_key_pressed_on_track_canvas) self.track_canvas.bind("<Up>", self.right_or_up_key_pressed_on_track_canvas) self.track_canvas.bind("<Right>", self.right_or_up_key_pressed_on_track_canvas) self.track_canvas.bind("<Down>", self.left_or_down_key_pressed_on_track_canvas) self.control_frame = tk.Frame(root) # # Create the various "analyzers" and let them take control of the contents of the high level UI components # self.track_graphics = TrackGraphics(self.track_canvas) self.analyze_route = AnalyzeRoute(self.redraw, self.track_graphics, self.control_frame) self.analyze_convergence = AnalyzeConvergence(self.redraw, self.track_graphics, self.control_frame) self.analyzer = self.analyze_route self.all_analyzers = [self.analyze_route, self.analyze_convergence] self.analyzer.set_track(self.current_track) self.analyzer.take_control() if ss.SHOW_SS: self.secret_analyzers = ss.get_secret_analyzers( self.redraw, self.track_graphics, self.control_frame) else: self.secret_analyzers = None # # Define the layout of the high level UI components # self.status_frame.pack(side=tk.BOTTOM) self.track_canvas.pack(fill=tk.BOTH, expand=True, side=tk.LEFT) self.control_frame.pack(side=tk.RIGHT) self.pack(fill=tk.BOTH, expand=True) # # Configure the rest of the application window and then make it appear # self.master.title("Deep Racer Guru") self.menu_bar = MenuBar(root, self, False) # # All done, so display main window now # self.update()
def draw_at_point_(self, track_graphics: TrackGraphics, point): track_graphics.plot_dot(point, 4, self.colour)
def draw_at_point_(self, track_graphics: TrackGraphics, point): track_graphics.plot_dot(point, 3, self.colour) track_graphics.plot_angle_line(point, self.bearing, self.length, 2, self.colour) track_graphics.plot_angle_line(point, self.bearing + self.angular_width / 2, self.length, 1, self.colour) track_graphics.plot_angle_line(point, self.bearing - self.angular_width / 2, self.length, 1, self.colour)
def draw(self, track_graphics: TrackGraphics, track_drawing_points, track_width): track_graphics.plot_dot((self.x, self.y), 4, self.colour)
def draw_starting_line(self, track_graphics: TrackGraphics, colour: str): track_graphics.plot_line(self._drawing_points[0].left, self._drawing_points[0].right, 3, colour)
def draw_sector_dividers(self, track_graphics: TrackGraphics, colour: str): for p in self._drawing_points: if p.is_divider: track_graphics.plot_line(p.left, p.right, 3, colour, (4, 2))
def configure_track_graphics(self, track_graphics: TrackGraphics): track_graphics.set_track_area(self.min_x - DISPLAY_BORDER, self.min_y - DISPLAY_BORDER, self.max_x + DISPLAY_BORDER, self.max_y + DISPLAY_BORDER)
class MainApp(tk.Frame): def __init__(self, root): # # Basic frame initialization # super().__init__(root) # # First of all, get config manager up and running so we have access to any settings that it manages for us # self._config_manager = ConfigManager() # # Initialise all internal settings not related to UI components # self.tracks = get_all_tracks() self.current_track = self.tracks[ self._config_manager.get_last_open_track()] self.log = None self.filtered_episodes = None self.episode_filter = EpisodeFilter() self.view_manager = ViewManager() self.action_space_filter = ActionSpaceFilter() self.episode_selector = EpisodeSelector() self.sector_filter = "" # # Create the simple high level UI components (the canvas, control frame and status frame) # self.status_frame = StatusFrame(self) self.track_canvas = tk.Canvas(self, bg="black", width=DEFAULT_CANVAS_WIDTH, height=DEFAULT_CANVAS_HEIGHT) self.track_canvas.bind("<Configure>", self.redraw) self.track_canvas.bind("<Button-3>", self.right_button_pressed_on_track_canvas) self.track_canvas.bind("<Left>", self.left_or_down_key_pressed_on_track_canvas) self.track_canvas.bind("<Up>", self.right_or_up_key_pressed_on_track_canvas) self.track_canvas.bind("<Right>", self.right_or_up_key_pressed_on_track_canvas) self.track_canvas.bind("<Down>", self.left_or_down_key_pressed_on_track_canvas) self.track_canvas.bind("<Button-1>", self.left_button_pressed_on_track_canvas) self.track_canvas.bind("<B1-Motion>", self.left_button_moved_on_track_canvas) self.track_canvas.bind("<ButtonRelease-1>", self.left_button_released_on_track_canvas) self.control_frame = tk.Frame(root) self.inner_control_frame = tk.Frame(self.control_frame) # # Initialise variables to control the right mouse zoom-in feature over a canvas # self.zoom_start_x = None self.zoom_start_y = None self.zoom_widget = None # # Create the graph plotting UI components using the magic of matplotlib # graph_figure = Figure(figsize=(5, 4), dpi=100) matplotlib_canvas = FigureCanvasTkAgg(graph_figure, master=self) self.graph_canvas = matplotlib_canvas.get_tk_widget() self.graph_canvas.config(width=DEFAULT_CANVAS_WIDTH, height=DEFAULT_CANVAS_HEIGHT) # # Initialize the "please wait" widget in the middle of each canvas # self.please_wait_track = PleaseWait(root, self.track_canvas) self.please_wait_graph = PleaseWait(root, self.graph_canvas) self.please_wait = self.please_wait_track # # Create the various "analyzers" and let them take control of the contents of the high level UI components # self.track_graphics = TrackGraphics(self.track_canvas) self.current_track.configure_track_graphics(self.track_graphics) self.analyze_route = AnalyzeRoute(self.redraw, self.track_graphics, self.inner_control_frame, self.episode_selector, self._config_manager) self.analyze_track_heatmap = AnalyzeHeatmap(self.redraw, self.track_graphics, self.inner_control_frame, self.please_wait_track, self._config_manager) self.analyze_exit_points = AnalyzeExitPoints(self.redraw, self.track_graphics, self.inner_control_frame) self.analyze_race = AnalyzeRace(self.redraw, self.track_graphics, self.inner_control_frame) self.analyze_curve_fitting = AnalyzeCurveFitting( self.redraw, self.track_graphics, self.inner_control_frame) self.analyze_straight_fitting = AnalyzeStraightFitting( self.redraw, self.track_graphics, self.inner_control_frame) self.analyze_training_progress = AnalyzeTrainingProgress( self.redraw, matplotlib_canvas, self.inner_control_frame) self.analyze_quarterly_results = AnalyzeQuarterlyResults( self.redraw, matplotlib_canvas, self.inner_control_frame) self.analyze_reward_distribution = AnalyzeRewardDistribution( self.redraw, matplotlib_canvas, self.inner_control_frame) self.analyze_common_rewards = AnalyzeCommonRewards( self.redraw, matplotlib_canvas, self.inner_control_frame) self.analyze_rewards_per_waypoint = AnalyzeRewardsPerWaypoint( self.redraw, matplotlib_canvas, self.inner_control_frame) self.analyze_episode_speed = AnalyzeEpisodeSpeed( self.redraw, matplotlib_canvas, self.inner_control_frame, self.episode_selector) self.analyze_episode_reward = AnalyzeEpisodeReward( self.redraw, matplotlib_canvas, self.inner_control_frame, self.episode_selector, self._config_manager) self.analyze_episode_slide = AnalyzeEpisodeSlide( self.redraw, matplotlib_canvas, self.inner_control_frame, self.episode_selector) self.analyze_episode_action_distribution = AnalyzeEpisodeActionDistribution( self.redraw, matplotlib_canvas, self.inner_control_frame, self.episode_selector) self.analyze_lap_time_correlations = AnalyzeLapTimeCorrelations( self.redraw, matplotlib_canvas, self.inner_control_frame) self.analyze_sector_time_correlations = AnalyzeSectorTimeCorrelations( self.redraw, matplotlib_canvas, self.inner_control_frame) self.analyze_lap_time_distribution = AnalyzeLapTimeDistribution( self.redraw, matplotlib_canvas, self.inner_control_frame) self.analyze_complete_lap_percentage = AnalyzeCompleteLapPercentage( self.redraw, matplotlib_canvas, self.inner_control_frame) self.analyze_discount_factors = AnalyzeDiscountFactors( self.redraw, matplotlib_canvas, self.inner_control_frame) self.all_analyzers = [ self.analyze_route, self.analyze_track_heatmap, self.analyze_exit_points, self.analyze_race, self.analyze_curve_fitting, self.analyze_straight_fitting, self.analyze_training_progress, self.analyze_quarterly_results, self.analyze_reward_distribution, self.analyze_common_rewards, self.analyze_rewards_per_waypoint, self.analyze_episode_speed, self.analyze_episode_reward, self.analyze_episode_slide, self.analyze_episode_action_distribution, self.analyze_lap_time_correlations, self.analyze_sector_time_correlations, self.analyze_lap_time_distribution, self.analyze_complete_lap_percentage, self.analyze_discount_factors ] for v in self.all_analyzers: v.set_track(self.current_track) self.analyzer = self.analyze_route self.background_analyzer = None self.analyzer.take_control() if ss.SHOW_SS: self.secret_analyzers = ss.get_secret_analyzers( self.redraw, self.track_graphics, self.inner_control_frame) else: self.secret_analyzers = None # # Define the layout of the high level UI components # self.layout_ui_for_track_analyzer() # # Configure the rest of the application window and then make it appear # self.master.title("Deep Racer Guru v" + VERSION) self.menu_bar = MenuBar(root, self, False) # # All done, so display main window now # self.already_drawing = False self.update() # # And now lock-in the sizes of the control and status frames so switches between views will be smooth # self.control_frame.pack_propagate(0) self.control_frame.grid_propagate(0) self.status_frame.pack_propagate(0) self.status_frame.grid_propagate(0) def layout_ui_for_track_analyzer(self): self.status_frame.pack(fill=tk.BOTH, side=tk.BOTTOM) self.track_canvas.pack(fill=tk.BOTH, expand=True, side=tk.LEFT) self.control_frame.pack(fill=tk.BOTH, side=tk.RIGHT) self.inner_control_frame.pack() self.pack(fill=tk.BOTH, expand=True) self.please_wait = self.please_wait_track def layout_ui_for_graph_analyzer(self): self.status_frame.pack(fill=tk.BOTH, side=tk.BOTTOM) self.graph_canvas.pack(fill=tk.BOTH, expand=True, side=tk.LEFT) self.control_frame.pack(fill=tk.BOTH, side=tk.RIGHT) self.inner_control_frame.pack() self.pack(fill=tk.BOTH, expand=True) self.please_wait = self.please_wait_graph def menu_callback_switch_track(self, new_track): self.log = None self.filtered_episodes = None self.status_frame.reset() self.current_track = new_track self._config_manager.set_last_open_track(new_track.get_world_name()) for v in self.all_analyzers: v.set_track(new_track) self.episode_selector.set_filtered_episodes(None) self._reset_analyzer(self.analyzer) if self.background_analyzer: self._reset_analyzer(self.background_analyzer) self.view_manager.zoom_clear() self.menu_bar = MenuBar(root, self, False) self.redraw() def _reset_analyzer(self, analyzer): analyzer.set_track(self.current_track) analyzer.set_filtered_episodes(None) analyzer.set_all_episodes(None, None) analyzer.set_log_meta(None) analyzer.set_evaluation_phases(None) def switch_analyzer(self, new_analyzer, new_background_analyzer=None): self.analyzer.lost_control() if new_background_analyzer: assert new_background_analyzer.uses_track_graphics( ) and new_analyzer.uses_track_graphics() if new_analyzer.uses_graph_canvas( ) and not self.analyzer.uses_graph_canvas(): self.track_canvas.pack_forget() self.layout_ui_for_graph_analyzer() elif new_analyzer.uses_track_graphics( ) and not self.analyzer.uses_track_graphics(): self.graph_canvas.pack_forget() self.layout_ui_for_track_analyzer() self.analyzer = new_analyzer self.background_analyzer = new_background_analyzer self.analyzer.take_control() self.redraw() def menu_callback_analyze_track_heatmap(self): self.switch_analyzer(self.analyze_track_heatmap) def menu_callback_analyze_exit_points(self): self.switch_analyzer(self.analyze_exit_points) def menu_callback_analyze_race(self): self.switch_analyzer(self.analyze_race) def menu_callback_analyze_curve_fitting(self): self.switch_analyzer(self.analyze_curve_fitting) def menu_callback_analyze_straight_fitting(self): self.switch_analyzer(self.analyze_straight_fitting) def menu_callback_analyze_route(self): self.switch_analyzer(self.analyze_route) def menu_callback_analyze_route_over_heatmap(self): self.switch_analyzer(self.analyze_route, self.analyze_track_heatmap) def menu_callback_analyze_exit_points_over_heatmap(self): self.switch_analyzer(self.analyze_exit_points, self.analyze_track_heatmap) def menu_callback_analyze_training_progress(self): self.switch_analyzer(self.analyze_training_progress) def menu_callback_analyze_quarterly_results(self): self.switch_analyzer(self.analyze_quarterly_results) def menu_callback_analyze_reward_distribution(self): self.switch_analyzer(self.analyze_reward_distribution) def menu_callback_analyze_common_rewards(self): self.switch_analyzer(self.analyze_common_rewards) def menu_callback_analyze_rewards_per_waypoint(self): self.switch_analyzer(self.analyze_rewards_per_waypoint) def menu_callback_analyze_episode_speed(self): self.switch_analyzer(self.analyze_episode_speed) def menu_callback_analyze_episode_reward(self): self.switch_analyzer(self.analyze_episode_reward) def menu_callback_analyze_episode_slide(self): self.switch_analyzer(self.analyze_episode_slide) def menu_callback_analyze_episode_action_distribution(self): self.switch_analyzer(self.analyze_episode_action_distribution) def menu_callback_analyze_lap_time_correlations(self): self.switch_analyzer(self.analyze_lap_time_correlations) def menu_callback_analyze_sector_time_correlations(self): self.switch_analyzer(self.analyze_sector_time_correlations) def menu_callback_analyze_lap_time_distribution(self): self.switch_analyzer(self.analyze_lap_time_distribution) def menu_callback_analyze_complete_lap_percentage(self): self.switch_analyzer(self.analyze_complete_lap_percentage) def menu_callback_analyze_discount_factors(self): self.switch_analyzer(self.analyze_discount_factors) def menu_callback_switch_directory(self): result = tk.filedialog.askdirectory( title="Choose the directory where log files are stored", mustexist=True, initialdir=self._config_manager.get_log_directory()) if result: self._config_manager.set_log_directory(result) self.menu_bar.refresh() def callback_open_this_file(self, file_name): redraw_menu_afterwards = not self.log self.log = Log(self._config_manager.get_log_directory()) self.log.load_all( file_name, self.please_wait, self.current_track, self._config_manager.get_calculate_new_reward(), self._config_manager.get_calculate_alternate_discount_factors()) self.status_frame.change_model_name(self.log.get_log_meta().model_name) self.apply_new_action_space() reward_percentiles = RewardPercentiles( self.log.get_episodes(), self._config_manager.get_calculate_new_reward()) for v in self.all_analyzers: v.set_all_episodes(self.log.get_episodes(), reward_percentiles) v.set_log_meta(self.log.get_log_meta()) v.set_evaluation_phases(self.log.get_evaluation_phases()) self.episode_filter.set_all_episodes(self.log.get_episodes()) self.reapply_episode_filter() # Re-issue control to current analyzer so it has the chance to redraw its controls for the new log self.analyzer.take_control() if redraw_menu_afterwards: self.menu_bar = MenuBar(root, self, True) self.update() def apply_new_action_space(self): self.action_space_filter.set_new_action_space( self.log.get_log_meta().action_space) for v in self.all_analyzers: v.set_action_space(self.log.get_log_meta().action_space) v.set_action_space_filter(self.action_space_filter) def reapply_action_space_filter(self): for v in self.all_analyzers: v.set_action_space_filter(self.action_space_filter) self.redraw() def reapply_sector_filter(self): for v in self.all_analyzers: v.set_sector_filter(self.sector_filter) self.redraw() def reapply_episode_filter(self): self.filtered_episodes = self.episode_filter.get_filtered_episodes( self.current_track) self.episode_selector.set_filtered_episodes(self.filtered_episodes) for v in self.all_analyzers: v.set_filtered_episodes(self.filtered_episodes) self.status_frame.change_episodes(len(self.log.get_episodes()), len(self.filtered_episodes)) self.redraw() def redraw(self, event=None): if not self.already_drawing: # Nasty workaround to avoid multiple calls due to "please wait" self.already_drawing = True self.view_manager.redraw(self.current_track, self.track_graphics, self.analyzer, self.background_analyzer, self.episode_filter) self.please_wait.stop() self.already_drawing = False def refresh_analysis_controls(self): self.analyzer.take_control() def close_file(self): self.log = None self.filtered_episodes = None self.status_frame.reset() self.episode_selector.set_filtered_episodes(None) self._reset_analyzer(self.analyzer) if self.background_analyzer: self._reset_analyzer(self.background_analyzer) self.menu_bar = MenuBar(root, self, False) self.redraw() def right_button_pressed_on_track_canvas(self, event): track_point = self.track_graphics.get_real_point_for_widget_location( event.x, event.y) self.analyzer.right_button_pressed(track_point) self.track_canvas.focus_set( ) # Set focus so we will now receive keyboard events too def left_button_pressed_on_track_canvas(self, event): self.zoom_start_x = event.x self.zoom_start_y = event.y def left_button_moved_on_track_canvas(self, event): if self.zoom_widget: self.track_canvas.delete(self.zoom_widget) self.zoom_widget = self.track_canvas.create_rectangle( self.zoom_start_x, self.zoom_start_y, event.x, event.y, outline="blue", width=2, dash=(4, 4)) def left_button_released_on_track_canvas(self, event): if self.zoom_widget: self.track_canvas.delete(self.zoom_widget) x_diff = abs(self.zoom_start_x - event.x) y_diff = abs(self.zoom_start_y - event.y) if x_diff > 10 and y_diff > 10: self.view_manager.zoom_set(self.track_graphics, self.zoom_start_x, self.zoom_start_y, event.x, event.y) self.redraw() def right_or_up_key_pressed_on_track_canvas(self, event): track_point = self.track_graphics.get_real_point_for_widget_location( event.x, event.y) self.analyzer.go_forwards(track_point) def left_or_down_key_pressed_on_track_canvas(self, event): track_point = self.track_graphics.get_real_point_for_widget_location( event.x, event.y) self.analyzer.go_backwards(track_point) def menu_callback_episodes_all(self): self.episode_filter.reset() self.reapply_episode_filter() def menu_callback_episodes_all_from_start(self): self.episode_filter.reset() self.episode_filter.set_filter_from_start_line(True) self.reapply_episode_filter() def menu_callback_episodes_complete_laps(self): self.episode_filter.reset() self.episode_filter.set_filter_min_percent(100) self.reapply_episode_filter() def menu_callback_episodes_fast_laps(self): es = self.log.get_log_meta().episode_stats target_steps = round((es.average_steps + es.best_steps) / 2) self.episode_filter.reset() self.episode_filter.set_filter_min_percent(100) self.episode_filter.set_filter_max_steps(target_steps) self.reapply_episode_filter() def menu_callback_episodes_complete_laps_from_start(self): self.episode_filter.reset() self.episode_filter.set_filter_min_percent(100) self.episode_filter.set_filter_from_start_line(True) self.reapply_episode_filter() def menu_callback_episodes_min_percent_10(self): self.episode_filter.reset() self.episode_filter.set_filter_min_percent(10) self.reapply_episode_filter() def menu_callback_episodes_min_percent_25(self): self.episode_filter.reset() self.episode_filter.set_filter_min_percent(25) self.reapply_episode_filter() def menu_callback_episodes_min_percent_33(self): self.episode_filter.reset() self.episode_filter.set_filter_min_percent(33) self.reapply_episode_filter() def menu_callback_episodes_min_percent_50(self): self.episode_filter.reset() self.episode_filter.set_filter_min_percent(50) self.reapply_episode_filter() def menu_callback_episodes_q1(self): self.episode_filter.reset() self.episode_filter.set_filter_quarters(True, False, False, False) self.reapply_episode_filter() def menu_callback_episodes_q2(self): self.episode_filter.reset() self.episode_filter.set_filter_quarters(False, True, False, False) self.reapply_episode_filter() def menu_callback_episodes_q3(self): self.episode_filter.reset() self.episode_filter.set_filter_quarters(False, False, True, False) self.reapply_episode_filter() def menu_callback_episodes_q4(self): self.episode_filter.reset() self.episode_filter.set_filter_quarters(False, False, False, True) self.reapply_episode_filter() def menu_callback_episodes_sector(self, sector): self.episode_filter.reset() (start, finish) = self.current_track.get_sector_start_and_finish(sector) self.episode_filter.set_filter_complete_section_and_time( start, finish, None, None) self.reapply_episode_filter() def menu_callback_actions_all(self): self.action_space_filter.set_filter_all() self.reapply_action_space_filter() def menu_callback_actions_high_speed(self): self.action_space_filter.set_filter_high_speed() self.reapply_action_space_filter() def menu_callback_actions_medium_speed(self): self.action_space_filter.set_filter_medium_speed() self.reapply_action_space_filter() def menu_callback_actions_low_speed(self): self.action_space_filter.set_filter_low_speed() self.reapply_action_space_filter() def menu_callback_actions_straight(self): self.action_space_filter.set_filter_straight() self.reapply_action_space_filter() def menu_callback_sector_filter(self, sector: str): assert len(sector) == 1 self.sector_filter = sector self.reapply_sector_filter() def menu_callback_sector_zoom(self, sector: str): assert len(sector) == 1 self.view_manager.zoom_sector(self.current_track, sector) self.redraw() def menu_callback_zoom_in_out(self): self.view_manager.zoom_toggle() self.redraw() def menu_callback_grid_front(self): self.view_manager.set_grid_front() self.redraw() def menu_callback_grid_back(self): self.view_manager.set_grid_back() self.redraw() def menu_callback_grid_off(self): self.view_manager.set_grid_off() self.redraw() def menu_callback_track_front(self): self.view_manager.set_track_front() self.redraw() def menu_callback_track_back(self): self.view_manager.set_track_back() self.redraw() def menu_callback_track_grey(self): self.view_manager.set_track_colour_grey() self.redraw() def menu_callback_track_blue(self): self.view_manager.set_track_colour_blue() self.redraw() def menu_callback_sectors_on(self): self.view_manager.set_sectors_on() self.redraw() def menu_callback_sectors_off(self): self.view_manager.set_sectors_off() self.redraw() def menu_callback_waypoints_large(self): self.view_manager.set_waypoint_sizes_large() self.redraw() def menu_callback_waypoints_small(self): self.view_manager.set_waypoint_sizes_small() self.redraw() def menu_callback_waypoints_micro(self): self.view_manager.set_waypoint_sizes_micro() self.redraw() def menu_callback_waypoints_off(self): self.view_manager.set_waypoints_off() self.redraw() def menu_callback_waypoint_labels_on(self): self.view_manager.set_waypoint_labels_on() self.redraw() def menu_callback_waypoint_labels_off(self): self.view_manager.set_waypoint_labels_off() self.redraw() def menu_callback_analyze_front(self): self.view_manager.set_analyze_front() self.redraw() def menu_callback_analyze_back(self): self.view_manager.set_analyze_back() self.redraw() def menu_callback_annotations_front(self): self.view_manager.set_annotations_front() self.redraw() def menu_callback_annotations_back(self): self.view_manager.set_annotations_back() self.redraw() def menu_callback_annotations_off(self): self.view_manager.set_annotations_off() self.redraw() def menu_callback_heading_on(self): self.analyze_route.set_show_heading(True) def menu_callback_heading_off(self): self.analyze_route.set_show_heading(False) def menu_callback_true_bearing_on(self): self.analyze_route.set_show_true_bearing(True) def menu_callback_true_bearing_off(self): self.analyze_route.set_show_true_bearing(False) def menu_callback_camera_vision_on(self): self.analyze_route.set_show_camera_vision(True) def menu_callback_camera_vision_off(self): self.analyze_route.set_show_camera_vision(False) def menu_callback_view_log_file_info(self): if self.log: ViewLogFileInfo(self, self.log) def get_log_directory(self): return self._config_manager.get_log_directory() def get_config_manager(self): return self._config_manager
def __init__(self, root): # # Basic frame initialization # super().__init__(root) # # First of all, get config manager up and running so we have access to any settings that it manages for us # self._config_manager = ConfigManager() # # Initialise all internal settings not related to UI components # self.tracks = get_all_tracks() self.current_track = self.tracks[ self._config_manager.get_last_open_track()] self.log = None self.filtered_episodes = None self.episode_filter = EpisodeFilter() self.view_manager = ViewManager() self.action_space_filter = ActionSpaceFilter() self.episode_selector = EpisodeSelector() self.sector_filter = "" # # Create the simple high level UI components (the canvas, control frame and status frame) # self.status_frame = StatusFrame(self) self.track_canvas = tk.Canvas(self, bg="black", width=DEFAULT_CANVAS_WIDTH, height=DEFAULT_CANVAS_HEIGHT) self.track_canvas.bind("<Configure>", self.redraw) self.track_canvas.bind("<Button-3>", self.right_button_pressed_on_track_canvas) self.track_canvas.bind("<Left>", self.left_or_down_key_pressed_on_track_canvas) self.track_canvas.bind("<Up>", self.right_or_up_key_pressed_on_track_canvas) self.track_canvas.bind("<Right>", self.right_or_up_key_pressed_on_track_canvas) self.track_canvas.bind("<Down>", self.left_or_down_key_pressed_on_track_canvas) self.track_canvas.bind("<Button-1>", self.left_button_pressed_on_track_canvas) self.track_canvas.bind("<B1-Motion>", self.left_button_moved_on_track_canvas) self.track_canvas.bind("<ButtonRelease-1>", self.left_button_released_on_track_canvas) self.control_frame = tk.Frame(root) self.inner_control_frame = tk.Frame(self.control_frame) # # Initialise variables to control the right mouse zoom-in feature over a canvas # self.zoom_start_x = None self.zoom_start_y = None self.zoom_widget = None # # Create the graph plotting UI components using the magic of matplotlib # graph_figure = Figure(figsize=(5, 4), dpi=100) matplotlib_canvas = FigureCanvasTkAgg(graph_figure, master=self) self.graph_canvas = matplotlib_canvas.get_tk_widget() self.graph_canvas.config(width=DEFAULT_CANVAS_WIDTH, height=DEFAULT_CANVAS_HEIGHT) # # Initialize the "please wait" widget in the middle of each canvas # self.please_wait_track = PleaseWait(root, self.track_canvas) self.please_wait_graph = PleaseWait(root, self.graph_canvas) self.please_wait = self.please_wait_track # # Create the various "analyzers" and let them take control of the contents of the high level UI components # self.track_graphics = TrackGraphics(self.track_canvas) self.current_track.configure_track_graphics(self.track_graphics) self.analyze_route = AnalyzeRoute(self.redraw, self.track_graphics, self.inner_control_frame, self.episode_selector, self._config_manager) self.analyze_track_heatmap = AnalyzeHeatmap(self.redraw, self.track_graphics, self.inner_control_frame, self.please_wait_track, self._config_manager) self.analyze_exit_points = AnalyzeExitPoints(self.redraw, self.track_graphics, self.inner_control_frame) self.analyze_race = AnalyzeRace(self.redraw, self.track_graphics, self.inner_control_frame) self.analyze_curve_fitting = AnalyzeCurveFitting( self.redraw, self.track_graphics, self.inner_control_frame) self.analyze_straight_fitting = AnalyzeStraightFitting( self.redraw, self.track_graphics, self.inner_control_frame) self.analyze_training_progress = AnalyzeTrainingProgress( self.redraw, matplotlib_canvas, self.inner_control_frame) self.analyze_quarterly_results = AnalyzeQuarterlyResults( self.redraw, matplotlib_canvas, self.inner_control_frame) self.analyze_reward_distribution = AnalyzeRewardDistribution( self.redraw, matplotlib_canvas, self.inner_control_frame) self.analyze_common_rewards = AnalyzeCommonRewards( self.redraw, matplotlib_canvas, self.inner_control_frame) self.analyze_rewards_per_waypoint = AnalyzeRewardsPerWaypoint( self.redraw, matplotlib_canvas, self.inner_control_frame) self.analyze_episode_speed = AnalyzeEpisodeSpeed( self.redraw, matplotlib_canvas, self.inner_control_frame, self.episode_selector) self.analyze_episode_reward = AnalyzeEpisodeReward( self.redraw, matplotlib_canvas, self.inner_control_frame, self.episode_selector, self._config_manager) self.analyze_episode_slide = AnalyzeEpisodeSlide( self.redraw, matplotlib_canvas, self.inner_control_frame, self.episode_selector) self.analyze_episode_action_distribution = AnalyzeEpisodeActionDistribution( self.redraw, matplotlib_canvas, self.inner_control_frame, self.episode_selector) self.analyze_lap_time_correlations = AnalyzeLapTimeCorrelations( self.redraw, matplotlib_canvas, self.inner_control_frame) self.analyze_sector_time_correlations = AnalyzeSectorTimeCorrelations( self.redraw, matplotlib_canvas, self.inner_control_frame) self.analyze_lap_time_distribution = AnalyzeLapTimeDistribution( self.redraw, matplotlib_canvas, self.inner_control_frame) self.analyze_complete_lap_percentage = AnalyzeCompleteLapPercentage( self.redraw, matplotlib_canvas, self.inner_control_frame) self.analyze_discount_factors = AnalyzeDiscountFactors( self.redraw, matplotlib_canvas, self.inner_control_frame) self.all_analyzers = [ self.analyze_route, self.analyze_track_heatmap, self.analyze_exit_points, self.analyze_race, self.analyze_curve_fitting, self.analyze_straight_fitting, self.analyze_training_progress, self.analyze_quarterly_results, self.analyze_reward_distribution, self.analyze_common_rewards, self.analyze_rewards_per_waypoint, self.analyze_episode_speed, self.analyze_episode_reward, self.analyze_episode_slide, self.analyze_episode_action_distribution, self.analyze_lap_time_correlations, self.analyze_sector_time_correlations, self.analyze_lap_time_distribution, self.analyze_complete_lap_percentage, self.analyze_discount_factors ] for v in self.all_analyzers: v.set_track(self.current_track) self.analyzer = self.analyze_route self.background_analyzer = None self.analyzer.take_control() if ss.SHOW_SS: self.secret_analyzers = ss.get_secret_analyzers( self.redraw, self.track_graphics, self.inner_control_frame) else: self.secret_analyzers = None # # Define the layout of the high level UI components # self.layout_ui_for_track_analyzer() # # Configure the rest of the application window and then make it appear # self.master.title("Deep Racer Guru v" + VERSION) self.menu_bar = MenuBar(root, self, False) # # All done, so display main window now # self.already_drawing = False self.update() # # And now lock-in the sizes of the control and status frames so switches between views will be smooth # self.control_frame.pack_propagate(0) self.control_frame.grid_propagate(0) self.status_frame.pack_propagate(0) self.status_frame.grid_propagate(0)
def OLD_plot_label(self, track_graphics: TrackGraphics, point, text, size): off_track_point = self.get_target_point( (self.mid_x, self.mid_y), point, -180, 1.5 * self.track_width) track_graphics.plot_text(off_track_point, text, size)