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