source: orange/Orange/OrangeWidgets/Unsupervised/OWNxExplorer.py @ 10862:6ff8fcae285e

Revision 10862:6ff8fcae285e, 74.9 KB checked in by mstajdohar, 2 years ago (diff)

Set node coordinates to original positions if found in the graph data.

Line 
1"""
2<name>Net Explorer</name>
3<description>Orange widget for network exploration.</description>
4<icon>icons/Network.png</icon>
5<contact>Miha Stajdohar (miha.stajdohar(@at@)gmail.com)</contact> 
6<priority>6420</priority>
7"""
8import math
9import operator
10import statc
11import time
12
13import Orange
14import OWGUI
15import OWColorPalette
16import orngMDS
17
18from OWWidget import *
19from operator import itemgetter
20
21try:
22    from OWNxCanvasQt import *
23
24    class OWNxExplorer(OWWidget):
25
26        settingsList = ["autoSendSelection", "spinExplicit", "spinPercentage",
27        "maxLinkSize", "minVertexSize", "maxVertexSize", "networkCanvas.animate_plot",
28        "networkCanvas.animate_points", "networkCanvas.antialias_plot",
29        "networkCanvas.antialias_points", "networkCanvas.antialias_lines",
30        "networkCanvas.auto_adjust_performance", "invertSize", "optMethod",
31        "lastVertexSizeColumn", "lastColorColumn", "networkCanvas.show_indices", "networkCanvas.show_weights",
32        "lastNameComponentAttribute", "lastLabelColumns", "lastTooltipColumns",
33        "showWeights", "showEdgeLabels", "colorSettings",
34        "selectedSchemaIndex", "edgeColorSettings", "selectedEdgeSchemaIndex",
35        "showMissingValues", "fontSize", "mdsTorgerson", "mdsAvgLinkage",
36        "mdsSteps", "mdsRefresh", "mdsStressDelta", "organism", "showTextMiningInfo",
37        "toolbarSelection", "minComponentEdgeWidth", "maxComponentEdgeWidth",
38        "mdsFromCurrentPos", "labelsOnMarkedOnly", "tabIndex",
39        "networkCanvas.trim_label_words", "opt_from_curr", "networkCanvas.explore_distances",
40        "networkCanvas.show_component_distances", "fontWeight", "networkCanvas.state",
41        "networkCanvas.selection_behavior", "hubs", "markDistance",
42        "markNConnections", "markNumber", "markSearchString"]
43
44        def __init__(self, parent=None, signalManager=None, name='Net Explorer',
45                     NetworkCanvas=OWNxCanvas):
46            OWWidget.__init__(self, parent, signalManager, name, noReport=True)
47            #self.contextHandlers = {"": DomainContextHandler("", [ContextField("attributes", selected="markerAttributes"), ContextField("attributes", selected="tooltipAttributes"), "color"])}
48            self.inputs = [("Network", Orange.network.Graph, self.set_graph, Default),
49                           ("Items", Orange.data.Table, self.set_items),
50                           ("Item Subset", Orange.data.Table, self.mark_items),
51                           ("Distances", Orange.core.SymMatrix, self.set_items_distance_matrix),
52                           ("Net View", Orange.network.NxView, self.set_network_view)]
53
54            self.outputs = [("Selected Network", Orange.network.Graph),
55                            ("Distance Matrix", Orange.core.SymMatrix),
56                            ("Marked Items", Orange.data.Table),
57                            ("Selected Items", Orange.data.Table),
58                            ("Other Items", Orange.data.Table)]
59                            #("Attribute Selection List", AttributeList)]
60
61            self.networkCanvas = NetworkCanvas(self, self.mainArea, "Net Explorer")
62
63            self.markerAttributes = []
64            self.tooltipAttributes = []
65            self.edgeLabelAttributes = []
66            self.attributes = []
67            self.edgeAttributes = []
68            self.autoSendSelection = False
69            self.graphShowGrid = 1  # show gridlines in the graph
70            self.markNConnections = 2
71            self.markNumber = 0
72            self.markProportion = 0
73            self.markSearchString = ""
74            self.markDistance = 2
75            self.frSteps = 1
76            self.hubs = 0
77            self.color = 0
78            self.edgeColor = 0
79            self.vertexSize = 0
80            self.nShown = self.nHidden = self.nMarked = self.nSelected = self.verticesPerEdge = self.edgesPerVertex = 0
81            self.optimizeWhat = 1
82            self.maxLinkSize = 3
83            self.maxVertexSize = 7
84            self.minVertexSize = 12
85            self.labelsOnMarkedOnly = 0
86            self.invertSize = 0
87            self.optMethod = 0
88            self.lastVertexSizeColumn = ''
89            self.lastColorColumn = ''
90            self.lastNameComponentAttribute = ''
91            self.lastLabelColumns = set()
92            self.lastTooltipColumns = set()
93            self.showWeights = 0
94            self.showEdgeLabels = 0
95            self.colorSettings = None
96            self.selectedSchemaIndex = 0
97            self.edgeColorSettings = [('net_edges', [[], [('contPalette', (4294967295L, 4278190080L, 0))], [('discPalette', [(204, 204, 204), (179, 226, 205), (253, 205, 172), (203, 213, 232), (244, 202, 228), (230, 245, 201), (255, 242, 174), (241, 226, 204)])]]), ('Default', [[], [('contPalette', (4294967295L, 4278190080L, 0))], [('discPalette', [(0, 0, 255), (255, 0, 0), (0, 255, 0), (255, 128, 0), (255, 255, 0), (255, 0, 255), (0, 255, 255), (128, 0, 255), (0, 128, 255), (255, 223, 128), (127, 111, 64), (92, 46, 0), (0, 84, 0), (192, 192, 0), (0, 127, 127), (128, 0, 0), (127, 0, 127)])]])]
98            self.selectedEdgeSchemaIndex = 0
99            self.items_matrix = None
100            self.showDistances = 0
101            self.showMissingValues = 0
102            self.fontSize = 12
103            self.fontWeight = 1
104            self.mdsTorgerson = 0
105            self.mdsAvgLinkage = 1
106            self.mdsSteps = 10000
107            self.mdsRefresh = 50
108            self.mdsStressDelta = 0.0000001
109            self.organism = 'goa_human'
110            self.showTextMiningInfo = 0
111            self.toolbarSelection = 0
112            self.minComponentEdgeWidth = 10
113            self.maxComponentEdgeWidth = 70
114            self.mdsFromCurrentPos = 0
115            self.tabIndex = 0
116            self.number_of_nodes_label = -1
117            self.number_of_edges_label = -1
118            self.opt_from_curr = False
119
120            self.checkSendMarkedNodes = True
121            self.checkSendSelectedNodes = True
122            self.explore_distances = False
123
124            self.loadSettings()
125
126            self._network_view = None
127            self.graph = None
128            self.graph_base = None
129            self.markInputItems = None
130
131            # if optimization method is set to FragViz, set it to FR
132            if self.optMethod == 9:
133                self.optMethod = 3
134
135            self.networkCanvas.showMissingValues = self.showMissingValues
136            self.mainArea.layout().addWidget(self.networkCanvas)
137
138            self.networkCanvas.maxLinkSize = self.maxLinkSize
139
140            self.tabs = OWGUI.tabWidget(self.controlArea)
141
142            self.verticesTab = OWGUI.createTabPage(self.tabs, "Nodes")
143            self.edgesTab = OWGUI.createTabPage(self.tabs, "Edges")
144            self.markTab = OWGUI.createTabPage(self.tabs, "Mark")
145            self.infoTab = OWGUI.createTabPage(self.tabs, "Info")
146            self.performanceTab = OWGUI.createTabPage(self.tabs, "Performance")
147
148            self.tabs.setCurrentIndex(self.tabIndex)
149            self.connect(self.tabs, SIGNAL("currentChanged(int)"), lambda index: setattr(self, 'tabIndex', index))
150
151            self.optimizeBox = OWGUI.radioButtonsInBox(self.verticesTab, self, "optimizeWhat", [], "Optimize", addSpace=False)
152
153            self.optCombo = OWGUI.comboBox(self.optimizeBox, self, "optMethod", label='Method:     ', orientation='horizontal', callback=self.graph_layout_method)
154            self.optCombo.addItem("No optimization")
155            self.optCombo.addItem("Random")
156            self.optCombo.addItem("Fruchterman Reingold")
157            self.optCombo.addItem("Fruchterman Reingold Weighted")
158            self.optCombo.addItem("Fruchterman Reingold Radial")
159            self.optCombo.addItem("Circular Crossing Reduction")
160            self.optCombo.addItem("Circular Original")
161            self.optCombo.addItem("Circular Random")
162            self.optCombo.addItem("FragViz")
163            self.optCombo.addItem("MDS")
164            self.optCombo.addItem("Pivot MDS")
165            self.optCombo.setCurrentIndex(self.optMethod)
166            self.stepsSpin = OWGUI.spin(self.optimizeBox, self, "frSteps", 1, 100000, 1, label="Iterations: ")
167            self.cb_opt_from_curr = OWGUI.checkBox(self.optimizeBox, self, "opt_from_curr", label="Optimize from current positions")
168            self.cb_opt_from_curr.setEnabled(False)
169            self.stepsSpin.setEnabled(False)
170
171            self.optButton = OWGUI.button(self.optimizeBox, self, "Optimize layout", callback=self.graph_layout, toggleButton=1)
172
173            colorBox = OWGUI.widgetBox(self.verticesTab, "Node color attribute", orientation="horizontal", addSpace=False)
174            self.colorCombo = OWGUI.comboBox(colorBox, self, "color", callback=self.set_node_colors)
175            self.colorCombo.addItem("(same color)")
176            OWGUI.button(colorBox, self, "palette", self._set_colors, tooltip="Set node color palette", width=60, debuggingEnabled=0)
177
178            ib = OWGUI.widgetBox(self.verticesTab, "Node size attribute", orientation="vertical", addSpace=False)
179            hb = OWGUI.widgetBox(ib, orientation="horizontal", addSpace=False)
180            OWGUI.checkBox(hb, self, "invertSize", "Invert size", callback=self.set_node_sizes)
181            OWGUI.spin(hb, self, "minVertexSize", 5, 200, 1, label="Min:", callback=self.set_node_sizes)
182            OWGUI.spin(hb, self, "maxVertexSize", 5, 200, 1, label="Max:", callback=self.set_node_sizes)
183            self.vertexSizeCombo = OWGUI.comboBox(ib, self, "vertexSize", callback=self.set_node_sizes)
184            self.vertexSizeCombo.addItem("(none)")
185
186            self.attBox = OWGUI.widgetBox(self.verticesTab, "Node labels | tooltips", orientation="vertical", addSpace=False)
187            hb = OWGUI.widgetBox(self.attBox, orientation="horizontal", addSpace=False)
188            self.attListBox = OWGUI.listBox(hb, self, "markerAttributes", "attributes", selectionMode=QListWidget.MultiSelection, callback=self._clicked_att_lstbox)
189            self.tooltipListBox = OWGUI.listBox(hb, self, "tooltipAttributes", "attributes", selectionMode=QListWidget.MultiSelection, callback=self._clicked_tooltip_lstbox)
190            OWGUI.spin(self.attBox, self, "networkCanvas.trim_label_words", 0, 5, 1, label='Trim label words to', callback=self._clicked_att_lstbox)
191
192            ib = OWGUI.widgetBox(self.edgesTab, "General", orientation="vertical")
193            OWGUI.checkBox(ib, self, 'networkCanvas.show_weights', 'Show weights', callback=self.networkCanvas.set_edge_labels)
194            #OWGUI.checkBox(ib, self, 'showEdgeLabels', 'Show labels on edges', callback=(lambda: self._set_canvas_attr('showEdgeLabels', self.showEdgeLabels)))
195            OWGUI.spin(ib, self, "maxLinkSize", 1, 50, 1, label="Max edge width:", callback=self.set_edge_sizes)
196            self.cb_show_distances = OWGUI.checkBox(ib, self, 'explore_distances', 'Explore node distances', callback=self.set_explore_distances, disabled=1)
197            self.cb_show_component_distances = OWGUI.checkBox(ib, self, 'networkCanvas.show_component_distances', 'Show component distances', callback=self.networkCanvas.set_show_component_distances, disabled=1)
198
199            colorBox = OWGUI.widgetBox(self.edgesTab, "Edge color attribute", orientation="horizontal", addSpace=False)
200            self.edgeColorCombo = OWGUI.comboBox(colorBox, self, "edgeColor", callback=self.set_edge_colors)
201            self.edgeColorCombo.addItem("(same color)")
202            OWGUI.button(colorBox, self, "palette", self._set_edge_color_palette, tooltip="Set edge color palette", width=60, debuggingEnabled=0)
203
204            self.edgeLabelBox = OWGUI.widgetBox(self.edgesTab, "Edge labels", addSpace=False)
205            self.edgeLabelListBox = OWGUI.listBox(self.edgeLabelBox, self, "edgeLabelAttributes", "edgeAttributes", selectionMode=QListWidget.MultiSelection, callback=self._clicked_edge_label_listbox)
206            #self.edgeLabelBox.setEnabled(False)
207
208            ib = OWGUI.widgetBox(self.verticesTab, "General", orientation="vertical")
209            OWGUI.checkBox(ib, self, 'networkCanvas.show_indices', 'Show indices', callback=self.networkCanvas.set_node_labels)
210            OWGUI.checkBox(ib, self, 'labelsOnMarkedOnly', 'Show labels on marked nodes only', callback=(lambda: self.networkCanvas.set_labels_on_marked(self.labelsOnMarkedOnly)))
211            OWGUI.spin(ib, self, "fontSize", 4, 30, 1, label="Font size:", callback=self.set_font)
212            self.comboFontWeight = OWGUI.comboBox(ib, self, "fontWeight", label='Font weight:', orientation='horizontal', callback=self.set_font)
213            self.comboFontWeight.addItem("Normal")
214            self.comboFontWeight.addItem("Bold")
215            self.comboFontWeight.setCurrentIndex(self.fontWeight)
216
217            ib = OWGUI.widgetBox(self.markTab, "Info", orientation="vertical")
218            OWGUI.label(ib, self, "Nodes (shown/hidden): %(number_of_nodes_label)i (%(nShown)i/%(nHidden)i)")
219            OWGUI.label(ib, self, "Selected: %(nSelected)i, marked: %(nMarked)i")
220
221            ribg = OWGUI.radioButtonsInBox(self.markTab, self, "hubs", [], "Mark", callback=self.set_mark_mode)
222            OWGUI.appendRadioButton(ribg, self, "hubs", "None", callback=self.set_mark_mode)
223            OWGUI.appendRadioButton(ribg, self, "hubs", "Search", callback=self.set_mark_mode)
224            self.ctrlMarkSearchString = OWGUI.lineEdit(OWGUI.indentedBox(ribg), self, "markSearchString", callback=self._set_search_string_timer, callbackOnType=True)
225            self.searchStringTimer = QTimer(self)
226            self.connect(self.searchStringTimer, SIGNAL("timeout()"), self.set_mark_mode)
227
228            OWGUI.appendRadioButton(ribg, self, "hubs", "Neighbors of focused", callback=self.set_mark_mode)
229            OWGUI.appendRadioButton(ribg, self, "hubs", "Neighbours of selected", callback=self.set_mark_mode)
230            ib = OWGUI.indentedBox(ribg, orientation=0)
231            self.ctrlMarkDistance = OWGUI.spin(ib, self, "markDistance", 0, 100, 1, label="Distance ",
232                callback=(lambda: self.set_mark_mode(2 if not self.hubs == 3 else 3)))
233            #self.ctrlMarkFreeze = OWGUI.button(ib, self, "&Freeze", value="graph.freezeNeighbours", toggleButton = True)
234            OWGUI.widgetLabel(ribg, "Mark nodes with ...")
235            OWGUI.appendRadioButton(ribg, self, "hubs", "at least N connections", callback=self.set_mark_mode)
236            OWGUI.appendRadioButton(ribg, self, "hubs", "at most N connections", callback=self.set_mark_mode)
237            self.ctrlMarkNConnections = OWGUI.spin(OWGUI.indentedBox(ribg), self, "markNConnections", 0, 1000000, 1, label="N ",
238                callback=(lambda: self.set_mark_mode(4 if not self.hubs == 5 else 5)))
239            OWGUI.appendRadioButton(ribg, self, "hubs", "more connections than any neighbour", callback=self.set_mark_mode)
240            OWGUI.appendRadioButton(ribg, self, "hubs", "more connections than avg neighbour", callback=self.set_mark_mode)
241            OWGUI.appendRadioButton(ribg, self, "hubs", "most connections", callback=self.set_mark_mode)
242            ib = OWGUI.indentedBox(ribg)
243            self.ctrlMarkNumber = OWGUI.spin(ib, self, "markNumber", 0, 1000000, 1, label="Number of nodes:", callback=(lambda h=8: self.set_mark_mode(h)))
244            OWGUI.widgetLabel(ib, "(More nodes are marked in case of ties)")
245            self.markInputRadioButton = OWGUI.appendRadioButton(ribg, self, "hubs", "Mark nodes given in the input signal", callback=self.set_mark_mode)
246            ib = OWGUI.indentedBox(ribg)
247            self.markInput = 0
248            self.markInputCombo = OWGUI.comboBox(ib, self, "markInput", callback=(lambda h=9: self.set_mark_mode(h)))
249            self.markInputRadioButton.setEnabled(False)
250
251            #ib = OWGUI.widgetBox(self.markTab, "General", orientation="vertical")
252            #self.checkSendMarkedNodes = True
253            #OWGUI.checkBox(ib, self, 'checkSendMarkedNodes', 'Send marked nodes', callback = self.send_marked_nodes, disabled=0)
254
255            self.toolbar = OWGUI.widgetBox(self.controlArea, orientation='horizontal')
256            prevstate = self.networkCanvas.state
257            prevselbeh = self.networkCanvas.selection_behavior
258            G = self.networkCanvas.gui
259            self.zoomSelectToolbar = G.zoom_select_toolbar(self.toolbar, nomargin=True, buttons=
260                G.default_zoom_select_buttons +
261                [
262                    G.Spacing,
263                    ("buttonM2S", "Marked to selection", None, None, "marked_to_selected", 'Dlg_Mark2Sel'),
264                    ("buttonS2M", "Selection to marked", None, None, "selected_to_marked", 'Dlg_Sel2Mark'),
265                    ("buttonHSEL", "Hide selection", None, None, "hide_selection", 'Dlg_HideSelection'),
266                    ("buttonSSEL", "Show all nodes", None, None, "show_selection", 'Dlg_ShowSelection'),
267                    #("buttonUN", "Hide unselected", None, None, "hideUnSelectedVertices", 'Dlg_SelectedNodes'),
268                    #("buttonSW", "Show all nodes", None, None, "showAllVertices", 'Dlg_clear'),
269                ])
270            self.zoomSelectToolbar.buttons[G.SendSelection].clicked.connect(self.send_data)
271            self.zoomSelectToolbar.buttons[G.SendSelection].clicked.connect(self.send_marked_nodes)
272            self.zoomSelectToolbar.buttons[("buttonHSEL", "Hide selection", None, None, "hide_selection", 'Dlg_HideSelection')].clicked.connect(self.hide_selection)
273            self.zoomSelectToolbar.buttons[("buttonSSEL", "Show all nodes", None, None, "show_selection", 'Dlg_ShowSelection')].clicked.connect(self.show_selection)
274            #self.zoomSelectToolbar.buttons[G.SendSelection].hide()
275            self.zoomSelectToolbar.select_selection_behaviour(prevselbeh)
276            self.zoomSelectToolbar.select_state(prevstate)
277
278            ib = OWGUI.widgetBox(self.infoTab, "General")
279            OWGUI.label(ib, self, "Number of nodes: %(number_of_nodes_label)i")
280            OWGUI.label(ib, self, "Number of edges: %(number_of_edges_label)i")
281            OWGUI.label(ib, self, "Nodes per edge: %(verticesPerEdge).2f")
282            OWGUI.label(ib, self, "Edges per node: %(edgesPerVertex).2f")
283
284            ib = OWGUI.widgetBox(self.infoTab, orientation="horizontal")
285
286            OWGUI.button(ib, self, "Save net", callback=self.save_network, debuggingEnabled=False)
287            OWGUI.button(ib, self, "Save img", callback=self.networkCanvas.saveToFile, debuggingEnabled=False)
288            self.reportButton = OWGUI.button(ib, self, "&Report", self.reportAndFinish, debuggingEnabled=0)
289            self.reportButton.setAutoDefault(0)
290
291            #OWGUI.button(self.edgesTab, self, "Clustering", callback=self.clustering)
292            ib = OWGUI.widgetBox(self.infoTab, "Edit")
293            self.editAttribute = 0
294            self.editCombo = OWGUI.comboBox(ib, self, "editAttribute", label="Edit attribute:", orientation="horizontal")
295            self.editCombo.addItem("Select attribute")
296            self.editValue = ''
297            hb = OWGUI.widgetBox(ib, orientation="horizontal")
298            OWGUI.lineEdit(hb, self, "editValue", "Value:", orientation='horizontal')
299            OWGUI.button(hb, self, "Set", callback=self.edit)
300
301            ib = OWGUI.widgetBox(self.infoTab, "Prototype")
302            ib.setVisible(True)
303
304            OWGUI.lineEdit(ib, self, "organism", "Organism:", orientation='horizontal')
305
306            self.nameComponentAttribute = 0
307            self.nameComponentCombo = OWGUI.comboBox(ib, self, "nameComponentAttribute", callback=self.nameComponents, label="Name components:", orientation="horizontal")
308            self.nameComponentCombo.addItem("Select attribute")
309
310            self.showComponentAttribute = 0
311            self.showComponentCombo = OWGUI.comboBox(ib, self, "showComponentAttribute", callback=self.showComponents, label="Labels on components:", orientation="horizontal")
312            self.showComponentCombo.addItem("Select attribute")
313            OWGUI.checkBox(ib, self, 'showTextMiningInfo', "Show text mining info")
314
315            #OWGUI.spin(ib, self, "rotateSteps", 1, 10000, 1, label="Rotate max steps: ")
316            OWGUI.spin(ib, self, "minComponentEdgeWidth", 0, 100, 1, label="Min component edge width: ", callback=(lambda changedMin=1: self.set_component_edge_width(changedMin)))
317            OWGUI.spin(ib, self, "maxComponentEdgeWidth", 0, 200, 1, label="Max component edge width: ", callback=(lambda changedMin=0: self.set_component_edge_width(changedMin)))
318
319            self.attSelectionAttribute = 0
320            self.comboAttSelection = OWGUI.comboBox(ib, self, "attSelectionAttribute", label='Send attribute selection list:', orientation='horizontal', callback=self.sendAttSelectionList)
321            self.comboAttSelection.addItem("Select attribute")
322            self.autoSendAttributes = 0
323            OWGUI.checkBox(ib, self, 'autoSendAttributes', "auto send attributes", callback=self.setAutoSendAttributes)
324
325            self.icons = self.createAttributeIconDict()
326            self.set_mark_mode()
327
328            self.networkCanvas.gui.effects_box(self.performanceTab)
329
330            self.verticesTab.layout().addStretch(1)
331            self.edgesTab.layout().addStretch(1)
332            self.markTab.layout().addStretch(1)
333            self.infoTab.layout().addStretch(1)
334            self.performanceTab.layout().addStretch(1)
335
336            dlg = self._create_color_dialog(self.colorSettings, self.selectedSchemaIndex)
337            self.networkCanvas.contPalette = dlg.getContinuousPalette("contPalette")
338            self.networkCanvas.discPalette = dlg.getDiscretePalette("discPalette")
339
340            dlg = self._create_color_dialog(self.edgeColorSettings, self.selectedEdgeSchemaIndex)
341            self.networkCanvas.contEdgePalette = dlg.getContinuousPalette("contPalette")
342            self.networkCanvas.discEdgePalette = dlg.getDiscretePalette("discPalette")
343
344            self.graph_layout_method()
345            self.set_font()
346            self.set_graph(None)
347
348            self.setMinimumWidth(900)
349
350            self.connect(self.networkCanvas, SIGNAL("marked_points_changed()"), self.send_marked_nodes)
351            self.connect(self.networkCanvas, SIGNAL("selection_changed()"), self.send_data)
352
353        def hide_selection(self):
354            nodes = set(self.graph.nodes()).difference(self.networkCanvas.selected_nodes())
355            self.change_graph(Orange.network.nx.Graph.subgraph(self.graph, nodes))
356
357        def show_selection(self):
358            self.change_graph(self.graph_base)
359
360        def edit(self):
361            if self.graph is None:
362                return
363
364            vars = [x.name for x in self.graph_base.items_vars()]
365            if not self.editCombo.currentText() in vars:
366                return
367            att = str(self.editCombo.currentText())
368            vertices = self.networkCanvas.selected_nodes()
369
370            if len(vertices) == 0:
371                return
372
373            items = self.graph_base.items()
374            if items.domain[att].var_type == Orange.feature.Type.Continuous:
375                for v in vertices:
376                    items[v][att] = float(self.editValue)
377            else:
378                for v in vertices:
379                    items[v][att] = str(self.editValue)
380
381        def set_items_distance_matrix(self, matrix):
382            self.error()
383            self.warning()
384            self.information()
385
386            self.cb_show_distances.setEnabled(0)
387            self.cb_show_component_distances.setEnabled(0)
388
389            if matrix is None or self.graph_base is None:
390                self.items_matrix = None
391                self.networkCanvas.items_matrix = None
392                self.information('No graph found!')
393                return
394
395            if matrix.dim != self.graph_base.number_of_nodes():
396                self.error('The number of vertices does not match matrix size.')
397                self.items_matrix = None
398                self.networkCanvas.items_matrix = None
399                return
400
401            self.items_matrix = matrix
402            self.networkCanvas.items_matrix = matrix
403            self.cb_show_distances.setEnabled(1)
404            self.cb_show_component_distances.setEnabled(1)
405
406            if str(self.optMethod) in ['8', '9', '10']:
407                if self.items_matrix is not None and self.graph is not None and \
408                self.items_matrix.dim == self.graph.number_of_nodes():
409                    self.optButton.setEnabled(True)
410                    self.optButton.setChecked(True)
411                    self.graph_layout()
412
413        def _set_canvas_attr(self, attr, value):
414            setattr(self.networkCanvas, attr, value)
415            self.networkCanvas.updateCanvas()
416
417        def _set_curve_attr(self, attr, value):
418            setattr(self.networkCanvas.networkCurve, attr, value)
419            self.networkCanvas.updateCanvas()
420
421        def _set_search_string_timer(self):
422            self.hubs = 1
423            self.searchStringTimer.stop()
424            self.searchStringTimer.start(1000)
425
426        def set_mark_mode(self, i=None):
427            self.searchStringTimer.stop()
428            if not i is None:
429                self.hubs = i
430
431            QObject.disconnect(self.networkCanvas, SIGNAL('selection_changed()'), self.networkCanvas.mark_on_selection_changed)
432            QObject.disconnect(self.networkCanvas, SIGNAL('point_hovered(Point*)'), self.networkCanvas.mark_on_focus_changed)
433
434            if self.graph is None:
435                return
436
437            hubs = self.hubs
438
439            if hubs in [0, 1, 2, 3]:
440                if hubs == 0:
441                    self.networkCanvas.networkCurve.clear_node_marks()
442                elif hubs == 1:
443                    if self.graph_base.items() is None or self.markSearchString == '':
444                        self.networkCanvas.networkCurve.clear_node_marks()
445                        return
446
447                    txt = self.markSearchString
448                    toMark = set(i for i, values in enumerate(self.graph_base.items()) if txt.lower() in " ".join([str(values[ndx]).decode("ascii", "ignore").lower() for ndx in range(len(self.graph_base.items().domain)) + self.graph_base.items().domain.getmetas().keys()]))
449                    toMark = toMark.intersection(self.graph.nodes())
450                    self.networkCanvas.networkCurve.clear_node_marks()
451                    self.networkCanvas.networkCurve.set_node_marks(dict((i, True) for i in toMark))
452                elif hubs == 2:
453                    #print "mark on focus"
454                    self.networkCanvas.mark_neighbors = self.markDistance
455                    QObject.connect(self.networkCanvas, SIGNAL('point_hovered(Point*)'), self.networkCanvas.mark_on_focus_changed)
456                elif hubs == 3:
457                    #print "mark selected"
458                    self.networkCanvas.mark_neighbors = self.markDistance
459                    QObject.connect(self.networkCanvas, SIGNAL('selection_changed()'), self.networkCanvas.mark_on_selection_changed)
460                    self.networkCanvas.mark_on_selection_changed()
461
462            elif hubs in [4, 5, 6, 7, 8, 9]:
463
464                powers = sorted(self.graph.degree_iter(), key=itemgetter(1), reverse=True)
465
466                if hubs == 4:
467                    #print "mark at least N connections"
468                    N = self.markNConnections
469                    self.networkCanvas.networkCurve.set_node_marks(dict((i, True) if \
470                        d >= N else (i, False) for i, d in powers))
471                elif hubs == 5:
472                    #print "mark at most N connections"
473                    N = self.markNConnections
474                    self.networkCanvas.networkCurve.set_node_marks(dict((i, True) if \
475                        d <= N else (i, False) for i, d in powers))
476                elif hubs == 6:
477                    #print "mark more than any"
478                    self.networkCanvas.networkCurve.set_node_marks(dict((i, True) if \
479                        d > max([0] + self.graph.degree(self.graph.neighbors(i)).values()) \
480                        else (i, False) for i, d in powers))
481                elif hubs == 7:
482                    #print "mark more than avg"
483                    self.networkCanvas.networkCurve.set_node_marks(dict((i, True) if \
484                        d > statc.mean([0] + self.graph.degree(self.graph.neighbors(i)).values()) \
485                        else (i, False) for i, d in powers))
486                    self.networkCanvas.replot()
487                elif hubs == 8:
488                    #print "mark most"
489                    self.networkCanvas.networkCurve.clear_node_marks()
490
491                    if self.markNumber < 1:
492                        return
493
494                    cut = min(self.markNumber, len(powers))
495                    cutPower = powers[cut - 1][1]
496                    while cut < len(powers) and powers[cut][1] == cutPower:
497                        cut += 1
498
499                    self.networkCanvas.networkCurve.clear_node_marks()
500                    self.networkCanvas.networkCurve.set_node_marks(dict((i, True) for \
501                        i, d in powers[:cut]))
502
503                elif hubs == 9:
504                    if self.graph_base.items() is None:
505                        self.networkCanvas.networkCurve.clear_node_marks()
506                        return
507
508                    var = str(self.markInputCombo.currentText())
509                    if self.markInputItems is not None and len(self.markInputItems) > 0:
510                        if var == 'ID':
511                            values = [x.id for x in self.markInputItems]
512                            tomark = dict((x, True) for x in self.graph.nodes() if self.graph_base.items()[x].id in values)
513                        else:
514                            values = [str(x[var]).strip().upper() for x in self.markInputItems]
515                            tomark = dict((x, True) for x in self.graph.nodes() if str(self.graph_base.items()[x][var]).strip().upper() in values)
516                        self.networkCanvas.networkCurve.clear_node_marks()
517                        self.networkCanvas.networkCurve.set_node_marks(tomark)
518
519                    else:
520                        self.networkCanvas.networkCurve.clear_node_marks()
521
522            self.nMarked = len(self.networkCanvas.marked_nodes())
523
524        def save_network(self):
525            if self.networkCanvas is None or self.graph is None:
526                return
527
528            filename = QFileDialog.getSaveFileName(self, 'Save Network File', \
529                '', 'NetworkX graph as Python pickle (*.gpickle)\nPajek ' + \
530                'network (*.net)\nGML network (*.gml)')
531            filename = unicode(filename)
532            if filename:
533                fn = ""
534                head, tail = os.path.splitext(filename)
535                if not tail:
536                    fn = head + ".net"
537                else:
538                    fn = filename
539
540                items = self.graph.items()
541                for i in range(self.graph.number_of_nodes()):
542                    graph_node = self.graph.node[i]
543                    plot_node = self.networkCanvas.networkCurve.nodes()[i]
544
545                    if items is not None:
546                        ex = items[i]
547                        if 'x' in ex.domain:
548                            ex['x'] = plot_node.x()
549                        if 'y' in ex.domain:
550                            ex['y'] = plot_node.y()
551
552                    graph_node['x'] = plot_node.x()
553                    graph_node['y'] = plot_node.y()
554
555                Orange.network.readwrite.write(self.graph, fn)
556
557        def send_data(self):
558            selected_nodes = self.networkCanvas.selected_nodes()
559            self.nSelected = len(selected_nodes)
560
561            if len(self.signalManager.getLinks(self, None, \
562                "Selected Items", None)) > 0 or \
563                    len(self.signalManager.getLinks(self, None, \
564                        "Unselected Items", None)) > 0 or \
565                            len(self.signalManager.getLinks(self, None, \
566                                "Selected Network", None)) > 0:
567
568                # signal connected
569                graph = self.graph_base.subgraph(selected_nodes)
570
571                if graph is not None:
572                    self.send("Selected Items", graph.items())
573
574                    if len(self.signalManager.getLinks(self, None, \
575                                                "Unselected Items", None)) > 0:
576                        nodes = self.networkCanvas.not_selected_nodes()
577                        if len(nodes) > 0 and self.graph_base.items() is not None:
578                            self.send("Other Items", self.graph_base.items().getitems(nodes))
579                        else:
580                            self.send("Other Items", None)
581
582                    self.send("Selected Network", graph)
583                else:
584                    self.send("Selected Items", None)
585                    self.send("Other Items", None)
586                    self.send("Selected Network", None)
587
588            if len(self.signalManager.getLinks(self, None, \
589                                "Selected Items Distance Matrix", None)) > 0:
590                # signal connected
591                matrix = None if self.items_matrix is None else self.items_matrix.getitems(selected_nodes)
592                self.send("Distance Matrix", matrix)
593
594        def send_marked_nodes(self):
595            if self.checkSendMarkedNodes and \
596                len(self.signalManager.getLinks(self, None, \
597                                                "Marked Items", None)) > 0:
598                # signal connected
599                markedNodes = self.networkCanvas.marked_nodes()
600
601                if len(markedNodes) > 0 and self.graph is not None and\
602                                         self.graph_base.items() is not None:
603
604                    items = self.graph_base.items().getitems(markedNodes)
605                    self.send("Marked Items", items)
606                else:
607                    self.send("Marked Items", None)
608
609        def _set_combos(self):
610            vars = self.graph_base.items_vars()
611            edgeVars = self.graph_base.links_vars()
612            lastLabelColumns = self.lastLabelColumns
613            lastTooltipColumns = self.lastTooltipColumns
614
615            self._clear_combos()
616
617            self.attributes = [(var.name, var.varType) for var in vars]
618            self.edgeAttributes = [(var.name, var.varType) for var in edgeVars]
619
620            for var in vars:
621                if var.varType in [Orange.feature.Type.Discrete, \
622                                   Orange.feature.Type.Continuous]:
623                    self.colorCombo.addItem(self.icons.get(var.varType, \
624                                            self.icons[-1]), unicode(var.name))
625
626                if var.varType in [Orange.feature.Type.String] and hasattr(self.graph, 'items') and self.graph_base.items() is not None and len(self.graph_base.items()) > 0:
627
628                    value = self.graph_base.items()[0][var].value
629
630                    # can value be a list?
631                    try:
632                        if type(eval(value)) == type([]):
633                            self.vertexSizeCombo.addItem(self.icons.get(var.varType, self.icons[-1]), unicode(var.name))
634                            continue
635                    except:
636                        pass
637
638                    if len(value.split(',')) > 1:
639                        self.vertexSizeCombo.addItem(self.icons.get(var.varType, self.icons[-1]), "num of " + unicode(var.name))
640
641                elif var.varType in [Orange.feature.Type.Continuous]:
642                    self.vertexSizeCombo.addItem(self.icons.get(var.varType, self.icons[-1]), unicode(var.name))
643
644                self.nameComponentCombo.addItem(self.icons.get(var.varType, self.icons[-1]), unicode(var.name))
645                self.showComponentCombo.addItem(self.icons.get(var.varType, self.icons[-1]), unicode(var.name))
646                self.editCombo.addItem(self.icons.get(var.varType, self.icons[-1]), unicode(var.name))
647                self.comboAttSelection.addItem(self.icons.get(var.varType, self.icons[-1]), unicode(var.name))
648
649            for var in edgeVars:
650                if var.varType in [Orange.feature.Type.Discrete, Orange.feature.Type.Continuous]:
651                    self.edgeColorCombo.addItem(self.icons.get(var.varType, self.icons[-1]), unicode(var.name))
652
653            for i in range(self.vertexSizeCombo.count()):
654                if self.lastVertexSizeColumn == \
655                        self.vertexSizeCombo.itemText(i):
656                    self.vertexSize = i
657                    self.set_node_sizes()
658                    break
659
660            for i in range(self.colorCombo.count()):
661                if self.lastColorColumn == self.colorCombo.itemText(i):
662                    self.color = i
663                    self.set_node_colors()
664                    break
665
666            for i in range(self.attListBox.count()):
667                if str(self.attListBox.item(i).text()) in lastLabelColumns:
668                    self.attListBox.item(i).setSelected(1)
669                self._clicked_att_lstbox()
670
671            for i in range(self.tooltipListBox.count()):
672                if str(self.tooltipListBox.item(i).text()) \
673                                                    in lastTooltipColumns:
674                    self.tooltipListBox.item(i).setSelected(1)
675                self._clicked_tooltip_lstbox()
676
677            self.lastLabelColumns = lastLabelColumns
678            self.lastTooltipColumns = lastTooltipColumns
679
680        def _clear_combos(self):
681            self.attributes = []
682            self.edgeAttributes = []
683
684            self.colorCombo.clear()
685            self.vertexSizeCombo.clear()
686            self.nameComponentCombo.clear()
687            self.showComponentCombo.clear()
688            self.edgeColorCombo.clear()
689            self.editCombo.clear()
690            self.comboAttSelection.clear()
691
692            self.colorCombo.addItem("(same color)")
693            self.edgeColorCombo.addItem("(same color)")
694            self.vertexSizeCombo.addItem("(same size)")
695            self.nameComponentCombo.addItem("Select attribute")
696            self.showComponentCombo.addItem("Select attribute")
697            self.editCombo.addItem("Select attribute")
698            self.comboAttSelection.addItem("Select attribute")
699
700        def compute_network_info(self):
701            self.nShown = self.graph.number_of_nodes()
702
703            if self.graph.number_of_edges() > 0:
704                self.verticesPerEdge = float(self.graph.number_of_nodes()) / float(self.graph.number_of_edges())
705            else:
706                self.verticesPerEdge = 0
707
708            if self.graph.number_of_nodes() > 0:
709                self.edgesPerVertex = float(self.graph.number_of_edges()) / float(self.graph.number_of_nodes())
710            else:
711                self.edgesPerVertex = 0
712
713        def change_graph(self, newgraph):
714            self.information()
715
716            # if graph has more nodes and edges than pixels in 1600x1200 display,
717            # it is too big to visualize!
718            if newgraph.number_of_nodes() + newgraph.number_of_edges() > 50000:
719                self.information('New graph is too big to visualize. Keeping the old graph.')
720                return
721
722            self.graph = newgraph
723
724            self.number_of_nodes_label = self.graph.number_of_nodes()
725            self.number_of_edges_label = self.graph.number_of_edges()
726
727            if not self.networkCanvas.change_graph(self.graph):
728                return
729
730            self.compute_network_info()
731
732            if self.graph.number_of_nodes() > 0:
733                t = 1.13850193174e-008 * (self.graph.number_of_nodes() ** 2 + self.graph.number_of_edges())
734                self.frSteps = int(2.0 / t)
735                if self.frSteps < 1: self.frSteps = 1
736                if self.frSteps > 100: self.frSteps = 100
737    #       
738    #        if self.frSteps < 10:
739    #            self.networkCanvas.use_antialiasing = 0
740    #            self.networkCanvas.use_animations = 0
741    #            self.minVertexSize = 5
742    #            self.maxVertexSize = 5
743    #            self.maxLinkSize = 1
744    #            self.optMethod = 0
745    #            self.graph_layout_method()
746
747            animation_enabled = self.networkCanvas.animate_points;
748            self.networkCanvas.animate_points = False;
749
750            self.set_node_sizes()
751            self.set_node_colors()
752            self.set_edge_sizes()
753            self.set_edge_colors()
754
755            self._clicked_att_lstbox()
756            self._clicked_tooltip_lstbox()
757            self._clicked_edge_label_listbox()
758
759            self.networkCanvas.replot()
760
761            self.networkCanvas.animate_points = animation_enabled
762            qApp.processEvents()
763            self.networkCanvas.networkCurve.layout_fr(100, weighted=False, smooth_cooling=True)
764            self.networkCanvas.update_canvas()
765
766        def set_graph_none(self):
767            self.graph = None
768            #self.graph_base = None
769            self._clear_combos()
770            self.number_of_nodes_label = -1
771            self.number_of_edges_label = -1
772            self._items = None
773            self._links = None
774            self.set_items_distance_matrix(None)
775            self.networkCanvas.set_graph(None)
776
777        def set_graph(self, graph, curve=None):
778            self.information()
779            self.warning()
780            self.error()
781
782            if graph is None:
783                self.set_graph_none()
784                return
785
786            if graph.number_of_nodes() < 2:
787                self.set_graph_none()
788                self.information('I\'m not really in a mood to visualize just one node. Try again tomorrow.')
789                return
790
791            if graph == self.graph_base and self.graph is not None and \
792                                                    self._network_view is None:
793                self.set_items(graph.items())
794                return
795
796            self.graph_base = graph
797
798            if self._network_view is not None:
799                graph = self._network_view.init_network(graph)
800
801            self.graph = graph
802
803            # if graph has more nodes and edges than pixels in 1600x1200 display,
804            # it is too big to visualize!
805            if self.graph.number_of_nodes() + self.graph.number_of_edges() > 50000:
806                self.set_graph_none()
807                self.error('Graph is too big to visualize. Try using one of the network views.')
808                return
809
810            if self.items_matrix is not None and self.items_matrix.dim != self.graph_base.number_of_nodes():
811                self.set_items_distance_matrix(None)
812
813            self.number_of_nodes_label = self.graph.number_of_nodes()
814            self.number_of_edges_label = self.graph.number_of_edges()
815
816            self.networkCanvas.set_graph(self.graph, curve, items=self.graph_base.items(), links=self.graph_base.links())
817
818            items = self.graph.items()
819            if items is not None and 'x' in items.domain and 'y' in items.domain:
820                positions = dict((node, (items[node]['x'].value, items[node]['y'].value)) \
821                             for node in self.graph if items[node]['x'].value != '?' \
822                             and items[node]['y'].value != '?')
823
824                # ignore start position if all nodes are on the same coordinate
825                if len(set(positions.values())) > 1:
826                    self.networkCanvas.networkCurve.set_node_coordinates(positions)
827
828
829            self.networkCanvas.showEdgeLabels = self.showEdgeLabels
830            self.networkCanvas.maxEdgeSize = self.maxLinkSize
831            self.networkCanvas.minComponentEdgeWidth = self.minComponentEdgeWidth
832            self.networkCanvas.maxComponentEdgeWidth = self.maxComponentEdgeWidth
833            self.networkCanvas.set_labels_on_marked(self.labelsOnMarkedOnly)
834
835            self.compute_network_info()
836            self._set_combos()
837
838            lastNameComponentAttributeFound = False
839            for i in range(self.nameComponentCombo.count()):
840                if self.lastNameComponentAttribute == self.nameComponentCombo.itemText(i):
841                    lastNameComponentAttributeFound = True
842                    self.nameComponentAttribute = i
843                    self.nameComponents()
844                    self.showComponentAttribute = self.showComponentCombo.count() - 1
845                    self.showComponents()
846                    break
847
848            if not lastNameComponentAttributeFound:
849                self.lastNameComponentAttribute = ''
850
851            self.showComponentAttribute = None
852
853            t = 1.13850193174e-008 * (self.graph.number_of_nodes() ** 2 + self.graph.number_of_edges())
854            self.frSteps = int(2.0 / t)
855            if self.frSteps < 1: self.frSteps = 1
856            if self.frSteps > 100: self.frSteps = 100
857
858            # if graph is large, set random layout, min vertex size, min edge size
859            if self.frSteps < 10:
860                self.networkCanvas.update_antialiasing(False)
861                self.networkCanvas.update_animations(False)
862                self.minVertexSize = 5
863                self.maxVertexSize = 5
864                self.maxLinkSize = 1
865                self.optMethod = 0
866                self.graph_layout_method()
867
868            self.networkCanvas.labelsOnMarkedOnly = self.labelsOnMarkedOnly
869            self.networkCanvas.showWeights = self.showWeights
870
871            self.set_node_sizes()
872            self.set_node_colors()
873            self.set_edge_sizes()
874            self.set_edge_colors()
875
876            self._clicked_att_lstbox()
877            self._clicked_tooltip_lstbox()
878            self._clicked_edge_label_listbox()
879
880            self.optButton.setChecked(1)
881            self.graph_layout()
882            self.set_mark_mode()
883
884        def set_network_view(self, nxView):
885            self.error()
886            self.warning()
887            self.information()
888
889            if self.graph is None:
890                self.information('Do not forget to add a graph!')
891
892            if self._network_view is not None:
893                QObject.disconnect(self.networkCanvas, SIGNAL('selection_changed()'), self._network_view.node_selection_changed)
894
895            self._network_view = nxView
896
897            g = self.graph_base
898            if self._network_view is not None:
899                self._network_view.set_nx_explorer(self)
900            else:
901                self.graph_base = None
902
903            self.set_graph(g)
904
905            if self._network_view is not None:
906                QObject.connect(self.networkCanvas, SIGNAL('selection_changed()'), self._network_view.node_selection_changed)
907
908        def set_items(self, items=None):
909            self.error()
910            self.warning()
911            self.information()
912
913            if items is None:
914                return
915
916            if self.graph is None:
917                self.warning('No graph found!')
918                return
919
920            if len(items) != self.graph_base.number_of_nodes():
921                self.error('Table items must have one example for each node.')
922                return
923
924            self.graph_base.set_items(items)
925
926            self.set_node_sizes()
927            self.networkCanvas.items = items
928            self.networkCanvas.showWeights = self.showWeights
929            self.networkCanvas.showEdgeLabels = self.showEdgeLabels
930            self._set_combos()
931            #self.networkCanvas.updateData()
932
933        def mark_items(self, items):
934            self.markInputCombo.clear()
935            self.markInputRadioButton.setEnabled(False)
936            self.markInputItems = items
937
938            self.error()
939            self.warning()
940            self.information()
941
942            if items is None:
943                return
944
945            if self.graph is None or self.graph_base.items() is None or items is None:
946                self.warning('No graph found or no items attached to the graph.')
947                return
948
949            if len(items) > 0:
950                lstOrgDomain = [x.name for x in self.graph_base.items().domain] + [self.graph_base.items().domain[x].name for x in self.graph_base.items().domain.getmetas()]
951                lstNewDomain = [x.name for x in items.domain] + [items.domain[x].name for x in items.domain.getmetas()]
952                commonVars = set(lstNewDomain) & set(lstOrgDomain)
953
954                self.markInputCombo.addItem(self.icons[Orange.feature.Type.Discrete], unicode("ID"))
955
956                if len(commonVars) > 0:
957                    for var in commonVars:
958                        orgVar = self.graph_base.items().domain[var]
959                        mrkVar = items.domain[var]
960
961                        if orgVar.varType == mrkVar.varType and orgVar.varType == Orange.feature.Type.String:
962                            self.markInputCombo.addItem(self.icons[orgVar.varType], unicode(orgVar.name))
963
964                self.markInputRadioButton.setEnabled(True)
965                self.set_mark_mode(9)
966
967        def set_explore_distances(self):
968            QObject.disconnect(self.networkCanvas, SIGNAL('selection_changed()'), self.explore_focused)
969
970            if self.explore_distances:
971                QObject.connect(self.networkCanvas, SIGNAL('selection_changed()'), self.explore_focused)
972
973        def explore_focused(self):
974            sel = self.networkCanvas.selected_nodes()
975            if len(sel) == 1:
976                ndx_1 = sel[0]
977                self.networkCanvas.label_distances = [['%.2f' % \
978                                self.items_matrix[ndx_1][ndx_2]] \
979                                for ndx_2 in self.networkCanvas.graph.nodes()]
980            else:
981                self.networkCanvas.label_distances = None
982
983            self.networkCanvas.set_node_labels(self.lastLabelColumns)
984            self.networkCanvas.replot()
985
986        #######################################################################
987        ### Layout Optimization                                             ###
988        #######################################################################
989
990        def graph_layout(self):
991            if self.graph is None or self.graph.number_of_nodes <= 0:   #grafa se ni
992                self.optButton.setChecked(False)
993                return
994
995            if not self.optButton.isChecked() and not self.optMethod in [2, 3, 9, 10]:
996                self.optButton.setChecked(False)
997                return
998
999            qApp.processEvents()
1000
1001            if self.optMethod == 0:
1002                items = self.graph.items()
1003                if items is not None and 'x' in items.domain and 'y' in items.domain:
1004                    positions = dict((node, (items[node]['x'].value, items[node]['y'].value)) \
1005                                 for node in self.graph if items[node]['x'].value != '?' \
1006                                 and items[node]['y'].value != '?')
1007
1008                    # ignore start position if all nodes are on the same coordinate
1009                    if len(set(positions.values())) > 1:
1010                        self.networkCanvas.networkCurve.set_node_coordinates(positions)
1011            elif self.optMethod == 1:
1012                self.networkCanvas.networkCurve.random()
1013            elif self.optMethod == 2:
1014                self.graph_layout_fr(False)
1015            elif self.optMethod == 3:
1016                self.graph_layout_fr(True)
1017            elif self.optMethod == 4:
1018                self.graph_layout_fr_radial()
1019            elif self.optMethod == 5:
1020                self.networkCanvas.networkCurve.circular(\
1021                                            NetworkCurve.circular_crossing)
1022            elif self.optMethod == 6:
1023                self.networkCanvas.networkCurve.circular(\
1024                                            NetworkCurve.circular_original)
1025            elif self.optMethod == 7:
1026                self.networkCanvas.networkCurve.circular(\
1027                                            NetworkCurve.circular_random)
1028            elif self.optMethod == 8:
1029                self.graph_layout_fragviz()
1030            elif self.optMethod == 9:
1031                self.graph_layout_mds()
1032            elif self.optMethod == 10:
1033                self.graph_layout_pivot_mds()
1034
1035            self.optButton.setChecked(False)
1036            self.networkCanvas.update_canvas()
1037
1038        def graph_layout_method(self, method=None):
1039            self.information()
1040            self.stepsSpin.label.setText('Iterations: ')
1041            self.optButton.setEnabled(True)
1042            self.cb_opt_from_curr.setEnabled(False)
1043
1044            if method is not None:
1045                self.optMethod = method
1046
1047            if str(self.optMethod) == '0':
1048                self.optButton.setEnabled(False)
1049            else:
1050                self.optButton.setEnabled(True)
1051
1052            if str(self.optMethod) in ['2', '3', '4']:
1053                self.stepsSpin.setEnabled(True)
1054
1055            elif str(self.optMethod) in ['8', '9', '10']:
1056                if str(self.optMethod) == '8':
1057                    self.stepsSpin.label.setText('Pivots: ')
1058
1059                if str(self.optMethod) in ['9', '10']:
1060                    self.cb_opt_from_curr.setEnabled(True)
1061
1062                self.stepsSpin.setEnabled(True)
1063
1064                if self.items_matrix is None:
1065                    self.information('Set distance matrix to input signal')
1066                    self.optButton.setEnabled(False)
1067                    return
1068                if self.graph is None:
1069                    self.information('No network found')
1070                    self.optButton.setEnabled(False)
1071                    return
1072                if self.items_matrix.dim != self.graph.number_of_nodes():
1073                    self.error('Distance matrix dimensionality must equal number of vertices')
1074                    self.optButton.setEnabled(False)
1075                    return
1076            else:
1077                self.stepsSpin.setEnabled(False)
1078                self.optButton.setChecked(True)
1079                self.graph_layout()
1080
1081        def mds_progress(self, avgStress, stepCount):
1082            #self.drawForce()
1083
1084            #self.mdsInfoA.setText("Avg. Stress: %.20f" % avgStress)
1085            #self.mdsInfoB.setText("Num. steps: %i" % stepCount)
1086            self.progressBarSet(int(stepCount * 100 / self.frSteps))
1087            qApp.processEvents()
1088
1089        def graph_layout_fragviz(self):
1090            if self.items_matrix is None:
1091                self.information('Set distance matrix to input signal')
1092                self.optButton.setChecked(False)
1093                return
1094
1095            if self.layout is None:
1096                self.information('No network found')
1097                self.optButton.setChecked(False)
1098                return
1099
1100            if self.items_matrix.dim != self.graph.number_of_nodes():
1101                self.error('Distance matrix dimensionality must equal number of vertices')
1102                self.optButton.setChecked(False)
1103                return
1104
1105            if not self.optButton.isChecked():
1106                self.networkCanvas.networkCurve.stopMDS = True
1107                self.optButton.setChecked(False)
1108                self.optButton.setText("Optimize layout")
1109                return
1110
1111            self.optButton.setText("Stop")
1112            self.progressBarInit()
1113            qApp.processEvents()
1114
1115            if self.graph.number_of_nodes() == self.graph_base.number_of_nodes():
1116                matrix = self.items_matrix
1117            else:
1118                matrix = self.items_matrix.get_items(sorted(self.graph.nodes()))
1119
1120            self.networkCanvas.networkCurve.layout_fragviz(self.frSteps, matrix, self.graph, self.mds_progress, self.opt_from_curr)
1121
1122            self.optButton.setChecked(False)
1123            self.optButton.setText("Optimize layout")
1124            self.progressBarFinished()
1125
1126        def graph_layout_mds(self):
1127            if self.items_matrix is None:
1128                self.information('Set distance matrix to input signal')
1129                self.optButton.setChecked(False)
1130                return
1131
1132            if self.layout is None:
1133                self.information('No network found')
1134                self.optButton.setChecked(False)
1135                return
1136
1137            if self.items_matrix.dim != self.graph.number_of_nodes():
1138                self.error('Distance matrix dimensionality must equal number of vertices')
1139                self.optButton.setChecked(False)
1140                return
1141
1142            if not self.optButton.isChecked():
1143                self.networkCanvas.networkCurve.stopMDS = True
1144                self.optButton.setChecked(False)
1145                self.optButton.setText("Optimize layout")
1146                return
1147
1148            self.optButton.setText("Stop")
1149            self.progressBarInit()
1150            qApp.processEvents()
1151
1152            if self.graph.number_of_nodes() == self.graph_base.number_of_nodes():
1153                matrix = self.items_matrix
1154            else:
1155                matrix = self.items_matrix.get_items(sorted(self.graph.nodes()))
1156
1157            self.networkCanvas.networkCurve.layout_mds(self.frSteps, matrix, self.mds_progress, self.opt_from_curr)
1158
1159            self.optButton.setChecked(False)
1160            self.optButton.setText("Optimize layout")
1161            self.progressBarFinished()
1162
1163        def graph_layout_fr(self, weighted):
1164            if self.graph is None:
1165                return
1166
1167            if not self.optButton.isChecked():
1168                self.networkCanvas.networkCurve.stop_optimization()
1169                self.optButton.setChecked(False)
1170                self.optButton.setText("Optimize layout")
1171                return
1172
1173            self.optButton.setText("Stop")
1174            qApp.processEvents()
1175            self.networkCanvas.networkCurve.layout_fr(self.frSteps, False)
1176            self.optButton.setChecked(False)
1177            self.optButton.setText("Optimize layout")
1178
1179        def graph_layout_fr_radial(self):
1180            if self.graph is None:   #grafa se ni
1181                return
1182
1183    #        #print "F-R Radial"
1184    #        k = 1.13850193174e-008
1185    #        nodes = self.graph.number_of_nodes()
1186    #        t = k * nodes * nodes
1187    #        refreshRate = int(5.0 / t)
1188    #        if refreshRate <    1: refreshRate = 1
1189    #        if refreshRate > 1500: refreshRate = 1500
1190    #        #print "refreshRate: " + str(refreshRate)
1191    #       
1192    #        tolerance = 5
1193    #        initTemp = 100
1194    #        centerNdx = 0
1195    #       
1196    #        selection = self.networkCanvas.getSelection()
1197    #        if len(selection) > 0:
1198    #            centerNdx = selection[0]
1199    #           
1200    #        #print "center ndx: " + str(centerNdx)
1201    #        initTemp = self.layout.fr_radial(centerNdx, refreshRate, initTemp)
1202    #        self.networkCanvas.circles = [10000 / 12, 10000/12*2, 10000/12*3]#, 10000/12*4, 10000/12*5]
1203    #        #self.networkCanvas.circles = [100, 200, 300]
1204    #        self.networkCanvas.updateCanvas()
1205    #        self.networkCanvas.circles = []
1206
1207        def graph_layout_pivot_mds(self):
1208            self.information()
1209
1210            if self.items_matrix is None:
1211                self.information('Set distance matrix to input signal')
1212                return
1213
1214            if self.graph_base is None:
1215                self.information('No network found')
1216                return
1217
1218            if self.items_matrix.dim != self.graph_base.number_of_nodes():
1219                self.error('The number of vertices does not match matrix size.')
1220                return
1221
1222            self.frSteps = min(self.frSteps, self.graph.number_of_nodes())
1223            qApp.processEvents()
1224
1225            if self.graph.number_of_nodes() == self.graph_base.number_of_nodes():
1226                matrix = self.items_matrix
1227            else:
1228                matrix = self.items_matrix.get_items(sorted(self.graph.nodes()))
1229
1230            mds = orngMDS.PivotMDS(matrix, self.frSteps)
1231            x, y = mds.optimize()
1232            xy = zip(list(x), list(y))
1233            coors = dict(zip(sorted(self.graph.nodes()), xy))
1234            self.networkCanvas.networkCurve.set_node_coordinates(coors)
1235            self.networkCanvas.update_canvas()
1236
1237        #######################################################################
1238        ### Network Visualization                                           ###
1239        #######################################################################
1240
1241        def _set_colors(self):
1242            dlg = self._create_color_dialog(self.colorSettings, self.selectedSchemaIndex)
1243            if dlg.exec_():
1244                self.colorSettings = dlg.getColorSchemas()
1245                self.selectedSchemaIndex = dlg.selectedSchemaIndex
1246                self.networkCanvas.contPalette = dlg.getContinuousPalette("contPalette")
1247                self.networkCanvas.discPalette = dlg.getDiscretePalette("discPalette")
1248
1249                self.set_node_colors()
1250
1251        def _set_edge_color_palette(self):
1252            dlg = self._create_color_dialog(self.edgeColorSettings, self.selectedEdgeSchemaIndex)
1253            if dlg.exec_():
1254                self.edgeColorSettings = dlg.getColorSchemas()
1255                self.selectedEdgeSchemaIndex = dlg.selectedSchemaIndex
1256                self.networkCanvas.contEdgePalette = dlg.getContinuousPalette("contPalette")
1257                self.networkCanvas.discEdgePalette = dlg.getDiscretePalette("discPalette")
1258
1259                self.set_edge_colors()
1260
1261        def _create_color_dialog(self, colorSettings, selectedSchemaIndex):
1262            c = OWColorPalette.ColorPaletteDlg(self, "Color Palette")
1263            c.createDiscretePalette("discPalette", "Discrete Palette")
1264            c.createContinuousPalette("contPalette", "Continuous Palette")
1265            c.setColorSchemas(colorSettings, selectedSchemaIndex)
1266            return c
1267
1268        def _clicked_att_lstbox(self):
1269            if self.graph is None:
1270                return
1271
1272            self.lastLabelColumns = [self.attributes[i][0] for i in self.markerAttributes]
1273            self.networkCanvas.set_node_labels(self.lastLabelColumns)
1274            self.networkCanvas.replot()
1275
1276        def _clicked_tooltip_lstbox(self):
1277            if self.graph is None:
1278                return
1279
1280            self.lastTooltipColumns = [self.attributes[i][0] for i in self.tooltipAttributes]
1281            self.networkCanvas.set_tooltip_attributes(self.lastTooltipColumns)
1282            self.networkCanvas.replot()
1283
1284        def _clicked_edge_label_listbox(self):
1285            if self.graph is None:
1286                return
1287
1288            self.lastEdgeLabelAttributes = set([self.edgeAttributes[i][0] for i in self.edgeLabelAttributes])
1289            self.networkCanvas.set_edge_labels(self.lastEdgeLabelAttributes)
1290            self.networkCanvas.replot()
1291
1292        def set_node_colors(self):
1293            if self.graph is None:
1294                return
1295
1296            self.networkCanvas.set_node_colors(self.colorCombo.currentText())
1297            self.lastColorColumn = self.colorCombo.currentText()
1298
1299        def set_edge_colors(self):
1300            if self.graph is None:
1301                return
1302
1303            self.networkCanvas.set_edge_colors(self.edgeColorCombo.currentText())
1304            self.lastEdgeColorColumn = self.edgeColorCombo.currentText()
1305
1306        def set_edge_sizes(self):
1307            if self.graph is None:
1308                return
1309
1310            self.networkCanvas.networkCurve.set_edge_sizes(self.maxLinkSize)
1311            self.networkCanvas.replot()
1312
1313        def set_node_sizes(self):
1314            if self.graph is None or self.networkCanvas is None:
1315                return
1316
1317            if self.minVertexSize > self.maxVertexSize:
1318                self.maxVertexSize = self.minVertexSize
1319
1320            items = self.graph_base.items()
1321
1322            if items is None:
1323                self.networkCanvas.networkCurve.set_node_sizes({}, min_size=self.minVertexSize, max_size=self.maxVertexSize)
1324                return
1325
1326            self.lastVertexSizeColumn = self.vertexSizeCombo.currentText()
1327            column = str(self.vertexSizeCombo.currentText())
1328
1329            values = {}
1330            if column in items.domain or (column.startswith("num of ") and column.replace("num of ", "") in items.domain):
1331                if column in items.domain:
1332                    values = dict((x, items[x][column].value) for x in self.graph if not items[x][column].isSpecial())
1333                else:
1334                    values = dict((x, len(items[x][column.replace("num of ", "")].value.split(','))) for x in self.graph)
1335
1336            if len(values) == 0:
1337                values = dict((node, 1.) for node in self.graph)
1338
1339            if self.invertSize:
1340                maxval = max(values.itervalues())
1341                values.update((key, maxval - val) for key, val in values.iteritems())
1342                self.networkCanvas.networkCurve.set_node_sizes(values, min_size=self.minVertexSize, max_size=self.maxVertexSize)
1343            else:
1344                self.networkCanvas.networkCurve.set_node_sizes(values, min_size=self.minVertexSize, max_size=self.maxVertexSize)
1345
1346            self.networkCanvas.replot()
1347
1348        def set_font(self):
1349            if self.networkCanvas is None:
1350                return
1351
1352            weights = {0: 50, 1: 80}
1353
1354            font = self.networkCanvas.font()
1355            font.setPointSize(self.fontSize)
1356            font.setWeight(weights[self.fontWeight])
1357            self.networkCanvas.setFont(font)
1358            self.networkCanvas.fontSize = font
1359            self.networkCanvas.set_node_labels()
1360
1361        def sendReport(self):
1362            self.reportSettings("Graph data",
1363                                [("Number of vertices", self.graph.number_of_nodes()),
1364                                 ("Number of edges", self.graph.number_of_edges()),
1365                                 ("Vertices per edge", "%.3f" % self.verticesPerEdge),
1366                                 ("Edges per vertex", "%.3f" % self.edgesPerVertex),
1367                                 ])
1368            if self.color or self.vertexSize or self.markerAttributes or self.edgeColor:
1369                self.reportSettings("Visual settings",
1370                                    [self.color and ("Vertex color", self.colorCombo.currentText()),
1371                                     self.vertexSize and ("Vertex size", str(self.vertexSizeCombo.currentText()) + " (inverted)" if self.invertSize else ""),
1372                                     self.markerAttributes and ("Labels", ", ".join(self.attributes[i][0] for i in self.markerAttributes)),
1373                                     self.edgeColor and ("Edge colors", self.edgeColorCombo.currentText()),
1374                                    ])
1375            self.reportSettings("Optimization",
1376                                [("Method", self.optCombo.currentText()),
1377                                 ("Iterations", self.frSteps)])
1378            self.reportSection("Graph")
1379            self.reportImage(self.networkCanvas.saveToFileDirect)
1380
1381        #######################################################################
1382        ### PROTOTYPE                                                       ###
1383        #######################################################################
1384
1385        def set_component_edge_width(self, changedMin=True):
1386            if self.networkCanvas is None:
1387                return
1388
1389            canvas = self.networkCanvas
1390            if changedMin:
1391                if self.maxComponentEdgeWidth < self.minComponentEdgeWidth:
1392                    self.maxComponentEdgeWidth = self.minComponentEdgeWidth
1393            else:
1394                if self.minComponentEdgeWidth > self.maxComponentEdgeWidth:
1395                    self.minComponentEdgeWidth = self.maxComponentEdgeWidth
1396
1397            canvas.minComponentEdgeWidth = self.minComponentEdgeWidth
1398            canvas.maxComponentEdgeWidth = self.maxComponentEdgeWidth
1399            self.networkCanvas.updateCanvas()
1400
1401        def showComponents(self):
1402            if self.graph is None or self.graph_base.items() is None:
1403                return
1404
1405            vars = [x.name for x in self.graph_base.items_vars()]
1406
1407            if not self.showComponentCombo.currentText() in vars:
1408                self.networkCanvas.showComponentAttribute = None
1409                self.lastNameComponentAttribute = ''
1410            else:
1411                self.networkCanvas.showComponentAttribute = self.showComponentCombo.currentText()
1412
1413            self.networkCanvas.drawComponentKeywords()
1414
1415        def nameComponents(self):
1416            """Names connected components of genes according to GO terms."""
1417            self.progressBarFinished()
1418            self.lastNameComponentAttribute = None
1419
1420            if self.graph is None or self.graph_base.items() is None:
1421                return
1422
1423            vars = [x.name for x in self.graph_base.items_vars()]
1424            if not self.nameComponentCombo.currentText() in vars:
1425                return
1426
1427            self.progressBarInit()
1428            components = [c for c in Orange.network.nx.algorithms.components.connected_components(self.graph) if len(c) > 1]
1429            if 'component name' in self.graph_base.items().domain:
1430                keyword_table = self.graph_base.items()
1431            else:
1432                keyword_table = Orange.data.Table(Orange.data.Domain(Orange.feature.String('component name')), [[''] for i in range(len(self.graph_base.items()))])
1433
1434            import obiGO
1435            ontology = obiGO.Ontology.Load(progressCallback=self.progressBarSet)
1436            annotations = obiGO.Annotations.Load(self.organism, ontology=ontology, progressCallback=self.progressBarSet)
1437
1438            allGenes = set([e[str(self.nameComponentCombo.currentText())].value for e in self.graph_base.items()])
1439            foundGenesets = False
1440            if len(annotations.geneNames & allGenes) < 1:
1441                allGenes = set(reduce(operator.add, [e[str(self.nameComponentCombo.currentText())].value.split(', ') for e in self.graph_base.items()]))
1442                if len(annotations.geneNames & allGenes) < 1:
1443                    self.warning('no genes found')
1444                    return
1445                else:
1446                    foundGenesets = True
1447
1448            def rank(a, j, reverse=False):
1449                if len(a) <= 0: return
1450
1451                if reverse:
1452                    a.sort(lambda x, y: 1 if x[j] > y[j] else -1 if x[j] < y[j] else 0)
1453                    top_value = a[0][j]
1454                    top_rank = len(a)
1455                    max_rank = float(len(a))
1456                    int_ndx = 0
1457                    for k in range(len(a)):
1458                        if top_value < a[k][j]:
1459                            top_value = a[k][j]
1460                            if k - int_ndx > 1:
1461                                avg_rank = (a[int_ndx][j] + a[k - 1][j]) / 2
1462                                for l in range(int_ndx, k):
1463                                    a[l][j] = avg_rank
1464
1465                            int_ndx = k
1466
1467                        a[k][j] = top_rank / max_rank
1468                        top_rank -= 1
1469
1470                    k += 1
1471                    if k - int_ndx > 1:
1472                        avg_rank = (a[int_ndx][j] + a[k - 1][j]) / 2
1473                        for l in range(int_ndx, k):
1474                            a[l][j] = avg_rank
1475
1476                else:
1477                    a.sort(lambda x, y: 1 if x[j] < y[j] else -1 if x[j] > y[j] else 0)
1478                    top_value = a[0][j]
1479                    top_rank = len(a)
1480                    max_rank = float(len(a))
1481                    int_ndx = 0
1482                    for k in range(len(a)):
1483                        if top_value > a[k][j]:
1484                            top_value = a[k][j]
1485                            if k - int_ndx > 1:
1486                                avg_rank = (a[int_ndx][j] + a[k - 1][j]) / 2
1487                                for l in range(int_ndx, k):
1488                                    a[l][j] = avg_rank
1489
1490                            int_ndx = k
1491
1492                        a[k][j] = top_rank / max_rank
1493                        top_rank -= 1
1494
1495                    k += 1
1496                    if k - int_ndx > 1:
1497                        avg_rank = (a[int_ndx][j] + a[k - 1][j]) / 2
1498                        for l in range(int_ndx, k):
1499                            a[l][j] = avg_rank
1500
1501            for i in range(len(components)):
1502                component = components[i]
1503                if len(component) <= 1:
1504                    continue
1505
1506                if foundGenesets:
1507                    genes = reduce(operator.add, [self.graph_base.items()[v][str(self.nameComponentCombo.currentText())].value.split(', ') for v in component])
1508                else:
1509                    genes = [self.graph_base.items()[v][str(self.nameComponentCombo.currentText())].value for v in component]
1510
1511                res1 = annotations.GetEnrichedTerms(genes, aspect="P")
1512                res2 = annotations.GetEnrichedTerms(genes, aspect="F")
1513                res = res1.items() + res2.items()
1514                #namingScore = [[(1-p_value) * (float(len(g)) / len(genes)) / (float(ref) / len(annotations.geneNames)), ontology.terms[GOId].name, len(g), ref, p_value] for GOId, (g, p_value, ref) in res.items() if p_value < 0.1]
1515                #namingScore = [[(1-p_value) * len(g) / ref, ontology.terms[GOId].name, len(g), ref, p_value] for GOId, (g, p_value, ref) in res.items() if p_value < 0.1]
1516
1517                namingScore = [[len(g), ref, p_value, ontology[GOId].name, len(g), ref, p_value] for GOId, (g, p_value, ref) in res if p_value < 0.1]
1518                if len(namingScore) == 0:
1519                    continue
1520
1521                annotated_genes = max([a[0] for a in namingScore])
1522
1523                rank(namingScore, 1, reverse=True)
1524                rank(namingScore, 2, reverse=True)
1525                rank(namingScore, 0)
1526
1527                namingScore = [[10 * rank_genes + 0.5 * rank_ref + rank_p_value, name, g, ref, p_value] for rank_genes, rank_ref, rank_p_value, name, g, ref, p_value in namingScore]
1528                namingScore.sort(reverse=True)
1529
1530                if len(namingScore) < 1:
1531                    print "warning. no annotations found for group of genes: " + ", ".join(genes)
1532                    continue
1533                elif len(namingScore[0]) < 2:
1534                    print "warning. error computing score for group of genes: " + ", ".join(genes)
1535                    continue
1536
1537                for v in component:
1538                    name = str(namingScore[0][1])
1539                    attrs = "%d/%d, %d, %lf" % (namingScore[0][2], annotated_genes, namingScore[0][3], namingScore[0][4])
1540                    info = ''
1541                    if self.showTextMiningInfo:
1542                        info = "\n" + attrs + "\n" + str(namingScore[0][0])
1543                    keyword_table[v]['component name'] = name + info
1544
1545                self.progressBarSet(i * 100.0 / len(components))
1546
1547            self.lastNameComponentAttribute = self.nameComponentCombo.currentText()
1548            self.set_items(Orange.data.Table([self.graph_base.items(), keyword_table]))
1549            self.progressBarFinished()
1550
1551
1552        def setAutoSendAttributes(self):
1553            print 'TODO setAutoSendAttributes'
1554            #if self.autoSendAttributes:
1555            #    self.networkCanvas.callbackSelectVertex = self.sendAttSelectionList
1556            #else:
1557            #    self.networkCanvas.callbackSelectVertex = None
1558
1559        def sendAttSelectionList(self):
1560            if not self.graph is None:
1561                vars = [x.name for x in self.graph_base.links_vars()]
1562                if not self.comboAttSelection.currentText() in vars:
1563                    return
1564                att = str(self.comboAttSelection.currentText())
1565                vertices = self.networkCanvas.selected_nodes()
1566
1567                if len(vertices) != 1:
1568                    return
1569
1570                attributes = str(self.graph_base.items()[vertices[0]][att]).split(', ')
1571            else:
1572                attributes = None
1573            self.send("Features", attributes)
1574
1575
1576except ImportError as err:
1577    try:
1578        from OWNxCanvas import *
1579    except:
1580        # if Qwt is also not installed throw could not import orangeqt error
1581        raise err
1582
1583    from OWNxExplorerQwt import OWNxExplorerQwt as OWNxExplorer
1584
1585if __name__ == "__main__":
1586    a = QApplication(sys.argv)
1587    ow = OWNxExplorer()
1588    ow.show()
1589
1590    def setNetwork(signal, data, id=None):
1591        if signal == 'Network':
1592            ow.set_graph(data)
1593        #if signal == 'Items':
1594        #    ow.set_items(data)
1595
1596    import OWNxFile
1597    owFile = OWNxFile.OWNxFile()
1598    owFile.send = setNetwork
1599    owFile.show()
1600    owFile.selectNetFile(0)
1601
1602    a.exec_()
1603    ow.saveSettings()
1604    owFile.saveSettings()
Note: See TracBrowser for help on using the repository browser.