-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathVisualization.py
167 lines (137 loc) · 6.13 KB
/
Visualization.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
from bokeh.io import show
from bokeh.layouts import column, row
from bokeh.models import Dropdown, Div, Legend, LegendItem
from bokeh.plotting import from_networkx
import networkx as nx
from bokeh.models import MultiLine, Circle, TapTool, HoverTool, BoxSelectTool
from bokeh.plotting import figure
from bokeh.io import curdoc
from bokeh.events import Tap
from P1 import P1
from P2 import P2
from P3 import P3
from P4 import P4
from P5 import P5
from P6 import P6
from P7 import P7
from P8 import P8
# TODO usuwac image po kliknieciu produkcji
class Visualization:
production_classes_by_names = {
"Production 1": P1,
"Production 2": P2,
"Production 3": P3,
"Production 4": P4,
"Production 5": P5,
"Production 6": P6,
"Production 7": P7,
"Production 8": P8,
}
production_selected = None
vertices_chosen = list()
source = None
networkx_graph = None
graph_renderer = None
plot = None
def __init__(self, graph):
self.graph = graph
self._create_buttons()
self._graph_initialization()
self._set_hover_tool_and_click_event()
self.layout = column(self.dropdown, self.plot)
self.layout = row(self.layout, self._create_legend())
def _create_colors(self):
colors = []
labels = []
self.source.data['index'] = list(self.graph.vertices[v].index for v in self.graph.vertices)
for v in self.graph.vertices:
colors.append(self.graph.vertices[v].to_color())
labels.append(self.graph.vertices[v].label)
self.source.data['colors'] = colors
self.source.data['labels'] = labels
def _create_edges_to_lists(self):
edges_to = [[] for _ in self.graph.vertices]
vertices_indexes = self.source.data['index']
for edge_tuple in self.graph.edges:
vertex_from, vertex_to = edge_tuple
edges_to[vertices_indexes.index(vertex_from)].append(vertex_to)
self.source.data['edges_to'] = edges_to
def _create_buttons(self):
self.menu = [("Production 1", "Production 1"), ("Production 2", "Production 2"),
("Production 3", "Production 3"), ("Production 4", "Production 4"),
("Production 5", "Production 5"), ("Production 6", "Production 6"),
("Production 7", "Production 7"), ("Production 8", "Production 8")]
self.dropdown = Dropdown(label="Productions", button_type="warning", menu=self.menu)
self.dropdown.on_click(self._dropdown_update)
def _remove_image(self):
for element in self.layout.children:
if element.name == "production":
self.layout.children.remove(element)
def _create_image(self, production):
self._remove_image()
div_image = Div(text=f"<img src='Graph-Transformations/static/images/"
f"{self.production_classes_by_names[production].to_string()}.jpg' width='540' height='auto'>",
name="production", margin=(5, 5, 5, -100))
self.layout = row(self.layout, div_image)
curdoc().clear()
curdoc().add_root(self.layout)
@staticmethod
def _create_legend():
return Div(text=f"<img src='Graph-Transformations/static/images/legend.jpg'>", margin=(200, 5, 5, 5))
def _dropdown_update(self, event):
self.dropdown.label = event.item
self._create_image(event.item)
self.production_selected = self.production_classes_by_names.get(event.item)
self.vertices_chosen.clear()
def _clicking_update(self, event):
node_clicked_list = self.source.selected.indices
if node_clicked_list and self.production_selected:
vertex_index = node_clicked_list[0]
if vertex_index not in self.vertices_chosen:
self.vertices_chosen.append(vertex_index)
if len(self.vertices_chosen) == self.production_selected.get_vertices_number():
self._apply_production()
def _apply_production(self):
self.production_selected.apply([self.graph.vertices[i] for i in self.vertices_chosen], self.graph)
self.production_selected = None
self.vertices_chosen.clear()
self.dropdown.label = "Productions"
self._graph_initialization()
self.layout.children[0] = row(column(self.dropdown, self.plot), self._create_legend())
self._remove_image()
self._set_hover_tool_and_click_event()
curdoc().clear()
curdoc().add_root(self.layout)
def _set_hover_tool_and_click_event(self):
tooltips = [
("Index", "@index"),
("Edges to", "@edges_to"),
("Label", "@labels")
]
self.plot.add_tools(HoverTool(tooltips=tooltips), TapTool(), BoxSelectTool())
self.plot.renderers.append(self.graph_renderer)
self.plot.select(type=TapTool)
self.plot.on_event(Tap, self._clicking_update)
def _graph_initialization(self):
self.networkx_graph = self._convert_graph()
self.plot = figure(width=800, height=600, x_range=(-1.2, 1.2), y_range=(-1.2, 1.2),
x_axis_location=None, y_axis_location=None, toolbar_location=None,
title="Graph Transformations", background_fill_color="#efefef")
self.plot.grid.grid_line_color = None
self.graph_renderer = from_networkx(self.networkx_graph, nx.spring_layout, scale=1, center=(0, 0))
self.source = self.graph_renderer.node_renderer.data_source
self._create_colors()
self._create_edges_to_lists()
self.graph_renderer.node_renderer.glyph = Circle(size=15, fill_color="colors")
self.graph_renderer.edge_renderer.glyph = MultiLine(line_color="black",
line_alpha=0.8, line_width=1.5)
def _convert_graph(self):
new_graph = nx.Graph()
for vertex in self.graph.vertices:
new_graph.add_node(vertex)
for edge in self.graph.edges:
new_graph.add_edge(edge[0], edge[1])
return new_graph
def run(self):
curdoc().add_root(self.layout)
show(self.layout)