How to get a list of Bokeh widget events and attributes (which can be used to trigger a Python callback)How to use 'tap' in bokeh to effect changes in a different plot (or table)?Trigger a JavaScript callback upon ColumnDataSource change in a plotHow can I safely create a nested directory?How can I remove a trailing newline?How to get the current time in PythonHow can I make a time delay in Python?How to know if an object has an attribute in PythonGetting the last element of a listHow do I get the number of elements in a list?How do I concatenate two lists in Python?How can I count the occurrences of a list item?How to add a Callback to Bokeh DataTable?
Seeming violation-wave travelling faster than speed of light
Get Max value comparing multiple columns and return specific values
Received a package but didn't order it
What is the difference between 「変更」 and 「変化」?
Why does this image of Jupiter look so strange?
What is the meaning of word 'crack' in chapter 33 of A Game of Thrones?
How to justify a team increase when the team is doing good?
Does "as soon as" imply simultaneity?
Safe to use 220V electric clothes dryer when building has been bridged down to 110V?
Is it impolite to ask for halal food when traveling to and in Thailand?
Does the Prepare Food ability from Cook's Utensils stack?
Does HSTS protect against a rogue CA issuing a illegitimate valid certificate?
2000s Animated TV show where teenagers could physically go into a virtual world
Tesla coil and Tesla tower
Do I have advantage with Riposte when moving away from a flanked enemy and triggering an opportunity attack?
Line segments inside a square
Cut a cake into 3 equal portions with only a knife
What is the meaning of "heutig" in this sentence?
If an object moving in a circle experiences centripetal force, then doesn't it also experience centrifugal force, because of Newton's third law?
Late 1970's and 6502 chip facilities for operating systems
practicality of 30 year fix mortgage at 55 years of age
What secular civic space would pioneers build for small frontier towns?
Why does (inf + 0j)*1 evaluate to inf + nanj?
Can I take new (still in their boxes) PC parts in my checked in luggage?
How to get a list of Bokeh widget events and attributes (which can be used to trigger a Python callback)
How to use 'tap' in bokeh to effect changes in a different plot (or table)?Trigger a JavaScript callback upon ColumnDataSource change in a plotHow can I safely create a nested directory?How can I remove a trailing newline?How to get the current time in PythonHow can I make a time delay in Python?How to know if an object has an attribute in PythonGetting the last element of a listHow do I get the number of elements in a list?How do I concatenate two lists in Python?How can I count the occurrences of a list item?How to add a Callback to Bokeh DataTable?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
The real (general) question
I am new to Bokeh and I am trying to build a plot which can be dynamically updated based on input provided by a widget. However, usage of Python callbacks is not thoroughly documented for most widgets and therefore I'm stuck.
- How can I know which widget method I should use to attach my callback? I can guess the available choices by probing the widgets attributes in an interactive console, but that's not elegant and I'm sure it's written somewhere in the documentation.
- Provided that I would know about the method to use (e.g.
on_eventoron_change), I still have to figure out its signature and arguments. For instance, if I'm usingon_change, which widget attributes can I monitor? - Once I know which attribute I can monitor, how can I know the data structure which will be yielded by the event?
Some more context and the (not-as-useful) specific question
Here is an appropriate example. I am using a notebook-embedded server like in this example. As an exercise, I would like to replace the slider with a DataTable with arbitrary values. Here is the code I currently have:
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, DataTable
from bokeh.plotting import figure
from bokeh.io import show, output_notebook
from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature
output_notebook()
def modify_doc(doc):
df = sea_surface_temperature.copy()
source = ColumnDataSource(data=df)
source_table = ColumnDataSource(data="alpha": [s for s in "abcdefgh"],
"num": list(range(8)))
plot = figure(x_axis_type='datetime', y_range=(0, 25),
y_axis_label='Temperature (Celsius)',
title="Sea Surface Temperature at 43.18, -70.43")
plot.line('time', 'temperature', source=source)
def callback(attr, old, new):
# This is the old callback from the example. What is "new" when I use
# a table widget?
if new == 0:
data = df
else:
data = df.rolling('0D'.format(new)).mean()
source.data = ColumnDataSource(data=data).data
table = DataTable(source=source_table,
columns=[TableColumn(field="alpha", title="Alpha"),
TableColumn(field="num", title="Num")])
# How can I attach a callback to table so that the plot gets updated
# with the "num" value when I select a row?
# table.on_change("some_attribute", callback)
doc.add_root(column(table, plot))
show(modify_doc)
python bokeh
add a comment
|
The real (general) question
I am new to Bokeh and I am trying to build a plot which can be dynamically updated based on input provided by a widget. However, usage of Python callbacks is not thoroughly documented for most widgets and therefore I'm stuck.
- How can I know which widget method I should use to attach my callback? I can guess the available choices by probing the widgets attributes in an interactive console, but that's not elegant and I'm sure it's written somewhere in the documentation.
- Provided that I would know about the method to use (e.g.
on_eventoron_change), I still have to figure out its signature and arguments. For instance, if I'm usingon_change, which widget attributes can I monitor? - Once I know which attribute I can monitor, how can I know the data structure which will be yielded by the event?
Some more context and the (not-as-useful) specific question
Here is an appropriate example. I am using a notebook-embedded server like in this example. As an exercise, I would like to replace the slider with a DataTable with arbitrary values. Here is the code I currently have:
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, DataTable
from bokeh.plotting import figure
from bokeh.io import show, output_notebook
from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature
output_notebook()
def modify_doc(doc):
df = sea_surface_temperature.copy()
source = ColumnDataSource(data=df)
source_table = ColumnDataSource(data="alpha": [s for s in "abcdefgh"],
"num": list(range(8)))
plot = figure(x_axis_type='datetime', y_range=(0, 25),
y_axis_label='Temperature (Celsius)',
title="Sea Surface Temperature at 43.18, -70.43")
plot.line('time', 'temperature', source=source)
def callback(attr, old, new):
# This is the old callback from the example. What is "new" when I use
# a table widget?
if new == 0:
data = df
else:
data = df.rolling('0D'.format(new)).mean()
source.data = ColumnDataSource(data=data).data
table = DataTable(source=source_table,
columns=[TableColumn(field="alpha", title="Alpha"),
TableColumn(field="num", title="Num")])
# How can I attach a callback to table so that the plot gets updated
# with the "num" value when I select a row?
# table.on_change("some_attribute", callback)
doc.add_root(column(table, plot))
show(modify_doc)
python bokeh
add a comment
|
The real (general) question
I am new to Bokeh and I am trying to build a plot which can be dynamically updated based on input provided by a widget. However, usage of Python callbacks is not thoroughly documented for most widgets and therefore I'm stuck.
- How can I know which widget method I should use to attach my callback? I can guess the available choices by probing the widgets attributes in an interactive console, but that's not elegant and I'm sure it's written somewhere in the documentation.
- Provided that I would know about the method to use (e.g.
on_eventoron_change), I still have to figure out its signature and arguments. For instance, if I'm usingon_change, which widget attributes can I monitor? - Once I know which attribute I can monitor, how can I know the data structure which will be yielded by the event?
Some more context and the (not-as-useful) specific question
Here is an appropriate example. I am using a notebook-embedded server like in this example. As an exercise, I would like to replace the slider with a DataTable with arbitrary values. Here is the code I currently have:
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, DataTable
from bokeh.plotting import figure
from bokeh.io import show, output_notebook
from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature
output_notebook()
def modify_doc(doc):
df = sea_surface_temperature.copy()
source = ColumnDataSource(data=df)
source_table = ColumnDataSource(data="alpha": [s for s in "abcdefgh"],
"num": list(range(8)))
plot = figure(x_axis_type='datetime', y_range=(0, 25),
y_axis_label='Temperature (Celsius)',
title="Sea Surface Temperature at 43.18, -70.43")
plot.line('time', 'temperature', source=source)
def callback(attr, old, new):
# This is the old callback from the example. What is "new" when I use
# a table widget?
if new == 0:
data = df
else:
data = df.rolling('0D'.format(new)).mean()
source.data = ColumnDataSource(data=data).data
table = DataTable(source=source_table,
columns=[TableColumn(field="alpha", title="Alpha"),
TableColumn(field="num", title="Num")])
# How can I attach a callback to table so that the plot gets updated
# with the "num" value when I select a row?
# table.on_change("some_attribute", callback)
doc.add_root(column(table, plot))
show(modify_doc)
python bokeh
The real (general) question
I am new to Bokeh and I am trying to build a plot which can be dynamically updated based on input provided by a widget. However, usage of Python callbacks is not thoroughly documented for most widgets and therefore I'm stuck.
- How can I know which widget method I should use to attach my callback? I can guess the available choices by probing the widgets attributes in an interactive console, but that's not elegant and I'm sure it's written somewhere in the documentation.
- Provided that I would know about the method to use (e.g.
on_eventoron_change), I still have to figure out its signature and arguments. For instance, if I'm usingon_change, which widget attributes can I monitor? - Once I know which attribute I can monitor, how can I know the data structure which will be yielded by the event?
Some more context and the (not-as-useful) specific question
Here is an appropriate example. I am using a notebook-embedded server like in this example. As an exercise, I would like to replace the slider with a DataTable with arbitrary values. Here is the code I currently have:
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, DataTable
from bokeh.plotting import figure
from bokeh.io import show, output_notebook
from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature
output_notebook()
def modify_doc(doc):
df = sea_surface_temperature.copy()
source = ColumnDataSource(data=df)
source_table = ColumnDataSource(data="alpha": [s for s in "abcdefgh"],
"num": list(range(8)))
plot = figure(x_axis_type='datetime', y_range=(0, 25),
y_axis_label='Temperature (Celsius)',
title="Sea Surface Temperature at 43.18, -70.43")
plot.line('time', 'temperature', source=source)
def callback(attr, old, new):
# This is the old callback from the example. What is "new" when I use
# a table widget?
if new == 0:
data = df
else:
data = df.rolling('0D'.format(new)).mean()
source.data = ColumnDataSource(data=data).data
table = DataTable(source=source_table,
columns=[TableColumn(field="alpha", title="Alpha"),
TableColumn(field="num", title="Num")])
# How can I attach a callback to table so that the plot gets updated
# with the "num" value when I select a row?
# table.on_change("some_attribute", callback)
doc.add_root(column(table, plot))
show(modify_doc)
python bokeh
python bokeh
asked Mar 28 at 17:41
M4uriceM4urice
942 silver badges8 bronze badges
942 silver badges8 bronze badges
add a comment
|
add a comment
|
1 Answer
1
active
oldest
votes
This answer was given for Bokeh v1.0.4 and may not be compliant with the latest documentation
JavaScript callbacks and Python callbacks, are very powerful tools in Bokeh and can be attached to any Bokeh model element. Additionally you can extend Bokeh functionality by writing your own extensions with TypeScript (eventually compiled to JS)
JS callbacks can be added using either of both methods:
Model.js_on_event('event', callback)
Model.js_on_change('attr', callback)
Python callbacks are mainly used for widgets:
Widget.on_event('event, onevent_handler)
Widget.on_change('attr', onchange_handler)
Widget.on_click(onclick_handler)
The exact function signature for event handlers very per widget and can be:
onevent_handler(event)
onchange_handler(attr, old, new)
onclick_handler(new)
onclick_handler()
The attr can be any widget class (or it's base class) attribute. Therefore you need always to consult the Bokeh reference pages. Also expanding the JSON Prototype helps to find out which attributes are supported e.g. looking at Div we cannot see directly the id, name, style or text attributes which come from its base classes. However, all of these attributes are present in the Div's JSON Prototype and hence are supported by Div:
"css_classes": [],
"disabled": false,
"height": null,
"id": "32025",
"js_event_callbacks": ,
"js_property_callbacks": ,
"name": null,
"render_as_text": false,
"sizing_mode": "fixed",
"style": ,
"subscribed_events": [],
"tags": [],
"text": "",
"width": null
Coming back to your question: Many times you can achieve the same result using different approaches.
To my knowledge, there is no nice method that lists all supported events per widget but reading documentation and digging into the base classes helps a lot.
Using methods described above it is possible to check which widget attributes you can use in your callbacks. When it comes to events I advice you to look at and explore the bokeh.events class in your IDE. You can find there extended description for every event. In time it will come naturally when using your programmer's intuition to select the right event that your widget supports (so no button_click for Plot and no pan event for Button but the other way around).
Decision to which widget (model element) attach the callback and which method to choose or to which event bound the callback is yours and depends mainly on: which user action should trigger your callback?
So you can have a JS callback attached to any widget (value change, slider move, etc...), any tool (TapTool, HoverTool, etc...), data_source (clicking on glyph), plot canvas (e.g. for clicks on area outside a glyph) or plot range (zoom or pan events), etc...
Basically you need to know that all Python objects have their equivalents in BokehJS so you can use them the same way in in both domains (with some syntax differences, of course).
This documentation shows for example that ColumnDataSource has a "selected" property so for points you can inspect source.selected.indices and see which point on the plot are selected or like in your case: which table rows are selected. You can set a breakpoint in code in Python and also in the browser and inspect the Python or BokehJS data structures.
And here is your code (slightly modified for "pure Bokeh" v1.0.4 as I don't have Jupiter Notebook installed)
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, DataTable, TableColumn
from bokeh.plotting import figure, curdoc
from bokeh.io import show, output_notebook
from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature
# output_notebook()
def modify_doc(doc):
df = sea_surface_temperature.copy()
source = ColumnDataSource(data = df)
source_table = ColumnDataSource(data = "alpha": [s for s in "abcdefgh"],
"num": list(range(8)))
plot = figure(x_axis_type = 'datetime', y_range = (0, 25),
y_axis_label = 'Temperature (Celsius)',
title = "Sea Surface Temperature at 43.18, -70.43")
plot.line('time', 'temperature', source = source)
def callback(attr, old, new): # here new is an array containing selected rows
if new == 0:
data = df
else:
data = df.rolling('0D'.format(new[0])).mean() # asuming one row is selected
source.data = ColumnDataSource(data = data).data
table = DataTable(source = source_table,
columns = [TableColumn(field = "alpha", title = "Alpha"),
TableColumn(field = "num", title = "Num")])
source_table.selected.on_change('indices', callback)
doc().add_root(column(table, plot))
modify_doc(curdoc)
# show(modify_doc)
Result:

add a comment
|
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55403853%2fhow-to-get-a-list-of-bokeh-widget-events-and-attributes-which-can-be-used-to-tr%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
This answer was given for Bokeh v1.0.4 and may not be compliant with the latest documentation
JavaScript callbacks and Python callbacks, are very powerful tools in Bokeh and can be attached to any Bokeh model element. Additionally you can extend Bokeh functionality by writing your own extensions with TypeScript (eventually compiled to JS)
JS callbacks can be added using either of both methods:
Model.js_on_event('event', callback)
Model.js_on_change('attr', callback)
Python callbacks are mainly used for widgets:
Widget.on_event('event, onevent_handler)
Widget.on_change('attr', onchange_handler)
Widget.on_click(onclick_handler)
The exact function signature for event handlers very per widget and can be:
onevent_handler(event)
onchange_handler(attr, old, new)
onclick_handler(new)
onclick_handler()
The attr can be any widget class (or it's base class) attribute. Therefore you need always to consult the Bokeh reference pages. Also expanding the JSON Prototype helps to find out which attributes are supported e.g. looking at Div we cannot see directly the id, name, style or text attributes which come from its base classes. However, all of these attributes are present in the Div's JSON Prototype and hence are supported by Div:
"css_classes": [],
"disabled": false,
"height": null,
"id": "32025",
"js_event_callbacks": ,
"js_property_callbacks": ,
"name": null,
"render_as_text": false,
"sizing_mode": "fixed",
"style": ,
"subscribed_events": [],
"tags": [],
"text": "",
"width": null
Coming back to your question: Many times you can achieve the same result using different approaches.
To my knowledge, there is no nice method that lists all supported events per widget but reading documentation and digging into the base classes helps a lot.
Using methods described above it is possible to check which widget attributes you can use in your callbacks. When it comes to events I advice you to look at and explore the bokeh.events class in your IDE. You can find there extended description for every event. In time it will come naturally when using your programmer's intuition to select the right event that your widget supports (so no button_click for Plot and no pan event for Button but the other way around).
Decision to which widget (model element) attach the callback and which method to choose or to which event bound the callback is yours and depends mainly on: which user action should trigger your callback?
So you can have a JS callback attached to any widget (value change, slider move, etc...), any tool (TapTool, HoverTool, etc...), data_source (clicking on glyph), plot canvas (e.g. for clicks on area outside a glyph) or plot range (zoom or pan events), etc...
Basically you need to know that all Python objects have their equivalents in BokehJS so you can use them the same way in in both domains (with some syntax differences, of course).
This documentation shows for example that ColumnDataSource has a "selected" property so for points you can inspect source.selected.indices and see which point on the plot are selected or like in your case: which table rows are selected. You can set a breakpoint in code in Python and also in the browser and inspect the Python or BokehJS data structures.
And here is your code (slightly modified for "pure Bokeh" v1.0.4 as I don't have Jupiter Notebook installed)
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, DataTable, TableColumn
from bokeh.plotting import figure, curdoc
from bokeh.io import show, output_notebook
from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature
# output_notebook()
def modify_doc(doc):
df = sea_surface_temperature.copy()
source = ColumnDataSource(data = df)
source_table = ColumnDataSource(data = "alpha": [s for s in "abcdefgh"],
"num": list(range(8)))
plot = figure(x_axis_type = 'datetime', y_range = (0, 25),
y_axis_label = 'Temperature (Celsius)',
title = "Sea Surface Temperature at 43.18, -70.43")
plot.line('time', 'temperature', source = source)
def callback(attr, old, new): # here new is an array containing selected rows
if new == 0:
data = df
else:
data = df.rolling('0D'.format(new[0])).mean() # asuming one row is selected
source.data = ColumnDataSource(data = data).data
table = DataTable(source = source_table,
columns = [TableColumn(field = "alpha", title = "Alpha"),
TableColumn(field = "num", title = "Num")])
source_table.selected.on_change('indices', callback)
doc().add_root(column(table, plot))
modify_doc(curdoc)
# show(modify_doc)
Result:

add a comment
|
This answer was given for Bokeh v1.0.4 and may not be compliant with the latest documentation
JavaScript callbacks and Python callbacks, are very powerful tools in Bokeh and can be attached to any Bokeh model element. Additionally you can extend Bokeh functionality by writing your own extensions with TypeScript (eventually compiled to JS)
JS callbacks can be added using either of both methods:
Model.js_on_event('event', callback)
Model.js_on_change('attr', callback)
Python callbacks are mainly used for widgets:
Widget.on_event('event, onevent_handler)
Widget.on_change('attr', onchange_handler)
Widget.on_click(onclick_handler)
The exact function signature for event handlers very per widget and can be:
onevent_handler(event)
onchange_handler(attr, old, new)
onclick_handler(new)
onclick_handler()
The attr can be any widget class (or it's base class) attribute. Therefore you need always to consult the Bokeh reference pages. Also expanding the JSON Prototype helps to find out which attributes are supported e.g. looking at Div we cannot see directly the id, name, style or text attributes which come from its base classes. However, all of these attributes are present in the Div's JSON Prototype and hence are supported by Div:
"css_classes": [],
"disabled": false,
"height": null,
"id": "32025",
"js_event_callbacks": ,
"js_property_callbacks": ,
"name": null,
"render_as_text": false,
"sizing_mode": "fixed",
"style": ,
"subscribed_events": [],
"tags": [],
"text": "",
"width": null
Coming back to your question: Many times you can achieve the same result using different approaches.
To my knowledge, there is no nice method that lists all supported events per widget but reading documentation and digging into the base classes helps a lot.
Using methods described above it is possible to check which widget attributes you can use in your callbacks. When it comes to events I advice you to look at and explore the bokeh.events class in your IDE. You can find there extended description for every event. In time it will come naturally when using your programmer's intuition to select the right event that your widget supports (so no button_click for Plot and no pan event for Button but the other way around).
Decision to which widget (model element) attach the callback and which method to choose or to which event bound the callback is yours and depends mainly on: which user action should trigger your callback?
So you can have a JS callback attached to any widget (value change, slider move, etc...), any tool (TapTool, HoverTool, etc...), data_source (clicking on glyph), plot canvas (e.g. for clicks on area outside a glyph) or plot range (zoom or pan events), etc...
Basically you need to know that all Python objects have their equivalents in BokehJS so you can use them the same way in in both domains (with some syntax differences, of course).
This documentation shows for example that ColumnDataSource has a "selected" property so for points you can inspect source.selected.indices and see which point on the plot are selected or like in your case: which table rows are selected. You can set a breakpoint in code in Python and also in the browser and inspect the Python or BokehJS data structures.
And here is your code (slightly modified for "pure Bokeh" v1.0.4 as I don't have Jupiter Notebook installed)
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, DataTable, TableColumn
from bokeh.plotting import figure, curdoc
from bokeh.io import show, output_notebook
from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature
# output_notebook()
def modify_doc(doc):
df = sea_surface_temperature.copy()
source = ColumnDataSource(data = df)
source_table = ColumnDataSource(data = "alpha": [s for s in "abcdefgh"],
"num": list(range(8)))
plot = figure(x_axis_type = 'datetime', y_range = (0, 25),
y_axis_label = 'Temperature (Celsius)',
title = "Sea Surface Temperature at 43.18, -70.43")
plot.line('time', 'temperature', source = source)
def callback(attr, old, new): # here new is an array containing selected rows
if new == 0:
data = df
else:
data = df.rolling('0D'.format(new[0])).mean() # asuming one row is selected
source.data = ColumnDataSource(data = data).data
table = DataTable(source = source_table,
columns = [TableColumn(field = "alpha", title = "Alpha"),
TableColumn(field = "num", title = "Num")])
source_table.selected.on_change('indices', callback)
doc().add_root(column(table, plot))
modify_doc(curdoc)
# show(modify_doc)
Result:

add a comment
|
This answer was given for Bokeh v1.0.4 and may not be compliant with the latest documentation
JavaScript callbacks and Python callbacks, are very powerful tools in Bokeh and can be attached to any Bokeh model element. Additionally you can extend Bokeh functionality by writing your own extensions with TypeScript (eventually compiled to JS)
JS callbacks can be added using either of both methods:
Model.js_on_event('event', callback)
Model.js_on_change('attr', callback)
Python callbacks are mainly used for widgets:
Widget.on_event('event, onevent_handler)
Widget.on_change('attr', onchange_handler)
Widget.on_click(onclick_handler)
The exact function signature for event handlers very per widget and can be:
onevent_handler(event)
onchange_handler(attr, old, new)
onclick_handler(new)
onclick_handler()
The attr can be any widget class (or it's base class) attribute. Therefore you need always to consult the Bokeh reference pages. Also expanding the JSON Prototype helps to find out which attributes are supported e.g. looking at Div we cannot see directly the id, name, style or text attributes which come from its base classes. However, all of these attributes are present in the Div's JSON Prototype and hence are supported by Div:
"css_classes": [],
"disabled": false,
"height": null,
"id": "32025",
"js_event_callbacks": ,
"js_property_callbacks": ,
"name": null,
"render_as_text": false,
"sizing_mode": "fixed",
"style": ,
"subscribed_events": [],
"tags": [],
"text": "",
"width": null
Coming back to your question: Many times you can achieve the same result using different approaches.
To my knowledge, there is no nice method that lists all supported events per widget but reading documentation and digging into the base classes helps a lot.
Using methods described above it is possible to check which widget attributes you can use in your callbacks. When it comes to events I advice you to look at and explore the bokeh.events class in your IDE. You can find there extended description for every event. In time it will come naturally when using your programmer's intuition to select the right event that your widget supports (so no button_click for Plot and no pan event for Button but the other way around).
Decision to which widget (model element) attach the callback and which method to choose or to which event bound the callback is yours and depends mainly on: which user action should trigger your callback?
So you can have a JS callback attached to any widget (value change, slider move, etc...), any tool (TapTool, HoverTool, etc...), data_source (clicking on glyph), plot canvas (e.g. for clicks on area outside a glyph) or plot range (zoom or pan events), etc...
Basically you need to know that all Python objects have their equivalents in BokehJS so you can use them the same way in in both domains (with some syntax differences, of course).
This documentation shows for example that ColumnDataSource has a "selected" property so for points you can inspect source.selected.indices and see which point on the plot are selected or like in your case: which table rows are selected. You can set a breakpoint in code in Python and also in the browser and inspect the Python or BokehJS data structures.
And here is your code (slightly modified for "pure Bokeh" v1.0.4 as I don't have Jupiter Notebook installed)
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, DataTable, TableColumn
from bokeh.plotting import figure, curdoc
from bokeh.io import show, output_notebook
from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature
# output_notebook()
def modify_doc(doc):
df = sea_surface_temperature.copy()
source = ColumnDataSource(data = df)
source_table = ColumnDataSource(data = "alpha": [s for s in "abcdefgh"],
"num": list(range(8)))
plot = figure(x_axis_type = 'datetime', y_range = (0, 25),
y_axis_label = 'Temperature (Celsius)',
title = "Sea Surface Temperature at 43.18, -70.43")
plot.line('time', 'temperature', source = source)
def callback(attr, old, new): # here new is an array containing selected rows
if new == 0:
data = df
else:
data = df.rolling('0D'.format(new[0])).mean() # asuming one row is selected
source.data = ColumnDataSource(data = data).data
table = DataTable(source = source_table,
columns = [TableColumn(field = "alpha", title = "Alpha"),
TableColumn(field = "num", title = "Num")])
source_table.selected.on_change('indices', callback)
doc().add_root(column(table, plot))
modify_doc(curdoc)
# show(modify_doc)
Result:

This answer was given for Bokeh v1.0.4 and may not be compliant with the latest documentation
JavaScript callbacks and Python callbacks, are very powerful tools in Bokeh and can be attached to any Bokeh model element. Additionally you can extend Bokeh functionality by writing your own extensions with TypeScript (eventually compiled to JS)
JS callbacks can be added using either of both methods:
Model.js_on_event('event', callback)
Model.js_on_change('attr', callback)
Python callbacks are mainly used for widgets:
Widget.on_event('event, onevent_handler)
Widget.on_change('attr', onchange_handler)
Widget.on_click(onclick_handler)
The exact function signature for event handlers very per widget and can be:
onevent_handler(event)
onchange_handler(attr, old, new)
onclick_handler(new)
onclick_handler()
The attr can be any widget class (or it's base class) attribute. Therefore you need always to consult the Bokeh reference pages. Also expanding the JSON Prototype helps to find out which attributes are supported e.g. looking at Div we cannot see directly the id, name, style or text attributes which come from its base classes. However, all of these attributes are present in the Div's JSON Prototype and hence are supported by Div:
"css_classes": [],
"disabled": false,
"height": null,
"id": "32025",
"js_event_callbacks": ,
"js_property_callbacks": ,
"name": null,
"render_as_text": false,
"sizing_mode": "fixed",
"style": ,
"subscribed_events": [],
"tags": [],
"text": "",
"width": null
Coming back to your question: Many times you can achieve the same result using different approaches.
To my knowledge, there is no nice method that lists all supported events per widget but reading documentation and digging into the base classes helps a lot.
Using methods described above it is possible to check which widget attributes you can use in your callbacks. When it comes to events I advice you to look at and explore the bokeh.events class in your IDE. You can find there extended description for every event. In time it will come naturally when using your programmer's intuition to select the right event that your widget supports (so no button_click for Plot and no pan event for Button but the other way around).
Decision to which widget (model element) attach the callback and which method to choose or to which event bound the callback is yours and depends mainly on: which user action should trigger your callback?
So you can have a JS callback attached to any widget (value change, slider move, etc...), any tool (TapTool, HoverTool, etc...), data_source (clicking on glyph), plot canvas (e.g. for clicks on area outside a glyph) or plot range (zoom or pan events), etc...
Basically you need to know that all Python objects have their equivalents in BokehJS so you can use them the same way in in both domains (with some syntax differences, of course).
This documentation shows for example that ColumnDataSource has a "selected" property so for points you can inspect source.selected.indices and see which point on the plot are selected or like in your case: which table rows are selected. You can set a breakpoint in code in Python and also in the browser and inspect the Python or BokehJS data structures.
And here is your code (slightly modified for "pure Bokeh" v1.0.4 as I don't have Jupiter Notebook installed)
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, DataTable, TableColumn
from bokeh.plotting import figure, curdoc
from bokeh.io import show, output_notebook
from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature
# output_notebook()
def modify_doc(doc):
df = sea_surface_temperature.copy()
source = ColumnDataSource(data = df)
source_table = ColumnDataSource(data = "alpha": [s for s in "abcdefgh"],
"num": list(range(8)))
plot = figure(x_axis_type = 'datetime', y_range = (0, 25),
y_axis_label = 'Temperature (Celsius)',
title = "Sea Surface Temperature at 43.18, -70.43")
plot.line('time', 'temperature', source = source)
def callback(attr, old, new): # here new is an array containing selected rows
if new == 0:
data = df
else:
data = df.rolling('0D'.format(new[0])).mean() # asuming one row is selected
source.data = ColumnDataSource(data = data).data
table = DataTable(source = source_table,
columns = [TableColumn(field = "alpha", title = "Alpha"),
TableColumn(field = "num", title = "Num")])
source_table.selected.on_change('indices', callback)
doc().add_root(column(table, plot))
modify_doc(curdoc)
# show(modify_doc)
Result:

edited Sep 17 at 11:55
answered Mar 28 at 20:28
TonyTony
3,0271 gold badge5 silver badges24 bronze badges
3,0271 gold badge5 silver badges24 bronze badges
add a comment
|
add a comment
|
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55403853%2fhow-to-get-a-list-of-bokeh-widget-events-and-attributes-which-can-be-used-to-tr%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown