I have a semi-working example here, where moving the slider updates the plot, as does hovering over either of the scatter plots.
What I would like is if moving the slider also updated the color of the plot. How do I do that?
import numpy as np
import bokeh
from bokeh.models import ColumnDataSource, CustomJS, Slider
from bokeh.plotting import figure, show, output_notebook
from bokeh.models import HoverTool
from bokeh.layouts import layout
output_notebook()
# make some fake data
n = 100
n_time_pts = 1000
time = np.linspace(0,1,n_time_pts)
all_traces = [np.random.random(n_time_pts) + x for x in np.arange(n)]
x = [np.mean(x) for x in all_traces]
y = [np.std(x) for x in all_traces]
z = [np.std(x)/np.mean(x) for x in all_traces]
# make colors
colors = list(bokeh.palettes.inferno(n))
rejected_color = "#969696"
for i in np.arange(10):
colors[i] = rejected_color
colors = tuple(colors)
source = ColumnDataSource(data=dict(time=time, y=all_traces[0]))
scatter_source = ColumnDataSource(data=dict(x=x, y=y,z=z))
marker_source = ColumnDataSource(data=dict(x=[1], y=[1], z=[1]))
line_color = ColumnDataSource(data=dict(color=["black"]))
slider = Slider(start=0, end=n, step=1, value=0, max_height=50, max_width=500)
# make figure panels
trace_fig = figure(width=1000, height=500, tools=[])
trace_fig.xaxis.axis_label = 'Time (s)'
scatter1 = figure(sizing_mode="stretch_width",
height=500,
max_width = 500,
tools=[])
scatter2 = figure(sizing_mode="stretch_width",
height=500,
max_width = 500,
tools=[])
# make plots in figures
line_handle = trace_fig.line('time','y',source=source, color=line_color.data["color"][0])
scatter1.circle(x,y, size=10, color=colors, alpha=0.8, hover_alpha=0)
marker1 = scatter1.circle('x','y',size=20,fill_color = None, color="red", source=marker_source)
scatter2.circle(x,z, size=10, color=colors, alpha=0.8)
marker2 = scatter2.circle('x','z',size=20,fill_color = None, color="red", source=marker_source)
# add a hover tool that sets the link data for a hovered circle
code = """
if (cb_data.index.indices.length > 0) {
if (cb_data.index.indices[0] > 0) { // dirty hack to ignore the zero index of the marker
slider.value = (cb_data.index.indices[0])
}
};
"""
callback = CustomJS(args=dict(slider=slider), code=code)
scatter1.add_tools(HoverTool(tooltips=[],callback=callback))
scatter2.add_tools(HoverTool(tooltips=[],callback=callback))
# slider callback
callback = CustomJS(args=dict(source=source,
all_traces=all_traces,
slider=slider,
marker_source=marker_source,
scatter_source=scatter_source,
line_color=line_color,
colors=colors),
code="""
source.data.y = all_traces[slider.value];
source.change.emit();
marker_source.data.x[0] = scatter_source.data.x[slider.value];
marker_source.data.y[0] = scatter_source.data.y[slider.value];
marker_source.data.z[0] = scatter_source.data.z[slider.value];
marker_source.change.emit();
line_color.data.color = colors[slider.value];
line_color.change.emit();
""")
slider.js_on_change('value', callback)
show(layout([
[slider],
[trace_fig],
[scatter1, scatter2],
]))