Hi There,
Ive been trying to serve up a dynamic network graph, working with bokeh has been great and I’ve made some progress…however the graph only updates while the mouse is actually moving around over the graph.
At this stage I’m just using curdoc().add_periodic_callback(update, 100) and generating some mock data in the callback function, then calling ColumnDataSource.stream(new_data, rollover) to perform the update.
Code:
from bokeh.palettes import Spectral8,Spectral4
from bokeh.io import curdoc
from bokeh.models import ColumnDataSource, GraphRenderer, StaticLayoutProvider, Oval, Circle, MultiLine, BoxSelectTool, TapTool, HoverTool
from bokeh.models.graphs import NodesAndLinkedEdges, EdgesAndLinkedNodes
from bokeh.plotting import figure
import random
number_nodes = 100
N = number_nodes
node_indices = list(range(N))
node_hover = HoverTool()
node_hover.tooltips = '''
Zone ID: $index <br>
Occupants: $occupants <br>
Dwell Time: $dwell_time <br>
'''
plot = figure(title="Network Demo", x_range=(0,11), y_range=(0, 11), tools=[node_hover], width=800, height=800)
plot.toolbar.logo = None
plot.axis.visible = False
plot.xgrid.grid_line_color = None
plot.ygrid.grid_line_color = None
plot.background_fill_color = None
plot.background_fill_alpha = 0.0
graph = GraphRenderer()
node_source = ColumnDataSource(data=dict(index=node_indices, occupants=node_indices, dwell_time=node_indices, name=node_indices))
graph.node_renderer.data_source.data = node_source.data
plot.add_tools(HoverTool(tooltips=None))
graph.node_renderer.glyph = Circle(size=15, fill_color=Spectral4[0])
graph.node_renderer.selection_glyph = Circle(size=15, fill_color=Spectral4[2])
graph.node_renderer.hover_glyph = Circle(size=15, fill_color=Spectral4[1])
graph.edge_renderer.glyph = MultiLine(line_color="#CCCCCC", line_alpha=0.8, line_width=5)
graph.edge_renderer.selection_glyph = MultiLine(line_color=Spectral4[2], line_width=5)
graph.edge_renderer.hover_glyph = MultiLine(line_color=Spectral4[1], line_width=5)
graph.selection_policy = NodesAndLinkedEdges()
graph.inspection_policy = EdgesAndLinkedNodes()
edge_source = ColumnDataSource(data=dict(start=[0],end=[44], xs=[[1,5]], ys=[[1,5]]))
graph.edge_renderer.data_source.data = edge_source.data
### start of layout code
y_list = []
x_list = []
for y in range(10):
for x in range(10):
y_list.append(y + 1)
x_list.append(x + 1)
graph_layout = dict(zip(node_indices, zip(x_list, y_list)))
graph.layout_provider = StaticLayoutProvider(graph_layout=graph_layout)
plot.renderers.append(graph)
def update():
x_val = random.randint(1,10)
y_val = random.randint(1,10)
start_val = random.randint(1,10)
end_node = (10 * x_val) - 10 + (y_val - 1)
node_data = dict(start=[start_val], end=[end_node],xs=[[start_val,x_val]], ys=[[start_val,y_val]])
edge_source.stream(node_data, rollover=8)
graph.edge_renderer.data_source.data = edge_source.data
curdoc().add_periodic_callback(update, 100)
curdoc().add_root(plot)
``
Wondering if anyone has any pointers on what I’m missing
Thanks
Grant