代码之家  ›  专栏  ›  技术社区  ›  hhprogram

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

  •  3
  • hhprogram  · 技术社区  · 7 年前

    我正在尝试创建一个网页,其中包含由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

    当我运行它并更改相应的“开始”文本输入框时。CustomJS相应地运行,并且根据我看到的警报,它捕获了正确的新数据(假设您输入了ISO格式的日期,如YYYY-mm-dd),但它无法更新打印轴范围(即打印根本没有更改)。我将如何实现这一点?(我希望维护绘图,使其也具有底层AjaxDataSources,而不使用bokeh服务器-如果运行bokeh服务器,我已经知道如何实现这种类型的轴更改功能。)

    1 回复  |  直到 7 年前
        1
  •  3
  •   hhprogram    7 年前

    任何好奇的人都会发现我的问题。我想主要的问题是我没有把我想要用来控制plot xrange和实际plot本身的小部件放在同一个布局对象中。因此,当我在plot对象上调用组件时,它不包括小部件。然后,当我将小部件与绘图一起包含时,它就工作了。请参阅以下更新和更新的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)