【问题标题】:Bokeh (0.12.1) Update DataColumnSource Selection programmatically with bokeh serve (Python only)Bokeh (0.12.1) 使用 bokeh serve 以编程方式更新 DataColumnSource 选择(仅限 Python)
【发布时间】:2016-08-15 11:10:24
【问题描述】:

使用 Bokeh,我试图通过 Slider 的回调以编程方式更新 .selected.selected 字典,但无法设法使选择反映在情节中。

在下面的 sn-p 中,我希望能够通过ybox_select 工具和/或通过调整控制一对最小/最大线的位置(注意:为简洁起见,在此示例中,我只包括了“最大”滑块和线)。如果可能的话,我想在不使用 CustomJS 回调的情况下实现这一点。

我在操作ybox_select 工具(触发selection_change 函数)时调整了水平线和滑块值(当然还有选择,这是隐式发生的)。相反,当我操作滑块(触发slider_selection 函数)时,我设法控制了水平线,但显然不是源选择。换言之,slider_selection 中发生的source.data 的修改会反映在绘图中(即水平线的修改位置),但source.selected 的修改不会反映在绘图中(也不反映在 DataTable 中,正如我单独验证的那样)。

按照this thread 中的建议(我已经问过这个问题的简短版本,但到目前为止没有得到任何答案),我已经制作了source.selected 的副本,然后复制回@ 987654332@(.data 相同),但这没有任何影响。

我一定错过了一些相当基本的东西,但不知道是什么。任何想法?请避免基于 CustomJS 的建议,除非您确定没有纯 Python 替代方案。

非常感谢您的任何反馈!

(注意:使用bokeh serve --show script.py将此代码作为脚本运行)

from bokeh.io import curdoc
from bokeh.models import BoxSelectTool, Slider
from bokeh.plotting import figure, ColumnDataSource
from bokeh.sampledata.glucose import data
from bokeh.layouts import column
import numpy as np


#===============================================================================
# Data and source
y = data.ix['2010-10-06']['glucose']
x = np.arange(len(y))
maxval=[max(y)]*len(x)
source = ColumnDataSource(dict(x=x, y=y, maxval=maxval))

#===============================================================================
# Basic plot setup
tools = 'wheel_zoom,ybox_select,reset'
p = figure(plot_width=800, plot_height=400, tools=tools, title='Min/max selection')

# Plot data
cr = p.circle('x', 'y', color="blue", source = source,
              selection_color="blue", nonselection_color="gray", 
              size=6, alpha=0.8)

# Plot max horizontal line
p.line('x', 'maxval', line_color='blue', line_width=0.5, source=source,
       nonselection_alpha=1.0, nonselection_color='blue')

#===============================================================================
# Callbacks
def selection_change(attrname, old, new):
    ixs = new['1d']['indices']
    if ixs:
        arr = np.asarray(source.data['y'])[ixs]
        max_slider.value = np.max(arr)
        source.data['maxval'] = [np.max(arr)]*len(source.data['x'])

def slider_selection(attrname, old, new):
    selected = source.selected.copy()
    data = source.data.copy()
    data['maxval'] = [max_slider.value]*len(data['x'])
    yy = np.asarray(data['y'])
    maxi = np.asarray(data['maxval'])
    # Below is the new selection I would to visualize
    selected['1d']['indices'] = np.where(yy <= maxi)[0].tolist() 
    # Updated data is reflected in the plot (horizontal line at 'maxval' moves)
    source.data = data.copy()  
    # Updated selection is NOT reflected in the plot 
    # (nor in a DataTable, as tested separately)
    source.selected = selected.copy() 

#===============================================================================
# Slider
max_slider = Slider(start=min(y), end=max(y), 
                    value=max(y), step=0.1, title="Maximum")

#===============================================================================
# Trigger callbacks
source.on_change('selected', selection_change)
max_slider.on_change('value', slider_selection)

#===============================================================================
# Layout
plot_layout = column(p, max_slider)

curdoc().add_root(plot_layout)
curdoc().title = "Demo"

【问题讨论】:

    标签: python bokeh


    【解决方案1】:

    将以下行添加到 slider_selection 似乎可以满足您的要求:

    source.trigger("selected", old, selected)
    

    新的函数定义:

    def slider_selection(attrname, old, new):
        selected = source.selected.copy()
        data = source.data.copy()
        data['maxval'] = [max_slider.value]*len(data['x'])
        yy = np.asarray(data['y'])
        maxi = np.asarray(data['maxval'])
        # Below is the new selection I would to visualize
        selected['1d']['indices'] = np.where(yy <= maxi)[0].tolist()
        # Updated data is reflected in the plot (horizontal line at 'maxval' moves)
        source.data = data.copy()
        # Updated selection is NOT reflected in the plot
        # (nor in a DataTable, as tested separately)
        source.selected = selected.copy()
        source.trigger("selected", old, selected)
    

    (虽然有点晚了,我发现你的问题试图找到一个类似的答案,我想这可能对其他人有用)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-28
      • 1970-01-01
      • 2020-02-02
      • 1970-01-01
      • 1970-01-01
      • 2021-06-04
      • 1970-01-01
      相关资源
      最近更新 更多