With the new server, this was very straightforward to build. But just to close the loop and in case it’s of any interest to others here, I’ll post the SliderApp class that accepts user-defined functions:
“”"
This file demonstrates a bokeh server application where you pass a
user-defined function, which you canrun with
bokeh serve sliders_app_func.py
“”"
import numpy as np
from bokeh.plotting import Figure
from bokeh.models import Plot, ColumnDataSource
from bokeh.models.widgets import HBox, Slider, TextInput, VBoxForm
from bokeh.io import curdoc
class SliderApp:
def init(self, my_func):
Set up data
self.N = 200
x = np.linspace(0, 4*np.pi, self.N)
y = np.sin(x)
self.source = ColumnDataSource(data=dict(x=x, y=y))
self.my_func = my_func
Set up plot
self.plot = Figure(plot_height=400, plot_width=400, title=“my sine wave”,
tools=“crosshair,pan,reset,resize,save,wheel_zoom”,
x_range=[0, 4*np.pi], y_range=[-2.5, 2.5])
self.plot.line(‘x’, ‘y’, source=self.source, line_width=3, line_alpha=0.6)
Set up widgets
self.text = TextInput(title=“title”, name=‘title’, value=‘my sine wave’)
self.offset = Slider(title=“offset”, name=‘offset’,
value=0.0, start=-5.0, end=5.0, step=0.1)
self.amplitude = Slider(title=“amplitude”, name=‘amplitude’,
value=1.0, start=-5.0, end=5.0)
self.phase = Slider(title=“phase”, name=‘phase’,
value=0.0, start=0.0, end=2*np.pi)
self.freq = Slider(title=“frequency”, name=‘frequency’,
value=1.0, start=0.1, end=5.1)
self.text.on_change(‘value’, self.update_title)
for w in [self.offset, self.amplitude, self.phase, self.freq]:
w.on_change(‘value’, self.update_data)
print(w._callbacks)
def get_app(self):
Set up layouts and add to document
inputs = VBoxForm(children=[self.text, self.offset, self.amplitude, self.phase, self.freq])
hbox = HBox(children=[inputs, self.plot])
return hbox
Set up callbacks
def update_title(self, attrname, old, new):
self.plot.title = self.text.value
def update_data(self, attrname, old, new):
Get the current slider values
a = self.amplitude.value
b = self.offset.value
w = self.phase.value
k = self.my_func(self.freq.value)
print("NEW K: ", k, self.freq.value)
Generate the new curve
x = np.linspace(0, 4*np.pi, self.N)
y = anp.sin(kx + w) + b
self.source.data = dict(x=x, y=y)
myFunction = lambda x: x**2
app = SliderApp(myFunction)
hbox = app.get_app()
curdoc().add(hbox)
``
···
On Thursday, November 12, 2015 at 6:33:26 PM UTC-5, Bryan Van de ven wrote:
Michael,
I am very glad to hear that! I think that’s just about the best vindication we could ask for for the new approach. Also know when 0.11 lands there will be an extensive users guide section, and many more examples as well.
Thanks,
Bryan
On Nov 11, 2015, at 4:23 PM, [email protected] wrote:
Out of personal interest, I’m hoping to better understand the mechanisms of the current version of the server. But I wanted to briefly note that the new, simpler version you pointed me to makes this very easy to do! I’ve generated a working example of the slider_app using a custom function passed by the user.
I love the new approach to the server, and not just for this reason Wonderful update!
On Wednesday, November 11, 2015 at 11:25:47 AM UTC-5, [email protected] wrote:
Fabio, Bryan,
Thanks for the response, and the details on what’s going on under the hood. I’m using Bokeh 0.10.0, and have attached the code. I tried renaming with an underscore, as recommended, however it still fails with the same error. I may just be missing something obvious.
Thanks also for the heads up on the new PR. I’ll shift to start working with the new server. Do you know when the 0.11 release will happen, and if there may be additional details on best practices for deploying it for production apps (such as on AWS)?
Thanks again!
On Wednesday, November 11, 2015 at 6:26:26 AM UTC-5, Bryan Van de ven wrote:
Are you passing the function and setting it as a public attribute on the class? If so, that is the problem. In order to make Bokeh models just be simple declarative classes (by and large) there is alot of hidden metaprogramming machinery that performs serialization, validation, and can be used to auto-document every thing in the reference guide. One of the consequences of this machinery is that all pubilc attributes on a HasProps class are treated a properties to be serialized. This is why Bokeh is trying to serialize your lambda function (something it does not have any idea how to do). The solution is simple, though: “private” attributes are not automatically serialized, so just add an underscore in front of the name of whatever attribute you are using.
I will add, though: we just landed a large PR to merge in a completely new server. It is not compatible with the old (current) server, but is smaller, simpler, easier to use and deploy. It will be part of the upcoming 0.11 release but you can check out the current work on master and in the latest “dev” builds. As an example of how much simpler things are, here is the sliders app, rewritten in the new style:
[https://github.com/bokeh/bokeh/blob/misc_server_examples/examples/app/sliders_applet/sliders_app.py](https://github.com/bokeh/bokeh/blob/misc_server_examples/examples/app/sliders_applet/sliders_app.py)
There is no need for a special App class at all, it’s just a straightforward script. (FYI, the location of this example in the repository may change soon, if the link breaks, hunt around one directory level up.)
Thanks,
Bryan
On Nov 11, 2015, at 12:05 AM, [email protected] wrote:
Anybody have any thoughts on this at all?
On Saturday, November 7, 2015 at 3:45:53 PM UTC-5, [email protected] wrote:
I’ve been working with the Slider App example, and am playing around with having the data update according to different functions. This is straightforward when hard-coding the function into the update_data method of the app.One thing I’d like to do is pass a lambda function to the app, at creation and have the data update according to that function based on the slider values. The ultimate goal is to automatically generate an interactive plot, where the interaction is based on some function selected by the user (though once the plot is generated, the interaction will remain the same).
What I’ve tried so far is to make a class level attribute of type Function (from bokeh.properties), and then assign the passed lambda to this class attribute (which is then accessible by the update_data method). However, when I try this I get the following error:
TypeError: <function SlidersApp.create.. at 0x106b09158> is not JSON serializable
Are there any recommendations on how to work around this, or perhaps a better to approach to the problem at hand?
–
You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/96aafa0d-7998-4db4-9a77-742c493ad567%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.
–
You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/2ee4c9cb-f12f-4676-b16c-c910004a9141%40continuum.io.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.