Reputation: 2566
A Bokeh object is a figure that shows 3 indipendent lines.
Data are streamed. An AjaxDataSource call updates the data every 5 seconds reading the last ones from a database.
This is the stripped down class:
class Graph:
def __init__(self):
data_source = AjaxDataSource(data=dict(date_time=[],
value_1=[],
value_2=[],
value_3=[]),
data_url="/data",
polling_interval=5000)
line1 = self.figure.line(x="date_time", y="value_1", source=data_source)
line2 = self.figure.line(x="date_time", y="value_2", source=data_source)
line3 = self.figure.line(x="date_time", y="value_3", source=data_source)
app.add_url_rule("/data", "/data", self.serve, methods=['GET', 'OPTIONS', 'POST'])
def serve(self):
# load data from db and return JSON
...
return jsonify(
date_time= da.df["Date_Time"].tolist(),
value_1=da.df["Value1"].tolist(),
value_2=da.df["Value2"].tolist(),
value_3=da.df["Value3"].tolist()
)
date_time
is the common x-axis, value_1
is for line 1, value_2
for line 2, value_3
for line 3.
The problem
Why is AjaxDataSource
called 3 times (they are a few milliseconds apart, then the triple reading is done again after 5 seconds) instead of only once every 5 seconds?
I believed that AjaxDataSource fills dynamically data_source.data
every 5 seconds and then, after they have been read, the 3 lines read these "now static" data.
Workaround?
Is there a way to read the data using AjaxDataSource, transfer automatically the data into a ColumnDataSource and use this as a "static" data source?
Or am I missing something important here?
Upvotes: 0
Views: 572
Reputation: 10697
The issue is that each glyph that has a remote data source attached to it, tries to initialize the data source. In the case of AjaxDataSource
, it doesn't check for previous initializations.
I've opened an issue for it: https://github.com/bokeh/bokeh/issues/6736
A temporary workaround that you could try:
Bokeh.require('models/sources/ajax_data_source').AjaxDataSource.prototype.setup = function () {
this.get_data(this.mode);
if (this.polling_interval && this.interval == null) {
return this.interval = setInterval(this.get_data, this.polling_interval, this.mode, this.max_size, this.if_modified);
}
}
Make sure that this code is run right after Bokeh is included in your page, but before it initializes its documents. How to do it depends on how you embed Bokeh.
Upvotes: 1