Я работал над проектом, использующим визуализацию bokeh для отображения результатов моделирования на основе агентов (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 1.4.0 (anaconda не разрешит мне обновить), python 3.7.6, spyder 4.0.1 и оба Chrome & Brave браузеры для визуализации.