Skip to content

Commit

Permalink
Update sliders_app to work with bokeh serve
Browse files Browse the repository at this point in the history
  • Loading branch information
havocp committed Oct 29, 2015
1 parent c15af9e commit 0fc0974
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 143 deletions.
10 changes: 4 additions & 6 deletions examples/app/sliders_applet/README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@

This example shows how to create a simple applet in Bokeh, which can
be viewed directly on a bokeh-server.
This example shows how to create a simple server application in Bokeh.

Running
=======

To view this applet directly from a bokeh server, you simply need to
run a bokeh-server and point it at the stock example script:
To run this application, use this command:

bokeh-server --script sliders_app.py
bokeh serve sliders_app.py

Now navigate to the following URL in a browser:

http://localhost:5006/bokeh/sliders
http://localhost:5006/sliders_app
224 changes: 87 additions & 137 deletions examples/app/sliders_applet/sliders_app.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""
This file demonstrates a bokeh applet, which can be viewed directly
on a bokeh-server. See the README.md file in this directory for
instructions on running.
This file demonstrates a bokeh server application, which you can
run with `bokeh serve sliders_app.py`
"""

import logging
Expand All @@ -10,158 +9,109 @@

import numpy as np

from bokeh.plotting import figure
from bokeh.plotting import Figure
from bokeh.models import Plot, ColumnDataSource
from bokeh.properties import Instance
from bokeh.server.app import bokeh_app
from bokeh.server.utils.plugins import object_page
from bokeh.models.widgets import HBox, Slider, TextInput, VBoxForm


class SlidersApp(HBox):
"""An example of a browser-based, interactive plot with slider controls."""

extra_generated_classes = [["SlidersApp", "SlidersApp", "HBox"]]

inputs = Instance(VBoxForm)

text = Instance(TextInput)

offset = Instance(Slider)
amplitude = Instance(Slider)
phase = Instance(Slider)
freq = Instance(Slider)

plot = Instance(Plot)
source = Instance(ColumnDataSource)

@classmethod
def create(cls):
"""One-time creation of app's objects.
This function is called once, and is responsible for
creating all objects (plots, datasources, etc)
"""
obj = cls()

obj.source = ColumnDataSource(data=dict(x=[], y=[]))

obj.text = TextInput(
title="title", name='title', value='my sine wave'
from bokeh.io import curdoc

source = ColumnDataSource(data=dict(x=[], y=[]))

text = TextInput(
title="title", name='title', value='my sine wave'
)

offset = Slider(
title="offset", name='offset',
value=0.0, start=-5.0, end=5.0, step=0.1
)
amplitude = Slider(
title="amplitude", name='amplitude',
value=1.0, start=-5.0, end=5.0
)
phase = Slider(
title="phase", name='phase',
value=0.0, start=0.0, end=2*np.pi
)
freq = Slider(
title="frequency", name='frequency',
value=1.0, start=0.1, end=5.1
)

toolset = "crosshair,pan,reset,resize,save,wheel_zoom"

# Generate a figure container
plot = Figure(title_text_font_size="12pt",
plot_height=400,
plot_width=400,
tools=toolset,
title=text.value,
x_range=[0, 4*np.pi],
y_range=[-2.5, 2.5]
)

obj.offset = Slider(
title="offset", name='offset',
value=0.0, start=-5.0, end=5.0, step=0.1
)
obj.amplitude = Slider(
title="amplitude", name='amplitude',
value=1.0, start=-5.0, end=5.0
)
obj.phase = Slider(
title="phase", name='phase',
value=0.0, start=0.0, end=2*np.pi
)
obj.freq = Slider(
title="frequency", name='frequency',
value=1.0, start=0.1, end=5.1
)
# Plot the line by the x,y values in the source property
plot.line('x', 'y', source=source,
line_width=3,
line_alpha=0.6
)

toolset = "crosshair,pan,reset,resize,save,wheel_zoom"
plot = plot

# Generate a figure container
plot = figure(title_text_font_size="12pt",
plot_height=400,
plot_width=400,
tools=toolset,
title=obj.text.value,
x_range=[0, 4*np.pi],
y_range=[-2.5, 2.5]
)
inputs = VBoxForm(
children=[
text, offset, amplitude, phase, freq
]
)

# Plot the line by the x,y values in the source property
plot.line('x', 'y', source=obj.source,
line_width=3,
line_alpha=0.6
)
hbox = HBox(children=[inputs, plot])

obj.plot = plot
obj.update_data()
def update_data():
"""Called each time that any watched property changes.
obj.inputs = VBoxForm(
children=[
obj.text, obj.offset, obj.amplitude, obj.phase, obj.freq
]
)

obj.children.append(obj.inputs)
obj.children.append(obj.plot)

return obj

def setup_events(self):
"""Attaches the on_change event to the value property of the widget.
The callback is set to the input_change method of this app.
This updates the sin wave data with the most recent values of the
sliders. This is stored as two numpy arrays in a dict into the app's
data source property.
"""
super(SlidersApp, self).setup_events()
if not self.text:
return
N = 200

# Text box event registration
self.text.on_change('value', self, 'input_change')
# Get the current slider values
a = amplitude.value
b = offset.value
w = phase.value
k = freq.value

# Slider event registration
for w in ["offset", "amplitude", "phase", "freq"]:
getattr(self, w).on_change('value', self, 'input_change')
# Generate the sine wave
x = np.linspace(0, 4*np.pi, N)
y = a*np.sin(k*x + w) + b

def input_change(self, obj, attrname, old, new):
"""Executes whenever the input form changes.
logging.debug(
"PARAMS: offset: %s amplitude: %s", offset.value,
amplitude.value
)

It is responsible for updating the plot, or anything else you want.
source.data = dict(x=x, y=y)

Args:
obj : the object that changed
attrname : the attr that changed
old : old value of attr
new : new value of attr
"""
self.update_data()
self.plot.title = self.text.value
update_data()

def update_data(self):
"""Called each time that any watched property changes.
def input_change(attrname, old, new):
"""Executes whenever the input form changes.
This updates the sin wave data with the most recent values of the
sliders. This is stored as two numpy arrays in a dict into the app's
data source property.
"""
N = 200
It is responsible for updating the plot, or anything else you want.
# Get the current slider values
a = self.amplitude.value
b = self.offset.value
w = self.phase.value
k = self.freq.value

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

logging.debug(
"PARAMS: offset: %s amplitude: %s", self.offset.value,
self.amplitude.value
)
Args:
attrname : the attr that changed
old : old value of attr
new : new value of attr
"""
update_data()
plot.title = text.value

self.source.data = dict(x=x, y=y)
# Text box event registration
text.on_change('value', input_change)

# Slider event registration
for w in [offset, amplitude, phase, freq]:
w.on_change('value', input_change)

# The following code adds a "/bokeh/sliders/" url to the bokeh-server. This
# URL will render this sine wave sliders app. If you don't want to serve this
# applet from a Bokeh server (for instance if you are embedding in a separate
# Flask application), then just remove this block of code.
@bokeh_app.route("/bokeh/sliders/")
@object_page("sin")
def make_sliders():
app = SlidersApp.create()
return app
# put ourselves in the document
curdoc().add(hbox)

0 comments on commit 0fc0974

Please sign in to comment.