source: orange/Orange/OrangeWidgets/Unsupervised/OWNxExplorer.py @ 10929:bda30472945b

Revision 10929:bda30472945b, 75.3 KB checked in by mstajdohar, 22 months ago (diff)

Removed scale axis.

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 OWGUI
14import OWColorPalette
15import orngMDS
16
17from Orange import core, data, feature, network
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", network.Graph, self.set_graph, Default),
49                           ("Items", data.Table, self.set_items),
50                           ("Item Subset", data.Table, self.mark_items),
51                           ("Distances", core.SymMatrix, self.set_items_distance_matrix),
52                           ("Net View", network.NxView, self.set_network_view)]
53
54            self.outputs = [("Selected Network", network.Graph),
55                            ("Distance Matrix", core.SymMatrix),
56                            ("Marked Items", data.Table),
57                            ("Selected Items", data.Table),
58                            ("Other Items", 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(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 == 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:
390                self.items_matrix = None
391                return
392
393            if self.graph_base is None:
394                self.networkCanvas.items_matrix = None
395                self.information('No graph found!')
396                return
397
398            if matrix.dim != self.graph_base.number_of_nodes():
399                self.error('The number of vertices does not match matrix size.')
400                self.items_matrix = None
401                self.networkCanvas.items_matrix = None
402                return
403
404            self.items_matrix = matrix
405            self.networkCanvas.items_matrix = matrix
406            self.cb_show_distances.setEnabled(1)
407            self.cb_show_component_distances.setEnabled(1)
408
409            if self.optMethod in [8, 9, 10]:
410                if self.items_matrix is not None and self.graph_base is not None and \
411                                    self.items_matrix.dim == self.graph_base.number_of_nodes():
412                    self.optButton.setEnabled(True)
413
414                    if self.optMethod in [8, 9]:
415                        self.cb_opt_from_curr.setEnabled(True)
416
417                    if self.optMethod == 8: # if FragViz, run FR first
418                        self.optMethod = 2
419                        self.optButton.setChecked(True)
420                        self.graph_layout()
421                        self.optMethod = 8
422
423                self.optButton.setChecked(True)
424                self.graph_layout()
425
426        def _set_canvas_attr(self, attr, value):
427            setattr(self.networkCanvas, attr, value)
428            self.networkCanvas.updateCanvas()
429
430        def _set_curve_attr(self, attr, value):
431            setattr(self.networkCanvas.networkCurve, attr, value)
432            self.networkCanvas.updateCanvas()
433
434        def _set_search_string_timer(self):
435            self.hubs = 1
436            self.searchStringTimer.stop()
437            self.searchStringTimer.start(1000)
438
439        def set_mark_mode(self, i=None):
440            self.searchStringTimer.stop()
441            if not i is None:
442                self.hubs = i
443
444            QObject.disconnect(self.networkCanvas, SIGNAL('selection_changed()'), self.networkCanvas.mark_on_selection_changed)
445            QObject.disconnect(self.networkCanvas, SIGNAL('point_hovered(Point*)'), self.networkCanvas.mark_on_focus_changed)
446
447            if self.graph is None:
448                return
449
450            hubs = self.hubs
451
452            if hubs in [0, 1, 2, 3]:
453                if hubs == 0:
454                    self.networkCanvas.networkCurve.clear_node_marks()
455                elif hubs == 1:
456                    if self.graph_base.items() is None or self.markSearchString == '':
457                        self.networkCanvas.networkCurve.clear_node_marks()
458                        return
459
460                    txt = self.markSearchString
461                    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()]))
462                    toMark = toMark.intersection(self.graph.nodes())
463                    self.networkCanvas.networkCurve.clear_node_marks()
464                    self.networkCanvas.networkCurve.set_node_marks(dict((i, True) for i in toMark))
465                elif hubs == 2:
466                    #print "mark on focus"
467                    self.networkCanvas.mark_neighbors = self.markDistance
468                    QObject.connect(self.networkCanvas, SIGNAL('point_hovered(Point*)'), self.networkCanvas.mark_on_focus_changed)
469                elif hubs == 3:
470                    #print "mark selected"
471                    self.networkCanvas.mark_neighbors = self.markDistance
472                    QObject.connect(self.networkCanvas, SIGNAL('selection_changed()'), self.networkCanvas.mark_on_selection_changed)
473                    self.networkCanvas.mark_on_selection_changed()
474
475            elif hubs in [4, 5, 6, 7, 8, 9]:
476
477                powers = sorted(self.graph.degree_iter(), key=itemgetter(1), reverse=True)
478
479                if hubs == 4:
480                    #print "mark at least N connections"
481                    N = self.markNConnections
482                    self.networkCanvas.networkCurve.set_node_marks(dict((i, True) if \
483                        d >= N else (i, False) for i, d in powers))
484                elif hubs == 5:
485                    #print "mark at most N connections"
486                    N = self.markNConnections
487                    self.networkCanvas.networkCurve.set_node_marks(dict((i, True) if \
488                        d <= N else (i, False) for i, d in powers))
489                elif hubs == 6:
490                    #print "mark more than any"
491                    self.networkCanvas.networkCurve.set_node_marks(dict((i, True) if \
492                        d > max([0] + self.graph.degree(self.graph.neighbors(i)).values()) \
493                        else (i, False) for i, d in powers))
494                elif hubs == 7:
495                    #print "mark more than avg"
496                    self.networkCanvas.networkCurve.set_node_marks(dict((i, True) if \
497                        d > statc.mean([0] + self.graph.degree(self.graph.neighbors(i)).values()) \
498                        else (i, False) for i, d in powers))
499                    self.networkCanvas.replot()
500                elif hubs == 8:
501                    #print "mark most"
502                    self.networkCanvas.networkCurve.clear_node_marks()
503
504                    if self.markNumber < 1:
505                        return
506
507                    cut = min(self.markNumber, len(powers))
508                    cutPower = powers[cut - 1][1]
509                    while cut < len(powers) and powers[cut][1] == cutPower:
510                        cut += 1
511
512                    self.networkCanvas.networkCurve.clear_node_marks()
513                    self.networkCanvas.networkCurve.set_node_marks(dict((i, True) for \
514                        i, d in powers[:cut]))
515
516                elif hubs == 9:
517                    if self.graph_base.items() is None:
518                        self.networkCanvas.networkCurve.clear_node_marks()
519                        return
520
521                    var = str(self.markInputCombo.currentText())
522                    if self.markInputItems is not None and len(self.markInputItems) > 0:
523                        if var == 'ID':
524                            values = [x.id for x in self.markInputItems]
525                            tomark = dict((x, True) for x in self.graph.nodes() if self.graph_base.items()[x].id in values)
526                        else:
527                            values = [str(x[var]).strip().upper() for x in self.markInputItems]
528                            tomark = dict((x, True) for x in self.graph.nodes() if str(self.graph_base.items()[x][var]).strip().upper() in values)
529                        self.networkCanvas.networkCurve.clear_node_marks()
530                        self.networkCanvas.networkCurve.set_node_marks(tomark)
531
532                    else:
533                        self.networkCanvas.networkCurve.clear_node_marks()
534
535            self.nMarked = len(self.networkCanvas.marked_nodes())
536
537        def save_network(self):
538            if self.networkCanvas is None or self.graph is None:
539                return
540
541            filename = QFileDialog.getSaveFileName(self, 'Save Network File', \
542                '', 'NetworkX graph as Python pickle (*.gpickle)\nPajek ' + \
543                'network (*.net)\nGML network (*.gml)')
544            filename = unicode(filename)
545            if filename:
546                fn = ""
547                head, tail = os.path.splitext(filename)
548                if not tail:
549                    fn = head + ".net"
550                else:
551                    fn = filename
552
553                items = self.graph.items()
554                for i in range(self.graph.number_of_nodes()):
555                    graph_node = self.graph.node[i]
556                    plot_node = self.networkCanvas.networkCurve.nodes()[i]
557
558                    if items is not None:
559                        ex = items[i]
560                        if 'x' in ex.domain:
561                            ex['x'] = plot_node.x()
562                        if 'y' in ex.domain:
563                            ex['y'] = plot_node.y()
564
565                    graph_node['x'] = plot_node.x()
566                    graph_node['y'] = plot_node.y()
567
568                network.readwrite.write(self.graph, fn)
569
570        def send_data(self):
571            selected_nodes = self.networkCanvas.selected_nodes()
572            self.nSelected = len(selected_nodes)
573
574            if len(self.signalManager.getLinks(self, None, \
575                "Selected Items", None)) > 0 or \
576                    len(self.signalManager.getLinks(self, None, \
577                        "Unselected Items", None)) > 0 or \
578                            len(self.signalManager.getLinks(self, None, \
579                                "Selected Network", None)) > 0:
580
581                # signal connected
582                graph = self.graph_base.subgraph(selected_nodes)
583
584                if graph is not None:
585                    self.send("Selected Items", graph.items())
586
587                    if len(self.signalManager.getLinks(self, None, \
588                                                "Unselected Items", None)) > 0:
589                        nodes = self.networkCanvas.not_selected_nodes()
590                        if len(nodes) > 0 and self.graph_base.items() is not None:
591                            self.send("Other Items", self.graph_base.items().getitems(nodes))
592                        else:
593                            self.send("Other Items", None)
594
595                    self.send("Selected Network", graph)
596                else:
597                    self.send("Selected Items", None)
598                    self.send("Other Items", None)
599                    self.send("Selected Network", None)
600
601            if len(self.signalManager.getLinks(self, None, \
602                                "Selected Items Distance Matrix", None)) > 0:
603                # signal connected
604                matrix = None if self.items_matrix is None else self.items_matrix.getitems(selected_nodes)
605                self.send("Distance Matrix", matrix)
606
607        def send_marked_nodes(self):
608            if self.checkSendMarkedNodes and \
609                len(self.signalManager.getLinks(self, None, \
610                                                "Marked Items", None)) > 0:
611                # signal connected
612                markedNodes = self.networkCanvas.marked_nodes()
613
614                if len(markedNodes) > 0 and self.graph is not None and\
615                                         self.graph_base.items() is not None:
616
617                    items = self.graph_base.items().getitems(markedNodes)
618                    self.send("Marked Items", items)
619                else:
620                    self.send("Marked Items", None)
621
622        def _set_combos(self):
623            vars = self.graph_base.items_vars()
624            edgeVars = self.graph_base.links_vars()
625            lastLabelColumns = self.lastLabelColumns
626            lastTooltipColumns = self.lastTooltipColumns
627
628            self._clear_combos()
629
630            self.attributes = [(var.name, var.varType) for var in vars]
631            self.edgeAttributes = [(var.name, var.varType) for var in edgeVars]
632
633            for var in vars:
634                if var.varType in [feature.Type.Discrete, \
635                                   feature.Type.Continuous]:
636                    self.colorCombo.addItem(self.icons.get(var.varType, \
637                                            self.icons[-1]), unicode(var.name))
638
639                if var.varType in [feature.Type.String] and hasattr(self.graph, 'items') and self.graph_base.items() is not None and len(self.graph_base.items()) > 0:
640
641                    value = self.graph_base.items()[0][var].value
642
643                    # can value be a list?
644                    try:
645                        if type(eval(value)) == type([]):
646                            self.vertexSizeCombo.addItem(self.icons.get(var.varType, self.icons[-1]), unicode(var.name))
647                            continue
648                    except:
649                        pass
650
651                    if len(value.split(',')) > 1:
652                        self.vertexSizeCombo.addItem(self.icons.get(var.varType, self.icons[-1]), "num of " + unicode(var.name))
653
654                elif var.varType in [feature.Type.Continuous]:
655                    self.vertexSizeCombo.addItem(self.icons.get(var.varType, self.icons[-1]), unicode(var.name))
656
657                if var.varType in [feature.Type.String] and var.name == "label":
658                    self.colorCombo.addItem(self.icons.get(var.varType, self.icons[-1]), unicode(var.name))
659
660                self.nameComponentCombo.addItem(self.icons.get(var.varType, self.icons[-1]), unicode(var.name))
661                self.showComponentCombo.addItem(self.icons.get(var.varType, self.icons[-1]), unicode(var.name))
662                self.editCombo.addItem(self.icons.get(var.varType, self.icons[-1]), unicode(var.name))
663                self.comboAttSelection.addItem(self.icons.get(var.varType, self.icons[-1]), unicode(var.name))
664
665            for var in edgeVars:
666                if var.varType in [feature.Type.Discrete, feature.Type.Continuous]:
667                    self.edgeColorCombo.addItem(self.icons.get(var.varType, self.icons[-1]), unicode(var.name))
668
669            for i in range(self.vertexSizeCombo.count()):
670                if self.lastVertexSizeColumn == \
671                        self.vertexSizeCombo.itemText(i):
672                    self.vertexSize = i
673                    self.set_node_sizes()
674                    break
675
676            for i in range(self.colorCombo.count()):
677                if self.lastColorColumn == self.colorCombo.itemText(i):
678                    self.color = i
679                    self.set_node_colors()
680                    break
681
682            for i in range(self.attListBox.count()):
683                if str(self.attListBox.item(i).text()) in lastLabelColumns:
684                    self.attListBox.item(i).setSelected(1)
685                self._clicked_att_lstbox()
686
687            for i in range(self.tooltipListBox.count()):
688                if str(self.tooltipListBox.item(i).text()) \
689                                                    in lastTooltipColumns:
690                    self.tooltipListBox.item(i).setSelected(1)
691                self._clicked_tooltip_lstbox()
692
693            self.lastLabelColumns = lastLabelColumns
694            self.lastTooltipColumns = lastTooltipColumns
695
696        def _clear_combos(self):
697            self.attributes = []
698            self.edgeAttributes = []
699
700            self.colorCombo.clear()
701            self.vertexSizeCombo.clear()
702            self.nameComponentCombo.clear()
703            self.showComponentCombo.clear()
704            self.edgeColorCombo.clear()
705            self.editCombo.clear()
706            self.comboAttSelection.clear()
707
708            self.colorCombo.addItem("(same color)")
709            self.edgeColorCombo.addItem("(same color)")
710            self.vertexSizeCombo.addItem("(same size)")
711            self.nameComponentCombo.addItem("Select attribute")
712            self.showComponentCombo.addItem("Select attribute")
713            self.editCombo.addItem("Select attribute")
714            self.comboAttSelection.addItem("Select attribute")
715
716        def compute_network_info(self):
717            self.nShown = self.graph.number_of_nodes()
718
719            if self.graph.number_of_edges() > 0:
720                self.verticesPerEdge = float(self.graph.number_of_nodes()) / float(self.graph.number_of_edges())
721            else:
722                self.verticesPerEdge = 0
723
724            if self.graph.number_of_nodes() > 0:
725                self.edgesPerVertex = float(self.graph.number_of_edges()) / float(self.graph.number_of_nodes())
726            else:
727                self.edgesPerVertex = 0
728
729        def change_graph(self, newgraph):
730            self.information()
731
732            # if graph has more nodes and edges than pixels in 1600x1200 display,
733            # it is too big to visualize!
734            if newgraph.number_of_nodes() + newgraph.number_of_edges() > 50000:
735                self.information('New graph is too big to visualize. Keeping the old graph.')
736                return
737
738            self.graph = newgraph
739
740            self.number_of_nodes_label = self.graph.number_of_nodes()
741            self.number_of_edges_label = self.graph.number_of_edges()
742
743            if not self.networkCanvas.change_graph(self.graph):
744                return
745
746            self.compute_network_info()
747
748            if self.graph.number_of_nodes() > 0:
749                t = 1.13850193174e-008 * (self.graph.number_of_nodes() ** 2 + self.graph.number_of_edges())
750                self.frSteps = int(2.0 / t)
751                if self.frSteps < 1: self.frSteps = 1
752                if self.frSteps > 100: self.frSteps = 100
753    #       
754    #        if self.frSteps < 10:
755    #            self.networkCanvas.use_antialiasing = 0
756    #            self.networkCanvas.use_animations = 0
757    #            self.minVertexSize = 5
758    #            self.maxVertexSize = 5
759    #            self.maxLinkSize = 1
760    #            self.optMethod = 0
761    #            self.graph_layout_method()
762
763            animation_enabled = self.networkCanvas.animate_points;
764            self.networkCanvas.animate_points = False;
765
766            self.set_node_sizes()
767            self.set_node_colors()
768            self.set_edge_sizes()
769            self.set_edge_colors()
770
771            self._clicked_att_lstbox()
772            self._clicked_tooltip_lstbox()
773            self._clicked_edge_label_listbox()
774
775            self.networkCanvas.replot()
776
777            self.networkCanvas.animate_points = animation_enabled
778            qApp.processEvents()
779            self.networkCanvas.networkCurve.layout_fr(100, weighted=False, smooth_cooling=True)
780            self.networkCanvas.replot()
781
782        def set_graph_none(self):
783            self.graph = None
784            self.graph_base = None
785            #self.graph_base = None
786            self._clear_combos()
787            self.number_of_nodes_label = -1
788            self.number_of_edges_label = -1
789            self._items = None
790            self._links = None
791            self.set_items_distance_matrix(None)
792            self.networkCanvas.set_graph(None)
793
794        def set_graph(self, graph, curve=None):
795            self.information()
796            self.warning()
797            self.error()
798
799            if graph is None:
800                self.set_graph_none()
801                return
802
803            if graph.number_of_nodes() < 2:
804                self.set_graph_none()
805                self.information('I\'m not really in a mood to visualize just one node. Try again tomorrow.')
806                return
807
808            if graph == self.graph_base and self.graph is not None and \
809                                                    self._network_view is None:
810                self.set_items(graph.items())
811                return
812
813            self.graph_base = graph
814
815            if self._network_view is not None:
816                graph = self._network_view.init_network(graph)
817
818            self.graph = graph
819
820            # if graph has more nodes and edges than pixels in 1600x1200 display,
821            # it is too big to visualize!
822            if self.graph.number_of_nodes() + self.graph.number_of_edges() > 50000:
823                self.set_graph_none()
824                self.error('Graph is too big to visualize. Try using one of the network views.')
825                return
826
827            if self.items_matrix is not None and self.items_matrix.dim != self.graph_base.number_of_nodes():
828                self.set_items_distance_matrix(None)
829
830            self.number_of_nodes_label = self.graph.number_of_nodes()
831            self.number_of_edges_label = self.graph.number_of_edges()
832
833            self.networkCanvas.set_graph(self.graph, curve, items=self.graph_base.items(), links=self.graph_base.links())
834
835            items = self.graph.items()
836            if items is not None and 'x' in items.domain and 'y' in items.domain:
837                positions = dict((node, (items[node]['x'].value, items[node]['y'].value)) \
838                             for node in self.graph if items[node]['x'].value != '?' \
839                             and items[node]['y'].value != '?')
840
841                # ignore start position if all nodes are on the same coordinate
842                if len(set(positions.values())) > 1:
843                    self.networkCanvas.networkCurve.set_node_coordinates(positions)
844
845
846            self.networkCanvas.showEdgeLabels = self.showEdgeLabels
847            self.networkCanvas.maxEdgeSize = self.maxLinkSize
848            self.networkCanvas.minComponentEdgeWidth = self.minComponentEdgeWidth
849            self.networkCanvas.maxComponentEdgeWidth = self.maxComponentEdgeWidth
850            self.networkCanvas.set_labels_on_marked(self.labelsOnMarkedOnly)
851
852            self.compute_network_info()
853            self._set_combos()
854
855            lastNameComponentAttributeFound = False
856            for i in range(self.nameComponentCombo.count()):
857                if self.lastNameComponentAttribute == self.nameComponentCombo.itemText(i):
858                    lastNameComponentAttributeFound = True
859                    self.nameComponentAttribute = i
860                    self.nameComponents()
861                    self.showComponentAttribute = self.showComponentCombo.count() - 1
862                    self.showComponents()
863                    break
864
865            if not lastNameComponentAttributeFound:
866                self.lastNameComponentAttribute = ''
867
868            self.showComponentAttribute = None
869
870            t = 1.13850193174e-008 * (self.graph.number_of_nodes() ** 2 + self.graph.number_of_edges())
871            self.frSteps = int(2.0 / t)
872            if self.frSteps < 1: self.frSteps = 1
873            if self.frSteps > 100: self.frSteps = 100
874
875            # if graph is large, set random layout, min vertex size, min edge size
876            if self.frSteps < 10:
877                self.networkCanvas.update_antialiasing(False)
878                self.networkCanvas.update_animations(False)
879                self.minVertexSize = 5
880                self.maxVertexSize = 5
881                self.maxLinkSize = 1
882                self.optMethod = 0
883                self.graph_layout_method()
884
885            self.networkCanvas.labelsOnMarkedOnly = self.labelsOnMarkedOnly
886            self.networkCanvas.showWeights = self.showWeights
887
888            self.set_node_sizes()
889            self.set_node_colors()
890            self.set_edge_sizes()
891            self.set_edge_colors()
892
893            self._clicked_att_lstbox()
894            self._clicked_tooltip_lstbox()
895            self._clicked_edge_label_listbox()
896
897            self.optButton.setChecked(1)
898            self.graph_layout()
899            self.set_mark_mode()
900
901        def set_network_view(self, nxView):
902            self.error()
903            self.warning()
904            self.information()
905
906            if self.graph is None:
907                self.information('Do not forget to add a graph!')
908
909            if self._network_view is not None:
910                QObject.disconnect(self.networkCanvas, SIGNAL('selection_changed()'), self._network_view.node_selection_changed)
911
912            self._network_view = nxView
913
914            g = self.graph_base
915            if self._network_view is not None:
916                self._network_view.set_nx_explorer(self)
917            else:
918                self.graph_base = None
919
920            self.set_graph(g)
921
922            if self._network_view is not None:
923                QObject.connect(self.networkCanvas, SIGNAL('selection_changed()'), self._network_view.node_selection_changed)
924
925        def set_items(self, items=None):
926            self.error()
927            self.warning()
928            self.information()
929
930            if items is None:
931                return
932
933            if self.graph is None:
934                self.warning('No graph found!')
935                return
936
937            if len(items) != self.graph_base.number_of_nodes():
938                self.error('Table items must have one example for each node.')
939                return
940
941            self.graph_base.set_items(items)
942
943            self.set_node_sizes()
944            self.networkCanvas.items = items
945            self.networkCanvas.showWeights = self.showWeights
946            self.networkCanvas.showEdgeLabels = self.showEdgeLabels
947            self._set_combos()
948            #self.networkCanvas.updateData()
949
950        def mark_items(self, items):
951            self.markInputCombo.clear()
952            self.markInputRadioButton.setEnabled(False)
953            self.markInputItems = items
954
955            self.error()
956            self.warning()
957            self.information()
958
959            if items is None:
960                return
961
962            if self.graph is None or self.graph_base.items() is None or items is None:
963                self.warning('No graph found or no items attached to the graph.')
964                return
965
966            if len(items) > 0:
967                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()]
968                lstNewDomain = [x.name for x in items.domain] + [items.domain[x].name for x in items.domain.getmetas()]
969                commonVars = set(lstNewDomain) & set(lstOrgDomain)
970
971                self.markInputCombo.addItem(self.icons[feature.Type.Discrete], unicode("ID"))
972
973                if len(commonVars) > 0:
974                    for var in commonVars:
975                        orgVar = self.graph_base.items().domain[var]
976                        mrkVar = items.domain[var]
977
978                        if orgVar.varType == mrkVar.varType and orgVar.varType == feature.Type.String:
979                            self.markInputCombo.addItem(self.icons[orgVar.varType], unicode(orgVar.name))
980
981                self.markInputRadioButton.setEnabled(True)
982                self.set_mark_mode(9)
983
984        def set_explore_distances(self):
985            QObject.disconnect(self.networkCanvas, SIGNAL('selection_changed()'), self.explore_focused)
986
987            if self.explore_distances:
988                QObject.connect(self.networkCanvas, SIGNAL('selection_changed()'), self.explore_focused)
989
990        def explore_focused(self):
991            sel = self.networkCanvas.selected_nodes()
992            if len(sel) == 1:
993                ndx_1 = sel[0]
994                self.networkCanvas.label_distances = [['%.2f' % \
995                                self.items_matrix[ndx_1][ndx_2]] \
996                                for ndx_2 in self.networkCanvas.graph.nodes()]
997            else:
998                self.networkCanvas.label_distances = None
999
1000            self.networkCanvas.set_node_labels(self.lastLabelColumns)
1001            self.networkCanvas.replot()
1002
1003        #######################################################################
1004        ### Layout Optimization                                             ###
1005        #######################################################################
1006
1007        def graph_layout(self):
1008            if self.graph is None or self.graph.number_of_nodes <= 0:   #grafa se ni
1009                self.optButton.setChecked(False)
1010                return
1011
1012            if not self.optButton.isChecked() and not self.optMethod in [2, 3, 8, 9, 10]:
1013                self.optButton.setChecked(False)
1014                return
1015
1016            qApp.processEvents()
1017
1018            if self.optMethod == 0:
1019                items = self.graph.items()
1020                if items is not None and 'x' in items.domain and 'y' in items.domain:
1021                    positions = dict((node, (items[node]['x'].value, items[node]['y'].value)) \
1022                                 for node in self.graph if items[node]['x'].value != '?' \
1023                                 and items[node]['y'].value != '?')
1024
1025                    # ignore start position if all nodes are on the same coordinate
1026                    if len(set(positions.values())) > 1:
1027                        self.networkCanvas.networkCurve.set_node_coordinates(positions)
1028            elif self.optMethod == 1:
1029                self.networkCanvas.networkCurve.random()
1030            elif self.optMethod == 2:
1031                self.graph_layout_fr(False)
1032            elif self.optMethod == 3:
1033                self.graph_layout_fr(True)
1034            elif self.optMethod == 4:
1035                self.graph_layout_fr_radial()
1036            elif self.optMethod == 5:
1037                self.networkCanvas.networkCurve.circular(\
1038                                            NetworkCurve.circular_crossing)
1039            elif self.optMethod == 6:
1040                self.networkCanvas.networkCurve.circular(\
1041                                            NetworkCurve.circular_original)
1042            elif self.optMethod == 7:
1043                self.networkCanvas.networkCurve.circular(\
1044                                            NetworkCurve.circular_random)
1045            elif self.optMethod == 8:
1046                self.graph_layout_fragviz()
1047            elif self.optMethod == 9:
1048                self.graph_layout_mds()
1049            elif self.optMethod == 10:
1050                self.graph_layout_pivot_mds()
1051
1052            self.optButton.setChecked(False)
1053            self.networkCanvas.replot()
1054
1055        def graph_layout_method(self, method=None):
1056            self.information()
1057            self.stepsSpin.label.setText('Iterations: ')
1058            self.optButton.setEnabled(True)
1059            self.cb_opt_from_curr.setEnabled(False)
1060
1061            if method is not None:
1062                self.optMethod = method
1063
1064            if self.optMethod == 0:
1065                self.optButton.setEnabled(False)
1066            else:
1067                self.optButton.setEnabled(True)
1068
1069            if self.optMethod in [2, 3, 4]:
1070                self.stepsSpin.setEnabled(True)
1071
1072            elif self.optMethod in [8, 9, 10]:
1073                if self.optMethod == 10:
1074                    self.stepsSpin.label.setText('Pivots: ')
1075
1076                if self.optMethod in [8, 9]:
1077                    self.cb_opt_from_curr.setEnabled(True)
1078
1079                self.stepsSpin.setEnabled(True)
1080
1081                if self.items_matrix is None:
1082                    self.information('Set distance matrix to input signal')
1083                    self.optButton.setEnabled(False)
1084                    return
1085                if self.graph is None:
1086                    self.information('No network found')
1087                    self.optButton.setEnabled(False)
1088                    return
1089                if self.items_matrix.dim != self.graph_base.number_of_nodes():
1090                    self.error('Distance matrix dimensionality must equal number of vertices')
1091                    self.optButton.setEnabled(False)
1092                    return
1093            else:
1094                self.stepsSpin.setEnabled(False)
1095                self.optButton.setChecked(True)
1096                self.graph_layout()
1097
1098        def mds_progress(self, avgStress, stepCount):
1099            #self.drawForce()
1100
1101            #self.mdsInfoA.setText("Avg. Stress: %.20f" % avgStress)
1102            #self.mdsInfoB.setText("Num. steps: %i" % stepCount)
1103            self.progressBarSet(int(stepCount * 100 / self.frSteps))
1104            qApp.processEvents()
1105
1106        def graph_layout_fragviz(self):
1107            if self.items_matrix is None:
1108                self.information('Set distance matrix to input signal')
1109                self.optButton.setChecked(False)
1110                return
1111
1112            if self.layout is None:
1113                self.information('No network found')
1114                self.optButton.setChecked(False)
1115                return
1116
1117            if self.items_matrix.dim != self.graph_base.number_of_nodes():
1118                self.error('Distance matrix dimensionality must equal number of vertices')
1119                self.optButton.setChecked(False)
1120                return
1121
1122            if not self.optButton.isChecked():
1123                self.networkCanvas.networkCurve.stopMDS = True
1124                self.optButton.setChecked(False)
1125                self.optButton.setText("Optimize layout")
1126                return
1127
1128            self.optButton.setText("Stop")
1129            self.progressBarInit()
1130            qApp.processEvents()
1131
1132            if self.graph.number_of_nodes() == self.graph_base.number_of_nodes():
1133                matrix = self.items_matrix
1134            else:
1135                matrix = self.items_matrix.get_items(sorted(self.graph.nodes_iter()))
1136
1137            self.networkCanvas.networkCurve.layout_fragviz(self.frSteps, matrix, self.graph, self.mds_progress, self.opt_from_curr)
1138
1139            self.optButton.setChecked(False)
1140            self.optButton.setText("Optimize layout")
1141            self.progressBarFinished()
1142
1143        def graph_layout_mds(self):
1144            if self.items_matrix is None:
1145                self.information('Set distance matrix to input signal')
1146                self.optButton.setChecked(False)
1147                return
1148
1149            if self.layout is None:
1150                self.information('No network found')
1151                self.optButton.setChecked(False)
1152                return
1153
1154            if self.items_matrix.dim != self.graph_base.number_of_nodes():
1155                self.error('Distance matrix dimensionality must equal number of vertices')
1156                self.optButton.setChecked(False)
1157                return
1158
1159            if not self.optButton.isChecked():
1160                self.networkCanvas.networkCurve.stopMDS = True
1161                self.optButton.setChecked(False)
1162                self.optButton.setText("Optimize layout")
1163                return
1164
1165            self.optButton.setText("Stop")
1166            self.progressBarInit()
1167            qApp.processEvents()
1168
1169            if self.graph.number_of_nodes() == self.graph_base.number_of_nodes():
1170                matrix = self.items_matrix
1171            else:
1172                matrix = self.items_matrix.get_items(sorted(self.graph.nodes()))
1173
1174            self.networkCanvas.networkCurve.layout_mds(self.frSteps, matrix, self.mds_progress, self.opt_from_curr)
1175
1176            self.optButton.setChecked(False)
1177            self.optButton.setText("Optimize layout")
1178            self.progressBarFinished()
1179
1180        def graph_layout_fr(self, weighted):
1181            if self.graph is None:
1182                return
1183
1184            if not self.optButton.isChecked():
1185                self.networkCanvas.networkCurve.stop_optimization()
1186                self.optButton.setChecked(False)
1187                self.optButton.setText("Optimize layout")
1188                return
1189
1190            self.optButton.setText("Stop")
1191            qApp.processEvents()
1192            self.networkCanvas.networkCurve.layout_fr(self.frSteps, False)
1193            self.optButton.setChecked(False)
1194            self.optButton.setText("Optimize layout")
1195
1196        def graph_layout_fr_radial(self):
1197            if self.graph is None:   #grafa se ni
1198                return
1199
1200    #        #print "F-R Radial"
1201    #        k = 1.13850193174e-008
1202    #        nodes = self.graph.number_of_nodes()
1203    #        t = k * nodes * nodes
1204    #        refreshRate = int(5.0 / t)
1205    #        if refreshRate <    1: refreshRate = 1
1206    #        if refreshRate > 1500: refreshRate = 1500
1207    #        #print "refreshRate: " + str(refreshRate)
1208    #       
1209    #        tolerance = 5
1210    #        initTemp = 100
1211    #        centerNdx = 0
1212    #       
1213    #        selection = self.networkCanvas.getSelection()
1214    #        if len(selection) > 0:
1215    #            centerNdx = selection[0]
1216    #           
1217    #        #print "center ndx: " + str(centerNdx)
1218    #        initTemp = self.layout.fr_radial(centerNdx, refreshRate, initTemp)
1219    #        self.networkCanvas.circles = [10000 / 12, 10000/12*2, 10000/12*3]#, 10000/12*4, 10000/12*5]
1220    #        #self.networkCanvas.circles = [100, 200, 300]
1221    #        self.networkCanvas.updateCanvas()
1222    #        self.networkCanvas.circles = []
1223
1224        def graph_layout_pivot_mds(self):
1225            self.information()
1226
1227            if self.items_matrix is None:
1228                self.information('Set distance matrix to input signal')
1229                return
1230
1231            if self.graph_base is None:
1232                self.information('No network found')
1233                return
1234
1235            if self.items_matrix.dim != self.graph_base.number_of_nodes():
1236                self.error('The number of vertices does not match matrix size.')
1237                return
1238
1239            self.frSteps = min(self.frSteps, self.graph.number_of_nodes())
1240            qApp.processEvents()
1241
1242            if self.graph.number_of_nodes() == self.graph_base.number_of_nodes():
1243                matrix = self.items_matrix
1244            else:
1245                matrix = self.items_matrix.get_items(sorted(self.graph.nodes()))
1246
1247            mds = orngMDS.PivotMDS(matrix, self.frSteps)
1248            x, y = mds.optimize()
1249            xy = zip(list(x), list(y))
1250            coors = dict(zip(sorted(self.graph.nodes()), xy))
1251            self.networkCanvas.networkCurve.set_node_coordinates(coors)
1252            self.networkCanvas.update_layout()
1253
1254        #######################################################################
1255        ### Network Visualization                                           ###
1256        #######################################################################
1257
1258        def _set_colors(self):
1259            dlg = self._create_color_dialog(self.colorSettings, self.selectedSchemaIndex)
1260            if dlg.exec_():
1261                self.colorSettings = dlg.getColorSchemas()
1262                self.selectedSchemaIndex = dlg.selectedSchemaIndex
1263                self.networkCanvas.contPalette = dlg.getContinuousPalette("contPalette")
1264                self.networkCanvas.discPalette = dlg.getDiscretePalette("discPalette")
1265
1266                self.set_node_colors()
1267
1268        def _set_edge_color_palette(self):
1269            dlg = self._create_color_dialog(self.edgeColorSettings, self.selectedEdgeSchemaIndex)
1270            if dlg.exec_():
1271                self.edgeColorSettings = dlg.getColorSchemas()
1272                self.selectedEdgeSchemaIndex = dlg.selectedSchemaIndex
1273                self.networkCanvas.contEdgePalette = dlg.getContinuousPalette("contPalette")
1274                self.networkCanvas.discEdgePalette = dlg.getDiscretePalette("discPalette")
1275
1276                self.set_edge_colors()
1277
1278        def _create_color_dialog(self, colorSettings, selectedSchemaIndex):
1279            c = OWColorPalette.ColorPaletteDlg(self, "Color Palette")
1280            c.createDiscretePalette("discPalette", "Discrete Palette")
1281            c.createContinuousPalette("contPalette", "Continuous Palette")
1282            c.setColorSchemas(colorSettings, selectedSchemaIndex)
1283            return c
1284
1285        def _clicked_att_lstbox(self):
1286            if self.graph is None:
1287                return
1288
1289            self.lastLabelColumns = [self.attributes[i][0] for i in self.markerAttributes]
1290            self.networkCanvas.set_node_labels(self.lastLabelColumns)
1291            self.networkCanvas.replot()
1292
1293        def _clicked_tooltip_lstbox(self):
1294            if self.graph is None:
1295                return
1296
1297            self.lastTooltipColumns = [self.attributes[i][0] for i in self.tooltipAttributes]
1298            self.networkCanvas.set_tooltip_attributes(self.lastTooltipColumns)
1299            self.networkCanvas.replot()
1300
1301        def _clicked_edge_label_listbox(self):
1302            if self.graph is None:
1303                return
1304
1305            self.lastEdgeLabelAttributes = set([self.edgeAttributes[i][0] for i in self.edgeLabelAttributes])
1306            self.networkCanvas.set_edge_labels(self.lastEdgeLabelAttributes)
1307            self.networkCanvas.replot()
1308
1309        def set_node_colors(self):
1310            if self.graph is None:
1311                return
1312
1313            self.networkCanvas.set_node_colors(self.colorCombo.currentText())
1314            self.lastColorColumn = self.colorCombo.currentText()
1315
1316        def set_edge_colors(self):
1317            if self.graph is None:
1318                return
1319
1320            self.networkCanvas.set_edge_colors(self.edgeColorCombo.currentText())
1321            self.lastEdgeColorColumn = self.edgeColorCombo.currentText()
1322
1323        def set_edge_sizes(self):
1324            if self.graph is None:
1325                return
1326
1327            self.networkCanvas.networkCurve.set_edge_sizes(self.maxLinkSize)
1328            self.networkCanvas.replot()
1329
1330        def set_node_sizes(self):
1331            if self.graph is None or self.networkCanvas is None:
1332                return
1333
1334            if self.minVertexSize > self.maxVertexSize:
1335                self.maxVertexSize = self.minVertexSize
1336
1337            items = self.graph_base.items()
1338
1339            if items is None:
1340                self.networkCanvas.networkCurve.set_node_sizes({}, min_size=self.minVertexSize, max_size=self.maxVertexSize)
1341                return
1342
1343            self.lastVertexSizeColumn = self.vertexSizeCombo.currentText()
1344            column = str(self.vertexSizeCombo.currentText())
1345
1346            values = {}
1347            if column in items.domain or (column.startswith("num of ") and column.replace("num of ", "") in items.domain):
1348                if column in items.domain:
1349                    values = dict((x, items[x][column].value) for x in self.graph if not items[x][column].isSpecial())
1350                else:
1351                    values = dict((x, len(items[x][column.replace("num of ", "")].value.split(','))) for x in self.graph)
1352
1353            if len(values) == 0:
1354                values = dict((node, 1.) for node in self.graph)
1355
1356            if self.invertSize:
1357                maxval = max(values.itervalues())
1358                values.update((key, maxval - val) for key, val in values.iteritems())
1359                self.networkCanvas.networkCurve.set_node_sizes(values, min_size=self.minVertexSize, max_size=self.maxVertexSize)
1360            else:
1361                self.networkCanvas.networkCurve.set_node_sizes(values, min_size=self.minVertexSize, max_size=self.maxVertexSize)
1362
1363            self.networkCanvas.replot()
1364
1365        def set_font(self):
1366            if self.networkCanvas is None:
1367                return
1368
1369            weights = {0: 50, 1: 80}
1370
1371            font = self.networkCanvas.font()
1372            font.setPointSize(self.fontSize)
1373            font.setWeight(weights[self.fontWeight])
1374            self.networkCanvas.setFont(font)
1375            self.networkCanvas.fontSize = font
1376            self.networkCanvas.set_node_labels()
1377
1378        def sendReport(self):
1379            self.reportSettings("Graph data",
1380                                [("Number of vertices", self.graph.number_of_nodes()),
1381                                 ("Number of edges", self.graph.number_of_edges()),
1382                                 ("Vertices per edge", "%.3f" % self.verticesPerEdge),
1383                                 ("Edges per vertex", "%.3f" % self.edgesPerVertex),
1384                                 ])
1385            if self.color or self.vertexSize or self.markerAttributes or self.edgeColor:
1386                self.reportSettings("Visual settings",
1387                                    [self.color and ("Vertex color", self.colorCombo.currentText()),
1388                                     self.vertexSize and ("Vertex size", str(self.vertexSizeCombo.currentText()) + " (inverted)" if self.invertSize else ""),
1389                                     self.markerAttributes and ("Labels", ", ".join(self.attributes[i][0] for i in self.markerAttributes)),
1390                                     self.edgeColor and ("Edge colors", self.edgeColorCombo.currentText()),
1391                                    ])
1392            self.reportSettings("Optimization",
1393                                [("Method", self.optCombo.currentText()),
1394                                 ("Iterations", self.frSteps)])
1395            self.reportSection("Graph")
1396            self.reportImage(self.networkCanvas.saveToFileDirect)
1397
1398        #######################################################################
1399        ### PROTOTYPE                                                       ###
1400        #######################################################################
1401
1402        def set_component_edge_width(self, changedMin=True):
1403            if self.networkCanvas is None:
1404                return
1405
1406            canvas = self.networkCanvas
1407            if changedMin:
1408                if self.maxComponentEdgeWidth < self.minComponentEdgeWidth:
1409                    self.maxComponentEdgeWidth = self.minComponentEdgeWidth
1410            else:
1411                if self.minComponentEdgeWidth > self.maxComponentEdgeWidth:
1412                    self.minComponentEdgeWidth = self.maxComponentEdgeWidth
1413
1414            canvas.minComponentEdgeWidth = self.minComponentEdgeWidth
1415            canvas.maxComponentEdgeWidth = self.maxComponentEdgeWidth
1416            self.networkCanvas.updateCanvas()
1417
1418        def showComponents(self):
1419            if self.graph is None or self.graph_base.items() is None:
1420                return
1421
1422            vars = [x.name for x in self.graph_base.items_vars()]
1423
1424            if not self.showComponentCombo.currentText() in vars:
1425                self.networkCanvas.showComponentAttribute = None
1426                self.lastNameComponentAttribute = ''
1427            else:
1428                self.networkCanvas.showComponentAttribute = self.showComponentCombo.currentText()
1429
1430            self.networkCanvas.drawComponentKeywords()
1431
1432        def nameComponents(self):
1433            """Names connected components of genes according to GO terms."""
1434            self.progressBarFinished()
1435            self.lastNameComponentAttribute = None
1436
1437            if self.graph is None or self.graph_base.items() is None:
1438                return
1439
1440            vars = [x.name for x in self.graph_base.items_vars()]
1441            if not self.nameComponentCombo.currentText() in vars:
1442                return
1443
1444            self.progressBarInit()
1445            components = [c for c in network.nx.algorithms.components.connected_components(self.graph) if len(c) > 1]
1446            if 'component name' in self.graph_base.items().domain:
1447                keyword_table = self.graph_base.items()
1448            else:
1449                keyword_table = data.Table(data.Domain(feature.String('component name')), [[''] for i in range(len(self.graph_base.items()))])
1450
1451            import obiGO
1452            ontology = obiGO.Ontology.Load(progressCallback=self.progressBarSet)
1453            annotations = obiGO.Annotations.Load(self.organism, ontology=ontology, progressCallback=self.progressBarSet)
1454
1455            allGenes = set([e[str(self.nameComponentCombo.currentText())].value for e in self.graph_base.items()])
1456            foundGenesets = False
1457            if len(annotations.geneNames & allGenes) < 1:
1458                allGenes = set(reduce(operator.add, [e[str(self.nameComponentCombo.currentText())].value.split(', ') for e in self.graph_base.items()]))
1459                if len(annotations.geneNames & allGenes) < 1:
1460                    self.warning('no genes found')
1461                    return
1462                else:
1463                    foundGenesets = True
1464
1465            def rank(a, j, reverse=False):
1466                if len(a) <= 0: return
1467
1468                if reverse:
1469                    a.sort(lambda x, y: 1 if x[j] > y[j] else -1 if x[j] < y[j] else 0)
1470                    top_value = a[0][j]
1471                    top_rank = len(a)
1472                    max_rank = float(len(a))
1473                    int_ndx = 0
1474                    for k in range(len(a)):
1475                        if top_value < a[k][j]:
1476                            top_value = a[k][j]
1477                            if k - int_ndx > 1:
1478                                avg_rank = (a[int_ndx][j] + a[k - 1][j]) / 2
1479                                for l in range(int_ndx, k):
1480                                    a[l][j] = avg_rank
1481
1482                            int_ndx = k
1483
1484                        a[k][j] = top_rank / max_rank
1485                        top_rank -= 1
1486
1487                    k += 1
1488                    if k - int_ndx > 1:
1489                        avg_rank = (a[int_ndx][j] + a[k - 1][j]) / 2
1490                        for l in range(int_ndx, k):
1491                            a[l][j] = avg_rank
1492
1493                else:
1494                    a.sort(lambda x, y: 1 if x[j] < y[j] else -1 if x[j] > y[j] else 0)
1495                    top_value = a[0][j]
1496                    top_rank = len(a)
1497                    max_rank = float(len(a))
1498                    int_ndx = 0
1499                    for k in range(len(a)):
1500                        if top_value > a[k][j]:
1501                            top_value = a[k][j]
1502                            if k - int_ndx > 1:
1503                                avg_rank = (a[int_ndx][j] + a[k - 1][j]) / 2
1504                                for l in range(int_ndx, k):
1505                                    a[l][j] = avg_rank
1506
1507                            int_ndx = k
1508
1509                        a[k][j] = top_rank / max_rank
1510                        top_rank -= 1
1511
1512                    k += 1
1513                    if k - int_ndx > 1:
1514                        avg_rank = (a[int_ndx][j] + a[k - 1][j]) / 2
1515                        for l in range(int_ndx, k):
1516                            a[l][j] = avg_rank
1517
1518            for i in range(len(components)):
1519                component = components[i]
1520                if len(component) <= 1:
1521                    continue
1522
1523                if foundGenesets:
1524                    genes = reduce(operator.add, [self.graph_base.items()[v][str(self.nameComponentCombo.currentText())].value.split(', ') for v in component])
1525                else:
1526                    genes = [self.graph_base.items()[v][str(self.nameComponentCombo.currentText())].value for v in component]
1527
1528                res1 = annotations.GetEnrichedTerms(genes, aspect="P")
1529                res2 = annotations.GetEnrichedTerms(genes, aspect="F")
1530                res = res1.items() + res2.items()
1531                #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]
1532                #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]
1533
1534                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]
1535                if len(namingScore) == 0:
1536                    continue
1537
1538                annotated_genes = max([a[0] for a in namingScore])
1539
1540                rank(namingScore, 1, reverse=True)
1541                rank(namingScore, 2, reverse=True)
1542                rank(namingScore, 0)
1543
1544                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]
1545                namingScore.sort(reverse=True)
1546
1547                if len(namingScore) < 1:
1548                    print "warning. no annotations found for group of genes: " + ", ".join(genes)
1549                    continue
1550                elif len(namingScore[0]) < 2:
1551                    print "warning. error computing score for group of genes: " + ", ".join(genes)
1552                    continue
1553
1554                for v in component:
1555                    name = str(namingScore[0][1])
1556                    attrs = "%d/%d, %d, %lf" % (namingScore[0][2], annotated_genes, namingScore[0][3], namingScore[0][4])
1557                    info = ''
1558                    if self.showTextMiningInfo:
1559                        info = "\n" + attrs + "\n" + str(namingScore[0][0])
1560                    keyword_table[v]['component name'] = name + info
1561
1562                self.progressBarSet(i * 100.0 / len(components))
1563
1564            self.lastNameComponentAttribute = self.nameComponentCombo.currentText()
1565            self.set_items(data.Table([self.graph_base.items(), keyword_table]))
1566            self.progressBarFinished()
1567
1568
1569        def setAutoSendAttributes(self):
1570            print 'TODO setAutoSendAttributes'
1571            #if self.autoSendAttributes:
1572            #    self.networkCanvas.callbackSelectVertex = self.sendAttSelectionList
1573            #else:
1574            #    self.networkCanvas.callbackSelectVertex = None
1575
1576        def sendAttSelectionList(self):
1577            if not self.graph is None:
1578                vars = [x.name for x in self.graph_base.links_vars()]
1579                if not self.comboAttSelection.currentText() in vars:
1580                    return
1581                att = str(self.comboAttSelection.currentText())
1582                vertices = self.networkCanvas.selected_nodes()
1583
1584                if len(vertices) != 1:
1585                    return
1586
1587                attributes = str(self.graph_base.items()[vertices[0]][att]).split(', ')
1588            else:
1589                attributes = None
1590            self.send("Features", attributes)
1591
1592
1593except ImportError as err:
1594    try:
1595        from OWNxCanvas import *
1596    except:
1597        # if Qwt is also not installed throw could not import orangeqt error
1598        raise err
1599
1600    from OWNxExplorerQwt import OWNxExplorerQwt as OWNxExplorer
1601
1602if __name__ == "__main__":
1603    a = QApplication(sys.argv)
1604    ow = OWNxExplorer()
1605    ow.show()
1606
1607    def setNetwork(signal, data, id=None):
1608        if signal == 'Network':
1609            ow.set_graph(data)
1610        #if signal == 'Items':
1611        #    ow.set_items(data)
1612
1613    import OWNxFile
1614    owFile = OWNxFile.OWNxFile()
1615    owFile.send = setNetwork
1616    owFile.show()
1617    owFile.selectNetFile(0)
1618
1619    a.exec_()
1620    ow.saveSettings()
1621    owFile.saveSettings()
Note: See TracBrowser for help on using the repository browser.