【问题标题】:Bokeh dynamically changing BoxAnnotationBokeh 动态改变 BoxAnnotation
【发布时间】:2016-01-28 22:13:18
【问题描述】:

是否可以在 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])

【问题讨论】:

    标签: bokeh


    【解决方案1】:

    您可以使用 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)
    

    输出将如下所示:

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

    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))
    

    【讨论】:

      【解决方案2】:

      从 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

      【讨论】:

      • 如果我们不使用笔记本,那么 push_notebook() 的等价物是什么。以免我们使用由 file_html() 生成的独立 html/javascript 网页?
      • 如果JS代码执行足够,则CustomJS如下图。否则运行真正的 python 回调需要散景服务器。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多