class CellSegment(object): """ Used for drawing the animations. There is one segment for each 'ring' in the cell. -- This is cell segment is for the animation panel. """ def __init__(self, (tl_x, tl_y), radius, index, file_name, species): #WorldState.Instance() = WorldState.Instance() self.counter = 0 num_of_segments = len(WorldState.Instance().session_dict['tree_list']) change = 0 self.sub_segments = [] """ create each cell segment """ for i in range(0, num_of_segments): centre_x = tl_x centre_y = tl_y outer_x1, outer_y1 = centre_x + radius - change, centre_y outer_x2, outer_y2 = centre_x, 10 + change self.sub_segments.append( (file_name, species, i, WorldState.Instance().session_dict['tree_list'][i], centre_x, centre_y, outer_x1, outer_y1, outer_x2, outer_y2)) change += radius / num_of_segments
def create_cell_segments_by_species(self, n): """ Used when switching file. Draws a cell cross-section for each species in the file Should integrate this with create...by_file """ self.drop_down_files.SetSelection(n) (a_width, a_height) = self.animation_panel.GetSize() for child in self.animation_panel.GetChildren(): try: int(child.GetName()) child.Destroy() except: pass WorldState.Instance().panels = [] panel_vboxes = [] WorldState.Instance().cell_segments = [] #TODO: Fix these magic numbers a = 10 b = (a_height * 0.7) - 10 c = (a_height * 0.7) - 20 d = 0 for i, species_name in enumerate(sorted(self.list_of_species())): if species_name != "Time": small_vbox = wx.BoxSizer(wx.VERTICAL) panel_vboxes.append(small_vbox) title = wx.StaticText(self.animation_panel, -1, species_name, name=str(i)) small_vbox.Add(title, 0, wx.EXPAND | wx.ALL, border=2) panel = wx.Panel(self.animation_panel, -1, size=(a_height * 0.7, a_height * 0.7), name=str(i)) panel.SetBackgroundColour('white') panel.Bind(wx.EVT_PAINT, self.animate_cell) panel.Bind(wx.EVT_LEFT_UP, self.annotate_cell) WorldState.Instance().panels.append(panel) small_vbox.Add(panel, 0, wx.EXPAND | wx.ALL, border=2) self.animation_panels_hbox.Add(small_vbox, 0, wx.EXPAND | wx.ALL, border=2) WorldState.Instance().cell_segments.append( CellSegment((a, b), c, d, self.drop_down_files.GetStringSelection(), species_name.split("@")[0])) self.animation_panel.Layout() self.animation_panel.SetupScrolling(scroll_y=False) for panel in WorldState.Instance().panels: panel.Refresh()
def paint(self, dc, p_id): species_locations = ['whole_cell'] """ draw the segments """ for (file_name, species, i, location, centre_x, centre_y, outer_x1, outer_y1, outer_x2, outer_y2) in self.sub_segments: line = WorldState.Instance().session_dict['lines'][file_name].get( species + "@" + WorldState.Instance().session_dict['tree_list'][i], None) if line != None: if location in species_locations or species_locations == [ 'whole_cell' ]: line.update_animation_colour( WorldState.Instance().session_dict['clock']) dc.SetBrush(wx.Brush(line.seg_colour)) else: dc.SetBrush(wx.Brush('white')) dc.DrawArc(outer_x1, outer_y1, outer_x2, outer_y2, centre_x, centre_y) dc.SetBrush(wx.Brush('black')) """ Draw the annotations """ for annotation in WorldState.Instance( ).session_dict['anime_annotations'].get(p_id, []): #Draw the labels if annotation.in_time(WorldState.Instance().session_dict['clock']): dc.SetBrush(wx.Brush('white')) dc.DrawCircle(annotation.x, annotation.y, 10) dc.SetBrush(wx.Brush('black')) dc.DrawLabel(str(annotation.a_id), (annotation.x - 4, annotation.y - 7, 5, 5), alignment=wx.ALIGN_LEFT | wx.ALIGN_TOP)
def export_data(self, event): titles = [] data_arrays = [] for file_name in WorldState.Instance().session_dict['lines'].keys(): for species in WorldState.Instance( ).session_dict['lines'][file_name].keys(): titles.append(species) data_arrays.append(WorldState.Instance().session_dict['lines'] [file_name][species].original_results) titles.append(species + "-normalised") data_arrays.append(WorldState.Instance().session_dict['lines'] [file_name][species].normalised_results) out_str = "" out_str += ','.join(titles) out_str += "\n" for line in zip(*data_arrays): out_str += ','.join(map(str, line)) out_str += "\n" file_choices = "CSV (*.csv)|*.csv" dlg = wx.FileDialog(self, message="Export Data as...", defaultDir=os.getcwd(), defaultFile="exported_data.csv", wildcard=file_choices, style=wx.SAVE) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() with open(path, 'wb') as f: f.write(out_str) self.SetTitle(_TITLE) else: dlg.Destroy()
def _on_custom_annotate_text_arrow(self, e): self.get_label() WorldState.Instance().change_cursor(wx.CURSOR_HAND) WorldState.Instance().session_dict[ 'annotate'] = not WorldState.Instance().session_dict['annotate'] WorldState.Instance( ).session_dict['annotation_mode'] = WorldState.Instance()._TEXT_ARROW
def update_legend(self, clock, update_tuple): """ works """ old_clock = clock """ Assume that if I am master that I am more right """ if WorldState.Instance().lamport_clock == clock: if self.port == 8000: WorldState.Instance().lamport_clock += 1 else: clock += 1 WorldState.Instance().push_state() WorldState.Instance().lamport_clock = max( WorldState.Instance().lamport_clock, clock) + 1 line, file_key, species_key = pickle.loads(update_tuple) WorldState.Instance( ).session_dict['lines'][file_key][species_key] = line WorldState.Instance().reorder(clock) WorldState.Instance().legend.draw_legend() WorldState.Instance().legend.legend_panel.Refresh() WorldState.Instance().refresh_plot() if old_clock != clock: return clock else: None
def refresh_plot(): """ Null pointers on the mac if I don't tell it to not redraw the legend unless necessary. """ WorldState.Instance().session_dict['redraw_legend'] = False WorldState.Instance().draw_plot.plot() WorldState.Instance().session_dict['redraw_legend'] = True
def request_session(self): """ works """ data = self.server.get_session_dict() WorldState.Instance().unpickle_session(data) WorldState.Instance().push_state() return True
def move_animation(self, e): """ Bound to the slider when you move it -- updates the session clock """ WorldState.Instance( ).session_dict['clock'] = self.slider_time.GetValue() for segment in WorldState.Instance().cell_segments: segment.update_clock()
def on_ok(self, e): text = self.text_ctrl.GetValue() start = self.start_time.GetValue() finish = self.end_time.GetValue() WorldState.Instance().temp_anime_annotation = AnimationAnnotation( text, start, finish, WorldState.Instance().session_dict['cur_annotation_id']) self.Close()
def animate_cell(self, e): """ called when the animation pane is refreshed. -- OnPaint pane is refreshed by animate() update the position of the vertical line. Draw each of the cell segments """ wx.CallAfter(WorldState.Instance().draw_plot.vertical_line) panel = e.GetEventObject() idx = int(panel.GetName()) dc2 = wx.PaintDC(panel) WorldState.Instance().cell_segments[idx].paint(dc2, idx)
def intensity_click(self, event): """ Event for toggling between colour intensity plot and normal plot """ cb_intense = event.GetEventObject() file_key = cb_intense.GetParent().GetParent().GetLabel() species_key = self.get_species(cb_intense) WorldState.Instance().session_dict['lines'][file_key][ species_key].intense_plot = cb_intense.GetValue() WorldState.Instance().lamport_clock += 1 WorldState.Instance().push_state() WorldState.Instance().reorder(WorldState.Instance().lamport_clock) refresh_plot()
def show_hide_click(self, event): """ Updates the line to say don't or do draw """ cb_show_hide = event.GetEventObject() file_key = cb_show_hide.GetParent().GetParent().GetLabel() species_key = self.get_species(cb_show_hide) WorldState.Instance().session_dict['lines'][file_key][ species_key].plot_line = cb_show_hide.GetValue() WorldState.Instance().lamport_clock += 1 WorldState.Instance().push_state() WorldState.Instance().reorder(WorldState.Instance().lamport_clock) refresh_plot()
def real_play_animation(self): if not WorldState.Instance().session_dict['start_playing']: WorldState.Instance().session_dict['clock'] = 0 self.slider_time.SetValue(0) for line_dict in WorldState.Instance( ).session_dict['lines'].values(): for line in line_dict.values(): line.counter = 0 WorldState.Instance().session_dict['clock_pause'] = False WorldState.Instance().session_dict['start_playing'] = True t4 = Thread(target=self.change_button_text, args=("Pause", )) t = Thread(target=self.animate, args=(0.1, )) t.start() t4.start() else: if WorldState.Instance().session_dict['clock_pause']: WorldState.Instance().session_dict['clock_pause'] = False t2 = Thread(target=self.change_button_text, args=("Pause", )) t2.start() else: WorldState.Instance().session_dict['clock_pause'] = True t3 = Thread(target=self.change_button_text, args=("Play", )) t3.start()
def sessiony_stuff(self): """ Each of the routes into a new session come here. It handles all the initial drawing of session state """ WorldState.Instance().draw_plot = Plotter(self.graph_axes) WorldState.Instance().draw_plot.plot() self.slider_time.SetMax(WorldState.Instance().session_dict['max_time']) if WorldState.Instance().session_dict['tree_list']: for species in self.list_of_species(): self.drop_down_species.Append(species) for file_name in WorldState.Instance( ).session_dict['results'].keys(): self.drop_down_files.Append(file_name) self.drop_down_species.SetSelection(0) self.drop_down_files.SetSelection(0) self.create_cell_segments_by_file( self.drop_down_files.GetSelection()) WorldState.Instance().populate_anime_annotation_lb() WorldState.Instance().push_state() WorldState.Instance().lamport_clock += 1 self.enable_all(True)
def move_mouse(self, event): """ Handles the drawing of the arrow when deciding where to annotate """ if WorldState.Instance().draw_plot: if WorldState.Instance().session_dict['click_one']: WorldState.Instance( ).session_dict['temp_annotation'] = Annotation( WorldState.Instance()._ARROW, (WorldState.Instance().session_dict['click_one_x'], WorldState.Instance().session_dict['click_one_y']), (event.xdata, event.ydata)) if WorldState.Instance().session_dict['annotate']: WorldState.Instance().session_dict['redraw_legend'] = False WorldState.Instance().draw_plot.plot() WorldState.Instance().session_dict['redraw_legend'] = True
def plot_line(self, line): """ Decides, for each line, how we're going to plot, normal or with intensities """ if line.plot_line: if not WorldState.Instance().session_dict['normalised']: if not line.intense_plot: self.axes.plot(line.original_time, line.original_results, label=line.species, color=rgb_to_hex(line.rgb_tuple), alpha=1, lw=line.thickness) else: for (sub_plot, new_colour) in line.sub_plot_tuples: self.axes.plot(line.interpolated_time, sub_plot, color=new_colour, lw=line.thickness) else: if not line.intense_plot: self.axes.plot(line.original_time, line.normalised_results, label=line.species, color=rgb_to_hex(line.rgb_tuple), alpha=1, lw=line.thickness) else: for (sub_plot, new_colour) in line.normalised_sub_plots: self.axes.plot(line.interpolated_time, sub_plot, color=new_colour, lw=line.thickness)
def non_blocking(self, *args, **kwargs): """ Every thread call comes here. It is passed the server method to call and the arguments to that function """ new_clock = kwargs['name'](*args) if new_clock is not None: WorldState.Instance().lamport_clock = new_clock
def launch_dialog(self, event): btn_props = event.GetEventObject() file_key = btn_props.GetParent().GetParent().GetLabel() species_key = self.get_species(btn_props) plot_prefs = Plot_Dialog(None, title='Change Plot Style') plot_prefs.set_line( WorldState.Instance().session_dict['lines'][file_key][species_key]) plot_prefs.ShowModal() plot_prefs.Destroy() self.update(btn_props.GetParent(), file_key, species_key) WorldState.Instance().client.update_legend( WorldState.Instance().session_dict['lines'][file_key][species_key], file_key, species_key)
def open_attached_file(self, event): """ Opening attached files, must be a better way of doing this """ idx = self.attached_file_list.GetSelection() if platform.system() == "Linux": call([ "gnome-open", WorldState.Instance().session_dict['attached_file_locations'] [idx] ]) else: call([ "open", WorldState.Instance().session_dict['attached_file_locations'] [idx] ])
def calc_graph_size(dpi, cols, num_sidebars, phi): """ Want it to stick to the golden ration as Tufte recommends it hence phi """ graph_width = int( ((WorldState.Instance().dispW / cols) * (cols - num_sidebars)) / dpi) graph_height = int(graph_width / phi) return (graph_width, graph_height)
def list_of_species(self): species_list = [] for key, item in WorldState.Instance( ).session_dict['species_dict'].items(): for species in item: if species not in species_list: species_list.append(species) return species_list
def get_label(self): dialog = wx.TextEntryDialog(None, "Please Enter A Label:", "Annotation Text", "", style=wx.OK | wx.CANCEL) if dialog.ShowModal() == wx.ID_OK: WorldState.Instance( ).session_dict['annotation_text'] = dialog.GetValue()
def vertical_line(self): """ The sliding bar that follows the clock """ if WorldState.Instance().session_dict['normalised']: height = 1 else: height = WorldState.Instance().session_dict['ymax'] self.axes.plot([ WorldState.Instance().session_dict['clock'], WorldState.Instance().session_dict['clock'] ], [0, height], label="time_line", color='red', lw=3) WorldState.Instance().graph_canvas.draw() self.axes.lines.pop()
def onclick(self, event): """ On the graph canvas """ if WorldState.Instance().draw_plot: if event.button == _LEFT_BUTTON: self.left_click_handler(event) elif event.button == _RIGHT_BUTTON: self.right_click_handler(event)
def tree_to_list(self, tree): next_key = 'root' tree_list = [] while True: next_key = tree.get(next_key, [None])[0] if next_key is None: break tree_list.append(next_key) WorldState.Instance().session_dict['tree_list'] = tree_list return tree_list
def toggle_param(self, param): WorldState.Instance( ).session_dict[param] = not WorldState.Instance().session_dict[param] WorldState.Instance().lamport_clock += 1 WorldState.Instance().push_state() WorldState.Instance().reorder(WorldState.Instance().lamport_clock) WorldState.Instance().client.toggle_param( param, WorldState.Instance().session_dict[param]) refresh_plot()
def open_results_file(self): file_chooser = wx.FileDialog(self, message="Choose a file", wildcard="*.csv", style=wx.OPEN | wx.MULTIPLE | wx.CHANGE_DIR) if file_chooser.ShowModal() == wx.ID_OK: paths = file_chooser.GetPaths() results = {} parser = BioPepaCsvParser() for path in paths: parser.parse_csv(path) results[path.split('/')[-1]] = parser.results_dict WorldState.Instance().session_dict['results'] = results WorldState.Instance().parser = parser file_chooser.Destroy() else: file_chooser.Destroy()
def on_save_plot(self, event): """ Save the graph """ file_choices = "PNG (*.png)|*.png" dlg = wx.FileDialog(self, message="Export plot as...", defaultDir=os.getcwd(), defaultFile="plot.png", wildcard=file_choices, style=wx.SAVE) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() WorldState.Instance().draw_plot.mpl_legend = True refresh_plot() self.graph_canvas.print_figure(path, dpi=_DPI) WorldState.Instance().draw_plot.mpl_legend = False refresh_plot()
def add_files(self, e): """ Results files. There can be many, they can be added in multiple goes """ open_results_file(self) for key in WorldState.Instance().session_dict['results'].keys(): self.species_dict[key] = {} for species in WorldState.Instance( ).session_dict['results'][key].keys(): if species != 'Time': try: (name, location) = species.split("@") except: (name, location) = (species, "whole_cell") if name in self.species_dict[key]: self.species_dict[key][name].append(location) else: self.species_dict[key][name] = [location] self.populate_file_dd_list() self.chosen_paths.append(key) self.file_list.Append(key)