我一直在做一个项目,使用虚化可视化来显示基于代理模型(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两种浏览器进行可视化。
你的 button3_reset
代码并没有清理任何东西--它只是在现有的东西上添加了新的东西。
相反,你应该只迭代一下 sources
列表,并设置 data
属性的初始值。这意味着,你也必须在某个地方保存这些数据。
就像通常的情况一样,我把事情搞得非常复杂。下面是代码 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处重新开始步骤编号,有了这个,就可以重新设置它应该做的事情了。再次感谢大家的回复。