Reputation: 1205
Is it possible to use js_on_change
with bokeh
to dynamically update text that is placed next to a plot?
For example, using this code snippet from a different question
from random import random
from bokeh.models import CustomJS, ColumnDataSource, Span
from bokeh.plotting import figure, output_file, show
output_file("callback.html")
x = [random() for x in range(500)]
y = [random() for y in range(500)]
color = ["navy"] * len(x)
s = ColumnDataSource(data=dict(x=x, y=y, color=color))
p = figure(plot_width=400,
plot_height=400,
tools="lasso_select",
title="Select Here")
p.circle(x='x', y='y', color='color', size=8, source=s, alpha=0.4)
slope = Span(location=.5,
dimension="width",
line_alpha=.6,
line_width=5)
p.add_layout(slope)
s.selected.js_on_change(
'indices',
CustomJS(args=dict(s=s, slope=slope),
code="""
var inds = cb_obj.indices;
if (inds.length == 0) {
slope.location = 0.5
return
}
var total = 0;
for (var i = 0; i < inds.length; i++) {
total += s.data["y"][inds[i]]
}
var avg = total / inds.length;
slope.location = avg;
"""))
show(p)
I'd like to include a text right of the figure that shows the value of the computed slope.location
and updates whenever I select new points.
Upvotes: 1
Views: 1595
Reputation: 535
You can Use a Text Widget like PreText
, place it on the right side of the plot e.g via layout
and update the .text
property of that widget in your JSCallback. Make sure you use the .toString()
methode to assign the value.
from random import random
from bokeh.models import CustomJS, ColumnDataSource, Span, PreText
from bokeh.plotting import figure, output_file, show
from bokeh.layouts import layout
output_file("callback.html")
x = [random() for x in range(500)]
y = [random() for y in range(500)]
color = ["navy"] * len(x)
s = ColumnDataSource(data=dict(x=x, y=y, color=color))
p = figure(plot_width=400,
plot_height=400,
tools="lasso_select",
title="Select Here")
p.circle(x='x', y='y', color='color', size=8, source=s, alpha=0.4)
slope = Span(location=.5,
dimension="width",
line_alpha=.6,
line_width=5)
p.add_layout(slope)
slope_text = PreText(text='Slope_Text')
s.selected.js_on_change(
'indices',
CustomJS(args=dict(s=s, slope=slope, slope_text=slope_text),
code="""
var inds = cb_obj.indices;
if (inds.length == 0) {
slope.location = 0.5
return
}
var total = 0;
for (var i = 0; i < inds.length; i++) {
total += s.data["y"][inds[i]]
}
var avg = total / inds.length;
slope.location = avg;
slope_text.text = avg.toString();
"""))
layout_ = layout([[p,slope_text]])
show(layout_)
Upvotes: 1