Bokeh动态改变BoxAnnotation

时间:2015-10-28 22:47:32

标签: bokeh

是否有可能在IPython的交互功能中更新散景图的渲染。我的代码看起来像:

x = [0, 1, 2, 3, 4]
y = [0, 1, 2, 3, 4]
source = ColumnDataSource(data=dict(x=x, y=y)
f = figure()
f.line(x, y, source=source)
show(f)

def update_func(selected_data):
   source.data['y'] = ...
   source.push_notebook()
   <here I would like to add BoxAnnotation to figure f, and rerender it>

interactive(update_func, selected_data=[0,1,2])

2 个答案:

答案 0 :(得分:7)

您可以使用CustomJS插入一些JavaScript代码,这些代码将用于更改BoxAnnotation的底部和顶部值。我在这个例子中使用了来自Bokeh的Slider:

from bokeh.io import vform
from bokeh.models import CustomJS, Slider
from bokeh.plotting import figure, show
from bokeh.models import BoxAnnotation

plot = figure(plot_width=300, plot_height=300)
plot.line([0,1],[0,1], line_width=3, line_alpha=0.6)

box_l = BoxAnnotation(plot=plot, top=0.4, 
                      fill_alpha=0.1, fill_color='red')
box_m = BoxAnnotation(plot=plot, bottom = 0.4,top=0.6, 
                      fill_alpha=0.1, fill_color='green')
box_h = BoxAnnotation(plot=plot, bottom=0.6, 
                      fill_alpha=0.1, fill_color='red')
plot.renderers.extend([box_l, box_m, box_h])

callb_low = CustomJS(args=dict(box_l=box_l,box_m=box_m,plot=plot),
    code="""
        var level = cb_obj.get('value')
        box_l.set({"top":level})
        box_m.set({"bottom":level})
        plot.trigger('change');
    """)

callb_high = CustomJS(args=dict(box_m=box_m,box_h=box_h,plot=plot),
    code="""
        var level = cb_obj.get('value')
        box_m.set({"top":level})
        box_h.set({"bottom":level})
        plot.trigger('change');
    """)

slider1 = Slider(start=0.1, end=1, value=0.4, step=.01, title="low",
                 callback=callb_low)
slider2 = Slider(start=0.1, end=1, value=0.6, step=.01, title="high",
                 callback=callb_high)
layout = vform(slider1,slider2, plot)
show(layout)

输出结果如下: enter image description here

根据bigreddot的建议,您可以在ipython笔记本中完成以下操作:

from bokeh.io import push_notebook
from bokeh.plotting import figure, show
from bokeh.models import BoxAnnotation
from ipywidgets import interact

p = figure(x_range=(0,1), y_range=(0,1),plot_width=300, plot_height=300)
box_L = BoxAnnotation(plot=p, top=0.4, 
                      fill_alpha=0.1, fill_color='red')
box_M = BoxAnnotation(plot=p, bottom = 0.4,top=0.6, 
                      fill_alpha=0.1, fill_color='green')
box_H = BoxAnnotation(plot=p, bottom=0.6, 
                      fill_alpha=0.1, fill_color='red')
p.renderers.extend([box_L, box_M, box_H])

def update_func(thresh_L=0.4, thresh_H=0.6):
    box_L.top = box_M.bottom = thresh_L;
    box_M.top = box_H.bottom=thresh_H;
    p.renderers.extend([box_L, box_M, box_H])
    push_notebook()  # note, just a function, not a method on "source"

show(p)

然后在另一个单元格中启动滑块,如:

interact(update_func, thresh_L=(0, 1, 0.1),thresh_H=(0, 1, 0.1))

enter image description here

答案 1 :(得分:4)

从Bokeh 0.11开始,push_notebook函数现在可以更新任意Bokeh模型对象。因此,只需在框注释上设置/更新属性,然后调用push_notebook。您的代码看起来像:

x = [0, 1, 2, 3, 4]
y = [0, 1, 2, 3, 4]
source = ColumnDataSource(data=dict(x=x, y=y)
f = figure()
f.line(x, y, source=source)
show(f)

def update_func(selected_data):
    source.data['y'] = ...
    # update box annotation (or any other properties) here
    push_notebook()  # note, just a function, not a method on "source"

interactive(update_func, selected_data=[0,1,2]) 

你可以在这里看到一些笔记本电脑:

https://github.com/bokeh/bokeh/blob/master/examples/howto/notebook_comms/Basic%20Usage.ipynb

https://github.com/bokeh/bokeh/blob/master/examples/howto/notebook_comms/Continuous%20Updating.ipynb

https://github.com/bokeh/bokeh/blob/master/examples/howto/notebook_comms/Jupyter%20Interactors.ipynb