I have the following example, which successfully runs as a jupyterlab notebook
, but will not run as a standalone server app.
Here is the code that runs inside JupyterLab (v3.3.2), Bokeh (v3.2.0)
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, CheckboxButtonGroup, CustomJS
from bokeh.plotting import show, figure, output_notebook
import pandas as pd
output_notebook()
def create_plot(doc):
# create fake data
x = [2, 4, 8, 5, 9, 3]
y = [4, 8, 2, 7, 4, 6]
id_ = ['1001', '1002', '1003', '1004', '1005', '1006']
color = ['red'] + ['green']*5
df = pd.DataFrame({'x': x, 'y': y, 'ids': id_, 'color': color})
# create column data source
cds = ColumnDataSource(data=df)
# create figure
p = figure(width=300, height=200)
p.circle(x='x', y='y', size=5, source=cds, color='color')
# Create widget (checkbox button)
checkbox_button_group = CheckboxButtonGroup(labels=id_, active=[0])
# Update the colors after a click on an id
checkbox_button_group.js_on_change("active", CustomJS(code="""
console.log('checkbox_button_group: active=' + this.active, this.toString())
"""))
def set_col(row, red_ids):
color = 'red' if row in red_ids else 'green'
return color
def update_data(df, red_ids=None):
if red_ids is None:
red_ids = []
df['color'] = df['ids'].apply(lambda x: set_col(x, red_ids))
cds.data = df
def update(attr, old, new):
red_ids = [checkbox_button_group.labels[i] for i in checkbox_button_group.active]
update_data(df, red_ids)
checkbox_button_group.on_change('active', update)
# display button & plot in a column
doc.add_root(column(checkbox_button_group, p))
show(create_plot, notebook_url="localhost:8891")
Here is the modified code, to be run as a bokeh-server app:
# test-app.py
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, CheckboxButtonGroup, CustomJS
from bokeh.plotting import show, figure, curdoc
import pandas as pd
def create_plot(doc):
# create fake data
x = [2, 4, 8, 5, 9, 3]
y = [4, 8, 2, 7, 4, 6]
id_ = ['1001', '1002', '1003', '1004', '1005', '1006']
color = ['red'] + ['green']*5
df = pd.DataFrame({'x': x, 'y': y, 'ids': id_, 'color': color})
# create column data source
cds = ColumnDataSource(data=df)
# create figure
p = figure(width=300, height=200)
p.circle(x='x', y='y', size=5, source=cds, color='color')
# Create widget (checkbox button)
checkbox_button_group = CheckboxButtonGroup(labels=id_, active=[0])
# Update the colors after a click on an id
checkbox_button_group.js_on_change("active", CustomJS(code="""
console.log('checkbox_button_group: active=' + this.active, this.toString())
"""))
def set_col(row, red_ids):
color = 'red' if row in red_ids else 'green'
return color
def update_data(df, red_ids=None):
if red_ids is None:
red_ids = []
df['color'] = df['ids'].apply(lambda x: set_col(x, red_ids))
cds.data = df
def update(attr, old, new):
red_ids = [checkbox_button_group.labels[i] for i in checkbox_button_group.active]
update_data(df, red_ids)
checkbox_button_group.on_change('active', update)
# display button & plot in a column
doc.add_root(column(checkbox_button_group, p))
if __name__ == "__main__":
create_plot(curdoc)
When I run this with the following command:
bokeh serve --show test-app.py
I get a blank page inside the browser.