Bokeh Server - Dynamic updates only occur while my mouse is moving??

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

Hi,

There is a lot of extraneous stuff going on in that script. After paring it down a bit I think there are multiple things going on. I think the order and way you are "putting the building blocks together" is not correct (i.e. you are setting the data source on the default node_renderer... then throwing it away by replacing the node_renderer later). In general we try to steer people towards the higher level bokeh.plotting API so that the building blocks are more easily assembled. The latest release just added Figure.graph to help with this but it can probably use more refinement. You might want to check it out.

However, I also think there are some bugs. The graph stuff is the first ever "multi-data-source" type glyph, and I expect there will be some issue to hammer out beyond static plots, because of the added coordination needs. Below is the pared down example I made. I would have expected this to work but it didn't, so I'd suggest creating a GH bug report with this code and a link to this thread.

Thanks

Bryan

from bokeh.io import curdoc
from bokeh.models import GraphRenderer, StaticLayoutProvider, Circle
from bokeh.palettes import Spectral4
from bokeh.plotting import figure

import random

N = 100
node_indices = list(range(N))

plot = figure(title="Network Demo", x_range=(0, 11), y_range=(0, 11), tools="", width=800, height=800)

graph = GraphRenderer()

graph.node_renderer.glyph = Circle(size=15, fill_color=Spectral4[0])
graph.node_renderer.data_source.data = dict(index=node_indices)

graph.edge_renderer.data_source.data = dict(start=[0], end=[44])

# 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():
    print("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)
    new_data = dict(start=[start_val], end=[end_node])
    graph.edge_renderer.data_source.stream(new_data, rollover=8)

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

curdoc().add_periodic_callback(update, 200)
curdoc().add_root(plot)

···

On Sep 17, 2017, at 06:19, [email protected] wrote:

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

--
You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/2caf3d2b-93c1-4362-bd72-a8bc4b7c5d8c%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

Hi Bryan,
Thanks for taking the time to look in to this,

Cudos to you and your team on such an awesome library,

I appreciate how much more concise your example is, I had cobbled my code by ‘frankenstein-ing’ a tweaking a few examples together :slight_smile:

I will definitely check out the Figure.graph API documentation as I didn’t see that before (FYI graph doesn’t appear with the other methods linked at the top of bokeh.plotting — Bokeh 3.3.2 Documentation)

I will also be sure to work through and create an issue on GH if I stumble across anything.

Thanks once again

Kind regards

Grant

···

On Monday, September 18, 2017 at 1:19:42 AM UTC+10, Bryan Van de ven wrote:

Hi,

There is a lot of extraneous stuff going on in that script. After paring it down a bit I think there are multiple things going on. I think the order and way you are “putting the building blocks together” is not correct (i.e. you are setting the data source on the default node_renderer… then throwing it away by replacing the node_renderer later). In general we try to steer people towards the higher level bokeh.plotting API so that the building blocks are more easily assembled. The latest release just added Figure.graph to help with this but it can probably use more refinement. You might want to check it out.

However, I also think there are some bugs. The graph stuff is the first ever “multi-data-source” type glyph, and I expect there will be some issue to hammer out beyond static plots, because of the added coordination needs. Below is the pared down example I made. I would have expected this to work but it didn’t, so I’d suggest creating a GH bug report with this code and a link to this thread.

Thanks

Bryan

from bokeh.io import curdoc

from bokeh.models import GraphRenderer, StaticLayoutProvider, Circle

from bokeh.palettes import Spectral4

from bokeh.plotting import figure

import random

N = 100

node_indices = list(range(N))

plot = figure(title=“Network Demo”, x_range=(0, 11), y_range=(0, 11), tools=“”, width=800, height=800)

graph = GraphRenderer()

graph.node_renderer.glyph = Circle(size=15, fill_color=Spectral4[0])

graph.node_renderer.data_source.data = dict(index=node_indices)

graph.edge_renderer.data_source.data = dict(start=[0], end=[44])

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():

print("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)

new_data = dict(start=[start_val], end=[end_node])

graph.edge_renderer.data_source.stream(new_data, rollover=8)

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

curdoc().add_periodic_callback(update, 200)

curdoc().add_root(plot)

On Sep 17, 2017, at 06:19, [email protected] wrote:

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


You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/2caf3d2b-93c1-4362-bd72-a8bc4b7c5d8c%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.