首页 > 解决方案 > Color network graph node lines on click in Bokeh, Python

问题描述

Using the following code with Bokeh server, I am currently able to color a selected node in my network graph pink by selecting it from a dropdown.

What I'd like to do is extend the code to do is allow me to perform the same highlight callback, when a node is clicked, using Taptool() or some other method. Is this possible?

import networkx as nx
from bokeh.models.graphs import from_networkx
from bokeh.models import Range1d, MultiLine, Circle, TapTool, Plot
from bokeh.plotting import figure
from bokeh.io import curdoc
from bokeh.layouts import row
from bokeh.models.widgets import Dropdown


def choose_node_outline_colors(node_clicked):
    outline_colors = []
    for node in G.nodes():
        if str(node) == node_clicked:
            outline_colors.append('pink')
        else:
            outline_colors.append('black')
    return outline_colors

def update_node_highlight(attrname, old, new):
    node_clicked = dropdown.value
    data['line_color'] = choose_node_outline_colors(node_clicked)

G = nx.karate_club_graph()

plot = Plot(plot_width=400, plot_height=400,
            x_range=Range1d(-1.1,1.1), y_range=Range1d(-1.1,1.1))
graph = from_networkx(
    G,
    nx.circular_layout,
    scale=1,
    center=(0,0)
)

# Create nodes and edges
data = graph.node_renderer.data_source.data
data['line_color'] = choose_node_outline_colors('1')
graph.node_renderer.glyph = Circle(size=10, line_color="line_color")
graph.edge_renderer.glyph = MultiLine(line_alpha=1.6, line_width=0.5)

# Add tap tool
plot.add_tools(TapTool())

plot.renderers.append(graph)

# Dropdown menu to highlight a particular node
dropdown = Dropdown(label="Highlight Node", menu=list(map(str, list(G.nodes()))))
dropdown.on_change('value', update_node_highlight)
dropdown.value = '1'

curdoc().add_root(row(plot, dropdown))

enter image description here

标签: pythondata-visualizationbokeh

解决方案


Ok, I managed to find a solution using TapTool and making use of the node index:

import networkx as nx
from bokeh.models.graphs import from_networkx
from bokeh.models import Range1d, MultiLine, Circle, TapTool, Plot, HoverTool, BoxSelectTool
from bokeh.plotting import figure
from bokeh.io import curdoc
from bokeh.layouts import row
from bokeh.models.widgets import Dropdown
from bokeh.events import Tap


def choose_node_outline_colors(nodes_clicked):
    outline_colors = []
    for node in G.nodes():
        if str(node) in nodes_clicked:
            outline_colors.append('pink')
        else:
            outline_colors.append('black')
    return outline_colors


def update_node_highlight(event):
    nodes_clicked_ints = source.selected.indices
    nodes_clicked = list(map(str, nodes_clicked_ints))
    source.data['line_color'] = choose_node_outline_colors(nodes_clicked)


G = nx.karate_club_graph()

plot = Plot(plot_width=400, plot_height=400,
            x_range=Range1d(-1.1,1.1), y_range=Range1d(-1.1,1.1))
graph = from_networkx(
    G,
    nx.circular_layout,
    scale=1,
    center=(0,0)
)

# Create nodes and edges
source = graph.node_renderer.data_source
source.data['line_color'] = choose_node_outline_colors('1')
graph.node_renderer.glyph = Circle(size=10, line_color="line_color")
graph.edge_renderer.glyph = MultiLine(line_alpha=1.6, line_width=0.5)

# Add tap tool
TOOLTIPS = [
    ("Index", "@index"),
]
plot.add_tools(HoverTool(tooltips=TOOLTIPS), TapTool(), BoxSelectTool())

plot.renderers.append(graph)

taptool = plot.select(type=TapTool)

plot.on_event(Tap, update_node_highlight)

curdoc().add_root(plot)

推荐阅读