6

I'm trying to use toggle buttons in Bokeh to create an interactive website where a user can click toggle buttons to select which graphs are plotted.

The buttons would load data from a text file (containing two columns x and y data). the data files have two columns containing x and y data separated by a space.

When the toggle buttons are selected then the corresponding data would be plotted, the plot would be removed when the toggle button is deselected.

I'm currently having trouble passing an argument to the callback event, is it possible?

from bokeh.io import vform
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.models.widgets import Toggle
from bokeh.plotting import figure, output_file, show

output_file("load_data_buttons.html")

x = [0]
y = x

source = ColumnDataSource(data=dict(x=x, y=y))

plot = figure(plot_width=400, plot_height=400)
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)

callback = CustomJS(args=filename,dict(source=source), code="""
        var data = source.get('data');
        console.log(filename)
        x = data['x']
        y = data['y']
        #load data stored in the file name and assign to x and y
        source.trigger('change');
    """)

toggle1 = Toggle(label="Load data file 1", type="success",callback=callback("data_file_1.txt"))
toggle2 = Toggle(label="Load data file 2", type="success",callback=callback("data_file_2.txt"))

layout = vform(toggle1, toggle2, plot)

show(layout)
Jon
  • 171
  • 3
  • 12

1 Answers1

2

You should load the two file and save the data into a DataSource object, here is an example:

from bokeh.io import vplot
import pandas as pd
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.models.widgets import Button
from bokeh.plotting import figure, output_file, show

output_file("load_data_buttons.html")

df1 = pd.read_csv("data_file_1.txt")
df2 = pd.read_csv("data_file_2.txt")

plot = figure(plot_width=400, plot_height=400)

source = ColumnDataSource(data=dict(x=[0, 1], y=[0, 1]))
source2 = ColumnDataSource(data=dict(x1=df1.x.values, y1=df1.y.values, 
                                    x2=df2.x.values, y2=df2.y.values))

plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)

callback = CustomJS(args=dict(source=source, source2=source2), code="""
        var data = source.get('data');
        var data2 = source2.get('data');
        data['x'] = data2['x' + cb_obj.get("name")];
        data['y'] = data2['y' + cb_obj.get("name")];
        source.trigger('change');
    """)

toggle1 = Button(label="Load data file 1", callback=callback, name="1")
toggle2 = Button(label="Load data file 2", callback=callback, name="2")

layout = vplot(toggle1, toggle2, plot)

show(layout)
HYRY
  • 94,853
  • 25
  • 187
  • 187
  • Thanks for the answer HYRY. This is really nice the only trouble is I've got hundreds of data files which result in many mb of data. I don't really want to preload it all up in advance as this would take a long time. Do you know of a way to load up the data as the buttons are clicked. – Jon Jan 13 '16 at 15:42
  • 2
    Then you need create a javascript function to parse csv file, here is a example: http://stackoverflow.com/questions/7431268/how-to-read-data-from-csv-file-using-javascript – HYRY Jan 13 '16 at 22:36
  • Many thanks, this combination of answers solved my problem. Much appreciated. – Jon Jan 14 '16 at 08:19