【问题标题】:bokeh update data with slider using callback散景更新数据与滑块使用回调
【发布时间】:2018-01-07 12:27:05
【问题描述】:

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

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

我使用散景示例滑块:

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)

【问题讨论】:

    标签: javascript python bokeh


    【解决方案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)
    

    【讨论】:

    • 非常感谢,效果很好。我已经尝试了将近半天试图运行它,但我从来没有做过 javascript,所以我有点迷茫。
    猜你喜欢
    • 1970-01-01
    • 2020-06-30
    • 2022-06-21
    • 1970-01-01
    • 1970-01-01
    • 2018-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多