我目前正在使用三个滑块实时更新ColumnDataSource。我需要更新数据有两个原因,第一个是根据滑块的值修改字形颜色,之后,我希望能够在数据表上显示点并下载数据表。
所以我使用函数custumJS但它不起作用。我认为问题来自命令source.on_change(“value”),但我不确定,因为我在使用回调时遇到了一些麻烦。
我使用散景示例滑块: https://bokeh.pydata.org/en/latest/docs/gallery/slider.html
这是我的代码:
from bokeh.plotting import figure, output_file, show,ColumnDataSource
from bokeh.models import HoverTool,Span,Slider, CustomJS,CategoricalColorMapper
from bokeh.layouts import row, widgetbox
from bokeh.models.widgets import *
import pandas as pd
import numpy as np
source = ColumnDataSource(
data=dict(
x = [0.154228,0.118865,0.071774,0.230292,0.070180,0.010010,0.141877,0.085712,0.166331,0.101799],
y = [1.358454,2.736966,1.556393,1.286304,1.785875,0.168123,2.120294,2.556393,5.058894,6.671531],
accession =[158489.0,442616758.0,349669.0,320544370.0,161077523.0,24648576.0,320545678.0, 17137000.0,442625663.0,17647529.0],
position = ["normal","normal","normal","normal","normal","normal","normal","normal","normal","normal"]
))
color_mapper = CategoricalColorMapper(factors=["up","normal","down"],palette=['yellow', 'green','blue'])
hover = HoverTool(tooltips=[
("accession", "@accession"),
("x","@x"),
("y","@y")
])
# setting the tools
TOOLS=",pan,wheel_zoom,box_zoom,reset,box_select,lasso_select"
# create a new plot with a title and axis labels
p = figure(
x_axis_label = 'log(fc)',
y_axis_label = '-log(pvalue)',
tools = TOOLS,)
p.add_tools(hover)
#setting the widgets slider
h_slider = Slider(start=0,end=5, value=1, step=.1, title="variation of log(pvalue)")
v_slider_right = Slider(start = 0.1, end = 0.2, value=0.15, step=.01,title="right fold change")
v_slider_left = Slider(start =0, end=0.1, value=0.05, step=.01,title="left log fold change")
# Horizontal line
hline = Span(location=h_slider.value, dimension='width', line_color='green', line_width=2)
# Vertical line
vline1 = Span(location =v_slider_right.value , dimension='height', line_color='blue', line_width=2)
vline2 = Span(location=v_slider_left.value, dimension='height', line_color='black', line_width=2)
p.renderers.extend([vline1,vline2, hline])
# add a circle points
p.circle('x','y',source = source,
color=dict(field='position', transform=color_mapper),
legend='position')
# callback of the sliders
h_slider.callback = CustomJS(args=dict(span=hline, slider=h_slider),code="""span.location = slider.value""")
v_slider_right.callback = CustomJS(args=dict(span=vline1, slider=v_slider_right),code="""span.location = slider.value""")
v_slider_left.callback = CustomJS(args=dict(span=vline2, slider=v_slider_left),code="""span.location = slider.value""")
callback = CustomJS(args=dict(source=source,v_slider_left=v_slider_left,h_slider=h_slider,v_slider_right=v_slider_right), code="""
var data = source.data;
var low = v_slider_left.value;
var up = v_slider_right.value
var back_value = h_slider.value;
x = data['x']
y = data['y']
pos = data['color']
for (i = 0; i < x.length; i++) {
if( (x < low) && (y > back_value)){
data["color"] = 'down'
} else if ((x > up) && (y > back_value)){
data["color"] = 'up'
}else{ data['color'] = 'normal'}
}
source.change.emit()
""")
columns = [TableColumn(field="accession", title="numero d'accession"),
TableColumn(field="x", title="log(fc)"),
TableColumn(field="y", title="-log(pvalue)")
]
data_table = DataTable(source=source, columns=columns, width=400, height=280)
#show the results
layout = row(p, widgetbox(v_slider_left,v_slider_right,h_slider,data_table ))
show(layout)
答案 0 :(得分:1)
上面的代码有几个问题。一个是在你的回调的JS循环中,你根本没有索引列。 x
,y
等是数组,要更新它们,您必须使用外观索引,例如x[i]
。此外,根据我的想法,最好只需要一个回调来更新源和适当的跨度,每当更改滑块时。这是一个完整的更新代码:
from bokeh.plotting import figure, output_file, show,ColumnDataSource
from bokeh.models import Button, HoverTool,Span,Slider, CustomJS,CategoricalColorMapper
from bokeh.layouts import row, widgetbox
from bokeh.models.widgets import *
import pandas as pd
import numpy as np
source = ColumnDataSource(
data=dict(
x = [0.154228,0.118865,0.071774,0.230292,0.070180,0.010010,0.141877,0.085712,0.166331,0.101799],
y = [1.358454,2.736966,1.556393,1.286304,1.785875,0.168123,2.120294,2.556393,5.058894,6.671531],
accession =[158489.0,442616758.0,349669.0,320544370.0,161077523.0,24648576.0,320545678.0, 17137000.0,442625663.0,17647529.0],
position = ["normal","normal","normal","normal","normal","normal","normal","normal","normal","normal"]
))
color_mapper = CategoricalColorMapper(factors=["up","normal","down"], palette=['yellow', 'green','blue'])
hover = HoverTool(tooltips=[
("accession", "@accession"),
("x","@x"),
("y","@y")
])
# setting the tools
TOOLS=",pan,wheel_zoom,box_zoom,reset,box_select,lasso_select"
# create a new plot with a title and axis labels
p = figure(
x_axis_label = 'log(fc)',
y_axis_label = '-log(pvalue)',
tools = TOOLS,)
p.add_tools(hover)
#setting the widgets slider
h_slider = Slider(start=0,end=5, value=1, step=.1, title="variation of log(pvalue)")
v_slider_right = Slider(start = 0.1, end = 0.2, value=0.15, step=.01,title="right fold change")
v_slider_left = Slider(start =0, end=0.1, value=0.05, step=.01,title="left log fold change")
# Horizontal line
hline = Span(location=h_slider.value, dimension='width', line_color='green', line_width=2)
# Vertical line
vline1 = Span(location =v_slider_right.value , dimension='height', line_color='blue', line_width=2)
vline2 = Span(location=v_slider_left.value, dimension='height', line_color='black', line_width=2)
p.renderers.extend([vline1,vline2, hline])
# add a circle points
p.circle('x','y',source = source,
color=dict(field='position', transform=color_mapper),
legend='position')
code="""
var data = source.data;
var low = v_slider_left.value;
var up = v_slider_right.value
var back_value = h_slider.value;
x = data['x']
y = data['y']
pos = data['position']
span.location = slider.value
for (i = 0; i < x.length; i++) {
if( (x[i] < low) && (y[i] > back_value)) {
pos[i] = 'down'
} else if ((x[i] > up) && (y[i] > back_value)){
pos[i] = 'up'
} else {
pos[i] = 'normal'
}
}
console.log(source.data)
source.change.emit()
"""
# callback of the sliders
h_slider.callback = CustomJS(args=dict(source=source, span=hline, slider=h_slider, v_slider_left=v_slider_left,h_slider=h_slider,v_slider_right=v_slider_right), code=code)
v_slider_right.callback = CustomJS(args=dict(source=source, span=vline1, slider=v_slider_right, v_slider_left=v_slider_left,h_slider=h_slider,v_slider_right=v_slider_right), code=code)
v_slider_left.callback = CustomJS(args=dict(source=source, span=vline2, slider=v_slider_left, v_slider_left=v_slider_left,h_slider=h_slider,v_slider_right=v_slider_right), code=code)
columns = [TableColumn(field="accession", title="numero d'accession"),
TableColumn(field="x", title="log(fc)"),
TableColumn(field="y", title="-log(pvalue)")
]
data_table = DataTable(source=source, columns=columns, width=400, height=280)
#show the results
layout = row(p, widgetbox(v_slider_left,v_slider_right,h_slider,data_table ))
show(layout)