将带有小部件的交互式散景图导出到独立的HTML [英] Export interactive Bokeh plots with widgets to standalone HTML

查看:76
本文介绍了将带有小部件的交互式散景图导出到独立的HTML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种方法,将包含交互式Bokeh图和小部件的Jupyter Notebook导出到独立HTML.当使用工具栏中的Jupyter NB下载至" HTML函数时,除交互式散景图外,其他所有内容都可以很好地导出,静态散景图也可以很好地导出(静态散点图也是交互式的,但基础数据不会更改")

如何使用在独立HTML中工作的小部件来获得交互式绘图?

下面您可以在安装了Bokeh 13.0的Jupyter Notebook中找到一个可用的示例.

import numpy as np
import pandas as pd

from bokeh.io import save, curdoc,output_file ,show, output_notebook, push_notebook
from bokeh.plotting import figure, gridplot

from bokeh.models import ColumnDataSource, Panel
from bokeh.models.widgets import Slider, Tabs, DataTable, TableColumn
from bokeh.layouts import layout, WidgetBox
from bokeh.application.handlers import FunctionHandler
from bokeh.application import Application
# output_file('tryout.html')
output_notebook()

# Static Bokeh plot:
data = pd.DataFrame(np.random.random([10,2]),columns=['x','y'])
dataMean = pd.DataFrame([],columns=['mean','std'])

dataMean.loc[:,'mean'] =data.mean()
dataMean.loc[:,'std'] =data.std()        
src1 = ColumnDataSource(data)
src2 = ColumnDataSource(dataMean)

p = figure(plot_width = 700, plot_height = 400, 
title = 'Test case',x_axis_label = 'x', y_axis_label = 'y')

p.line(source=src1,y='y',x='x',color='blue',line_width=2)
p.circle(source=src1,y='y',x='x',color='green')

columnsT = [TableColumn(field="mean", title="mean"),
        TableColumn(field="std", title='std')]
data_table = DataTable(source=src2, columns=columnsT, width=400, height=400)    
data_table.index_position = None
controls = WidgetBox(data_table)    
layO = layout([[p],[controls]])
# Make a tab with the layout 
tab1 = Panel(child=layO, title = 'test')
tabs = Tabs(tabs=[tab1])
show(tabs)

# Now the same plot, but fitted with a slider widget
def modify_doc(doc):

    def make_dataset(N = 2):

        data = pd.DataFrame(np.random.random([N,2]),columns=['x','y'])
        dataMean = pd.DataFrame([],columns=['mean','std'])

        dataMean.loc[:,'mean'] =data.mean()
        dataMean.loc[:,'std'] =data.std()        
        return ColumnDataSource(data),ColumnDataSource(dataMean)

    def make_plot(src):
        # Blank plot with correct labels
        p = figure(plot_width = 700, plot_height = 400, 
                  title = 'Test case',x_axis_label = 'x', y_axis_label = 'y')

        p.line(source=src,y='y',x='x',color='blue',line_width=2)
        p.circle(source=src,y='y',x='x',color='green')
        return p
    def update(attr, old, new):
        new_src, new_src2 = make_dataset(N_select.value)

        src.data.update(new_src.data)
        src2.data.update(new_src2.data)

    N_select = Slider(start = 2, end = 20, step = 1, value = 2, title = 'number of points',width=700)
    N_select.on_change('value', update)    

    columnsT = [
        TableColumn(field="mean", title="mean"),
        TableColumn(field="std", title='std')]

    src, src2 = make_dataset(N_select.value)
    data_table = DataTable(source=src2, columns=columnsT, width=400, height=400)    
    data_table.index_position = None

    p = make_plot(src)
    # Put controls in a single element
    controls = WidgetBox(N_select,data_table)
    layO = layout([[p],[controls]])
    # Make a tab with the layout 
    tab1 = Panel(child=layO, title = 'test')  
    tabs = Tabs(tabs=[tab1])    
    doc.add_root(tabs)
handler= FunctionHandler(modify_doc)
app = Application(handler)
show(app)

如果我将output_notebook()更改为output_file('tryout.html'),则会出现以下错误,我不理解,也可以找到解决方案:

RuntimeError:没有为笔记本类型无"安装显示钩子

希望任何人都可以帮助我解决这个问题.

提前谢谢!

解决方案

您要的是不可能的,至少据我所知,这是不可能的.您已经创建了具有真正的Python代码回调的Bokeh服务器应用程序.独立的HTML文档不可能运行真实的Python代码,因为浏览器完全无法运行Python代码.真正的Python代码回调需要实时运行的Python解释程序.如上所述,当您将bokeh服务器应用程序嵌入笔记本中时,该过程就是IPython内核.

如果您只需要可以在笔记本之外运行的Bokeh服务器应用程序(需要在Bokeh服务器上运行,因为这是运行回调的Python进程),那么最简单的方法是将所有代码放入脚本中与

一起运行

bokeh serve --show myapp.py

此类应用的非常粗略的轮廓是:

from bokeh.io import curdoc
from bokeh.layouts import column
from bokeh.models import Slider
from bokeh.plotting import figure

# create plots
plot = figure(...)

# create widgets
slider = Slider(...)

# add callbacks to widgets
def update(attr, old, new):
    pass
slider.on_change('value', update)

# put things in a layout
layout = column(slider, plot)

# add to curdoc
curdoc().add_root(layout)

或者,也可以将Bokeh服务器应用程序嵌入常规" python脚本中.为此,请参见将Bokeh Server嵌入为库.

I'm looking for a way to export my Jupyter Notebook containing interactive Bokeh plots with widgets to standalone HTML. When using the Jupyter NB "download to" HTML function located in the toolbar, everything but the interactive Bokeh plots export well, also the static Bokeh plots (static plots are 'interactive' as well, but the underlying data does not change)

How do I get the interactive plots with widgets working in a standalone HTML?

Below you can find a working example in Jupyter Notebook with Bokeh 13.0 installed.

import numpy as np
import pandas as pd

from bokeh.io import save, curdoc,output_file ,show, output_notebook, push_notebook
from bokeh.plotting import figure, gridplot

from bokeh.models import ColumnDataSource, Panel
from bokeh.models.widgets import Slider, Tabs, DataTable, TableColumn
from bokeh.layouts import layout, WidgetBox
from bokeh.application.handlers import FunctionHandler
from bokeh.application import Application
# output_file('tryout.html')
output_notebook()

# Static Bokeh plot:
data = pd.DataFrame(np.random.random([10,2]),columns=['x','y'])
dataMean = pd.DataFrame([],columns=['mean','std'])

dataMean.loc[:,'mean'] =data.mean()
dataMean.loc[:,'std'] =data.std()        
src1 = ColumnDataSource(data)
src2 = ColumnDataSource(dataMean)

p = figure(plot_width = 700, plot_height = 400, 
title = 'Test case',x_axis_label = 'x', y_axis_label = 'y')

p.line(source=src1,y='y',x='x',color='blue',line_width=2)
p.circle(source=src1,y='y',x='x',color='green')

columnsT = [TableColumn(field="mean", title="mean"),
        TableColumn(field="std", title='std')]
data_table = DataTable(source=src2, columns=columnsT, width=400, height=400)    
data_table.index_position = None
controls = WidgetBox(data_table)    
layO = layout([[p],[controls]])
# Make a tab with the layout 
tab1 = Panel(child=layO, title = 'test')
tabs = Tabs(tabs=[tab1])
show(tabs)

# Now the same plot, but fitted with a slider widget
def modify_doc(doc):

    def make_dataset(N = 2):

        data = pd.DataFrame(np.random.random([N,2]),columns=['x','y'])
        dataMean = pd.DataFrame([],columns=['mean','std'])

        dataMean.loc[:,'mean'] =data.mean()
        dataMean.loc[:,'std'] =data.std()        
        return ColumnDataSource(data),ColumnDataSource(dataMean)

    def make_plot(src):
        # Blank plot with correct labels
        p = figure(plot_width = 700, plot_height = 400, 
                  title = 'Test case',x_axis_label = 'x', y_axis_label = 'y')

        p.line(source=src,y='y',x='x',color='blue',line_width=2)
        p.circle(source=src,y='y',x='x',color='green')
        return p
    def update(attr, old, new):
        new_src, new_src2 = make_dataset(N_select.value)

        src.data.update(new_src.data)
        src2.data.update(new_src2.data)

    N_select = Slider(start = 2, end = 20, step = 1, value = 2, title = 'number of points',width=700)
    N_select.on_change('value', update)    

    columnsT = [
        TableColumn(field="mean", title="mean"),
        TableColumn(field="std", title='std')]

    src, src2 = make_dataset(N_select.value)
    data_table = DataTable(source=src2, columns=columnsT, width=400, height=400)    
    data_table.index_position = None

    p = make_plot(src)
    # Put controls in a single element
    controls = WidgetBox(N_select,data_table)
    layO = layout([[p],[controls]])
    # Make a tab with the layout 
    tab1 = Panel(child=layO, title = 'test')  
    tabs = Tabs(tabs=[tab1])    
    doc.add_root(tabs)
handler= FunctionHandler(modify_doc)
app = Application(handler)
show(app)

If I change the output_notebook() to output_file('tryout.html'), it givesme the following error, which I dont understand and could find a solution for as well:

RuntimeError: no display hook installed for notebook type None

Hope anybody is able to help me out with this.

thanks in advance!

解决方案

What you are asking for is not possible, at least not as I understand your question. You have created a Bokeh server application, with real Python code callbacks. It is not possible for a standalone HTML document to run real Python code, because browsers have no ability whatsoever to run Python code. Real Python code callbacks require a live, running Python interpreter process. When you embed a bokeh server app in the notebook, as you have done above, that process is the IPython kernel.

If you simply want a Bokeh sever app (which requires running on a Bokeh server, because that is the Python process that runs your callbacks) that can run outside the notebook, the easiest way is to put all the code in a script that you run with

bokeh serve --show myapp.py

The very rough outline of such apps is:

from bokeh.io import curdoc
from bokeh.layouts import column
from bokeh.models import Slider
from bokeh.plotting import figure

# create plots
plot = figure(...)

# create widgets
slider = Slider(...)

# add callbacks to widgets
def update(attr, old, new):
    pass
slider.on_change('value', update)

# put things in a layout
layout = column(slider, plot)

# add to curdoc
curdoc().add_root(layout)

Alternatively it's also possible to embed Bokeh server apps in "regular" python scripts. For that, see Embedding Bokeh Server as Library.

这篇关于将带有小部件的交互式散景图导出到独立的HTML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆