Alex Poca
Alex Poca

Reputation: 2566

Bokeh+Flask: Multiple AjaxDataSource calls

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

Answers (1)

Eugene Pakhomov
Eugene Pakhomov

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

Related Questions