繁体   English   中英

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

[英]How do stream data to a Bokeh plot in Jupyter with a high refresh rate?

我正在尝试使用Bokeh在Jupyter笔记本中绘制流数据集。 这是我到目前为止所拥有的。

从命令行我通过运行命令启动散景服务器

$> 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(my_figure)但每次更新都打开了一个新选项卡。 我也尝试将刷新率降低到10毫秒, period = 10 ; session.show()运行良好,但笔记本最终崩溃,因为它无法快速刷新。

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

这是修改后的笔记本的代码,遵循@ bigreddot的评论,它使用push_notebook在笔记本中产生更清晰的结果(它不需要你为绘图运行bokeh serve )。 它不使用回调; 我不确定这是否有利。 因此,如果您希望在新数据点进入时更新绘图,则可以在while循环开始时添加if data_event:语句,然后根据事件速率调整睡眠时间。

官方文档中的此页面提供了有关在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)

注意添加new_data['x'] = x = x[-n_show] (对y相同的)所以理​​论上这可以无限期地运行而不会填满你的记忆。 此外, 实际流式传输某种数据源(可能来自网络)以使其成为更现实的例子会更好。 最后,您可能已经意识到这一点,但是在使用流式图运行单元格之后,内核将被锁定,直到它完成或被中断; 你不能执行额外的单元格/代码。 如果你想拥有分析/控制功能,它们应该进入while循环。

@Steven C. Howell

受您的示例启发,我使用非阻塞回调函数对其进行了修改。 它没有使用add_periodic_callback,因为此功能在jupyter笔记本中不起作用( 在Bokeh文档中提到 )。 但是,在使用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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM