def __init__(self, window, disc_bn=DiscreteBayesianNetworkExt()): self.window = window # Create graphic widgets self.box_disc_bn, self.drawing_box, self.toolbar_edit, self.toolbar_evidence, self.bedit, self.brun, self.bvertex, \ self.bclear_evidence = ugraphic.create_widget( res.TAB_DISC_BAYES_NET_GLADE, [BOX_DISC_BN, DRAWING_BOX, TB_EDIT_BN, TB_EVIDENCE, RB_EDIT, RB_RUN, RB_VERTEX, RB_CLEAR_EVIDENCE], self) super(BoxDiscreteBN, self).__init__(spacing=1) self.pack_start(self.box_disc_bn, True, True, 0) self.set_visible(True) self.drawer = GraphDrawer() self.drawing_box.pack_start(self.drawer.get_drawing_area(), True, True, 0) self.mode = Mode.edit_vertex # Temporal vertex for edge self.vertex_1 = None self.selected_vertex = None self.selected_edge = None self.marginals = None self.evidences = {} # Temporal arrow for mouse motion self.tmp_arrow = None # Graph self.disc_bn = disc_bn # Vertex locations to draw self.vertex_locations = {} self.clicked_point = None self.button_pressed = False # connect listeners self.drawer.clicked_element_listener = self.clicked_element self.drawer.clicked_clear_space_listener = self.clicked_clear_space self.drawer.right_click_elem_listener = self.right_clicked_elem self.drawer.double_clicked_element_listener = self.double_click_on_elem # Graphical objects in the background self.background_gobjs = []
class BoxDiscreteBN(Gtk.Box): """ Gtk Box to show and edit a discrete bayesian network. """ def __init__(self, window, disc_bn=DiscreteBayesianNetworkExt()): self.window = window # Create graphic widgets self.box_disc_bn, self.drawing_box, self.toolbar_edit, self.toolbar_evidence, self.bedit, self.brun, self.bvertex, \ self.bclear_evidence = ugraphic.create_widget( res.TAB_DISC_BAYES_NET_GLADE, [BOX_DISC_BN, DRAWING_BOX, TB_EDIT_BN, TB_EVIDENCE, RB_EDIT, RB_RUN, RB_VERTEX, RB_CLEAR_EVIDENCE], self) super(BoxDiscreteBN, self).__init__(spacing=1) self.pack_start(self.box_disc_bn, True, True, 0) self.set_visible(True) self.drawer = GraphDrawer() self.drawing_box.pack_start(self.drawer.get_drawing_area(), True, True, 0) self.mode = Mode.edit_vertex # Temporal vertex for edge self.vertex_1 = None self.selected_vertex = None self.selected_edge = None self.marginals = None self.evidences = {} # Temporal arrow for mouse motion self.tmp_arrow = None # Graph self.disc_bn = disc_bn # Vertex locations to draw self.vertex_locations = {} self.clicked_point = None self.button_pressed = False # connect listeners self.drawer.clicked_element_listener = self.clicked_element self.drawer.clicked_clear_space_listener = self.clicked_clear_space self.drawer.right_click_elem_listener = self.right_clicked_elem self.drawer.double_clicked_element_listener = self.double_click_on_elem # Graphical objects in the background self.background_gobjs = [] def double_click_on_elem(self, elem): if self.mode == Mode.run or self.selected_vertex is None: return # Show cpt dialog self.show_edit_var_dialog() self.clicked_point = None self.selected_vertex = None self.drawer.dynamic_arrow = None self.draw_graph() def clicked_clear_space(self, p): if self.mode == Mode.edit_vertex: # Crate vertex vname = self.get_new_vertex_name() # new vertex self.vertex_locations[vname] = GPoint(p[0], p[1]) self.disc_bn.add_vertex(vname) elif self.mode == Mode.edit_edge: self.drawer.dynamic_arrow = None self.selected_vertex = None self.draw_graph() def right_clicked_elem(self, elem, event): if self.mode == Mode.edit_vertex or self.mode == Mode.edit_edge: if isinstance(elem, GVertex) or isinstance(elem, GArrow): self.show_edit_popup(event) def organize_graph(self, random=True): v_locts = ugraphic.create_vertex_locations(self.disc_bn, random=random) self.dict_to_gpoints(v_locts) self.draw_graph() def dict_to_gpoints(self, v_locts): for vname, point in v_locts.items(): self.vertex_locations[vname] = GPoint(point[0], point[1]) def gpoints_to_dict(self): l_loc = {} for vname, gpoint in self.vertex_locations.items(): l_loc[vname] = [gpoint.x, gpoint.y] return l_loc def get_new_vertex_name(self): """ Vertex name generator to create incremental variables and does not generate incompatibility with assigned names by user . """ counter = 1 new_name = DEFAULT_NODE_NAME + ' ' + str(counter) while new_name in self.disc_bn.get_vertices(): counter += 1 new_name = DEFAULT_NODE_NAME + ' ' + str(counter) return new_name def draw_graph(self): if self.mode == Mode.edit_vertex or self.mode == Mode.edit_edge: self._draw_mode_edit() else: self._draw_mode_run() def _draw_mode_edit(self): ## Configure drawer vl = self.vertex_locations # Graphic elements gelements = list(self.background_gobjs) # Edges for e in self.disc_bn.get_edges(): arrow = GArrow(self.vertex_locations[e[0]], self.vertex_locations[e[1]]) if e == self.selected_edge: arrow.selected = True gelements.append(arrow) # Vertices for vname, p in vl.items(): v = GVertex(p, vname) v.translatable = True if self.selected_vertex == vname: v.selected = True gelements.append(v) self.drawer.set_graphic_objects(gelements) self.drawer.repaint() def _draw_mode_run(self): ## Configure drawer vl = self.vertex_locations # Graphic elements boxes = [] dboxes = {} for vname, p in vl.items(): evidence = {} if vname in self.evidences: evidence = self.evidences[vname] b = GStateBox(p, vname, self.marginals[vname], evidence) b.translatable = True dboxes[vname] = b boxes.append(b) # Edges bedges = [] for e in self.disc_bn.get_edges(): arrow = GBoxArrow(dboxes[e[0]], dboxes[e[1]]) bedges.append(arrow) self.drawer.set_graphic_objects(self.background_gobjs + bedges + boxes) self.drawer.repaint() def editing_action(self, p): """ Action for adding vertices or edges. """ # if self.transform is not None: p = self.drawer.transform_point(p) # p = [p[0] - self.translation[0], p[1] - self.translation[1]] #### Mode Edit ##### self._draw_mode_edit() ####### MODE EDIT EDGE if self.mode_edit == Mode.edge: # If there is not a initial vertex selected if self.vertex_1 is None and self.selected_vertex is not None: self.vertex_1 = self.selected_vertex # If there is an initial vertex elif self.vertex_1 is not None and self.selected_vertex is None: #Select anything self.vertex_1 = None # draw a dynamic arrow self.drawer.set_dynamic_arrow(self.selected_edge) elif self.vertex_1 is not None and self.selected_vertex is not None: if not self.vertex_1 == self.selected_vertex and self.selected_vertex is not None: self.disc_bn.add_edge([self.vertex_1, self.selected_vertex]) self.vertex_1 = None self.selected_vertex = None self.tmp_arrow = None self.draw_graph() def change_vertex_name_h(self, old_name, new_name): #vertex locations self.vertex_locations[new_name] = self.vertex_locations.pop(old_name) # Change in BN self.disc_bn.change_vertex_name(old_name, new_name) #selected vertex if self.selected_vertex == old_name: self.selected_vertex = new_name def show_edit_popup(self, event): #Draw selected node self.drawer.repaint() menu = Gtk.Menu() menu_it = Gtk.MenuItem() menu_it.set_label("Edit") menu = Gtk.Menu() menuitem = Gtk.MenuItem(label="RadioMenuItem") menuitem.set_submenu(menu) # Edit selected vertex if self.selected_vertex is not None: menu_it = Gtk.MenuItem("Edit Variable") # Click on edit vertex data. def event_edit(widget, event): menu.destroy() self.show_edit_var_dialog() menu_it.connect("button-release-event", event_edit) menu.append(menu_it) # Delete variable or edge menu_it_del = Gtk.MenuItem("Delete") menu_it_del.connect("button-release-event", self.on_delete) menu.append(menu_it_del) menu.show_all() menu.popup(None, None, None, None, event.button, event.time) def set_mode(self, mode): """ Select Edit or Run mode. """ self.mode = mode if self.mode == Mode.edit_edge or self.mode == Mode.edit_vertex: self.bedit.set_active(True) self.toolbar_edit.set_visible(True) self.toolbar_evidence.set_visible(False) if self.mode == Mode.edit_vertex: self.bvertex.set_active(True) elif self.mode == Mode.run: self.brun.set_active(True) # Validate BN for v in self.disc_bn.get_vertices(): # Validate cycles try: self.disc_bn.toporder() except Exception: ugraphic.show_warning(self.window, "The Bayesian Network contains cycles.") return # Validate that the BN has all the cpts ok = self.disc_bn.validate_cprob(v) if not ok: ugraphic.show_warning(self.window, v + " is not valid.", "please, check the probability table.") self.bedit.set_active(True) return # compute marginals self.marginals = self.disc_bn.compute_marginals(self.evidences) self.toolbar_edit.set_visible(False) self.toolbar_evidence.set_visible(True) self.bclear_evidence.set_visible_horizontal(True) print "aqui pasa" self.selected_vertex = None self.selected_edge = None self.draw_graph() def show_edit_var_dialog(self): cpt_dialog = CptDialog() # Create clone of disc_bn new_disc_bn = self.disc_bn.clone() cpt_dialog.show_cpt_dialog(self.window, new_disc_bn, self.selected_vertex) new_var_name = cpt_dialog.get_var_name() ## Cancel button, new_var_name is assigned if new_var_name is None: return self.disc_bn = new_disc_bn if not new_var_name == self.selected_vertex: self.change_vertex_name_h(self.selected_vertex, new_var_name) self.selected_edge = None self.selected_vertex = None self.draw_graph() def save_bn_to_file(self, file_name): # if does not have extension if not file_name.endswith(FILE_EXTENSION): file_name += FILE_EXTENSION bn = { "vertex_loc": self.gpoints_to_dict(), "E": self.disc_bn.get_edges(), "V": self.disc_bn.get_vertices(), "Vdata": self.disc_bn.get_vdata()} dic_to_file(bn, file_name) def load_bn_from_file(self, file_name): """ Load a bayesian network to show. Initially, the bn can be loaded by itself, but vertex positions must be loaded independently. """ try: # load bayesian network self.disc_bn = DiscreteBayesianNetworkExt() self.disc_bn.load(file_name) ### Load Vertex locations json_data = dic_from_json_file(file_name) # Vertex locations if "vertex_loc" in json_data.keys(): self.dict_to_gpoints(json_data["vertex_loc"]) else: vl = ugraphic.create_vertex_locations(self.disc_bn) self.dict_to_gpoints(vl) except Exception: ugraphic.show_warning(self.window, "Error loading the Bayesian Network", Exception) return self._draw_mode_edit() ########### Listeners #################### def on_clear_evidence(self, button): """ Event to clear all evidence """ self.evidences = {} self.marginals = self.disc_bn.compute_marginals(self.evidences) self.draw_graph() def on_zoom(self, button): """ Zoom event by button. """ self.drawer.restore_zoom() def on_key_press(self, widget, event): """ Key event generated by box container. """ # Supr key is pressed if event.keyval == KEY_SUPR_CODE: self.on_delete(None) elif event.keyval == KEY_E_CODE: self.bedit.set_active(True) elif event.keyval == KEY_R_CODE: self.brun.set_active(True) def on_mode(self, radio_tool): """ Event to choose the 'edit mode' or the 'run mode'. """ if not radio_tool.get_active(): return True # Edit button, then select edit_vertex mode if radio_tool.get_label() == RB_EDIT: self.mode = Mode.edit_vertex self.set_mode(Mode.edit_vertex) if radio_tool.get_label() == RB_RUN: self.set_mode(Mode.run) def on_edit_mode(self, radiotool): """ Click on buttons: edit_vertex or edit_node :param radiotool: selected button :return: """ if not radiotool.get_active(): return True # Radio selected if radiotool.get_label() == RB_VERTEX: self.mode = Mode.edit_vertex elif radiotool.get_label() == RB_EDGE: self.mode = Mode.edit_edge elif radiotool.get_label() == RB_MANUAL: pass else: print "not supported" # No selections self.selected_edge = None self.selected_vertex = None self.draw_graph() def on_organize(self, widget): """ Estimate good places to draw each vertex of the graph. """ self.organize_graph() def on_delete(self, *widget): # Delete vertex if self.selected_vertex is not None: self.vertex_locations.pop(self.selected_vertex) # Delete from model self.disc_bn.remove_vertex(self.selected_vertex) # Delete edge elif self.selected_edge is not None: # Delete from model self.disc_bn.remove_edge(self.selected_edge) # Non selected self.selected_vertex = None self.selected_edge = None self.drawer.dynamic_arrow = None # Draw self.draw_graph() def clicked_element(self, gelement): # Edge is clicked if isinstance(gelement, GArrow): if self.mode == Mode.edit_vertex or self.mode == Mode.edit_edge: # Selected edge edge = [] for vname, p in self.vertex_locations.iteritems(): if p == gelement.p1: edge.append(vname) break for vname, p in self.vertex_locations.iteritems(): if p == gelement.p2: edge.append(vname) break gelement.selected = True self.selected_edge = edge self.selected_vertex = None # Vertex is clicked if isinstance(gelement, GVertex): self.selected_edge = None if self.mode == Mode.edit_vertex: gelement.selected = True self.selected_vertex = gelement.name elif self.mode == Mode.edit_edge: new_selection = gelement.name # if there is not selected a source vertex. if self.selected_vertex is None: self.selected_vertex = new_selection self.drawer.dynamic_arrow = self.vertex_locations[new_selection] # the second vertex was selected. else: # Create the new vertex self.disc_bn.add_edge([self.selected_vertex, new_selection]) self.selected_vertex = None self.drawer.dynamic_arrow = None # get selected state for evidence. only works on run_mode. if isinstance(gelement, GStateBox): new_evidence = gelement.selected_state if new_evidence is not None: self.evidences[gelement.name] = new_evidence # compute marginals again self.marginals = self.disc_bn.compute_marginals(self.evidences) self.draw_graph() self.draw_graph()
class BoxDiscreteBN(Gtk.Box): """ Gtk Box to show and edit a discrete bayesian network. """ def __init__(self, window, disc_bn=DiscreteBayesianNetworkExt()): self.window = window # Create graphic widgets self.box_disc_bn, self.drawing_box, self.toolbar_edit, self.toolbar_evidence, self.bedit, self.brun, self.bvertex, \ self.bclear_evidence = ugraphic.create_widget( res.TAB_DISC_BAYES_NET_GLADE, [BOX_DISC_BN, DRAWING_BOX, TB_EDIT_BN, TB_EVIDENCE, RB_EDIT, RB_RUN, RB_VERTEX, RB_CLEAR_EVIDENCE], self) super(BoxDiscreteBN, self).__init__(spacing=1) self.pack_start(self.box_disc_bn, True, True, 0) self.set_visible(True) self.drawer = GraphDrawer() self.drawing_box.pack_start(self.drawer.get_drawing_area(), True, True, 0) self.mode = Mode.edit_vertex # Temporal vertex for edge self.vertex_1 = None self.selected_vertex = None self.selected_edge = None self.marginals = None self.evidences = {} # Temporal arrow for mouse motion self.tmp_arrow = None # Graph self.disc_bn = disc_bn # Vertex locations to draw self.vertex_locations = {} self.clicked_point = None self.button_pressed = False # connect listeners self.drawer.clicked_element_listener = self.clicked_element self.drawer.clicked_clear_space_listener = self.clicked_clear_space self.drawer.right_click_elem_listener = self.right_clicked_elem self.drawer.double_clicked_element_listener = self.double_click_on_elem # Graphical objects in the background self.background_gobjs = [] def double_click_on_elem(self, elem): if self.mode == Mode.run or self.selected_vertex is None: return # Show cpt dialog self.show_edit_var_dialog() self.clicked_point = None self.selected_vertex = None self.drawer.dynamic_arrow = None self.draw_graph() def clicked_clear_space(self, p): if self.mode == Mode.edit_vertex: # Crate vertex vname = self.get_new_vertex_name() # new vertex self.vertex_locations[vname] = GPoint(p[0], p[1]) self.disc_bn.add_vertex(vname) elif self.mode == Mode.edit_edge: self.drawer.dynamic_arrow = None self.selected_vertex = None self.draw_graph() def right_clicked_elem(self, elem, event): if self.mode == Mode.edit_vertex or self.mode == Mode.edit_edge: if isinstance(elem, GVertex) or isinstance(elem, GArrow): self.show_edit_popup(event) def organize_graph(self, random=True): v_locts = ugraphic.create_vertex_locations(self.disc_bn, random=random) self.dict_to_gpoints(v_locts) self.draw_graph() def dict_to_gpoints(self, v_locts): for vname, point in v_locts.items(): self.vertex_locations[vname] = GPoint(point[0], point[1]) def gpoints_to_dict(self): l_loc = {} for vname, gpoint in self.vertex_locations.items(): l_loc[vname] = [gpoint.x, gpoint.y] return l_loc def get_new_vertex_name(self): """ Vertex name generator to create incremental variables and does not generate incompatibility with assigned names by user . """ counter = 1 new_name = DEFAULT_NODE_NAME + ' ' + str(counter) while new_name in self.disc_bn.get_vertices(): counter += 1 new_name = DEFAULT_NODE_NAME + ' ' + str(counter) return new_name def draw_graph(self): if self.mode == Mode.edit_vertex or self.mode == Mode.edit_edge: self._draw_mode_edit() else: self._draw_mode_run() def _draw_mode_edit(self): ## Configure drawer vl = self.vertex_locations # Graphic elements gelements = list(self.background_gobjs) # Edges for e in self.disc_bn.get_edges(): arrow = GArrow(self.vertex_locations[e[0]], self.vertex_locations[e[1]]) if e == self.selected_edge: arrow.selected = True gelements.append(arrow) # Vertices for vname, p in vl.items(): v = GVertex(p, vname) v.translatable = True if self.selected_vertex == vname: v.selected = True gelements.append(v) self.drawer.set_graphic_objects(gelements) self.drawer.repaint() def _draw_mode_run(self): ## Configure drawer vl = self.vertex_locations # Graphic elements boxes = [] dboxes = {} for vname, p in vl.items(): evidence = {} if vname in self.evidences: evidence = self.evidences[vname] b = GStateBox(p, vname, self.marginals[vname], evidence) b.translatable = True dboxes[vname] = b boxes.append(b) # Edges bedges = [] for e in self.disc_bn.get_edges(): arrow = GBoxArrow(dboxes[e[0]], dboxes[e[1]]) bedges.append(arrow) self.drawer.set_graphic_objects(self.background_gobjs + bedges + boxes) self.drawer.repaint() def editing_action(self, p): """ Action for adding vertices or edges. """ # if self.transform is not None: p = self.drawer.transform_point(p) # p = [p[0] - self.translation[0], p[1] - self.translation[1]] #### Mode Edit ##### self._draw_mode_edit() ####### MODE EDIT EDGE if self.mode_edit == Mode.edge: # If there is not a initial vertex selected if self.vertex_1 is None and self.selected_vertex is not None: self.vertex_1 = self.selected_vertex # If there is an initial vertex elif self.vertex_1 is not None and self.selected_vertex is None: #Select anything self.vertex_1 = None # draw a dynamic arrow self.drawer.set_dynamic_arrow(self.selected_edge) elif self.vertex_1 is not None and self.selected_vertex is not None: if not self.vertex_1 == self.selected_vertex and self.selected_vertex is not None: self.disc_bn.add_edge( [self.vertex_1, self.selected_vertex]) self.vertex_1 = None self.selected_vertex = None self.tmp_arrow = None self.draw_graph() def change_vertex_name_h(self, old_name, new_name): #vertex locations self.vertex_locations[new_name] = self.vertex_locations.pop(old_name) # Change in BN self.disc_bn.change_vertex_name(old_name, new_name) #selected vertex if self.selected_vertex == old_name: self.selected_vertex = new_name def show_edit_popup(self, event): #Draw selected node self.drawer.repaint() menu = Gtk.Menu() menu_it = Gtk.MenuItem() menu_it.set_label("Edit") menu = Gtk.Menu() menuitem = Gtk.MenuItem(label="RadioMenuItem") menuitem.set_submenu(menu) # Edit selected vertex if self.selected_vertex is not None: menu_it = Gtk.MenuItem("Edit Variable") # Click on edit vertex data. def event_edit(widget, event): menu.destroy() self.show_edit_var_dialog() menu_it.connect("button-release-event", event_edit) menu.append(menu_it) # Delete variable or edge menu_it_del = Gtk.MenuItem("Delete") menu_it_del.connect("button-release-event", self.on_delete) menu.append(menu_it_del) menu.show_all() menu.popup(None, None, None, None, event.button, event.time) def set_mode(self, mode): """ Select Edit or Run mode. """ self.mode = mode if self.mode == Mode.edit_edge or self.mode == Mode.edit_vertex: self.bedit.set_active(True) self.toolbar_edit.set_visible(True) self.toolbar_evidence.set_visible(False) if self.mode == Mode.edit_vertex: self.bvertex.set_active(True) elif self.mode == Mode.run: self.brun.set_active(True) # Validate BN for v in self.disc_bn.get_vertices(): # Validate cycles try: self.disc_bn.toporder() except Exception: ugraphic.show_warning( self.window, "The Bayesian Network contains cycles.") return # Validate that the BN has all the cpts ok = self.disc_bn.validate_cprob(v) if not ok: ugraphic.show_warning( self.window, v + " is not valid.", "please, check the probability table.") self.bedit.set_active(True) return # compute marginals self.marginals = self.disc_bn.compute_marginals(self.evidences) self.toolbar_edit.set_visible(False) self.toolbar_evidence.set_visible(True) self.bclear_evidence.set_visible_horizontal(True) print "aqui pasa" self.selected_vertex = None self.selected_edge = None self.draw_graph() def show_edit_var_dialog(self): cpt_dialog = CptDialog() # Create clone of disc_bn new_disc_bn = self.disc_bn.clone() cpt_dialog.show_cpt_dialog(self.window, new_disc_bn, self.selected_vertex) new_var_name = cpt_dialog.get_var_name() ## Cancel button, new_var_name is assigned if new_var_name is None: return self.disc_bn = new_disc_bn if not new_var_name == self.selected_vertex: self.change_vertex_name_h(self.selected_vertex, new_var_name) self.selected_edge = None self.selected_vertex = None self.draw_graph() def save_bn_to_file(self, file_name): # if does not have extension if not file_name.endswith(FILE_EXTENSION): file_name += FILE_EXTENSION bn = { "vertex_loc": self.gpoints_to_dict(), "E": self.disc_bn.get_edges(), "V": self.disc_bn.get_vertices(), "Vdata": self.disc_bn.get_vdata() } dic_to_file(bn, file_name) def load_bn_from_file(self, file_name): """ Load a bayesian network to show. Initially, the bn can be loaded by itself, but vertex positions must be loaded independently. """ try: # load bayesian network self.disc_bn = DiscreteBayesianNetworkExt() self.disc_bn.load(file_name) ### Load Vertex locations json_data = dic_from_json_file(file_name) # Vertex locations if "vertex_loc" in json_data.keys(): self.dict_to_gpoints(json_data["vertex_loc"]) else: vl = ugraphic.create_vertex_locations(self.disc_bn) self.dict_to_gpoints(vl) except Exception: ugraphic.show_warning(self.window, "Error loading the Bayesian Network", Exception) return self._draw_mode_edit() ########### Listeners #################### def on_clear_evidence(self, button): """ Event to clear all evidence """ self.evidences = {} self.marginals = self.disc_bn.compute_marginals(self.evidences) self.draw_graph() def on_zoom(self, button): """ Zoom event by button. """ self.drawer.restore_zoom() def on_key_press(self, widget, event): """ Key event generated by box container. """ # Supr key is pressed if event.keyval == KEY_SUPR_CODE: self.on_delete(None) elif event.keyval == KEY_E_CODE: self.bedit.set_active(True) elif event.keyval == KEY_R_CODE: self.brun.set_active(True) def on_mode(self, radio_tool): """ Event to choose the 'edit mode' or the 'run mode'. """ if not radio_tool.get_active(): return True # Edit button, then select edit_vertex mode if radio_tool.get_label() == RB_EDIT: self.mode = Mode.edit_vertex self.set_mode(Mode.edit_vertex) if radio_tool.get_label() == RB_RUN: self.set_mode(Mode.run) def on_edit_mode(self, radiotool): """ Click on buttons: edit_vertex or edit_node :param radiotool: selected button :return: """ if not radiotool.get_active(): return True # Radio selected if radiotool.get_label() == RB_VERTEX: self.mode = Mode.edit_vertex elif radiotool.get_label() == RB_EDGE: self.mode = Mode.edit_edge elif radiotool.get_label() == RB_MANUAL: pass else: print "not supported" # No selections self.selected_edge = None self.selected_vertex = None self.draw_graph() def on_organize(self, widget): """ Estimate good places to draw each vertex of the graph. """ self.organize_graph() def on_delete(self, *widget): # Delete vertex if self.selected_vertex is not None: self.vertex_locations.pop(self.selected_vertex) # Delete from model self.disc_bn.remove_vertex(self.selected_vertex) # Delete edge elif self.selected_edge is not None: # Delete from model self.disc_bn.remove_edge(self.selected_edge) # Non selected self.selected_vertex = None self.selected_edge = None self.drawer.dynamic_arrow = None # Draw self.draw_graph() def clicked_element(self, gelement): # Edge is clicked if isinstance(gelement, GArrow): if self.mode == Mode.edit_vertex or self.mode == Mode.edit_edge: # Selected edge edge = [] for vname, p in self.vertex_locations.iteritems(): if p == gelement.p1: edge.append(vname) break for vname, p in self.vertex_locations.iteritems(): if p == gelement.p2: edge.append(vname) break gelement.selected = True self.selected_edge = edge self.selected_vertex = None # Vertex is clicked if isinstance(gelement, GVertex): self.selected_edge = None if self.mode == Mode.edit_vertex: gelement.selected = True self.selected_vertex = gelement.name elif self.mode == Mode.edit_edge: new_selection = gelement.name # if there is not selected a source vertex. if self.selected_vertex is None: self.selected_vertex = new_selection self.drawer.dynamic_arrow = self.vertex_locations[ new_selection] # the second vertex was selected. else: # Create the new vertex self.disc_bn.add_edge( [self.selected_vertex, new_selection]) self.selected_vertex = None self.drawer.dynamic_arrow = None # get selected state for evidence. only works on run_mode. if isinstance(gelement, GStateBox): new_evidence = gelement.selected_state if new_evidence is not None: self.evidences[gelement.name] = new_evidence # compute marginals again self.marginals = self.disc_bn.compute_marginals(self.evidences) self.draw_graph() self.draw_graph()