Hi all,
I’m making a network visualization app, and I’m hoping to implement a PointDraw stream on the network (only for drag/drop purposes–not for adding additional nodes). I have gotten this to work for the graph.nodes element of the plot, but I’m struggling to figure out how to also get the graph edgepaths and labels to update with the node positions. Below is my code that successfully updates the node locations.
import pandas as pd
import numpy as np
import itertools
import holoviews as hv
import networkx as nx
hv.extension('bokeh')
# define some test nodes/edges
test_nodes = pd.DataFrame([[50.,],
[5.,],
[100.,],
[20.,],
[75.,],
[1.,]], columns = ['node score'])
e = np.array(list(itertools.combinations(test_nodes.index, 2)))
test_edges = pd.DataFrame(np.vstack([e.T, np.random.uniform(0, 1, len(e))]).T, columns = ['source', 'target', 'edge score'])
# make the graph, adding columns as node attributes
g = nx.Graph()
g.add_nodes_from(test_nodes.apply(lambda x: (x.name, x.to_dict()), axis=1).values.tolist())
g.add_edges_from(test_edges.apply(lambda x: (x['source'], x['target'], x.to_dict()), axis=1).values.tolist())
# make an hv.Graph from the networkx graph
graph = hv.Graph.from_networkx(g, nx.circular_layout)
labels = hv.Labels(graph.nodes.data, ['x', 'y'], 'index')
# define PointDraw tool (NOTE--this only works with the source set to graph.nodes)
draw = hv.streams.PointDraw(source=graph.nodes, add=False, drag=True)
(graph.edgepaths*(graph.nodes.opts(color='white'))*labels).opts(active_tools=['point_draw'])
I suspect that successfully implementing this will involve linking columns in graph.nodes.data to the graph.edgepaths, but my attempts at this have not been successful. Hopefully someone here can help me out!
Thanks!!
====================== UPDATE ===================
I just discovered the CurveEdit stream, which seems to provide the edge movement functionality that I need. I can now individually move the nodes and edgepaths with the following code–however, I need to be able to link the CurveEdit and PointDraw stream objects to the same values. How can I accomplish this?
# define some test nodes/edges
test_nodes = pd.DataFrame([[50.,],
[5.,],
[100.,],
[20.,],
[75.,],
[1.,]], columns = ['node score'])
e = np.array(list(itertools.combinations(test_nodes.index, 2)))
test_edges = pd.DataFrame(np.vstack([e.T, np.random.uniform(0, 1, len(e))]).T, columns = ['source', 'target', 'edge score'])
# make the graph, adding columns as node attributes
G = nx.Graph()
G.add_nodes_from(test_nodes.apply(lambda x: (x.name, x.to_dict()), axis=1).values.tolist())
G.add_edges_from(test_edges.apply(lambda x: (x['source'], x['target'], x.to_dict()), axis=1).values.tolist())
# make an hv.Graph from the networkx graph
graph = hv.Graph.from_networkx(G, nx.circular_layout)
labels = hv.Labels(graph.nodes.data, ['x', 'y'], 'index')
curve = hv.Curve(graph.edgepaths.columns())
pt_edit = hv.streams.PointDraw(source=graph.nodes, data=graph.nodes.columns(), add=False)
cv_edit = hv.streams.CurveEdit(source=curve, data=curve.columns(),)
(curve*graph.nodes).opts(xlim=(-1.3, 1.3), ylim=(-1.3, 1.3))