I’m trying to plot a scatter plot using Bokeh, and then give the user the option to change how many points are displayed on the plot based on the time window (specified by the range slider). The time window itself is not on the axes of the graph.
I tried to update the x_range slice based on the slider values (which is the method used in the official Bokeh tutorials page), but this is not working for me. I’ve written the code inside the CustomJS function to get the slider values, use them to find the indices of the corresponding x_axis values. However, the x-axis is not changing.
My code:
sample_data = {'Time': [1, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 10, 11, 12, 12, 12, 13, 14, 14],
'A': ['eggs', 'eggs', 'eggs', 'eggs', 'eggs', 'eggs', 'banana', 'banana', 'banana', 'banana',
'banana', 'milk', 'milk', 'milk', 'milk', 'milk', 'sugar', 'sugar', 'sugar', 'sugar'],
'X': ['id1', 'id2', 'id3', 'id4', 'id5', 'id6', 'id7', 'id8', 'id9', 'id10', 'id11', 'id12', 'id13', 'id14', 'id15',
'id16', 'id17', 'id18', 'id19', 'id20'],
'Y': [26, 21, 49, 28, 22, 31, 33, 45, 42, 27, 11, 12, 42, 43, 36, 43, 30, 41, 16, 21]}
source = ColumnDataSource(sample_data)
TOOLTIPS= [
("X","@X"),
("Y", "@Y"),
("A", "@A"),
("Time", "@Time"),
]
plot = figure(x_range = source.data['X'], tooltips = TOOLTIPS,sizing_mode = 'stretch_width', tools = ('pan','xpan','ypan','hover','box_zoom','zoom_in','zoom_out','reset'))
plot.circle("X", "Y", source = source,size = 10 )
plot.title.text = 'All Values'
# Set up Slider widget
number_slider = RangeSlider(
start=source.data['Time'][0],
end=source.data['Time'][-1],
step = 1,
value=(source.data['Time'][0],source.data['Time'][-1]),
title="Time Window",
)
# Set up CustomJS callback
custom_js = CustomJS(
args={ # the args parameter is a dictionary of the variables that will be accessible in the JavaScript code
"plot":plot, # the first variable will be called "plot" and links to the largest_carriers_plot Python object
"x": source.data["X"], # links to list of X in the source ColumnDataSource
"time": source.data["Time"] #links to list of times in the source
},
code="""
start = this.value[0] //start time value
end = this.value[1] //end time value
//find index values of these corresponding timestamps
start_idx = time.indexOf(start)
end_idx = time.indexOf(end)
plot.x_range = x.slice(start_idx,end_idx)
plot.x_range.change.emit()
"""
)
# Add callback to slider widget
number_slider.js_on_change("value", custom_js)
layout = column([number_slider, plot], sizing_mode="stretch_width")
show(layout)