custom tornado bokeh server for 0.13.0

Hi, is there anywhere any example of how to run bokeh server with a stream to the client in a custom tornado server fashion which works on 0.13.0?
I find the docs on how to do this a bit difficult to read and I dont understand how to get started on this - so an example would be wonderful.

Thanks

I did find this example
and modified the code so that data is being pushed to the client rather than pulled.

When I run this i get the error:

Exception in thread Thread-1:

Traceback (most recent call last):

File “/Users/Jg/anaconda3431/lib/python3.6/threading.py”, line 916, in _bootstrap_inner

self.run()

File “/Users/Jg/anaconda3431/lib/python3.6/threading.py”, line 864, in run

self._target(*self._args, **self._kwargs)

File “tornado_embed.py”, line 43, in threaded_function

source.data = ColumnDataSource(data=data).data

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/has_props.py”, line 263, in setattr

super(HasProps, self).__setattr__(name, value)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 931, in set

self._internal_set(obj, value, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 727, in _internal_set

self._real_set(obj, old, value, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 796, in _real_set

self._trigger(obj, old, value, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 873, in _trigger

obj.trigger([self.name](http://self.name), old, value, hint, setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/model.py”, line 549, in trigger

super(Model, self).trigger(attr, old, new, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/util/callback_manager.py”, line 120, in trigger

self._document._notify_change(self, attr, old, new, hint, setter, invoke)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 941, in _notify_change

self._trigger_on_change(event)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 1049, in _trigger_on_change

self._with_self_as_curdoc(invoke_callbacks)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 1062, in _with_self_as_curdoc

return f()

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 1048, in invoke_callbacks

cb(event)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 614, in

self._callbacks[receiver] = lambda event: event.dispatch(receiver)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py”, line 195, in dispatch

super(ModelChangedEvent, self).dispatch(receiver)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py”, line 77, in dispatch

receiver._document_patched(self)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/server/session.py”, line 180, in _document_patched

raise RuntimeError("_pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes")

RuntimeError: _pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes

What am I doing wrong here?

Code is:

from jinja2 import Environment, FileSystemLoader

from tornado.web import RequestHandler

from bokeh.embed import server_document

from bokeh.layouts import column

from bokeh.models import ColumnDataSource, Slider

from bokeh.plotting import figure

from bokeh.server.server import Server

from bokeh.themes import Theme

from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature

#from threading import Thread

import threading

from time import sleep

env = Environment(loader=FileSystemLoader(‘templates’))

class IndexHandler(RequestHandler):

def get(self):

template = env.get_template(‘embed.html’)

script = server_document(‘http://localhost:5006/bkapp’)

self.write(template.render(script=script, template=“Tornado”))

def modify_doc(doc):

df = sea_surface_temperature.copy()

source = ColumnDataSource(data=df)

plot = figure(x_axis_type=‘datetime’, y_range=(0, 25), y_axis_label=‘Temperature (Celsius)’,

title=“Sea Surface Temperature at 43.18, -70.43”)

plot.line(‘time’, ‘temperature’, source=source)

def threaded_function():

sleep(3)

for new in range(20):

print(new)

if new == 0:

data = df

else:

data = df.rolling(’{0}D’.format(new)).mean()

source.data = ColumnDataSource(data=data).data

sleep(1)

slider = Slider(start=0, end=30, value=0, step=1, title=“Smoothing by N Days”)

#slider.on_change(‘value’, callback)

doc.add_root(column(slider, plot))

doc.theme = Theme(filename=“theme.yaml”)

tf = threading.Thread(target=threaded_function)

tf.start()

Setting num_procs here means we can’t touch the IOLoop before now, we must

let Server handle that. If you need to explicitly handle IOLoops then you

will need to use the lower level BaseServer class.

server = Server({’/bkapp’: modify_doc}, num_procs=4, extra_patterns=[(’/’, IndexHandler)])

server.start()

if name == ‘main’:

from bokeh.util.browser import view

print(‘Opening Tornado app with embedded Bokeh application on http://localhost:5006/’)

server.io_loop.add_callback(view, “http://localhost:5006/”)

server.io_loop.start()

···

On Mon, Jul 30, 2018 at 5:37 PM, Bokeh coder [email protected] wrote:

Hi, is there anywhere any example of how to run bokeh server with a stream to the client in a custom tornado server fashion which works on 0.13.0?
I find the docs on how to do this a bit difficult to read and I dont understand how to get started on this - so an example would be wonderful.

Thanks

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/cb17001b-e2ca-4085-b62a-7726bfe95a1f%40continuum.io.

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

Hi,

Please see the documentation regarding updating from threads:

  https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads

Thanks,

Bryan

···

On Jul 30, 2018, at 11:13, Michael Hansen <[email protected]> wrote:

I did find this example
and modified the code so that data is being pushed to the client rather than pulled.

When I run this i get the error:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/Users/Jg/anaconda3431/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/Users/Jg/anaconda3431/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "tornado_embed.py", line 43, in threaded_function
    source.data = ColumnDataSource(data=data).data
  File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/has_props.py", line 263, in __setattr__
    super(HasProps, self).__setattr__(name, value)
  File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 931, in __set__
    self._internal_set(obj, value, hint=hint, setter=setter)
  File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 727, in _internal_set
    self._real_set(obj, old, value, hint=hint, setter=setter)
  File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 796, in _real_set
    self._trigger(obj, old, value, hint=hint, setter=setter)
  File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 873, in _trigger
    obj.trigger(self.name, old, value, hint, setter)
  File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/model.py", line 549, in trigger
    super(Model, self).trigger(attr, old, new, hint=hint, setter=setter)
  File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/util/callback_manager.py", line 120, in trigger
    self._document._notify_change(self, attr, old, new, hint, setter, invoke)
  File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 941, in _notify_change
    self._trigger_on_change(event)
  File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 1049, in _trigger_on_change
    self._with_self_as_curdoc(invoke_callbacks)
  File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 1062, in _with_self_as_curdoc
    return f()
  File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 1048, in invoke_callbacks
    cb(event)
  File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 614, in <lambda>
    self._callbacks[receiver] = lambda event: event.dispatch(receiver)
  File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py", line 195, in dispatch
    super(ModelChangedEvent, self).dispatch(receiver)
  File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py", line 77, in dispatch
    receiver._document_patched(self)
  File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/server/session.py", line 180, in _document_patched
    raise RuntimeError("_pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes")
RuntimeError: _pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes

What am I doing wrong here?

Code is:

from jinja2 import Environment, FileSystemLoader

from tornado.web import RequestHandler

from bokeh.embed import server_document
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, Slider
from bokeh.plotting import figure
from bokeh.server.server import Server
from bokeh.themes import Theme

from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature

#from threading import Thread
import threading
from time import sleep

env = Environment(loader=FileSystemLoader('templates'))

class IndexHandler(RequestHandler):
    def get(self):
        template = env.get_template('embed.html')
        script = server_document('http://localhost:5006/bkapp')
        self.write(template.render(script=script, template="Tornado"))

def modify_doc(doc):
    df = sea_surface_temperature.copy()
    source = ColumnDataSource(data=df)

    plot = figure(x_axis_type='datetime', y_range=(0, 25), y_axis_label='Temperature (Celsius)',
                  title="Sea Surface Temperature at 43.18, -70.43")
    plot.line('time', 'temperature', source=source)

    def threaded_function():
        sleep(3)
        for new in range(20):
            print(new)
            if new == 0:
                data = df
            else:
                data = df.rolling('{0}D'.format(new)).mean()
            source.data = ColumnDataSource(data=data).data
            sleep(1)

    slider = Slider(start=0, end=30, value=0, step=1, title="Smoothing by N Days")
    #slider.on_change('value', callback)

    doc.add_root(column(slider, plot))

    doc.theme = Theme(filename="theme.yaml")
    tf = threading.Thread(target=threaded_function)
    tf.start()

# Setting num_procs here means we can't touch the IOLoop before now, we must
# let Server handle that. If you need to explicitly handle IOLoops then you
# will need to use the lower level BaseServer class.
server = Server({'/bkapp': modify_doc}, num_procs=4, extra_patterns=[('/', IndexHandler)])
server.start()

if __name__ == '__main__':
    from bokeh.util.browser import view

    print('Opening Tornado app with embedded Bokeh application on http://localhost:5006/')

    server.io_loop.add_callback(view, "http://localhost:5006/")
    server.io_loop.start()

On Mon, Jul 30, 2018 at 5:37 PM, Bokeh coder <[email protected]> wrote:
Hi, is there anywhere any example of how to run bokeh server with a stream to the client in a custom tornado server fashion which works on 0.13.0?
I find the docs on how to do this a bit difficult to read and I dont understand how to get started on this - so an example would be wonderful.

Thanks

--
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/cb17001b-e2ca-4085-b62a-7726bfe95a1f%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/CAPty9BMctKbXjXQ1pKWwk3qkEUV%3DF-40tGK5V3HnbjUMYHOi4A%40mail.gmail.com.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Aha right…I see.
Could I possibly persuade you show how to combine

https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/tornado_embed.py

and

https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads

That would be a really big help for understanding the overall setup

···

On Mon, Jul 30, 2018 at 8:21 PM, Bryan Van de ven [email protected] wrote:

Hi,

Please see the documentation regarding updating from threads:

    [https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads](https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads)

Thanks,

Bryan

On Jul 30, 2018, at 11:13, Michael Hansen [email protected] wrote:

I did find this example

and modified the code so that data is being pushed to the client rather than pulled.

When I run this i get the error:

Exception in thread Thread-1:

Traceback (most recent call last):

File “/Users/Jg/anaconda3431/lib/python3.6/threading.py”, line 916, in _bootstrap_inner

self.run()

File “/Users/Jg/anaconda3431/lib/python3.6/threading.py”, line 864, in run

self._target(*self._args, **self._kwargs)

File “tornado_embed.py”, line 43, in threaded_function

source.data = ColumnDataSource(data=data).data

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/has_props.py”, line 263, in setattr

super(HasProps, self).__setattr__(name, value)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 931, in set

self._internal_set(obj, value, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 727, in _internal_set

self._real_set(obj, old, value, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 796, in _real_set

self._trigger(obj, old, value, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 873, in _trigger

obj.trigger([self.name](http://self.name), old, value, hint, setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/model.py”, line 549, in trigger

super(Model, self).trigger(attr, old, new, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/util/callback_manager.py”, line 120, in trigger

self._document._notify_change(self, attr, old, new, hint, setter, invoke)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 941, in _notify_change

self._trigger_on_change(event)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 1049, in _trigger_on_change

self._with_self_as_curdoc(invoke_callbacks)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 1062, in _with_self_as_curdoc

return f()

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 1048, in invoke_callbacks

cb(event)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 614, in

self._callbacks[receiver] = lambda event: event.dispatch(receiver)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py”, line 195, in dispatch

super(ModelChangedEvent, self).dispatch(receiver)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py”, line 77, in dispatch

receiver._document_patched(self)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/server/session.py”, line 180, in _document_patched

raise RuntimeError("_pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes")

RuntimeError: _pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes

What am I doing wrong here?

Code is:

from jinja2 import Environment, FileSystemLoader

from tornado.web import RequestHandler

from bokeh.embed import server_document

from bokeh.layouts import column

from bokeh.models import ColumnDataSource, Slider

from bokeh.plotting import figure

from bokeh.server.server import Server

from bokeh.themes import Theme

from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature

#from threading import Thread

import threading

from time import sleep

env = Environment(loader=FileSystemLoader(‘templates’))

class IndexHandler(RequestHandler):

def get(self):
    template = env.get_template('embed.html')
    script = server_document('[http://localhost:5006/bkapp](http://localhost:5006/bkapp)')
    self.write(template.render(script=script, template="Tornado"))

def modify_doc(doc):

df = sea_surface_temperature.copy()
source = ColumnDataSource(data=df)
plot = figure(x_axis_type='datetime', y_range=(0, 25), y_axis_label='Temperature (Celsius)',
              title="Sea Surface Temperature at 43.18, -70.43")
plot.line('time', 'temperature', source=source)
def threaded_function():
    sleep(3)
    for new in range(20):
        print(new)
        if new == 0:
            data = df
        else:
            data = df.rolling('{0}D'.format(new)).mean()
        source.data = ColumnDataSource(data=data).data
        sleep(1)
slider = Slider(start=0, end=30, value=0, step=1, title="Smoothing by N Days")
#slider.on_change('value', callback)
doc.add_root(column(slider, plot))
doc.theme = Theme(filename="theme.yaml")
tf = threading.Thread(target=threaded_function)
tf.start()

Setting num_procs here means we can’t touch the IOLoop before now, we must

let Server handle that. If you need to explicitly handle IOLoops then you

will need to use the lower level BaseServer class.

server = Server({’/bkapp’: modify_doc}, num_procs=4, extra_patterns=[(’/’, IndexHandler)])

server.start()

if name == ‘main’:

from bokeh.util.browser import view
print('Opening Tornado app with embedded Bokeh application on [http://localhost:5006/](http://localhost:5006/)')
server.io_loop.add_callback(view, "[http://localhost:5006/](http://localhost:5006/)")
server.io_loop.start()

On Mon, Jul 30, 2018 at 5:37 PM, Bokeh coder [email protected] wrote:

Hi, is there anywhere any example of how to run bokeh server with a stream to the client in a custom tornado server fashion which works on 0.13.0?

I find the docs on how to do this a bit difficult to read and I dont understand how to get started on this - so an example would be wonderful.

Thanks

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/cb17001b-e2ca-4085-b62a-7726bfe95a1f%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/CAPty9BMctKbXjXQ1pKWwk3qkEUV%3DF-40tGK5V3HnbjUMYHOi4A%40mail.gmail.com.

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/7D078D9C-CCAD-4E6C-BBE5-6DE1E27A838D%40anaconda.com.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Hi,

I'm sorry, I simply don't have the bandwidth to work up an example right now. The relevant change you need to make is:

* put the call to "source.data = new_data" in a small function of its own
* have you current callback add that small function as a next_tick_callback

However, I also note that you do this:

   source.data = ColumnDataSource(data=data).data

Don't do that. The RHS of "source.data = " should always be a *plain python dict*. It should NOT be the .data property of another CDS. which is actually a complicated wrapper that just happens to look like a dict. Doing the above will currently fail ungracefully. We have yet to either disallow it via an immediate exception or find a way to make it work.

Thanks,

Bryan

···

On Jul 30, 2018, at 14:49, Michael Hansen <[email protected]> wrote:

Aha right....I see.
Could I possibly persuade you show how to combine

https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/tornado_embed.py
and
https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads

That would be a really big help for understanding the overall setup

On Mon, Jul 30, 2018 at 8:21 PM, Bryan Van de ven <[email protected]> wrote:
Hi,

Please see the documentation regarding updating from threads:

        https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads

Thanks,

Bryan

> On Jul 30, 2018, at 11:13, Michael Hansen <[email protected]> wrote:
>
> I did find this example
> and modified the code so that data is being pushed to the client rather than pulled.
>
> When I run this i get the error:
>
> Exception in thread Thread-1:
> Traceback (most recent call last):
> File "/Users/Jg/anaconda3431/lib/python3.6/threading.py", line 916, in _bootstrap_inner
> self.run()
> File "/Users/Jg/anaconda3431/lib/python3.6/threading.py", line 864, in run
> self._target(*self._args, **self._kwargs)
> File "tornado_embed.py", line 43, in threaded_function
> source.data = ColumnDataSource(data=data).data
> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/has_props.py", line 263, in __setattr__
> super(HasProps, self).__setattr__(name, value)
> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 931, in __set__
> self._internal_set(obj, value, hint=hint, setter=setter)
> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 727, in _internal_set
> self._real_set(obj, old, value, hint=hint, setter=setter)
> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 796, in _real_set
> self._trigger(obj, old, value, hint=hint, setter=setter)
> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 873, in _trigger
> obj.trigger(self.name, old, value, hint, setter)
> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/model.py", line 549, in trigger
> super(Model, self).trigger(attr, old, new, hint=hint, setter=setter)
> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/util/callback_manager.py", line 120, in trigger
> self._document._notify_change(self, attr, old, new, hint, setter, invoke)
> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 941, in _notify_change
> self._trigger_on_change(event)
> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 1049, in _trigger_on_change
> self._with_self_as_curdoc(invoke_callbacks)
> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 1062, in _with_self_as_curdoc
> return f()
> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 1048, in invoke_callbacks
> cb(event)
> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 614, in <lambda>
> self._callbacks[receiver] = lambda event: event.dispatch(receiver)
> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py", line 195, in dispatch
> super(ModelChangedEvent, self).dispatch(receiver)
> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py", line 77, in dispatch
> receiver._document_patched(self)
> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/server/session.py", line 180, in _document_patched
> raise RuntimeError("_pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes")
> RuntimeError: _pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes
>
>
> What am I doing wrong here?
>
> Code is:
>
> from jinja2 import Environment, FileSystemLoader
>
> from tornado.web import RequestHandler
>
> from bokeh.embed import server_document
> from bokeh.layouts import column
> from bokeh.models import ColumnDataSource, Slider
> from bokeh.plotting import figure
> from bokeh.server.server import Server
> from bokeh.themes import Theme
>
> from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature
>
> #from threading import Thread
> import threading
> from time import sleep
>
> env = Environment(loader=FileSystemLoader('templates'))
>
> class IndexHandler(RequestHandler):
> def get(self):
> template = env.get_template('embed.html')
> script = server_document('http://localhost:5006/bkapp')
> self.write(template.render(script=script, template="Tornado"))
>
> def modify_doc(doc):
> df = sea_surface_temperature.copy()
> source = ColumnDataSource(data=df)
>
> plot = figure(x_axis_type='datetime', y_range=(0, 25), y_axis_label='Temperature (Celsius)',
> title="Sea Surface Temperature at 43.18, -70.43")
> plot.line('time', 'temperature', source=source)
>
>
> def threaded_function():
> sleep(3)
> for new in range(20):
> print(new)
> if new == 0:
> data = df
> else:
> data = df.rolling('{0}D'.format(new)).mean()
> source.data = ColumnDataSource(data=data).data
> sleep(1)
>
> slider = Slider(start=0, end=30, value=0, step=1, title="Smoothing by N Days")
> #slider.on_change('value', callback)
>
> doc.add_root(column(slider, plot))
>
> doc.theme = Theme(filename="theme.yaml")
> tf = threading.Thread(target=threaded_function)
> tf.start()
>
> # Setting num_procs here means we can't touch the IOLoop before now, we must
> # let Server handle that. If you need to explicitly handle IOLoops then you
> # will need to use the lower level BaseServer class.
> server = Server({'/bkapp': modify_doc}, num_procs=4, extra_patterns=[('/', IndexHandler)])
> server.start()
>
> if __name__ == '__main__':
> from bokeh.util.browser import view
>
> print('Opening Tornado app with embedded Bokeh application on http://localhost:5006/')
>
> server.io_loop.add_callback(view, "http://localhost:5006/")
> server.io_loop.start()
>
>
> On Mon, Jul 30, 2018 at 5:37 PM, Bokeh coder <[email protected]> wrote:
> Hi, is there anywhere any example of how to run bokeh server with a stream to the client in a custom tornado server fashion which works on 0.13.0?
> I find the docs on how to do this a bit difficult to read and I dont understand how to get started on this - so an example would be wonderful.
>
> Thanks
>
>
> --
> 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/cb17001b-e2ca-4085-b62a-7726bfe95a1f%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/CAPty9BMctKbXjXQ1pKWwk3qkEUV%3DF-40tGK5V3HnbjUMYHOi4A%40mail.gmail.com.
> 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/7D078D9C-CCAD-4E6C-BBE5-6DE1E27A838D%40anaconda.com.
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/CAPty9BM%3Db5VKw7GTXwkDaMShMTTf0yq2eRGBUDMa-BtN%2B9R8ew%40mail.gmail.com.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Well, upon further inspection, it's possible that

  source.data = ColumnDataSource(data=data).data

Is in fact, "OK", but it's definitely not what I would recommend. Just set

  source.data = data

Thanks,

Bryan

···

On Jul 30, 2018, at 15:12, Bryan Van de ven <[email protected]> wrote:

Hi,

I'm sorry, I simply don't have the bandwidth to work up an example right now. The relevant change you need to make is:

* put the call to "source.data = new_data" in a small function of its own
* have you current callback add that small function as a next_tick_callback

However, I also note that you do this:

   source.data = ColumnDataSource(data=data).data

Don't do that. The RHS of "source.data = " should always be a *plain python dict*. It should NOT be the .data property of another CDS. which is actually a complicated wrapper that just happens to look like a dict. Doing the above will currently fail ungracefully. We have yet to either disallow it via an immediate exception or find a way to make it work.

Thanks,

Bryan

On Jul 30, 2018, at 14:49, Michael Hansen <[email protected]> wrote:

Aha right....I see.
Could I possibly persuade you show how to combine

https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/tornado_embed.py
and
https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads

That would be a really big help for understanding the overall setup

On Mon, Jul 30, 2018 at 8:21 PM, Bryan Van de ven <[email protected]> wrote:
Hi,

Please see the documentation regarding updating from threads:

       https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads

Thanks,

Bryan

On Jul 30, 2018, at 11:13, Michael Hansen <[email protected]> wrote:

I did find this example
and modified the code so that data is being pushed to the client rather than pulled.

When I run this i get the error:

Exception in thread Thread-1:
Traceback (most recent call last):
File "/Users/Jg/anaconda3431/lib/python3.6/threading.py", line 916, in _bootstrap_inner
   self.run()
File "/Users/Jg/anaconda3431/lib/python3.6/threading.py", line 864, in run
   self._target(*self._args, **self._kwargs)
File "tornado_embed.py", line 43, in threaded_function
   source.data = ColumnDataSource(data=data).data
File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/has_props.py", line 263, in __setattr__
   super(HasProps, self).__setattr__(name, value)
File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 931, in __set__
   self._internal_set(obj, value, hint=hint, setter=setter)
File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 727, in _internal_set
   self._real_set(obj, old, value, hint=hint, setter=setter)
File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 796, in _real_set
   self._trigger(obj, old, value, hint=hint, setter=setter)
File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 873, in _trigger
   obj.trigger(self.name, old, value, hint, setter)
File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/model.py", line 549, in trigger
   super(Model, self).trigger(attr, old, new, hint=hint, setter=setter)
File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/util/callback_manager.py", line 120, in trigger
   self._document._notify_change(self, attr, old, new, hint, setter, invoke)
File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 941, in _notify_change
   self._trigger_on_change(event)
File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 1049, in _trigger_on_change
   self._with_self_as_curdoc(invoke_callbacks)
File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 1062, in _with_self_as_curdoc
   return f()
File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 1048, in invoke_callbacks
   cb(event)
File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 614, in <lambda>
   self._callbacks[receiver] = lambda event: event.dispatch(receiver)
File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py", line 195, in dispatch
   super(ModelChangedEvent, self).dispatch(receiver)
File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py", line 77, in dispatch
   receiver._document_patched(self)
File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/server/session.py", line 180, in _document_patched
   raise RuntimeError("_pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes")
RuntimeError: _pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes

What am I doing wrong here?

Code is:

from jinja2 import Environment, FileSystemLoader

from tornado.web import RequestHandler

from bokeh.embed import server_document
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, Slider
from bokeh.plotting import figure
from bokeh.server.server import Server
from bokeh.themes import Theme

from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature

#from threading import Thread
import threading
from time import sleep

env = Environment(loader=FileSystemLoader('templates'))

class IndexHandler(RequestHandler):
   def get(self):
       template = env.get_template('embed.html')
       script = server_document('http://localhost:5006/bkapp')
       self.write(template.render(script=script, template="Tornado"))

def modify_doc(doc):
   df = sea_surface_temperature.copy()
   source = ColumnDataSource(data=df)

   plot = figure(x_axis_type='datetime', y_range=(0, 25), y_axis_label='Temperature (Celsius)',
                 title="Sea Surface Temperature at 43.18, -70.43")
   plot.line('time', 'temperature', source=source)

   def threaded_function():
       sleep(3)
       for new in range(20):
           print(new)
           if new == 0:
               data = df
           else:
               data = df.rolling('{0}D'.format(new)).mean()
           source.data = ColumnDataSource(data=data).data
           sleep(1)

   slider = Slider(start=0, end=30, value=0, step=1, title="Smoothing by N Days")
   #slider.on_change('value', callback)

   doc.add_root(column(slider, plot))

   doc.theme = Theme(filename="theme.yaml")
   tf = threading.Thread(target=threaded_function)
   tf.start()

# Setting num_procs here means we can't touch the IOLoop before now, we must
# let Server handle that. If you need to explicitly handle IOLoops then you
# will need to use the lower level BaseServer class.
server = Server({'/bkapp': modify_doc}, num_procs=4, extra_patterns=[('/', IndexHandler)])
server.start()

if __name__ == '__main__':
   from bokeh.util.browser import view

   print('Opening Tornado app with embedded Bokeh application on http://localhost:5006/')

   server.io_loop.add_callback(view, "http://localhost:5006/")
   server.io_loop.start()

On Mon, Jul 30, 2018 at 5:37 PM, Bokeh coder <[email protected]> wrote:
Hi, is there anywhere any example of how to run bokeh server with a stream to the client in a custom tornado server fashion which works on 0.13.0?
I find the docs on how to do this a bit difficult to read and I dont understand how to get started on this - so an example would be wonderful.

Thanks

--
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/cb17001b-e2ca-4085-b62a-7726bfe95a1f%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/CAPty9BMctKbXjXQ1pKWwk3qkEUV%3DF-40tGK5V3HnbjUMYHOi4A%40mail.gmail.com.
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]continuum.io.
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/7D078D9C-CCAD-4E6C-BBE5-6DE1E27A838D%40anaconda.com.
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/CAPty9BM%3Db5VKw7GTXwkDaMShMTTf0yq2eRGBUDMa-BtN%2B9R8ew%40mail.gmail.com.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

It seems i actually managed to do it. I got something working.
My question is now - am I doing this the right way?

All comments are greatly appreciated.

Thanks

from jinja2 import Environment, FileSystemLoader

from functools import partial

from tornado.web import RequestHandler

from tornado import gen

from bokeh.embed import server_document

from bokeh.layouts import column

from bokeh.models import ColumnDataSource, Slider

from bokeh.plotting import figure

from bokeh.server.server import Server

from bokeh.themes import Theme

from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature

#from threading import Thread

import threading

from time import sleep

import numpy as np

from random import random

env = Environment(loader=FileSystemLoader(‘templates’))

class IndexHandler(RequestHandler):

def get(self):

template = env.get_template(‘embed.html’)

script = server_document(‘http://localhost:5006/bkapp’)

print(script)

self.write(template.render(script=script, template=“Tornado”))

@gen.coroutine

def update(x, y):

source.stream(dict(x=, y=[y]))

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

def modify_doc(doc):

plot = figure(y_axis_label=‘Temperature (Celsius)’, y_range=(-2, 2),

title=“Sea Surface Temperature at 43.18, -70.43”) #x_axis_type=‘datetime’, ,

plot.line(x=‘x’, y=‘y’, source=source)

doc.add_root(plot)

doc.theme = Theme(filename=“theme.yaml”)

def threaded_function():

sleep(3)

for new in range(20):

sleep(1)

doc.add_next_tick_callback(partial(update, x=new+1, y=random()))

tf = threading.Thread(target=threaded_function)

tf.start()

server = Server({’/bkapp’: modify_doc}, num_procs=4, extra_patterns=[(’/’, IndexHandler)])

server.start()

if name == ‘main’:

from bokeh.util.browser import view

print(‘Opening Tornado app with embedded Bokeh application on http://localhost:5006/’)

server.io_loop.add_callback(view, “http://localhost:5006/”)

server.io_loop.start()

···

On Tue, Jul 31, 2018 at 12:20 AM, Bryan Van de ven [email protected] wrote:

On Jul 30, 2018, at 15:12, Bryan Van de ven [email protected] wrote:

Hi,

I’m sorry, I simply don’t have the bandwidth to work up an example right now. The relevant change you need to make is:

  • put the call to “source.data = new_data” in a small function of its own
  • have you current callback add that small function as a next_tick_callback

However, I also note that you do this:

   source.data = ColumnDataSource(data=data).data

Don’t do that. The RHS of "source.data = " should always be a plain python dict. It should NOT be the .data property of another CDS. which is actually a complicated wrapper that just happens to look like a dict. Doing the above will currently fail ungracefully. We have yet to either disallow it via an immediate exception or find a way to make it work.

Thanks,

Bryan

On Jul 30, 2018, at 14:49, Michael Hansen [email protected] wrote:

Aha right…I see.

Could I possibly persuade you show how to combine

https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/tornado_embed.py

and

https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads

That would be a really big help for understanding the overall setup

On Mon, Jul 30, 2018 at 8:21 PM, Bryan Van de ven [email protected] wrote:

Hi,

Please see the documentation regarding updating from threads:

   [https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads](https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads)

Thanks,

Bryan

On Jul 30, 2018, at 11:13, Michael Hansen [email protected] wrote:

I did find this example

and modified the code so that data is being pushed to the client rather than pulled.

When I run this i get the error:

Exception in thread Thread-1:

Traceback (most recent call last):

File “/Users/Jg/anaconda3431/lib/python3.6/threading.py”, line 916, in _bootstrap_inner

self.run()

File “/Users/Jg/anaconda3431/lib/python3.6/threading.py”, line 864, in run

self._target(*self._args, **self._kwargs)

File “tornado_embed.py”, line 43, in threaded_function

source.data = ColumnDataSource(data=data).data

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/has_props.py”, line 263, in setattr

super(HasProps, self).setattr(name, value)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 931, in set

self._internal_set(obj, value, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 727, in _internal_set

self._real_set(obj, old, value, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 796, in _real_set

self._trigger(obj, old, value, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 873, in _trigger

obj.trigger(self.name, old, value, hint, setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/model.py”, line 549, in trigger

super(Model, self).trigger(attr, old, new, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/util/callback_manager.py”, line 120, in trigger

self._document._notify_change(self, attr, old, new, hint, setter, invoke)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 941, in _notify_change

self._trigger_on_change(event)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 1049, in _trigger_on_change

self._with_self_as_curdoc(invoke_callbacks)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 1062, in _with_self_as_curdoc

return f()

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 1048, in invoke_callbacks

cb(event)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 614, in

self._callbacks[receiver] = lambda event: event.dispatch(receiver)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py”, line 195, in dispatch

super(ModelChangedEvent, self).dispatch(receiver)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py”, line 77, in dispatch

receiver._document_patched(self)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/server/session.py”, line 180, in _document_patched

raise RuntimeError("_pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes")

RuntimeError: _pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes

What am I doing wrong here?

Code is:

from jinja2 import Environment, FileSystemLoader

from tornado.web import RequestHandler

from bokeh.embed import server_document

from bokeh.layouts import column

from bokeh.models import ColumnDataSource, Slider

from bokeh.plotting import figure

from bokeh.server.server import Server

from bokeh.themes import Theme

from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature

#from threading import Thread

import threading

from time import sleep

env = Environment(loader=FileSystemLoader(‘templates’))

class IndexHandler(RequestHandler):

def get(self):

   template = env.get_template('embed.html')
   script = server_document('[http://localhost:5006/bkapp](http://localhost:5006/bkapp)')
   self.write(template.render(script=script, template="Tornado"))

def modify_doc(doc):

df = sea_surface_temperature.copy()

source = ColumnDataSource(data=df)

plot = figure(x_axis_type=‘datetime’, y_range=(0, 25), y_axis_label=‘Temperature (Celsius)’,

             title="Sea Surface Temperature at 43.18, -70.43")

plot.line(‘time’, ‘temperature’, source=source)

def threaded_function():

   sleep(3)
   for new in range(20):
       print(new)
       if new == 0:
           data = df
       else:
           data = df.rolling('{0}D'.format(new)).mean()
       source.data = ColumnDataSource(data=data).data
       sleep(1)

slider = Slider(start=0, end=30, value=0, step=1, title=“Smoothing by N Days”)

#slider.on_change(‘value’, callback)

doc.add_root(column(slider, plot))

doc.theme = Theme(filename=“theme.yaml”)

tf = threading.Thread(target=threaded_function)

tf.start()

Setting num_procs here means we can’t touch the IOLoop before now, we must

let Server handle that. If you need to explicitly handle IOLoops then you

will need to use the lower level BaseServer class.

server = Server({’/bkapp’: modify_doc}, num_procs=4, extra_patterns=[(’/’, IndexHandler)])

server.start()

if name == ‘main’:

from bokeh.util.browser import view

print(‘Opening Tornado app with embedded Bokeh application on http://localhost:5006/’)

server.io_loop.add_callback(view, “http://localhost:5006/”)

server.io_loop.start()

On Mon, Jul 30, 2018 at 5:37 PM, Bokeh coder [email protected] wrote:

Hi, is there anywhere any example of how to run bokeh server with a stream to the client in a custom tornado server fashion which works on 0.13.0?

I find the docs on how to do this a bit difficult to read and I dont understand how to get started on this - so an example would be wonderful.

Thanks

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/cb17001b-e2ca-4085-b62a-7726bfe95a1f%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/CAPty9BMctKbXjXQ1pKWwk3qkEUV%3DF-40tGK5V3HnbjUMYHOi4A%40mail.gmail.com.

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/7D078D9C-CCAD-4E6C-BBE5-6DE1E27A838D%40anaconda.com.

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/CAPty9BM%3Db5VKw7GTXwkDaMShMTTf0yq2eRGBUDMa-BtN%2B9R8ew%40mail.gmail.com.

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].

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

Well, upon further inspection, it’s possible that

    source.data = ColumnDataSource(data=data).data

Is in fact, “OK”, but it’s definitely not what I would recommend. Just set

    source.data = data

Thanks,

Bryan
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/A665241E-97BC-4451-B5A1-CF4A3F317E8D%40anaconda.com.

Hi,

Looks reasonable to me. It might be nice to add an example that demonstrates this (or update an existing one to add a custom handler), if you are interested in making a small PR.

Thanks,

Bryan

···

On Aug 1, 2018, at 13:48, Michael Hansen <[email protected]> wrote:

It seems i actually managed to do it. I got something working.
My question is now - am I doing this the right way?
All comments are greatly appreciated.
Thanks

from jinja2 import Environment, FileSystemLoader

from functools import partial

from tornado.web import RequestHandler
from tornado import gen

from bokeh.embed import server_document
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, Slider
from bokeh.plotting import figure
from bokeh.server.server import Server
from bokeh.themes import Theme

from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature

#from threading import Thread
import threading
from time import sleep
import numpy as np
from random import random

env = Environment(loader=FileSystemLoader('templates'))

class IndexHandler(RequestHandler):
    def get(self):
        template = env.get_template('embed.html')
        script = server_document('http://localhost:5006/bkapp')
        print(script)
        self.write(template.render(script=script, template="Tornado"))

@gen.coroutine
def update(x, y):
    source.stream(dict(x=, y=[y]))

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

def modify_doc(doc):
    
    plot = figure(y_axis_label='Temperature (Celsius)', y_range=(-2, 2),
                  title="Sea Surface Temperature at 43.18, -70.43") #x_axis_type='datetime', ,
    plot.line(x='x', y='y', source=source)

    doc.add_root(plot)

    doc.theme = Theme(filename="theme.yaml")

    def threaded_function():
        sleep(3)
        for new in range(20):
            sleep(1)
            doc.add_next_tick_callback(partial(update, x=new+1, y=random()))

    tf = threading.Thread(target=threaded_function)
    tf.start()

server = Server({'/bkapp': modify_doc}, num_procs=4, extra_patterns=[('/', IndexHandler)])
server.start()

if __name__ == '__main__':
    from bokeh.util.browser import view

    print('Opening Tornado app with embedded Bokeh application on http://localhost:5006/')

    server.io_loop.add_callback(view, "http://localhost:5006/")
    server.io_loop.start()

On Tue, Jul 31, 2018 at 12:20 AM, Bryan Van de ven <[email protected]> wrote:
Well, upon further inspection, it's possible that

        source.data = ColumnDataSource(data=data).data

Is in fact, "OK", but it's definitely not what I would recommend. Just set

        source.data = data

Thanks,

Bryan

> On Jul 30, 2018, at 15:12, Bryan Van de ven <[email protected]> wrote:
>
> Hi,
>
> I'm sorry, I simply don't have the bandwidth to work up an example right now. The relevant change you need to make is:
>
> * put the call to "source.data = new_data" in a small function of its own
> * have you current callback add that small function as a next_tick_callback
>
> However, I also note that you do this:
>
> source.data = ColumnDataSource(data=data).data
>
> Don't do that. The RHS of "source.data = " should always be a *plain python dict*. It should NOT be the .data property of another CDS. which is actually a complicated wrapper that just happens to look like a dict. Doing the above will currently fail ungracefully. We have yet to either disallow it via an immediate exception or find a way to make it work.
>
> Thanks,
>
> Bryan
>
>> On Jul 30, 2018, at 14:49, Michael Hansen <[email protected]> wrote:
>>
>> Aha right....I see.
>> Could I possibly persuade you show how to combine
>>
>> https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/tornado_embed.py
>> and
>> https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads
>>
>> That would be a really big help for understanding the overall setup
>>
>>
>>
>> On Mon, Jul 30, 2018 at 8:21 PM, Bryan Van de ven <[email protected]> wrote:
>> Hi,
>>
>> Please see the documentation regarding updating from threads:
>>
>> https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads
>>
>> Thanks,
>>
>> Bryan
>>
>>> On Jul 30, 2018, at 11:13, Michael Hansen <[email protected]> wrote:
>>>
>>> I did find this example
>>> and modified the code so that data is being pushed to the client rather than pulled.
>>>
>>> When I run this i get the error:
>>>
>>> Exception in thread Thread-1:
>>> Traceback (most recent call last):
>>> File "/Users/Jg/anaconda3431/lib/python3.6/threading.py", line 916, in _bootstrap_inner
>>> self.run()
>>> File "/Users/Jg/anaconda3431/lib/python3.6/threading.py", line 864, in run
>>> self._target(*self._args, **self._kwargs)
>>> File "tornado_embed.py", line 43, in threaded_function
>>> source.data = ColumnDataSource(data=data).data
>>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/has_props.py", line 263, in __setattr__
>>> super(HasProps, self).__setattr__(name, value)
>>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 931, in __set__
>>> self._internal_set(obj, value, hint=hint, setter=setter)
>>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 727, in _internal_set
>>> self._real_set(obj, old, value, hint=hint, setter=setter)
>>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 796, in _real_set
>>> self._trigger(obj, old, value, hint=hint, setter=setter)
>>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 873, in _trigger
>>> obj.trigger(self.name, old, value, hint, setter)
>>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/model.py", line 549, in trigger
>>> super(Model, self).trigger(attr, old, new, hint=hint, setter=setter)
>>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/util/callback_manager.py", line 120, in trigger
>>> self._document._notify_change(self, attr, old, new, hint, setter, invoke)
>>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 941, in _notify_change
>>> self._trigger_on_change(event)
>>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 1049, in _trigger_on_change
>>> self._with_self_as_curdoc(invoke_callbacks)
>>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 1062, in _with_self_as_curdoc
>>> return f()
>>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 1048, in invoke_callbacks
>>> cb(event)
>>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 614, in <lambda>
>>> self._callbacks[receiver] = lambda event: event.dispatch(receiver)
>>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py", line 195, in dispatch
>>> super(ModelChangedEvent, self).dispatch(receiver)
>>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py", line 77, in dispatch
>>> receiver._document_patched(self)
>>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/server/session.py", line 180, in _document_patched
>>> raise RuntimeError("_pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes")
>>> RuntimeError: _pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes
>>>
>>>
>>> What am I doing wrong here?
>>>
>>> Code is:
>>>
>>> from jinja2 import Environment, FileSystemLoader
>>>
>>> from tornado.web import RequestHandler
>>>
>>> from bokeh.embed import server_document
>>> from bokeh.layouts import column
>>> from bokeh.models import ColumnDataSource, Slider
>>> from bokeh.plotting import figure
>>> from bokeh.server.server import Server
>>> from bokeh.themes import Theme
>>>
>>> from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature
>>>
>>> #from threading import Thread
>>> import threading
>>> from time import sleep
>>>
>>> env = Environment(loader=FileSystemLoader('templates'))
>>>
>>> class IndexHandler(RequestHandler):
>>> def get(self):
>>> template = env.get_template('embed.html')
>>> script = server_document('http://localhost:5006/bkapp')
>>> self.write(template.render(script=script, template="Tornado"))
>>>
>>> def modify_doc(doc):
>>> df = sea_surface_temperature.copy()
>>> source = ColumnDataSource(data=df)
>>>
>>> plot = figure(x_axis_type='datetime', y_range=(0, 25), y_axis_label='Temperature (Celsius)',
>>> title="Sea Surface Temperature at 43.18, -70.43")
>>> plot.line('time', 'temperature', source=source)
>>>
>>>
>>> def threaded_function():
>>> sleep(3)
>>> for new in range(20):
>>> print(new)
>>> if new == 0:
>>> data = df
>>> else:
>>> data = df.rolling('{0}D'.format(new)).mean()
>>> source.data = ColumnDataSource(data=data).data
>>> sleep(1)
>>>
>>> slider = Slider(start=0, end=30, value=0, step=1, title="Smoothing by N Days")
>>> #slider.on_change('value', callback)
>>>
>>> doc.add_root(column(slider, plot))
>>>
>>> doc.theme = Theme(filename="theme.yaml")
>>> tf = threading.Thread(target=threaded_function)
>>> tf.start()
>>>
>>> # Setting num_procs here means we can't touch the IOLoop before now, we must
>>> # let Server handle that. If you need to explicitly handle IOLoops then you
>>> # will need to use the lower level BaseServer class.
>>> server = Server({'/bkapp': modify_doc}, num_procs=4, extra_patterns=[('/', IndexHandler)])
>>> server.start()
>>>
>>> if __name__ == '__main__':
>>> from bokeh.util.browser import view
>>>
>>> print('Opening Tornado app with embedded Bokeh application on http://localhost:5006/')
>>>
>>> server.io_loop.add_callback(view, "http://localhost:5006/")
>>> server.io_loop.start()
>>>
>>>
>>> On Mon, Jul 30, 2018 at 5:37 PM, Bokeh coder <[email protected]> wrote:
>>> Hi, is there anywhere any example of how to run bokeh server with a stream to the client in a custom tornado server fashion which works on 0.13.0?
>>> I find the docs on how to do this a bit difficult to read and I dont understand how to get started on this - so an example would be wonderful.
>>>
>>> Thanks
>>>
>>>
>>> --
>>> 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/cb17001b-e2ca-4085-b62a-7726bfe95a1f%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/CAPty9BMctKbXjXQ1pKWwk3qkEUV%3DF-40tGK5V3HnbjUMYHOi4A%40mail.gmail.com.
>>> 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/7D078D9C-CCAD-4E6C-BBE5-6DE1E27A838D%40anaconda.com.
>> 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]nuum.io.
>> 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/CAPty9BM%3Db5VKw7GTXwkDaMShMTTf0yq2eRGBUDMa-BtN%2B9R8ew%40mail.gmail.com.
>> 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/A665241E-97BC-4451-B5A1-CF4A3F317E8D%40anaconda.com.
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/CAPty9BMh7qKesHn0q4eXHCuNbE3nCUMu%3DBSQF6jhsTGvBbWyCQ%40mail.gmail.com.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Yes, will definitely do that.
However it might be that I should fix a problem with this code which I just found first.

It seems that if i load the page, let it run a bit and then refresh the page i am getting this error:

Models must be owned by only a single document

Do you have any idea why I would be getting this?

···

On Wed, Aug 1, 2018 at 11:01 PM, Bryan Van de ven [email protected] wrote:

Hi,

Looks reasonable to me. It might be nice to add an example that demonstrates this (or update an existing one to add a custom handler), if you are interested in making a small PR.

Thanks,

Bryan

On Aug 1, 2018, at 13:48, Michael Hansen [email protected] wrote:

It seems i actually managed to do it. I got something working.

My question is now - am I doing this the right way?

All comments are greatly appreciated.

Thanks

from jinja2 import Environment, FileSystemLoader

from functools import partial

from tornado.web import RequestHandler

from tornado import gen

from bokeh.embed import server_document

from bokeh.layouts import column

from bokeh.models import ColumnDataSource, Slider

from bokeh.plotting import figure

from bokeh.server.server import Server

from bokeh.themes import Theme

from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature

#from threading import Thread

import threading

from time import sleep

import numpy as np

from random import random

env = Environment(loader=FileSystemLoader(‘templates’))

class IndexHandler(RequestHandler):

def get(self):
    template = env.get_template('embed.html')
    script = server_document('[http://localhost:5006/bkapp](http://localhost:5006/bkapp)')
    print(script)
    self.write(template.render(script=script, template="Tornado"))

@gen.coroutine

def update(x, y):

source.stream(dict(x=[x], y=[y]))

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

def modify_doc(doc):

plot = figure(y_axis_label='Temperature (Celsius)', y_range=(-2, 2),
              title="Sea Surface Temperature at 43.18, -70.43") #x_axis_type='datetime', ,
plot.line(x='x', y='y', source=source)
doc.add_root(plot)
doc.theme = Theme(filename="theme.yaml")
def threaded_function():
    sleep(3)
    for new in range(20):
        sleep(1)
        doc.add_next_tick_callback(partial(update, x=new+1, y=random()))
tf = threading.Thread(target=threaded_function)
tf.start()

server = Server({’/bkapp’: modify_doc}, num_procs=4, extra_patterns=[(’/’, IndexHandler)])

server.start()

if name == ‘main’:

from bokeh.util.browser import view
print('Opening Tornado app with embedded Bokeh application on [http://localhost:5006/](http://localhost:5006/)')
server.io_loop.add_callback(view, "[http://localhost:5006/](http://localhost:5006/)")
server.io_loop.start()

On Tue, Jul 31, 2018 at 12:20 AM, Bryan Van de ven [email protected] wrote:

Well, upon further inspection, it’s possible that

    source.data = ColumnDataSource(data=data).data

Is in fact, “OK”, but it’s definitely not what I would recommend. Just set

    source.data = data

Thanks,

Bryan

On Jul 30, 2018, at 15:12, Bryan Van de ven [email protected] wrote:

Hi,

I’m sorry, I simply don’t have the bandwidth to work up an example right now. The relevant change you need to make is:

  • put the call to “source.data = new_data” in a small function of its own
  • have you current callback add that small function as a next_tick_callback

However, I also note that you do this:

   source.data = ColumnDataSource(data=data).data

Don’t do that. The RHS of "source.data = " should always be a plain python dict. It should NOT be the .data property of another CDS. which is actually a complicated wrapper that just happens to look like a dict. Doing the above will currently fail ungracefully. We have yet to either disallow it via an immediate exception or find a way to make it work.

Thanks,

Bryan

On Jul 30, 2018, at 14:49, Michael Hansen [email protected] wrote:

Aha right…I see.

Could I possibly persuade you show how to combine

https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/tornado_embed.py

and

https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads

That would be a really big help for understanding the overall setup

On Mon, Jul 30, 2018 at 8:21 PM, Bryan Van de ven [email protected] wrote:

Hi,

Please see the documentation regarding updating from threads:

   [https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads](https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads)

Thanks,

Bryan

On Jul 30, 2018, at 11:13, Michael Hansen [email protected] wrote:

I did find this example

and modified the code so that data is being pushed to the client rather than pulled.

When I run this i get the error:

Exception in thread Thread-1:

Traceback (most recent call last):

File “/Users/Jg/anaconda3431/lib/python3.6/threading.py”, line 916, in _bootstrap_inner

self.run()

File “/Users/Jg/anaconda3431/lib/python3.6/threading.py”, line 864, in run

self._target(*self._args, **self._kwargs)

File “tornado_embed.py”, line 43, in threaded_function

source.data = ColumnDataSource(data=data).data

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/has_props.py”, line 263, in setattr

super(HasProps, self).setattr(name, value)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 931, in set

self._internal_set(obj, value, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 727, in _internal_set

self._real_set(obj, old, value, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 796, in _real_set

self._trigger(obj, old, value, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 873, in _trigger

obj.trigger(self.name, old, value, hint, setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/model.py”, line 549, in trigger

super(Model, self).trigger(attr, old, new, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/util/callback_manager.py”, line 120, in trigger

self._document._notify_change(self, attr, old, new, hint, setter, invoke)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 941, in _notify_change

self._trigger_on_change(event)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 1049, in _trigger_on_change

self._with_self_as_curdoc(invoke_callbacks)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 1062, in _with_self_as_curdoc

return f()

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 1048, in invoke_callbacks

cb(event)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 614, in

self._callbacks[receiver] = lambda event: event.dispatch(receiver)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py”, line 195, in dispatch

super(ModelChangedEvent, self).dispatch(receiver)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py”, line 77, in dispatch

receiver._document_patched(self)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/server/session.py”, line 180, in _document_patched

raise RuntimeError("_pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes")

RuntimeError: _pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes

What am I doing wrong here?

Code is:

from jinja2 import Environment, FileSystemLoader

from tornado.web import RequestHandler

from bokeh.embed import server_document

from bokeh.layouts import column

from bokeh.models import ColumnDataSource, Slider

from bokeh.plotting import figure

from bokeh.server.server import Server

from bokeh.themes import Theme

from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature

#from threading import Thread

import threading

from time import sleep

env = Environment(loader=FileSystemLoader(‘templates’))

class IndexHandler(RequestHandler):

def get(self):

   template = env.get_template('embed.html')
   script = server_document('[http://localhost:5006/bkapp](http://localhost:5006/bkapp)')
   self.write(template.render(script=script, template="Tornado"))

def modify_doc(doc):

df = sea_surface_temperature.copy()

source = ColumnDataSource(data=df)

plot = figure(x_axis_type=‘datetime’, y_range=(0, 25), y_axis_label=‘Temperature (Celsius)’,

             title="Sea Surface Temperature at 43.18, -70.43")

plot.line(‘time’, ‘temperature’, source=source)

def threaded_function():

   sleep(3)
   for new in range(20):
       print(new)
       if new == 0:
           data = df
       else:
           data = df.rolling('{0}D'.format(new)).mean()
       source.data = ColumnDataSource(data=data).data
       sleep(1)

slider = Slider(start=0, end=30, value=0, step=1, title=“Smoothing by N Days”)

#slider.on_change(‘value’, callback)

doc.add_root(column(slider, plot))

doc.theme = Theme(filename=“theme.yaml”)

tf = threading.Thread(target=threaded_function)

tf.start()

Setting num_procs here means we can’t touch the IOLoop before now, we must

let Server handle that. If you need to explicitly handle IOLoops then you

will need to use the lower level BaseServer class.

server = Server({’/bkapp’: modify_doc}, num_procs=4, extra_patterns=[(’/’, IndexHandler)])

server.start()

if name == ‘main’:

from bokeh.util.browser import view

print(‘Opening Tornado app with embedded Bokeh application on http://localhost:5006/’)

server.io_loop.add_callback(view, “http://localhost:5006/”)

server.io_loop.start()

On Mon, Jul 30, 2018 at 5:37 PM, Bokeh coder [email protected] wrote:

Hi, is there anywhere any example of how to run bokeh server with a stream to the client in a custom tornado server fashion which works on 0.13.0?

I find the docs on how to do this a bit difficult to read and I dont understand how to get started on this - so an example would be wonderful.

Thanks

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/cb17001b-e2ca-4085-b62a-7726bfe95a1f%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/CAPty9BMctKbXjXQ1pKWwk3qkEUV%3DF-40tGK5V3HnbjUMYHOi4A%40mail.gmail.com.

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/7D078D9C-CCAD-4E6C-BBE5-6DE1E27A838D%40anaconda.com.

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/CAPty9BM%3Db5VKw7GTXwkDaMShMTTf0yq2eRGBUDMa-BtN%2B9R8ew%40mail.gmail.com.

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/A665241E-97BC-4451-B5A1-CF4A3F317E8D%40anaconda.com.

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]o.

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/CAPty9BMh7qKesHn0q4eXHCuNbE3nCUMu%3DBSQF6jhsTGvBbWyCQ%40mail.gmail.com.

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/1B51F206-D72A-496F-8970-E1B16C8D9CB0%40anaconda.com.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Hi,

Oh, I missed it in the quick glance, but the problem is your defining source globally, outside modify_doc. The application handler (i.e. in this case the modify_doc function) *always* must return a new, unique collection of Bokeh objects for each session. You can't create a single source and share/re-use it between sessions like that.

Bryan

···

On Aug 1, 2018, at 14:04, Michael Hansen <[email protected]> wrote:

Yes, will definitely do that.
However it might be that I should fix a problem with this code which I just found first.
It seems that if i load the page, let it run a bit and then refresh the page i am getting this error:

Models must be owned by only a single document

Do you have any idea why I would be getting this?

On Wed, Aug 1, 2018 at 11:01 PM, Bryan Van de ven <[email protected]> wrote:
Hi,

Looks reasonable to me. It might be nice to add an example that demonstrates this (or update an existing one to add a custom handler), if you are interested in making a small PR.

Thanks,

Bryan

> On Aug 1, 2018, at 13:48, Michael Hansen <[email protected]> wrote:
>
> It seems i actually managed to do it. I got something working.
> My question is now - am I doing this the right way?
> All comments are greatly appreciated.
> Thanks
>
>
> from jinja2 import Environment, FileSystemLoader
>
> from functools import partial
>
> from tornado.web import RequestHandler
> from tornado import gen
>
> from bokeh.embed import server_document
> from bokeh.layouts import column
> from bokeh.models import ColumnDataSource, Slider
> from bokeh.plotting import figure
> from bokeh.server.server import Server
> from bokeh.themes import Theme
>
> from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature
>
> #from threading import Thread
> import threading
> from time import sleep
> import numpy as np
> from random import random
>
> env = Environment(loader=FileSystemLoader('templates'))
>
> class IndexHandler(RequestHandler):
> def get(self):
> template = env.get_template('embed.html')
> script = server_document('http://localhost:5006/bkapp')
> print(script)
> self.write(template.render(script=script, template="Tornado"))
>
> @gen.coroutine
> def update(x, y):
> source.stream(dict(x=, y=[y]))
>
> source = ColumnDataSource(data=dict(x=[0], y=[0]))
>
> def modify_doc(doc):
>
>
> plot = figure(y_axis_label='Temperature (Celsius)', y_range=(-2, 2),
> title="Sea Surface Temperature at 43.18, -70.43") #x_axis_type='datetime', ,
> plot.line(x='x', y='y', source=source)
>
> doc.add_root(plot)
>
> doc.theme = Theme(filename="theme.yaml")
>
> def threaded_function():
> sleep(3)
> for new in range(20):
> sleep(1)
> doc.add_next_tick_callback(partial(update, x=new+1, y=random()))
>
>
> tf = threading.Thread(target=threaded_function)
> tf.start()
>
> server = Server({'/bkapp': modify_doc}, num_procs=4, extra_patterns=[('/', IndexHandler)])
> server.start()
>
> if __name__ == '__main__':
> from bokeh.util.browser import view
>
> print('Opening Tornado app with embedded Bokeh application on http://localhost:5006/')
>
> server.io_loop.add_callback(view, "http://localhost:5006/")
> server.io_loop.start()
>
>
> On Tue, Jul 31, 2018 at 12:20 AM, Bryan Van de ven <[email protected]> wrote:
> Well, upon further inspection, it's possible that
>
> source.data = ColumnDataSource(data=data).data
>
> Is in fact, "OK", but it's definitely not what I would recommend. Just set
>
> source.data = data
>
> Thanks,
>
> Bryan
>
> > On Jul 30, 2018, at 15:12, Bryan Van de ven <[email protected]> wrote:
> >
> > Hi,
> >
> > I'm sorry, I simply don't have the bandwidth to work up an example right now. The relevant change you need to make is:
> >
> > * put the call to "source.data = new_data" in a small function of its own
> > * have you current callback add that small function as a next_tick_callback
> >
> > However, I also note that you do this:
> >
> > source.data = ColumnDataSource(data=data).data
> >
> > Don't do that. The RHS of "source.data = " should always be a *plain python dict*. It should NOT be the .data property of another CDS. which is actually a complicated wrapper that just happens to look like a dict. Doing the above will currently fail ungracefully. We have yet to either disallow it via an immediate exception or find a way to make it work.
> >
> > Thanks,
> >
> > Bryan
> >
> >> On Jul 30, 2018, at 14:49, Michael Hansen <[email protected]> wrote:
> >>
> >> Aha right....I see.
> >> Could I possibly persuade you show how to combine
> >>
> >> https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/tornado_embed.py
> >> and
> >> https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads
> >>
> >> That would be a really big help for understanding the overall setup
> >>
> >>
> >>
> >> On Mon, Jul 30, 2018 at 8:21 PM, Bryan Van de ven <[email protected]> wrote:
> >> Hi,
> >>
> >> Please see the documentation regarding updating from threads:
> >>
> >> https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads
> >>
> >> Thanks,
> >>
> >> Bryan
> >>
> >>> On Jul 30, 2018, at 11:13, Michael Hansen <[email protected]> wrote:
> >>>
> >>> I did find this example
> >>> and modified the code so that data is being pushed to the client rather than pulled.
> >>>
> >>> When I run this i get the error:
> >>>
> >>> Exception in thread Thread-1:
> >>> Traceback (most recent call last):
> >>> File "/Users/Jg/anaconda3431/lib/python3.6/threading.py", line 916, in _bootstrap_inner
> >>> self.run()
> >>> File "/Users/Jg/anaconda3431/lib/python3.6/threading.py", line 864, in run
> >>> self._target(*self._args, **self._kwargs)
> >>> File "tornado_embed.py", line 43, in threaded_function
> >>> source.data = ColumnDataSource(data=data).data
> >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/has_props.py", line 263, in __setattr__
> >>> super(HasProps, self).__setattr__(name, value)
> >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 931, in __set__
> >>> self._internal_set(obj, value, hint=hint, setter=setter)
> >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 727, in _internal_set
> >>> self._real_set(obj, old, value, hint=hint, setter=setter)
> >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 796, in _real_set
> >>> self._trigger(obj, old, value, hint=hint, setter=setter)
> >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 873, in _trigger
> >>> obj.trigger(self.name, old, value, hint, setter)
> >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/model.py", line 549, in trigger
> >>> super(Model, self).trigger(attr, old, new, hint=hint, setter=setter)
> >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/util/callback_manager.py", line 120, in trigger
> >>> self._document._notify_change(self, attr, old, new, hint, setter, invoke)
> >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 941, in _notify_change
> >>> self._trigger_on_change(event)
> >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 1049, in _trigger_on_change
> >>> self._with_self_as_curdoc(invoke_callbacks)
> >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 1062, in _with_self_as_curdoc
> >>> return f()
> >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 1048, in invoke_callbacks
> >>> cb(event)
> >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 614, in <lambda>
> >>> self._callbacks[receiver] = lambda event: event.dispatch(receiver)
> >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py", line 195, in dispatch
> >>> super(ModelChangedEvent, self).dispatch(receiver)
> >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py", line 77, in dispatch
> >>> receiver._document_patched(self)
> >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/server/session.py", line 180, in _document_patched
> >>> raise RuntimeError("_pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes")
> >>> RuntimeError: _pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes
> >>>
> >>>
> >>> What am I doing wrong here?
> >>>
> >>> Code is:
> >>>
> >>> from jinja2 import Environment, FileSystemLoader
> >>>
> >>> from tornado.web import RequestHandler
> >>>
> >>> from bokeh.embed import server_document
> >>> from bokeh.layouts import column
> >>> from bokeh.models import ColumnDataSource, Slider
> >>> from bokeh.plotting import figure
> >>> from bokeh.server.server import Server
> >>> from bokeh.themes import Theme
> >>>
> >>> from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature
> >>>
> >>> #from threading import Thread
> >>> import threading
> >>> from time import sleep
> >>>
> >>> env = Environment(loader=FileSystemLoader('templates'))
> >>>
> >>> class IndexHandler(RequestHandler):
> >>> def get(self):
> >>> template = env.get_template('embed.html')
> >>> script = server_document('http://localhost:5006/bkapp')
> >>> self.write(template.render(script=script, template="Tornado"))
> >>>
> >>> def modify_doc(doc):
> >>> df = sea_surface_temperature.copy()
> >>> source = ColumnDataSource(data=df)
> >>>
> >>> plot = figure(x_axis_type='datetime', y_range=(0, 25), y_axis_label='Temperature (Celsius)',
> >>> title="Sea Surface Temperature at 43.18, -70.43")
> >>> plot.line('time', 'temperature', source=source)
> >>>
> >>>
> >>> def threaded_function():
> >>> sleep(3)
> >>> for new in range(20):
> >>> print(new)
> >>> if new == 0:
> >>> data = df
> >>> else:
> >>> data = df.rolling('{0}D'.format(new)).mean()
> >>> source.data = ColumnDataSource(data=data).data
> >>> sleep(1)
> >>>
> >>> slider = Slider(start=0, end=30, value=0, step=1, title="Smoothing by N Days")
> >>> #slider.on_change('value', callback)
> >>>
> >>> doc.add_root(column(slider, plot))
> >>>
> >>> doc.theme = Theme(filename="theme.yaml")
> >>> tf = threading.Thread(target=threaded_function)
> >>> tf.start()
> >>>
> >>> # Setting num_procs here means we can't touch the IOLoop before now, we must
> >>> # let Server handle that. If you need to explicitly handle IOLoops then you
> >>> # will need to use the lower level BaseServer class.
> >>> server = Server({'/bkapp': modify_doc}, num_procs=4, extra_patterns=[('/', IndexHandler)])
> >>> server.start()
> >>>
> >>> if __name__ == '__main__':
> >>> from bokeh.util.browser import view
> >>>
> >>> print('Opening Tornado app with embedded Bokeh application on http://localhost:5006/')
> >>>
> >>> server.io_loop.add_callback(view, "http://localhost:5006/")
> >>> server.io_loop.start()
> >>>
> >>>
> >>> On Mon, Jul 30, 2018 at 5:37 PM, Bokeh coder <[email protected]> wrote:
> >>> Hi, is there anywhere any example of how to run bokeh server with a stream to the client in a custom tornado server fashion which works on 0.13.0?
> >>> I find the docs on how to do this a bit difficult to read and I dont understand how to get started on this - so an example would be wonderful.
> >>>
> >>> Thanks
> >>>
> >>>
> >>> --
> >>> 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/cb17001b-e2ca-4085-b62a-7726bfe95a1f%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/CAPty9BMctKbXjXQ1pKWwk3qkEUV%3DF-40tGK5V3HnbjUMYHOi4A%40mail.gmail.com.
> >>> 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/7D078D9C-CCAD-4E6C-BBE5-6DE1E27A838D%40anaconda.com.
> >> 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/CAPty9BM%3Db5VKw7GTXwkDaMShMTTf0yq2eRGBUDMa-BtN%2B9R8ew%40mail.gmail.com.
> >> 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/A665241E-97BC-4451-B5A1-CF4A3F317E8D%40anaconda.com.
> 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/CAPty9BMh7qKesHn0q4eXHCuNbE3nCUMu%3DBSQF6jhsTGvBbWyCQ%40mail.gmail.com.
> 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/1B51F206-D72A-496F-8970-E1B16C8D9CB0%40anaconda.com.
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/CAPty9BPYsrO3hgqu4%3DcoOzESFOsHYi6nvmWf4BovPsOm0ENTjg%40mail.gmail.com.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

ahh yes of course.
How clumsy of me - I now moved both the source declaration as well as the update function inside the modify_doc function which seems to be working great.

Unless you dont have any more comments on how this code is made I will polish it of a bit and make a PR with that example

···

On Wed, Aug 1, 2018 at 11:08 PM, Bryan Van de ven [email protected] wrote:

Hi,

Oh, I missed it in the quick glance, but the problem is your defining source globally, outside modify_doc. The application handler (i.e. in this case the modify_doc function) always must return a new, unique collection of Bokeh objects for each session. You can’t create a single source and share/re-use it between sessions like that.

Bryan

On Aug 1, 2018, at 14:04, Michael Hansen [email protected] wrote:

Yes, will definitely do that.

However it might be that I should fix a problem with this code which I just found first.

It seems that if i load the page, let it run a bit and then refresh the page i am getting this error:

Models must be owned by only a single document

Do you have any idea why I would be getting this?

On Wed, Aug 1, 2018 at 11:01 PM, Bryan Van de ven [email protected] wrote:

Hi,

Looks reasonable to me. It might be nice to add an example that demonstrates this (or update an existing one to add a custom handler), if you are interested in making a small PR.

Thanks,

Bryan

On Aug 1, 2018, at 13:48, Michael Hansen [email protected] wrote:

It seems i actually managed to do it. I got something working.

My question is now - am I doing this the right way?

All comments are greatly appreciated.

Thanks

from jinja2 import Environment, FileSystemLoader

from functools import partial

from tornado.web import RequestHandler

from tornado import gen

from bokeh.embed import server_document

from bokeh.layouts import column

from bokeh.models import ColumnDataSource, Slider

from bokeh.plotting import figure

from bokeh.server.server import Server

from bokeh.themes import Theme

from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature

#from threading import Thread

import threading

from time import sleep

import numpy as np

from random import random

env = Environment(loader=FileSystemLoader(‘templates’))

class IndexHandler(RequestHandler):

def get(self):
    template = env.get_template('embed.html')
    script = server_document('[http://localhost:5006/bkapp](http://localhost:5006/bkapp)')
    print(script)
    self.write(template.render(script=script, template="Tornado"))

@gen.coroutine

def update(x, y):

source.stream(dict(x=[x], y=[y]))

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

def modify_doc(doc):

plot = figure(y_axis_label='Temperature (Celsius)', y_range=(-2, 2),
              title="Sea Surface Temperature at 43.18, -70.43") #x_axis_type='datetime', ,
plot.line(x='x', y='y', source=source)
doc.add_root(plot)
doc.theme = Theme(filename="theme.yaml")
def threaded_function():
    sleep(3)
    for new in range(20):
        sleep(1)
        doc.add_next_tick_callback(partial(update, x=new+1, y=random()))
tf = threading.Thread(target=threaded_function)
tf.start()

server = Server({’/bkapp’: modify_doc}, num_procs=4, extra_patterns=[(’/’, IndexHandler)])

server.start()

if name == ‘main’:

from bokeh.util.browser import view
print('Opening Tornado app with embedded Bokeh application on [http://localhost:5006/](http://localhost:5006/)')
server.io_loop.add_callback(view, "[http://localhost:5006/](http://localhost:5006/)")
server.io_loop.start()

On Tue, Jul 31, 2018 at 12:20 AM, Bryan Van de ven [email protected] wrote:

Well, upon further inspection, it’s possible that

    source.data = ColumnDataSource(data=data).data

Is in fact, “OK”, but it’s definitely not what I would recommend. Just set

    source.data = data

Thanks,

Bryan

On Jul 30, 2018, at 15:12, Bryan Van de ven [email protected] wrote:

Hi,

I’m sorry, I simply don’t have the bandwidth to work up an example right now. The relevant change you need to make is:

  • put the call to “source.data = new_data” in a small function of its own
  • have you current callback add that small function as a next_tick_callback

However, I also note that you do this:

   source.data = ColumnDataSource(data=data).data

Don’t do that. The RHS of "source.data = " should always be a plain python dict. It should NOT be the .data property of another CDS. which is actually a complicated wrapper that just happens to look like a dict. Doing the above will currently fail ungracefully. We have yet to either disallow it via an immediate exception or find a way to make it work.

Thanks,

Bryan

On Jul 30, 2018, at 14:49, Michael Hansen [email protected] wrote:

Aha right…I see.

Could I possibly persuade you show how to combine

https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/tornado_embed.py

and

https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads

That would be a really big help for understanding the overall setup

On Mon, Jul 30, 2018 at 8:21 PM, Bryan Van de ven [email protected] wrote:

Hi,

Please see the documentation regarding updating from threads:

   [https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads](https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads)

Thanks,

Bryan

On Jul 30, 2018, at 11:13, Michael Hansen [email protected] wrote:

I did find this example

and modified the code so that data is being pushed to the client rather than pulled.

When I run this i get the error:

Exception in thread Thread-1:

Traceback (most recent call last):

File “/Users/Jg/anaconda3431/lib/python3.6/threading.py”, line 916, in _bootstrap_inner

self.run()

File “/Users/Jg/anaconda3431/lib/python3.6/threading.py”, line 864, in run

self._target(*self._args, **self._kwargs)

File “tornado_embed.py”, line 43, in threaded_function

source.data = ColumnDataSource(data=data).data

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/has_props.py”, line 263, in setattr

super(HasProps, self).setattr(name, value)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 931, in set

self._internal_set(obj, value, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 727, in _internal_set

self._real_set(obj, old, value, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 796, in _real_set

self._trigger(obj, old, value, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py”, line 873, in _trigger

obj.trigger(self.name, old, value, hint, setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/model.py”, line 549, in trigger

super(Model, self).trigger(attr, old, new, hint=hint, setter=setter)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/util/callback_manager.py”, line 120, in trigger

self._document._notify_change(self, attr, old, new, hint, setter, invoke)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 941, in _notify_change

self._trigger_on_change(event)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 1049, in _trigger_on_change

self._with_self_as_curdoc(invoke_callbacks)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 1062, in _with_self_as_curdoc

return f()

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 1048, in invoke_callbacks

cb(event)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py”, line 614, in

self._callbacks[receiver] = lambda event: event.dispatch(receiver)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py”, line 195, in dispatch

super(ModelChangedEvent, self).dispatch(receiver)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py”, line 77, in dispatch

receiver._document_patched(self)

File “/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/server/session.py”, line 180, in _document_patched

raise RuntimeError("_pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes")

RuntimeError: _pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes

What am I doing wrong here?

Code is:

from jinja2 import Environment, FileSystemLoader

from tornado.web import RequestHandler

from bokeh.embed import server_document

from bokeh.layouts import column

from bokeh.models import ColumnDataSource, Slider

from bokeh.plotting import figure

from bokeh.server.server import Server

from bokeh.themes import Theme

from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature

#from threading import Thread

import threading

from time import sleep

env = Environment(loader=FileSystemLoader(‘templates’))

class IndexHandler(RequestHandler):

def get(self):

   template = env.get_template('embed.html')
   script = server_document('[http://localhost:5006/bkapp](http://localhost:5006/bkapp)')
   self.write(template.render(script=script, template="Tornado"))

def modify_doc(doc):

df = sea_surface_temperature.copy()

source = ColumnDataSource(data=df)

plot = figure(x_axis_type=‘datetime’, y_range=(0, 25), y_axis_label=‘Temperature (Celsius)’,

             title="Sea Surface Temperature at 43.18, -70.43")

plot.line(‘time’, ‘temperature’, source=source)

def threaded_function():

   sleep(3)
   for new in range(20):
       print(new)
       if new == 0:
           data = df
       else:
           data = df.rolling('{0}D'.format(new)).mean()
       source.data = ColumnDataSource(data=data).data
       sleep(1)

slider = Slider(start=0, end=30, value=0, step=1, title=“Smoothing by N Days”)

#slider.on_change(‘value’, callback)

doc.add_root(column(slider, plot))

doc.theme = Theme(filename=“theme.yaml”)

tf = threading.Thread(target=threaded_function)

tf.start()

Setting num_procs here means we can’t touch the IOLoop before now, we must

let Server handle that. If you need to explicitly handle IOLoops then you

will need to use the lower level BaseServer class.

server = Server({’/bkapp’: modify_doc}, num_procs=4, extra_patterns=[(’/’, IndexHandler)])

server.start()

if name == ‘main’:

from bokeh.util.browser import view

print(‘Opening Tornado app with embedded Bokeh application on http://localhost:5006/’)

server.io_loop.add_callback(view, “http://localhost:5006/”)

server.io_loop.start()

On Mon, Jul 30, 2018 at 5:37 PM, Bokeh coder michaelsven[email protected] wrote:

Hi, is there anywhere any example of how to run bokeh server with a stream to the client in a custom tornado server fashion which works on 0.13.0?

I find the docs on how to do this a bit difficult to read and I dont understand how to get started on this - so an example would be wonderful.

Thanks

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/cb17001b-e2ca-4085-b62a-7726bfe95a1f%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/CAPty9BMctKbXjXQ1pKWwk3qkEUV%3DF-40tGK5V3HnbjUMYHOi4A%40mail.gmail.com.

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/7D078D9C-CCAD-4E6C-BBE5-6DE1E27A838D%40anaconda.com.

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/CAPty9BM%3Db5VKw7GTXwkDaMShMTTf0yq2eRGBUDMa-BtN%2B9R8ew%40mail.gmail.com.

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/A665241E-97BC-4451-B5A1-CF4A3F317E8D%40anaconda.com.

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/CAPty9BMh7qKesHn0q4eXHCuNbE3nCUMu%3DBSQF6jhsTGvBbWyCQ%40mail.gmail.com.

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/1B51F206-D72A-496F-8970-E1B16C8D9CB0%40anaconda.com.

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/CAPty9BPYsrO3hgqu4%3DcoOzESFOsHYi6nvmWf4BovPsOm0ENTjg%40mail.gmail.com.

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/BB237626-686A-4265-BB45-E7E104BC758B%40anaconda.com.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Sounds great!

···

On Aug 1, 2018, at 14:16, Michael Hansen <[email protected]> wrote:

ahh yes of course.
How clumsy of me - I now moved both the source declaration as well as the update function inside the modify_doc function which seems to be working great.
Unless you dont have any more comments on how this code is made I will polish it of a bit and make a PR with that example

On Wed, Aug 1, 2018 at 11:08 PM, Bryan Van de ven <[email protected]> wrote:
Hi,

Oh, I missed it in the quick glance, but the problem is your defining source globally, outside modify_doc. The application handler (i.e. in this case the modify_doc function) *always* must return a new, unique collection of Bokeh objects for each session. You can't create a single source and share/re-use it between sessions like that.

Bryan

> On Aug 1, 2018, at 14:04, Michael Hansen <[email protected]> wrote:
>
> Yes, will definitely do that.
> However it might be that I should fix a problem with this code which I just found first.
> It seems that if i load the page, let it run a bit and then refresh the page i am getting this error:
>
> Models must be owned by only a single document
>
> Do you have any idea why I would be getting this?
>
> On Wed, Aug 1, 2018 at 11:01 PM, Bryan Van de ven <[email protected]> wrote:
> Hi,
>
> Looks reasonable to me. It might be nice to add an example that demonstrates this (or update an existing one to add a custom handler), if you are interested in making a small PR.
>
> Thanks,
>
> Bryan
>
> > On Aug 1, 2018, at 13:48, Michael Hansen <[email protected]> wrote:
> >
> > It seems i actually managed to do it. I got something working.
> > My question is now - am I doing this the right way?
> > All comments are greatly appreciated.
> > Thanks
> >
> >
> > from jinja2 import Environment, FileSystemLoader
> >
> > from functools import partial
> >
> > from tornado.web import RequestHandler
> > from tornado import gen
> >
> > from bokeh.embed import server_document
> > from bokeh.layouts import column
> > from bokeh.models import ColumnDataSource, Slider
> > from bokeh.plotting import figure
> > from bokeh.server.server import Server
> > from bokeh.themes import Theme
> >
> > from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature
> >
> > #from threading import Thread
> > import threading
> > from time import sleep
> > import numpy as np
> > from random import random
> >
> > env = Environment(loader=FileSystemLoader('templates'))
> >
> > class IndexHandler(RequestHandler):
> > def get(self):
> > template = env.get_template('embed.html')
> > script = server_document('http://localhost:5006/bkapp')
> > print(script)
> > self.write(template.render(script=script, template="Tornado"))
> >
> > @gen.coroutine
> > def update(x, y):
> > source.stream(dict(x=, y=[y]))
> >
> > source = ColumnDataSource(data=dict(x=[0], y=[0]))
> >
> > def modify_doc(doc):
> >
> >
> > plot = figure(y_axis_label='Temperature (Celsius)', y_range=(-2, 2),
> > title="Sea Surface Temperature at 43.18, -70.43") #x_axis_type='datetime', ,
> > plot.line(x='x', y='y', source=source)
> >
> > doc.add_root(plot)
> >
> > doc.theme = Theme(filename="theme.yaml")
> >
> > def threaded_function():
> > sleep(3)
> > for new in range(20):
> > sleep(1)
> > doc.add_next_tick_callback(partial(update, x=new+1, y=random()))
> >
> >
> > tf = threading.Thread(target=threaded_function)
> > tf.start()
> >
> > server = Server({'/bkapp': modify_doc}, num_procs=4, extra_patterns=[('/', IndexHandler)])
> > server.start()
> >
> > if __name__ == '__main__':
> > from bokeh.util.browser import view
> >
> > print('Opening Tornado app with embedded Bokeh application on http://localhost:5006/')
> >
> > server.io_loop.add_callback(view, "http://localhost:5006/")
> > server.io_loop.start()
> >
> >
> > On Tue, Jul 31, 2018 at 12:20 AM, Bryan Van de ven <[email protected]> wrote:
> > Well, upon further inspection, it's possible that
> >
> > source.data = ColumnDataSource(data=data).data
> >
> > Is in fact, "OK", but it's definitely not what I would recommend. Just set
> >
> > source.data = data
> >
> > Thanks,
> >
> > Bryan
> >
> > > On Jul 30, 2018, at 15:12, Bryan Van de ven <[email protected]> wrote:
> > >
> > > Hi,
> > >
> > > I'm sorry, I simply don't have the bandwidth to work up an example right now. The relevant change you need to make is:
> > >
> > > * put the call to "source.data = new_data" in a small function of its own
> > > * have you current callback add that small function as a next_tick_callback
> > >
> > > However, I also note that you do this:
> > >
> > > source.data = ColumnDataSource(data=data).data
> > >
> > > Don't do that. The RHS of "source.data = " should always be a *plain python dict*. It should NOT be the .data property of another CDS. which is actually a complicated wrapper that just happens to look like a dict. Doing the above will currently fail ungracefully. We have yet to either disallow it via an immediate exception or find a way to make it work.
> > >
> > > Thanks,
> > >
> > > Bryan
> > >
> > >> On Jul 30, 2018, at 14:49, Michael Hansen <[email protected]> wrote:
> > >>
> > >> Aha right....I see.
> > >> Could I possibly persuade you show how to combine
> > >>
> > >> https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/tornado_embed.py
> > >> and
> > >> https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads
> > >>
> > >> That would be a really big help for understanding the overall setup
> > >>
> > >>
> > >>
> > >> On Mon, Jul 30, 2018 at 8:21 PM, Bryan Van de ven <[email protected]> wrote:
> > >> Hi,
> > >>
> > >> Please see the documentation regarding updating from threads:
> > >>
> > >> https://bokeh.pydata.org/en/latest/docs/user_guide/server.html#updating-from-threads
> > >>
> > >> Thanks,
> > >>
> > >> Bryan
> > >>
> > >>> On Jul 30, 2018, at 11:13, Michael Hansen <[email protected]> wrote:
> > >>>
> > >>> I did find this example
> > >>> and modified the code so that data is being pushed to the client rather than pulled.
> > >>>
> > >>> When I run this i get the error:
> > >>>
> > >>> Exception in thread Thread-1:
> > >>> Traceback (most recent call last):
> > >>> File "/Users/Jg/anaconda3431/lib/python3.6/threading.py", line 916, in _bootstrap_inner
> > >>> self.run()
> > >>> File "/Users/Jg/anaconda3431/lib/python3.6/threading.py", line 864, in run
> > >>> self._target(*self._args, **self._kwargs)
> > >>> File "tornado_embed.py", line 43, in threaded_function
> > >>> source.data = ColumnDataSource(data=data).data
> > >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/has_props.py", line 263, in __setattr__
> > >>> super(HasProps, self).__setattr__(name, value)
> > >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 931, in __set__
> > >>> self._internal_set(obj, value, hint=hint, setter=setter)
> > >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 727, in _internal_set
> > >>> self._real_set(obj, old, value, hint=hint, setter=setter)
> > >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 796, in _real_set
> > >>> self._trigger(obj, old, value, hint=hint, setter=setter)
> > >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/core/property/descriptors.py", line 873, in _trigger
> > >>> obj.trigger(self.name, old, value, hint, setter)
> > >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/model.py", line 549, in trigger
> > >>> super(Model, self).trigger(attr, old, new, hint=hint, setter=setter)
> > >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/util/callback_manager.py", line 120, in trigger
> > >>> self._document._notify_change(self, attr, old, new, hint, setter, invoke)
> > >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 941, in _notify_change
> > >>> self._trigger_on_change(event)
> > >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 1049, in _trigger_on_change
> > >>> self._with_self_as_curdoc(invoke_callbacks)
> > >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 1062, in _with_self_as_curdoc
> > >>> return f()
> > >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 1048, in invoke_callbacks
> > >>> cb(event)
> > >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/document.py", line 614, in <lambda>
> > >>> self._callbacks[receiver] = lambda event: event.dispatch(receiver)
> > >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py", line 195, in dispatch
> > >>> super(ModelChangedEvent, self).dispatch(receiver)
> > >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/document/events.py", line 77, in dispatch
> > >>> receiver._document_patched(self)
> > >>> File "/Users/Jg/anaconda3431/lib/python3.6/site-packages/bokeh/server/session.py", line 180, in _document_patched
> > >>> raise RuntimeError("_pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes")
> > >>> RuntimeError: _pending_writes should be non-None when we have a document lock, and we should have the lock when the document changes
> > >>>
> > >>>
> > >>> What am I doing wrong here?
> > >>>
> > >>> Code is:
> > >>>
> > >>> from jinja2 import Environment, FileSystemLoader
> > >>>
> > >>> from tornado.web import RequestHandler
> > >>>
> > >>> from bokeh.embed import server_document
> > >>> from bokeh.layouts import column
> > >>> from bokeh.models import ColumnDataSource, Slider
> > >>> from bokeh.plotting import figure
> > >>> from bokeh.server.server import Server
> > >>> from bokeh.themes import Theme
> > >>>
> > >>> from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature
> > >>>
> > >>> #from threading import Thread
> > >>> import threading
> > >>> from time import sleep
> > >>>
> > >>> env = Environment(loader=FileSystemLoader('templates'))
> > >>>
> > >>> class IndexHandler(RequestHandler):
> > >>> def get(self):
> > >>> template = env.get_template('embed.html')
> > >>> script = server_document('http://localhost:5006/bkapp')
> > >>> self.write(template.render(script=script, template="Tornado"))
> > >>>
> > >>> def modify_doc(doc):
> > >>> df = sea_surface_temperature.copy()
> > >>> source = ColumnDataSource(data=df)
> > >>>
> > >>> plot = figure(x_axis_type='datetime', y_range=(0, 25), y_axis_label='Temperature (Celsius)',
> > >>> title="Sea Surface Temperature at 43.18, -70.43")
> > >>> plot.line('time', 'temperature', source=source)
> > >>>
> > >>>
> > >>> def threaded_function():
> > >>> sleep(3)
> > >>> for new in range(20):
> > >>> print(new)
> > >>> if new == 0:
> > >>> data = df
> > >>> else:
> > >>> data = df.rolling('{0}D'.format(new)).mean()
> > >>> source.data = ColumnDataSource(data=data).data
> > >>> sleep(1)
> > >>>
> > >>> slider = Slider(start=0, end=30, value=0, step=1, title="Smoothing by N Days")
> > >>> #slider.on_change('value', callback)
> > >>>
> > >>> doc.add_root(column(slider, plot))
> > >>>
> > >>> doc.theme = Theme(filename="theme.yaml")
> > >>> tf = threading.Thread(target=threaded_function)
> > >>> tf.start()
> > >>>
> > >>> # Setting num_procs here means we can't touch the IOLoop before now, we must
> > >>> # let Server handle that. If you need to explicitly handle IOLoops then you
> > >>> # will need to use the lower level BaseServer class.
> > >>> server = Server({'/bkapp': modify_doc}, num_procs=4, extra_patterns=[('/', IndexHandler)])
> > >>> server.start()
> > >>>
> > >>> if __name__ == '__main__':
> > >>> from bokeh.util.browser import view
> > >>>
> > >>> print('Opening Tornado app with embedded Bokeh application on http://localhost:5006/')
> > >>>
> > >>> server.io_loop.add_callback(view, "http://localhost:5006/")
> > >>> server.io_loop.start()
> > >>>
> > >>>
> > >>> On Mon, Jul 30, 2018 at 5:37 PM, Bokeh coder <[email protected]> wrote:
> > >>> Hi, is there anywhere any example of how to run bokeh server with a stream to the client in a custom tornado server fashion which works on 0.13.0?
> > >>> I find the docs on how to do this a bit difficult to read and I dont understand how to get started on this - so an example would be wonderful.
> > >>>
> > >>> Thanks
> > >>>
> > >>>
> > >>> --
> > >>> 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/cb17001b-e2ca-4085-b62a-7726bfe95a1f%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/CAPty9BMctKbXjXQ1pKWwk3qkEUV%3DF-40tGK5V3HnbjUMYHOi4A%40mail.gmail.com.
> > >>> 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/7D078D9C-CCAD-4E6C-BBE5-6DE1E27A838D%40anaconda.com.
> > >> 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/CAPty9BM%3Db5VKw7GTXwkDaMShMTTf0yq2eRGBUDMa-BtN%2B9R8ew%40mail.gmail.com.
> > >> 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/A665241E-97BC-4451-B5A1-CF4A3F317E8D%40anaconda.com.
> > 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/CAPty9BMh7qKesHn0q4eXHCuNbE3nCUMu%3DBSQF6jhsTGvBbWyCQ%40mail.gmail.com.
> > 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/1B51F206-D72A-496F-8970-E1B16C8D9CB0%40anaconda.com.
> 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/CAPty9BPYsrO3hgqu4%3DcoOzESFOsHYi6nvmWf4BovPsOm0ENTjg%40mail.gmail.com.
> 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/BB237626-686A-4265-BB45-E7E104BC758B%40anaconda.com.
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/CAPty9BPwP1Qk2ky92nJqctYhNPCZoMr86ZF30y%3DfDSa3XWU32w%40mail.gmail.com.
For more options, visit https://groups.google.com/a/continuum.io/d/optout.