source: orange/Orange/OrangeWidgets/VisualizeQt/OWNxCanvas3D.py @ 11474:df0622184ee6

Revision 11474:df0622184ee6, 29.5 KB checked in by markotoplak, 12 months ago (diff)

Renamed Visualize Qt to VisualizeQt (so it can be loaded in new canvas).

RevLine 
[9079]1from plot.owplot3d import OWPlot3D, GL_FLOAT, GL_LINES, GL_POINTS, glEnable, GL_PROGRAM_POINT_SIZE
2from plot.owopenglrenderer import VertexBuffer
[9047]3from PyQt4.QtCore import Qt
[9064]4from PyQt4.QtGui import QVBoxLayout
[9079]5from PyQt4 import QtOpenGL
[10854]6from Orange import orangeqt
[9045]7import Orange
8import orange
9import numpy
10import math
[9079]11import os
[9045]12
13from orngScaleScatterPlotData import getVariableValueIndices
14
15class Node3D(orangeqt.Node3D):
[9079]16    # TODO: __slot__
[9045]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
[9047]36class OWNxCanvas3D(orangeqt.Canvas3D):
[9045]37    def __init__(self, master, parent=None, name='None'):
38        orangeqt.Canvas3D.__init__(self, parent)
39
[9064]40        layout = QVBoxLayout()
[9047]41        self.plot = OWPlot3D(self)
[9064]42        layout.addWidget(self.plot)
43        self.setLayout(layout)
[9056]44        self.plot.initializeGL()
[9064]45        self.plot.before_draw_callback = self.draw_callback
[9047]46        self.plot.replot = self.plot.update
47        self.gui = self.plot.gui
48        self.saveToFile = self.plot.save_to_file
49
[9045]50        # A little workaround, since NetExplorer sometimes calls networkCurve directly
51        self.networkCurve = self
52
[9047]53        self.Node3D = Node3D
[9045]54        self.replot = self.update
[9047]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
[9045]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
[9079]93        self._markers = []
94
[9064]95    def draw_callback(self):
[9079]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)
[9104]115            self._node_shader.bindAttributeLocation('offset', 1)
116            self._node_shader.bindAttributeLocation('color', 2)
117            self._node_shader.bindAttributeLocation('selected_marked', 3)
[9079]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)
[9081]128        orangeqt.Canvas3D.draw_edges(self)
[9079]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)
[9104]137        self._node_shader.setUniformValue('mode', 0.)
[9081]138        orangeqt.Canvas3D.draw_nodes(self)
[9079]139        self._node_shader.release()
[9064]140
[9045]141    def update_canvas(self):
[9079]142        self.update_component_keywords()
[9045]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
[9079]193    def update_component_keywords(self):
[9045]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
[9079]204        self._markers = []
205
[9045]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)
[9079]212            z1 = sum(nodes[n].z() for n in c) / len(c)
[9045]213            lbl = str(self.items[c[0]][str(self.show_component_attribute)])
214
[9079]215            self._markers.append((lbl, x1, y1, z1))
[9045]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
[9079]224        if attribute[0] != "(" or attribute[-1] != ")":
[9045]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
[9056]249    getColorIndeces = get_color_indices
250
[9045]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 = {}
[9079]257
[9045]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)
[9079]263
[9045]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)
[9079]271
[9045]272        else:
273            colors.update((node, self.discPalette[0]) for node in nodes)
[9079]274
[9045]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
[9079]286
[9045]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]
[9079]291
[9045]292        indices = [[] for u in nodes]
293        if self.show_indices:
294            indices = [[str(u)] for u in nodes]
[9079]295
[9045]296        if self.trim_label_words > 0:
[9056]297            orangeqt.Canvas3D.set_node_labels(self, dict((node, 
[9045]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:
[9056]302            orangeqt.Canvas3D.set_node_labels(self, dict((node, ', '.join(indices[i]+\
[9045]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:
[9056]315            colors = [self.discEdgePalette[0] for edge in orangeqt.Canvas3D.edge_indices(self)]
[9045]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 
[9056]320                          self.discPalette[0] for edge in orangeqt.Canvas3D.edges(self)]
[9045]321           
322        elif colorIndex is not None and self.links.domain[colorIndex].varType == orange.VarTypes.Discrete:
[9056]323            colors = [self.discEdgePalette[colorIndices[self.links[edge.links_index()][colorIndex].value]] for edge in orangeqt.Canvas3D.edges(self)]
[9045]324           
325        else:
[9056]326            colors = [self.discEdgePalette[0] for edge in orangeqt.Canvas3D.edge_indices(self)]
[9045]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 
[9079]334
[9045]335        edges = self.edge_indices()
336
337        if attributes is not None:
338            self.edge_label_attributes = attributes
[9079]339
[9045]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]
[9079]344
[9045]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]
[9079]348
[9045]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
[9056]352        self.update()
[9045]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
[9079]371
[9045]372        if len(remove_nodes) == 0 and len(add_nodes) == 0:
373            return False
[9079]374
[9045]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 []
[9079]385
[9045]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):
[9056]428        # TODO: clear previous nodes and edges?
[9045]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
[9079]438            zMin = -1.0
439            zMax = 1.0
440            self._markers.append(('no network', (xMax - xMin) / 2, (yMax - yMin) / 2, (zMax - zMin) / 2))
[9045]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
[9056]448        nodes = dict((v, self.Node3D(v)) for v in self.graph)
449        orangeqt.Canvas3D.set_nodes(self, nodes)
[9045]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():
[9056]471                edges = [Edge3D(nodes[i], nodes[j],
[9045]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:
[9056]474                edges = [Edge3D(nodes[i], nodes[j],
[9045]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():
[9056]477            edges = [Edge3D(nodes[i], nodes[j],
[9045]478                                      graph[i][j].get('weight', 1), arrows=Edge3D.ArrowV) for (i, j) in self.graph.edges()]
479        else:
[9056]480            edges = [Edge3D(nodes[i], nodes[j],
[9045]481                                      graph[i][j].get('weight', 1)) for (i, j) in self.graph.edges()]
482
483        self.set_edges(edges)
[9056]484        self._nodes = nodes # Store references, so these objects are not destroyed
485        self._edges = edges
[9045]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
[9064]603        #edges = self.edges()
[9045]604        nodes = self.nodes()
605
606        avgLinkage = True
[9064]607        #rotationOnly = False
[9045]608        minStressDelta = 0
609        mdsRefresh = int(steps / 20)
[9079]610
[9045]611        self.mdsStep = 1
612        self.stopMDS = False
[9079]613
[9045]614        components = Orange.network.nx.algorithms.components.connected.connected_components(graph)
615        distances.matrixType = Orange.core.SymMatrix.Symmetric
[9079]616
[9045]617        # scale net coordinates
618        if avgLinkage:
619            distances = distances.avgLinkage(components)
[9079]620
[9045]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)
[9079]627
[9045]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)
[9079]633
[9045]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))
[9079]636
[9045]637        self.update()
638        qApp.processEvents()
[9079]639
[9045]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))
[9081]663
[9045]664        self.mds_callback(mds.avgStress, 0, mds, mdsRefresh, components, progress_callback)
[9081]665
[9045]666        if progress_callback != None:
667            progress_callback(mds.avgStress, self.mdsStep)
[9081]668
[9045]669        return 0
670
671    def mds_callback(self, a, b, mds, mdsRefresh, progress_callback):
672        """Refresh the UI when running  MDS."""
[9079]673
[9045]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()
[9079]680
[9045]681            if progress_callback is not None:
[9079]682                progress_callback(a, self.mdsStep)
683
[9045]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()
[9079]692
[9045]693        if distances == None or distances.dim != len(nodes):
694            self.information('invalid or no distance matrix')
695            return 1
[9079]696
[9045]697        minStressDelta = 0
698        mdsRefresh = int(steps / 20)
[9079]699
[9045]700        self.mdsStep = 1
701        self.stopMDS = False
[9079]702
[9045]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)
[9079]710
[9045]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)
[9079]716
[9045]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))
[9079]719
[9045]720        self.update()
721        qApp.processEvents()
[9079]722
[9045]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))
[9079]738
[9045]739        self.mds_callback(mds.avgStress, 0, mds, mdsRefresh, progress_callback)
[9079]740
[9045]741        if progress_callback != None:
742            progress_callback(mds.avgStress, self.mdsStep)
[9079]743
[9045]744        return 0
745
[9047]746    def update(self):
[9081]747        orangeqt.Canvas3D.update(self)
748        self.plot.update()
[9079]749
Note: See TracBrowser for help on using the repository browser.