Created
June 3, 2018 05:07
-
-
Save telegraphic/6e192491af08c0655e106cea5dfc8e0b to your computer and use it in GitHub Desktop.
Example bottle.py app showing how to embed Bokeh plots that update dynamically with AJAX, using AjaxDataSource.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
# app.py -- Example bottle.py app showing how to embed AJAX Bokeh plots that update automatically. | |
""" | |
from bottle import * | |
from bokeh.plotting import figure | |
from bokeh.embed import components | |
from bokeh.resources import CDN | |
from bokeh.models.sources import AjaxDataSource | |
from bokeh.layouts import gridplot | |
import simplejson as json | |
import numpy as np | |
#################### | |
## MAIN WEBSERVER ## | |
#################### | |
@route('/dashboard') | |
def show_dashboard(): | |
""" Generate HTML for main dashboard """ | |
adc_plot = bokeh_adc_plot() | |
bandpass_plot = bokeh_bandpass_plot() | |
return template('dashboard.html', adc_plot=adc_plot, bandpass_plot=bandpass_plot) | |
#################### | |
## AJAX CALLBACKS ## | |
#################### | |
@route('/adc_data/<idx>') | |
@route('/adc_data/<idx>', method='POST') | |
def bokeh_adc_data(idx): | |
""" Return JSON data for ADC RMS plot. | |
Returns JSON data when requested. Used by Bokeh AjaxDataSource """ | |
idx = int(idx) | |
a = np.random.normal(size=1024) * (float(idx) + 1) | |
b = np.random.normal(size=1024) * (float(idx) + 1) | |
pola, bins = np.histogram(a, bins=31, range=(-64, 64)) | |
polb, bins = np.histogram(b, bins=31, range=(-64, 64)) | |
return json.dumps({'bins': list(bins[:-1]), 'pola': list(pola), 'polb': list(polb)}) | |
@route('/bandpass_data/<idx>') | |
@route('/bandpass_data/<idx>', method='POST') | |
def bokeh_bandpass_data(idx): | |
""" Return JSON data for bandpass plot. | |
Returns JSON data when requested. Used by Bokeh AjaxDataSource """ | |
idx = int(idx) | |
pola = np.random.normal(size=1024) * (float(idx) + 1) | |
polb = np.random.normal(size=1024) * (float(idx) + 1) | |
f = np.linspace(1.1, 1.5, 1024) | |
return json.dumps({'f': list(f), 'pola': list(pola), 'polb': list(polb)}) | |
#################### | |
## BOKEH PLOTTING ## | |
#################### | |
def bokeh_adc_plot(): | |
""" Generate ADC RMS bokeh layout. | |
Creates 13x plots in a grid layout. Each plot has a AjaxDataSource that updates automatically. | |
""" | |
n_sources = 13 | |
sources, plots = [], [] | |
for n in range(n_sources): | |
# Create AJAX data source | |
source = AjaxDataSource(data_url='/adc_data/%i' % n, polling_interval=2000, mode='replace') | |
a = np.random.normal(size=1024) * (float(n) + 1) | |
b = np.random.normal(size=1024) * (float(n) + 1) | |
pola, bins = np.histogram(a, bins=31, range=(-64, 64)) | |
polb, bins = np.histogram(b, bins=31, range=(-64, 64)) | |
source.data = dict(bins=bins[:-1], pola=pola, polb=polb) | |
sources.append(source) | |
# Generate bokeh plot | |
plot = figure(plot_height=150, plot_width=150, title=str(n)) | |
plot.line(source=source, x='bins', y='pola') | |
plot.line(source=source, x='bins', y='polb', color='green') | |
plots.append(plot) | |
# Put plots into a grid layout | |
plots.append(None) | |
PP = gridplot([ | |
[plots[ii] for ii in range(0, 7)], | |
[plots[ii] for ii in range(7, 14)] | |
]) | |
# Generate the HTML and javascript required for embedding | |
script, div = components(PP, CDN) | |
return script, div | |
def bokeh_bandpass_plot(): | |
""" Generate Bandpass bokeh layout. | |
Creates 13x plots in a grid layout. Each plot has a AjaxDataSource that updates automatically. | |
""" | |
n_sources = 13 | |
sources, plots = [], [] | |
for n in range(n_sources): | |
source = AjaxDataSource(data_url='/bandpass_data/%i' % n, polling_interval=2000, mode='replace') | |
pola = np.random.normal(size=1024) * (float(n) + 1) | |
polb = np.random.normal(size=1024) * (float(n) + 1) | |
f = np.linspace(1.1, 1.5, 1024) | |
source.data = dict(f=f, pola=pola, polb=polb) | |
sources.append(source) | |
plot = figure(plot_height=150, plot_width=150, title=str(n)) | |
#plot.vbar(source=source, x='x', bottom=0, width=0.5, top='y') | |
plot.line(source=source, x='f', y='pola') | |
plot.line(source=source, x='f', y='polb', color='green') | |
plots.append(plot) | |
plots.append(None) | |
PP = gridplot([ | |
[plots[ii] for ii in range(0, 7)], | |
[plots[ii] for ii in range(7, 14)] | |
]) | |
script, div = components(PP, CDN) | |
return script, div | |
########## | |
## MAIN ## | |
########## | |
if __name__ == '__main__': | |
# Option parsing to allow command line arguments to be parsed | |
from optparse import OptionParser | |
p = OptionParser() | |
p.set_usage('app.py [options]') | |
p.set_description(__doc__) | |
p.add_option("-i", "--hostip", dest="hostip", type="string", default="0.0.0.0", | |
help="change host IP address to run server. Default is localhost (127.0.0.1)") | |
p.add_option("-p", "--hostport", dest="hostport", type="int", default=8888, | |
help="change host port for server. Default is 8888") | |
(options, args) = p.parse_args(sys.argv[1:]) | |
hostip = options.hostip | |
hostport = options.hostport | |
# Development mode | |
debug(True) | |
# Start bottle server | |
# See: http://bottlepy.org/docs/dev/tutorial_app.html#server-setup | |
run(host=hostip, port=hostport, reloader=True, server=PasteServer) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<!-- Bokeh includes--> | |
<link rel="stylesheet" href="http://cdn.pydata.org/bokeh/release/bokeh-0.12.13.min.css" type="text/css" /> | |
<script type="text/javascript" src="http://cdn.pydata.org/bokeh/release/bokeh-0.12.13.min.js"></script> | |
</head> | |
<body> | |
<div> | |
<h1>ADC RMS</h1> | |
{{!adc_plot[1]}} | |
</div> | |
<div> | |
<h1>Bandpass</h1> | |
{{!bandpass_plot[1]}} | |
</div> | |
{{!adc_plot[0]}} | |
{{!bandpass_plot[0]}} | |
</body> | |
</html> |
Great relevant post for Flask: https://davidhamann.de/2018/02/11/integrate-bokeh-plots-in-flask-ajax/
I was trying to run this to get a working example. If I go to the localhost and port I see a Jupyter Authentication page, which was not what I was expecting. Can you please confirm this should not be what I see. Thanks!
Sounds like you have a jupyterhub server running on that port already. You'll need to stop jupyterhub, or use the -p
option to select a different port.
PS: I've been using https://plotly.com/dash/ for my most recent project, which might be work checking out if you're not tied to bokeh + flask.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
NOTE: the dashboard template HTML file must be in a subdirectory,
views/dashboard.html
.