Python 推送笔记本后Bokeh布局更改和打印尺寸不正确
我正在尝试用bokeh制作一个有点复杂的仪表板,其中有几个不同的图形对象和按行和列排列的小部件 当用户与小部件交互时,一些绘图会被更新,而一些绘图则保持不变。我正在创建新的绘图对象并将其替换为layout.children[I]=x,然后发送一个push_笔记本以更新仪表板,但这会导致一些绘图调整为最小画布大小 我创建了一个简单的示例来说明我的意思:Python 推送笔记本后Bokeh布局更改和打印尺寸不正确,python,jupyter-notebook,bokeh,Python,Jupyter Notebook,Bokeh,我正在尝试用bokeh制作一个有点复杂的仪表板,其中有几个不同的图形对象和按行和列排列的小部件 当用户与小部件交互时,一些绘图会被更新,而一些绘图则保持不变。我正在创建新的绘图对象并将其替换为layout.children[I]=x,然后发送一个push_笔记本以更新仪表板,但这会导致一些绘图调整为最小画布大小 我创建了一个简单的示例来说明我的意思: from numpy import random from bokeh.plotting import figure, curdoc from b
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)”,则布局显示正确。有人对这类事情的最佳实践有什么想法吗
==编辑==
即使嵌入类似于此示例的bokeh服务器,也会发生相同类型的错误:
Python 3.6.1 Anaconda 4.4.0(64位)IPython 5.3.0我尝试了几种不同的更新方法,包括使用curdoc()和删除根并将其重置为我的布局变量,但它们都不会触发push_notebook的正确重画事件我建议在笔记本中嵌入一个真正的Bokeh服务器应用程序,它将比使用
push\u笔记本
的任何东西都更加健壮。总有一天,当有人有时间时,push_笔记本将在嵌入式服务器上重新实现,以使其更好。你可以在这里找到一个例子:我尝试使用bigreddot在链接中发送的app方法重新制作我的简单示例,但是我使用这个方法得到了相同类型的错误。此外,该应用程序的运行速度比使用push_笔记本要慢得多(仅更新绘图需要约15秒),因此,您的设置有些奇怪。当我运行应用程序代码时,应用程序最初会立即显示。我还要说你的方法更新不是最优的。更新绘图的最佳方法不是替换绘图,而是更新现有绘图中的数据。我很乐意尝试在这方面提供更多的建议(将我的可用带宽模化),但这对于迭代、来回的工作来说是很糟糕的。请随时访问公共邮件列表Python 3.6.1 Anaconda 4.4.0(64位)IPython 5.3.0我尝试了几种不同的更新方法,包括使用curdoc()和删除根并将其重置为布局变量,但是它们都不会触发push_notebook的正确重画事件。我建议在笔记本中嵌入一个真正的Bokeh服务器应用程序,它将比使用push_notebook
的任何应用程序都更加健壮。总有一天,当有人有时间时,push_笔记本将在嵌入式服务器上重新实现,以使其更好。你可以在这里找到一个例子:我尝试使用bigreddot在链接中发送的app方法重新制作我的简单示例,但是我使用这个方法得到了相同类型的错误。此外,该应用程序的运行速度比使用push_笔记本要慢得多(仅更新绘图需要约15秒),因此,您的设置有些奇怪。当我运行应用程序代码时,应用程序最初会立即显示。我还要说你的方法更新不是最优的。更新绘图的最佳方法不是替换绘图,而是更新现有绘图中的数据。我很乐意尝试在这方面提供更多的建议(将我的可用带宽模化),但这对于迭代、来回的工作来说是很糟糕的。请随时通过公共邮件列表访问
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)