how to trigger a callback on editing a cell in a DataTable ?

Hi,

I have been trying to get this to work, digging through the documentation and googling, but sofar without luck.

I create a plot of some data (x,y) (plot_source) with the y generated via some parameters p (params_source).

The params are in an editable DataTable (params_data_table).

I would like to trigger an event on changing one of the parameters in the DataTable, and plot an updated (x,y) plot.

From googling I managed to get something working which triggers on a ‘select’ event, but that is not really what I want.

In that case, I edit a cell, and am forced to select another cell to trigger the event…

I assume there must be a correct/better way, but I have not found it yet.

I include the code below (based on models/server/widgets.py)

If anybody can tell me what I am missing, I would greatly appreciate ! Thanks

Jiri

···

from future import print_function

from datetime import date

from random import randint

import random

from bokeh.client import push_session

from bokeh.document import Document

from bokeh.models.glyphs import Line, Circle

from bokeh.models import (

Plot, ColumnDataSource, DataRange1d,
LinearAxis, DatetimeAxis, Grid, HoverTool

)

from bokeh.models.widgets import (

Button, TableColumn, DataTable,
NumberEditor, DateEditor, DateFormatter, IntEditor)

from bokeh.models.layouts import WidgetBox, Column, Row

import pandas as pd

import numpy as np

document = Document()

session = push_session(document)

def make_params_data():

params = [random.uniform(0.0,1.0),random.uniform(-0.5,0.5)]
return dict(params=params)

def make_plot_data(params):

x = np.linspace(50,150,100)
y = params[0]* np.cos(params[1]*x)
return dict(x=x,y=y)

params_source = ColumnDataSource(make_params_data())

plot_source = ColumnDataSource(make_plot_data(params_source.data[‘params’]))

def make_plot():

xdr = DataRange1d()
ydr = DataRange1d()
plot = Plot(x_range=xdr, y_range=ydr, plot_width=600, plot_height=400)
plot.title.text = "Y"
line = Line(x="x", y="y", line_color="blue")
plot.add_glyph(plot_source, line)
circle = Circle(x="x", y="y", fill_color="red")
plot.add_glyph(plot_source, circle)
xaxis = LinearAxis()
plot.add_layout(xaxis, 'below')
yaxis = LinearAxis()
plot.add_layout(yaxis, 'left')
plot.add_layout(Grid(dimension=0, ticker=xaxis.ticker))
plot.add_layout(Grid(dimension=1, ticker=yaxis.ticker))
plot.add_tools(HoverTool(tooltips=dict(y="@y")))
return plot, plot_source

def click_handler():

params_source.data = make_params_data()
plot_source.data = make_plot_data(params_source.data['params'])

def params_handler(attr,old,new):

plot_source.data = make_plot_data(params_source.data['params'])

def make_layout():

plot, plot_source = make_plot()
params_columns = [
    TableColumn(field="params", title="Param", editor=NumberEditor())
]
params_data_table = DataTable(source=params_source, columns=params_columns, width=100, height=100, editable=True)
params_source.on_change('selected',params_handler)
# this is not what i want, instead i want to be able to update a cell and have an event fire on the updated cell...
plot_columns = [
    TableColumn(field="x", title="X", editor=NumberEditor()),
    TableColumn(field="y", title="Y", editor=NumberEditor()),
]
plot_data_table = DataTable(source=plot_source, columns=plot_columns, width=400, height=400, editable=True)
button = Button(label="Randomize data", button_type="success")
button.on_click(click_handler)
buttons = WidgetBox(children=[button], width=400)
column = Column(children=[buttons, params_data_table, Row(children=[plot, plot_data_table])])
return column

layout = make_layout()

document.add_root(layout)

session.show(layout)

if name == “main”:

document.validate()
print("\npress ctrl-C to exit")
session.loop_until_closed()