Problems when calling update function through add_period_callback

Hello,

First of all, I’m fairly new to bokeh, so I apologize if this is a simple question. I have created a simple line plot with bands, linked the range to another graph and added a checkbox_group to toggle the lines visibility. What I need to do now is to allow the users to change the line colors. I’ve not found any example of some color picker and I know absolutely nothing of javascript to do one myself. I figured, however, that if I specified the color sequence with a palette, and then let the user update the order in which the lines are plotted this effect woud be achieved. This is not the best solution, the ideal would be to have a color picker in some sort of button or dropdown menu. If anyone could point me in the right direction I would be very grateful. However I’m trying to implement my not-so-good solution. Inspired by the crosfitter example i created an update function to my buttons that would redraw the plot when a button checked. This way the plot order would follow the checking order. Then I used “curdoc().add_periodic_callback(update, 100)” to call this function and constantly redraw my graph. This rise an error. The callback function to “checkbox_group.on_change(‘active’, update)” requires 3 positional arguments ‘atrr’, ‘old’ and ‘new’, however “add_periodic_callback” doesn’t pass this arguments.

How could I redraw this graph?
Thanks,
Ricardo

Hi,

I tried to change the colors using this answer to stack overflow. I could create a dropdown for each line, but they don’t update the colors. I’m sharing the code below. Any help is appreciated.

from difflib import SequenceMatcher

from bokeh.io import show, output_notebook, curdoc

from bokeh.layouts import row, column, widgetbox

from bokeh.models import ColumnDataSource, RangeTool, CustomJS, Select

from bokeh.plotting import figure, curdoc

from bokeh.models import Band, HoverTool, Legend, Spacer

from bokeh.palettes import Category10

from bokeh.models.widgets import CheckboxGroup

import numpy as np

import pandas as pd

import glob

import csv

def update(atrr, old, new):

for i in range(len(lines)):

    if i in new:

        lines[i].visible = True

        pvals[i].visible = True

        bands[i].visible = True

        if (len(lines)) not in new:

             bands[i].visible = False

    else:

        lines[i].visible = False

        bands[i].visible = False

        pvals[i].visible = False

    if (len(lines)) not in new:

        for i in range(len(lines)):

            bands[i].visible = False

            if i in new:

                lines[i].visible = True

pattern = ‘*Bmpnonnon.txt’

pattern = ‘pvalue_’ + pattern

pv_name = glob.glob(pattern)[0]

av_name = ‘averageRelative’ + pv_name[6:]

name = pv_name[6:]

figname = name[7:-3] + ‘png’

tools_to_show = ‘box_zoom,save,hover,reset’

tr = figure(plot_height =300, plot_width = 1200,

        toolbar_location='above',

        y_axis_label = 'Transcriptogram',

        tools=tools_to_show)#,

pv = figure(plot_height =300, plot_width = 1200,

        toolbar_location=None,

        y_axis_label = 'p_values',

        y_axis_type="log",

        y_range=(10**(-5),1))    

c_palette = [‘#000000’] + Category10[10]

legend_it =

glyph_list =

avreldf = pd.read_csv(av_name, sep=‘\t’)

pvdf = pd.read_csv(pv_name, sep=‘\t’)

catsize =

catnames =

itercab = iter(avreldf.columns[2:])

for indcat in range(len(avreldf.columns[2:])//2):

cat = next(itercab)

catname = cat.split()

catsize += [len(catname) -2]

if len(catname) > 3:

    string1 = catname[1]

    string2 = catname[2]

    match = SequenceMatcher(None, string1, string2).find_longest_match(1, len(string1)-1, 1, len(string2)-1)

    catnames += [string1[match.a: match.a + match.size]]

else:

    catnames += catname[1][1:-1]

cat = next(itercab)

for i, col in enumerate(avreldf.iloc[:,3::2]):

avreldf[col] = avreldf[col]/np.sqrt(catsize[i])

colnames = [‘Protein’, ‘Abs. Position’]

for cat in catnames:

colnames += ['Av. ' + cat]

colnames += [cat]

avreldf.columns = colnames

avreldf[‘Position’] = avreldf[‘Abs. Position’] / avreldf[‘Abs. Position’].max()

pvdf[‘Position’] = pvdf[‘position(dim1)’] / pvdf[‘position(dim1)’].max()

avreldf.sort_values(‘Position’, inplace=True)

pvdf.sort_values(‘Position’, inplace=True)

for i, cat in enumerate(catnames):

avreldf['pvalue ' + cat] = pvdf.iloc[:,2+i]

avreldf[cat + '_low'] = avreldf['Av. ' + cat] - avreldf[cat]

avreldf[cat + '_up'] = avreldf['Av. ' + cat] + avreldf[cat]

avreldf['pvalue ’ + catnames[0]] = 1

n = len(catnames)

source = ColumnDataSource(avreldf)

lines =

bands =

pvals =

for i, cat in enumerate(catnames):

bands.append(Band(base='Position', lower=cat + '_low', upper=cat + '_up', source=source, level='underlay', fill_alpha=0.3, line_alpha=0, fill_color=c_palette[i]))

tr.add_layout(bands[i])

lines.append(tr.line('Position', 'Av. ' + cat, source=source, color=c_palette[i], name=cat))



legend_it.append((cat, [lines[i]]))

pvals.append(pv.line('Position', 'pvalue ' + cat, source=source, color = c_palette[i], line_width=0.5))

legend = Legend(items=legend_it, location=(5,114))#(0, -60))

tr.add_layout(legend, ‘right’)

hover = tr.select(dict(type=HoverTool))

hover.tooltips = [ (“Group”, “$name”),(“Position”, “@{Abs. Position}”), (“Protein”, “@Protein”),

              ("Std.", "@$name")]

hover.mode = ‘mouse’

tr.x_range = pv.x_range

layout = column(tr, row(pv, checkbox_group))

select =

callbacks =

for i in range(len(lines)):

select.append(Select(title=catnames[i] + " color", value=c_palette[i],

            options = c_palette))

callbacks.append(CustomJS(args=dict(renderer=tr, line=lines[i], band=bands[i], pval=pvals[i], select=select[i]), code ="""

line.fill_color.value = select.value;

band.fill_color.value = select.value;

pval.fill_color.value = select.value;

renderer.trigger('change')

“”"))

select[i].callback = callbacks[i]

checkbox_group = CheckboxGroup(labels = list(catnames + [‘Std.’]), active = [i for i in range(len(catnames)+1)])

checkbox_group.on_change(‘active’,update)

#layout = row(column(tr,pv),column(Spacer(height=300),checkbox_group))

layout = row(column(tr,pv),column(checkbox_group,widgetbox(select)))

#show(layout)

curdoc().add_root(layout)

``

···

Em terça-feira, 17 de julho de 2018 10:15:52 UTC-3, Ricardo Melo Ferreira escreveu:

Hello,

First of all, I’m fairly new to bokeh, so I apologize if this is a simple question. I have created a simple line plot with bands, linked the range to another graph and added a checkbox_group to toggle the lines visibility. What I need to do now is to allow the users to change the line colors. I’ve not found any example of some color picker and I know absolutely nothing of javascript to do one myself. I figured, however, that if I specified the color sequence with a palette, and then let the user update the order in which the lines are plotted this effect woud be achieved. This is not the best solution, the ideal would be to have a color picker in some sort of button or dropdown menu. If anyone could point me in the right direction I would be very grateful. However I’m trying to implement my not-so-good solution. Inspired by the crosfitter example i created an update function to my buttons that would redraw the plot when a button checked. This way the plot order would follow the checking order. Then I used “curdoc().add_periodic_callback(update, 100)” to call this function and constantly redraw my graph. This rise an error. The callback function to “checkbox_group.on_change(‘active’, update)” requires 3 positional arguments ‘atrr’, ‘old’ and ‘new’, however “add_periodic_callback” doesn’t pass this arguments.

How could I redraw this graph?
Thanks,
Ricardo

  1. it would help a lot if you post a working code
  2. it would help even more if you simplify your code to focus just on the actual problem

Tony

···

On Tuesday, July 17, 2018 at 3:15:52 PM UTC+2, Ricardo Melo Ferreira wrote:

Hello,

First of all, I’m fairly new to bokeh, so I apologize if this is a simple question. I have created a simple line plot with bands, linked the range to another graph and added a checkbox_group to toggle the lines visibility. What I need to do now is to allow the users to change the line colors. I’ve not found any example of some color picker and I know absolutely nothing of javascript to do one myself. I figured, however, that if I specified the color sequence with a palette, and then let the user update the order in which the lines are plotted this effect woud be achieved. This is not the best solution, the ideal would be to have a color picker in some sort of button or dropdown menu. If anyone could point me in the right direction I would be very grateful. However I’m trying to implement my not-so-good solution. Inspired by the crosfitter example i created an update function to my buttons that would redraw the plot when a button checked. This way the plot order would follow the checking order. Then I used “curdoc().add_periodic_callback(update, 100)” to call this function and constantly redraw my graph. This rise an error. The callback function to “checkbox_group.on_change(‘active’, update)” requires 3 positional arguments ‘atrr’, ‘old’ and ‘new’, however “add_periodic_callback” doesn’t pass this arguments.

How could I redraw this graph?
Thanks,
Ricardo