首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用" reset“回调按钮将bokeh图形重置为初始状态?

如何使用" reset“回调按钮将bokeh图形重置为初始状态?
EN

Stack Overflow用户
提问于 2020-04-24 11:23:37
回答 2查看 524关注 0票数 0

我一直在做一个项目,使用bokeh可视化来显示基于代理的模型(ABM)模拟的结果。在recent post中,我得到了帮助,让我的数据在我的模拟的一个非常简化的版本中正常流动。我的下一个任务,我认为是不需要动脑筋的,是在我的布局中添加一个“重置”按钮,这样我就可以将我的图形恢复到它的初始状态,并从“步骤0”再次运行模拟。令人惊讶的是,似乎没有一种简单的方法可以做到这一点。我尝试了几种不同的方法,包括重新初始化我的所有数据和重新填充我的ColumnDataSources,但我无法让以前运行的模拟中的数据消失。下面是一个独立的代码示例,说明了这个问题:

代码语言:javascript
复制
import colorcet as cc
from bokeh.server.server import Server
from bokeh.application import Application
from bokeh.application.handlers.function import FunctionHandler
from bokeh.plotting import figure, ColumnDataSource
from bokeh.models import Button
from bokeh.layouts import column
import random

def make_document(doc):

    # make a list of groups
    strategies = ['DD', 'DC', 'CD', 'CCDD']

    # initialize some vars
    step = 0
    callback_obj = None  
    colors = cc.glasbey_dark
    #num_colors = len(colors)
    # create a list to hold all CDSs for active strategies in next step
    sources = []

    # Create a figure container
    fig = figure(title='Streaming Line Plot - Step 0', plot_width=1400, plot_height=400)

    # get step 0 data for initial strategies
    for i in range(len(strategies)):
        step_data = dict(step=[step], 
                        strategy = [strategies[i]],
                        ncount=[random.choice(range(1, 100))])
        data_source = ColumnDataSource(step_data)
        color = colors[i]
        # this will create one fig.line renderer for each strategy & its data for this step
        fig.line(x='step', y='ncount', source=data_source, color=color, line_width=2)
        # add this CDS to the sources list
        sources.append(data_source)

    def button1_run():
        nonlocal callback_obj
        if button1.label == 'Run':
            button1.label = 'Stop'
            button1.button_type='danger'
            callback_obj = doc.add_periodic_callback(button2_step, 100)
        else:
            button1.label = 'Run'
            button1.button_type = 'success'
            doc.remove_periodic_callback(callback_obj)

    def button2_step():
        nonlocal step
        data = []
        step += 1
        fig.title.text = 'Streaming Line Plot - Step '+str(step)
        for i in range(len(strategies)):
            step_data = dict(step=[step], 
                            strategy = [strategies[i]],
                            ncount=[random.choice(range(1, 100))])
            data.append(step_data)
        for source, data in zip(sources, data):
            source.stream(data)        

    def button3_reset():
        step = 0
        fig.title.text = 'Streaming Line Plot - Step '+str(step)

        for i in range(len(strategies)):
            init_data = dict(step=[step], 
                            strategy = [strategies[i]],
                            ncount=[random.choice(range(1, 100))])
            reset_source = ColumnDataSource(init_data)
            print(init_data)
            color = colors[i]
            # this will create one fig.line renderer for each strategy & its data for this step
            fig.line(x='step', y='ncount', source=reset_source, color=color, line_width=2)
            # add this CDS to the sources list
            sources.append(reset_source)


    # add on_click callback for button widget
    button1 = Button(label="Run", button_type='success', width=390)
    button1.on_click(button1_run)
    button2 = Button(label="Step", button_type='primary', width=390)
    button2.on_click(button2_step)
    button3 = Button(label="Reset", button_type='warning', width=390)
    button3.on_click(button3_reset)

    doc.add_root(column(fig, button1, button2, button3))
    doc.title = "Now with live updating!"

apps = {'/': Application(FunctionHandler(make_document))}

server = Server(apps, port=5004)
server.start()

if __name__ == '__main__':
    server.io_loop.add_callback(server.show, "/")
    server.io_loop.start()

我试图在我的button3_reset代码中做的基本上是在make_document函数的顶部重复初始化。但是,即使这些代码的工作方式相同(从button3步骤中间的打印输出可以明显看出),我也无法将该图形重置为其初始的空状态。我已经阅读了很多堆栈溢出帖子和其他bokeh文档,但没有找到一个我认为是简单问题的简单答案:如何将bokeh线条图重置回其原始状态,以便可以从其起点再次运行数据流?

我使用bokeh 1.4.0 (anaconda不让我更新),python 3.7.6,spyder 4.0.1,以及Chrome和Brave浏览器来进行可视化。

EN

回答 2

Stack Overflow用户

发布于 2020-04-24 17:45:16

您的button3_reset代码不会清理任何东西-它只是在现有内容的基础上添加新内容。

相反,您应该遍历sources列表,并将每个源的data属性设置为代码中第一个循环中使用的初始值。这意味着,您还必须将这些数据保存在某个地方。

票数 0
EN

Stack Overflow用户

发布于 2020-04-25 03:18:52

像往常一样,我把事情搞得过于复杂了。下面是完成这项工作的button3_reset代码。

代码语言:javascript
复制
 def button3_reset():
        nonlocal step
        step = 0
        data = []
        fig.title.text = 'Streaming Line Plot - Step '+str(step)

        for i in range(len(strategies)):
            init_data = dict(step=[step], 
                            strategy = [strategies[i]],
                            ncount=[random.choice(range(1, 100))])
            data.append(init_data)

        for source, data in zip(sources, data):
            source.data = data

我之前所做的是生成新的CDS,但旧的CDS仍然嵌入在图中。再次感谢Eugene的提示,我意识到我只需要重新分配现有CDS的.data属性,而不是创建新的CDS。然后,为了整理东西,我不得不将标题更新回“步骤0”,然后让step成为一个非局部变量,这样button2_step就可以知道从1开始重新开始步骤编号,这样就可以重新设置它应该做的事情。再次感谢您的回复。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61400585

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档