Hi All,
I would like to display the edge weights of a graph network as a bar graph in a subplot
The graph network is constructed in the following manner
import networkx as nx
import plotly.graph_objects as go
from collections import OrderedDict
from sympy.geometry import Point
def distance_finder(s, t):
p1, p2 = Point(s), Point(t)
pmid = p1.midpoint(p2)
return pmid.evalf()
def get_edge_trace(G):
edge_x = []
edge_y = []
edge_z = []
etext = [f'weight{w}' for w in list(nx.get_edge_attributes(G, 'weight').values())]
xtext = [x]
ytext = []
ztext = []
for edge in G.edges():
x0, y0, z0 = G.nodes[edge[0]]['pos']
x1, y1, z1 = G.nodes[edge[1]]['pos']
mid = distance_finder(s=[x0, y0, z0], t=[x1, y1, z1])
xtext.append(mid.x)
ytext.append(mid.y)
ztext.append(mid.z)
edge_x.append(x0)
edge_x.append(x1)
edge_x.append(None)
edge_y.append(y0)
edge_y.append(y1)
edge_y.append(None)
edge_z.append(z0)
edge_z.append(z1)
edge_z.append(None)
edge_trace = go.Scatter3d(
x=edge_x, y=edge_y, z=edge_z,
line=dict(width=0.5, color='#888'),
mode='lines'
)
eweights_trace = go.Scatter3d(x=xtext, y=ytext, z=ztext, mode='text',
marker_size=0.5,
text=[0.45, 0.7, 0.34],
textposition='top center',
hovertemplate='weight: %{text}<extra></extra>')
return edge_trace, eweights_trace
def get_node_trace(G):
node_x = []
node_y = []
node_z = []
for node in G.nodes():
x, y, z = G.nodes[node]['pos']
node_x.append(x)
node_y.append(y)
node_z.append(z)
node_trace = go.Scatter3d(
x=node_x, y=node_y, z=node_z,
mode='markers',
marker_size=12,
#hoverinfo='text', #THIS LINE HAS NO SENSE BECAUSE text WAS NOT DEFINED
marker_color='RoyalBlue',
)
return node_trace
if __name__ == '__main__':
tail = [1, 2, 3]
head = [2, 3, 4]
xpos = [0, 1, 2, 3]
ypos = [0, 0, 0, 0]
zpos = [-1, 0, -9, 10]
w = [1, 2, 3]
v = [.1, 0.2, 0.3]
xpos_ypos_zpos = [(x, y, z) for x, y, z in zip(xpos, ypos, zpos)]
ed_ls = [(x, y) for x, y in zip(tail, head)]
G = nx.OrderedGraph()
G.add_edges_from(ed_ls)
pos = OrderedDict(zip(G.nodes, xpos_ypos_zpos))
edge_w = OrderedDict(zip(G.edges, w))
edge_v = OrderedDict(zip(G.edges, v))
nx.set_node_attributes(G, pos, 'pos')
nx.set_edge_attributes(G, edge_w, 'weight')
nx.set_edge_attributes(G, edge_v, 'value')
# convert to plotly graph
edge_trace, eweights_trace = get_edge_trace(G)
node_trace = get_node_trace(G)
fig = go.Figure(data=[edge_trace, node_trace],
layout=go.Layout(
title='<br>Network graph made with Python',
titlefont_size=16,
showlegend=False,
hovermode='closest',
margin=dict(b=20, l=5, r=5, t=40),
xaxis_visible=False,
yaxis_visible=False)
)
fig.write_html('plot1.html', auto_open=True)
I want to create a subplot that can display the edge weights as a bar graph
Bargraph can be created in the following way
df = pd.DataFrame({'edges': list(G.edges()), 'weight': w})
fig = px.bar(df, x='edges', y='weight')
fig.write_html('plot2.html', auto_open=True)
However, I want to do this interactively. i.e display only the bars of edges that are clicked in plot1.html
.
In a similar question that has been posted here https://stackoverflow.com/questions/60596968/visualizing-time-series-data-of-graph-nodes-in-plotly , it has been suggested to use post_script
post_script = """
gd = document.getElementById('{plot_id}');
gd.on('plotly_click', function(data) {
var pn='',
tn='',
isNodeClick=false;
for (var i=0; i < data.points.length; i++){
pn = data.points[i].pointNumber;
tn = data.points[i].curveNumber;
if(data.points[i].fullData.mode === 'markers') {
isNodeClick = true;
}
};
if (!isNodeClick) return;
var visible = gd.calcdata[pn][0].trace.visible;
const update = {'visible': visible === true ? 'legendonly': true}
Plotly.restyle(gd, update, [pn]);
return false;
});
"""
I would like to know how to modify the above post_script to interactively display the bars corresponding to the edges that are clicked in plot1.html.