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()