0
votes

I want my Bokeh sliders app situated inside a flask app.

Here's the code for my Bokeh app, taken directly from Bokeh's sliders.py example:

Scrub the sliders to change the properties of the ``sin`` curve, or
type into the title text box to update the title of the plot.
Use the ``bokeh serve`` command to run the example by executing:
    bokeh serve sliders.py
at your command prompt. Then navigate to the URL
    http://localhost:5006/sliders
in your browser.
'''
import numpy as np

from bokeh.io import curdoc
from bokeh.layouts import row, column
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import Slider, TextInput
from bokeh.plotting import figure

# Set up data
N = 200
x = np.linspace(0, 4*np.pi, N)
y = np.sin(x)
source = ColumnDataSource(data=dict(x=x, y=y))


# Set up plot
plot = figure(plot_height=400, plot_width=400, title="my sine wave",
              tools="crosshair,pan,reset,save,wheel_zoom",
              x_range=[0, 4*np.pi], y_range=[-2.5, 2.5])

plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)


# Set up widgets
text = TextInput(title="title", value='my sine wave')
offset = Slider(title="offset", value=0.0, start=-5.0, end=5.0, step=0.1)
amplitude = Slider(title="amplitude", value=1.0, start=-5.0, end=5.0, step=0.1)
phase = Slider(title="phase", value=0.0, start=0.0, end=2*np.pi)
freq = Slider(title="frequency", value=1.0, start=0.1, end=5.1, step=0.1)


# Set up callbacks
def update_title(attrname, old, new):
    plot.title.text = text.value

text.on_change('value', update_title)

def update_data(attrname, old, new):

    # Get the current slider values
    a = amplitude.value
    b = offset.value
    w = phase.value
    k = freq.value

    # Generate the new curve
    x = np.linspace(0, 4*np.pi, N)
    y = a*np.sin(k*x + w) + b

    source.data = dict(x=x, y=y)

for w in [offset, amplitude, phase, freq]:
    w.on_change('value', update_data)


# Set up layouts and add to document
inputs = column(text, offset, amplitude, phase, freq)

curdoc().add_root(row(inputs, plot, width=800))
curdoc().title = "Sliders"

Here's my main.py code, which launches the Flask app.

from flask import Flask, render_template

from bokeh.client import pull_session
from bokeh.embed import server_session

app = Flask(__name__)

@app.route('/', methods=['GET'])
def bkapp_page():

    # pull a new session from a running Bokeh server
    with pull_session(url="http://localhost:5006/sliders") as session:

        # update or customize that session
        session.document.roots[0].children[1].title.text = "Special Sliders For A Specific User!"

        # generate a script to load the customized session
        script = server_session(session_id=session.id, url='http://localhost:5006/sliders')

        # use the script in the rendered page
        return render_template("embed.html", script=script)

if __name__ == '__main__':
    app.run(port=8080)

So I start my sliders app with bokeh serve, visit it and it works fine. Then I launch my Flask app, and all I see is a blank page, with the console errors:

Firefox can’t establish a connection to the server at ws://localhost:5006/sliders/ws?bokeh-protocol-version=1.0&bokeh-session-id=Z2BPtTLxYcfINlynDozIjp5goLx6UR8RFqPFG5O8QH3R. connection.js:55

[bokeh] Failed to connect to Bokeh server Error: Could not open websocket connection.js:287

[bokeh] Lost websocket 0 connection, 1006 () connection.js:208

[bokeh] Websocket connection 0 disconnected, will not attempt to reconnect

What's preventing the websocket connections?

This is what my embed.html template looks like as well:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <script src="https://cdn.bokeh.data.org/bokeh/release/bokeh-1.3.4.min.js"></script>
        <script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.3.4.min.js"></script>
        <script src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-1.3.4.min.js"></script>
    </head>

    <body>
        {{ script|safe }}

    </body>
</html>
1

1 Answers

0
votes

Just tried the sliders example as well. When you are running the bokeh serve sliders.py you have to expicitly allow the websocket for the second app as well - I ran the following in powershell that worked for me

bokeh serve sliders.py --allow-websocket-origin=localhost:5006 --allow-websocket-origin=localhost:8080