如何使用Bokeh服务器在范围内使用时间间隔

时间:2017-12-01 21:08:54

标签: python 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)

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

enter image description here

表示callback()函数按照有意义工作。但是一秒钟之后,从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'>

这里到底发生了什么?

1 个答案:

答案 0 :(得分:1)

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

中看到的10个回调
for _ in range(10):
   callback()
当你点击散景服务器的URL时,

循环执行,循环执行并计算然后返回结果并连接WebSocket等。

之后,ColumnDataSource突然出现在datetime的float表示中!

以下代码显示了如何将float转换回datetime将使图表&#34;工作&#34;再次。

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

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)