Animation not working when using components

Hi,

Having issues with an animation I am plotting in a web app. I followed the gapminder example. I want the user to be able to select a ticker value like its done in the second example, but the second example only gives a static plot on the web app. Neither the slider or the button is working. The first example works, but is stuck on one single ticker. Anyone that can help me on how to sort it out. Why the animation doesnt work when using components, do I need to run a server to run an animation?

Code working:

def animationPlotter(doc):

‘’’

The animationPlotter function

‘’’

wellName = wellnameticker.value

zonesdata = getZonesData(wellName)

dfWellInterp = getWellAnalysisData(wellName)

wellsurvey = getWellSurveyData(wellName)

oildf, waterdf, oilzones, waterzones = getSourceData(dfWellInterp, zonesdata)

sourceoil = ColumnDataSource(data = (oildf.loc[oildf[‘Date’] == dfWellInterp.index[0]]))

sourcewater = ColumnDataSource(data = (waterdf.loc[waterdf[‘Date’] == dfWellInterp.index[0]]))

plotAni = AnimationWellSurveyPlotter(sourceoil, sourcewater, wellsurvey)

datelabel = Label(x = 3600, y = -1.5, text = str(dfWellInterp.index[0]), text_font_size=‘35pt’, text_color=’#eeeeee’)

plotAni.add_layout(datelabel)

def animate_update():

datewell = sliderAni.value + 1

#if datewell > dfWellInterp.index[-1]:

datewell = dfWellInterp.index[0]

sliderAni.value = datewell

def slider_update(attrname, old, new):

datewell = sliderAni.value

datewell = dfWellInterp.index[datewell]

datelabel.text = str(datewell)

data1 = ColumnDataSource(data = (oildf.loc[oildf[‘Date’] == datewell]))

data2 = ColumnDataSource(data = (waterdf.loc[waterdf[‘Date’] == datewell]))

sourceoil.data = data1.data

sourcewater.data = data2.data

sliderAni = Slider(start = 0, end = 14, value = 0, step = 1)

sliderAni.on_change(‘value’, slider_update)

callback_id = None

def animate():

global callback_id

if buttonAni.label == ‘Play’:

buttonAni.label = ‘Pause’

callback_id = curdoc().add_periodic_callback(animate_update, 600)

else:

buttonAni.label = ‘Play’

curdoc().remove_periodic_callback(callback_id)

buttonAni = Button(label=‘Play’, width = 60)

buttonAni.on_click(animate)

Layout = column(column(plotWellSurvey, plotAni), row(sliderAni, buttonAni))

doc.add_root(Layout)

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

.
.
.

from bokeh.server.server import Server

from tornado.ioloop import IOLoop

def bk_worker():

Can’t pass num_procs > 1 in this configuration. If you need to run multiple

processes, see e.g. flask_gunicorn_embed.py

server = Server({’/animationPlotter’: animationPlotter,

}, io_loop = IOLoop(), allow_websocket_origin = [“localhost:8000”])

server.start()

server.io_loop.start()

from threading import Thread

Thread(target = bk_worker).start()

``

Code not working:

def animationPlotter(wellName):

‘’’

The animationPlotter function

‘’’

zonesdata = getZonesData(wellName)

dfWellInterp = getWellAnalysisData(wellName)

oildf, waterdf, oilzones, waterzones = getSourceData(dfWellInterp, zonesdata)

sourceoil = ColumnDataSource(data = (oildf.loc[oildf[‘Date’] == dfWellInterp.index[0]]))

sourcewater = ColumnDataSource(data = (waterdf.loc[waterdf[‘Date’] == dfWellInterp.index[0]]))

plotAni = AnimationWellSurveyPlotter(sourceoil, sourcewater)

datelabel = Label(x = 3600, y = -1.5, text = str(dfWellInterp.index[0]), text_font_size=‘35pt’, text_color=’#eeeeee’)

plotAni.add_layout(datelabel)

def animate_update():

sliderAni.value = sliderAni.value + 1

def slider_update(attrname, old, new):

datewell = dfWellInterp.index[sliderAni.value]

datelabel.text = str(datewell)

data1 = ColumnDataSource(data = (oildf.loc[oildf[‘Date’] == datewell]))

data2 = ColumnDataSource(data = (waterdf.loc[waterdf[‘Date’] == datewell]))

sourceoil.data = data1.data

sourcewater.data = data2.data

sliderAni = Slider(start = 0, end = 14, value = 0, step = 1)

sliderAni.on_change(‘value’, slider_update)

callback_id = None

def animate():

global callback_id

if buttonAni.label == ‘Play’:

buttonAni.label = ‘Pause’

callback_id = curdoc().add_periodic_callback(animate_update, 600)

else:

buttonAni.label = ‘Play’

curdoc().remove_periodic_callback(callback_id)

buttonAni = Button(label=‘Play’, width = 60)

buttonAni.on_click(animate)

Layout = column(plotAni, row(sliderAni, buttonAni))

return Layout

.
.
.

plotani = animationPlotter(current_well_name)
scriptplotani, divplotani = components(plotani)

``

Hi,

You are already running a server, programmatically. However, "components" is specifically and only for embedding standalone Bokeh content. It does not, and is not expected to handle embedding Bokeh server content. For that you need "server_document".

Thanks,

Bryan

···

On Oct 17, 2018, at 06:03, Zana <[email protected]> wrote:

Hi,

Having issues with an animation I am plotting in a web app. I followed the gapminder example. I want the user to be able to select a ticker value like its done in the second example, but the second example only gives a static plot on the web app. Neither the slider or the button is working. The first example works, but is stuck on one single ticker. Anyone that can help me on how to sort it out. Why the animation doesnt work when using components, do I need to run a server to run an animation?

Code working:

def animationPlotter(doc):
    '''
    The animationPlotter function
    '''
    
    wellName = wellnameticker.value
    
    zonesdata = getZonesData(wellName)
    dfWellInterp = getWellAnalysisData(wellName)
    wellsurvey = getWellSurveyData(wellName)
    
    oildf, waterdf, oilzones, waterzones = getSourceData(dfWellInterp, zonesdata)
    
    sourceoil = ColumnDataSource(data = (oildf.loc[oildf['Date'] == dfWellInterp.index[0]]))
    sourcewater = ColumnDataSource(data = (waterdf.loc[waterdf['Date'] == dfWellInterp.index[0]]))

    plotAni = AnimationWellSurveyPlotter(sourceoil, sourcewater, wellsurvey)
    
    datelabel = Label(x = 3600, y = -1.5, text = str(dfWellInterp.index[0]), text_font_size='35pt', text_color='#eeeeee')
    plotAni.add_layout(datelabel)
    
    def animate_update():
        datewell = sliderAni.value + 1
        #if datewell > dfWellInterp.index[-1]:
        # datewell = dfWellInterp.index[0]
        sliderAni.value = datewell
    
    def slider_update(attrname, old, new):
        datewell = sliderAni.value
        datewell = dfWellInterp.index[datewell]
        datelabel.text = str(datewell)
        
        data1 = ColumnDataSource(data = (oildf.loc[oildf['Date'] == datewell]))
        data2 = ColumnDataSource(data = (waterdf.loc[waterdf['Date'] == datewell]))

        sourceoil.data = data1.data
        sourcewater.data = data2.data
    
    sliderAni = Slider(start = 0, end = 14, value = 0, step = 1)
    sliderAni.on_change('value', slider_update)

    callback_id = None

    def animate():
        global callback_id
        if buttonAni.label == 'Play':
            buttonAni.label = 'Pause'
            callback_id = curdoc().add_periodic_callback(animate_update, 600)
        else:
            buttonAni.label = 'Play'
            curdoc().remove_periodic_callback(callback_id)

    buttonAni = Button(label='Play', width = 60)
    buttonAni.on_click(animate)
        
    Layout = column(column(plotWellSurvey, plotAni), row(sliderAni, buttonAni))
    doc.add_root(Layout)

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

from bokeh.server.server import Server
from tornado.ioloop import IOLoop

def bk_worker():
    # Can't pass num_procs > 1 in this configuration. If you need to run multiple
    # processes, see e.g. flask_gunicorn_embed.py
    server = Server({'/animationPlotter': animationPlotter,
                     }, io_loop = IOLoop(), allow_websocket_origin = ["localhost:8000"])

    server.start()
    server.io_loop.start()

from threading import Thread
Thread(target = bk_worker).start()

Code not working:

def animationPlotter(wellName):
    '''
    The animationPlotter function
    '''
        
    zonesdata = getZonesData(wellName)
    dfWellInterp = getWellAnalysisData(wellName)
    
    oildf, waterdf, oilzones, waterzones = getSourceData(dfWellInterp, zonesdata)
    
    sourceoil = ColumnDataSource(data = (oildf.loc[oildf['Date'] == dfWellInterp.index[0]]))
    sourcewater = ColumnDataSource(data = (waterdf.loc[waterdf['Date'] == dfWellInterp.index[0]]))

    plotAni = AnimationWellSurveyPlotter(sourceoil, sourcewater)
    
    datelabel = Label(x = 3600, y = -1.5, text = str(dfWellInterp.index[0]), text_font_size='35pt', text_color='#eeeeee')
    plotAni.add_layout(datelabel)
    
    def animate_update():
        sliderAni.value = sliderAni.value + 1
    
    def slider_update(attrname, old, new):
        datewell = dfWellInterp.index[sliderAni.value]
        datelabel.text = str(datewell)
        
        data1 = ColumnDataSource(data = (oildf.loc[oildf['Date'] == datewell]))
        data2 = ColumnDataSource(data = (waterdf.loc[waterdf['Date'] == datewell]))

        sourceoil.data = data1.data
        sourcewater.data = data2.data
    
    sliderAni = Slider(start = 0, end = 14, value = 0, step = 1)
    sliderAni.on_change('value', slider_update)

    callback_id = None

    def animate():
        global callback_id
        if buttonAni.label == 'Play':
            buttonAni.label = 'Pause'
            callback_id = curdoc().add_periodic_callback(animate_update, 600)
        else:
            buttonAni.label = 'Play'
            curdoc().remove_periodic_callback(callback_id)

    buttonAni = Button(label='Play', width = 60)
    buttonAni.on_click(animate)
        
    Layout = column(plotAni, row(sliderAni, buttonAni))
    
    return Layout

.
.
.

    plotani = animationPlotter(current_well_name)
        scriptplotani, divplotani = components(plotani)

--
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/6ddaca67-34d8-4769-9ea1-a3ba80898dee%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

Bryan,

Thanks for quick reply. So how would I handle this problem? I have a dropdown meny and would like the user to be able to select a name and the animation then updates the animation. The page refreshes when user selects a different item on the drop down meny.

Hi,

I'm not sure what you are asking. You need to use the "server_document" function, instead of the "components" function. There is documentation in the users guide and reference guide, and examples in the repo:

  https://github.com/bokeh/bokeh/tree/master/examples/howto/server_embed

Thanks,

Bryan

···

On Oct 17, 2018, at 07:45, Zana <[email protected]> wrote:

Bryan,

Thanks for quick reply. So how would I handle this problem? I have a dropdown meny and would like the user to be able to select a name and the animation then updates the animation. The page refreshes when user selects a different item on the drop down meny.

--
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/73f9a678-66db-4f59-a41c-7db453672a67%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.

I’m new to server stuff :stuck_out_tongue:
Just wondering how I can update the server_document for a different ticker value.

This is how the function should be defined for a server_document right:

def modify_doc(doc):

How do you change the df dynamically? In all these examples the dataframe object is within the function. Say you have df1, df2, df3.

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

How do you run the server for different df’s?

Do you understand what I mean?:stuck_out_tongue: Because this doesnt work f.ex: def modify_doc(doc, df)

···

On Wednesday, October 17, 2018 at 4:54:42 PM UTC+2, Bryan Van de ven wrote:

Hi,

I’m not sure what you are asking. You need to use the “server_document” function, instead of the “components” function. There is documentation in the users guide and reference guide, and examples in the repo:

    [https://github.com/bokeh/bokeh/tree/master/examples/howto/server_embed](https://github.com/bokeh/bokeh/tree/master/examples/howto/server_embed)

Thanks,

Bryan

On Oct 17, 2018, at 07:45, Zana [email protected] wrote:

Bryan,

Thanks for quick reply. So how would I handle this problem? I have a dropdown meny and would like the user to be able to select a name and the animation then updates the animation. The page refreshes when user selects a different item on the drop down meny.


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/73f9a678-66db-4f59-a41c-7db453672a67%40continuum.io.

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

Hey managed to solve this problem by adding arguments to the server document.

I added the following to the code:

import atexit

import subprocess

bokeh_process = subprocess.Popen(

['python', '-m', 'bokeh', 'serve', '--allow-websocket-origin=localhost:8000', 'animation_server.py'], stdout = subprocess.PIPE)

.
.
.
.

animationPlotter = server_document(url = ‘http://localhost:5006/animation_server’, arguments = dict(wellname = current_well_name))

``

Bryan,

If I want to run more servers like this with arguments how would I do it. I tried something like this:

bokeh_process = subprocess.Popen(

['python', '-m', 'bokeh', 'serve', '--allow-websocket-origin=localhost:8000', 'animation_server.py', 'newPlotter_server.py'], stdout = subprocess.PIPE)

.
.
.
.

animationPlotter = server_document(url = ‘http://localhost:5006/animation_server’, arguments = dict(wellname = current_well_name))
newPlotter = server_document(url = ‘http://localhost:5007/newPlotter_server’, arguments = dict(wellname = current_well_name))

``

But that didnt work, I did change the port. Do you have an example of multiple servers running in the same web app?

Zana

···

On Wednesday, October 17, 2018 at 3:03:31 PM UTC+2, Zana wrote:

Hi,

Having issues with an animation I am plotting in a web app. I followed the gapminder example. I want the user to be able to select a ticker value like its done in the second example, but the second example only gives a static plot on the web app. Neither the slider or the button is working. The first example works, but is stuck on one single ticker. Anyone that can help me on how to sort it out. Why the animation doesnt work when using components, do I need to run a server to run an animation?

Code working:

def animationPlotter(doc):

‘’’

The animationPlotter function

‘’’

wellName = wellnameticker.value

zonesdata = getZonesData(wellName)

dfWellInterp = getWellAnalysisData(wellName)

wellsurvey = getWellSurveyData(wellName)

oildf, waterdf, oilzones, waterzones = getSourceData(dfWellInterp, zonesdata)

sourceoil = ColumnDataSource(data = (oildf.loc[oildf[‘Date’] == dfWellInterp.index[0]]))

sourcewater = ColumnDataSource(data = (waterdf.loc[waterdf[‘Date’] == dfWellInterp.index[0]]))

plotAni = AnimationWellSurveyPlotter(sourceoil, sourcewater, wellsurvey)

datelabel = Label(x = 3600, y = -1.5, text = str(dfWellInterp.index[0]), text_font_size=‘35pt’, text_color=‘#eeeeee’)

plotAni.add_layout(datelabel)

def animate_update():

datewell = sliderAni.value + 1

#if datewell > dfWellInterp.index[-1]:

datewell = dfWellInterp.index[0]

sliderAni.value = datewell

def slider_update(attrname, old, new):

datewell = sliderAni.value

datewell = dfWellInterp.index[datewell]

datelabel.text = str(datewell)

data1 = ColumnDataSource(data = (oildf.loc[oildf[‘Date’] == datewell]))

data2 = ColumnDataSource(data = (waterdf.loc[waterdf[‘Date’] == datewell]))

sourceoil.data = data1.data

sourcewater.data = data2.data

sliderAni = Slider(start = 0, end = 14, value = 0, step = 1)

sliderAni.on_change(‘value’, slider_update)

callback_id = None

def animate():

global callback_id

if buttonAni.label == ‘Play’:

buttonAni.label = ‘Pause’

callback_id = curdoc().add_periodic_callback(animate_update, 600)

else:

buttonAni.label = ‘Play’

curdoc().remove_periodic_callback(callback_id)

buttonAni = Button(label=‘Play’, width = 60)

buttonAni.on_click(animate)

Layout = column(column(plotWellSurvey, plotAni), row(sliderAni, buttonAni))

doc.add_root(Layout)

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

.
.
.

from bokeh.server.server import Server

from tornado.ioloop import IOLoop

def bk_worker():

Can’t pass num_procs > 1 in this configuration. If you need to run multiple

processes, see e.g. flask_gunicorn_embed.py

server = Server({‘/animationPlotter’: animationPlotter,

}, io_loop = IOLoop(), allow_websocket_origin = [“localhost:8000”])

server.start()

server.io_loop.start()

from threading import Thread

Thread(target = bk_worker).start()

``

Code not working:

def animationPlotter(wellName):

‘’’

The animationPlotter function

‘’’

zonesdata = getZonesData(wellName)

dfWellInterp = getWellAnalysisData(wellName)

oildf, waterdf, oilzones, waterzones = getSourceData(dfWellInterp, zonesdata)

sourceoil = ColumnDataSource(data = (oildf.loc[oildf[‘Date’] == dfWellInterp.index[0]]))

sourcewater = ColumnDataSource(data = (waterdf.loc[waterdf[‘Date’] == dfWellInterp.index[0]]))

plotAni = AnimationWellSurveyPlotter(sourceoil, sourcewater)

datelabel = Label(x = 3600, y = -1.5, text = str(dfWellInterp.index[0]), text_font_size=‘35pt’, text_color=‘#eeeeee’)

plotAni.add_layout(datelabel)

def animate_update():

sliderAni.value = sliderAni.value + 1

def slider_update(attrname, old, new):

datewell = dfWellInterp.index[sliderAni.value]

datelabel.text = str(datewell)

data1 = ColumnDataSource(data = (oildf.loc[oildf[‘Date’] == datewell]))

data2 = ColumnDataSource(data = (waterdf.loc[waterdf[‘Date’] == datewell]))

sourceoil.data = data1.data

sourcewater.data = data2.data

sliderAni = Slider(start = 0, end = 14, value = 0, step = 1)

sliderAni.on_change(‘value’, slider_update)

callback_id = None

def animate():

global callback_id

if buttonAni.label == ‘Play’:

buttonAni.label = ‘Pause’

callback_id = curdoc().add_periodic_callback(animate_update, 600)

else:

buttonAni.label = ‘Play’

curdoc().remove_periodic_callback(callback_id)

buttonAni = Button(label=‘Play’, width = 60)

buttonAni.on_click(animate)

Layout = column(plotAni, row(sliderAni, buttonAni))

return Layout

.
.
.

plotani = animationPlotter(current_well_name)
scriptplotani, divplotani = components(plotani)

``