javascript - 使用回调使用 slider 更新 Bokeh 数据

标签 javascript python bokeh

我目前正在做需要使用三个 slider 实时更新 ColumnDataSource 的事情。我需要更新数据有两个原因,第一个是根据 slider 的值修改字形颜色,之后,我希望能够在数据表上显示点并下载数据表。

所以我使用了 custumJS 函数,但它不起作用。我认为问题出在命令 source.on_change("value") 上,但我不确定,因为我在使用回调时遇到了一些问题。

我使用 Bokeh 示例 slider :

https://docs.bokeh.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)

最佳答案

上面的代码有几个问题。一是在回调的 JS 循环中,您根本没有对列建立索引。 xy 等都是数组,要更新它们,您必须使用外观索引,例如x[i]。此外,根据我认为您想要的,最好只有一个回调,在 slider 更改时更新源和适当的跨度。这是执行此操作的完整更新代码:

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)

关于javascript - 使用回调使用 slider 更新 Bokeh 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48137081/

相关文章:

javascript - Chrome滚动错误?

python - 基于文档中嵌套元素的 Pymongo 查询

python - MFCC Python : completely different result from librosa vs python_speech_features vs tensorflow. 信号

bokeh - "BAD_COLUMN_NAME"来自 Bokeh 图的消息

javascript - 在具有固定链调用结束的循环中链接 jquery .when().then()

javascript - JavaScript 中的乘法表 - 2 个表

javascript - 我在 Jquery 中操作 'this' 有什么问题吗?

python - 如何应用将向量返回到每个 numpy 数组元素的函数(并获取更高维度的数组)

python - 保存 Bokeh 仪表板(独立)以及内部生成的所有数据

python - Bokeh 以及如何将其变成 GUI