python - 如何使用 Bokeh 服务器在范围内使用时间戳

标签 python bokeh

在 Bokeh 应用中使用 source.stream 时,应该如何使用时间戳?

这是我想要实现的目标的一个最小示例

# test.py
from bokeh.io import curdoc, output_notebook, show
from bokeh.models import Line, Plot, ColumnDataSource, Range1d
from bokeh.layouts import column
import numpy as np

delta_time = np.timedelta64(1,'s')
start_time = np.datetime64('2017-01-01T00:00:00')

tail_length = 30

timerange = Range1d(start_time - tail_length * delta_time, start_time)
source = ColumnDataSource(dict(time=[start_time], y=[0.5]))
plot = Plot(width=200, height=100, x_range=timerange, y_range=Range1d(0,1))
plot.add_glyph(source, Line(x='time',y='y'))

def callback():
    # update axis
    layout.children[0].x_range.start += delta_time
    layout.children[0].x_range.end += delta_time

    # update data
    source.stream(dict(time=[source.data['time'][-1] + delta_time],
                       y=[np.random.rand()]), tail_length)

layout = column(plot)

curdoc().add_root(layout)

# move 10 datapoints into the sliding window before the server starts
for _ in range(10):
    callback()

# then add a new datapoint each second
curdoc().add_periodic_callback(callback, 1000)

当我使用 bokehserve test.py 启动服务器时,输出显示

enter image description here

这表明callback()函数按预期工作。但一秒钟后,当从 curdoc().add_periodic_callback 调用回调时,它无法显示任何内容,

enter image description here

为了研究 x_range 在回调期间如何变化,我添加了一条打印语句 print(layout.children[0].x_range.end, type(layout.children[0].x_range .end))callback() 定义中。看起来 x_range 坐标的类型保持不变,但由于某些奇怪的原因,当在 curdoc().add_periodic_callback 中调用回调时,它具有不同的字符串表示形式.

2017-12-01 21:54:45,520 Starting Bokeh server version 0.12.11 (running on Tornado 4.5.2)
2017-12-01 21:54:45,522 Bokeh app running at: http://localhost:5006/test
2017-12-01 21:54:45,522 Starting Bokeh server with process id: 22665
# printing the 10 initial callback calls here
2017-01-01T00:00:01 <class 'numpy.datetime64'>
2017-01-01T00:00:02 <class 'numpy.datetime64'>
2017-01-01T00:00:03 <class 'numpy.datetime64'>
2017-01-01T00:00:04 <class 'numpy.datetime64'>
2017-01-01T00:00:05 <class 'numpy.datetime64'>
2017-01-01T00:00:06 <class 'numpy.datetime64'>
2017-01-01T00:00:07 <class 'numpy.datetime64'>
2017-01-01T00:00:08 <class 'numpy.datetime64'>
2017-01-01T00:00:09 <class 'numpy.datetime64'>
2017-01-01T00:00:10 <class 'numpy.datetime64'>
2017-12-01 21:54:47,961 200 GET /test (::1) 31.59ms
2017-12-01 21:54:48,381 101 GET /test/ws?bokeh-protocol-version=1.0&bokeh-session-id=jekHIMP5Eo5kjzDDgdMgqba2bNxjbQEpDcBmgET6aHfL (::1) 0.68ms
2017-12-01 21:54:48,381 WebSocket connection opened
2017-12-01 21:54:48,381 ServerConnection created
# printing callback from curdoc().add_periodic_callback here
1483228810001 seconds <class 'numpy.timedelta64'>
1483228810002 seconds <class 'numpy.timedelta64'>
1483228810003 seconds <class 'numpy.timedelta64'>

这里到底发生了什么?

最佳答案

非常有趣的行为!正如您在

中看到的 10 个回调
for _ in range(10):
   callback()

当您点击 Bokeh 服务器的 URL 时循环执行,这些循环并计算然后返回结果并连接 WebSocket 等。

之后,ColumnDataSource 突然变成了日期时间的浮点表示形式!

以下代码显示了如何将 float 转换回日期时间以使图表再次“工作”。

请注意,我注释掉了循环,因此我只需转换第一个值。

from bokeh.io import curdoc, output_notebook, show
from bokeh.models import Line, Plot, ColumnDataSource, Range1d
from bokeh.layouts import column
import numpy as np


delta_time = np.timedelta64(1,'s')
start_time = np.datetime64('2017-01-01T00:00:00')

tail_length = 30

timerange = Range1d(start_time - tail_length * delta_time, start_time)

source = ColumnDataSource(dict(time=[start_time], y=[0.5]))
plot = Plot(width=500, height=500, x_range=timerange, y_range=Range1d(0,1))
plot.add_glyph(source, Line(x='time',y='y'))


def callback():
    # update axis
    # convert long to datetime
    layout.children[0].x_range.start = np.datetime64(layout.children[0].x_range.start, 'ms') + delta_time
    layout.children[0].x_range.end = np.datetime64(layout.children[0].x_range.end, 'ms') + delta_time

    # update data
    source.stream(dict(time=[np.datetime64(source.data['time'][-1],'ms') + delta_time],
                       y=[np.random.rand()]), tail_length)

layout = column(plot)
doc = curdoc()
doc.add_root(layout)

#move 10 datapoints into the sliding window before the server starts
# for _ in range(10):
#     callback()

# then add a new datapoint each second
doc.add_periodic_callback(callback, 1000)

关于python - 如何使用 Bokeh 服务器在范围内使用时间戳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47601524/

相关文章:

python - 面向对象

python - 正则表达式匹配以 _F<XX>_C<XX> 结尾的 URL

bokeh - 切换 Bokeh 图中的线条可见性

bokeh - 如何引用选定的 Bokeh 数据点

python - ABAQUS 中wireType 的NameError 警告

python - functools.wraps 不允许我用 Python 3 中的类包装函数

javascript - 如何检查我的 Bokeh 服务器应用程序是否已完全加载和呈现?

python - Bokeh 小部件 - 工作复选框组示例

python Bokeh ,如何制作相关图?