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’)
``