在push_notebook

时间:2017-09-01 13:12:32

标签: python jupyter-notebook bokeh

我试图在散景中制作一个有点复杂的仪表板,其中有几个不同的图形对象和按行和列排列的小部件。

当用户与小部件交互时,某些图表会更新,而某些图表保持不变。我正在创建新的绘图对象并用layout.children [i] = x替换它们,然后发送push_notebook来更新仪表板,但这会导致一些绘图调整为最小的画布大小。

我创建了一个简单的例子来说明我的意思:

from numpy import random
from bokeh.plotting import figure, curdoc
from bokeh.layouts import row, widgetbox, column
from bokeh.models.widgets import Button, Slider
from bokeh.io import push_notebook, show, output_notebook
from bokeh.models.callbacks import CustomJS
output_notebook()
num_samples = 500
def bUpdate(var, val):
    global num_samples
    if var == "Number of Samples":
        num_samples = int(val)
        replotBottom()              
def bReCalc():
    x = [random.random() for i in range(num_samples)]
    y = [random.random() for i in range(num_samples)]
    p = figure(plot_width=COL1_W, plot_height=250)
    p.circle(x, y, color='red') 
    p.toolbar.logo = None
    layout.children[0].children[0].children[0].children[1] = p
    x = [random.random() for i in range(num_samples)]
    y = [random.random() for i in range(num_samples)]
    p2 = figure(plot_width=COL2_W, plot_height=int(COL1_W*1.8))
    p2.circle(x,y)
    layout.children[0].children[0].children[1].children[0] = p2
    push_notebook(handle=bokeh_handle)
def replotBottom():    
    x = [random.random() for i in range(num_samples)]
    y = [random.random() for i in range(num_samples)]
    p2 = figure()
    p2.circle(x,y)
    p2.plot_width=COL1_W
    p2.plot_height=COL1_W    

    x = [random.random() for i in range(num_samples)]
    y = [random.random() for i in range(num_samples)]
    p3 = figure(plot_width = COL2_W, plot_height = int(COL1_W*1.5))
    p3.circle(x,y,color='green')

    x = [random.random() for i in range(num_samples)]
    y = [random.random() for i in range(num_samples)]
    z = [random.random() for i in range(num_samples)]
    p4 = figure(plot_width = int(TOTAL_WIDTH/2-5), plot_height=COL1_W)
    p5 = figure(plot_width = int(TOTAL_WIDTH/2-5), plot_height=COL1_W)
    p4.circle(x,y)
    p5.circle(x,z)

    layout.children[0].children[0].children[0].children[3]=p2
    layout.children[0].children[0].children[1].children[1]=p3
    layout.children[0].children[1].children[0] = p4
    layout.children[0].children[1].children[1] = p5
    push_notebook(handle=bokeh_handle)

cb = CustomJS(code="""
if (IPython.notebook.kernel !== undefined) {
    var kernel = IPython.notebook.kernel;
    cmd = "bUpdate('" + cb_obj.title + "','" + cb_obj.value + "')";
    kernel.execute(cmd, {}, {});
}
""")

cbRC = CustomJS(code="""
if (IPython.notebook.kernel !== undefined) {
    var kernel = IPython.notebook.kernel;
    cmd = "bReCalc()";
    kernel.execute(cmd, {}, {});
}
""")

TOTAL_WIDTH = 800
COL1_W = int(0.25*TOTAL_WIDTH)-5
COL2_W = int(0.75*TOTAL_WIDTH)-5
WID_W = int(0.5*COL1_W) - 15
btnCalc = Button(label="Recalculate", callback=cbRC, width=WID_W)
sldSamples = Slider(start=20, end=1000, step=10, title="Number of Samples", callback_policy="mouseup", callback=cb, width=WID_W)

layout = row(column( row( column( btnCalc, figure(plot_width=COL1_W, plot_height=250), \
                               sldSamples, figure(plot_width=COL1_W, plot_height=COL1_W)), \
                        column( figure(plot_width=COL2_W, plot_height=int(COL1_W*1.8)), \
                               figure(plot_width=COL2_W, plot_height = int(COL1_W*1.5), sizing_mode="scale_height")) \
                      ), \
                   row(figure(plot_width = int(TOTAL_WIDTH/2-5), plot_height=COL1_W), figure(plot_width = int(TOTAL_WIDTH/2-5), plot_height=COL1_W))))
bokeh_handle = show(layout, notebook_handle=True)

当用户单击按钮或更改滑块的值时,某些图表会更新并重新绘制,而其他图表会随机调整大小。但是,如果您只是在另一个单元格中调用“show(layout)”,则布局会正确显示。任何人对这类事情有最佳实践的想法吗?

== EDIT ==

即使嵌入类似于此示例的散景服务器,也会发生相同类型的错误:https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/notebook_embed.ipynb

output_notebook()
def modify_doc(doc):
    num_samples = 500
    def sampChange(attr, old, new):
        global num_samples
        num_samples = int(new)    
        x = [random.random() for i in range(num_samples)]
        y = [random.random() for i in range(num_samples)]
        p2 = figure()
        p2.circle(x,y)
        p2.plot_width=COL1_W
        p2.plot_height=COL1_W    

        x = [random.random() for i in range(num_samples)]
        y = [random.random() for i in range(num_samples)]
        p3 = figure(plot_width = COL2_W, plot_height = int(COL1_W*1.5))
        p3.circle(x,y,color='green')

        x = [random.random() for i in range(num_samples)]
        y = [random.random() for i in range(num_samples)]
        z = [random.random() for i in range(num_samples)]
        p4 = figure(plot_width = int(TOTAL_WIDTH/2-5), plot_height=COL1_W)
        p5 = figure(plot_width = int(TOTAL_WIDTH/2-5), plot_height=COL1_W)
        p4.circle(x,y)
        p5.circle(x,z)

        layout.children[0].children[1] = row(p4,p5)
        layout.children[0].children[0].children[0].children[3]=p2
        layout.children[0].children[0].children[1].children[1]=p3
        #layout.children[0].children[1].children[1] = p5
        #doc.add_root(layout)
    def bReCalc():
        x = [random.random() for i in range(num_samples)]
        y = [random.random() for i in range(num_samples)]
        p = figure(plot_width=COL1_W, plot_height=250)
        p.circle(x, y, color='red') 
        p.toolbar.logo = None
        layout.children[0].children[0].children[0].children[1] = p
        x = [random.random() for i in range(num_samples)]
        y = [random.random() for i in range(num_samples)]
        p2 = figure(plot_width=COL2_W, plot_height=int(COL1_W*1.8))
        p2.circle(x,y)
        layout.children[0].children[0].children[1].children[0] = p2
        #doc.add_root(layout)
        #push_notebook(handle=bokeh_handle)

    TOTAL_WIDTH = 800
    COL1_W = int(0.25*TOTAL_WIDTH)-5
    COL2_W = int(0.75*TOTAL_WIDTH)-5
    WID_W = int(0.5*COL1_W) - 15
    btnCalc = Button(label="Recalculate", width=WID_W)
    sldSamples = Slider(start=20, end=500, step=10, title="Number of Samples", callback_policy="mouseup", width=WID_W)
    btnCalc.on_click(bReCalc)
    sldSamples.on_change('value', sampChange)
    layout = row(column( row( column( btnCalc, figure(plot_width=COL1_W, plot_height=250), \
                                   sldSamples, figure(plot_width=COL1_W, plot_height=COL1_W)), \
                            column( figure(plot_width=COL2_W, plot_height=int(COL1_W*1.8)), \
                                   figure(plot_width=COL2_W, plot_height = int(COL1_W*1.5))) \
                          ), \
                       row(figure(plot_width = int(TOTAL_WIDTH/2-5), plot_height=COL1_W), figure(plot_width = int(TOTAL_WIDTH/2-5), plot_height=COL1_W))))
    doc.add_root(layout)
    bReCalc()
    return doc

from bokeh.application.handlers import FunctionHandler
from bokeh.application import Application
handler = FunctionHandler(modify_doc)
app = Application(handler)
show(app)

0 个答案:

没有答案