Spaces:
Running
Running
Add labels and edge coloring to graph visualizations.
Browse files
lynxkite-graph-analytics/src/lynxkite_graph_analytics/lynxkite_ops.py
CHANGED
@@ -325,7 +325,13 @@ def _map_color(value):
|
|
325 |
|
326 |
|
327 |
@op("Visualize graph", view="visualization")
|
328 |
-
def visualize_graph(
|
|
|
|
|
|
|
|
|
|
|
|
|
329 |
nodes = graph.dfs["nodes"].copy()
|
330 |
if color_nodes_by:
|
331 |
nodes["color"] = _map_color(nodes[color_nodes_by])
|
@@ -357,14 +363,18 @@ def visualize_graph(graph: Bundle, *, color_nodes_by: ops.NodeAttribute = None):
|
|
357 |
curveness = 0.3
|
358 |
nodes = nodes.to_records()
|
359 |
edges = graph.dfs["edges"].drop_duplicates(["source", "target"])
|
|
|
|
|
360 |
edges = edges.to_records()
|
361 |
v = {
|
362 |
"animationDuration": 500,
|
363 |
"animationEasingUpdate": "quinticInOut",
|
|
|
364 |
"series": [
|
365 |
{
|
366 |
"type": "graph",
|
367 |
-
|
|
|
368 |
"lineStyle": {
|
369 |
"color": "gray",
|
370 |
"curveness": curveness,
|
@@ -375,6 +385,7 @@ def visualize_graph(graph: Bundle, *, color_nodes_by: ops.NodeAttribute = None):
|
|
375 |
"width": 10,
|
376 |
},
|
377 |
},
|
|
|
378 |
"data": [
|
379 |
{
|
380 |
"id": str(n.id),
|
@@ -383,11 +394,24 @@ def visualize_graph(graph: Bundle, *, color_nodes_by: ops.NodeAttribute = None):
|
|
383 |
# Adjust node size to cover the same area no matter how many nodes there are.
|
384 |
"symbolSize": 50 / len(nodes) ** 0.5,
|
385 |
"itemStyle": {"color": n.color} if color_nodes_by else {},
|
|
|
|
|
|
|
|
|
|
|
386 |
}
|
387 |
for n in nodes
|
388 |
],
|
389 |
"links": [
|
390 |
-
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
391 |
],
|
392 |
},
|
393 |
],
|
|
|
325 |
|
326 |
|
327 |
@op("Visualize graph", view="visualization")
|
328 |
+
def visualize_graph(
|
329 |
+
graph: Bundle,
|
330 |
+
*,
|
331 |
+
color_nodes_by: ops.NodeAttribute = None,
|
332 |
+
label_by: ops.NodeAttribute = None,
|
333 |
+
color_edges_by: ops.EdgeAttribute = None,
|
334 |
+
):
|
335 |
nodes = graph.dfs["nodes"].copy()
|
336 |
if color_nodes_by:
|
337 |
nodes["color"] = _map_color(nodes[color_nodes_by])
|
|
|
363 |
curveness = 0.3
|
364 |
nodes = nodes.to_records()
|
365 |
edges = graph.dfs["edges"].drop_duplicates(["source", "target"])
|
366 |
+
if color_edges_by:
|
367 |
+
edges["color"] = _map_color(edges[color_edges_by])
|
368 |
edges = edges.to_records()
|
369 |
v = {
|
370 |
"animationDuration": 500,
|
371 |
"animationEasingUpdate": "quinticInOut",
|
372 |
+
"tooltip": {"show": True},
|
373 |
"series": [
|
374 |
{
|
375 |
"type": "graph",
|
376 |
+
# Mouse zoom/panning is disabled for now. It interacts badly with ReactFlow.
|
377 |
+
# "roam": True,
|
378 |
"lineStyle": {
|
379 |
"color": "gray",
|
380 |
"curveness": curveness,
|
|
|
385 |
"width": 10,
|
386 |
},
|
387 |
},
|
388 |
+
"label": {"position": "top", "formatter": "{b}"},
|
389 |
"data": [
|
390 |
{
|
391 |
"id": str(n.id),
|
|
|
394 |
# Adjust node size to cover the same area no matter how many nodes there are.
|
395 |
"symbolSize": 50 / len(nodes) ** 0.5,
|
396 |
"itemStyle": {"color": n.color} if color_nodes_by else {},
|
397 |
+
"label": {"show": label_by is not None},
|
398 |
+
"name": getattr(n, label_by, None) if label_by else None,
|
399 |
+
"value": getattr(n, color_nodes_by, None)
|
400 |
+
if color_nodes_by
|
401 |
+
else None,
|
402 |
}
|
403 |
for n in nodes
|
404 |
],
|
405 |
"links": [
|
406 |
+
{
|
407 |
+
"source": str(r.source),
|
408 |
+
"target": str(r.target),
|
409 |
+
"lineStyle": {"color": r.color} if color_edges_by else {},
|
410 |
+
"value": getattr(r, color_edges_by, None)
|
411 |
+
if color_edges_by
|
412 |
+
else None,
|
413 |
+
}
|
414 |
+
for r in edges
|
415 |
],
|
416 |
},
|
417 |
],
|