Python 如何以高刷新率将数据流传输到Jupyter中的Bokeh绘图?

Python 如何以高刷新率将数据流传输到Jupyter中的Bokeh绘图?,python,plot,stream,jupyter-notebook,bokeh,Python,Plot,Stream,Jupyter Notebook,Bokeh,我试图使用Bokeh在一个数据库中绘制一个流数据集。这是我到目前为止所拥有的 在命令行中,我通过运行命令启动bokeh服务器 $> bokeh server 这是我Jupyter笔记本上的代码 import numpy as np from IPython.display import clear_output # ------------------- new cell ---------------------# from bokeh.models.sources import C

我试图使用Bokeh在一个数据库中绘制一个流数据集。这是我到目前为止所拥有的

在命令行中,我通过运行命令启动bokeh服务器

$> bokeh server
这是我Jupyter笔记本上的代码

import numpy as np
from IPython.display import clear_output
# ------------------- new cell ---------------------#

from bokeh.models.sources import ColumnDataSource
from bokeh.client import push_session
from bokeh.driving import linear
from bokeh.plotting import figure
from bokeh.io import curdoc, output_notebook, show
# ------------------- new cell ---------------------#

output_notebook()
# ------------------- new cell ---------------------#

my_figure = figure(plot_width=800, plot_height=400)
test_data = ColumnDataSource(data=dict(x=[0], y=[0]))
linea = my_figure.line("x", "y", source=test_data)
# ------------------- new cell ---------------------#

new_data=dict(x=[0], y=[0])
x = []
y = []

step_size = 0.1  # increment for increasing step
@linear(m=step_size, b=0)
def update(step):
    x.append(step)
    y.append(np.random.rand())
    new_data['x'] = x
    new_data['y'] = y

    test_data.stream(new_data, 10)

    clear_output()
    show(my_figure)

    if step > 10: 
        session.close()    
# ------------------- new cell ---------------------#

# open a session to keep our local document in sync with server
session = push_session(curdoc())

period = 100  # in ms
curdoc().add_periodic_callback(update, period)

session.show()  # open a new browser tab with the updating plot

session.loop_until_closed()
目前,我得到的结果是Jupyter笔记本中的一个闪烁绘图,以及一个新浏览器选项卡中的一个很好的更新绘图。我想要下列任何一种

  • Jupyter中的一个很好的更新绘图,没有闪烁
  • 只需在“新浏览器”选项卡中打印
我试图删除
show(我的图)
,但每次更新都会打开一个新选项卡。我还尝试将刷新率降低到10毫秒,
period=10
session.show()
工作得很好,但是笔记本最终崩溃了,因为它刷新的速度不够快


如何获得Jupyter中bokeh绘图的良好刷新率?或者,我如何关闭Jupyter绘图,并且只有一个选项卡显示更新绘图?

以下是@bigreddot评论后修改的笔记本的代码,它使用
push_notebook
在笔记本中生成更清晰的结果(不需要运行
bokeh serve
)。它不使用回调;我不确定这是否是一个优势。同样,如果希望在新数据点出现时更新绘图,则可以在
while
循环的开头添加
if data\u事件:
语句,然后根据与事件速率配合良好的情况调整睡眠时间

官方文档中提供了有关在Jupyter笔记本中使用Bokeh的其他有用信息

import time
import numpy as np
# ------------------- new cell ---------------------#

from bokeh.models.sources import ColumnDataSource
from bokeh.plotting import figure
from bokeh.io import output_notebook, show, push_notebook
# ------------------- new cell ---------------------#

output_notebook()
# ------------------- new cell ---------------------#

my_figure = figure(plot_width=800, plot_height=400)
test_data = ColumnDataSource(data=dict(x=[0], y=[0]))
line = my_figure.line("x", "y", source=test_data)
handle = show(my_figure, notebook_handle=True)

new_data=dict(x=[0], y=[0])
x = []
y = []

step = 0
step_size = 0.1  # increment for increasing step
max_step = 10  # arbitrary stop point for example
period = .1  # in seconds (simulate waiting for new data)
n_show = 10  # number of points to keep and show
while step < max_step:
    x.append(step)
    y.append(np.random.rand())
    new_data['x'] = x = x[-n_show:]  # prevent filling ram
    new_data['y'] = y = y[-n_show:]  # prevent filling ram

    test_data.stream(new_data, n_show)

    push_notebook(handle=handle)
    step += step_size
    time.sleep(period)
导入时间
将numpy作为np导入
#--------新单元---------------------#
从bokeh.models.sources导入ColumnDataSource
从bokeh.plotting导入图形
从bokeh.io导入输出笔记本、显示、推送笔记本
#--------新单元---------------------#
输出_笔记本()
#--------新单元---------------------#
我的图形=图形(绘图宽度=800,绘图高度=400)
test_data=ColumnDataSource(data=dict(x=[0],y=[0]))
线=我的图。线(“x”,“y”,源=测试数据)
句柄=显示(我的数字,笔记本句柄=真)
新数据=dict(x=[0],y=[0])
x=[]
y=[]
步长=0
步长=0.1#增加步长的增量
最大步长=10#例如任意停止点
周期=.1秒(模拟等待新数据)
n_show=10#保留和显示的点数
当步骤<最大步骤:
x、 附加(步骤)
y、 追加(np.random.rand())
新数据['x']=x=x[-n_show:]#防止填充ram
新数据['y']=y=y[-n_show:]#防止填充ram
测试数据流(新数据,n显示)
推送笔记本(手柄=手柄)
步长+=步长大小
时间。睡眠(周期)
请注意,添加了
new_data['x']=x=x[-n_show]
(与
y
相同),因此从理论上讲,这可以无限期运行,而不会占用您的内存。另外,如果能够将某种数据源(可能来自web)流式传输,这将是一个更现实的例子。最后,您可能意识到了这一点,但在使用流图运行单元之后,内核将被锁定,直到它完成或被中断;不能执行其他单元格/代码。如果你想拥有分析/控制功能,它们应该进入
while
循环中。

@Steven C.Howell

受您示例的启发,我使用非阻塞回调函数对其进行了修改。它没有使用add_periodic_callback,因为此功能在jupyter笔记本()中不起作用。不过,在使用jupyter笔记本电脑时,能够进行非阻塞数据流可能会很有用

import time
import numpy as np
# ------------------- new cell ---------------------#

from bokeh.models.sources import ColumnDataSource
from bokeh.plotting import figure
from bokeh.io import output_notebook, show, push_notebook
# ------------------- new cell ---------------------#

output_notebook()
# ------------------- new cell ---------------------#

my_figure = figure(plot_width=800, plot_height=400)
test_data = ColumnDataSource(data=dict(x=[0], y=[0]))
line = my_figure.line("x", "y", source=test_data)
handle = show(my_figure, notebook_handle=True)
# ------------------- new cell ---------------------#

from threading import Thread

stop_threads = False

def blocking_callback(id, stop):
    new_data=dict(x=[0], y=[0])

    step = 0
    step_size = 0.1  # increment for increasing step
    max_step = 10  # arbitrary stop point for example
    period = .1  # in seconds (simulate waiting for new data)
    n_show = 10  # number of points to keep and show

    while True:

        new_data['x'] = [step]
        new_data['y'] = [np.random.rand()]

        test_data.stream(new_data, n_show)

        push_notebook(handle=handle)
        step += step_size
        time.sleep(period)

        if stop():
            print("exit")
            break

thread = Thread(target=blocking_callback, args=(id, lambda: stop_threads))
thread.start()
这样做的优点是,无限数据流不会阻止后续单元格执行:

# ------------------- new cell ---------------------#

# preceding streaming is not blocking
for cnt in range(10):
    print("Do this, while plot is still streaming", cnt)

# ------------------- new cell ---------------------#

# you might also want to stop the thread
stop_threads=True
del thread

对于我的(速度较慢的)Windows计算机,“显示(我的图形)”的绘图更加倾斜。。即使刷新速度相当慢(500毫秒以上),也无法正确更新。。我必须离开/返回选项卡以刷新x轴,点从绘图中消失。(对于之前的向下投票,请记住,新用户不能推荐!)在MacBook Pro上,我得到了与您上面描述的类似的行为,尽管使用100毫秒的刷新率,Jupyter中的绘图无法足够快地渲染,没有线条可见。将周期调整为500后,Jupyter绘图将显示出来,每次更新时都会向上滚动,使其难以查看。@bigreddot的一条注释:答案要么是
push_笔记本,要么是0.12.5,[bokeh server app embedded in notebook](https://github.com/bokeh/bokeh/blob/master/examples/howto/server_embed/notebook_embed.ipynb).  您当前正在重新创建或重新显示全部每个绘图,这将导致较差的结果。此外,使用
bokeh.client`可以将网络流量增加一倍。如果有人有一种方法可以使用回调,请随意评论或添加另一个答案,详细说明这一点。请注意,这个答案错误地使用了
函数。它只能用于发送新数据。此答案会一次又一次地重新发送最后一个
n_show
数据点。应该放弃对x和y的整个“跟踪”,在本例中,对
test\u data.stream
的调用应该替换为以下内容:
test\u data.stream({“x”:[step],“y”:[np.random.rand()]},n\u show)
@hidde jan,这听起来很合理,更像我所期望的。我将不得不尝试这个,然后更新。