source: orange/Orange/OrangeWidgets/Visualize Qt/OWNxCanvas3D.py @ 10854:e1100b7b4761

Revision 10854:e1100b7b4761, 29.5 KB checked in by anze <anze.staric@…>, 2 years ago (diff)

Fixed imports of orangeqt

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