I'm trying to get separate hover tooltips for nodes and edges in Bokeh, but haven't been able to get it to work. Could someone point out what I'm doing wrong? I believe the code should look something like this:
from bokeh.io import show, output_notebook
from bokeh.models import Plot, Range1d, MultiLine, Circle, HoverTool
from bokeh.models.graphs import from_networkx, NodesAndLinkedEdges, EdgesAndLinkedNodes
import networkx as nx
output_notebook()
# Generate data
G = nx.karate_club_graph()
nx.set_edge_attributes(G, nx.edge_betweenness_centrality(G), "betweenness_centrality")
# Setup plot
plot = Plot(plot_width=400, plot_height=400,
x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1))
graph_renderer = from_networkx(G, nx.spring_layout, scale=1, center=(0, 0))
graph_renderer.node_renderer.glyph = Circle(size=15)
graph_renderer.edge_renderer.glyph = MultiLine(line_alpha=0.8, line_width=1)
plot.renderers.append(graph_renderer)
# Add hover
node_hover_tool = HoverTool(renderers=[graph_renderer.node_renderer],
tooltips=[("index", "@index"), ("club", "@club")])
edge_hover_tool = HoverTool(renderers=[graph_renderer.edge_renderer],
tooltips=[("betweenness_centrality", "@betweenness_centrality")],
line_policy="interp")
plot.add_tools(node_hover_tool, edge_hover_tool)
# Show
show(plot)
But I don't see any hover over with this. I've tried a few things to work around this:
renderers
argument, I can get some hover over, but not specific to the glyphs I want.renderers
argument from both HoverTool
s, I'm able to get correct tooltips on the nodes along with a betweenness_centrality: ??
renderers
argument from both HoverTool
s and add graph_renderer.inspection_policy = NodesAndLinkedEdges()
, I get correct tooltips on the nodesrenderers
argument from both HoverTool
s and add graph_renderer.inspection_policy = EdgesAndLinkedNodes()
, I get correct tooltips on the edgesI believe this question was asked before on the google group here, but didn't get an answer.
Thanks for any help!
So, we construct our networks differently, but I just solved this problem with one of my Bokeh rendered networks from networkx.
The way that I did it was by generating dataframes with my desired networkx data by using the lines_source approach outlined on another question here, which gives you:
....
plot = figure(
plot_width=1100, plot_height=700,
tools=['tap','box_zoom', 'reset']
) # This is the size of the widget designed.
# This function sets the color of the nodes, but how to set based on the
# name of the node?
r_circles = plot.circle(
'x', 'y', source=nodes_source, name= "Node_list",
size="_size_", fill_color="_color_", level = 'overlay',
)
hover = HoverTool(
tooltips=[('Name', '@name'),('Members','@Members')],
renderers=[r_circles]
) # Works to render only the nodes tooltips
def get_edges_specs(_network, _layout):
d = dict(xs=[], ys=[], alphas=[],from_node=[],to_node=[])
weights = [d['weight'] for u, v, d in _network.edges(data=True)]
max_weight = max(weights)
calc_alpha = lambda h: 0.1 + 0.6 * (h / max_weight)
for u, v, data in _network.edges(data=True):
d['xs'].append([_layout[u][0], _layout[v][0]])
d['from_node'].append(u)
d['to_node'].append(v)
d['ys'].append([_layout[u][1], _layout[v][1]])
d['alphas'].append(calc_alpha(data['weight']))
return d
lines_source = ColumnDataSource(get_edges_specs(network, layout))
r_lines = plot.multi_line(
'xs', 'ys',
line_width=1.5, alpha='alphas', color='navy',
source=lines_source
) # This function sets the color of the edges
Then I generated a hover tool to display the edge information I wanted, so in my case I wanted to know the 'from node' attribute. I also wanted to give it a lofty name, so the tooltip will render "Whered_ya_come_from"
hover2 = HoverTool(
tooltips=[('Whered_ya_come_from','@from_node')],
renderers=[r_lines]
)
And then the only difference between how we implement it is that you try to do it as a single addition to the plot, whereas I plot them one after the other.
plot.tools.append(hover1)
# done to append the tool at the end because it has a problem getting
# rendered, as it depended on the nodes being rendered first.
plot.tools.append(hover2)
From there, you can export it or render it into an HTML file (my preferred method).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With