Commit 17e4b25a127e9bb5b3f69616f8d0a5649894954e
1 parent
4407a915
Bug fixes, Dual version, histograms, cluster exploration, vertex exploration, to…
… do: path exploration and hover-over
Showing
13 changed files
with
1493 additions
and
235 deletions
Show diff stats
GraphCanvas.py
... | ... | @@ -13,6 +13,18 @@ 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 | 15 | from vispy import app |
16 | +#from shapely.geometry import Polygon | |
17 | +#from shapely.geometry import Point | |
18 | +#from shapely.geometry import MultiPoint | |
19 | +from scipy.spatial import ConvexHull | |
20 | +from scipy.spatial import Delaunay | |
21 | +#import scipy.spatial.ConvexHull | |
22 | + | |
23 | +from vispy.scene.visuals import Text | |
24 | +from vispy.scene.visuals import ColorBar | |
25 | + | |
26 | + | |
27 | + | |
16 | 28 | import copy |
17 | 29 | |
18 | 30 | import numpy as np |
... | ... | @@ -211,6 +223,10 @@ class GraphCanvas(scene.SceneCanvas): |
211 | 223 | self.timer = app.Timer('auto', connect=self.on_timer, start=False) |
212 | 224 | #self.constant = app.Timer('auto', connect=self.update, start=True) |
213 | 225 | self.num=0 |
226 | + self.current_color = "" | |
227 | + self.update_text(self.current_color) | |
228 | + self.update_color_bar(self.current_color) | |
229 | + | |
214 | 230 | print(self.context.config) |
215 | 231 | |
216 | 232 | def on_timer(self, event): |
... | ... | @@ -251,42 +267,42 @@ class GraphCanvas(scene.SceneCanvas): |
251 | 267 | self.vbo_line = gloo.VertexBuffer(self.line_data) |
252 | 268 | self.program_e.bind(self.vbo_line) |
253 | 269 | |
254 | - | |
255 | - self.update_clusters(self.old_pos) | |
256 | - edges = self.G_cluster.get_edges() | |
257 | -# #generate the vertex buffer and the connections buffer. | |
258 | - for e in range(edges.shape[0]): | |
259 | - idx = int(4*edges[e][2]) | |
260 | - p0 = self.cluster_pos[int(edges[e][0])] | |
261 | - p1 = self.cluster_pos[int(edges[e][1])] | |
262 | - #p0 = self.G_cluster.vertex_properties["pos"][self.G_cluster.vertex(edges[e][0])] | |
263 | - #p1 = self.G_cluster.vertex_properties["pos"][self.G_cluster.vertex(edges[e][1])] | |
264 | - d = np.subtract(p1, p0) | |
265 | - #d_norm = np.multiply(d, 1/np.sqrt(np.power(d[0],2) + np.power(d[1],2))) | |
266 | - d_norm = d[0:2] | |
267 | - d_norm = d_norm / np.sqrt(np.power(d_norm[0],2) + np.power(d_norm[1],2)) | |
268 | - norm = np.zeros((2,), dtype=np.float32) | |
269 | - norm[0] = d_norm[1] | |
270 | - norm[1] = d_norm[0]*-1 | |
271 | - #print(np.sqrt(norm[0]*norm[0] + norm[1]*norm[1])) | |
272 | - #thickness = G.edge_properties["thickness"][e] | |
273 | - #self.cluster_dict[int(edges[e][0]), int(edges[e][1])] = int(edges[e][2]) | |
274 | - self.cluster_line_data['a_position'][idx] = p0 | |
275 | - self.cluster_line_data['a_normal'][idx] = norm | |
276 | - | |
277 | - self.cluster_line_data['a_position'][idx+1] = p1 | |
278 | - self.cluster_line_data['a_normal'][idx+1] = norm | |
279 | - | |
280 | - self.cluster_line_data['a_position'][idx+2] = p0 | |
281 | - self.cluster_line_data['a_normal'][idx+2] = -norm | |
282 | - | |
283 | - self.cluster_line_data['a_position'][idx+3] = p1 | |
284 | - self.cluster_line_data['a_normal'][idx+3] = -norm | |
285 | - | |
286 | - self.vbo_cluster_lines.set_data(self.cluster_line_data) | |
287 | - self.vbo_s.set_data(self.clusters) | |
288 | - self.program_s.bind(self.vbo_s) | |
289 | - self.program_e_s.bind(self.vbo_cluster_lines) | |
270 | + if(self.subgraphs): | |
271 | + self.update_clusters(self.old_pos) | |
272 | + edges = self.G_cluster.get_edges() | |
273 | + # #generate the vertex buffer and the connections buffer. | |
274 | + for e in range(edges.shape[0]): | |
275 | + idx = int(4*edges[e][2]) | |
276 | + p0 = self.cluster_pos[int(edges[e][0])] | |
277 | + p1 = self.cluster_pos[int(edges[e][1])] | |
278 | + #p0 = self.G_cluster.vertex_properties["pos"][self.G_cluster.vertex(edges[e][0])] | |
279 | + #p1 = self.G_cluster.vertex_properties["pos"][self.G_cluster.vertex(edges[e][1])] | |
280 | + d = np.subtract(p1, p0) | |
281 | + #d_norm = np.multiply(d, 1/np.sqrt(np.power(d[0],2) + np.power(d[1],2))) | |
282 | + d_norm = d[0:2] | |
283 | + d_norm = d_norm / np.sqrt(np.power(d_norm[0],2) + np.power(d_norm[1],2)) | |
284 | + norm = np.zeros((2,), dtype=np.float32) | |
285 | + norm[0] = d_norm[1] | |
286 | + norm[1] = d_norm[0]*-1 | |
287 | + #print(np.sqrt(norm[0]*norm[0] + norm[1]*norm[1])) | |
288 | + #thickness = G.edge_properties["thickness"][e] | |
289 | + #self.cluster_dict[int(edges[e][0]), int(edges[e][1])] = int(edges[e][2]) | |
290 | + self.cluster_line_data['a_position'][idx] = p0 | |
291 | + self.cluster_line_data['a_normal'][idx] = norm | |
292 | + | |
293 | + self.cluster_line_data['a_position'][idx+1] = p1 | |
294 | + self.cluster_line_data['a_normal'][idx+1] = norm | |
295 | + | |
296 | + self.cluster_line_data['a_position'][idx+2] = p0 | |
297 | + self.cluster_line_data['a_normal'][idx+2] = -norm | |
298 | + | |
299 | + self.cluster_line_data['a_position'][idx+3] = p1 | |
300 | + self.cluster_line_data['a_normal'][idx+3] = -norm | |
301 | + | |
302 | + self.vbo_cluster_lines.set_data(self.cluster_line_data) | |
303 | + self.vbo_s.set_data(self.clusters) | |
304 | + self.program_s.bind(self.vbo_s) | |
305 | + self.program_e_s.bind(self.vbo_cluster_lines) | |
290 | 306 | |
291 | 307 | self.refresh() |
292 | 308 | |
... | ... | @@ -309,6 +325,8 @@ class GraphCanvas(scene.SceneCanvas): |
309 | 325 | self.vbo = gloo.VertexBuffer(self.data) |
310 | 326 | self.program.bind(self.vbo) |
311 | 327 | #self.program_e.bind(self.vbo) |
328 | + self.update_text(self.current_color) | |
329 | + self.update_color_bar(self.current_color) | |
312 | 330 | self.refresh() |
313 | 331 | |
314 | 332 | def update_color_buffers(self): |
... | ... | @@ -622,7 +640,7 @@ class GraphCanvas(scene.SceneCanvas): |
622 | 640 | two. |
623 | 641 | """ |
624 | 642 | def gen_cluster_line_vbo(self, G): |
625 | - #create a graph that stores the edges of between the clusters | |
643 | + | |
626 | 644 | self.G_cluster = nwt.gt.Graph(directed=False) |
627 | 645 | self.G_cluster.vertex_properties["pos"] = self.G_cluster.new_vertex_property("vector<double>", val=np.zeros((3,1), dtype=np.float32)) |
628 | 646 | self.G_cluster.vertex_properties["RGBA"] = self.G_cluster.new_vertex_property("vector<double>", val=np.zeros((4,1), dtype=np.float32)) |
... | ... | @@ -630,22 +648,73 @@ class GraphCanvas(scene.SceneCanvas): |
630 | 648 | self.G_cluster.add_vertex() |
631 | 649 | self.G_cluster.vertex_properties["pos"][self.G_cluster.vertex(v)] = np.asarray(self.cluster_pos[v], dtype=np.float32) |
632 | 650 | self.G_cluster.edge_properties["weight"] = self.G_cluster.new_edge_property("int", val = 0) |
651 | + self.G_cluster.edge_properties["volume"] = self.G_cluster.new_edge_property("float", val = 0.0) | |
633 | 652 | #for each edge in the original graph, generate appropriate subgraph edges without repretiions |
634 | 653 | #i.e. controls the thichness of the edges in the subgraph view. |
635 | 654 | for e in G.edges(): |
636 | 655 | #if the source and target cluster is not equal to each other |
637 | 656 | #add an inter subgraph edge. |
638 | 657 | if(G.vertex_properties["clusters"][e.source()] != G.vertex_properties["clusters"][e.target()]): |
658 | + t0 = e.source() | |
659 | + t1 = e.target() | |
660 | + ct0 = self.G_cluster.vertex(G.vertex_properties["clusters"][t0]) | |
661 | + ct1 = self.G_cluster.vertex(G.vertex_properties["clusters"][t1]) | |
662 | + if(self.G_cluster.edge(ct0, ct1) == None): | |
663 | + if(self.G_cluster.edge(ct1, ct0) == None): | |
639 | 664 | #temp_e.append([G.vertex_properties["clusters"][e.source()], G.vertex_properties["clusters"][e.target()]]) |
640 | - self.G_cluster.add_edge(self.G_cluster.vertex(G.vertex_properties["clusters"][e.source()]), \ | |
641 | - self.G_cluster.vertex(G.vertex_properties["clusters"][e.target()])) | |
642 | - self.G_cluster.edge_properties["weight"][self.G_cluster.edge(self.G_cluster.vertex(G.vertex_properties["clusters"][e.source()]), \ | |
643 | - self.G_cluster.vertex(G.vertex_properties["clusters"][e.target()]))] += 1 | |
644 | - self.G_cluster.vertex_properties["RGBA"][self.G_cluster.vertex(G.vertex_properties["clusters"][e.source()])] \ | |
645 | - = G.vertex_properties["RGBA"][e.source()] | |
646 | - self.G_cluster.vertex_properties["RGBA"][self.G_cluster.vertex(G.vertex_properties["clusters"][e.target()])] \ | |
647 | - = G.vertex_properties["RGBA"][e.target()] | |
648 | - | |
665 | + self.G_cluster.add_edge(self.G_cluster.vertex(G.vertex_properties["clusters"][t0]), \ | |
666 | + self.G_cluster.vertex(G.vertex_properties["clusters"][t1])) | |
667 | + self.G_cluster.edge_properties["weight"][self.G_cluster.edge(self.G_cluster.vertex(G.vertex_properties["clusters"][t0]), \ | |
668 | + self.G_cluster.vertex(G.vertex_properties["clusters"][t1]))] += 1 | |
669 | + self.G_cluster.edge_properties["volume"][self.G_cluster.edge(self.G_cluster.vertex(G.vertex_properties["clusters"][t0]), \ | |
670 | + self.G_cluster.vertex(G.vertex_properties["clusters"][t1]))] += G.edge_properties["volume"][e] | |
671 | + self.G_cluster.vertex_properties["RGBA"][self.G_cluster.vertex(G.vertex_properties["clusters"][t0])] \ | |
672 | + = G.vertex_properties["RGBA"][t0] | |
673 | + self.G_cluster.vertex_properties["RGBA"][self.G_cluster.vertex(G.vertex_properties["clusters"][t1])] \ | |
674 | + = G.vertex_properties["RGBA"][t1] | |
675 | + else: | |
676 | + self.G_cluster.edge_properties["weight"][self.G_cluster.edge(self.G_cluster.vertex(G.vertex_properties["clusters"][t1]), \ | |
677 | + self.G_cluster.vertex(G.vertex_properties["clusters"][t0]))] += 1 | |
678 | + self.G_cluster.edge_properties["volume"][self.G_cluster.edge(self.G_cluster.vertex(G.vertex_properties["clusters"][t1]), \ | |
679 | + self.G_cluster.vertex(G.vertex_properties["clusters"][t0]))] += G.edge_properties["volume"][e] | |
680 | + self.G_cluster.vertex_properties["RGBA"][self.G_cluster.vertex(G.vertex_properties["clusters"][t1])] \ | |
681 | + = G.vertex_properties["RGBA"][t1] | |
682 | + self.G_cluster.vertex_properties["RGBA"][self.G_cluster.vertex(G.vertex_properties["clusters"][t0])] \ | |
683 | + = G.vertex_properties["RGBA"][t0] | |
684 | + else: | |
685 | + self.G_cluster.edge_properties["weight"][self.G_cluster.edge(self.G_cluster.vertex(G.vertex_properties["clusters"][t0]), \ | |
686 | + self.G_cluster.vertex(G.vertex_properties["clusters"][t1]))] += 1 | |
687 | + self.G_cluster.edge_properties["volume"][self.G_cluster.edge(self.G_cluster.vertex(G.vertex_properties["clusters"][t0]), \ | |
688 | + self.G_cluster.vertex(G.vertex_properties["clusters"][t1]))] += G.edge_properties["volume"][e] | |
689 | + self.G_cluster.vertex_properties["RGBA"][self.G_cluster.vertex(G.vertex_properties["clusters"][t0])] \ | |
690 | + = G.vertex_properties["RGBA"][t0] | |
691 | + self.G_cluster.vertex_properties["RGBA"][self.G_cluster.vertex(G.vertex_properties["clusters"][t1])] \ | |
692 | + = G.vertex_properties["RGBA"][t1] | |
693 | + #create a graph that stores the edges of between the clusters | |
694 | +# self.G_cluster = nwt.gt.Graph(directed=False) | |
695 | +# self.G_cluster.vertex_properties["pos"] = self.G_cluster.new_vertex_property("vector<double>", val=np.zeros((3,1), dtype=np.float32)) | |
696 | +# self.G_cluster.vertex_properties["RGBA"] = self.G_cluster.new_vertex_property("vector<double>", val=np.zeros((4,1), dtype=np.float32)) | |
697 | +# for v in range(len(self.cluster_pos)): | |
698 | +# self.G_cluster.add_vertex() | |
699 | +# self.G_cluster.vertex_properties["pos"][self.G_cluster.vertex(v)] = np.asarray(self.cluster_pos[v], dtype=np.float32) | |
700 | +# self.G_cluster.edge_properties["weight"] = self.G_cluster.new_edge_property("int", val = 0) | |
701 | +# #for each edge in the original graph, generate appropriate subgraph edges without repretiions | |
702 | +# #i.e. controls the thichness of the edges in the subgraph view. | |
703 | +# for e in G.edges(): | |
704 | +# #if the source and target cluster is not equal to each other | |
705 | +# #add an inter subgraph edge. | |
706 | +# if(G.vertex_properties["clusters"][e.source()] != G.vertex_properties["clusters"][e.target()]): | |
707 | +# #temp_e.append([G.vertex_properties["clusters"][e.source()], G.vertex_properties["clusters"][e.target()]]) | |
708 | +# self.G_cluster.add_edge(self.G_cluster.vertex(G.vertex_properties["clusters"][e.source()]), \ | |
709 | +# self.G_cluster.vertex(G.vertex_properties["clusters"][e.target()])) | |
710 | +# self.G_cluster.edge_properties["weight"][self.G_cluster.edge(self.G_cluster.vertex(G.vertex_properties["clusters"][e.source()]), \ | |
711 | +# self.G_cluster.vertex(G.vertex_properties["clusters"][e.target()]))] += 1 | |
712 | +# self.G_cluster.vertex_properties["RGBA"][self.G_cluster.vertex(G.vertex_properties["clusters"][e.source()])] \ | |
713 | +# = G.vertex_properties["RGBA"][e.source()] | |
714 | +# self.G_cluster.vertex_properties["RGBA"][self.G_cluster.vertex(G.vertex_properties["clusters"][e.target()])] \ | |
715 | +# = G.vertex_properties["RGBA"][e.target()] | |
716 | + | |
717 | + self.G_cluster.vertex_properties["degree"] = self.G_cluster.degree_property_map("total") | |
649 | 718 | self.cluster_line_data = np.zeros(self.G_cluster.num_edges()*4, dtype=[('a_position', np.float32, 3), |
650 | 719 | ('a_normal', np.float32, 2), |
651 | 720 | ('a_fg_color', np.float32, 4), |
... | ... | @@ -824,6 +893,62 @@ class GraphCanvas(scene.SceneCanvas): |
824 | 893 | |
825 | 894 | |
826 | 895 | """ |
896 | + Generates a hierarchical layout based on the cluster graph (spdf) and subclusters | |
897 | + """ | |
898 | + def voronoi_layout(self, G = None, n_c = None, G_c = None): | |
899 | + | |
900 | + def gen_subclusters(G, G_cluster, i, reposition = False): | |
901 | + vfilt = np.zeros([G.num_vertices(), 1], dtype='bool') | |
902 | + labels = G.vertex_properties["clusters"].get_array() | |
903 | + num_v_in_cluster = len(np.argwhere(labels == i)) | |
904 | + vfilt[np.argwhere(labels == i)] = 1 | |
905 | + vfilt_prop = G.new_vertex_property("bool", vals = vfilt) | |
906 | + G.set_vertex_filter(vfilt_prop) | |
907 | + | |
908 | + g = nwt.gt.Graph(G, prune=True, directed=False) | |
909 | + | |
910 | + | |
911 | + if reposition == True: | |
912 | + vbetweeness_centrality = g.new_vertex_property("double") | |
913 | + ebetweeness_centrality = g.new_edge_property("double") | |
914 | + nwt.gt.graph_tool.centrality.betweenness(g, vprop=vbetweeness_centrality, eprop=ebetweeness_centrality, norm=True) | |
915 | + g.vertex_properties["bc"] = vbetweeness_centrality | |
916 | + g.edge_properties["bc"] = ebetweeness_centrality | |
917 | + g.vertex_properties["pos"] = nwt.gt.sfdp_layout(g, eweight = ebetweeness_centrality) | |
918 | + | |
919 | + positions = g.vertex_properties["pos"].get_2d_array(range(2)).T | |
920 | + center = np.sum(positions, 0)/num_v_in_cluster | |
921 | + G.clear_filters() | |
922 | + return g, center | |
923 | + | |
924 | + if G_c == None: | |
925 | + G_c = self.G_cluster | |
926 | + 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) | |
927 | + if(G == None): | |
928 | + G = self.G | |
929 | + if(n_c == None): | |
930 | + n_c = self.n_c | |
931 | + else: | |
932 | + if(G == None): | |
933 | + G = self.G | |
934 | + if(n_c == None): | |
935 | + n_c = self.n_c | |
936 | + if self.n_c == G_c.num_vertices(): | |
937 | + for i in range(n_c): | |
938 | + self.G_cluster.vertex_properties["pos"][self.G_cluster.vertex(i)] = G_c.vertex_properties["pos"][G_c.vertex(i)] | |
939 | + | |
940 | + | |
941 | + for i in range(n_c): | |
942 | + g, center = gen_subclusters(G, G_c, i, reposition=True) | |
943 | + d = G_c.vertex_properties["pos"][i] - center | |
944 | + for v in g.vertices(): | |
945 | + G.vertex_properties["pos"][g.vertex_properties["idx"][v]] = g.vertex_properties["pos"][v] + d | |
946 | + g.vertex_properties["pos"][v] = g.vertex_properties["pos"][v] + d | |
947 | + #print("stuff") | |
948 | + | |
949 | + | |
950 | + | |
951 | + """ | |
827 | 952 | Layout algorithm that expands the cluster based on the location of the of the clusters |
828 | 953 | """ |
829 | 954 | def expand_based_on_clusters(self, G, n): |
... | ... | @@ -920,73 +1045,14 @@ class GraphCanvas(scene.SceneCanvas): |
920 | 1045 | self.clusters['a_value'][index:index+4] = np.asarray(v, dtype=np.float32) |
921 | 1046 | self.G_cluster.vertex_properties["pos"][self.G_cluster.vertex(i)] = self.cluster_pos[i] |
922 | 1047 | |
923 | - | |
924 | - | |
925 | - | |
926 | 1048 | """ |
927 | - Function that generates the clusters for an unclustered graph | |
928 | - These are to be represented by the arcs | |
929 | - """ | |
930 | - def gen_clusters(self, G, bbl, bbu, n_c = None, edge_metric = 'volume', vertex_metric = 'degree'): | |
931 | - | |
932 | - #Generate the clusters | |
933 | - self.labels = nwt.Network.spectral_clustering(G,'length', n_clusters = n_c) | |
934 | - bb = nwt.AABB(G) | |
935 | - #print("FLJKKHDFLKJFDLKJFDLKJ ", m) | |
936 | - pts = [] | |
937 | - x, y, z = bb.project_grid(3) | |
938 | - for i in range(3): | |
939 | - for j in range(3): | |
940 | - for k in range(3): | |
941 | - pts.append(np.array([x[i], y[j], z[k]])) | |
942 | - | |
943 | - #self.labels = nwt.Network.spectral_clustering(G,'length') | |
1049 | + Function that creates the clusters, assuming that all the data is set already. | |
944 | 1050 | |
945 | - #Add clusters as a vertex property | |
946 | - G.vertex_properties["clusters"] = G.new_vertex_property("int", vals=self.labels) | |
947 | - num_clusters = len(np.unique(self.labels)) | |
948 | - self.n_c = n_c | |
949 | - new_indices = [] | |
950 | - pos = G.vertex_properties["p"].get_2d_array(range(3)).T | |
951 | - | |
952 | - #for each cluster find the average vertex position and match to closest point | |
953 | - #in the unique grid. | |
954 | - for i in range(n_c): | |
955 | - point = np.sum(pos[np.argwhere(self.labels == i)], axis=0)/len(np.argwhere(self.labels == i)) | |
956 | - d = 100000000.0 | |
957 | - idx = -1 | |
958 | - for j in range(len(pts)): | |
959 | - dist = np.sqrt(np.power(pts[j][0]-point[0,0],2) + np.power(pts[j][1]-point[0,1],2) + np.power(pts[j][2]-point[0,2],2)) | |
960 | - if dist < d: | |
961 | - d = dist | |
962 | - idx = j | |
963 | - new_indices.append(idx) | |
964 | - pts[idx] = np.array([100000000.0, 1000000000.0, 100000000.0]) | |
965 | - #since there are more points than clusters, we need to make the indices range from | |
966 | - #[0, n_c) | |
967 | - j=0 | |
968 | - unique_indices = np.array(new_indices) | |
969 | - for i in range(n_c): | |
970 | - idx = np.argmin(new_indices) | |
971 | - unique_indices[idx] = j | |
972 | - j += 1 | |
973 | - new_indices[idx] = 100 | |
974 | - | |
975 | - lbl = np.zeros(self.labels.shape) | |
976 | - for i in range(n_c): | |
977 | - idxs = np.argwhere(self.labels == i) | |
978 | - new_idx = np.argwhere(unique_indices == i) | |
979 | - lbl[idxs] = unique_indices[i] | |
980 | - | |
981 | - self.labels = lbl | |
982 | - G.vertex_properties["clusters"] = G.new_vertex_property("int", vals=self.labels) | |
983 | - | |
984 | - | |
985 | - | |
986 | - | |
987 | - | |
988 | - #add colormap | |
989 | - G.vertex_properties["RGBA"] = nwt.Network.map_property_to_color(G, G.vertex_properties["clusters"]) | |
1051 | + """ | |
1052 | + def gen_cluster_vbo(self, G, bbl, bbu, num_clusters, edge_metric = 'volume', vertex_metric = 'degree', update_color = True): | |
1053 | + #add colormap | |
1054 | + if(update_color == True): | |
1055 | + G.vertex_properties["RGBA"] = nwt.Network.map_property_to_color(G, G.vertex_properties["clusters"]) | |
990 | 1056 | |
991 | 1057 | #generate an empty property set for the clusters. |
992 | 1058 | self.clusters = np.zeros(num_clusters*4, dtype=[('a_position', np.float32, 3), |
... | ... | @@ -1105,6 +1171,66 @@ class GraphCanvas(scene.SceneCanvas): |
1105 | 1171 | # self.edges_s = [] |
1106 | 1172 | #print(self.edges_s) |
1107 | 1173 | |
1174 | + """ | |
1175 | + Function that generates the clusters for an unclustered graph | |
1176 | + These are to be represented by the arcs | |
1177 | + """ | |
1178 | + def gen_clusters(self, G, bbl, bbu, n_c = None, edge_metric = 'volume', vertex_metric = 'degree'): | |
1179 | + | |
1180 | + #Generate the clusters | |
1181 | + self.labels = nwt.Network.spectral_clustering(G,'length', n_clusters = n_c) | |
1182 | + bb = nwt.AABB(G) | |
1183 | + #print("FLJKKHDFLKJFDLKJFDLKJ ", m) | |
1184 | + pts = [] | |
1185 | + x, y, z = bb.project_grid(3) | |
1186 | + for i in range(3): | |
1187 | + for j in range(3): | |
1188 | + for k in range(3): | |
1189 | + pts.append(np.array([x[i], y[j], z[k]])) | |
1190 | + | |
1191 | + | |
1192 | + #self.labels = nwt.Network.spectral_clustering(G,'length') | |
1193 | + #Add clusters as a vertex property | |
1194 | + G.vertex_properties["clusters"] = G.new_vertex_property("int", vals=self.labels) | |
1195 | + num_clusters = len(np.unique(self.labels)) | |
1196 | + self.n_c = n_c | |
1197 | + new_indices = [] | |
1198 | + pos = G.vertex_properties["p"].get_2d_array(range(3)).T | |
1199 | + | |
1200 | + #for each cluster find the average vertex position and match to closest point | |
1201 | + #in the unique grid. | |
1202 | + for i in range(n_c): | |
1203 | + point = np.sum(pos[np.argwhere(self.labels == i)], axis=0)/len(np.argwhere(self.labels == i)) | |
1204 | + d = 100000000.0 | |
1205 | + idx = -1 | |
1206 | + for j in range(len(pts)): | |
1207 | + dist = np.sqrt(np.power(pts[j][0]-point[0,0],2) + np.power(pts[j][1]-point[0,1],2) + np.power(pts[j][2]-point[0,2],2)) | |
1208 | + if dist < d: | |
1209 | + d = dist | |
1210 | + idx = j | |
1211 | + new_indices.append(idx) | |
1212 | + pts[idx] = np.array([100000000.0, 1000000000.0, 100000000.0]) | |
1213 | + #since there are more points than clusters, we need to make the indices range from | |
1214 | + #[0, n_c) | |
1215 | + j=0 | |
1216 | + unique_indices = np.array(new_indices) | |
1217 | + for i in range(n_c): | |
1218 | + idx = np.argmin(new_indices) | |
1219 | + unique_indices[idx] = j | |
1220 | + j += 1 | |
1221 | + new_indices[idx] = 100 | |
1222 | + | |
1223 | + lbl = np.zeros(self.labels.shape) | |
1224 | + for i in range(n_c): | |
1225 | + idxs = np.argwhere(self.labels == i) | |
1226 | + new_idx = np.argwhere(unique_indices == i) | |
1227 | + lbl[idxs] = unique_indices[i] | |
1228 | + | |
1229 | + self.labels = lbl | |
1230 | + G.vertex_properties["clusters"] = G.new_vertex_property("int", vals=self.labels) | |
1231 | + self.gen_cluster_vbo(self.G, bbl, bbu, num_clusters, edge_metric, vertex_metric) | |
1232 | + | |
1233 | + | |
1108 | 1234 | |
1109 | 1235 | """ |
1110 | 1236 | Function that expands that generates the layout and updates the buffer |
... | ... | @@ -1124,11 +1250,288 @@ class GraphCanvas(scene.SceneCanvas): |
1124 | 1250 | print(self.view) |
1125 | 1251 | self.refresh() |
1126 | 1252 | |
1253 | + | |
1254 | + """ | |
1255 | + Function for generating a distance field based on the clusters in the | |
1256 | + clustered 3D network. | |
1257 | + """ | |
1258 | + def distancefield(self, G): | |
1259 | + | |
1260 | + import scipy as sp | |
1261 | + #generate a meshgrid of the appropriate size and resolution to surround the network | |
1262 | + #get the space occupied by the network | |
1263 | + lower = self.bbl | |
1264 | + upper = self.bbu | |
1265 | + R = np.asarray(np.floor(abs(lower-upper)), dtype=np.int) | |
1266 | + | |
1267 | + x = np.linspace(lower[0], upper[0], R[0]) #get the grid points for uniform sampling of this space | |
1268 | + y = np.linspace(lower[1], upper[1], R[1]) | |
1269 | + z = np.linspace(lower[2], upper[2], R[2]) | |
1270 | + X, Y, Z = np.meshgrid(x, y, z, indexing='ij') | |
1271 | + | |
1272 | + Q = np.stack((X, Y, Z), 3) | |
1273 | + #get a list of all node positions in the network | |
1274 | + P = [] | |
1275 | + #get a mirrored list of all the point labels | |
1276 | + L = [] | |
1277 | + | |
1278 | + for e in G.edges(): | |
1279 | + X_p = G.edge_properties["x"][e] | |
1280 | + Y_p = G.edge_properties["y"][e] | |
1281 | + Z_p = G.edge_properties["z"][e] | |
1282 | + l = list(np.array([X_p,Y_p,Z_p]).T) | |
1283 | + #generate points list foe each edge | |
1284 | + | |
1285 | + P = P + l | |
1286 | + #generate labels list for each edge | |
1287 | + if G.vertex_properties["clusters"][e.source()] == G.vertex_properties["clusters"][e.target()]: | |
1288 | + c = G.vertex_properties["clusters"][e.source()] | |
1289 | + for i in range(len(l)): | |
1290 | + L.append(c) | |
1291 | + #if source and target have the same label, all points have that label | |
1292 | + else: | |
1293 | + #if source != target label, then point takes on the closest label | |
1294 | + source = [] | |
1295 | + source.append(0.0) | |
1296 | + target = [] | |
1297 | + for i in range(1, len(l)): | |
1298 | + dist = math.sqrt(pow(l[i][0]-l[i-1][0],2) + pow(l[i][1]-l[i-1][1],2) + pow(l[i][2]-l[i-1][2],2)) | |
1299 | + source.append(dist + source[len(source)-1]) | |
1300 | + target = source[::-1] | |
1301 | + for i in range(len(l)): | |
1302 | + if source[i] > target[i]: | |
1303 | + L.append(G.vertex_properties["clusters"][e.source()]) | |
1304 | + else: | |
1305 | + L.append(G.vertex_properties["clusters"][e.target()]) | |
1306 | + | |
1307 | + #turn that list into a Numpy array so that we can create a KD tree | |
1308 | + P = np.array(P) | |
1309 | + | |
1310 | + #generate a KD-Tree out of the network point array | |
1311 | + tree = sp.spatial.cKDTree(P) | |
1312 | + | |
1313 | + D, I = tree.query(Q) | |
1314 | + C = np.zeros(I.shape, dtype=np.int) | |
1315 | + for i in range(I.shape[0]): | |
1316 | + for j in range(I.shape[1]): | |
1317 | + for k in range(I.shape[2]): | |
1318 | + C[i,j,k] = L[I[i,j,k]] | |
1319 | + | |
1320 | + self.write_VTK_R(G, "./test_field.vtk", Q, C, X, Y, Z) | |
1321 | + return D, x, y, z, C | |
1322 | + | |
1323 | + """ | |
1324 | + Function for saving the distance field based on the clusters in the | |
1325 | + clustered 3D network. | |
1326 | + """ | |
1327 | + def write_VTK_R(self, G, filepath, Q, C, X, Y, Z):\ | |
1328 | + | |
1329 | + from pyevtk.hl import gridToVTK | |
1330 | + from pyevtk.hl import imageToVTK | |
1331 | + from pyevtk.vtk import VtkFile, VtkImageData | |
1332 | + import vtk | |
1333 | + #T = C.reshape(C.shape[0]*C.shape[1]*C.shape[2]) | |
1334 | + #C = T.reshape((C.shape[0], C.shape[1], C.shape[2]), order = 'C') | |
1335 | + ColorR = np.zeros((C.shape[0], C.shape[1], C.shape[2])) | |
1336 | + ColorG = np.zeros((C.shape[0], C.shape[1], C.shape[2])) | |
1337 | + ColorB = np.zeros((C.shape[0], C.shape[1], C.shape[2])) | |
1338 | + ColorA = np.zeros((C.shape[0], C.shape[1], C.shape[2])) | |
1339 | + #ColorR = ColorG = ColorB = ColorA = np.chararray((P.shape[0], P.shape[1], P.shape[2])) | |
1340 | + G.vertex_properties["RGBA"] = nwt.Network.map_property_to_color(G, G.vertex_properties["clusters"]) | |
1341 | + self.color_edges(G) | |
1342 | + thisdict = {} | |
1343 | + otherdict = {} | |
1344 | + for v in G.vertices(): | |
1345 | + thisdict[G.vertex_properties["clusters"][v]] = G.vertex_properties["RGBA"][v] | |
1346 | + color = G.vertex_properties["RGBA"][v].get_array() | |
1347 | + c = '#%02x%02x%02x%02x' % (int(color[0]*255), int(color[1]*255), int(color[2]*255), int(color[3]*255*0.3)) | |
1348 | + otherdict[G.vertex_properties["clusters"][v]] = c | |
1349 | + | |
1350 | + print(thisdict, file=open('myfile.txt', 'w')) | |
1351 | + i = 0 | |
1352 | + for i in range(C.shape[0]): | |
1353 | + for j in range(C.shape[1]): | |
1354 | + for k in range(C.shape[2]): | |
1355 | + c = thisdict[C[i,j,k]] | |
1356 | + ColorR[i,j,k] = c[0] | |
1357 | + ColorG[i,j,k] = c[1] | |
1358 | + ColorB[i,j,k] = c[2] | |
1359 | + ColorA[i,j,k] = c[3] | |
1360 | + | |
1361 | + | |
1362 | + # fig = plt.figure() | |
1363 | + # ax = fig.gca(projection='3d') | |
1364 | + # for e in G.edges(): | |
1365 | + # X = G.edge_properties["x"][e] | |
1366 | + # Y = G.edge_properties["y"][e] | |
1367 | + # Z = G.edge_properties["z"][e] | |
1368 | + # color = G.edge_properties['RGBA'][e].get_array() | |
1369 | + # c = '#%02x%02x%02x' % (int(color[0]*255), int(color[1]*255), int(color[2]*255)) | |
1370 | + # ax.plot(X,Y,Z, color=c) | |
1371 | + # print("plotting line") | |
1372 | + # | |
1373 | + # | |
1374 | + # print("generating cells") | |
1375 | + # x, y, z = np.indices(np.array(C.shape) + 1).astype(float) | |
1376 | + # filled = np.ones(C.shape) | |
1377 | + # print("replacing dict") | |
1378 | + # vox = replace_with_dict(C, otherdict) | |
1379 | + # | |
1380 | + # print("plotting voxels") | |
1381 | + # ax.voxels(x, y, z, filled, facecolors=vox) | |
1382 | + | |
1383 | + | |
1384 | + #ax.imshow(np.stack((ColorR[:,:,0], ColorG[:,:,0], ColorB[:,:,0]), axis = 2)) | |
1385 | + | |
1386 | + #plt.show() | |
1387 | + | |
1388 | + | |
1389 | + | |
1390 | + | |
1391 | + | |
1392 | + filename = "./image_fixed.vti" | |
1393 | + imageData = vtk.vtkImageData() | |
1394 | + imageData.SetDimensions(C.shape[0], C.shape[1], C.shape[2]) | |
1395 | + imageData.SetOrigin(0.0, 0.0, 0.0) | |
1396 | + imageData.SetSpacing(1.0, 1.0, 1.0) | |
1397 | + if vtk.VTK_MAJOR_VERSION <= 5: | |
1398 | + imageData.SetNumberOfScalarComponents(4) | |
1399 | + imageData.SetScalarTypeToDouble() | |
1400 | + else: | |
1401 | + imageData.AllocateScalars(vtk.VTK_DOUBLE, 4) | |
1402 | + | |
1403 | + for z in range(C.shape[2]): | |
1404 | + for y in range(C.shape[1]): | |
1405 | + for x in range(C.shape[0]): | |
1406 | + imageData.SetScalarComponentFromDouble(x, y, z, 0, ColorR[x,y,z]) | |
1407 | + imageData.SetScalarComponentFromDouble(x, y, z, 1, ColorG[x,y,z]) | |
1408 | + imageData.SetScalarComponentFromDouble(x, y, z, 2, ColorB[x,y,z]) | |
1409 | + imageData.SetScalarComponentFromDouble(x, y, z, 3, ColorA[x,y,z]) | |
1410 | + | |
1411 | + | |
1412 | + writer = vtk.vtkXMLImageDataWriter() | |
1413 | + writer.SetFileName(filename) | |
1414 | + if vtk.VTK_MAJOR_VERSION <= 5: | |
1415 | + writer.SetInputConnection(imageData.GetProducerPort()) | |
1416 | + else: | |
1417 | + writer.SetInputData(imageData) | |
1418 | + | |
1419 | + writer.Write() | |
1420 | + nwt.Network.write_vtk(G, "./vessels_fixed.vtk", binning = False) | |
1421 | + | |
1422 | + def set_graph(self, G, bbl, bbu, subgraph = False): | |
1423 | + self.G = G | |
1424 | + self.bbl = bbl | |
1425 | + self.bbu = bbu | |
1426 | + clear(color=True, depth=True) | |
1427 | + self.subgraphs = subgraph | |
1428 | + self.current_color = "clusters" | |
1429 | + self.color_edges(G) | |
1430 | + print(self.G) | |
1431 | + color = G.vertex_properties["RGBA"].get_2d_array(range(4)).T | |
1432 | + size = nwt.Network.map_vertices_to_range(G, [30*self.pixel_scale, 8*self.pixel_scale], 'degree').get_array() | |
1433 | + | |
1434 | + position = G.vertex_properties["pos"].get_2d_array(range(3)).T | |
1435 | + #for p in range(position.shape[0]): | |
1436 | + # position[p][0] = position[p][0] + self.clusters["a_position"][G.vertex_properties["clusters"][G.vertex(p)]][0] | |
1437 | + # position[p][1] = position[p][1] + self.clusters["a_position"][G.vertex_properties["clusters"][G.vertex(p)]][1] | |
1438 | + # position[p][2] = position[p][2] + self.clusters["a_position"][G.vertex_properties["clusters"][G.vertex(p)]][2] | |
1439 | + #G.vertex_properties["pos"] = G.new_vertex_property("vector<double>", vals = position) | |
1440 | + edges = G.get_edges(); | |
1441 | + edges = edges[:, 0:2] | |
1442 | + #width = nwt.Network.map_edges_to_range(G, [1*self.pixel_scale, 5*self.pixel_scale], 'volume').get_array() | |
1443 | + #ecolor = G.edge_properties["RGBA"].get_2d_array(range(4)).T | |
1444 | + | |
1445 | + self.data = np.zeros(G.num_vertices(), dtype=[('a_position', np.float32, 3), | |
1446 | + ('a_fg_color', np.float32, 4), | |
1447 | + ('a_bg_color', np.float32, 4), | |
1448 | + ('a_size', np.float32, 1), | |
1449 | + ('a_linewidth', np.float32, 1), | |
1450 | + ('a_unique_id', np.float32, 4), | |
1451 | + ('a_selection', np.float32, 1), | |
1452 | + ]) | |
1453 | + | |
1454 | + #self.edges = edges.astype(np.uint32) | |
1455 | + self.data['a_position'] = position | |
1456 | + #fg color is the color of the ring | |
1457 | + self.data['a_fg_color'] = 0, 0, 0, 1 | |
1458 | + self.data['a_bg_color'] = color | |
1459 | + self.data['a_size'] = size | |
1460 | + self.data['a_linewidth'] = 4.*self.pixel_scale | |
1461 | + self.data['a_unique_id'] = self.gen_vertex_id(G) | |
1462 | + self.data['a_selection'] = G.vertex_properties["selection"].get_array() | |
1463 | + #self.data['a_graph_size'] = [bbu-bbl] | |
1464 | + | |
1465 | + #self.program['u_graph_size'] = [bbu-bbl] | |
1466 | + | |
1467 | + self.vbo = gloo.VertexBuffer(self.data) | |
1468 | + self.gen_line_vbo(G) | |
1469 | + #self.gen_cylinder_vbo(G) | |
1470 | + if(self.subgraphs): | |
1471 | + self.labels = self.G.vp["clusters"].get_array() | |
1472 | + self.gen_cluster_vbo(self.G, bbl, bbu, self.n_c) | |
1473 | + self.vbo_s = gloo.VertexBuffer(self.clusters) | |
1474 | + self.index_s = gloo.IndexBuffer(self.edges_s) | |
1475 | + #self.index = gloo.IndexBuffer(self.edges) | |
1476 | + self.program_e.bind(self.vbo_line) | |
1477 | + self.program.bind(self.vbo) | |
1478 | + if(self.subgraphs): | |
1479 | + #self.program_e_s.bind(self.vbo_s) | |
1480 | + self.program_s.bind(self.vbo_s) | |
1481 | + if DEBUG: | |
1482 | + print(self.view) | |
1483 | + self.update_text(self.current_color) | |
1484 | + self.update_color_bar(self.current_color) | |
1485 | + self.refresh() | |
1486 | + | |
1487 | + | |
1488 | + def update_text(self, text): | |
1489 | + self.t1 = Text(text, parent=self.scene, color = 'black', method='gpu', anchor_x = 'right', anchor_y='top') | |
1490 | + self.t1.font_size = 24 | |
1491 | + #self.t1.anchor_y = 'top' | |
1492 | + #self.t1.anchor_x = 'right' | |
1493 | +# print(self.t1.bounds(0), self.t1.bounds(1)) | |
1494 | + self.t1.pos = self.size[0]-10, self.size[1] // 24 | |
1495 | + self.refresh() | |
1496 | + | |
1497 | + def update_color_bar(self, color_property): | |
1498 | + if color_property != "": | |
1499 | + prop = self.G.vp[color_property].get_array().T | |
1500 | + mx = max(prop) | |
1501 | + mn = min(prop) | |
1502 | + else: | |
1503 | + mx = 1.0 | |
1504 | + mn = 0.0 | |
1505 | + if(color_property=="clusters"): | |
1506 | + cm = 'tab20' | |
1507 | + else: | |
1508 | + cm = 'plasma' | |
1509 | + self.c_bar = ColorBar(cmap=cm, orientation = 'bottom', | |
1510 | + size = (self.size[0] // 3, self.size[1] // 24), clim = (mn, mx), | |
1511 | + border_width = 10.0,border_color = 'white', | |
1512 | + parent=self.scene, | |
1513 | + pos=(self.size[0] // 3 // 2 + 20, self.size[1] // 24), | |
1514 | + padding = (100, 100) | |
1515 | + ) | |
1516 | + self.refresh() | |
1517 | + | |
1127 | 1518 | """ |
1128 | 1519 | Loads the data G and generates all the buffers necessary as well as performs |
1129 | 1520 | spectral clustering on the graph passed if the subgraph is set to true. |
1130 | 1521 | """ |
1131 | - def set_data(self, G, bbl, bbu, subgraph=True): | |
1522 | + def set_data(self, G, bbl, bbu, subgraph=True, G_other = None): | |
1523 | + | |
1524 | + def in_hull(point, hull, tolerance=1e-6): | |
1525 | + return all( | |
1526 | + (np.dot(eq[:-1], point) + eq[-1] <= tolerance) | |
1527 | + for eq in hull.equations) | |
1528 | + | |
1529 | +# def in_hull(p, hull): | |
1530 | +# if not isinstance(hull,Delaunay): | |
1531 | +# hull = Delaunay(hull) | |
1532 | +# | |
1533 | +# return hull.find_simplex(p)>=0 | |
1534 | + | |
1132 | 1535 | if DEBUG: |
1133 | 1536 | print("Setting data") |
1134 | 1537 | self.G = G |
... | ... | @@ -1137,11 +1540,115 @@ class GraphCanvas(scene.SceneCanvas): |
1137 | 1540 | clear(color=True, depth=True) |
1138 | 1541 | self.subgraphs = True |
1139 | 1542 | self.current_color = "clusters" |
1140 | - if(subgraph==True): | |
1141 | - self.gen_clusters(G, bbl, bbu, n_c=19) | |
1142 | 1543 | |
1544 | + if(subgraph==True and G_other == None): | |
1545 | + self.gen_clusters(G, bbl, bbu, n_c=19) | |
1546 | + self.G.vertex_properties["idx"] = self.G.vertex_index | |
1143 | 1547 | #color based on clusters |
1144 | 1548 | self.color_edges(G) |
1549 | + else: | |
1550 | + #polygons = [] | |
1551 | + self.G.vertex_properties["idx"] = self.G.vertex_index | |
1552 | + self.G.vertex_properties["clusters"] = self.G.new_vertex_property("int", vals=np.full(self.G.num_vertices(), -1, dtype="int")) | |
1553 | + num_clusters = len(np.unique(G_other.vertex_properties["clusters"].get_array().T)) | |
1554 | + color_lookup = [] | |
1555 | + lbls = G_other.vertex_properties["clusters"].get_array().T | |
1556 | + for i in range(num_clusters): | |
1557 | + idx = np.where(lbls == i)[0][0] | |
1558 | + color_lookup.append(G_other.vertex_properties["RGBA"][G_other.vertex(idx)]) | |
1559 | + | |
1560 | + | |
1561 | + self.n_c = num_clusters | |
1562 | + D, x, y, z, C = self.distancefield(G_other) | |
1563 | + print(len(x), len(y), len(z)) | |
1564 | + for v in self.G.vertices(): | |
1565 | + p = self.G.vertex_properties["p"][v] | |
1566 | + x_temp = np.fabs(x - p[0]) | |
1567 | + idx_x = x_temp.argmin() | |
1568 | + y_temp = np.fabs(y - p[1]) | |
1569 | + idx_y = y_temp.argmin() | |
1570 | + z_temp = np.fabs(z - p[2]) | |
1571 | + idx_z = z_temp.argmin() | |
1572 | + cluster = C[idx_x][idx_y][idx_z] | |
1573 | + self.G.vertex_properties["clusters"][v] = cluster | |
1574 | + self.G.vertex_properties["RGBA"][v] = color_lookup[cluster] | |
1575 | + | |
1576 | + | |
1577 | + | |
1578 | + ###############OLD Comparison mechanic######################## | |
1579 | +# polygons = [] | |
1580 | +# for i in range(num_clusters): | |
1581 | +# #num_v_in_cluster = len(np.argwhere(self.labels == i)) | |
1582 | +# vfilt = np.zeros([G_other.num_vertices(), 1], dtype="bool") | |
1583 | +# vfilt[np.argwhere(G_other.vertex_properties["clusters"].get_array().T == i)] = 1 | |
1584 | +# vfilt_prop = G_other.new_vertex_property("bool", vals = vfilt) | |
1585 | +# G_other.set_vertex_filter(vfilt_prop) | |
1586 | +# | |
1587 | +# #get the filtered properties | |
1588 | +# g = nwt.gt.Graph(G_other, prune=True, directed=False) | |
1589 | +# color = g.vertex_properties["RGBA"][g.vertex(0)] | |
1590 | +# positions = g.vertex_properties["p"].get_2d_array(range(3)).T | |
1591 | +# hull = ConvexHull(positions) | |
1592 | +# #hull = Delaunay(positions) | |
1593 | +# #hull = multipoint.convex_hull | |
1594 | +# polygons.append(hull) | |
1595 | +# G_other.clear_filters() | |
1596 | +# for v in self.G.vertices(): | |
1597 | +# if in_hull(self.G.vertex_properties["p"][v], hull) and self.G.vertex_properties["clusters"][v] == -1: | |
1598 | +# self.G.vertex_properties["clusters"][v] = i | |
1599 | +# self.G.vertex_properties["RGBA"][v] = color | |
1600 | +## if hull.contains(Point(self.G.vertex_properties["p"][v])): | |
1601 | +## self.G.vertex_properties["clusters"][v] = i | |
1602 | +## self.G.vertex_properties["RGBA"][v] = color | |
1603 | +# | |
1604 | +# unassigned = np.argwhere(self.G.vertex_properties["clusters"].get_array().T == -1) | |
1605 | +# while len(unassigned > 0): | |
1606 | +# for i in range(len(unassigned)): | |
1607 | +# gen = self.G.vertex(unassigned[i]).all_neighbors() | |
1608 | +# neighbors = [] | |
1609 | +# neighbors_clusters = [] | |
1610 | +# for j in gen: | |
1611 | +# neighbors.append(j) | |
1612 | +# neighbors_clusters.append(self.G.vertex_properties["clusters"][j]) | |
1613 | +# if len(np.unique(neighbors_clusters)) == 1 and np.unique(neighbors_clusters[0]) != -1: | |
1614 | +# self.G.vertex_properties["clusters"][self.G.vertex(unassigned[i])] = \ | |
1615 | +# self.G.vertex_properties["clusters"][neighbors[0]] | |
1616 | +# self.G.vertex_properties["RGBA"][self.G.vertex(unassigned[i])] = \ | |
1617 | +# self.G.vertex_properties["RGBA"][neighbors[0]] | |
1618 | +# else: | |
1619 | +# c, count = np.unique(neighbors_clusters, return_counts=True) | |
1620 | +# for k in range(len(c)): | |
1621 | +# if c[k] == -1: | |
1622 | +# c = np.delete(c, k) | |
1623 | +# count = np.delete(count, k) | |
1624 | +# break | |
1625 | +# if len(c) > 0: | |
1626 | +# cluster = np.argwhere(count == max(count))[0] | |
1627 | +# self.G.vertex_properties["clusters"][self.G.vertex(unassigned[i])] = c[cluster[0]] | |
1628 | +# for v in range(len(neighbors)): | |
1629 | +# if self.G.vertex_properties["clusters"][self.G.vertex(unassigned[i])] == c[cluster[0]]: | |
1630 | +# self.G.vertex_properties["RGBA"][self.G.vertex(unassigned[i])] = \ | |
1631 | +# self.G.vertex_properties["RGBA"][neighbors[v]] | |
1632 | +# unassigned = np.argwhere(self.G.vertex_properties["clusters"].get_array().T == -1) | |
1633 | +# #print("stuff") | |
1634 | +# #for j in range(len(neighbors_clusters)): | |
1635 | +# | |
1636 | +# #self.G.vertex_properties["RGBA"] = nwt.Network.map_property_to_color(self.G, self.G.vertex_properties["clusters"]) | |
1637 | + temp = self.G.vertex_properties["clusters"].get_array().T | |
1638 | + print(np.unique(temp)) | |
1639 | + self.labels = copy.copy(temp) | |
1640 | +# c = np.unique(temp) | |
1641 | +# idx = 0 | |
1642 | +# for i in range(len(c)): | |
1643 | +# self.labels[np.argwhere(temp == c[i])] = idx | |
1644 | +# idx += 1 | |
1645 | +# | |
1646 | + ###############/OLD Comparison mechanic######################## | |
1647 | + self.G.vertex_properties["clusters"] = self.G.new_vertex_property("int", vals = self.labels) | |
1648 | + self.n_c = len(np.unique(self.labels)) | |
1649 | + self.gen_cluster_vbo(self.G, bbl, bbu, self.n_c, update_color = False) | |
1650 | + self.color_edges(self.G) | |
1651 | + | |
1145 | 1652 | |
1146 | 1653 | color = G.vertex_properties["RGBA"].get_2d_array(range(4)).T |
1147 | 1654 | size = nwt.Network.map_vertices_to_range(G, [30*self.pixel_scale, 8*self.pixel_scale], 'degree').get_array() |
... | ... | @@ -1193,6 +1700,8 @@ class GraphCanvas(scene.SceneCanvas): |
1193 | 1700 | self.program_s.bind(self.vbo_s) |
1194 | 1701 | if DEBUG: |
1195 | 1702 | print(self.view) |
1703 | + self.update_text(self.current_color) | |
1704 | + self.update_color_bar(self.current_color) | |
1196 | 1705 | self.refresh() |
1197 | 1706 | |
1198 | 1707 | """ |
... | ... | @@ -1201,7 +1710,10 @@ class GraphCanvas(scene.SceneCanvas): |
1201 | 1710 | def on_resize(self, event): |
1202 | 1711 | set_viewport(0, 0, *event.physical_size) |
1203 | 1712 | self.fbo = gloo.FrameBuffer(color=gloo.RenderBuffer(self.size[::-1]), depth=gloo.RenderBuffer(self.size[::-1])) |
1204 | - | |
1713 | + self.update_text(self.current_color) | |
1714 | + self.update_color_bar(self.current_color) | |
1715 | + self.refresh() | |
1716 | + app.Canvas.update(self) | |
1205 | 1717 | |
1206 | 1718 | """ |
1207 | 1719 | Overloaded function that is called during every self.update() call |
... | ... | @@ -1215,8 +1727,10 @@ class GraphCanvas(scene.SceneCanvas): |
1215 | 1727 | if(self.subgraphs): |
1216 | 1728 | self.program_e_s.draw('triangles', indices=self.index_clusters_s) |
1217 | 1729 | self.program_s.draw('triangles', indices=self.index_s) |
1218 | - print("updated ", self.num) | |
1219 | - self.num += 1 | |
1730 | + #print("updated ", self.num) | |
1731 | + #self.num += 1 | |
1732 | + self.t1.draw() | |
1733 | + self.c_bar.draw() | |
1220 | 1734 | #self._u |
1221 | 1735 | #self._update_pending = True |
1222 | 1736 | #app.Canvas.update(self) |
... | ... | @@ -1227,6 +1741,7 @@ class GraphCanvas(scene.SceneCanvas): |
1227 | 1741 | vispy 0.6.3 |
1228 | 1742 | """ |
1229 | 1743 | def refresh(self): |
1744 | + self.update_view_global() | |
1230 | 1745 | self.update() |
1231 | 1746 | app.Canvas.update(self) |
1232 | 1747 | |
... | ... | @@ -1289,6 +1804,7 @@ class GraphCanvas(scene.SceneCanvas): |
1289 | 1804 | #imsave("test_ori.png", buff) |
1290 | 1805 | self.fbo.activate() |
1291 | 1806 | if clusters == False: |
1807 | + self.refresh() | |
1292 | 1808 | self.program['u_picking'] = True |
1293 | 1809 | clear(color='white', depth=True) |
1294 | 1810 | self.program.draw('points') |
... | ... | @@ -1336,6 +1852,12 @@ class GraphCanvas(scene.SceneCanvas): |
1336 | 1852 | else: |
1337 | 1853 | return self.cluster_dict[tuple(color)] |
1338 | 1854 | |
1855 | + def update_view_global(self): | |
1856 | + self.program['u_view'] = self.view | |
1857 | + self.program_e['u_view'] = self.view | |
1858 | + self.program_s['u_view'] = self.view | |
1859 | + self.program_e_s['u_view'] = self.view | |
1860 | + | |
1339 | 1861 | |
1340 | 1862 | """ |
1341 | 1863 | Top level handle-mouse presee event for either left or right click |
... | ... | @@ -1361,8 +1883,10 @@ class GraphCanvas(scene.SceneCanvas): |
1361 | 1883 | # #if menu.exec_(event.globalPos()): |
1362 | 1884 | # # print(item.text()) |
1363 | 1885 | if(event.button == 1): |
1364 | - if(self.view[0][0] > 0.0010): | |
1886 | + if(self.view[0][0] > 0.0024): | |
1887 | + self.refresh() | |
1365 | 1888 | c_id = self.get_clicked_id(event) |
1889 | + self.refresh() | |
1366 | 1890 | if(c_id != None): |
1367 | 1891 | self.original_point = self.G.vertex_properties["pos"][self.G.vertex(c_id)] |
1368 | 1892 | self.location = event.pos |
... | ... | @@ -1373,7 +1897,10 @@ class GraphCanvas(scene.SceneCanvas): |
1373 | 1897 | update_view() |
1374 | 1898 | #print("Clicked on:", event.pos) |
1375 | 1899 | else: |
1900 | +# c_id = None | |
1901 | + self.refresh() | |
1376 | 1902 | c_id = self.get_clicked_id(event, True) |
1903 | + self.refresh() | |
1377 | 1904 | if DEBUG: |
1378 | 1905 | print(c_id) |
1379 | 1906 | if(c_id != None): |
... | ... | @@ -1390,6 +1917,27 @@ class GraphCanvas(scene.SceneCanvas): |
1390 | 1917 | Gets the path and formats it in terms of vertex-to-vertex |
1391 | 1918 | instead of source(obj)-to-source(obj) |
1392 | 1919 | """ |
1920 | + | |
1921 | + def get_cluster(self, cluster_id): | |
1922 | + p = [] | |
1923 | + num_v_in_cluster = len(np.argwhere(self.labels == cluster_id)) | |
1924 | + vfilt = np.zeros([self.G.num_vertices(), 1], dtype="bool") | |
1925 | + vfilt[np.argwhere(self.labels == cluster_id)] = 1 | |
1926 | + vfilt_prop = self.G.new_vertex_property("bool", vals = vfilt) | |
1927 | + self.G.set_vertex_filter(vfilt_prop) | |
1928 | + | |
1929 | + #get the filtered properties | |
1930 | + g = nwt.gt.Graph(self.G, prune=True, directed=False) | |
1931 | + self.G.clear_filters() | |
1932 | + for e in g.edges(): | |
1933 | + source = g.vp["idx"][e.source()] | |
1934 | + target = g.vp["idx"][e.target()] | |
1935 | + temp = (int(source), int(target)) | |
1936 | + p.append(temp) | |
1937 | + | |
1938 | + return p | |
1939 | + | |
1940 | + | |
1393 | 1941 | def get_path(self): |
1394 | 1942 | p = [] |
1395 | 1943 | for s in self.path: |
... | ... | @@ -1422,12 +1970,14 @@ class GraphCanvas(scene.SceneCanvas): |
1422 | 1970 | self.G.vertex_properties["selection"][vl[v]] = 2.0 |
1423 | 1971 | update_vertex_alpha(self, self.G.vertex(vl[v]), 1.0) |
1424 | 1972 | self.data['a_selection'][int(vl[v])] = 2.0 |
1973 | + self.G.vp["exclude"][self.G.vertex(vl[v])] = True | |
1425 | 1974 | source.v_path.append(int(vl[v])) |
1426 | 1975 | for e in el: |
1427 | 1976 | source.e_path.append(e) |
1428 | 1977 | temp = self.G.edge_properties["RGBA"][e] |
1429 | 1978 | temp[3] = 1.0 |
1430 | 1979 | self.G.edge_properties["RGBA"][e] = temp |
1980 | + self.G.edge_properties["exclude"][e] = True | |
1431 | 1981 | |
1432 | 1982 | |
1433 | 1983 | def remove_from_path(self, source): |
... | ... | @@ -1435,15 +1985,19 @@ class GraphCanvas(scene.SceneCanvas): |
1435 | 1985 | self.G.vertex_properties["selection"][self.G.vertex(v)] = 0.0 |
1436 | 1986 | update_vertex_alpha(self,self.G.vertex(v), 0.5) |
1437 | 1987 | self.data['a_selection'][v] = 0.0 |
1988 | + self.G.vertex_properties["exclude"][v] = False | |
1438 | 1989 | for e in source.e_path: |
1439 | 1990 | temp = self.G.edge_properties["RGBA"][e] |
1440 | 1991 | temp[3] = 0.0 |
1441 | 1992 | self.G.edge_properties["RGBA"][e] = temp |
1993 | + self.G.edge_properties["exclude"][e] = False | |
1442 | 1994 | source.clear_path() |
1443 | 1995 | |
1444 | 1996 | if (event.button == 1): |
1445 | - if(self.view[0][0] > 0.0010): | |
1997 | + if(self.view[0][0] > 0.0024): | |
1998 | + self.refresh() | |
1446 | 1999 | c_id = self.get_clicked_id(event) |
2000 | + self.refresh() | |
1447 | 2001 | if(c_id != None): |
1448 | 2002 | #check whether this is the first node to be selected |
1449 | 2003 | if(self.pathing == False): |
... | ... | @@ -1496,6 +2050,7 @@ class GraphCanvas(scene.SceneCanvas): |
1496 | 2050 | self.pathing = False |
1497 | 2051 | self.make_all_transparent(1.0) |
1498 | 2052 | self.update_color_buffers() |
2053 | + self.refresh() | |
1499 | 2054 | |
1500 | 2055 | |
1501 | 2056 | |
... | ... | @@ -1725,6 +2280,43 @@ class GraphCanvas(scene.SceneCanvas): |
1725 | 2280 | self.location = event.pos |
1726 | 2281 | self.refresh() |
1727 | 2282 | |
2283 | + def set_view_matrix(self, matrix): | |
2284 | + self.view = matrix | |
2285 | + self.program['u_view'] = self.view | |
2286 | + self.program_e['u_view'] = self.view | |
2287 | + self.program_s['u_view'] = self.view | |
2288 | + self.program_e_s['u_view'] = self.view | |
2289 | + self.refresh() | |
2290 | + | |
2291 | + | |
2292 | + def center_camera_on(self, camera): | |
2293 | + self.translate[0] += (0.0 - camera[0])/self.view[0][0] | |
2294 | + self.translate[1] += (0.0 - camera[1])/self.view[1][1] | |
2295 | + #self.view[3][0] = self.view[3][0]-(self.location[0]-event.pos[0])/10000.0 | |
2296 | + #self.view[3][1] = self.view[3][1]+(self.location[1]-event.pos[1])/10000.0 | |
2297 | + | |
2298 | + self.view = np.matmul(translate((self.translate[0], self.translate[1], 0)), scale((self.scale[0], self.scale[1], 0))) | |
2299 | + | |
2300 | + self.program['u_view'] = self.view | |
2301 | + self.program_e['u_view'] = self.view | |
2302 | + self.program_s['u_view'] = self.view | |
2303 | + self.program_e_s['u_view'] = self.view | |
2304 | + self.refresh() | |
2305 | + | |
2306 | + def zoom_camera_on(self, zoom): | |
2307 | + self.scale[0] = zoom[0] | |
2308 | + self.scale[1] = zoom[1] | |
2309 | + | |
2310 | + self.view = np.matmul(translate((self.translate[0], self.translate[1], 0)), | |
2311 | + scale((self.scale[0], self.scale[1], 0))) | |
2312 | + | |
2313 | + self.program['u_view'] = self.view | |
2314 | + self.program_e['u_view'] = self.view | |
2315 | + self.program_s['u_view'] = self.view | |
2316 | + self.program_e_s['u_view'] = self.view | |
2317 | + #print(event.delta[1]) | |
2318 | + self.refresh() | |
2319 | + | |
1728 | 2320 | """ |
1729 | 2321 | Handles the mouse wheel zoom event. |
1730 | 2322 | """ | ... | ... |
GraphWidget.py
... | ... | @@ -5,15 +5,79 @@ Created on Mon Aug 5 15:42:19 2019 |
5 | 5 | |
6 | 6 | @author: pavel |
7 | 7 | """ |
8 | - | |
9 | 8 | from GraphCanvas import GraphCanvas |
9 | +from HistogramWidget import HistogramWidget | |
10 | +#from NodeInformationWidget import NodeInfoWidget | |
10 | 11 | from PyQt5 import QtCore, QtGui, QtWidgets |
12 | +from PyQt5.Qt import QRect | |
11 | 13 | import network_dep as nwt |
14 | +from TubeWidget import TubeWidget | |
15 | +from vispy.scene.visuals import Text | |
12 | 16 | |
13 | 17 | import numpy as np |
14 | 18 | |
15 | 19 | DEBUG = False |
16 | 20 | |
21 | + | |
22 | + | |
23 | +class NodeInfoWidget(QtWidgets.QWidget): | |
24 | + def __init__(self, *args, **kwargs): | |
25 | + QtWidgets.QWidget.__init__(self) | |
26 | + self.layout = QtWidgets.QGridLayout() | |
27 | + self.resize(900, 300) | |
28 | + self.bar = None | |
29 | + print("stuff 22") | |
30 | + if 'hist' in kwargs: | |
31 | + print("stuff") | |
32 | + self.bar = HistogramWidget() | |
33 | + self.bar.canvas.create_native() | |
34 | + self.fibers_mini = TubeWidget() | |
35 | + self.fibers_mini.canvas.create_native() | |
36 | + | |
37 | + self.graph_mini1 = GraphWidget() | |
38 | + self.graph_mini1.canvas.create_native() | |
39 | + self.graph_mini2 = GraphWidget() | |
40 | + self.graph_mini2.canvas.create_native() | |
41 | + self.graph_mini3 = GraphWidget() | |
42 | + self.graph_mini3.canvas.create_native() | |
43 | + self.graph_mini4 = GraphWidget() | |
44 | + self.graph_mini4.canvas.create_native() | |
45 | + | |
46 | + | |
47 | + | |
48 | + self.graph_mini1.connect(self.fibers_mini) | |
49 | + self.fibers_mini.connect(self.graph_mini1) | |
50 | + self.fibers_mini.connect(self.graph_mini2) | |
51 | + self.fibers_mini.connect(self.graph_mini3) | |
52 | + self.fibers_mini.connect(self.graph_mini4) | |
53 | + | |
54 | + | |
55 | + self.layout.addWidget(self.graph_mini1.canvas.native, 0, 0, 1, 1) | |
56 | + self.layout.addWidget(self.graph_mini2.canvas.native, 0, 1, 1, 1) | |
57 | + self.layout.addWidget(self.graph_mini3.canvas.native, 1, 0, 1, 1) | |
58 | + self.layout.addWidget(self.graph_mini4.canvas.native, 1, 1, 1, 1) | |
59 | + #layout.addItem(vspacer, 0, 2, 2, 1) | |
60 | + if self.bar == None: | |
61 | + self.layout.addWidget(self.fibers_mini.canvas.native, 0, 2, 2, 2) | |
62 | + else: | |
63 | + self.layout.addWidget(self.fibers_mini.canvas.native, 0, 2, 1, 1) | |
64 | + self.layout.addWidget(self.bar.canvas.native, 1, 2, 1, 1) | |
65 | + #layout.setColumnStretch(0, 2) | |
66 | + #layout.setRowStretch(0, 2) | |
67 | + #layout.setColumnStretch(2, 1) | |
68 | + #layout.setRowStretch(0, 1) | |
69 | + | |
70 | + self.setLayout(self.layout) | |
71 | + #print(layout.getContentsMargins()) | |
72 | + #top.show() | |
73 | + | |
74 | + | |
75 | +# def paintEvent(self, e): | |
76 | +# dc = QPainter(self) | |
77 | + | |
78 | + def bye(self): | |
79 | + self.exit(0) | |
80 | + | |
17 | 81 | """ |
18 | 82 | Initializes the entire QTlayout and sets the mouse press events. |
19 | 83 | These are connected to the slots such that each is processes by this class |
... | ... | @@ -34,11 +98,13 @@ class GraphWidget(QtWidgets.QWidget): |
34 | 98 | self.color = True |
35 | 99 | self.use_3D = False |
36 | 100 | self.camera = [0,0,0] |
101 | + self.other = None | |
37 | 102 | |
38 | 103 | self.canvas.events.mouse_press.connect(self.on_mouse_press) |
39 | 104 | self.canvas.events.mouse_release.connect(self.on_mouse_release) |
40 | 105 | self.canvas.events.mouse_move.connect(self.on_mouse_move) |
41 | 106 | self.canvas.events.mouse_double_click.connect(self.on_mouse_double_click) |
107 | + self.w = None | |
42 | 108 | #self.canvas.events. |
43 | 109 | #self.show() |
44 | 110 | #self.repaint() |
... | ... | @@ -55,18 +121,19 @@ class GraphWidget(QtWidgets.QWidget): |
55 | 121 | self.canvas.set_current(event) |
56 | 122 | if event.button == 2: |
57 | 123 | if self.canvas.view[0][0] >= 0.0010: |
58 | - self.canvas.update() | |
124 | + self.canvas.refresh() | |
59 | 125 | c_id = self.canvas.get_clicked_id(event) |
60 | - self.canvas.update() | |
126 | + self.canvas.refresh() | |
61 | 127 | else: |
62 | - self.canvas.update() | |
128 | + self.canvas.refresh() | |
63 | 129 | c_id = self.canvas.get_clicked_id(event, clusters=True) |
64 | - self.canvas.update() | |
130 | + self.canvas.refresh() | |
65 | 131 | #right click |
66 | 132 | if(c_id == None): |
67 | 133 | menu = QtWidgets.QMenu(self) |
68 | 134 | NS = menu.addAction('Node Size') |
69 | - | |
135 | + if (self.canvas.path != []): | |
136 | + FNP = menu.addAction("Filter Network Path") | |
70 | 137 | #tmp = menu.addAction('temp') |
71 | 138 | tmp = menu.addMenu('Node Color') |
72 | 139 | vertex_props = self.canvas.G.vertex_properties.keys() |
... | ... | @@ -76,12 +143,14 @@ class GraphWidget(QtWidgets.QWidget): |
76 | 143 | vertex_actions.append(tmp.addAction(vertex_props[i])) |
77 | 144 | #tmp.addAction("Cluster") |
78 | 145 | #NC = menu.addAction('Node Color') |
79 | - #EXP = menu.addAction('Export VTK') | |
146 | + EXP = menu.addAction('Export VTK') | |
80 | 147 | #EXP_adv = menu.addAction('Export VTK Advanced') |
81 | 148 | NL = menu.addAction('New Layout') |
82 | 149 | NSL = menu.addAction('New Spring-Onion Layout (sum)') |
83 | 150 | NSLMI = menu.addAction('New Spring-Onion Layout(max)') |
84 | 151 | EXPAND = menu.addAction('Expand') |
152 | + CL = menu.addAction('Cluster_Layout') | |
153 | + | |
85 | 154 | action = menu.exec_(event.native.globalPos()) |
86 | 155 | if DEBUG: |
87 | 156 | print(action) |
... | ... | @@ -101,11 +170,22 @@ class GraphWidget(QtWidgets.QWidget): |
101 | 170 | self.use_3D = False |
102 | 171 | self.canvas.size_vertices(self.canvas.G, 'degree' ) |
103 | 172 | self.canvas.color_vertices(self.canvas.G, 'degree') |
173 | + if (self.canvas.path != []): | |
174 | + if action == FNP: | |
175 | + net = nwt.Network() | |
176 | + G1 = net.filterBorder(self.canvas.G) | |
177 | + BB = nwt.AABB(G1) | |
178 | + self.canvas.set_graph(G1, BB.A, BB.B, subgraph=True) | |
179 | + self.test.canvas.set_data(G1, BB.A, BB.B, 16) | |
180 | + self.canvas.refresh() | |
181 | + self.test.canvas.refresh() | |
182 | + #self.canvas.set_data() | |
183 | + | |
104 | 184 | #if action == NC: |
105 | 185 | # self.canvas.color_vertices(self.canvas.G, not self.color) |
106 | 186 | # self.color = not self.color |
107 | -# if action == EXP: | |
108 | -# nwt.Network.write_vtk(self.canvas.G, "./nwt.vtk") | |
187 | + if action == EXP: | |
188 | + nwt.Network.write_vtk(self.canvas.G, "./nwt_small.vtk") | |
109 | 189 | # if action == EXP_adv: |
110 | 190 | # nwt.Network.write_vtk(self.canvas.G, "./nwt_median_binned.vtk") |
111 | 191 | # nwt.Network.write_vtk(self.canvas.G, "./nwt_median_non_binned.vtk", binning=False) |
... | ... | @@ -158,36 +238,221 @@ class GraphWidget(QtWidgets.QWidget): |
158 | 238 | #self.canvas.expand_clusters(self.canvas.G, self.canvas.n_c) |
159 | 239 | |
160 | 240 | self.canvas.animate(old_pos, new_pos) |
241 | + if action == CL: | |
242 | + old_pos = self.canvas.G.vertex_properties["pos"].get_2d_array(range(3)).T | |
243 | + self.canvas.voronoi_layout() | |
244 | + new_pos = self.canvas.G.vertex_properties["pos"].get_2d_array(range(3)).T | |
245 | + if self.other != None: | |
246 | + other_old_pos = self.other.canvas.G.vertex_properties["pos"].get_2d_array(range(3)).T | |
247 | + self.other.canvas.voronoi_layout(G_c = self.canvas.G_cluster) | |
248 | + other_new_pos = self.other.canvas.G.vertex_properties["pos"].get_2d_array(range(3)).T | |
249 | + self.other.canvas.animate(other_old_pos, other_new_pos) | |
250 | + self.canvas.animate(old_pos, new_pos) | |
161 | 251 | #self.canvas.size_vertices(self.canvas.G, 'degree_volume') |
162 | 252 | else: |
163 | 253 | if self.canvas.view[0][0] >= 0.0010: |
164 | 254 | menu = QtWidgets.QMenu(self) |
165 | - NS = menu.addAction('Display Node Info') | |
255 | + MnOC = menu.addAction('Minimize Other Clusters') | |
256 | + RA = menu.addAction('Reset Alpha') | |
257 | + NI = menu.addAction('Display Node Info') | |
258 | + CI = menu.addAction('Display Cluster Info') | |
166 | 259 | action = menu.exec_(event.native.globalPos()) |
167 | - if action == NS: | |
260 | + if action == MnOC: | |
261 | + self.canvas.set_current(event) | |
262 | + self.canvas.refresh() | |
263 | + c_id = self.canvas.get_clicked_id(event) | |
264 | + | |
265 | + cluster_id = self.canvas.G.vp["clusters"][self.canvas.G.vertex(c_id)] | |
266 | + self.select.emit(self.canvas.get_cluster(cluster_id)) | |
267 | + if action == RA: | |
268 | + t = [] | |
269 | + self.select.emit(self.canvas.get_cluster(t)) | |
270 | + if action == NI: | |
271 | + self.canvas.set_current(event) | |
272 | + self.canvas.refresh() | |
273 | + c_id = self.canvas.get_clicked_id(event) | |
274 | + self.canvas.refresh() | |
168 | 275 | print("Display Node Info") |
276 | + self.w = NodeInfoWidget() | |
277 | + | |
278 | + #generate the subgraph around the node | |
279 | + vfilt = np.zeros([self.canvas.G.num_vertices(), 1], dtype="bool") | |
280 | + center = self.canvas.G.vp["pos"][self.canvas.G.vertex(c_id)] | |
281 | + for v in self.canvas.G.vertex(c_id).all_neighbors(): | |
282 | + vfilt[int(v)] = 1 | |
283 | + vfilt[int(c_id)] = 1 | |
284 | + vfilt_prop = self.canvas.G.new_vertex_property("bool", vals = vfilt) | |
285 | + self.canvas.G.set_vertex_filter(vfilt_prop) | |
286 | + | |
287 | + #get the filtered properties | |
288 | + g = nwt.gt.Graph(self.canvas.G, prune=True, directed=False) | |
289 | + BB = nwt.AABB(g) | |
290 | + #print(BB.A) | |
291 | + #print(BB.B) | |
292 | + self.canvas.G.clear_filters() | |
293 | + self.w.setGeometry(QRect(100, 100, 900, 800)) | |
294 | + self.w.graph_mini1.canvas.set_graph(g, BB.A, BB.B) | |
295 | + self.w.graph_mini1.canvas.center_camera_on(center) | |
296 | + self.w.graph_mini1.canvas.zoom_camera_on(self.canvas.scale) | |
297 | + self.w.graph_mini1.canvas.color_vertices(g, "clusters") | |
298 | + | |
299 | + self.w.graph_mini2.canvas.set_graph(g, BB.A, BB.B) | |
300 | + self.w.graph_mini2.canvas.center_camera_on(center) | |
301 | + self.w.graph_mini2.canvas.zoom_camera_on(self.canvas.scale) | |
302 | + self.w.graph_mini2.canvas.color_vertices(g, "degree") | |
303 | + | |
304 | + self.w.graph_mini3.canvas.set_graph(g, BB.A, BB.B) | |
305 | + #self.w.graph_mini3.canvas.set_view_matrix(self.canvas.view) | |
306 | + self.w.graph_mini3.canvas.center_camera_on(center) | |
307 | + self.w.graph_mini3.canvas.zoom_camera_on(self.canvas.scale) | |
308 | + self.w.graph_mini3.canvas.color_vertices(g, "bc") | |
309 | + | |
310 | + self.w.graph_mini4.canvas.set_graph(g, BB.A, BB.B) | |
311 | + #self.w.graph_mini4.canvas.set_view_matrix(self.canvas.view) | |
312 | + self.w.graph_mini4.canvas.center_camera_on(center) | |
313 | + self.w.graph_mini4.canvas.zoom_camera_on(self.canvas.scale) | |
314 | + self.w.graph_mini4.canvas.color_vertices(g, "degree_volume") | |
315 | + | |
316 | + self.w.fibers_mini.canvas.set_data(g, BB.A, BB.B, 16) | |
317 | + self.w.show() | |
318 | + if action == CI: | |
319 | + self.canvas.set_current(event) | |
320 | + self.canvas.refresh() | |
321 | + c_id = self.canvas.get_clicked_id(event) | |
322 | + #self.canvas.refresh() | |
323 | + self.w = NodeInfoWidget(hist=True) | |
324 | + #self.w = NodeInfoWidget() | |
325 | + | |
326 | + cluster_id = self.canvas.G.vp["clusters"][self.canvas.G.vertex(c_id)] | |
327 | + num_v_in_cluster = len(np.argwhere(self.canvas.labels == cluster_id)) | |
328 | + vfilt = np.zeros([self.canvas.G.num_vertices(), 1], dtype="bool") | |
329 | + vfilt[np.argwhere(self.canvas.labels == cluster_id)] = 1 | |
330 | + vfilt_prop = self.canvas.G.new_vertex_property("bool", vals = vfilt) | |
331 | + self.canvas.G.set_vertex_filter(vfilt_prop) | |
332 | + | |
333 | + #get the filtered properties | |
334 | + g = nwt.gt.Graph(self.canvas.G, prune=True, directed=False) | |
335 | + positions = g.vertex_properties["pos"].get_2d_array(range(3)).T | |
336 | + center = np.sum(positions, 0)/num_v_in_cluster | |
337 | + self.canvas.G.clear_filters() | |
338 | + | |
339 | + BB = nwt.AABB(g) | |
340 | + self.canvas.G.clear_filters() | |
341 | + self.w.setGeometry(QRect(100, 100, 900, 800)) | |
342 | + self.w.graph_mini1.canvas.set_graph(g, BB.A, BB.B) | |
343 | + self.w.graph_mini1.canvas.center_camera_on(center) | |
344 | + self.w.graph_mini1.canvas.zoom_camera_on(self.canvas.scale) | |
345 | + | |
346 | + self.w.graph_mini2.canvas.set_graph(g, BB.A, BB.B) | |
347 | + self.w.graph_mini2.canvas.center_camera_on(center) | |
348 | + self.w.graph_mini2.canvas.zoom_camera_on(self.canvas.scale) | |
349 | + self.w.graph_mini2.canvas.color_vertices(g, "degree") | |
350 | + | |
351 | + self.w.graph_mini3.canvas.set_graph(g, BB.A, BB.B) | |
352 | + #self.w.graph_mini3.canvas.set_view_matrix(self.canvas.view) | |
353 | + self.w.graph_mini3.canvas.center_camera_on(center) | |
354 | + self.w.graph_mini3.canvas.zoom_camera_on(self.canvas.scale) | |
355 | + self.w.graph_mini3.canvas.color_vertices(g, "bc") | |
356 | + | |
357 | + self.w.graph_mini4.canvas.set_graph(g, BB.A, BB.B) | |
358 | + #self.w.graph_mini4.canvas.set_view_matrix(self.canvas.view) | |
359 | + self.w.graph_mini4.canvas.center_camera_on(center) | |
360 | + self.w.graph_mini4.canvas.zoom_camera_on(self.canvas.scale) | |
361 | + self.w.graph_mini4.canvas.color_vertices(g, "degree_volume") | |
362 | + | |
363 | + self.w.fibers_mini.canvas.set_data(g, BB.A, BB.B, 16) | |
364 | + | |
365 | + self.w.bar.set_Graph(g) | |
366 | + | |
367 | + self.w.show() | |
368 | + | |
369 | + print("Display Cluster Info") | |
169 | 370 | else: |
170 | 371 | menu = QtWidgets.QMenu(self) |
171 | 372 | MnOC = menu.addAction('Minimize Other Clusters') |
373 | + CI = menu.addAction('Display Cluster Info') | |
172 | 374 | RA = menu.addAction('Reset Alpha') |
173 | 375 | action = menu.exec_(event.native.globalPos()) |
174 | 376 | if action == MnOC: |
175 | - new_Graph = self.canvas.focus_on_cluster(self.canvas.G, c_id) | |
176 | - self.test.draw_new(new_Graph) | |
377 | + self.canvas.set_current(event) | |
378 | + self.canvas.refresh() | |
379 | + c_id = self.canvas.get_clicked_id(event, clusters=True) | |
380 | + self.canvas.refresh() | |
381 | + | |
382 | + cluster_id = self.canvas.G.vp["clusters"][c_id] | |
383 | + self.select.emit(self.canvas.get_path(cluster_id)) | |
177 | 384 | if action == RA: |
178 | - self.canvas.reset_alpha(c_id[0]) | |
385 | + t = [] | |
386 | + self.select.emit(self.canvas.get_cluster(t)) | |
387 | + if action == CI: | |
388 | + self.canvas.set_current(event) | |
389 | + self.canvas.refresh() | |
390 | + c_id = self.canvas.get_clicked_id(event, clusters=True) | |
391 | + self.canvas.refresh() | |
392 | + | |
393 | + self.w = NodeInfoWidget(hist=True) | |
394 | + #self.w = NodeInfoWidget() | |
395 | + | |
396 | + cluster_id = self.canvas.G.vp["clusters"][c_id] | |
397 | + num_v_in_cluster = len(np.argwhere(self.canvas.labels == c_id)) | |
398 | + vfilt = np.zeros([self.canvas.G.num_vertices(), 1], dtype="bool") | |
399 | + vfilt[np.argwhere(self.canvas.labels == c_id)] = 1 | |
400 | + vfilt_prop = self.canvas.G.new_vertex_property("bool", vals = vfilt) | |
401 | + self.canvas.G.set_vertex_filter(vfilt_prop) | |
402 | + | |
403 | + #get the filtered properties | |
404 | + g = nwt.gt.Graph(self.canvas.G, prune=True, directed=False) | |
405 | + positions = g.vertex_properties["pos"].get_2d_array(range(3)).T | |
406 | + center = np.sum(positions, 0)/num_v_in_cluster | |
407 | + self.canvas.G.clear_filters() | |
408 | + | |
409 | + BB = nwt.AABB(g) | |
410 | + self.canvas.G.clear_filters() | |
411 | + self.w.setGeometry(QRect(100, 100, 900, 800)) | |
412 | + self.w.graph_mini1.canvas.set_graph(g, BB.A, BB.B) | |
413 | + self.w.graph_mini1.canvas.center_camera_on(center) | |
414 | + self.w.graph_mini1.canvas.zoom_camera_on(self.canvas.scale) | |
415 | + | |
416 | + self.w.graph_mini2.canvas.set_graph(g, BB.A, BB.B) | |
417 | + self.w.graph_mini2.canvas.center_camera_on(center) | |
418 | + self.w.graph_mini2.canvas.zoom_camera_on(self.canvas.scale) | |
419 | + self.w.graph_mini2.canvas.color_vertices(g, "degree") | |
420 | + | |
421 | + self.w.graph_mini3.canvas.set_graph(g, BB.A, BB.B) | |
422 | + #self.w.graph_mini3.canvas.set_view_matrix(self.canvas.view) | |
423 | + self.w.graph_mini3.canvas.center_camera_on(center) | |
424 | + self.w.graph_mini3.canvas.zoom_camera_on(self.canvas.scale) | |
425 | + self.w.graph_mini3.canvas.color_vertices(g, "bc") | |
426 | + | |
427 | + self.w.graph_mini4.canvas.set_graph(g, BB.A, BB.B) | |
428 | + #self.w.graph_mini4.canvas.set_view_matrix(self.canvas.view) | |
429 | + self.w.graph_mini4.canvas.center_camera_on(center) | |
430 | + self.w.graph_mini4.canvas.zoom_camera_on(self.canvas.scale) | |
431 | + self.w.graph_mini4.canvas.color_vertices(g, "degree_volume") | |
432 | + | |
433 | + self.w.fibers_mini.canvas.set_data(g, BB.A, BB.B, 16) | |
434 | + | |
435 | + self.w.bar.set_Graph(g) | |
436 | + self.w.show() | |
437 | + | |
438 | + print("Display Cluster Info") | |
439 | + | |
179 | 440 | |
180 | 441 | |
181 | 442 | # def selection_change(self, i): |
182 | 443 | # self.canvas.size_vertices(self.canvas.G, self.cb.currentText()) |
183 | 444 | |
184 | 445 | |
446 | + def set_other(self, other): | |
447 | + self.other = other | |
448 | + | |
185 | 449 | """ |
186 | 450 | Handles the mouse double click event. |
187 | 451 | Pass-through function. |
188 | 452 | """ |
189 | 453 | |
190 | 454 | def on_mouse_double_click(self, event): |
455 | + self.canvas.set_current(event) | |
191 | 456 | self.canvas.update_path(event) |
192 | 457 | self.select.emit(self.canvas.get_path()) |
193 | 458 | # old_pos = self.canvas.G.vertex_properties["pos"].get_2d_array(range(3)).T |
... | ... | @@ -209,7 +474,11 @@ class GraphWidget(QtWidgets.QWidget): |
209 | 474 | Pass-through function. |
210 | 475 | """ |
211 | 476 | def on_mouse_move(self, event): |
212 | - n = 2 | |
477 | + self.canvas.set_current(event) | |
478 | + self.canvas.refresh() | |
479 | + c_id = self.canvas.get_clicked_id(event) | |
480 | + self.canvas.refresh() | |
481 | + print(c_id) | |
213 | 482 | |
214 | 483 | """ |
215 | 484 | Internal function that interacts with the tube visualization. | ... | ... |
GuiVisPy_tube.py
... | ... | @@ -57,23 +57,28 @@ graph.canvas.create_native() |
57 | 57 | graph.connect(fibers) |
58 | 58 | fibers.connect(graph) |
59 | 59 | |
60 | -#initialize the layout | |
61 | -layout.addWidget(graph.canvas.native, 0, 0, 2, 3) | |
62 | -layout.addWidget(fibers.canvas.native, 0, 2, 2, 3) | |
63 | -layout.setColumnStretch(0, 2) | |
64 | -layout.setRowStretch(0, 2) | |
65 | -layout.setColumnStretch(2, 1) | |
66 | -layout.setRowStretch(0, 1) | |
60 | +#vspacer = QtWidgets.QSpacerItem(10,10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) | |
67 | 61 | |
68 | -top.setLayout(layout) | |
62 | +#initialize the layoutddddddddddd | |
69 | 63 | |
70 | -top.show() | |
64 | +#addLayout(QLayout *layout, int row, int column, int rowSpan, int columnSpan | |
65 | +#, Qt::Alignment alignment = Qt::Alignment()) | |
66 | +#layout.addWidget(graph.canvas.native, 0, 0, 2, 3) | |
67 | +#layout.addItem(vspacer, 0, 1, 2, 3) | |
68 | +#layout.addWidget(fibers.canvas.native, 0, 2, 2, 3) | |
69 | + | |
70 | +layout.addWidget(graph.canvas.native, 0, 0, 2, 3) | |
71 | +#layout.addItem(vspacer, 0, 2, 2, 1) | |
72 | +layout.addWidget(fibers.canvas.native, 0, 4, 2, 3) | |
71 | 73 | |
74 | +#layout.setColumnStretch(0, 2) | |
75 | +#layout.setRowStretch(0, 2) | |
76 | +#layout.setColumnStretch(2, 1) | |
77 | +#layout.setRowStretch(0, 1) | |
72 | 78 | |
73 | -#def draw_histogram(G, value): | |
74 | -# vals = G.edge_properties[value].get_array() | |
75 | -# y, x = np.histogram(vals,40) | |
76 | -# hist.plot(x,y, stepMode=True, fillLevel=0, brush=(0,0,255,150)) | |
79 | +top.setLayout(layout) | |
80 | +print(layout.getContentsMargins()) | |
81 | +top.show() | |
77 | 82 | |
78 | 83 | def load_nwt(filepath): |
79 | 84 | net = nwt.Network(filepath) |
... | ... | @@ -115,6 +120,12 @@ fibers.canvas.set_data(G, bbl, bbu, 16) |
115 | 120 | #fibers.draw_all(G, center, fibers, graph, node_tex) |
116 | 121 | graph.set_g_view(fibers) |
117 | 122 | |
123 | +graph.label = QtWidgets.QLabel(graph) | |
124 | +graph.label.setFrameStyle(QtWidgets.QFrame.Panel | QtWidgets.QFrame.Sunken) | |
125 | +graph.label.setText("STUFF") | |
126 | +graph.label.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignRight) | |
127 | +graph.label.raise_() | |
128 | + | |
118 | 129 | ## Start Qt event loop unless running in interactive mode. |
119 | 130 | if __name__ == '__main__': |
120 | 131 | #import sys | ... | ... |
1 | +#!/usr/bin/env python3 | |
2 | +# -*- coding: utf-8 -*- | |
3 | +""" | |
4 | +Created on Thu Jan 31 15:29:40 2019 | |
5 | + | |
6 | +@author: pavel | |
7 | +`""" | |
8 | + | |
9 | +from vispy import app | |
10 | +import vispy | |
11 | + | |
12 | +import network_dep as nwt | |
13 | + | |
14 | +#from pyqtgraph.Qt import QtCore, QtGui, QtWidgets | |
15 | +from PyQt5 import QtCore, QtGui, QtWidgets | |
16 | +#import pyqtgraph as pg | |
17 | +import numpy as np | |
18 | +import math | |
19 | + | |
20 | +from mpl_toolkits.mplot3d import Axes3D | |
21 | +#import matplotlib | |
22 | +#import matplotlib.pyplot as plt | |
23 | +#matplotlib.use('Qt5Agg') | |
24 | + | |
25 | +from GraphWidget import GraphWidget | |
26 | +from TubeWidget import TubeWidget | |
27 | +#vispy.use(app='egl') | |
28 | + | |
29 | + | |
30 | +DEBUG = False | |
31 | + | |
32 | +#set the backend. for different versions of PyQt | |
33 | +app.use_app(backend_name='PyQt5') | |
34 | + | |
35 | +app.set_interactive(True) | |
36 | + | |
37 | +#Define a top level application | |
38 | +appMain = QtWidgets.QApplication([]) | |
39 | +#QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_ShareOpenGLContexts, True) | |
40 | + | |
41 | +##Define a toplevel Widget | |
42 | +top = QtWidgets.QWidget() | |
43 | +top.resize(900, 900) | |
44 | + | |
45 | + | |
46 | +#fibers = FiberView() | |
47 | +fibers = TubeWidget() | |
48 | +fibers.canvas.create_native() | |
49 | +#fibers = gl.GLViewWidget() | |
50 | + | |
51 | +#plt = hist.addPlot() | |
52 | + | |
53 | +layout = QtWidgets.QGridLayout() | |
54 | +graph = GraphWidget() | |
55 | +graph.canvas.create_native() | |
56 | + | |
57 | + | |
58 | +fibers2 = TubeWidget() | |
59 | +fibers2.canvas.create_native() | |
60 | + | |
61 | +graph2 = GraphWidget() | |
62 | +graph2.canvas.create_native() | |
63 | + | |
64 | +graph.connect(fibers) | |
65 | +fibers.connect(graph) | |
66 | + | |
67 | +graph2.connect(fibers2) | |
68 | +fibers2.connect(graph2) | |
69 | + | |
70 | +#vspacer = QtWidgets.QSpacerItem(10,10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) | |
71 | + | |
72 | +#initialize the layoutddddddddddd | |
73 | + | |
74 | +#addLayout(QLayout *layout, int row, int column, int rowSpan, int columnSpan | |
75 | +#, Qt::Alignment alignment = Qt::Alignment()) | |
76 | +#layout.addWidget(graph.canvas.native, 0, 0, 2, 3) | |
77 | +#layout.addItem(vspacer, 0, 1, 2, 3) | |
78 | +#layout.addWidget(fibers.canvas.native, 0, 2, 2, 3) | |
79 | + | |
80 | +layout.addWidget(graph.canvas.native, 0, 0, 1, 3) | |
81 | +#layout.addItem(vspacer, 0, 2, 2, 1) | |
82 | +layout.addWidget(fibers.canvas.native, 0, 4, 1, 3) | |
83 | + | |
84 | +layout.addWidget(graph2.canvas.native, 1, 0, 1, 3) | |
85 | +#layout.addItem(vspacer, 0, 2, 2, 1) | |
86 | +layout.addWidget(fibers2.canvas.native, 1, 4, 1, 3) | |
87 | + | |
88 | +#layout.setColumnStretch(0, 2) | |
89 | +#layout.setRowStretch(0, 2) | |
90 | +#layout.setColumnStretch(2, 1) | |
91 | +#layout.setRowStretch(0, 1) | |
92 | + | |
93 | +top.setLayout(layout) | |
94 | +print(layout.getContentsMargins()) | |
95 | +top.show() | |
96 | + | |
97 | +def load_nwt(filepath): | |
98 | + net = nwt.Network(filepath) | |
99 | + G = net.createFullGraph_gt() | |
100 | + G = net.filterDisconnected(G) | |
101 | + #G = net.gen_spring_onion_layout(G, 'degree', 1.0, 1000, 0.01, 1.0) | |
102 | + #G = net.filterFullGraph_gt(G, erode=True) | |
103 | + #G = net.filterFullGraph_gt(G, erode=True) | |
104 | + #G = net.gen_new_fd_layout(G) | |
105 | + #G = net.filterBorder(G) | |
106 | + #nwt.Network.saveGraph_gt(nwt, G, "FilteredNetwork_JACK_3.nwt") | |
107 | + color = np.zeros(4, dtype = np.double) | |
108 | + color = [0.0, 1.0, 0.0, 1.0] | |
109 | + G.edge_properties["RGBA"] = G.new_edge_property("vector<double>", val=color) | |
110 | + color = [1.0, 0.0, 0.0, 0.9] | |
111 | + G.vertex_properties["RGBA"] = G.new_vertex_property("vector<double>", val=color) | |
112 | + bbl, bbu = net.aabb() | |
113 | + | |
114 | + | |
115 | + return G, bbl, bbu | |
116 | + | |
117 | +G, bbl, bbu = load_nwt("/home/pavel/Documents/Python/GraphGuiQt/network_4.nwt") | |
118 | + | |
119 | +G2, bbl2, bbu2 = load_nwt("/home/pavel/Documents/Python/GraphGuiQt/network_4.nwt") | |
120 | +#G2, bbl2, bbu2 = load_nwt("/home/pavel/Documents/Python/GraphGuiQt/network_4.nwt") | |
121 | +#nwt.Network.write_vtk(G) | |
122 | + | |
123 | +#G, bbl, bbu = load_nwt("/home/pavel/Documents/Python/GraphGuiQt/net`````````work_test_251_1kx3_short_NEW.nwt") | |
124 | +#ret = nwt.Network.get_affinity_matrix(G, "length") | |
125 | +#node_image = QtGui.QImage("/home/pavel/Documents/Python/GraphGuiQt/node_tex.jpg") | |
126 | +#node_tex = QtGui.QBitmap.fromImage(node_image) | |
127 | + | |
128 | +if DEBUG: | |
129 | + print(node_tex.depth()) | |
130 | +#fibers.opts['distance'] = 5 | |
131 | +# item = NodeItem(G) | |
132 | +# graph.addItem(item) | |
133 | +#draw_histogram(G, "length") | |
134 | + | |
135 | + #self.canvas.events.mouse_press.connect(o_canvas.on_mouse_press) | |
136 | + #self.canvas.events.mouse_release.connect(o_canvas.on_mouse_release) | |
137 | + #self.canvas.events.mouse_move.connect(o_canvas.on_mouse_move) | |
138 | + #self.canvas.events.mouse_wheel.connect(o_canvas.on_mouse_wheel) | |
139 | +#fibers.canvas.events.mouse_press.connect(fibers2.mouse_press) | |
140 | +#fibers.canvas.events.mouse_release.connect(fibers2.mouse_release) | |
141 | +#fibers.canvas.events.on_mouse_wheel.connect(fibers2.canvas.on_mouse_wheel) | |
142 | + | |
143 | +graph.canvas.set_data(G, bbl, bbu) | |
144 | +fibers.canvas.set_data(G, bbl, bbu, 16) | |
145 | +fibers.set_other(fibers2) | |
146 | +fibers2.set_other(fibers) | |
147 | +graph.set_other(graph2) | |
148 | +graph2.set_other(graph) | |
149 | + | |
150 | +graph2.canvas.set_data(G2, bbl2, bbu2, G_other=graph.canvas.G) | |
151 | +fibers2.canvas.set_data(G2, bbl2, bbu2, 16) | |
152 | +#fibers.draw_all(G, center, fibers, graph, node_tex) | |
153 | +graph.set_g_view(fibers) | |
154 | +graph2.set_g_view(fibers2) | |
155 | + | |
156 | + | |
157 | +#fibers.link_cameras(fibers2) | |
158 | +#fibers2.link_cameras(fibers) | |
159 | + | |
160 | +## Start Qt event loop unless running in interactive mode. | |
161 | +if __name__ == '__main__': | |
162 | + #import sys | |
163 | + #if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): | |
164 | + #QtGui.QApplication.instance().exec_() | |
165 | + app.set_interactive(enabled=True) | |
166 | + app.run() | |
167 | + | ... | ... |
1 | +#!/usr/bin/env python3 | |
2 | +# -*- coding: utf-8 -*- | |
3 | +""" | |
4 | +Created on Tue Mar 3 13:47:39 2020 | |
5 | + | |
6 | +@author: pavel | |
7 | +""" | |
8 | + | |
9 | +from PyQt5 import QtCore, QtGui, QtWidgets | |
10 | +import network_dep as nwt | |
11 | +import vispy.plot as vp | |
12 | +#import vispy.scene.visuals. as Histogram | |
13 | +from vispy.scene.visuals import Histogram as Histogram | |
14 | + | |
15 | +import numpy as np | |
16 | + | |
17 | +DEBUG = False | |
18 | + | |
19 | + | |
20 | +class HistogramWidget(QtWidgets.QWidget): | |
21 | + def __init__(self): | |
22 | + super(HistogramWidget, self).__init__() | |
23 | + box = QtWidgets.QVBoxLayout(self) | |
24 | + self.resize(500,500) | |