在 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
启动服务器时,输出显示
这表明callback()
函数按预期工作。但一秒钟后,当从 curdoc().add_periodic_callback 调用回调时,它无法显示任何内容,
为了研究 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/