Skip to content

Commit 2dcbf62

Browse files
committed
add community coloring
1 parent 0d3b20a commit 2dcbf62

File tree

2 files changed

+52
-38
lines changed

2 files changed

+52
-38
lines changed

graph/graph_logic.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,32 @@ class ConversionArgs(NamedTuple):
1717
resolution: float = 1.0
1818
community_iters: int = 50
1919

20+
21+
# https://stackoverflow.com/questions/470690/how-to-automatically-generate-n-distinct-colors
22+
GRAPH_COLORS = [
23+
"#FFB300", # Vivid Yellow
24+
"#803E75", # Strong Purple
25+
"#FF6800", # Vivid Orange
26+
"#A6BDD7", # Very Light Blue
27+
"#C10020", # Vivid Red
28+
"#CEA262", # Grayish Yellow
29+
"#817066", # Medium Gray
30+
# The following don't work well for people with defective color vision
31+
"#007D34", # Vivid Green
32+
"#F6768E", # Strong Purplish Pink
33+
"#00538A", # Strong Blue
34+
"#FF7A5C", # Strong Yellowish Pink
35+
"#53377A", # Strong Violet
36+
"#FF8E00", # Vivid Orange Yellow
37+
"#B32851", # Strong Purplish Red
38+
"#F4C800", # Vivid Greenish Yellow
39+
"#7F180D", # Strong Reddish Brown
40+
"#93AA00", # Vivid Yellowish Green
41+
"#593315", # Deep Yellowish Brown
42+
"#F13A13", # Vivid Reddish Orange
43+
"#232C16", # Dark Olive Green
44+
]
45+
2046
def raw_graph_to_igraph(raw: GraphData, args: ConversionArgs) -> Tuple[igraph.Graph, igraph.VertexClustering]:
2147
""" Converts a graph (whether a call graph or a graph from association rules)
2248
into igraph representation, optionally constricting the graph's hierarchy(combining nodes and edges
@@ -85,6 +111,7 @@ def raw_graph_to_igraph(raw: GraphData, args: ConversionArgs) -> Tuple[igraph.Gr
85111
resolution_parameter=args.resolution,
86112
objective_function='modularity')
87113
graph.vs["community"] = clustering.membership
114+
graph.vs["color"] = [GRAPH_COLORS[c % len(GRAPH_COLORS)] for c in clustering.membership]
88115

89116
return graph, clustering
90117

viz/graph.py

Lines changed: 25 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@
8383
"selector": 'node',
8484
'style': {
8585
"opacity": 0.65,
86-
'z-index': 9999
86+
'z-index': 9999,
87+
'background-color': 'data(color)',
88+
'color': 'data(color)'
8789
}
8890
},
8991
{
@@ -152,6 +154,16 @@
152154
"font-size": 12,
153155
'z-index': 9999
154156
}
157+
},
158+
{
159+
'selector': '.selneighbor',
160+
"style": {
161+
"label": "data(label)",
162+
"color": "black",
163+
"font-size": 12,
164+
'z-index': 9999
165+
166+
}
155167
}
156168
]
157169

@@ -302,9 +314,10 @@ def generate_elements(graph_active, graph_params, nodeData, elements, expansion_
302314
print("Graph is being reloaded")
303315
return [igraph_vert_to_cyto(graph, graph.vs[0], classes=["genesis"])]
304316

317+
do_expand = True
305318
# If the node has already been expanded, we don't expand it again
306319
if nodeData.get(f'expanded-{expansion_mode}'):
307-
return elements
320+
do_expand = False
308321

309322
# This retrieves the currently selected element, and tag it as expanded
310323
for element in elements:
@@ -314,46 +327,20 @@ def generate_elements(graph_active, graph_params, nodeData, elements, expansion_
314327

315328
dir = "in" if expansion_mode == "followers" else "out"
316329
neigh_nodes = graph.neighbors(nodeData['id'], dir)
330+
neigh_names = set(graph.vs[ix]["name"] for ix in neigh_nodes)
317331
neigh_edges = graph.incident(nodeData['id'], dir)
318332
node_class = "followerNode" if dir == "in" else "followingNode"
319333
edge_class = "followerEdge" if dir == "in" else "followingEdge"
320334

335+
if do_expand:
336+
elements.extend(igraph_vert_to_cyto(graph, graph.vs[node_ix], classes=[node_class, "selneighbor"]) for node_ix in neigh_nodes)
337+
elements.extend(igraph_edge_to_cyto(graph, graph.es[edge_ix], classes=[edge_class, "selneighbor"]) for edge_ix in neigh_edges)
321338

322-
323-
elements.extend(igraph_vert_to_cyto(graph, graph.vs[node_ix], classes=[node_class]) for node_ix in neigh_nodes)
324-
elements.extend(igraph_edge_to_cyto(graph, graph.es[edge_ix], classes=[edge_class]) for edge_ix in neigh_edges)
339+
for element in elements:
340+
el_id = element.get('data').get('id')
341+
if el_id is None:
342+
continue
343+
if el_id not in neigh_names:
344+
element["classes"] = element["classes"].replace("selneighbor", "")
325345
return elements
326346

327-
328-
# if expansion_mode == 'followers':
329-
330-
# followers_nodes = followers_node_di.get(nodeData['id'])
331-
# followers_edges = followers_edges_di.get(nodeData['id'])
332-
333-
# if followers_nodes:
334-
# for node in followers_nodes:
335-
# node['classes'] = 'followerNode'
336-
# elements.extend(followers_nodes)
337-
338-
# if followers_edges:
339-
# for follower_edge in followers_edges:
340-
# follower_edge['classes'] = 'followerEdge'
341-
# elements.extend(followers_edges)
342-
343-
# elif expansion_mode == 'following':
344-
345-
# following_nodes = following_node_di.get(nodeData['id'])
346-
# following_edges = following_edges_di.get(nodeData['id'])
347-
348-
# if following_nodes:
349-
# for node in following_nodes:
350-
# if node['data']['id'] != genesis_node['data']['id']:
351-
# node['classes'] = 'followingNode'
352-
# elements.append(node)
353-
354-
# if following_edges:
355-
# for follower_edge in following_edges:
356-
# follower_edge['classes'] = 'followingEdge'
357-
# elements.extend(following_edges)
358-
359-
# return elements

0 commit comments

Comments
 (0)