source: orange/Orange/OrangeWidgets/Unsupervised/OWNxCanvasQt.py @ 10920:b32861f3640e

Revision 10920:b32861f3640e, 29.3 KB checked in by mstajdohar, 22 months ago (diff)

Auto scale axies in FR.

Line 
1CIRCLE = 0
2SQUARE = 1
3ROUND_RECT = 2
4
5NOTHING = 0
6ZOOMING = 1
7SELECT_RECTANGLE = 2
8SELECT_POLYGON = 3
9MOVE_SELECTION = 100
10
11import numpy
12
13from plot.owplot import *
14from plot.owpoint import *
15from plot.owtools import *
16
17from Orange import core, data, misc, network, orangeqt, projection
18from orngScaleScatterPlotData import *
19
20class NodeItem(orangeqt.NodeItem):
21    def __init__(self, index, x=None, y=None, parent=None):
22        orangeqt.NodeItem.__init__(self, index, OWPoint.Ellipse, Qt.blue, 5, parent)
23        if x is not None:
24            self.set_x(x)
25        if y is not None:
26            self.set_y(y)
27
28class EdgeItem(orangeqt.EdgeItem):
29    def __init__(self, u=None, v=None, weight=1, links_index=0, arrows=None, label='', parent=None):
30        orangeqt.EdgeItem.__init__(self, u, v, parent)
31        self.set_weight(weight)
32        self.set_links_index(links_index)
33        if arrows is not None:
34            self.set_arrows(arrows)
35
36class NetworkCurve(orangeqt.NetworkCurve):
37    def __init__(self, parent=None, pen=QPen(Qt.black), xData=None, yData=None):
38        orangeqt.NetworkCurve.__init__(self, parent)
39        self.name = "Network Curve"
40
41    def layout_fr(self, steps, weighted=False, smooth_cooling=False):
42        orangeqt.NetworkCurve.fr(self, steps, weighted, smooth_cooling)
43
44    def set_node_sizes(self, values={}, min_size=0, max_size=0):
45        orangeqt.NetworkCurve.set_node_sizes(self, values, min_size, max_size)
46
47    def fragviz_callback(self, a, b, mds, mdsRefresh, graph_components, matrix_components, progress_callback):
48        """Refresh the UI when running  MDS on network components."""
49
50        if not self.mdsStep % mdsRefresh:
51            rotationOnly = False
52            component_props = []
53            x_mds = []
54            y_mds = []
55            phi = [None] * len(graph_components)
56            nodes = self.nodes()
57            ncomponents = len(graph_components)
58
59            for i in range(ncomponents):
60
61                if len(mds.points) == ncomponents:  # if average linkage before
62                    x_avg_mds = mds.points[i][0]
63                    y_avg_mds = mds.points[i][1]
64                else:                                   # if not average linkage before
65                    x = [mds.points[u][0] for u in matrix_components[i]]
66                    y = [mds.points[u][1] for u in matrix_components[i]]
67
68                    x_avg_mds = sum(x) / len(x)
69                    y_avg_mds = sum(y) / len(y)
70                    # compute rotation angle
71#                    c = [numpy.linalg.norm(numpy.cross(mds.points[u], \
72#                                [nodes[u].x(), nodes[u].y()])) for u in component]
73#                   
74#                    n = [numpy.vdot([nodes[u].x(), nodes[u].y()], \
75#                                    [nodes[u].x(), nodes[u].y()]) for u in component]
76#                    phi[i] = sum(c) / sum(n)
77
78
79                x = [nodes[j].x() for j in graph_components[i]]
80                y = [nodes[j].y() for j in graph_components[i]]
81
82                x_avg_graph = sum(x) / len(x)
83                y_avg_graph = sum(y) / len(y)
84
85                x_mds.append(x_avg_mds)
86                y_mds.append(y_avg_mds)
87
88                component_props.append((x_avg_graph, y_avg_graph, \
89                                        x_avg_mds, y_avg_mds, phi))
90
91            for i, component in enumerate(graph_components):
92                x_avg_graph, y_avg_graph, x_avg_mds, \
93                y_avg_mds, phi = component_props[i]
94
95    #            if phi[i]:  # rotate vertices
96    #                #print "rotate", i, phi[i]
97    #                r = numpy.array([[numpy.cos(phi[i]), -numpy.sin(phi[i])], [numpy.sin(phi[i]), numpy.cos(phi[i])]])  #rotation matrix
98    #                c = [x_avg_graph, y_avg_graph]  # center of mass in FR coordinate system
99    #                v = [numpy.dot(numpy.array([self.graph.coors[0][u], self.graph.coors[1][u]]) - c, r) + c for u in component]
100    #                self.graph.coors[0][component] = [u[0] for u in v]
101    #                self.graph.coors[1][component] = [u[1] for u in v]
102
103                # translate vertices
104                if not rotationOnly:
105                    self.set_node_coordinates(dict(
106                       (j, ((nodes[j].x() - x_avg_graph) + x_avg_mds,
107                            (nodes[j].y() - y_avg_graph) + y_avg_mds)) \
108                                  for j in component))
109
110            #if self.mdsType == MdsType.exactSimulation:
111            #    self.mds.points = [[self.graph.coors[0][i], \
112            #                        self.graph.coors[1][i]] \
113            #                        for i in range(len(self.graph.coors))]
114            #    self.mds.freshD = 0
115
116            #self.update_properties()
117            self.plot().update_layout()
118            qApp.processEvents()
119
120            if progress_callback is not None:
121                progress_callback(a, self.mdsStep)
122
123        self.mdsStep += 1
124        return 0 if self.stopMDS else 1
125
126    def layout_fragviz(self, steps, distances, graph, progress_callback=None, opt_from_curr=False):
127        """Position the network components according to similarities among
128        them.
129       
130        """
131
132        if distances == None or graph == None or distances.dim != graph.number_of_nodes():
133            self.information('invalid or no distance matrix')
134            return 1
135
136        p = self.plot()
137        edges = self.edges()
138        nodes = self.nodes()
139
140        avgLinkage = True
141        rotationOnly = False
142        minStressDelta = 0
143        mdsRefresh = 10#int(steps / 20)
144
145        self.mdsStep = 1
146        self.stopMDS = False
147
148        nodes_inds = {n: i for i, n in enumerate(sorted(graph.nodes_iter()))}
149        inds_nodes = {i: n for i, n in enumerate(sorted(graph.nodes_iter()))}
150
151        graph_components = network.nx.algorithms.connected_components(graph)
152        matrix_components = [[nodes_inds[n] for n in c] for c in graph_components]
153
154        distances.matrixType = misc.SymMatrix.Symmetric
155
156        # scale net coordinates
157        if avgLinkage:
158            distances = distances.avgLinkage(matrix_components)
159
160        # if only one component
161        if distances.dim == 1:
162            return 0
163
164        mds = projection.mds.MDS(distances)
165        mds.optimize(10, projection.mds.SgnRelStress, 0)
166        rect = self.data_rect()
167        w_fr = rect.width()
168        h_fr = rect.height()
169        d_fr = math.sqrt(w_fr ** 2 + h_fr ** 2)
170
171        x_mds, y_mds = zip(*mds.points)
172        w_mds = max(x_mds) - min(x_mds)
173        h_mds = max(y_mds) - min(y_mds)
174        d_mds = math.sqrt(w_mds ** 2 + h_mds ** 2)
175
176        animate_points = p.animate_points
177        p.animate_points = False
178
179        # if only one component
180        if d_mds == 0 or d_fr == 0:
181            d_mds = 1
182            d_fr = 1
183
184        self.set_node_coordinates({key: (node.x() * d_mds / d_fr, node.y() * d_mds / d_fr) \
185                                   for key, node in nodes.iteritems()})
186
187        #self.update_properties()
188        p.update_layout()
189        qApp.processEvents()
190
191        if opt_from_curr:
192            if avgLinkage:
193                for u, c in enumerate(graph_components):
194                    x = sum([nodes[n].x() for n in c]) / len(c)
195                    y = sum([nodes[n].y() for n in c]) / len(c)
196                    mds.points[u][0] = x
197                    mds.points[u][1] = y
198            else:
199                for i, u in enumerate(sorted(nodes.iterkeys())):
200                    mds.points[i][0] = nodes[u].x()
201                    mds.points[i][1] = nodes[u].y()
202        else:
203            mds.Torgerson()
204
205        mds.optimize(steps, projection.mds.SgnRelStress, minStressDelta,
206                     progressCallback=
207                         lambda a, b=None, mds=mds, mdsRefresh=mdsRefresh, graph_comp=graph_components,
208                                matrix_comp=matrix_components, progress_callback=progress_callback:
209                         self.fragviz_callback(a, b, mds, mdsRefresh, graph_comp, matrix_comp, progress_callback))
210
211        self.fragviz_callback(mds.avgStress, 0, mds, mdsRefresh, graph_components, matrix_components, progress_callback)
212
213        if progress_callback is not None:
214            progress_callback(mds.avgStress, self.mdsStep)
215
216        p.animate_points = animate_points
217        return 0
218
219    def mds_callback(self, a, b, mds, mdsRefresh, progress_callback):
220        """Refresh the UI when running  MDS."""
221
222        if not self.mdsStep % mdsRefresh:
223
224            self.set_node_coordinates({n: (mds.points[i][0], \
225                                           mds.points[i][1]) for i, n in enumerate(sorted(self.nodes()))})
226            self.plot().update_layout()
227            qApp.processEvents()
228
229            if progress_callback is not None:
230                progress_callback(a, self.mdsStep)
231
232        self.mdsStep += 1
233        return 0 if self.stopMDS else 1
234
235    def layout_mds(self, steps, distances, progress_callback=None, opt_from_curr=False):
236        """Position the network components according to similarities among
237        them.
238       
239        """
240        nodes = self.nodes()
241
242        if distances == None or distances.dim != len(nodes):
243            self.information('invalid or no distance matrix')
244            return 1
245
246        p = self.plot()
247
248        minStressDelta = 0
249        mdsRefresh = int(steps / 20)
250
251        self.mdsStep = 1
252        self.stopMDS = False
253
254        distances.matrixType = core.SymMatrix.Symmetric
255        mds = projection.mds.MDS(distances)
256        mds.optimize(10, projection.mds.SgnRelStress, 0)
257        rect = self.data_rect()
258        w_fr = rect.width()
259        h_fr = rect.height()
260        d_fr = math.sqrt(w_fr ** 2 + h_fr ** 2)
261
262        x_mds, y_mds = zip(*mds.points)
263        w_mds = max(x_mds) - min(x_mds)
264        h_mds = max(y_mds) - min(y_mds)
265        d_mds = math.sqrt(w_mds ** 2 + h_mds ** 2)
266
267        animate_points = p.animate_points
268        p.animate_points = False
269
270        self.set_node_coordinates(dict(
271           (n, (nodes[n].x() * d_mds / d_fr, nodes[n].y() * d_mds / d_fr)) for n in nodes))
272
273        p.update_layout()
274        qApp.processEvents()
275
276        if opt_from_curr:
277            for i, u in enumerate(sorted(nodes.iterkeys())):
278                mds.points[i][0] = nodes[u].x()
279                mds.points[i][1] = nodes[u].y()
280        else:
281            mds.Torgerson()
282
283        mds.optimize(steps, projection.mds.SgnRelStress, minStressDelta,
284                     progressCallback=
285                         lambda a,
286                                b=None,
287                                mds=mds,
288                                mdsRefresh=mdsRefresh,
289                                progress_callback=progress_callback:
290                                    self.mds_callback(a, b, mds, mdsRefresh, progress_callback))
291
292        self.mds_callback(mds.avgStress, 0, mds, mdsRefresh, progress_callback)
293
294        if progress_callback is not None:
295            progress_callback(mds.avgStress, self.mdsStep)
296
297        p.animate_points = animate_points
298        return 0
299
300#    def move_selected_nodes(self, dx, dy):
301#        selected = self.get_selected_nodes()
302#       
303#        self.coors[selected][0] = self.coors[0][selected] + dx
304#        self.coors[1][selected][1] = self.coors[1][selected] + dy
305#         
306#        self.update_properties()
307#        return selected
308#       
309#    def set_hidden_nodes(self, nodes):
310#        for vertex in self.nodes().itervalues():
311#            vertex.setVisible(vertex.index() in nodes)
312#     
313#    def hide_selected_nodes(self):
314#        for vertex in self.nodes().itervalues():
315#          if vertex.selected:
316#            vertex.hide()
317
318#    def hide_unselected_nodes(self):
319#        for vertex in self.nodes().itervalues():
320#          if not vertex.selected:
321#            vertex.hide()
322#   
323#    def show_all_vertices(self):
324#        for vertex in self.nodes().itervalues():
325#          vertex.show()
326
327
328
329class OWNxCanvas(OWPlot):
330    def __init__(self, master, parent=None, name="None"):
331        OWPlot.__init__(self, parent, name, axes=[])
332        self.master = master
333        self.parent = parent
334        self.NodeItem = NodeItem
335        self.graph = None
336
337        self.circles = []
338        self.freezeNeighbours = False
339        self.labelsOnMarkedOnly = 0
340
341        self.show_indices = False
342        self.show_weights = False
343        self.trim_label_words = 0
344        self.show_component_distances = False
345
346        self.showComponentAttribute = None
347        self.forceVectors = None
348        #self.appendToSelection = 1
349        self.fontSize = 12
350
351        self.networkCurve = NetworkCurve()
352        self.add_custom_curve(self.networkCurve)
353
354        self.minComponentEdgeWidth = 0
355        self.maxComponentEdgeWidth = 0
356        self.items_matrix = None
357
358        self.items = None
359        self.links = None
360        self.edge_to_row = None
361        self.label_distances = None
362
363        self.node_label_attributes = []
364        self.edge_label_attributes = []
365
366        self.axis_margin = 0
367        self.title_margin = 0
368        self.graph_margin = 1
369        self._legend_margin = QRectF(0, 0, 0, 0)
370
371        #self.setFocusPolicy(Qt.StrongFocus)
372
373    def set_hidden_nodes(self, nodes):
374        self.networkCurve.set_hidden_nodes(nodes)
375
376    def hide_selected_nodes(self):
377      self.networkCurve.hide_selected_nodes()
378      self.drawPlotItems()
379
380    def hide_unselected_nodes(self):
381      self.networkCurve.hide_unselected_nodes()
382      self.drawPlotItems()
383
384    def show_all_vertices(self):
385      self.networkCurve.show_all_vertices()
386      self.drawPlotItems()
387
388    def selected_nodes(self):
389        return [vertex.index() for vertex in self.networkCurve.nodes().itervalues() if vertex.is_selected()]
390        #return [p.index() for p in self.selected_points()]
391
392    def not_selected_nodes(self):
393        return [vertex.index() for vertex in self.networkCurve.nodes().itervalues() if not vertex.is_selected()]
394
395    def marked_nodes(self):
396        return [vertex.index() for vertex in self.networkCurve.nodes().itervalues() if vertex.is_marked()]
397        #return [p.index() for p in self.marked_points()]
398
399    def not_marked_nodes(self):
400        return [vertex.index() for vertex in self.networkCurve.nodes().itervalues() if not vertex.is_marked()]
401
402    def get_neighbors_upto(self, ndx, dist):
403        newNeighbours = neighbours = set([ndx])
404        for d in range(dist):
405            tNewNeighbours = set()
406            for v in newNeighbours:
407                tNewNeighbours |= set(self.graph.neighbors(v))
408            newNeighbours = tNewNeighbours - neighbours
409            neighbours |= newNeighbours
410        return neighbours
411
412    def mark_on_selection_changed(self):
413        toMark = set()
414        for ndx in self.selected_nodes():
415            toMark |= self.get_neighbors_upto(ndx, self.mark_neighbors)
416
417        self.networkCurve.clear_node_marks()
418        self.networkCurve.set_node_marks(dict((i, True) for i in toMark))
419
420    def mark_on_focus_changed(self, node):
421        self.networkCurve.clear_node_marks()
422
423        if node is not None:
424            toMark = set(self.get_neighbors_upto(node.index(), self.mark_neighbors))
425            self.networkCurve.set_node_marks(dict((i, True) for i in toMark))
426
427    def drawComponentKeywords(self):
428        self.clear_markers()
429        if not hasattr(self, "showComponentAttribute") or self.showComponentAttribute is None or self.graph is None or self.items is None:
430            return
431
432        if str(self.showComponentAttribute) not in self.items.domain:
433            self.showComponentAttribute = None
434            return
435
436        components = network.nx.algorithms.components.connected_components(self.graph)
437        nodes = self.networkCurve.nodes()
438
439        for c in components:
440            if len(c) == 0:
441                continue
442
443            x1 = sum(nodes[n].x() for n in c) / len(c)
444            y1 = sum(nodes[n].y() for n in c) / len(c)
445            lbl = str(self.items[c[0]][str(self.showComponentAttribute)])
446
447            self.add_marker(lbl, x1, y1, alignment=Qt.AlignCenter, size=self.fontSize)
448
449    def getColorIndeces(self, table, attribute, palette):
450        colorIndices = {}
451        colorIndex = None
452        minValue = None
453        maxValue = None
454
455        if attribute[0] != "(" or attribute[ -1] != ")":
456            i = 0
457            for var in table.domain.variables:
458                if var.name == attribute:
459                    colorIndex = i
460                    if var.varType == core.VarTypes.Discrete:
461                        colorIndices = getVariableValueIndices(var, colorIndex)
462
463                i += 1
464            metas = table.domain.getmetas()
465            for i, var in metas.iteritems():
466                if var.name == attribute:
467                    colorIndex = i
468                    if var.varType == core.VarTypes.Discrete:
469                        colorIndices = getVariableValueIndices(var, colorIndex)
470
471        colorIndices['?'] = len(colorIndices)
472        palette.setNumberOfColors(len(colorIndices))
473
474        if colorIndex != None and table.domain[colorIndex].varType == core.VarTypes.Continuous:
475            minValue = float(min([x[colorIndex].value for x in table if x[colorIndex].value != "?"] or [0.0]))
476            maxValue = float(max([x[colorIndex].value for x in table if x[colorIndex].value != "?"] or [0.0]))
477
478        return colorIndices, colorIndex, minValue, maxValue
479
480    def set_node_colors(self, attribute, nodes=None):
481        if self.graph is None:
482            return
483
484        colorIndices, colorIndex, minValue, maxValue = self.getColorIndeces(self.items, attribute, self.discPalette)
485        colors = {}
486
487        if nodes is None:
488            nodes = self.graph.nodes()
489
490        if colorIndex is not None and self.items.domain[colorIndex].varType == core.VarTypes.Continuous and minValue == maxValue:
491            colors.update((node, self.discPalette[0]) for node in nodes)
492
493        elif colorIndex is not None and self.items.domain[colorIndex].varType == core.VarTypes.Continuous:
494            colors.update((v, self.contPalette[(float(self.items[v][colorIndex].value) - minValue) / (maxValue - minValue)])
495                          if str(self.items[v][colorIndex].value) != '?' else
496                          (v, self.discPalette[0]) for v in nodes)
497
498        elif colorIndex is not None and self.items.domain[colorIndex].varType == core.VarTypes.Discrete:
499            colors.update((v, self.discPalette[colorIndices[self.items[v][colorIndex].value]]) for v in nodes)
500
501        elif colorIndex is not None and self.items.domain[colorIndex].varType == core.VarTypes.String and self.items.domain[colorIndex].name == "label":
502            colorIndices = {v: i for i, v in enumerate(set(inst[colorIndex].value for inst in self.items))}
503            colors.update((v, self.discPalette[colorIndices[self.items[v][colorIndex].value]]) for v in nodes)
504        else:
505            colors.update((node, self.discPalette[0]) for node in nodes)
506
507        self.networkCurve.set_node_colors(colors)
508        self.replot()
509
510    def set_node_labels(self, attributes=None):
511        if self.graph is None:
512            return
513
514        nodes = self.graph.nodes()
515
516        if attributes is not None:
517            self.node_label_attributes = attributes
518
519        label_attributes = []
520        if self.items is not None and isinstance(self.items, data.Table):
521            label_attributes = [self.items.domain[att] for att in \
522                self.node_label_attributes if att in self.items.domain]
523
524        indices = [[] for u in nodes]
525        if self.show_indices:
526            indices = [[str(u)] for u in nodes]
527
528        distances = [[] for u in nodes]
529        show_distances = False
530        if self.label_distances is not None and type(self.label_distances) == \
531                           type([]) and len(self.label_distances) == len(nodes):
532            distances = self.label_distances
533            show_distances = True
534
535        if len(label_attributes) == 0 and \
536                        not self.show_indices and not show_distances:
537            self.networkCurve.set_node_labels({})
538
539        elif self.trim_label_words > 0:
540            self.networkCurve.set_node_labels(dict((node,
541                ', '.join(distances[i] + indices[i] +
542                          [' '.join(str(self.items[node][att]).split(' ')[:min(self.trim_label_words, len(str(self.items[node][att]).split(' ')))])
543                for att in label_attributes])) for i, node in enumerate(nodes)))
544        else:
545            self.networkCurve.set_node_labels(dict((node, ', '.join(\
546                        distances[i] + indices[i] + \
547                           [str(self.items[node][att]) for att in \
548                           label_attributes])) for i, node in enumerate(nodes)))
549
550        self.replot()
551
552
553    def set_edge_colors(self, attribute):
554        if self.graph is None:
555            return
556
557        colorIndices, colorIndex, minValue, maxValue = self.getColorIndeces(self.links, attribute, self.discPalette)
558        colors = []
559
560        if colorIndex is not None and self.links.domain[colorIndex].varType == core.VarTypes.Continuous and minValue == maxValue:
561            colors = [self.discEdgePalette[0] for edge in self.networkCurve.edge_indices()]
562
563        elif colorIndex is not None and self.links.domain[colorIndex].varType == core.VarTypes.Continuous:
564            colors = [self.contPalette[(float(self.links[edge.links_index()][colorIndex].value) - minValue) / (maxValue - minValue)]
565                          if str(self.links[edge.links_index()][colorIndex].value) != '?' else
566                          self.discPalette[0] for edge in self.networkCurve.edges()]
567
568        elif colorIndex is not None and self.links.domain[colorIndex].varType == core.VarTypes.Discrete:
569            colors = [self.discEdgePalette[colorIndices[self.links[edge.links_index()][colorIndex].value]] for edge in self.networkCurve.edges()]
570
571        else:
572            colors = [self.discEdgePalette[0] for edge in self.networkCurve.edge_indices()]
573
574        self.networkCurve.set_edge_colors(colors)
575        self.replot()
576
577    def set_edge_labels(self, attributes=None):
578        if self.graph is None:
579            return
580
581        edges = self.networkCurve.edge_indices()
582
583        if attributes is not None:
584            self.edge_label_attributes = attributes
585
586        label_attributes = []
587        if self.links is not None and isinstance(self.links, data.Table):
588            label_attributes = [self.links.domain[att] for att in \
589                self.edge_label_attributes if att in self.links.domain]
590
591        weights = [[] for ex in edges]
592        if self.show_weights:
593            weights = [["%.2f" % self.graph[u][v].get('weight', 1)] for u, v in edges]
594
595        self.networkCurve.set_edge_labels([', '.join(weights[i] + \
596                           [str(self.links[i][att]) for att in \
597                           label_attributes]) for i, edge in enumerate(edges)])
598
599        self.replot()
600
601    def set_tooltip_attributes(self, attributes):
602        if self.graph is None or self.items is None or \
603           not isinstance(self.items, data.Table):
604            return
605
606        tooltip_attributes = [self.items.domain[att] for att in \
607                                 attributes if att in self.items.domain]
608        self.networkCurve.set_node_tooltips(dict((node, ', '.join(str( \
609                   self.items[node][att]) for att in tooltip_attributes)) \
610                                                        for node in self.graph))
611
612    def change_graph(self, newgraph):
613        old_nodes = set(self.graph.nodes_iter())
614        new_nodes = set(newgraph.nodes_iter())
615        inter_nodes = old_nodes & new_nodes
616        remove_nodes = list(old_nodes - inter_nodes)
617        add_nodes = list(new_nodes - inter_nodes)
618
619        self.graph = newgraph
620
621        if len(remove_nodes) == 0 and len(add_nodes) == 0:
622            return False
623
624        current_nodes = self.networkCurve.nodes()
625
626        center_x = numpy.average([node.x() for node in current_nodes.itervalues()]) if len(current_nodes) > 0 else 0
627        center_y = numpy.average([node.y() for node in current_nodes.itervalues()]) if len(current_nodes) > 0 else 0
628
629        def closest_nodes_with_pos(nodes):
630
631            neighbors = set()
632            for n in nodes:
633                neighbors |= set(self.graph.neighbors(n))
634
635            # checked all, none found           
636            if len(neighbors - nodes) == 0:
637                return []
638
639            inter = old_nodes.intersection(neighbors)
640            if len(inter) > 0:
641                return inter
642            else:
643                return closest_nodes_with_pos(neighbors | nodes)
644
645        pos = dict((n, [numpy.average(c) for c in zip(*[(current_nodes[u].x(), current_nodes[u].y()) for u in closest_nodes_with_pos(set([n]))])]) for n in add_nodes)
646
647        self.networkCurve.remove_nodes(remove_nodes)
648
649        nodes = dict((v, self.NodeItem(v, x=pos[v][0] if len(pos[v]) == 2 else center_x, y=pos[v][1] if len(pos[v]) == 2 else center_y, parent=self.networkCurve)) for v in add_nodes)
650        self.networkCurve.add_nodes(nodes)
651        nodes = self.networkCurve.nodes()
652
653        #add edges
654        new_edges = self.graph.edges(add_nodes)
655
656        if self.links is not None and len(self.links) > 0:
657            links = self.links
658            links_indices = (self.edge_to_row[i + 1][j + 1] for (i, j) in new_edges)
659
660            if self.graph.is_directed():
661                edges = [EdgeItem(nodes[i], nodes[j],
662                    self.graph[i][j].get('weight', 1), links_index, arrows=EdgeItem.ArrowV, \
663                    parent=self.networkCurve) for ((i, j), links_index) in \
664                         zip(new_edges, links_indices)]
665            else:
666                edges = [EdgeItem(nodes[i], nodes[j],
667                    self.graph[i][j].get('weight', 1), links_index) for \
668                    ((i, j), links_index) in zip(new_edges, \
669                                        links_indices, parent=self.networkCurve)]
670        elif self.graph.is_directed():
671            edges = [EdgeItem(nodes[i], nodes[j], self.graph[i][j].get('weight', 1), \
672                    arrows=EdgeItem.ArrowV, parent=self.networkCurve) for (i, j) in new_edges]
673        else:
674            edges = [EdgeItem(nodes[i], nodes[j], self.graph[i][j].get('weight', 1), \
675                    parent=self.networkCurve) for (i, j) in new_edges]
676
677        self.networkCurve.add_edges(edges)
678
679        if len(current_nodes) < 3:
680            self.networkCurve.random()
681
682        return True
683
684    def set_graph(self, graph, curve=None, items=None, links=None):
685        self.clear()
686
687        if graph is None:
688            self.graph = None
689            self.networkCurve = None
690            self.items = None
691            self.links = None
692            xMin = -1.0
693            xMax = 1.0
694            yMin = -1.0
695            yMax = 1.0
696            self.addMarker("no network", (xMax - xMin) / 2, (yMax - yMin) / 2, alignment=Qt.AlignCenter, size=self.fontSize)
697            self.replot()
698            return
699
700        self.graph = graph
701        self.networkCurve = NetworkCurve() if curve is None else curve()
702        self.add_custom_curve(self.networkCurve)
703
704        self.items = items if items is not None else self.graph.items()
705        self.links = links if links is not None else self.graph.links()
706
707        #add nodes
708        #self.vertices_old = [(None, []) for v in self.graph]
709        nodes = dict((v, self.NodeItem(v, parent=self.networkCurve)) for v in self.graph.nodes_iter())
710        self.networkCurve.set_nodes(nodes)
711
712        #build edge to row index
713        self.edge_to_row = {}
714        if self.links is not None and len(self.links) > 0:
715            for i, r in enumerate(self.links):
716                u = int(r['u'].value)
717                v = int(r['v'].value)
718                if u - 1 in self.graph and v - 1 in self.graph:
719                    u_dict = self.edge_to_row.get(u, {})
720                    v_dict = self.edge_to_row.get(v, {})
721                    u_dict[v] = i
722                    v_dict[u] = i
723                    self.edge_to_row[u] = u_dict
724                    self.edge_to_row[v] = v_dict
725                else:
726                    print 'could not find edge', u, v
727
728        #add edges
729        if self.links is not None and len(self.links) > 0:
730            links = self.links
731            links_indices = (self.edge_to_row[i + 1][j + 1] \
732                             for (i, j) in self.graph.edges_iter())
733
734            arrow = EdgeItem.ArrowV if self.graph.is_directed() else None
735
736            edges = [EdgeItem(nodes[i], nodes[j],
737                    graph[i][j].get('weight', 1), links_index, arrows=arrow, \
738                    parent=self.networkCurve) for ((i, j), links_index) in \
739                         zip(self.graph.edges_iter(), links_indices)]
740        else:
741            arrow = EdgeItem.ArrowV if self.graph.is_directed() else None
742
743            edges = [EdgeItem(nodes[i], nodes[j], graph[i][j].get('weight', 1), \
744                              arrows=arrow, parent=self.networkCurve) \
745                                  for (i, j) in self.graph.edges_iter()]
746
747        self.networkCurve.set_edges(edges)
748        self.networkCurve.update_properties()
749        self.replot()
750
751    def update_animations(self, use_animations=None):
752        OWPlot.update_animations(self, use_animations)
753        self.networkCurve.set_use_animations(self.use_animations)
754
755    def set_labels_on_marked(self, labelsOnMarkedOnly):
756        self.networkCurve.set_labels_on_marked(labelsOnMarkedOnly)
757        self.set_node_labels()
758        self.replot()
759
760    def set_show_component_distances(self):
761        self.networkCurve.set_show_component_distances(self.show_component_distances)
762        self.replot()
763
764    def update_layout(self):
765        self._bounds_cache = {}
766        self._transform_cache = {}
767        OWPlot.update_layout(self)
768
769    def replot(self):
770        self.drawComponentKeywords()
771        OWPlot.replot(self)
Note: See TracBrowser for help on using the repository browser.