Fight with Bokeh and Flask to display data from streaming.
Updating the data source is planned and not controlled by Bokeh (I see that this is done every second).
How to force a graph to be updated (perhaps not the whole page, since there are several graphs in the final version)?
Here is a cut and executable version of the faulty code. Any idea is welcome.
import numpy as np
import pandas as pd
from bokeh.embed import components
from bokeh.plotting import figure
from bokeh.resources import INLINE
from bokeh.models.sources import ColumnDataSource
from flask import Flask, render_template_string
from flask_apscheduler import APScheduler
from apscheduler.triggers.interval import IntervalTrigger
html_template = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
{{ js_resources | safe }}
{{ css_resources | safe }}
</head>
<body>
<div>
{{ plot_div.graph_1 | safe }}
</div>
{{ plot_script | safe }}
</body>
</html>
"""
resources = INLINE
js_resources = resources.render_js()
css_resources = resources.render_css()
app = Flask(__name__)
@app.route("/")
def main_graph():
script, div = components({'graph_1': graph_1.figure,})
return render_template_string(html_template,
js_resources=js_resources,
css_resources=css_resources,
plot_script=script,
plot_div=div)
class Generic3Lines:
def __init__(self, scheduler):
self.data_source = ColumnDataSource()
self.figure = figure()
self.figure.axis.visible = True
self.update_data()
line1 = self.figure.line(y="value_1", line_color="red", x="date_time", source=self.data_source)
line2 = self.figure.line(y="value_2", line_color="blue", x="date_time", source=self.data_source)
line3 = self.figure.line(y="value_3", line_color="green", x="date_time", source=self.data_source)
scheduler.add_job(id="scheduled_update", func=self.update_data, trigger=IntervalTrigger(seconds=1))
def update_data(self):
df = pd.DataFrame(dict(
date_time = range(180),
"value_1" = np.random.random(size=180)*5+5,
"value_2" = np.random.random(size=180)*5+10,
"value_3" = np.random.random(size=180)*5+15,
))
print(df.head(1))
self.data_source = dict(date_time=df["date_time"],
value_1=df["value_1"],
value_2=df["value_2"],
value_3=df["value_3"],
)
scheduler = APScheduler()
scheduler.start()
graph_1 = Generic3Lines(scheduler=scheduler)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5050)
source
share