如何使用 "重置 "回调按钮将散景图重置为初始状态?

问题描述 投票:0回答:1

我一直在做一个项目,使用虚化可视化来显示基于代理模型(ABM)的模拟结果。在一个 最近的职位我得到了帮助,让我的数据正确地流在一个非常简化的模拟版本。我的下一个任务,我认为这将是一个没有脑子的,是添加一个 "复位 "按钮到我的布局,所以我可以把我的数字回到其初始状态,并再次从 "步骤0 "运行模拟。出乎意料的是,似乎没有一个简单的方法可以做到这一点。我已经尝试了几种不同的方法,包括重新初始化所有数据和重新填充ColumnDataSources,但我无法让之前模拟运行的数据消失。下面是一个独立的代码示例,说明了这个问题。

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两种浏览器进行可视化。

python plot server bokeh line-plot
1个回答
0
投票

你的 button3_reset 代码并没有清理任何东西--它只是在现有的东西上添加了新的东西。

相反,你应该只迭代一下 sources 列表,并设置 data 属性的初始值。这意味着,你也必须在某个地方保存这些数据。


0
投票

就像通常的情况一样,我把事情搞得非常复杂。下面是代码 button3_reset 这就是工作。

 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的提示,我意识到我只需要重新指定 .data 属性,而不是创建新的CDS。然后,为了整顿,我不得不将标题更新为 "步骤0",然后将 "步骤0 "改为 "步骤2"。step 非本地变量,所以 button2_step 就会知道在1处重新开始步骤编号,有了这个,就可以重新设置它应该做的事情了。再次感谢大家的回复。

© www.soinside.com 2019 - 2024. All rights reserved.