Commit 25fa0bfee2798ab831c75ced310a05bc1b73b929
1 parent
7c54fa21
Stable, pre-vispy update
Showing
10 changed files
with
746 additions
and
205 deletions
Show diff stats
GraphCanvas.py
... | ... | @@ -12,6 +12,7 @@ from vispy import gloo, scene |
12 | 12 | from vispy.gloo import set_viewport, set_state, clear, set_blend_color, context |
13 | 13 | from vispy.util.transforms import perspective, translate, rotate, scale |
14 | 14 | import vispy.gloo.gl as glcore |
15 | +from vispy import app | |
15 | 16 | |
16 | 17 | import numpy as np |
17 | 18 | import math |
... | ... | @@ -94,7 +95,7 @@ class GraphCanvas(scene.SceneCanvas): |
94 | 95 | n = 10 |
95 | 96 | ne = 10 |
96 | 97 | #Init dummy structures |
97 | - self.uniforms = [('u_graph_size', np.float32, 3)] | |
98 | + #self.uniforms = [('u_graph_size', np.float32, 3)] | |
98 | 99 | self.data = np.zeros(n, dtype=[('a_position', np.float32, 3), |
99 | 100 | ('a_fg_color', np.float32, 4), |
100 | 101 | ('a_bg_color', np.float32, 4), |
... | ... | @@ -102,13 +103,30 @@ class GraphCanvas(scene.SceneCanvas): |
102 | 103 | ('a_linewidth', np.float32, 1), |
103 | 104 | ('a_unique_id', np.float32, 4), |
104 | 105 | ]) |
106 | + | |
107 | + self.line_data = np.zeros(ne, dtype=[('a_position', np.float32, 3), | |
108 | + ('a_normal', np.float32, 2), | |
109 | + ('a_fg_color', np.float32, 4), | |
110 | + ('a_linewidth', np.float32, 1), | |
111 | + ]) | |
112 | + | |
113 | + | |
114 | + self.clusters = np.zeros(n*4, dtype=[('a_position', np.float32, 3), | |
115 | + ('a_value', np.float32, 2), | |
116 | + ('a_bg_color', np.float32, 4), | |
117 | + ('a_cluster_color', np.float32, 4), | |
118 | + ('a_arc_length', np.float32, 1), | |
119 | + ('a_outer_arc_length', np.float32, 4), | |
120 | + ('a_unique_id', np.float32, 4), | |
121 | + ]) | |
105 | 122 | |
106 | - self.clusters = np.zeros(n, dtype=[('a_position', np.float32, 3), | |
107 | - ('a_bg_color', np.float32, 4), | |
108 | - ('a_value', np.float32, 2), | |
109 | - ('a_unique_id', np.float32, 4), | |
110 | - ]) | |
123 | + self.cluster_line_data = np.zeros(ne, dtype=[('a_position', np.float32, 3), | |
124 | + ('a_normal', np.float32, 2), | |
125 | + ('a_fg_color', np.float32, 4), | |
126 | + ('a_linewidth', np.float32, 1), | |
127 | + ]) | |
111 | 128 | |
129 | + | |
112 | 130 | self.edges = np.random.randint(size=(ne, 2), low=0, |
113 | 131 | high=n-1).astype(np.uint32) |
114 | 132 | self.edges_s = np.random.randint(size=(ne, 4), low=0, |
... | ... | @@ -134,7 +152,7 @@ class GraphCanvas(scene.SceneCanvas): |
134 | 152 | self.vbo = gloo.VertexBuffer(self.data) |
135 | 153 | self.vbo_s = gloo.VertexBuffer(self.clusters) |
136 | 154 | |
137 | - #Need to initialize thick lines. | |
155 | + #Need to initialize thic/k lines. | |
138 | 156 | self.index = gloo.IndexBuffer(self.edges) |
139 | 157 | self.index_s = gloo.IndexBuffer(self.edges_s) |
140 | 158 | |
... | ... | @@ -151,35 +169,36 @@ class GraphCanvas(scene.SceneCanvas): |
151 | 169 | self.program['u_model'] = self.model |
152 | 170 | self.program['u_view'] = self.view |
153 | 171 | self.program['u_projection'] = self.projection |
154 | - self.program['u_graph_size'] = [1.0, 1.0, 1.0] | |
172 | + #self.program['u_graph_size'] = [1.0, 1.0, 1.0] | |
155 | 173 | self.program['u_picking'] = False |
156 | 174 | |
175 | + self.vbo_line = gloo.VertexBuffer(self.line_data) | |
157 | 176 | #init shades used for the edges in the graph |
158 | 177 | self.program_e = gloo.Program(vs, fs) |
159 | - self.program_e['u_size'] = 1 | |
178 | +# self.program_e['u_size'] = 1 | |
160 | 179 | self.program_e['u_model'] = self.model |
161 | 180 | self.program_e['u_view'] = self.view |
162 | 181 | self.program_e['u_projection'] = self.projection |
163 | 182 | #self.program_e['l_color'] = self.linecolor.astype(np.float32) |
164 | - self.program_e.bind(self.vbo) | |
165 | - | |
183 | + self.program_e.bind(self.vbo_line) | |
184 | + | |
166 | 185 | #init shaders used to the vertices in the subgraph graph. |
167 | 186 | self.program_s = gloo.Program(vert_s, frag_s) |
168 | 187 | self.program_s.bind(self.vbo_s) |
169 | 188 | self.program_s['u_model'] = self.model |
170 | 189 | self.program_s['u_view'] = self.view |
171 | 190 | self.program_s['u_projection'] = self.projection |
172 | - self.program_s['u_graph_size'] = [1.0, 1.0, 1.0] | |
191 | + #self.program_s['u_graph_size'] = [1.0, 1.0, 1.0] | |
173 | 192 | self.program_s['u_picking'] = False |
174 | 193 | |
175 | 194 | #init shaders used for the subgraph-edges |
176 | 195 | self.program_e_s = gloo.Program(vs_s, fs_s) |
177 | - self.program_e_s['u_size'] = 1 | |
178 | 196 | self.program_e_s['u_model'] = self.model |
179 | 197 | self.program_e_s['u_view'] = self.view |
180 | 198 | self.program_e_s['u_projection'] = self.projection |
181 | 199 | #self.program_e['l_color'] = self.linecolor.astype(np.float32) |
182 | - self.program_e_s.bind(self.vbo_s) | |
200 | + self.vbo_cluster_lines = gloo.VertexBuffer(self.cluster_line_data) | |
201 | + self.program_e_s.bind(self.vbo_cluster_lines) | |
183 | 202 | |
184 | 203 | |
185 | 204 | #set up the viewport and the gl state. |
... | ... | @@ -187,6 +206,86 @@ class GraphCanvas(scene.SceneCanvas): |
187 | 206 | |
188 | 207 | set_state(clear_color='white', depth_test=True, blend=True, |
189 | 208 | blend_func=('src_alpha', 'one_minus_src_alpha'), depth_func = ('lequal')) |
209 | + | |
210 | + | |
211 | + self.timer = app.Timer('auto', connect=self.on_timer, start=False) | |
212 | + | |
213 | + def on_timer(self, event): | |
214 | + #get the temporary positions of the vertices (and edges) | |
215 | + self.old_pos = np.add(self.old_pos, self.slopes) | |
216 | + #during each iteration set the new positions in the GPU | |
217 | + self.data['a_position'] = self.old_pos | |
218 | + #Adjust the edges | |
219 | + edges = self.G.get_edges() | |
220 | + for e in range(edges.shape[0]): | |
221 | + idx = int(4*edges[e][2]) | |
222 | + p0 = self.old_pos[edges[e][0], :] | |
223 | + p1 = self.old_pos[edges[e][1], :] | |
224 | + d = np.subtract(p1, p0) | |
225 | + #d_norm = np.multiply(d, 1/np.sqrt(np.power(d[0],2) + np.power(d[1],2))) | |
226 | + d_norm = d[0:2] | |
227 | + d_norm = d_norm / np.sqrt(np.power(d_norm[0],2) + np.power(d_norm[1],2)) | |
228 | + norm = np.zeros((2,), dtype=np.float32) | |
229 | + norm[0] = d_norm[1] | |
230 | + norm[1] = d_norm[0]*-1 | |
231 | + | |
232 | + self.edge_dict[int(edges[e][0]), int(edges[e][1])] = int(edges[e][2]) | |
233 | + self.line_data['a_position'][idx] = p0 | |
234 | + self.line_data['a_normal'][idx] = norm | |
235 | + | |
236 | + self.line_data['a_position'][idx+1] = p1 | |
237 | + self.line_data['a_normal'][idx+1] = norm | |
238 | + | |
239 | + self.line_data['a_position'][idx+2] = p0 | |
240 | + self.line_data['a_normal'][idx+2] = -norm | |
241 | + | |
242 | + self.line_data['a_position'][idx+3] = p1 | |
243 | + self.line_data['a_normal'][idx+3] = -norm | |
244 | + | |
245 | + #send data to GPU renderer | |
246 | + self.vbo.set_data(self.data) | |
247 | + self.program.bind(self.vbo) | |
248 | + self.vbo_line = gloo.VertexBuffer(self.line_data) | |
249 | + self.program_e.bind(self.vbo_line) | |
250 | + | |
251 | + | |
252 | + self.update_clusters(self.old_pos) | |
253 | + edges = self.G_cluster.get_edges() | |
254 | +# #generate the vertex buffer and the connections buffer. | |
255 | + for e in range(edges.shape[0]): | |
256 | + idx = int(4*edges[e][2]) | |
257 | + p0 = self.cluster_pos[int(edges[e][0])] | |
258 | + p1 = self.cluster_pos[int(edges[e][1])] | |
259 | + #p0 = self.G_cluster.vertex_properties["pos"][self.G_cluster.vertex(edges[e][0])] | |
260 | + #p1 = self.G_cluster.vertex_properties["pos"][self.G_cluster.vertex(edges[e][1])] | |
261 | + d = np.subtract(p1, p0) | |
262 | + #d_norm = np.multiply(d, 1/np.sqrt(np.power(d[0],2) + np.power(d[1],2))) | |
263 | + d_norm = d[0:2] | |
264 | + d_norm = d_norm / np.sqrt(np.power(d_norm[0],2) + np.power(d_norm[1],2)) | |
265 | + norm = np.zeros((2,), dtype=np.float32) | |
266 | + norm[0] = d_norm[1] | |
267 | + norm[1] = d_norm[0]*-1 | |
268 | + #print(np.sqrt(norm[0]*norm[0] + norm[1]*norm[1])) | |
269 | + #thickness = G.edge_properties["thickness"][e] | |
270 | + #self.cluster_dict[int(edges[e][0]), int(edges[e][1])] = int(edges[e][2]) | |
271 | + self.cluster_line_data['a_position'][idx] = p0 | |
272 | + self.cluster_line_data['a_normal'][idx] = norm | |
273 | + | |
274 | + self.cluster_line_data['a_position'][idx+1] = p1 | |
275 | + self.cluster_line_data['a_normal'][idx+1] = norm | |
276 | + | |
277 | + self.cluster_line_data['a_position'][idx+2] = p0 | |
278 | + self.cluster_line_data['a_normal'][idx+2] = -norm | |
279 | + | |
280 | + self.cluster_line_data['a_position'][idx+3] = p1 | |
281 | + self.cluster_line_data['a_normal'][idx+3] = -norm | |
282 | + | |
283 | + self.vbo_cluster_lines.set_data(self.cluster_line_data) | |
284 | + self.vbo_s.set_data(self.clusters) | |
285 | + self.program_s.bind(self.vbo_s) | |
286 | + self.program_e_s.bind(self.vbo_cluster_lines) | |
287 | + | |
288 | + self.update() | |
190 | 289 | |
191 | 290 | """ |
192 | 291 | Function that recolors vertices based on the selected statistic |
... | ... | @@ -377,6 +476,14 @@ class GraphCanvas(scene.SceneCanvas): |
377 | 476 | else: |
378 | 477 | G.edge_properties["RGBA"][e] = [0.0, 0.0, 0.0, 0.8] |
379 | 478 | |
479 | + """ | |
480 | + Test function that only binds the buffer | |
481 | + """ | |
482 | + def gen_vertex_vbo_minimalist(self): | |
483 | + self.update() | |
484 | + self.vbo.set_data(self.data) | |
485 | + self.program.bind(self.vbo) | |
486 | + self.update() | |
380 | 487 | |
381 | 488 | """ |
382 | 489 | Helper function that generates the framebuffer object that stores the vertices |
... | ... | @@ -418,7 +525,7 @@ class GraphCanvas(scene.SceneCanvas): |
418 | 525 | self.data['a_selection'] = G.vertex_properties["selection"].get_array() |
419 | 526 | #self.data['a_graph_size'] = [bbu-bbl] |
420 | 527 | |
421 | - self.program['u_graph_size'] = [self.bbu-self.bbl] | |
528 | + #self.program['u_graph_size'] = [self.bbu-self.bbl] | |
422 | 529 | |
423 | 530 | self.vbo = gloo.VertexBuffer(self.data) |
424 | 531 | self.gen_line_vbo(G) |
... | ... | @@ -499,7 +606,7 @@ class GraphCanvas(scene.SceneCanvas): |
499 | 606 | #self.program_e['l_color'] = self.linecolor.astype(np.float32) |
500 | 607 | self.vbo_line = gloo.VertexBuffer(self.line_data) |
501 | 608 | self.index = gloo.IndexBuffer(self.edges) |
502 | - self.program_e['u_size'] = 1 | |
609 | +# self.program_e['u_size'] = 1 | |
503 | 610 | self.program_e['u_model'] = self.model |
504 | 611 | self.program_e['u_view'] = self.view |
505 | 612 | self.program_e['u_projection'] = self.projection |
... | ... | @@ -591,7 +698,6 @@ class GraphCanvas(scene.SceneCanvas): |
591 | 698 | self.index_clusters_s = gloo.IndexBuffer(self.cluster_edges) |
592 | 699 | self.vbo_cluster_lines = gloo.VertexBuffer(self.cluster_line_data) |
593 | 700 | |
594 | - self.program_e_s['u_size'] = 1 | |
595 | 701 | self.program_e_s['u_model'] = self.model |
596 | 702 | self.program_e_s['u_view'] = self.view |
597 | 703 | self.program_e_s['u_projection'] = self.projection |
... | ... | @@ -648,8 +754,7 @@ class GraphCanvas(scene.SceneCanvas): |
648 | 754 | self.program_e_s = gloo.Program(vs_s, fs_s) |
649 | 755 | self.index_clusters_s = gloo.IndexBuffer(self.cluster_edges) |
650 | 756 | self.vbo_cluster_lines = gloo.VertexBuffer(self.cluster_line_data) |
651 | - | |
652 | - self.program_e_s['u_size'] = 1 | |
757 | + | |
653 | 758 | self.program_e_s['u_model'] = self.model |
654 | 759 | self.program_e_s['u_view'] = self.view |
655 | 760 | self.program_e_s['u_projection'] = self.projection |
... | ... | @@ -721,78 +826,99 @@ class GraphCanvas(scene.SceneCanvas): |
721 | 826 | def expand_based_on_clusters(self, G, n): |
722 | 827 | pos = G.vertex_properties["pos"].get_2d_array(range(3)).T |
723 | 828 | for p in range(pos.shape[0]): |
724 | - pos[p][0] = pos[p][0] + self.clusters["a_position"][G.vertex_properties["clusters"][G.vertex(p)]][0] | |
725 | - pos[p][1] = pos[p][1] + self.clusters["a_position"][G.vertex_properties["clusters"][G.vertex(p)]][1] | |
726 | - pos[p][2] = pos[p][2] + self.clusters["a_position"][G.vertex_properties["clusters"][G.vertex(p)]][2] | |
829 | + pos[p][0] = pos[p][0] - self.clusters["a_position"][G.vertex_properties["clusters"][G.vertex(p)]][0] | |
830 | + pos[p][1] = pos[p][1] - self.clusters["a_position"][G.vertex_properties["clusters"][G.vertex(p)]][1] | |
831 | + pos[p][2] = pos[p][2] - self.clusters["a_position"][G.vertex_properties["clusters"][G.vertex(p)]][2] | |
727 | 832 | G.vertex_properties["pos"] = G.new_vertex_property("vector<double>", vals = pos) |
728 | - for i in range(n): | |
729 | - index = 4*i | |
730 | - #generate the vertex filter for this cluster | |
731 | - num_v_in_cluster = len(np.argwhere(self.labels == i)) | |
732 | - vfilt = np.zeros([G.num_vertices(), 1], dtype="bool") | |
733 | - vfilt[np.argwhere(self.labels == i)] = 1 | |
734 | - vfilt_prop = G.new_vertex_property("bool", vals = vfilt) | |
735 | - G.set_vertex_filter(vfilt_prop) | |
833 | +# for i in range(n): | |
834 | +# index = 4*i | |
835 | +# #generate the vertex filter for this cluster | |
836 | +# num_v_in_cluster = len(np.argwhere(self.labels == i)) | |
837 | +# vfilt = np.zeros([G.num_vertices(), 1], dtype="bool") | |
838 | +# vfilt[np.argwhere(self.labels == i)] = 1 | |
839 | +# vfilt_prop = G.new_vertex_property("bool", vals = vfilt) | |
840 | +# G.set_vertex_filter(vfilt_prop) | |
841 | +# | |
842 | +# #get the filtered properties | |
843 | +# g = nwt.gt.Graph(G, prune=True, directed=False) | |
844 | +# positions = g.vertex_properties["pos"].get_2d_array(range(3)).T | |
845 | +# position = np.sum(positions, 0)/num_v_in_cluster | |
846 | +# p, v = self.gen_cluster_coords(position, np.sum(g.vertex_properties['degree'].get_array())) | |
847 | +# self.clusters['a_position'][index:index+4] = np.asarray(p, dtype=np.float32) | |
848 | +# self.clusters['a_value'][index:index+4] = np.asarray(v, dtype=np.float32) | |
849 | +# G.clear_filters() | |
850 | +# self.cluster_pos[i] = position | |
851 | +# color = G.vertex_properties["RGBA"].get_2d_array(range(4)).T | |
852 | +# size = nwt.Network.map_vertices_to_range(G, [30*self.pixel_scale, 8*self.pixel_scale], 'degree').get_array() | |
853 | +# | |
854 | +# position = G.vertex_properties["pos"].get_2d_array(range(3)).T | |
855 | +# #for p in range(position.shape[0]): | |
856 | +# # position[p][0] = position[p][0] + self.clusters["a_position"][G.vertex_properties["clusters"][G.vertex(p)]][0] | |
857 | +# # position[p][1] = position[p][1] + self.clusters["a_position"][G.vertex_properties["clusters"][G.vertex(p)]][1] | |
858 | +# # position[p][2] = position[p][2] + self.clusters["a_position"][G.vertex_properties["clusters"][G.vertex(p)]][2] | |
859 | +# #G.vertex_properties["pos"] = G.new_vertex_property("vector<double>", vals = position) | |
860 | +# | |
861 | +# | |
862 | +# edges = G.get_edges(); | |
863 | +# edges = edges[:, 0:2] | |
864 | +# #width = nwt.Network.map_edges_to_range(G, [1*self.pixel_scale, 5*self.pixel_scale], 'volume').get_array() | |
865 | +# #ecolor = G.edge_properties["RGBA"].get_2d_array(range(4)).T | |
866 | +# | |
867 | +# self.data = np.zeros(G.num_vertices(), dtype=[('a_position', np.float32, 3), | |
868 | +# ('a_fg_color', np.float32, 4), | |
869 | +# ('a_bg_color', np.float32, 4), | |
870 | +# ('a_size', np.float32, 1), | |
871 | +# ('a_linewidth', np.float32, 1), | |
872 | +# ('a_unique_id', np.float32, 4), | |
873 | +# ('a_selection', np.float32, 1), | |
874 | +# ]) | |
875 | +# | |
876 | +# #self.edges = edges.astype(np.uint32) | |
877 | +# self.data['a_position'] = position | |
878 | +# #fg color is the color of the ring | |
879 | +# self.data['a_fg_color'] = 0, 0, 0, 1 | |
880 | +# self.data['a_bg_color'] = color | |
881 | +# self.data['a_size'] = size | |
882 | +# self.data['a_linewidth'] = 4.*self.pixel_scale | |
883 | +# self.data['a_unique_id'] = self.gen_vertex_id(G) | |
884 | +# self.data['a_selection'] = G.vertex_properties["selection"].get_array() | |
885 | +# #self.data['a_graph_size'] = [bbu-bbl] | |
886 | +# | |
887 | +# self.program['u_graph_size'] = [self.bbu-self.bbl] | |
888 | +# self.vbo = gloo.VertexBuffer(self.data) | |
889 | +# self.gen_line_vbo(G) | |
890 | +# if(self.subgraphs): | |
891 | +# self.vbo_s = gloo.VertexBuffer(self.clusters) | |
892 | +# self.index_s = gloo.IndexBuffer(self.edges_s) | |
893 | +# #self.index = gloo.IndexBuffer(self.edges) | |
894 | +# self.program_e.bind(self.vbo_line) | |
895 | +# self.program.bind(self.vbo) | |
896 | +# if(self.subgraphs): | |
897 | +# #self.program_e_s.bind(self.vbo_s) | |
898 | +# self.program_s.bind(self.vbo_s) | |
899 | +# if DEBUG: | |
900 | +# print(self.view) | |
901 | +# self.update() | |
736 | 902 | |
737 | - #get the filtered properties | |
738 | - g = nwt.gt.Graph(G, prune=True, directed=False) | |
739 | - positions = g.vertex_properties["pos"].get_2d_array(range(3)).T | |
740 | - position = np.sum(positions, 0)/num_v_in_cluster | |
741 | - p, v = self.gen_cluster_coords(position, np.sum(g.vertex_properties['degree'].get_array())) | |
903 | + | |
904 | + """ | |
905 | + Function that updates the cluster positions based on new vertex positions | |
906 | + in the graph. Primarity used for animation. | |
907 | + """ | |
908 | + def update_clusters(self, new_pos): | |
909 | + clusters = self.G.vertex_properties["clusters"].get_array().T | |
910 | + for i in range(self.n_c): | |
911 | + idx = np.argwhere(clusters == i) | |
912 | + pos = np.sum(new_pos[idx], 0)/len(idx) | |
913 | + self.cluster_pos[i] = pos.reshape(3) | |
914 | + index = i*4 | |
915 | + p, v = self.gen_cluster_coords(self.cluster_pos[i], self.cluster_size[i]) | |
742 | 916 | self.clusters['a_position'][index:index+4] = np.asarray(p, dtype=np.float32) |
743 | 917 | self.clusters['a_value'][index:index+4] = np.asarray(v, dtype=np.float32) |
744 | - G.clear_filters() | |
745 | - self.cluster_pos[i] = position | |
746 | - color = G.vertex_properties["RGBA"].get_2d_array(range(4)).T | |
747 | - size = nwt.Network.map_vertices_to_range(G, [30*self.pixel_scale, 8*self.pixel_scale], 'degree').get_array() | |
748 | - | |
749 | - position = G.vertex_properties["pos"].get_2d_array(range(3)).T | |
750 | - #for p in range(position.shape[0]): | |
751 | - # position[p][0] = position[p][0] + self.clusters["a_position"][G.vertex_properties["clusters"][G.vertex(p)]][0] | |
752 | - # position[p][1] = position[p][1] + self.clusters["a_position"][G.vertex_properties["clusters"][G.vertex(p)]][1] | |
753 | - # position[p][2] = position[p][2] + self.clusters["a_position"][G.vertex_properties["clusters"][G.vertex(p)]][2] | |
754 | - #G.vertex_properties["pos"] = G.new_vertex_property("vector<double>", vals = position) | |
755 | - edges = G.get_edges(); | |
756 | - edges = edges[:, 0:2] | |
757 | - #width = nwt.Network.map_edges_to_range(G, [1*self.pixel_scale, 5*self.pixel_scale], 'volume').get_array() | |
758 | - #ecolor = G.edge_properties["RGBA"].get_2d_array(range(4)).T | |
759 | - | |
760 | - self.data = np.zeros(G.num_vertices(), dtype=[('a_position', np.float32, 3), | |
761 | - ('a_fg_color', np.float32, 4), | |
762 | - ('a_bg_color', np.float32, 4), | |
763 | - ('a_size', np.float32, 1), | |
764 | - ('a_linewidth', np.float32, 1), | |
765 | - ('a_unique_id', np.float32, 4), | |
766 | - ('a_selection', np.float32, 1), | |
767 | - ]) | |
768 | - | |
769 | - #self.edges = edges.astype(np.uint32) | |
770 | - self.data['a_position'] = position | |
771 | - #fg color is the color of the ring | |
772 | - self.data['a_fg_color'] = 0, 0, 0, 1 | |
773 | - self.data['a_bg_color'] = color | |
774 | - self.data['a_size'] = size | |
775 | - self.data['a_linewidth'] = 4.*self.pixel_scale | |
776 | - self.data['a_unique_id'] = self.gen_vertex_id(G) | |
777 | - self.data['a_selection'] = G.vertex_properties["selection"].get_array() | |
778 | - #self.data['a_graph_size'] = [bbu-bbl] | |
779 | - | |
780 | - self.program['u_graph_size'] = [bbu-bbl] | |
781 | - self.vbo = gloo.VertexBuffer(self.data) | |
782 | - self.gen_line_vbo(G) | |
783 | - if(self.subgraphs): | |
784 | - self.vbo_s = gloo.VertexBuffer(self.clusters) | |
785 | - self.index_s = gloo.IndexBuffer(self.edges_s) | |
786 | - #self.index = gloo.IndexBuffer(self.edges) | |
787 | - self.program_e.bind(self.vbo_line) | |
788 | - self.program.bind(self.vbo) | |
789 | - if(self.subgraphs): | |
790 | - #self.program_e_s.bind(self.vbo_s) | |
791 | - self.program_s.bind(self.vbo_s) | |
792 | - if DEBUG: | |
793 | - print(self.view) | |
794 | - self.update() | |
795 | - | |
918 | + self.G_cluster.vertex_properties["pos"][self.G_cluster.vertex(i)] = self.cluster_pos[i] | |
919 | + | |
920 | + | |
921 | + | |
796 | 922 | |
797 | 923 | """ |
798 | 924 | Function that generates the clusters for an unclustered graph |
... | ... | @@ -827,7 +953,7 @@ class GraphCanvas(scene.SceneCanvas): |
827 | 953 | #self.clusters['a_fg_color'] = 1., 1., 1., 0.0 |
828 | 954 | #self.clusters['a_linewidth'] = 4.*self.pixel_scale |
829 | 955 | |
830 | - G.vertex_properties["pos"] = nwt.gt.sfdp_layout(G, groups = G.vertex_properties["clusters"], pos = G.vertex_properties["pos"]) | |
956 | + G.vertex_properties["pos"] = nwt.gt.sfdp_layout(G, groups = G.vertex_properties["clusters"], pos = G.vertex_properties["pos"], C = 1.0, K = 10) | |
831 | 957 | temp = [] |
832 | 958 | temp_pos = [] |
833 | 959 | #Find the global total of the metric. |
... | ... | @@ -897,14 +1023,11 @@ class GraphCanvas(scene.SceneCanvas): |
897 | 1023 | print(self.clusters['a_outer_arc_length']) |
898 | 1024 | maximum = max(temp) |
899 | 1025 | minimum = min(temp) |
900 | - if len(temp) > 1: | |
901 | - temp = ((temp-minimum)/(maximum-minimum)*(60*self.pixel_scale)+20*self.pixel_scale) | |
902 | - else: | |
903 | - temp = [60*self.pixel_scale] | |
1026 | + temp = ((temp-minimum)/(maximum-minimum)*(60*self.pixel_scale)+20*self.pixel_scale)*2.0 | |
904 | 1027 | for i in range(num_clusters): |
905 | 1028 | index = i*4 |
906 | 1029 | index_t = i*2 |
907 | - p, v = self.gen_cluster_coords(temp_pos[i], temp[i]*2.0) | |
1030 | + p, v = self.gen_cluster_coords(temp_pos[i], temp[i]) | |
908 | 1031 | self.clusters['a_position'][index:index+4] = np.asarray(p, dtype=np.float32) |
909 | 1032 | self.clusters['a_value'][index:index+4] = np.asarray(v, dtype=np.float32) |
910 | 1033 | |
... | ... | @@ -913,6 +1036,7 @@ class GraphCanvas(scene.SceneCanvas): |
913 | 1036 | #self.edges_s[i][0:4] = np.asarray(range(index, index+4), dtype=np.uint32) |
914 | 1037 | #self.edges_s[i] |
915 | 1038 | self.cluster_pos = temp_pos |
1039 | + self.cluster_size = temp | |
916 | 1040 | #self.expand_based_on_clusters(G, self.n_c) |
917 | 1041 | G.clear_filters() |
918 | 1042 | # self.edges_s[1][0:4] = np.asarray(range(0, 0+4), dtype=np.uint32) |
... | ... | @@ -924,7 +1048,7 @@ class GraphCanvas(scene.SceneCanvas): |
924 | 1048 | # self.edges_s[0][5] = index+2 |
925 | 1049 | #self.clusters['a_size'] = temp |
926 | 1050 | self.gen_cluster_line_vbo(G) |
927 | - self.program_s['u_graph_size'] = [bbu-bbl] | |
1051 | + #self.program_s['u_graph_size'] = [bbu-bbl] | |
928 | 1052 | #if len(temp_e) > 0: |
929 | 1053 | # self.edges_s = np.unique(np.asarray(temp_e, np.uint32), axis=0) |
930 | 1054 | #else: |
... | ... | @@ -1003,7 +1127,7 @@ class GraphCanvas(scene.SceneCanvas): |
1003 | 1127 | self.data['a_selection'] = G.vertex_properties["selection"].get_array() |
1004 | 1128 | #self.data['a_graph_size'] = [bbu-bbl] |
1005 | 1129 | |
1006 | - self.program['u_graph_size'] = [bbu-bbl] | |
1130 | + #self.program['u_graph_size'] = [bbu-bbl] | |
1007 | 1131 | |
1008 | 1132 | self.vbo = gloo.VertexBuffer(self.data) |
1009 | 1133 | self.gen_line_vbo(G) |
... | ... | @@ -1033,6 +1157,7 @@ class GraphCanvas(scene.SceneCanvas): |
1033 | 1157 | Overloaded function that is called during every self.update() call |
1034 | 1158 | """ |
1035 | 1159 | def on_draw(self, event): |
1160 | + gloo.clear() | |
1036 | 1161 | clear(color='white', depth=True) |
1037 | 1162 | self.program_e.draw('triangles', indices=self.index) |
1038 | 1163 | self.program.draw('points') |
... | ... | @@ -1041,6 +1166,49 @@ class GraphCanvas(scene.SceneCanvas): |
1041 | 1166 | self.program_e_s.draw('triangles', indices=self.index_clusters_s) |
1042 | 1167 | self.program_s.draw('triangles', indices=self.index_s) |
1043 | 1168 | |
1169 | + | |
1170 | +# """ | |
1171 | +# A function to animate from one layout to another layout given a new G. | |
1172 | +# """ | |
1173 | + def animate(self, old_pos, new_pos): | |
1174 | + | |
1175 | +# old_pos = self.G.vertex_properties["pos"].get_2d_array(range(3)).T | |
1176 | +# new_pos = new_G.vertex_properties["pos"].get_2d_array(range(3)).T | |
1177 | + #we want to animate the move over 2 seconds. At 60 frames per second | |
1178 | + #we'd get 120 different positions along the transitional distance. | |
1179 | + self.new_pos = new_pos | |
1180 | + self.old_pos = old_pos | |
1181 | + self.slopes = np.zeros(old_pos.shape) | |
1182 | + for i in range(old_pos.shape[0]): | |
1183 | + self.slopes[i, 0] = (new_pos[i, 0] - old_pos[i, 0])/120.0 | |
1184 | + self.slopes[i, 1] = (new_pos[i, 1] - old_pos[i, 1])/120.0 | |
1185 | + | |
1186 | + #self.timer.start() | |
1187 | + #for i in range(120): | |
1188 | + #self.old_pos = np.add(old_pos, self.slopes) | |
1189 | + self.timer.start(iterations=120) | |
1190 | + #self.data['a_position'] = old_pos | |
1191 | + #self.gen_vertex_vbo_minimalist() | |
1192 | + #self.update() | |
1193 | +## self.gen_line_vbo(self.G) | |
1194 | +## self.program_e.bind(self.vbo_line) | |
1195 | +## self.program.bind(self.vbo) | |
1196 | +# self.update() | |
1197 | +# #self.program_e.draw('lines') | |
1198 | +# print(i) | |
1199 | + #self.timer.stop() | |
1200 | + | |
1201 | + #self.G = new_G | |
1202 | + #self.gen_vertex_vbo(self.G) | |
1203 | + #self.update() | |
1204 | + | |
1205 | +# def on_timer(self, event): | |
1206 | +# self.vbo = gloo.VertexBuffer(self.data) | |
1207 | +# #self.gen_line_vbo(self.G) | |
1208 | +# #self.program_e.bind(self.vbo_line) | |
1209 | +# self.program.bind(self.vbo) | |
1210 | +# self.update() | |
1211 | +# gloo.wrappers.flush() | |
1044 | 1212 | """ |
1045 | 1213 | Function performed during a mouse click (either right or left) |
1046 | 1214 | gets the unique id of the object drawn underneath the cursor |
... | ... | @@ -1356,7 +1524,7 @@ class GraphCanvas(scene.SceneCanvas): |
1356 | 1524 | |
1357 | 1525 | #get the filtered properties |
1358 | 1526 | g = nwt.gt.Graph(G, prune=True, directed=False) |
1359 | - p, v = self.gen_cluster_coords(pos, np.sum(g.vertex_properties['degree'].get_array())) | |
1527 | + p, v = self.gen_cluster_coords(pos, self.cluster_size[c_id]) | |
1360 | 1528 | self.clusters['a_position'][index:index+4] = np.asarray(p, dtype=np.float32) |
1361 | 1529 | self.clusters['a_value'][index:index+4] = np.asarray(v, dtype=np.float32) |
1362 | 1530 | G.clear_filters() | ... | ... |
GraphWidget.py
... | ... | @@ -10,6 +10,8 @@ from GraphCanvas import GraphCanvas |
10 | 10 | from pyqtgraph.Qt import QtCore, QtGui, QtWidgets |
11 | 11 | import network_dep as nwt |
12 | 12 | |
13 | +import numpy as np | |
14 | + | |
13 | 15 | DEBUG = False |
14 | 16 | |
15 | 17 | """ |
... | ... | @@ -69,6 +71,9 @@ class GraphWidget(QtGui.QWidget): |
69 | 71 | #EXP = menu.addAction('Export VTK') |
70 | 72 | #EXP_adv = menu.addAction('Export VTK Advanced') |
71 | 73 | NL = menu.addAction('New Layout') |
74 | + NSL = menu.addAction('New Spring-Onion Layout (sum)') | |
75 | + NSLMI = menu.addAction('New Spring-Onion Layout(max)') | |
76 | + EXPAND = menu.addAction('Expand') | |
72 | 77 | action = menu.exec_(event.native.globalPos()) |
73 | 78 | if DEBUG: |
74 | 79 | print(action) |
... | ... | @@ -108,11 +113,43 @@ class GraphWidget(QtGui.QWidget): |
108 | 113 | #self.cb.currentIndexChanged.connect(self.selection_change) |
109 | 114 | #self.cb.show() |
110 | 115 | if action == NL: |
111 | - self.canvas.G = nwt.Network.gen_new_fd_layout(self.canvas.G) | |
112 | - self.canvas.gen_vertex_vbo(self.canvas.G) | |
116 | + old_pos = self.canvas.G.vertex_properties["pos"].get_2d_array(range(3)).T | |
117 | + nG = nwt.Network.gen_new_fd_layout(self.canvas.G) | |
118 | + new_pos = nG.vertex_properties["pos"].get_2d_array(range(3)).T | |
119 | + self.canvas.animate(old_pos, new_pos) | |
120 | + | |
121 | + #self.canvas.gen_vertex_vbo(self.canvas.G) | |
113 | 122 | #self.canvas.set_data(self.canvas.G, self.canvas.bbl, self.canvas.bbu) |
123 | + #self.canvas.expand_clusters(self.canvas.G, self.canvas.n_c) | |
124 | + if action == NSL: | |
125 | + old_pos = self.canvas.G.vertex_properties["pos"].get_2d_array(range(3)).T | |
126 | + nG = nwt.Network.gen_spring_onion_layout(self.canvas.G, 'degree', 1.0, 1000, 0.01, 1.0) | |
127 | + new_pos = nG.vertex_properties["pos"].get_2d_array(range(3)).T | |
128 | + | |
129 | + self.canvas.animate(old_pos, new_pos) | |
130 | + #self.canvas.set_data(nG, self.canvas.bbl, self.canvas.bbu) | |
131 | + | |
132 | + #self.canvas.gen_vertex_vbo(self.canvas.G) | |
133 | + #self.canvas.expand_clusters(self.canvas.G, self.canvas.n_c) | |
134 | + if action == NSLMI: | |
135 | + old_pos = self.canvas.G.vertex_properties["pos"].get_2d_array(range(3)).T | |
136 | + nG = nwt.Network.gen_spring_onion_layout(self.canvas.G, 'degree', 1.0, 1000, 0.01, 1.0, False) | |
137 | + new_pos = nG.vertex_properties["pos"].get_2d_array(range(3)).T | |
138 | + | |
139 | + self.canvas.animate(old_pos, new_pos) | |
140 | + #self.canvas.set_data(nG, self.canvas.bbl, self.canvas.bbu) | |
141 | + #self.canvas.expand_clusters(self.canvas.G, self.canvas.n_c) | |
142 | + | |
143 | + #self.canvas.gen_vertex_vbo(self.canvas.G) | |
144 | + | |
145 | + if action == EXPAND: | |
146 | + #self.canvas.gen_vertex_vbo(self.canvas.G) | |
147 | + old_pos = self.canvas.G.vertex_properties["pos"].get_2d_array(range(3)).T | |
114 | 148 | self.canvas.expand_clusters(self.canvas.G, self.canvas.n_c) |
115 | - | |
149 | + new_pos = self.canvas.G.vertex_properties["pos"].get_2d_array(range(3)).T | |
150 | + #self.canvas.expand_clusters(self.canvas.G, self.canvas.n_c) | |
151 | + | |
152 | + self.canvas.animate(old_pos, new_pos) | |
116 | 153 | #self.canvas.size_vertices(self.canvas.G, 'degree_volume') |
117 | 154 | else: |
118 | 155 | if self.canvas.view[0][0] >= 0.0010: |
... | ... | @@ -144,6 +181,12 @@ class GraphWidget(QtGui.QWidget): |
144 | 181 | def on_mouse_double_click(self, event): |
145 | 182 | self.canvas.update_path(event) |
146 | 183 | self.select.emit(self.canvas.get_path()) |
184 | + old_pos = self.canvas.G.vertex_properties["pos"].get_2d_array(range(3)).T | |
185 | + nG = nwt.Network.gen_new_fd_layout(self.canvas.G) | |
186 | + # def animate(self, new_G): | |
187 | +# | |
188 | + new_pos = nG.vertex_properties["pos"].get_2d_array(range(3)).T | |
189 | + self.canvas.animate(old_pos, new_pos) | |
147 | 190 | |
148 | 191 | """ |
149 | 192 | Handles the mouse release event. | ... | ... |
GuiVisPy_tube.py
... | ... | @@ -39,7 +39,6 @@ top = QtGui.QWidget() |
39 | 39 | top.resize(900, 900) |
40 | 40 | |
41 | 41 | |
42 | -hist = pg.PlotWidget() | |
43 | 42 | #fibers = FiberView() |
44 | 43 | fibers = TubeWidget() |
45 | 44 | fibers.canvas.create_native() |
... | ... | @@ -66,15 +65,16 @@ top.setLayout(layout) |
66 | 65 | top.show() |
67 | 66 | |
68 | 67 | |
69 | -def draw_histogram(G, value): | |
70 | - vals = G.edge_properties[value].get_array() | |
71 | - y, x = np.histogram(vals,40) | |
72 | - hist.plot(x,y, stepMode=True, fillLevel=0, brush=(0,0,255,150)) | |
68 | +#def draw_histogram(G, value): | |
69 | +# vals = G.edge_properties[value].get_array() | |
70 | +# y, x = np.histogram(vals,40) | |
71 | +# hist.plot(x,y, stepMode=True, fillLevel=0, brush=(0,0,255,150)) | |
73 | 72 | |
74 | 73 | def load_nwt(filepath): |
75 | 74 | net = nwt.Network(filepath) |
76 | 75 | G = net.createFullGraph_gt() |
77 | 76 | G = net.filterDisconnected(G) |
77 | + #G = net.gen_spring_onion_layout(G, 'degree', 1.0, 1000, 0.01, 1.0) | |
78 | 78 | #G = net.filterFullGraph_gt(G, erode=True) |
79 | 79 | #G = net.filterFullGraph_gt(G, erode=True) |
80 | 80 | #G = net.gen_new_fd_layout(G) |
... | ... | @@ -104,7 +104,7 @@ center = (bbu-bbl)/2.0 |
104 | 104 | #fibers.opts['distance'] = 5 |
105 | 105 | # item = NodeItem(G) |
106 | 106 | # graph.addItem(item) |
107 | -draw_histogram(G, "length") | |
107 | +#draw_histogram(G, "length") | |
108 | 108 | graph.canvas.set_data(G, bbl, bbu) |
109 | 109 | fibers.canvas.set_data(G, bbl, bbu, 16) |
110 | 110 | #fibers.draw_all(G, center, fibers, graph, node_tex) | ... | ... |
TubeCanvas.py
... | ... | @@ -68,7 +68,7 @@ class TubeDraw(scene.SceneCanvas): |
68 | 68 | blend_func=('src_alpha', 'one_minus_src_alpha'), depth_func = ('lequal')) |
69 | 69 | #set_blend_color(color='black') |
70 | 70 | #set_state('translucent') |
71 | - self.program['u_LightPos'] = [0., 0., -1000.] | |
71 | + #self.program['u_LightPos'] = [0., 0., -1000.] | |
72 | 72 | #self.camera = self.central_widget.add_view() |
73 | 73 | #self.camera.camera = 'turntable' |
74 | 74 | self.down = False |
... | ... | @@ -107,7 +107,7 @@ class TubeDraw(scene.SceneCanvas): |
107 | 107 | self.projection = perspective(90.0, self.physical_size[0]/self.physical_size[1], 1.0, 1000.0) |
108 | 108 | #self.projection = perspective(90.0, 1.0, -1.0, 1.0) |
109 | 109 | self.program['u_model'] = self.model |
110 | - self.program['u_LightPos'] = [0., 0., 1000.] | |
110 | + #self.program['u_LightPos'] = [0., 0., 1000.] | |
111 | 111 | #self.program['u_view'] = self.view |
112 | 112 | self.program['u_projection'] = self.projection |
113 | 113 | self.program.bind(self.vbo) |
... | ... | @@ -481,8 +481,8 @@ class TubeDraw(scene.SceneCanvas): |
481 | 481 | #coord[1] = 0 |
482 | 482 | #coord2[1] = 0 |
483 | 483 | |
484 | - theta = (coord[0]-coord2[0])*360.0/2.0/np.pi | |
485 | - phi = (coord[1]-coord2[1])*360.0/2.0/np.pi | |
484 | + phi = (coord[0]-coord2[0])*360.0/2.0/np.pi | |
485 | + theta = (coord[1]-coord2[1])*360.0/2.0/np.pi | |
486 | 486 | if DEBUG: |
487 | 487 | print(theta*360.0/2.0/np.pi, -phi*360.0/2.0/np.pi) |
488 | 488 | self.camera = self.camera - self.translate |
... | ... | @@ -533,7 +533,7 @@ class TubeDraw(scene.SceneCanvas): |
533 | 533 | print("current position ", self.camera, " and up vector ", self.up) |
534 | 534 | self.program['u_eye'] = self.camera |
535 | 535 | self.program['u_up'] = self.up |
536 | - self.program['u_LightPos'] = [self.camera[0], self.camera[1], self.camera[2]] | |
536 | + #self.program['u_LightPos'] = [self.camera[0], self.camera[1], self.camera[2]] | |
537 | 537 | self.update() |
538 | 538 | |
539 | 539 | #reverts the mouse state during release. | ... | ... |
TubeWidget.py
graph_shaders.py
... | ... | @@ -14,14 +14,14 @@ vert = """ |
14 | 14 | #version 120 |
15 | 15 | // Uniforms |
16 | 16 | // ------------------------------------ |
17 | +uniform float u_size; | |
18 | +uniform float u_antialias; | |
17 | 19 | uniform mat4 u_model; |
18 | 20 | uniform mat4 u_view; |
19 | 21 | uniform mat4 u_projection; |
20 | -uniform float u_antialias; | |
21 | -uniform float u_size; | |
22 | +//uniform vec3 u_graph_size; | |
22 | 23 | uniform bool u_picking; |
23 | 24 | |
24 | -uniform vec3 u_graph_size; | |
25 | 25 | // Attributes |
26 | 26 | // ------------------------------------ |
27 | 27 | attribute vec3 a_position; |
... | ... | @@ -65,7 +65,6 @@ uniform mat4 u_model; |
65 | 65 | uniform mat4 u_view; |
66 | 66 | uniform mat4 u_projection; |
67 | 67 | uniform float u_antialias; |
68 | -uniform float u_size; | |
69 | 68 | uniform bool u_picking; |
70 | 69 | |
71 | 70 | // Varyings |
... | ... | @@ -192,8 +191,6 @@ attribute vec3 a_position; |
192 | 191 | attribute vec2 a_normal; |
193 | 192 | attribute vec4 a_fg_color; |
194 | 193 | attribute float a_linewidth; |
195 | -//attribute vec4 a_unique_id; | |
196 | -//attribute vec4 l_color; | |
197 | 194 | |
198 | 195 | // Varyings |
199 | 196 | // ------------------------------------ |
... | ... | @@ -253,4 +250,4 @@ float new_alpha(float zoom_level) |
253 | 250 | return val; |
254 | 251 | |
255 | 252 | } |
256 | -""" | |
257 | 253 | \ No newline at end of file |
254 | +""" | ... | ... |
network_dep.py
... | ... | @@ -1115,9 +1115,163 @@ class Network: |
1115 | 1115 | G_0.clear_filters() |
1116 | 1116 | |
1117 | 1117 | return graph |
1118 | + | |
1119 | + ''' | |
1120 | + Generates a layout based a 3 neighbors spring system. | |
1121 | + Vertices within 1 edge, 2 edges and 3 edges act upon one another based on | |
1122 | + Hooke's law. 1e springs are the stronges and strength decreases as edges get further away | |
1123 | + | |
1124 | + ''' | |
1125 | + def gen_spring_onion_layout(G, v_property, k, n_steps, time_step, min_distance, Sum=True): | |
1126 | + start = time.time() | |
1127 | + | |
1128 | + one_neighbors = G.new_vertex_property("vector<int>") | |
1129 | + o1_n = [] | |
1130 | + two_neighbors = G.new_vertex_property("vector<int>") | |
1131 | + o2_n = [] | |
1132 | + three_neighbors = G.new_vertex_property("vector<int>") | |
1133 | + o3_n = [] | |
1134 | + #generate the map of 1, 2 and 3 neighborhood vertices. | |
1135 | + for v in G.vertices(): | |
1136 | + one_n = [] | |
1137 | + two_n = [] | |
1138 | + three_n = [] | |
1139 | + #find all 1 neighbors | |
1140 | + for i in v.all_neighbors(): | |
1141 | + one_n.append(int(i)) | |
1142 | + if(len(one_n) == 0): | |
1143 | + print("WTF") | |
1144 | + #find all 2 neighbors | |
1145 | + for i in one_n: | |
1146 | + for j in G.vertex(i).all_neighbors(): | |
1147 | + if(int(j) not in one_n): | |
1148 | + two_n.append(int(j)) | |
1149 | + | |
1150 | + #find all 3 neighbors | |
1151 | + for i in two_n: | |
1152 | + for j in G.vertex(i).all_neighbors(): | |
1153 | + if(int(j) not in one_n and int(j) not in two_n): | |
1154 | + three_n.append(int(j)) | |
1118 | 1155 | |
1156 | + #we do not keep ones that have already counted, i.e. a vertex | |
1157 | + #appears in all 3 arrays only once. | |
1158 | + #it's ok to add self to any array because the distance -k(x=0) = 0 | |
1159 | + one_neighbors[v] = np.asarray(one_n) | |
1160 | + o1_n.append(np.asarray(one_n)) | |
1161 | + two_neighbors[v] = np.asarray(two_n) | |
1162 | + o2_n.append(np.asarray(two_n)) | |
1163 | + three_neighbors[v] = np.asarray(three_n) | |
1164 | + o3_n.append(np.asarray(three_n)) | |
1119 | 1165 | |
1120 | - | |
1166 | + print("generating neighborhoods: ", time.time() - start) | |
1167 | + start = time.time() | |
1168 | + G.vertex_properties["1_neighbor"] = one_neighbors | |
1169 | + G.vertex_properties["2_neighbor"] = two_neighbors | |
1170 | + G.vertex_properties["3_neighbor"] = three_neighbors | |
1171 | + | |
1172 | + cooling = 1.0 | |
1173 | + cooling_step = cooling/n_steps | |
1174 | + | |
1175 | + | |
1176 | +# #get points of the centers of every cluster | |
1177 | +# #generate voronoi region and plot it. | |
1178 | +# fig, ax = plt.subplots(2, 1, sharex='col', sharey='row') | |
1179 | +# fig.tight_layout() | |
1180 | +# grid = plt.GridSpec(2,1) | |
1181 | +# grid.update(wspace=0.025, hspace=0.2) | |
1182 | +# ax[0].axis('off') | |
1183 | +# ax[1].axis('off') | |
1184 | +# | |
1185 | +# | |
1186 | +# before = fig.add_subplot(grid[0]) | |
1187 | +# after = fig.add_subplot(grid[1]) | |
1188 | +# pts = G.vertex_properties["pos"].get_2d_array(range(2)).T | |
1189 | +# before.scatter(pts[:,0], pts[:, 1], marker="*") | |
1190 | +# | |
1191 | +# #plot the connections of the top level graph | |
1192 | +# for e in G.edges(): | |
1193 | +# coord = G.vertex_properties["pos"][e.source()] | |
1194 | +# coord2 = G.vertex_properties["pos"][e.target()] | |
1195 | +# x = [coord[0], coord2[0]] | |
1196 | +# y = [coord[1], coord2[1]] | |
1197 | +# before.plot(x, y, 'go--', linewidth=1, markersize=1) | |
1198 | +# | |
1199 | +# #plot the connections of the top level graph | |
1200 | +# for e in G.edges(): | |
1201 | +# coord = G.vertex_properties["pos"][e.source()] | |
1202 | +# coord2 = G.vertex_properties["pos"][e.target()] | |
1203 | +# x = [coord[0], coord2[0]] | |
1204 | +# y = [coord[1], coord2[1]] | |
1205 | +# before.plot(x, y, 'go--', linewidth=1, markersize=1) | |
1206 | + | |
1207 | + velocities = np.zeros([G.num_vertices(), 3]) | |
1208 | + print("setting neighborhoods: ", time.time() - start) | |
1209 | + start = time.time() | |
1210 | + | |
1211 | + pos = G.vertex_properties["pos"].get_2d_array(range(3)).T | |
1212 | + weight = G.vertex_properties[v_property].get_array().T | |
1213 | + | |
1214 | + for n in range(n_steps+1): | |
1215 | + forces = np.zeros([G.num_vertices(), 3]) | |
1216 | + #pos = G.vertex_properties["pos"].get_2d_array(range(2)).T | |
1217 | + if Sum: | |
1218 | + for v in G.vertices(): | |
1219 | + for i in o1_n[int(v)]: | |
1220 | + x = pos[int(i), :] - pos[int(v), :] | |
1221 | + forces[int(v), 0] += -k*(x[0]) | |
1222 | + forces[int(v), 1] += -k*(x[1]) | |
1223 | + for i in o2_n[int(v)]: | |
1224 | + x = pos[int(i)] - pos[int(v)] | |
1225 | + forces[int(v), 0] += -k*(x[0])/2.0 | |
1226 | + forces[int(v), 1] += -k*(x[1])/2.0 | |
1227 | + for i in o3_n[int(v)]: | |
1228 | + x = pos[int(i)] - pos[int(v)] | |
1229 | + forces[int(v), 0] += -k*(x[0])/4.0 | |
1230 | + forces[int(v), 1] += -k*(x[1])/4.0 | |
1231 | + else: | |
1232 | + for v in G.vertices(): | |
1233 | + for i in o3_n[int(v)]: | |
1234 | + x = pos[int(i)] - pos[int(v)] | |
1235 | + forces[int(v), 0] = -k*(x[0])/4.0 | |
1236 | + forces[int(v), 1] = -k*(x[1])/4.0 | |
1237 | + | |
1238 | + forces[:, 0] = forces[:, 0]/weight[:] | |
1239 | + forces[:, 1] = forces[:, 1]/weight[:] | |
1240 | +# if n < 1: | |
1241 | +# velocities = forces * time_step*G.num_vertices() | |
1242 | +# else: | |
1243 | +# pos += velocities * time_step | |
1244 | +# velocities = forces * time_step * cooling | |
1245 | +# cooling -= cooling_step | |
1246 | +# | |
1247 | + | |
1248 | + for v in G.vertices(): | |
1249 | + if n < 1: | |
1250 | + velocities = forces * time_step | |
1251 | + #G.vertex_properties["pos"][v] = pos[int(v), :] + forces[int(v), :] * time_step | |
1252 | + else: | |
1253 | + pos[int(v), :] = pos[int(v), :] + velocities[int(v), :] * time_step | |
1254 | + velocities = forces * time_step * cooling | |
1255 | + cooling -= cooling_step | |
1256 | + | |
1257 | + G.vertex_properties["pos"] = G.new_vertex_property("vector<double>", vals = pos) | |
1258 | + print("calculating new positions: ", time.time() - start) | |
1259 | +# pts = G.vertex_properties["pos"].get_2d_array(range(2)).T | |
1260 | +# after.scatter(pts[:,0], pts[:, 1], marker="*") | |
1261 | +# | |
1262 | +# #plot the connections of the top level graph | |
1263 | +# for e in G.edges(): | |
1264 | +# coord = G.vertex_properties["pos"][e.source()] | |
1265 | +# coord2 = G.vertex_properties["pos"][e.target()] | |
1266 | +# x = [coord[0], coord2[0]] | |
1267 | +# y = [coord[1], coord2[1]] | |
1268 | +# after.plot(x, y, 'go--', linewidth=1, markersize=1) | |
1269 | +# | |
1270 | +# plt.show() | |
1271 | + return G | |
1272 | + | |
1273 | + | |
1274 | + | |
1121 | 1275 | |
1122 | 1276 | ''' |
1123 | 1277 | Creates a graph from a list of nodes and a list of edges |
... | ... | @@ -1537,8 +1691,9 @@ class Network: |
1537 | 1691 | |
1538 | 1692 | |
1539 | 1693 | def gen_new_fd_layout(G): |
1540 | - pos = gt.sfdp_layout(G, C = 1.0, K = 10) | |
1541 | - G.vertex_properties["pos"] = pos | |
1694 | + G.vertex_properties["pos"] = gt.sfdp_layout(G, groups = G.vertex_properties["clusters"], pos = G.vertex_properties["pos"], C = 1.0, K = 10) | |
1695 | + #pos = gt.sfdp_layout(G, C = 1.0, K = 10) | |
1696 | + #G.vertex_properties["pos"] = pos | |
1542 | 1697 | return G |
1543 | 1698 | |
1544 | 1699 | def map_edges_to_range(G, rng, propertymap): |
... | ... | @@ -1668,7 +1823,7 @@ class Network: |
1668 | 1823 | G.vertex_properties["partition"] = G.new_vertex_property("vector<boolean>", array_cluster_bel) |
1669 | 1824 | G.edge_properties["partition"] = G.new_edge_property("vector<boolean>", array_ecluster_bel) |
1670 | 1825 | j = 0 |
1671 | - gt.graph_draw(G, pos = gt.sfdp_layout(G), output="Graph_full.pdf") | |
1826 | + #gt.graph_draw(G, pos = gt.sfdp_layout(G), output="Graph_full.pdf") | |
1672 | 1827 | for i in range(c): |
1673 | 1828 | TFv = G.new_vertex_property("bool", vals=array_cluster_bel[i,:]) |
1674 | 1829 | TFe = G.new_edge_property("bool", vals=array_ecluster_bel[i,:]) | ... | ... |
subgraph_shaders.py
... | ... | @@ -14,7 +14,7 @@ vert_s = """ |
14 | 14 | uniform mat4 u_model; |
15 | 15 | uniform mat4 u_view; |
16 | 16 | uniform mat4 u_projection; |
17 | -uniform vec3 u_graph_size; | |
17 | +//uniform vec3 u_graph_size; | |
18 | 18 | uniform bool u_picking; |
19 | 19 | // Attributes |
20 | 20 | // ------------------------------------ |
... | ... | @@ -214,8 +214,6 @@ attribute vec3 a_position; |
214 | 214 | attribute vec2 a_normal; |
215 | 215 | attribute vec4 a_fg_color; |
216 | 216 | attribute float a_linewidth; |
217 | -//attribute vec4 a_unique_id; | |
218 | -//attribute vec4 l_color; | |
219 | 217 | |
220 | 218 | // Varyings |
221 | 219 | // ------------------------------------ |
... | ... | @@ -273,4 +271,4 @@ float new_alpha(float zoom_level) |
273 | 271 | } |
274 | 272 | return val; |
275 | 273 | } |
276 | -""" | |
277 | 274 | \ No newline at end of file |
275 | +""" | ... | ... |
tube_shaders.py
... | ... | @@ -11,7 +11,6 @@ VERT_SHADER = """ |
11 | 11 | // Uniforms |
12 | 12 | // ------------------------------------ |
13 | 13 | uniform vec4 u_bb[26]; |
14 | -uniform vec3 u_LightPost; | |
15 | 14 | uniform mat4 u_model; |
16 | 15 | //uniform mat4 u_view; |
17 | 16 | uniform mat4 u_projection; |
... | ... | @@ -53,8 +52,8 @@ void main (void) { |
53 | 52 | v_position = vec3(MV*vec4(a_position, 1.0)); |
54 | 53 | vt_position = vec3(a_position); |
55 | 54 | v_fg_color = a_fg_color; |
56 | - v_selection = a_selection; | |
57 | 55 | gl_Position = MVP * vec4(a_position, 1.0); |
56 | + v_selection = a_selection; | |
58 | 57 | } |
59 | 58 | |
60 | 59 | mat4 make_view(vec3 eye, vec3 target, vec3 up) |
... | ... | @@ -87,7 +86,6 @@ FRAG_SHADER = """ |
87 | 86 | // Uniforms |
88 | 87 | // ------------------------------------ |
89 | 88 | uniform vec3 u_bb[26]; |
90 | -uniform vec3 u_LightPos; | |
91 | 89 | uniform mat4 u_model; |
92 | 90 | //uniform mat4 u_view; |
93 | 91 | uniform mat4 u_projection; |
... | ... | @@ -198,7 +196,7 @@ float new_alpha() |
198 | 196 | float bin_alpha(float alpha) |
199 | 197 | { |
200 | 198 | |
201 | - | |
199 | + | |
202 | 200 | if(alpha > 0.8) |
203 | 201 | return 0.0; |
204 | 202 | else if(alpha > 0.6) |
... | ... | @@ -211,7 +209,7 @@ float bin_alpha(float alpha) |
211 | 209 | return 1.0; |
212 | 210 | else |
213 | 211 | return 1.0; |
214 | - | |
212 | + | |
215 | 213 | // if(alpha > 0.9) |
216 | 214 | // return 0.0; |
217 | 215 | // else if(alpha > 0.8) | ... | ... |
voronoi_test.py
... | ... | @@ -31,32 +31,50 @@ import network_dep as nwt |
31 | 31 | class Polygon_mass: |
32 | 32 | def __init__(self, G): |
33 | 33 | self.G = G |
34 | + print(nwt.gt.graph_tool.topology.is_planar(G)) | |
34 | 35 | self.get_aabb() |
35 | 36 | self.gen_polygon() |
36 | 37 | self.torque = [] |
38 | + self.forces_r = np.zeros(2) | |
39 | + self.forces_a = np.zeros(2) | |
37 | 40 | self.vel = 0.0 |
38 | 41 | self.aa = 0.0 |
42 | + self.degree = 0 | |
39 | 43 | |
40 | 44 | |
41 | 45 | def clear_torques(self): |
42 | 46 | self.torque = [] |
43 | 47 | |
48 | + def clear_forces(self): | |
49 | + self.forces_r = np.zeros(2) | |
50 | + self.forces_a = np.zeros(2) | |
51 | + | |
52 | + def set_degree(self, degree): | |
53 | + self.degree = degree | |
54 | + | |
44 | 55 | def add_torque(self, p, f): |
45 | 56 | #direction of the torque = cross of (r, f) |
46 | 57 | #magnitude = ||r||*||f||*sin(theta) |
47 | 58 | #r = level arm vector |
48 | 59 | d = self.CoM - p |
49 | - r = np.linalg.norm(self.CoM - p) | |
50 | - theta = math.acos(np.dot(d, f)/np.dot(d, d)/np.dot(f, f)) | |
51 | - torque = math.sin(theta) * np.sqrt(f[0]*f[0]+f[1]*f[1]) * np.sqrt(r[0]*r[0]+r[1]*r[1]) | |
60 | + #r = np.linalg.norm(self.CoM - p) | |
61 | + value = np.dot(d, f)/np.dot(d, d)/np.dot(f, f) | |
62 | + if value < 1.0 and value > -1.0: | |
63 | + theta = math.acos(value) | |
64 | + torque = math.sin(theta) * np.sqrt(f[0]*f[0]+f[1]*f[1]) * np.sqrt(d[0]*d[0]+d[1]*d[1]) | |
65 | + else: | |
66 | + #print("value = ", value) | |
67 | + torque = 0.0 | |
68 | + | |
52 | 69 | #if < 0 then clockwise, else counter |
53 | - direction = np.cross(r, f) | |
70 | + direction = np.cross(d, f) | |
54 | 71 | if direction < 0: |
55 | - self.torque.append([torque, "clockwise"]) | |
72 | + self.torque.append([torque, f, p, "counterclock"]) | |
56 | 73 | else: |
57 | - self.torque.append([torque, "counterclock"]) | |
74 | + self.torque.append([torque, f, p, "clockwise"]) | |
75 | + | |
58 | 76 | |
59 | - def calculate_moment(self): | |
77 | + def calculate_moment(self, use_graph=False): | |
60 | 78 | |
61 | 79 | #returns the area of a triangle defined by two points |
62 | 80 | def area(t): |
... | ... | @@ -65,6 +83,7 @@ class Polygon_mass: |
65 | 83 | |
66 | 84 | def center(t): |
67 | 85 | output = np.asarray([(t[0,0]+t[1,0]+t[2,0])/3.0, (t[0,1]+t[1,1]+t[2,1])/3.0]) |
86 | + return output | |
68 | 87 | |
69 | 88 | segs = [] |
70 | 89 | pts = np.asarray(self.polygon.exterior.xy).T |
... | ... | @@ -72,9 +91,19 @@ class Polygon_mass: |
72 | 91 | for k in range(pts.shape[0]-1): |
73 | 92 | segs.append([k, k+1]) |
74 | 93 | segs.append([pts.shape[0]-1, 0]) |
94 | + if use_graph: | |
95 | + points = self.G.vertex_properties["pos"].get_2d_array(range(2)).T | |
96 | + segs2 = [] | |
97 | + n_pts = pts.shape[0] | |
98 | + for e in self.G.edges(): | |
99 | + segs2.append([int(e.source())+n_pts, int(e.target())+n_pts]) | |
100 | + pts = np.concatenate((pts, points)) | |
101 | + segs = segs + segs2 | |
75 | 102 | mesh = dict(vertices=pts, segments=segs) |
76 | 103 | #print(self.polygon.area()) |
77 | - tri = triangulate(mesh, 'pq20D') | |
104 | + tri = triangulate(mesh, 'pq20Ds') | |
105 | + self.mesh = mesh | |
106 | + self.tri = tri | |
78 | 107 | moment = 0.0 |
79 | 108 | #NEED TO ADD MASS maybe? |
80 | 109 | for i in range(tri['triangles'].shape[0]): |
... | ... | @@ -84,59 +113,75 @@ class Polygon_mass: |
84 | 113 | Moi = A+A*np.linalg.norm(C-self.CoM)**2 |
85 | 114 | moment += Moi |
86 | 115 | |
87 | - self.MoI = moment | |
116 | + self.MoI = abs(math.log(moment)) | |
117 | + #self.MoI = 10 | |
118 | + print(self.MoI) | |
88 | 119 | # triangle_plot(plt.gca(), **tri) |
89 | 120 | # plt.gca().set_title(str(self.polygon.area)) |
90 | - | |
121 | + | |
122 | + def translate(self, step): | |
123 | + d = self.forces_a + self.forces_r | |
124 | + #print(self.forces_a, self.forces_r) | |
125 | + d0 = step*d | |
126 | + self.CoM = self.CoM + d0 | |
127 | + pos = self.G.vertex_properties["pos"].get_2d_array(range(2)).T | |
128 | + pos = pos + d0 | |
129 | + self.G.vertex_properties["pos"] = self.G.new_vertex_property("vector<double>", vals = pos) | |
130 | + | |
91 | 131 | def rotate(self, phi, direction = "counterclock"): |
92 | 132 | if("counterclock"): |
93 | - for v in self.G.vertices: | |
94 | - p = self.G.vertex_properties["pos"][v] | |
95 | - p[0] = self.CoM[0] + math.cos(phi) * (self.CoM[0] - p[0]) - math.sin(phi) * (p[1] - self.CoM[1]) | |
96 | - p[1] = self.CoM[1] + math.sin(phi) * (self.CoM[0] - p[0]) + math.cos(phi) * (p[1] - self.CoM[1]) | |
97 | - self.G.vertex_properties["pos"][v] = p | |
133 | + for v in self.G.vertices(): | |
134 | + p_prime = copy.deepcopy(self.G.vertex_properties["pos"][v]) | |
135 | + p = copy.deepcopy(self.G.vertex_properties["pos"][v]) | |
136 | + p_prime[0] = self.CoM[0] + math.cos(phi) * (p[0] - self.CoM[0]) - math.sin(phi) * (p[1] - self.CoM[1]) | |
137 | + p_prime[1] = self.CoM[1] + math.sin(phi) * (p[0] - self.CoM[0]) + math.cos(phi) * (p[1] - self.CoM[1]) | |
138 | + self.G.vertex_properties["pos"][v] = p_prime | |
139 | + #rotate points in mesh | |
140 | + points = copy.deepcopy(self.mesh['vertices']) | |
141 | + for v in range(points.shape[0]): | |
142 | + points[v][0] = self.CoM[0] + math.cos(phi) * (self.mesh['vertices'][v][0] - self.CoM[0]) - math.sin(phi) * (self.mesh['vertices'][v][1] - self.CoM[1]) | |
143 | + points[v][1] = self.CoM[1] + math.sin(phi) * (self.mesh['vertices'][v][0] - self.CoM[0]) + math.cos(phi) * (self.mesh['vertices'][v][1] - self.CoM[1]) | |
144 | + self.mesh['vertices'] = points | |
98 | 145 | else: |
99 | - for v in self.G.vertices: | |
100 | - p = self.G.vertex_properties["pos"][v] | |
101 | - p[0] = self.CoM[0] + math.cos(phi) * (self.CoM[0] + p[0]) + math.sin(phi) * (p[1] - self.CoM[1]) | |
102 | - p[1] = self.CoM[1] + math.sin(phi) * (self.CoM[0] + p[0]) - math.cos(phi) * (p[1] - self.CoM[1]) | |
103 | - self.G.vertex_properties["pos"][v] = p | |
146 | + for v in self.G.vertices(): | |
147 | + p_prime = copy.deepcopy(self.G.vertex_properties["pos"][v]) | |
148 | + p = copy.deepcopy(self.G.vertex_properties["pos"][v]) | |
149 | + p_prime[0] = self.CoM[0] + math.cos(phi) * (p[0] - self.CoM[0]) + math.sin(phi) * (p[1] - self.CoM[1]) | |
150 | + p_prime[1] = self.CoM[1] - math.sin(phi) * (p[0] - self.CoM[0]) + math.cos(phi) * (p[1] - self.CoM[1]) | |
151 | + self.G.vertex_properties["pos"][v] = p_prime | |
152 | + #rotate points in mesh | |
153 | + points = copy.deepcopy(self.mesh['vertices']) | |
154 | + for v in range(points.shape[0]): | |
155 | + points[v][0] = self.CoM[0] + math.cos(phi) * (self.mesh['vertices'][v][0] - self.CoM[0]) + math.sin(phi) * (self.mesh['vertices'][v][1] - self.CoM[1]) | |
156 | + points[v][1] = self.CoM[1] - math.sin(phi) * (self.mesh['vertices'][v][0] - self.CoM[0]) + math.cos(phi) * (self.mesh['vertices'][v][1] - self.CoM[1]) | |
157 | + self.mesh['vertices'] = points | |
104 | 158 | |
159 | + | |
105 | 160 | |
106 | 161 | |
107 | 162 | def plot_graph(self, D, x, y): |
108 | 163 | plt.figure() |
109 | 164 | ext = [self.a[0], self.b[0], self.a[1], self.b[1]] |
110 | - plt.imshow(D, origin = 'lower', extent=ext) | |
165 | + #plt.imshow(D, origin = 'lower', extent=ext) | |
111 | 166 | p = self.G.vertex_properties["pos"].get_2d_array(range(2)).T |
112 | 167 | plt.scatter(p[:,0], p[:,1], color='r') |
113 | 168 | plt.scatter(self.CoM[0], self.CoM[1], marker='*') |
114 | 169 | |
170 | + #mesh = dict(vertices=pts, segments=segs) | |
171 | + #print(self.polygon.area()) | |
172 | + #tri = triangulate(mesh, 'pq20Ds') | |
173 | + triangle_plot(plt.gca(), **self.mesh) | |
115 | 174 | |
116 | - segs = [] | |
117 | - pts = np.asarray(self.polygon.exterior.xy).T | |
118 | - pts = pts[:-1, :] | |
119 | - for k in range(pts.shape[0]-1): | |
120 | - segs.append([k, k+1]) | |
121 | - segs.append([pts.shape[0]-1, 0]) | |
122 | - points = self.G.vertex_properties["pos"].get_2d_array(range(2)).T | |
123 | - segs2 = [] | |
124 | - n_pts = pts.shape[0] | |
125 | - for e in self.G.edges(): | |
126 | - segs2.append([int(e.source())+n_pts, int(e.target())+n_pts]) | |
127 | - | |
175 | + #plot polygon | |
176 | + #plt.plot(*self.polygon.exterior.xy, color = 'r') | |
128 | 177 | |
129 | 178 | |
130 | - pts = np.concatenate((pts, points)) | |
131 | - segs = segs + segs2 | |
132 | - mesh = dict(vertices=pts, segments=segs) | |
133 | - #print(self.polygon.area()) | |
134 | - # tri = triangulate(mesh, 'pq20D') | |
135 | - triangle_plot(plt.gca(), **mesh) | |
136 | - for i in range(len(segs)): | |
137 | - plt.plot((pts[segs[i][0]][0], pts[segs[i][0]][1]), (pts[segs[i][1]][0], pts[segs[i][1]][1]), color='b') | |
179 | +# for i in range(len(segs)): | |
180 | +# plt.plot((pts[segs[i][0]][0], pts[segs[i][1]][0]), (pts[segs[i][0]][1], pts[segs[i][1]][1]), color='b') | |
138 | 181 | plt.gca().set_title(str(self.polygon.area)) |
139 | 182 | |
183 | + for e in self.torque: | |
184 | + plt.quiver(e[2][0], e[2][1], e[1][0], e[1][1], color='r') | |
140 | 185 | #tri = Delaunay(np.asarray(self.polygon.exterior.coords.xy).T) |
141 | 186 | #tri = triangulate(mesh, 'pq20a' + str(self.polygon.area/100.0)+'D') |
142 | 187 | #delaunay_plot_2d(tri) |
... | ... | @@ -159,8 +204,7 @@ class Polygon_mass: |
159 | 204 | # Y = [coord[1], coord2[1]] |
160 | 205 | # #all_plots.plot(x, y, 'go--', linewidth=1, markersize=1) |
161 | 206 | # plt.plot(X, Y, 'go--', linewidth=1, markersize=1) |
162 | -# | |
163 | - plt.plot(*self.polygon.exterior.xy, color = 'r') | |
207 | +# | |
164 | 208 | plt.show() |
165 | 209 | |
166 | 210 | def get_aabb(self): |
... | ... | @@ -200,7 +244,7 @@ class Polygon_mass: |
200 | 244 | contour[: ,1] = Y(cn[0][:, 0]) |
201 | 245 | self.polygon = Polygon(contour) |
202 | 246 | self.CoM = self.centroid_com(contour) |
203 | - | |
247 | + self.calculate_moment(True) | |
204 | 248 | #cn = plt.contour(x, y, D, levels = [level]) |
205 | 249 | #cn = plt.contour(x, y, D, levels = [level]) |
206 | 250 | # plt.close() |
... | ... | @@ -215,12 +259,11 @@ class Polygon_mass: |
215 | 259 | # #nlist = c.trace(level, level, 0) |
216 | 260 | # #segs = nlist[:len(nlist)//2] |
217 | 261 | #self.polygon = Polygon(pts) |
218 | - self.plot_graph(D, x, y) | |
262 | + #self.plot_graph(D, x, y) | |
219 | 263 | |
220 | 264 | |
221 | 265 | |
222 | 266 | def distancefield(self): |
223 | - | |
224 | 267 | #generate a meshgrid of the appropriate size and resolution to surround the network |
225 | 268 | #get the space occupied by the network |
226 | 269 | lower = self.a |
... | ... | @@ -271,6 +314,9 @@ class Polygon_mass: |
271 | 314 | # R = (200, 200, 200) |
272 | 315 | |
273 | 316 | D, I = tree.query(Q) |
317 | + self.D = D | |
318 | + self.x = x | |
319 | + self.y = y | |
274 | 320 | |
275 | 321 | return D, x, y |
276 | 322 | |
... | ... | @@ -301,23 +347,66 @@ def get_torques(G, masses): |
301 | 347 | #if the source and target cluster is not equal to each other |
302 | 348 | #add an inter subgraph edge. |
303 | 349 | if(G.vertex_properties["clusters"][e.source()] != G.vertex_properties["clusters"][e.target()]): |
304 | - pf0 = G.vertex_properties["pos"][e.target()].get_2D_array(range(2)) | |
305 | - pf1 = G.vertex_properties["pos"][e.source()].get_2D_array(range(2)) | |
350 | + #index of the cluster | |
351 | + t0 = G.vertex_properties["clusters"][e.target()] | |
352 | + t1 = G.vertex_properties["clusters"][e.source()] | |
353 | + #index of the vertex outside of the subgraph | |
354 | + v0_index = G.vertex_properties["idx"][e.target()] | |
355 | + v1_index = G.vertex_properties["idx"][e.source()] | |
356 | + #location of torque arm in the subgraph | |
357 | + p0 = masses[t0].G.vertex_properties["pos"][np.argwhere(masses[t0].G.vertex_properties["idx"].get_array() == v0_index)] | |
358 | + p1 = masses[t1].G.vertex_properties["pos"][np.argwhere(masses[t1].G.vertex_properties["idx"].get_array() == v1_index)] | |
306 | 359 | |
307 | - t0 = G.vertex_properties["clusters"][e.source()] | |
308 | - t1 = G.vertex_properties["clusters"][e.target()] | |
360 | + f0 = np.subtract(p0, p1) | |
361 | + f1 = np.subtract(p1, p0) | |
362 | + masses[t0].add_torque(p0, f1) | |
363 | + masses[t1].add_torque(p1, f0) | |
364 | +''' | |
365 | + c1 scales the attractive force before log. | |
366 | + c2 scales the attractive force inside log. | |
367 | + c3 scales the repulsive force. | |
368 | +''' | |
369 | +def get_forces(G, masses, c1 = 50.0, c2 = 1.0, c3 = 1.0): | |
370 | + for i in range(len(masses)): | |
371 | + masses[i].clear_forces() | |
372 | + f_total = np.zeros(2) | |
373 | + for j in range(len(masses)): | |
374 | + if i != j: | |
375 | + f0 = np.subtract(masses[i].CoM, masses[j].CoM) | |
376 | + f1 = np.power(f0, 3.0) | |
377 | + f1[0] = c3/f1[0]*np.sign(f0[0]) | |
378 | + f1[1] = c3/f1[1]*np.sign(f0[1]) | |
379 | + f_total = np.add(f_total, f1) | |
380 | + masses[i].forces_r = f_total | |
309 | 381 | |
310 | - v0_index = G.vertex_properties["idx"][e.source()] | |
311 | - v1_index = G.vertex_properties["idx"][e.target()] | |
382 | + for e in G.edges(): | |
383 | + #if the source and target cluster is not equal to each other | |
384 | + #add an inter subgraph edge. | |
385 | + if(G.vertex_properties["clusters"][e.source()] != G.vertex_properties["clusters"][e.target()]): | |
386 | + #index of the cluster | |
387 | + t0 = G.vertex_properties["clusters"][e.target()] | |
388 | + t1 = G.vertex_properties["clusters"][e.source()] | |
389 | + #index of the vertex outside of the subgraph | |
390 | + v0_index = G.vertex_properties["idx"][e.target()] | |
391 | + v1_index = G.vertex_properties["idx"][e.source()] | |
392 | + #location of torque arm in the subgraph | |
393 | + p0 = masses[t0].G.vertex_properties["pos"][np.argwhere(masses[t0].G.vertex_properties["idx"].get_array() == v0_index)] | |
394 | + p1 = masses[t1].G.vertex_properties["pos"][np.argwhere(masses[t1].G.vertex_properties["idx"].get_array() == v1_index)] | |
312 | 395 | |
313 | - p0 = masses[t0].G.vertex_properties["pos"][masses[t0].G.vertex(v0_index)].get_2D_array(range(2)) | |
314 | - p1 = masses[t1].G.vertex_properties["pos"][masses[t1].G.vertex(v1_index)].get_2D_array(range(2)) | |
396 | + f0 = np.subtract(p1, p0) | |
397 | + f0_1 = abs(f0) | |
398 | + f0_1 = c1*np.log(f0_1/c2)/masses[t0].degree | |
399 | + f0_1 = f0_1*np.sign(f0) | |
400 | + f1 = np.subtract(p0, p1) | |
401 | + f1_1 = abs(f1) | |
402 | + f1_1 = c1*np.log(f1_1/c2)/masses[t1].degree | |
403 | + f1_1 = f1_1*np.sign(f1) | |
404 | + masses[t0].forces_a = np.add(masses[t0].forces_a, f1_1) | |
405 | + masses[t1].forces_a = np.add(masses[t1].forces_a, f0_1) | |
315 | 406 | |
316 | - f0 = pf0-p1 | |
317 | - f1 = pf1-p0 | |
318 | - masses[t0].add_torque(p0, f0) | |
319 | - masses[t1].add_torque(p1, f1) | |
320 | - | |
407 | + | |
408 | + | |
409 | + | |
321 | 410 | |
322 | 411 | def voronoi_polygons(voronoi, diameter): |
323 | 412 | """Generate shapely.geometry.Polygon objects corresponding to the |
... | ... | @@ -446,7 +535,7 @@ def gen_cluster_graph(G, num_clusters, cluster_pos): |
446 | 535 | G_cluster.vertex_properties["bc"] = vbetweeness_centrality |
447 | 536 | G_cluster.edge_properties["bc"] = ebetweeness_centrality |
448 | 537 | G_cluster.edge_properties["bc_scaled"] = G_cluster.new_edge_property("double", vals=ebc) |
449 | - | |
538 | + G_cluster.edge_properties["log"] = G_cluster.new_edge_property("double", vals=abs(np.log(G_cluster.edge_properties["volume"].get_array()))) | |
450 | 539 | dg = G_cluster.vertex_properties["degree"].get_array() |
451 | 540 | dg = 2*max(dg) - dg |
452 | 541 | d = G_cluster.new_vertex_property("int", vals=dg) |
... | ... | @@ -570,7 +659,35 @@ def centroid_region(vertices): |
570 | 659 | C_y = (1.0 / (6.0 * A)) * C_y |
571 | 660 | |
572 | 661 | return np.array([C_x, C_y]) |
573 | - | |
662 | + | |
663 | +def find_equlibrium(masses, t = 0.01): | |
664 | + for m in masses: | |
665 | + sum_torque = 0 | |
666 | + for torque in m.torque: | |
667 | + if torque[3] == "clockwise": | |
668 | + sum_torque -= torque[0] | |
669 | + else: | |
670 | + sum_torque += torque[0] | |
671 | + m.vel = m.aa * t + m.vel | |
672 | + m.aa = sum_torque/m.MoI | |
673 | + #print(m.G.vertex_properties["clusters"][0], m.vel) | |
674 | + if m.vel != 0.0: | |
675 | + if m.vel < 0.0: | |
676 | + m.rotate(abs(m.vel * t),"counterclock") | |
677 | + else: | |
678 | + m.rotate(abs(m.vel * t), "clockwise") | |
679 | + | |
680 | + | |
681 | +def gen_Eades(G, masses, M = 10): | |
682 | + for i in range(M): | |
683 | + get_forces(G, masses) | |
684 | + for j in masses: | |
685 | + j.translate(0.001) | |
686 | + | |
687 | +def onion_springs(G, masses, min_length): | |
688 | + for v in G.vertices(): | |
689 | + | |
690 | + | |
574 | 691 | |
575 | 692 | def gen_image(G, G_c, itr, bb_flag = False, bb = None, reposition = False): |
576 | 693 | #def gen_image(G, G_c, vor, vor_filtered): |
... | ... | @@ -580,18 +697,24 @@ def gen_image(G, G_c, itr, bb_flag = False, bb = None, reposition = False): |
580 | 697 | |
581 | 698 | #get points of the centers of every cluster |
582 | 699 | #generate voronoi region and plot it. |
583 | - fig, ax = plt.subplots(3, 1, sharex='col', sharey='row') | |
700 | + fig, ax = plt.subplots(4, 1, sharex='col', sharey='row') | |
584 | 701 | fig.tight_layout() |
585 | - grid = plt.GridSpec(3,1) | |
702 | + grid = plt.GridSpec(4,1) | |
586 | 703 | grid.update(wspace=0.025, hspace=0.2) |
587 | 704 | ax[0].axis('off') |
588 | 705 | ax[1].axis('off') |
589 | 706 | ax[2].axis('off') |
707 | + ax[3].axis('off') | |
708 | + | |
590 | 709 | |
710 | + #Add plots to the axes and get their handles | |
591 | 711 | all_plots = fig.add_subplot(grid[0]) |
592 | 712 | ax[0].set_title(itr) |
593 | 713 | no_links = fig.add_subplot(grid[1], sharey=all_plots, sharex=all_plots) |
594 | 714 | voronoi = fig.add_subplot(grid[2], sharey=all_plots, sharex=all_plots) |
715 | + rotated = fig.add_subplot(grid[3], sharey=all_plots, sharex=all_plots) | |
716 | + | |
717 | + #Get the points and generate the voronoi region | |
595 | 718 | pts = G_c.vertex_properties["pos"].get_2d_array(range(2)).T |
596 | 719 | if bb_flag == False: |
597 | 720 | vor = Voronoi(pts) |
... | ... | @@ -601,16 +724,20 @@ def gen_image(G, G_c, itr, bb_flag = False, bb = None, reposition = False): |
601 | 724 | a = voronoi.get_ylim() |
602 | 725 | b = voronoi.get_xlim() |
603 | 726 | bb = np.array([b[0], b[1], a[0], a[1]]) |
727 | + | |
728 | + #generate the polygons based on the voronoi regions | |
604 | 729 | G_c, regions, vor = gen_polygons(G_c, bb) |
605 | 730 | if bb_flag == True: |
606 | 731 | voronoi_plot_2d(vor, all_plots) |
607 | 732 | voronoi_plot_2d(vor, no_links) |
608 | 733 | voronoi_plot_2d(vor, voronoi) |
734 | + | |
609 | 735 | #plot the top-level graph |
610 | 736 | pts = G_c.vertex_properties["pos"].get_2d_array(range(2)).T |
611 | 737 | all_plots.scatter(pts[:,0], pts[:, 1], s=20*G_c.vertex_properties["degree"].get_array(), marker="*") |
612 | 738 | no_links.scatter(pts[:,0], pts[:, 1], s=20*G_c.vertex_properties["degree"].get_array(), marker="*") |
613 | 739 | voronoi.scatter(pts[:,0], pts[:, 1], s=20*G_c.vertex_properties["degree"].get_array(), marker="*") |
740 | + | |
614 | 741 | #plot the connections of the top level graph |
615 | 742 | for e in G_c.edges(): |
616 | 743 | coord = G_c.vertex_properties["pos"][e.source()] |
... | ... | @@ -621,18 +748,25 @@ def gen_image(G, G_c, itr, bb_flag = False, bb = None, reposition = False): |
621 | 748 | no_links.plot(x, y, 'go--', linewidth=1, markersize=1) |
622 | 749 | voronoi.plot(x, y, 'go--', linewidth=1, markersize=1) |
623 | 750 | |
624 | - #for every subgraph generate a layout and plot the resulting Polygon_mass | |
751 | + #For every subgraph generate a layout and plot the resulting Polygon_mass | |
752 | + #These polygons are not the same as the voronoi polygons and instead surround | |
753 | + #graph. | |
625 | 754 | masses = [] |
626 | 755 | for i in range(num_clusters): |
627 | 756 | g, center = gen_subclusters(G, G_c, i, reposition) |
628 | 757 | d = G_c.vertex_properties["pos"][i] - center |
629 | - t = Polygon_mass(g) | |
630 | - masses.append(g) | |
631 | - #t.distancefield() | |
632 | 758 | for v in g.vertices(): |
633 | 759 | G.vertex_properties["pos"][g.vertex_properties["idx"][v]] = g.vertex_properties["pos"][v] + d |
760 | + g.vertex_properties["pos"][v] = g.vertex_properties["pos"][v] + d | |
761 | + t = Polygon_mass(g) | |
762 | + t.set_degree(G_c.vertex_properties["degree"][i]) | |
763 | + masses.append(t) | |
764 | + #t.distancefield() | |
634 | 765 | |
635 | - | |
766 | + #get the torques generated by the positioning of the graphs. | |
767 | + get_torques(G, masses) | |
768 | +# for i in masses: | |
769 | +# i.plot_graph(i.D, i.x, i.y) | |
636 | 770 | #g.vertex_properties["pos"][g.vertex_properties["idx"][v]] = g.vertex_properties["pos"][v] + d |
637 | 771 | #sub_pts = g.vertex_properties["pos"].get_2d_array(range(2)).T |
638 | 772 | #all_plots.scatter(pts[:,0], pts[:, 1], marker="*") |
... | ... | @@ -642,7 +776,9 @@ def gen_image(G, G_c, itr, bb_flag = False, bb = None, reposition = False): |
642 | 776 | # x = [coord[0], coord2[0]] |
643 | 777 | # y = [coord[1], coord2[1]] |
644 | 778 | # plt.plot(x, y, 'ro--', linewidth=1, markersize=1) |
645 | - | |
779 | + | |
780 | + | |
781 | + #Plot the cluster level connections and the vertex level connections. | |
646 | 782 | for e in G.edges(): |
647 | 783 | coord = G.vertex_properties["pos"][e.source()] |
648 | 784 | coord2 = G.vertex_properties["pos"][e.target()] |
... | ... | @@ -653,7 +789,8 @@ def gen_image(G, G_c, itr, bb_flag = False, bb = None, reposition = False): |
653 | 789 | no_links.plot(x, y, 'ro--', linewidth=1, markersize=1) |
654 | 790 | else: |
655 | 791 | all_plots.plot(x, y, 'bo--', linewidth=1, markersize=1) |
656 | - | |
792 | + | |
793 | + #Update the centroids based on the voronoi polygons | |
657 | 794 | no_links.xaxis.set_visible(False) |
658 | 795 | all_plots.xaxis.set_visible(False) |
659 | 796 | for v in G_c.vertices(): |
... | ... | @@ -661,11 +798,16 @@ def gen_image(G, G_c, itr, bb_flag = False, bb = None, reposition = False): |
661 | 798 | centroid = centroid_region(region[0]) |
662 | 799 | G_c.vertex_properties["pos"][v] = centroid |
663 | 800 | |
801 | + | |
802 | + print(G_c.num_vertices(), G_c.num_edges()) | |
803 | + | |
804 | + #Plots the vertices of the subgraphs | |
664 | 805 | pts_temp = G_c.vertex_properties["pos"].get_2d_array(range(2)).T |
665 | 806 | all_plots.scatter(pts_temp[:,0], pts_temp[:, 1], marker='.', color='r') |
666 | 807 | no_links.scatter(pts_temp[:,0], pts_temp[:, 1], marker='.', color='r') |
667 | 808 | voronoi.scatter(pts_temp[:,0], pts_temp[:, 1], marker='.', color='r') |
668 | 809 | |
810 | + #set the limits of the plots. | |
669 | 811 | all_plots.set_xlim([bb[0], bb[1]]) |
670 | 812 | all_plots.set_ylim([bb[2], bb[3]]) |
671 | 813 | |
... | ... | @@ -675,10 +817,44 @@ def gen_image(G, G_c, itr, bb_flag = False, bb = None, reposition = False): |
675 | 817 | voronoi.set_xlim([bb[0], bb[1]]) |
676 | 818 | voronoi.set_ylim([bb[2], bb[3]]) |
677 | 819 | |
820 | + #show the plots. | |
678 | 821 | plt.show() |
679 | 822 | |
823 | +# for j in [7, 10, 15]: | |
824 | +# masses[j].plot_graph(masses[j].D, masses[j].x, masses[j].y) | |
825 | + | |
826 | + for j in range(10): | |
827 | + for i in range(100): | |
828 | + get_torques(G, masses) | |
829 | + find_equlibrium(masses) | |
830 | + gen_Eades(G, masses) | |
831 | +# for j in [7, 10]: | |
832 | +# masses[j].plot_graph(masses[j].D, masses[j].x, masses[j].y) | |
833 | +# for j in [7, 10, 15]: | |
834 | +# masses[j].plot_graph(masses[j].D, masses[j].x, masses[j].y) | |
835 | + | |
836 | + for i in masses: | |
837 | + for v in i.G.vertices(): | |
838 | + G.vertex_properties["pos"][i.G.vertex_properties["idx"][v]] = i.G.vertex_properties["pos"][v] | |
839 | + | |
840 | + | |
841 | + #Plot the cluster level connections and the vertex level connections. | |
842 | + for e in G.edges(): | |
843 | + coord = G.vertex_properties["pos"][e.source()] | |
844 | + coord2 = G.vertex_properties["pos"][e.target()] | |
845 | + x = [coord[0], coord2[0]] | |
846 | + y = [coord[1], coord2[1]] | |
847 | + if (G.vertex_properties["clusters"][e.source()] == G.vertex_properties["clusters"][e.target()]): | |
848 | + rotated.plot(x, y, 'ro--', linewidth=1, markersize=1) | |
849 | + else: | |
850 | + rotated.plot(x, y, 'bo--', linewidth=1, markersize=1) | |
851 | + | |
852 | + pts_temp = G.vertex_properties["pos"].get_2d_array(range(2)).T | |
853 | + rotated.scatter(pts_temp[:,0], pts_temp[:, 1], marker='.', color='r') | |
854 | + | |
855 | + | |
680 | 856 | |
681 | - return G, G_c, bb | |
857 | + return G, G_c, bb, masses | |
682 | 858 | |
683 | 859 | |
684 | 860 | |
... | ... | @@ -691,19 +867,25 @@ def gen_image(G, G_c, itr, bb_flag = False, bb = None, reposition = False): |
691 | 867 | |
692 | 868 | G, bbl, bbu = load_nwt("/home/pavel/Documents/Python/GraphGuiQt/network_4.nwt") |
693 | 869 | G_c, G = gen_clusters(G, bbl, bbu) |
870 | + | |
694 | 871 | num_clusters = 20 |
695 | 872 | |
696 | 873 | #G_c.vertex_properties["pos"] = nwt.gt.radial_tree_layout(G_c, root=np.argwhere(G_c.vertex_properties["degree"].get_array() == max(G_c.vertex_properties["degree"].get_array())), node_weight = G_c.vertex_properties["10-degree"], r= 2.0) |
697 | 874 | G_c.vertex_properties["pos"] = nwt.gt.sfdp_layout(G_c, eweight=G_c.edge_properties["volume"], vweight=G_c.vertex_properties["degree"], C = 1.0, K = 10) |
698 | 875 | |
699 | -G, G_c, bb = gen_image(G, G_c, "base", reposition = True) | |
876 | + | |
877 | + | |
878 | +G, G_c, bb, masses = gen_image(G, G_c, "base", reposition = True) | |
879 | + | |
880 | +print("Planarity test: G_c, G = " , nwt.gt.graph_tool.topology.is_planar(G_c), nwt.gt.graph_tool.topology.is_planar(G)) | |
881 | + | |
700 | 882 | itr = 0 |
701 | 883 | |
702 | 884 | #for itr in range(5): |
703 | -# G, G_c, bb = gen_image(G, G_c, itr, True, bb) | |
885 | +# G, G_c, bb, masses = gen_image(G, G_c, itr, True, bb) | |
704 | 886 | # itr+=1 |
705 | 887 | |
706 | -g, center = gen_subclusters(G, G_c) | |
888 | +#g, center = gen_subclusters(G, G_c) | |
707 | 889 | #d = G_c.vertex_properties["pos"][0] - center |
708 | 890 | #for v in g.vertices(): |
709 | 891 | # g.vertex_properties["pos"][v] = g.vertex_properties["pos"][v] + d | ... | ... |