pebble
pebble

Reputation: 31

How do I live update a bokeh chart in a flask app every time the data changes?

If I have a flask app with a couple of charts made from bokeh, how do I update the chart live while its in the browser as new data gets added or changed? I am new to bokeh and read the documentation that I have to start a bokeh server, I still do not understand what I should be adding to my code to make it update.

Upvotes: 1

Views: 1067

Answers (1)

Tony
Tony

Reputation: 8287

This is a Bokeh server app with a callback executed every 1s and data updated every 5s. Looking at the current plot_data length and compering it with last_data_length let us determine when we need to update the plot (code works for Bokeh v1.0.4)

import random, time
from tornado.ioloop import IOLoop
from bokeh.server.server import Server
from bokeh.application import Application
from bokeh.application.handlers.function import FunctionHandler
from bokeh.plotting import figure, ColumnDataSource
from threading import Thread

class BokehApp():
    plot_data = []
    last_data_length = None

    def __init__(self):
        thread = Thread(target = self.startDataAcquisition)
        thread.start()

        io_loop = IOLoop.current()
        server = Server(applications = {'/myapp': Application(FunctionHandler(self.make_document))}, io_loop = io_loop, port = 5001)
        server.start()
        server.show('/myapp')
        io_loop.start()

    def startDataAcquisition(self):
        while True:
            self.plot_data.append({'x': [random.random()], 'y': [random.random()], 'color': [random.choice(['red', 'blue', 'green'])]})
            time.sleep(5)

    def make_document(self, doc):
        source = ColumnDataSource({'x': [], 'y': [], 'color': []})
        fig = figure(title = 'Streaming Circle Plot!', sizing_mode = 'scale_both')
        fig.circle(source = source, x = 'x', y = 'y', color = 'color', size = 10)

        def update():
            if self.last_data_length is not None and self.last_data_length != len(self.plot_data):
                source.stream(self.plot_data[-1])
            self.last_data_length = len(self.plot_data)

        doc.add_root(fig)
        doc.add_periodic_callback(update, 1000)

if __name__ == '__main__':
    app = BokehApp()

Result:

enter image description here

Upvotes: 1

Related Questions