python - 如何将 Bokeh 中的 slider 值传递回 Python 代码

标签 python callback bokeh

我想将 slider 值(我用 Bokeh 构建的)传递回我的 Python 代码。该代码在绘图上生成 2 条线,并允许我更改其中一条线的斜率和截距。但是当我引入回调 javascript 将 slider 值作为 "ff" 传递回我的 Python 代码时,它失败了。
你能帮助我使用回调语法来将 slider 值返回到Python(例如,参见代码的最后一行) - 我确实想做一些比仅仅打印它更有趣的事情最终出来!
回调的错误消息是:

ValueError: expected an element of Dict(String, Instance(Model)), got {'my_dict': {'s': 0.5}}

我的代码是:-

from ipywidgets import interact  
import numpy as np  
from bokeh.io import push_notebook, show, output_notebook  
from bokeh.plotting import figure  
from bokeh.models import ColumnDataSource  
from bokeh.models.callbacks import CustomJS  
output_notebook()  
x = np.linspace(0, 20, 200) # create equally spaced points.  
s = 0.5 # slope.  
i = 3 # intercept.  
y = s * x + i # straight line.  
my_dict = dict(s=s) # need to create a dict object to hold what gets passed in the callback.  

callback = CustomJS(args=dict(my_dict=my_dict), code="""  
  var ff = cb_obj.value  
  my_dict.change.emit()  
""")  
// ff should be the slider value.  

p = figure(title="simple line example", plot_height=300, plot_width=600, y_range=(-20,20),  
           background_fill_color='#efefef')  
r = p.line(x, y, color="#8888cc", line_width=1.5, alpha=0.8) # 1st line. This line can be controlled by sliders.  
q = p.line(x, 2*x+1.2, color="#0088cc", line_width=1.9, alpha=0.2) # 2nd line.  
def update(w=s, a=i):  
    r.data_source.data['y'] = w * x + a  # allow updates for the line r.  
    push_notebook()  
show(p, notebook_handle=True)  
interact(update, w=(-10,10), a=(-12,12) )  
print(ff)  # Return what the slider value is. I want ff accessible back in my python code.

最佳答案

我没有 Jupyter Notebook,所以这两个示例是纯 Bokeh 应用程序,第一个使用 JS 回调,第二个使用 Python 回调(Bokeh v1.0.4)。

import numpy as np
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource, Slider, CustomJS, Range1d
from bokeh.layouts import column

slider_slope = Slider(start = 0, end = 1, value = 0.5, step = 0.1)
slider_intercept = Slider(start = 0, end = 20, value = 10, step = 1)

slider_code = '''   i = slider_intercept.value
                    s = slider_slope.value
                    x = r.data_source.data['x'];
                    y = [];

                    for (index = 0; index < x.length; index ++)
                        y.push((s * x[index]) + i);

                    r.data_source.data['y'] = y
                    r.data_source.change.emit(); '''

s = slider_slope.value  # slope.
i = slider_intercept.value  # intercept.

x = np.linspace(-40, 20, 200)
y = [(s * xx + i) for xx in x]

p = figure(title = "simple line example", plot_height = 500, plot_width = 600, y_range = Range1d(start = -80, end = 40), background_fill_color = '#efefef')
r = p.line(x, y, color = "red", line_width = 1.5, alpha = 0.8)  # 1st line. This line can be controlled by sliders.
q = p.line(x, 2 * x + 1.2, color = "blue", line_width = 1.9, alpha = 0.2)  # 2nd line.

slider_callback = CustomJS(args = dict(slider_slope = slider_slope,
                                slider_intercept = slider_intercept,
                                r = r), code = slider_code)

slider_slope.callback = slider_callback
slider_intercept.callback = slider_callback

layout = column(p, slider_slope, slider_intercept)
show(layout, notebook_handle = True)

您可以使用 Python 回调轻松将其转换为 Bokeh 服务器应用程序:

import numpy as np
from bokeh.plotting import figure, show, curdoc
from bokeh.models import Slider, CustomJS
from bokeh.layouts import column

slider_slope = Slider(title = 'Slope', start = 0, end = 1, value = 0.5, step = 0.1)
slider_intercept = Slider(title = 'Intercept', start = 0, end = 20, value = 10, step = 1)

s = slider_slope.value  # slope.
i = slider_intercept.value  # intercept.

x = np.linspace(-40, 20, 200)
y = [(s * xx + i) for xx in x]

p = figure(title = "simple line example", plot_height = 500, plot_width = 600, y_range = Range1d(start = -80, end = 40), background_fill_color = '#efefef')
r = p.line(x, y, color = "red", line_width = 1.5, alpha = 0.8)  # 1st line. This line can be controlled by sliders.
q = p.line(x, 2 * x + 1.2, color = "blue", line_width = 1.9, alpha = 0.2)  # 2nd line.

def update(attr, old, new):
    s = slider_slope.value  # slope.
    i = slider_intercept.value  # intercept
    x = r.data_source.data['x'];
    y = []

    for value in x:
        y.append((s * value) + i)

    r.data_source.data['y'] = y

slider_slope.on_change('value', update)
slider_intercept.on_change('value', update)

layout = column(p, slider_slope, slider_intercept)
curdoc().add_root(layout)

结果:

enter image description here

关于python - 如何将 Bokeh 中的 slider 值传递回 Python 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55362916/

相关文章:

python - 函数参数中的空星号?

c# - 通过 NSubstitute 中的回调验证调用参数

java - 在对象监视器上同步还是在我的情况下是更好的信号量?

python - 获取包含在 Bokeh 中的框选择工具中的选定数据

python - 如何构建一个内存中的虚拟文件系统,然后将这个结构写入磁盘

python - 在 MAC OS X 上,py.test 不被识别为命令

python - 相位相关

ios - 如何替换 Objective-C 中已弃用的方法 toSuccessCallbackString 和 writeJavascript?

python - 实时更改 Bokeh 图 block 上的颜色

python - 使用 Bokeh Python 没有显示烛台