Updating dataframe based graph with bokeh server using a class object

Working with a class containing a large data set in Python, I am trying to plot a graph that would change everytime a widget is triggered (intentionally avoiding ‘live update’ as the calculations may take a while).

Using a Bokeh Server, I don’t understand why the Figure fails to ‘update’: I have set up a callback function which seems to work, however the plot does not automatically update upon ‘click’.

I noticed that if I add a manual ‘make_figure’ line in my callback func, the updated data is then added to the figure - however I am under the impression that one of the abilities of the Server is to automate this process. To me this means the ColumnDataSource is being updated as it should, however there is a fault with the server process which I can’t find(?)

Finally I noticed the console brings out the following error which I could not trace back and not sure if at all related:

Couldn’t process kernel message TypeError: Cannot read property ‘trim’ of undefined

at output (eval at append_javascript (outputarea.js:762), :47:39)

at Kernel._handle_output_message (kernel.js:1196)

at i (jquery.min.js:2)

at Kernel._handle_iopub_message (kernel.js:1223)

at Kernel._finish_ws_message (kernel.js:1015)

at kernel.js:1006

(anonymous) @ kernel.js:1007

Promise.catch (async)

Kernel._handle_ws_message @ kernel.js:1007

i @ jquery.min.js:2

``

Code as below should be runnable in Jupyter Notebook

Thanks

import pandas as pd

import numpy as np

from bokeh.server.server import Server

from bokeh.application import Application

from bokeh.application.handlers.function import FunctionHandler

from bokeh.models import CustomJS, ColumnDataSource

from bokeh.models.widgets import Button

from bokeh.layouts import widgetbox, row, column

from bokeh.plotting import figure, show

from bokeh.io import show, output_notebook

output_notebook()

···

#################################################################

#data class. in my actual project this is used to perform heavy calculations on a large data base

class dataClass():

def init(self):

self.data = pd.DataFrame

self.reinitiate()

def reinitiate (self):

d = {‘a’: np.random.rand(10),

‘b’: np.random.rand(10),

‘c’: np.random.rand(10),

‘d’: np.random.rand(10)}

self.data = pd.DataFrame(d)

#################################################################

#create class instance

d = dataClass()

#################################################################

#server app

def make_doc (doc):

src = ColumnDataSource(data=d.data)

exeButton = Button(label=“Change Values”, button_type=“success”)

p = figure (title = ‘Random Numbers’,

plot_width=750, plot_height=350,

x_axis_label = ‘Column’,

y_axis_label = ‘Value’)

def exeButtonCallback ():

d.reinitiate()

src.data.update(d.data)

#if this line is enabled, the new source will appear in the figure

make_figure()

def make_figure():

p.multi_line(xs=[src.data[‘index’]] * (len(src.data)-1),

ys=[x for x in list(src.data.values())[1:]],

)

return (p)

#callback operators

exeButton.on_click(exeButtonCallback)

#figure

p = make_figure()

#add models to document

doc.add_root(column(p, exeButton))

handler = FunctionHandler(make_doc)

app = Application(handler)

server = Server(app, port=5001)

server.start()

show (app, ‘localhost=5001’)

``

Hi,

src.data is a Python dict (more or less) but your d.data is a Pandas DataFrame, evidently. I would not expect:

  src.data.update(d.data)

To work. Instead, you should assign to src.data from a plain Python dict. You can construct the appropriate dict from a DataFrame using the from_df method:

  src.data = ColumnDataSource.from_df(d.data)

Thanks,

Bryan

···

On Mar 29, 2019, at 6:02 AM, [email protected] wrote:

Working with a class containing a large data set in Python, I am trying to plot a graph that would change everytime a widget is triggered (intentionally avoiding 'live update' as the calculations may take a while).

Using a Bokeh Server, I don't understand why the Figure fails to 'update': I have set up a callback function which seems to work, however the plot does not automatically update upon 'click'.

I noticed that if I add a manual 'make_figure' line in my callback func, the updated data is then added to the figure - however I am under the impression that one of the abilities of the Server is to automate this process. To me this means the ColumnDataSource is being updated as it should, however there is a fault with the server process which I can't find(?)

Finally I noticed the console brings out the following error which I could not trace back and not sure if at all related:

Couldn't process kernel message TypeError: Cannot read property 'trim' of undefined
    at output (eval at append_javascript (outputarea.js:762), <anonymous>:47:39)
    at Kernel._handle_output_message (kernel.js:1196)
    at i (jquery.min.js:2)
    at Kernel._handle_iopub_message (kernel.js:1223)
    at Kernel._finish_ws_message (kernel.js:1015)
    at kernel.js:1006
(anonymous) @ kernel.js:1007
Promise.catch (async)
Kernel._handle_ws_message @ kernel.js:1007
i @ jquery.min.js:2

Code as below should be runnable in Jupyter Notebook

Thanks

import pandas as pd
import numpy as np

from bokeh.server.server import Server
from bokeh.application import Application
from bokeh.application.handlers.function import FunctionHandler

from bokeh.models import CustomJS, ColumnDataSource
from bokeh.models.widgets import Button
from bokeh.layouts import widgetbox, row, column
from bokeh.plotting import figure, show

from bokeh.io import show, output_notebook
output_notebook()

#################################################################
#data class. in my actual project this is used to perform heavy calculations on a large data base

class dataClass():
    def __init__(self):
        
        self.data = pd.DataFrame
        self.reinitiate()
    
    def reinitiate (self):
        d = {'a': np.random.rand(10),
             'b': np.random.rand(10),
             'c': np.random.rand(10),
             'd': np.random.rand(10)}
        
        self.data = pd.DataFrame(d)
        
#################################################################
#create class instance
d = dataClass()

#################################################################
server app
def make_doc (doc):
    src = ColumnDataSource(data=d.data)
    exeButton = Button(label="Change Values", button_type="success")
    
    p = figure (title = 'Random Numbers',
                        plot_width=750, plot_height=350,
                        x_axis_label = 'Column',
                        y_axis_label = 'Value')
    
    def exeButtonCallback ():
        d.reinitiate()
        src.data.update(d.data)
        
        #if this line is enabled, the new source will appear in the figure
# make_figure()
    
    def make_figure():
        p.multi_line(xs=[src.data['index']] * (len(src.data)-1),
                             ys=[x for x in list(src.data.values())[1:]],
                             )
        return (p)
    
    #callback operators
    exeButton.on_click(exeButtonCallback)

    figure
    p = make_figure()
    
    #add models to document
    doc.add_root(column(p, exeButton))
    
handler = FunctionHandler(make_doc)
app = Application(handler)
server = Server(app, port=5001)
server.start()
show (app, 'localhost=5001')

--
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/58025c53-e5cc-49ce-b6d5-1da6cfa82e96%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/d/optout\.