2

Working in a Bokeh plot that includes 35 lines, when trying to make them visible and invisble using checkbox widget this error arises when cliking in one of the elements of the checkbox, and no line disappears. The logs are:

PS C:\Users\407334\pad-s100> bokeh serve plot4.py
2017-02-01 14:42:36,759 Starting Bokeh server version 0.12.4
2017-02-01 15:09:13,523 Starting Bokeh server on port 5006 with applications at paths ['/plot4']
2017-02-01 15:09:13,525 Starting Bokeh server with process id: 11116
2017-02-01 15:10:05,821 200 GET /plot4 (::1) 6733.00ms
2017-02-01 15:10:06,246 WebSocket connection opened
2017-02-01 15:10:06,247 ServerConnection created
2017-02-01 15:10:30,026 error handling message Message 'PATCH-DOC' (revision 1): ValueError('too many values to unpack',
)

The python script used is influenced by this example:

from bokeh.layouts import row
from bokeh.plotting import figure
from bokeh.io import curdoc
from bokeh.palettes import inferno
from bokeh.models.widgets import CheckboxGroup
import pandas as pd

p = figure(title="Motor-Block Monitorization", width=900, plot_height=900, x_axis_type='datetime')

numlines = len(df.columns)
mypalette = inferno(numlines)
line_set = dict()

for (x, column_names, colores) in zip(range(0, numlines), df.columns.values, mypalette):
    if column_names != 'Date' and column_names != 'Time':
        line_set["line{0}".format(x)] = p.line(df.index, df[column_names], color=colores)

act = range(0, numlines)
checkbox = CheckboxGroup(labels=list(df.columns.values),
                     active=act)


def update(attr, old, new):
    for i, element in line_set:
        element.visible = i in checkbox.active

checkbox.on_change('active', update)
main_column = row(p, checkbox)
curdoc().add_root(main_column)

Different ways to plot them have been tested but the error is still there.

This is the plot working: Bokeh Plot

BSP
  • 735
  • 1
  • 10
  • 27

1 Answers1

2

checkbox.active is a list of integers from 0 to n-1, so when you search for a match to line0, line1... convert that to integer, i.e:

def update(attr, old, new):
    for i, element in line_set.iteritems():
        element.visible = int(i[4:]) in checkbox.active

Instead of creating a dictionary, a list can be populated, which will preserve the order, so no need to match the key of the dictionary with the active checkbox. I've created some panda data to play with. The following code implementing the later idea works, at least in bokeh version 0.12.4 using python2.7:

import bokeh
import bokeh.plotting

# Begin Creating some panda data
# ------------------------------
import datetime
import pandas as pd
todays_date = datetime.datetime.now().date()
cols = 20;rows = 10.
index = pd.date_range(todays_date, periods=rows, freq='D')
columns = ['col%d'%x for x in range(cols)]
data = [pd.np.arange(cols)/10.+x for x in pd.np.arange(rows)/rows]
df = pd.DataFrame(data, index=index, columns=columns)
# ----------------------------
# End Creating some panda data

p = bokeh.plotting.figure(title="Motor-Block Monitorization", 
                          width=500, plot_height=500, x_axis_type='datetime')

numlines = len(df.columns)
mypalette = bokeh.palettes.inferno(numlines)
line_list = []

for (column_names, colores) in zip(df.columns.values, mypalette):
    if column_names != 'Date' and column_names != 'Time':
        line_list += [p.line(df.index, df[column_names], color=colores)]

act = range(0, numlines)
checkbox = bokeh.models.CheckboxGroup(labels=list(df.columns.values),
                     active=act)

def update(attr, old, new):
    for i, element in enumerate(line_list):
        element.visible = i in checkbox.active

checkbox.on_change('active', update)
main_column = bokeh.layouts.row(p, checkbox)
bokeh.io.curdoc().add_root(main_column)

enter image description here

Pablo Reyes
  • 3,073
  • 1
  • 20
  • 30
  • Thanks! Now it works great! And your code in the example is much cleaner and clearer than mine. – BSP Feb 02 '17 at 08:18
  • Thank you. This give me the opportunity to make a bokeh server application for the first time. Before I was using static bokeh pages, with a lot of JavaScript to manage interaction. Also using XMLHttpRequest to communicate to cgi programs back in the server. I knew bokeh server was the way to handle that using only python, but I needed to create an example. Now, here it is. – Pablo Reyes Feb 02 '17 at 18:12