[bokeh] Can't get web app to render

wild guess (not at my computer) you may have a JS error about no view for MyApp.

To tell it to use the VBox view adding “view_model = ‘VBox’” might work (something like that anyway)

You could also skip the inheritance and use globals or composition.

Havoc

···

On Jan 11, 2016, at 8:29 AM, [email protected] wrote:

Hi,
I’m trying to inherit from a VBox class to create a simple class which plots sine waves with a random frequency. The code is below. I start the Bokeh server with the command ‘bokeh serve --show MyApp.py’. The browser launches and I get no error messages at the command prompt, but nether the button nor the plot appear. Any help would be much appreciated. I’m new to Bokeh so forgive me if I’m doing something daft!
I’m using Bokeh version 0.11.0, running on Ubuntu 14.04.
Thanks,
Marcus.
Code…

import numpy

from bokeh.models import Button, Plot, ColumnDataSource
from bokeh.plotting import Figure, curdoc
from bokeh.models.widgets.layouts import VBox

from bokeh.core.properties import Instance,Float
from bokeh.models.sources import DataSource

class MyApp(VBox):

button = Instance(Button)
plot = Instance(Plot)
ds = Instance(DataSource)
f = Float

def __init__(self):
   
    super(MyApp,self).__init__()

    self.button = Button(label="Randomise Frequency")
    self.button.on_click(self.callback)
   
    self.f = 1.0

    self.plot = Figure(x_range=[0,2*numpy.pi],y_range=[-1, 1])
   
    self.ds = ColumnDataSource(data={'x':numpy.linspace(0,2*numpy.pi,100),'y':numpy.zeros(100)})
   
    self.plot.line('x','y',source=self.ds,line_width=2,line_alpha=0.5)
           
    self.children.append(self.button)
    self.children.append(self.plot)

def callback(self):
   
    self.f = numpy.random.rand()*10
    self.ds.data['y'] = 2*numpy.pi*self.f*self.ds.data['x']

curdoc().add_root(MyApp())

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/0dec772d-a0e4-4d20-b455-24e9da2b14d5%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Hi Havoc,
Thanks for the suggestion. I’m not sure I’m doing it right - code below with relevant lines in bold - but I can’t make it work that way.
True, I could avoid inheritance. What I want to be able to do is create custom Bokeh classes, with e.g. multiple plots and widget controls such as buttons/sliders, and instantiate those as single objects. There may well be a better way of doing this - grateful for suggestions!
Note that I can get it to work by removing the curdoc() call and inserting the two commented lines below, but it’s not a very neat way of doing it.
Thanks,
Marcus.
Code…
import numpy
from bokeh.models import Button, Plot, ColumnDataSource
from bokeh.plotting import Figure, curdoc, vplot
from bokeh.models.widgets.layouts import VBox
from bokeh.core.properties import Instance,Float
from bokeh.models.sources import DataSource
from bokeh.model import Viewable
class MyApp(VBox):
button = Instance(Button)
plot = Instance(Plot)
ds = Instance(DataSource)
f = Float

def __init__(self):

d = Viewable.model_class_reverse_map
d[‘MyApp’] = d[‘VBox’]

    super(MyApp,self).__init__()

    self.button = Button(label="Randomise Frequency")
    self.button.on_click(self.callback)
   
    self.f = 1.0

    self.plot = Figure(x_range=[0,1],y_range=[-1, 1])
   
    self.ds = ColumnDataSource(data={'x':numpy.linspace(0,2*numpy.pi,100),'y':numpy.zeros(100)})
   
    self.plot.line('x','y',source=self.ds,line_width=2,line_alpha=0.5)
           
    self.children.append(self.button)
    self.children.append(self.plot)

def callback(self):
   
    self.f = numpy.random.rand()*10
    self.ds.data['y'] = numpy.sin(2*numpy.pi*self.f*self.ds.data['x'])

curdoc().add_root(MyApp())
#app = MyApp()
#vplot(*app.children)

···

On Monday, January 11, 2016 at 6:13:13 PM UTC, Havoc Pennington wrote:

wild guess (not at my computer) you may have a JS error about no view for MyApp.

To tell it to use the VBox view adding “view_model = ‘VBox’” might work (something like that anyway)

You could also skip the inheritance and use globals or composition.

Havoc

On Jan 11, 2016, at 8:29 AM, [email protected] wrote:

Hi,
I’m trying to inherit from a VBox class to create a simple class which plots sine waves with a random frequency. The code is below. I start the Bokeh server with the command ‘bokeh serve --show MyApp.py’. The browser launches and I get no error messages at the command prompt, but nether the button nor the plot appear. Any help would be much appreciated. I’m new to Bokeh so forgive me if I’m doing something daft!
I’m using Bokeh version 0.11.0, running on Ubuntu 14.04.
Thanks,
Marcus.
Code…

import numpy

from bokeh.models import Button, Plot, ColumnDataSource
from bokeh.plotting import Figure, curdoc
from bokeh.models.widgets.layouts import VBox

from bokeh.core.properties import Instance,Float
from bokeh.models.sources import DataSource

class MyApp(VBox):

button = Instance(Button)
plot = Instance(Plot)
ds = Instance(DataSource)
f = Float

def __init__(self):
   
    super(MyApp,self).__init__()

    self.button = Button(label="Randomise Frequency")
    self.button.on_click(self.callback)
   
    self.f = 1.0

    self.plot = Figure(x_range=[0,2*numpy.pi],y_range=[-1, 1])
   
    self.ds = ColumnDataSource(data={'x':numpy.linspace(0,2*numpy.pi,100),'y':numpy.zeros(100)})
   
    self.plot.line('x','y',source=self.ds,line_width=2,line_alpha=0.5)
           
    self.children.append(self.button)
    self.children.append(self.plot)

def callback(self):
   
    self.f = numpy.random.rand()*10
    self.ds.data['y'] = 2*numpy.pi*self.f*self.ds.data['x']

curdoc().add_root(MyApp())

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/0dec772d-a0e4-4d20-b455-24e9da2b14d5%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Here are some of the (many) options ...

1) Perhaps the simplest approach here is to avoid the class entirely and
instead use a function:

def make_app():
     vbox = VBox()
     ... put stuff in vbox...
     return vbox
curdoc.add_root(make_app())

2) If using a class, an approach could be to make your class inherit from
object instead of VBox, and have a property of the class like `model`, and
then add `mything.model` to the document:

class MyApp(object):
    def __init__(self):
        self.model = VBox()

curdoc().add_root(MyApp().model)

The downside of this is that the fields of MyApp will not be synced between
client and server, since it isn't a model. That is, if you have `foo =
Float` in MyApp and set foo, the client wouldn't see that you set foo. In
fact I guess you can't use Bokeh model properties at all only regular
python fields. However, unless you are writing custom JavaScript for the
view, this may well not matter.

3) If you instead derive from VBox then Bokeh will "see" the MyApp class,
so it needs to know the view that goes with it. I think the magic you need
to make that work is like
https://github.com/bokeh/bokeh/blob/master/bokeh/charts/chart.py#L74-L75

__view_model__ = "VBox"
__subtype__ = "MyApp"

This is maybe cleaner but it is a little less clear and obvious than the
"make model a property" approach.

4) Yet another approach is to write a new view for your custom MyApp, which
looks something like this:
https://github.com/bokeh/bokeh/blob/master/examples/plotting/file/custom_datetime_axis.py#L22-L35

In that case your view could use any properties you add to MyApp. But the
downside of this is you have to write JavaScript or CoffeeScript.

So 3) and 4) are two ways to get a view for a custom model (use existing
view OR implement new view)

5) The reason vplot() in your commented-out two lines works is that it
removes the passed-in children from their existing parent (MyApp) and
places them in a new VBox (and Bokeh knows the view for a plain VBox). So
in this case the MyApp class is totally ignored and the situation is
similar to 1) or 2) in effect, since Bokeh is given a plain VBox.

Havoc

···

On Tue, Jan 12, 2016 at 5:36 AM, Marcus Donnelly < [email protected]> wrote:

True, I could avoid inheritance. What I want to be able to do is create
custom Bokeh classes, with e.g. multiple plots and widget controls such as
buttons/sliders, and instantiate those as single objects. There may well be
a better way of doing this - grateful for suggestions!

Many thanks for the explanation and helpful suggestions. I’ll have a go at these and see what works best.

Marcus.

···

On Tuesday, January 12, 2016 at 2:31:02 PM UTC, Havoc Pennington wrote:

On Tue, Jan 12, 2016 at 5:36 AM, Marcus Donnelly [email protected] wrote:

True, I could avoid inheritance. What I want to be able to do is create custom Bokeh classes, with e.g. multiple plots and widget controls such as buttons/sliders, and instantiate those as single objects. There may well be a better way of doing this - grateful for suggestions!

Here are some of the (many) options …

  1. Perhaps the simplest approach here is to avoid the class entirely and instead use a function:

def make_app():

vbox = VBox()

… put stuff in vbox…

return vbox

curdoc.add_root(make_app())

  1. If using a class, an approach could be to make your class inherit from object instead of VBox, and have a property of the class like model, and then add mything.model to the document:

class MyApp(object):

def init(self):

self.model = VBox()

curdoc().add_root(MyApp().model)

The downside of this is that the fields of MyApp will not be synced between client and server, since it isn’t a model. That is, if you have foo = Float in MyApp and set foo, the client wouldn’t see that you set foo. In fact I guess you can’t use Bokeh model properties at all only regular python fields. However, unless you are writing custom JavaScript for the view, this may well not matter.

  1. If you instead derive from VBox then Bokeh will “see” the MyApp class, so it needs to know the view that goes with it. I think the magic you need to make that work is like

https://github.com/bokeh/bokeh/blob/master/bokeh/charts/chart.py#L74-L75

view_model = “VBox”
subtype = “MyApp”

This is maybe cleaner but it is a little less clear and obvious than the “make model a property” approach.

  1. Yet another approach is to write a new view for your custom MyApp, which looks something like this:

https://github.com/bokeh/bokeh/blob/master/examples/plotting/file/custom_datetime_axis.py#L22-L35

In that case your view could use any properties you add to MyApp. But the downside of this is you have to write JavaScript or CoffeeScript.

So 3) and 4) are two ways to get a view for a custom model (use existing view OR implement new view)

  1. The reason vplot() in your commented-out two lines works is that it removes the passed-in children from their existing parent (MyApp) and places them in a new VBox (and Bokeh knows the view for a plain VBox). So in this case the MyApp class is totally ignored and the situation is similar to 1) or 2) in effect, since Bokeh is given a plain VBox.

Havoc

Many thanks for the explanation and helpful suggestions. I’ll have a go at these and see what works best.

Marcus.

···

On Tuesday, January 12, 2016 at 2:31:02 PM UTC, Havoc Pennington wrote:

On Tue, Jan 12, 2016 at 5:36 AM, Marcus Donnelly [email protected] wrote:

True, I could avoid inheritance. What I want to be able to do is create custom Bokeh classes, with e.g. multiple plots and widget controls such as buttons/sliders, and instantiate those as single objects. There may well be a better way of doing this - grateful for suggestions!

Here are some of the (many) options …

  1. Perhaps the simplest approach here is to avoid the class entirely and instead use a function:

def make_app():

vbox = VBox()

… put stuff in vbox…

return vbox

curdoc.add_root(make_app())

  1. If using a class, an approach could be to make your class inherit from object instead of VBox, and have a property of the class like model, and then add mything.model to the document:

class MyApp(object):

def init(self):

self.model = VBox()

curdoc().add_root(MyApp().model)

The downside of this is that the fields of MyApp will not be synced between client and server, since it isn’t a model. That is, if you have foo = Float in MyApp and set foo, the client wouldn’t see that you set foo. In fact I guess you can’t use Bokeh model properties at all only regular python fields. However, unless you are writing custom JavaScript for the view, this may well not matter.

  1. If you instead derive from VBox then Bokeh will “see” the MyApp class, so it needs to know the view that goes with it. I think the magic you need to make that work is like

https://github.com/bokeh/bokeh/blob/master/bokeh/charts/chart.py#L74-L75

view_model = “VBox”
subtype = “MyApp”

This is maybe cleaner but it is a little less clear and obvious than the “make model a property” approach.

  1. Yet another approach is to write a new view for your custom MyApp, which looks something like this:

https://github.com/bokeh/bokeh/blob/master/examples/plotting/file/custom_datetime_axis.py#L22-L35

In that case your view could use any properties you add to MyApp. But the downside of this is you have to write JavaScript or CoffeeScript.

So 3) and 4) are two ways to get a view for a custom model (use existing view OR implement new view)

  1. The reason vplot() in your commented-out two lines works is that it removes the passed-in children from their existing parent (MyApp) and places them in a new VBox (and Bokeh knows the view for a plain VBox). So in this case the MyApp class is totally ignored and the situation is similar to 1) or 2) in effect, since Bokeh is given a plain VBox.

Havoc