Bokeh:CustomJS TextInput回调调整x轴范围

时间:2018-02-08 19:05:06

标签: javascript python ajax bokeh

我正在尝试创建一个由AjaxDataSource对象提供支持的绘图的网页。但是,我希望有一个TextInput小部件可用于更改此绘图的xrange。以下是一个片段:

source = AjaxDataSource(data={"time": [], "temperature": [], "id": []},
                        data_url='http://localhost:6543/AJAXdata',
                        polling_interval=100,
                        mode='append')
livePlot = figure(x_axis_type="datetime",
                  x_range=[startDt, endDt],
                  y_range=(0,25),
                  y_axis_label='Temperature (Celsius)',
                  title="Sea Surface Temperature at 43.18, -70.43",
                  plot_width=800)
livePlot.line("time", "temperature", source=source)
....
updateStartJS = CustomJS(args=dict(xrange=livePlot.x_range), code="""
    var startStr = cb_obj.value
    alert(startStr)
    var newStartMilliSeconds = Date.parse(startStr)
    alert(newStartMilliSeconds)
    alert(xrange)
    alert(xrange.start)
    xrange.start = newStartMilliSeconds
    alert(xrange.start)
    xrange.change.emit();
""")
startInput = TextInput(value=startDt.strftime(dateFmt), callback=updateStartJS)

有关完整实施的信息,请参阅此文件和bokeh_ajax()函数:https://github.com/hhprogram/PyramidSite/blob/master/webgraphing/views/ajaxView.py

当我运行它并更改相应的'开始' textInput框。 CustomJS相应地运行并根据警报我已经看到它正在捕获正确的新数据(假设您输入了像YYYY-mm-dd这样的ISO格式化日期),但是它无法更新绘图轴范围(即绘图没有&# 39; t完全改变)。我该如何实现? (我想维护这些图也有基础AjaxDataSources而不使用散景服务器 - 如果运行散景服务器,我已经知道如何实现这种类型的轴更改功能。)

1 个答案:

答案 0 :(得分:1)

对于任何好奇的人,找到了我的问题。认为主要的问题是我没有把我想要用来控制绘图xrange的小部件和实际的绘图本身放在同一个布局对象中。因此,当我在绘图对象上调用组件时,它没有包含小部件。然后,当我将小部件与情节一起包含在内时。请参阅以下更新和更新的github repo:

(感谢这篇文章非常有帮助我:Flask + Bokeh AjaxDataSource

完整档案:https://github.com/hhprogram/PyramidSite/blob/master/webgraphing/views/ajaxView.py

代码段:

source = AjaxDataSource(data={"time": [], "temperature": [], "id": []},
                        data_url='http://localhost:6543/AJAXdata',
                        polling_interval=100,
                        mode='append')
livePlot = figure(x_axis_type="datetime",
                  x_range=[startDt, endDt],
                  y_range=(0,25),
                  y_axis_label='Temperature (Celsius)',
                  title="Sea Surface Temperature at 43.18, -70.43",
                  plot_width=800)
livePlot.line("time", "temperature", source=source)
jsResources = INLINE.render_js()
cssResources = INLINE.render_css()

updateStartJS = CustomJS(args=dict(plotRange=livePlot.x_range), code="""
    var newStart = Date.parse(cb_obj.value)
    plotRange.start = newStart
    plotRange.change.emit()
""")

updateEndJS = CustomJS(args=dict(plotRange=livePlot.x_range), code="""
    var newEnd = Date.parse(cb_obj.value)
    plotRange.end = newEnd
    plotRange.change.emit()
""")

startInput = TextInput(value=startDt.strftime(dateFmt), title="Enter Date in format: YYYY-mm-dd")
startInput.js_on_change('value', updateStartJS)
endInput = TextInput(value=endDt.strftime(dateFmt), title="Enter Date in format: YYYY-mm-dd")
endInput.js_on_change('value', updateEndJS)
textWidgets = row(startInput, endInput)
# NOTE: this is important. Need to have the widgets and plot within same object that is the argument for components() method
layout =  column(textWidgets, livePlot)
script, div = components(layout)