Bokeh сбросить цифру при успешном нажатии на виджет - PullRequest
1 голос
/ 04 июня 2019

Я пытаюсь создать функцию обратного вызова виджета, которая сбрасывает весь график в его инициализированное состояние, но он не работает. Я ожидаю, что пользователи будут нажимать Sample столько раз, сколько они захотят, а затем смогут сбросить график vbar в исходное состояние.

Я уже создал функцию обратного вызова python и использовал некоторые функции печати для отладки, но график не сбрасывается.

plot2 = figure(plot_height=400, plot_width=int(1.618*600), title="Block Party",
              tools="crosshair,reset,save",
              x_range=[0, 11], y_range=[0, max(counts)])

plot2.vbar(x='x', top='y', source=source2, width=0.8)
"""
Set up widgets
"""
title2 = TextInput(title="Plot Title", value='Blocks')
sample = Button(label="Sample", button_type="success")
reset = Button(label="Reset", button_type="success")

# Callback
def reset_window_2():
    global source2
    print("I was clicked")
    np.random.seed(42)
    unique, counts = np.unique(np.random.randint(low=1, high=11, size=100), return_counts=True)
    source2 = ColumnDataSource(data=dict(x=unique, y=counts))
    plot2 = figure(plot_height=400, plot_width=int(1.618 * 600), title="Block Party",
                   tools="crosshair,reset,save",
                   x_range=[0, 11], y_range=[0, max(counts)])
    plot2.vbar(x='x', top='y', source=source2, width=0.618)
    reset.js_on_click(CustomJS(args=dict(p=plot2), code="""
            plots2.reset.emit()
        """))
    print("Check 2")


reset.on_click(reset_window_2)

# Set up layouts and add to document
inputs1 = column(title1, sigma, mu)
inputs2 = column(title2, sample, reset)
tab1 = row(inputs1, plot1, width=int(phi*400))
tab2 = row(inputs2, plot2, width=int(phi*400))
tab1 = Panel(child=tab1, title="Like a Gauss")
tab2 = Panel(child=tab2, title="Sampling")
tabs = Tabs(tabs=[tab1, tab2])
curdoc().add_root(tabs)
curdoc().title = "Sample Dash"

Функции печати выполняются, но сброс не выполняется. Любые идеи о том, как сбросить весь сюжет для инициализации?

1 Ответ

3 голосов
/ 04 июня 2019

Графики Боке не появляются просто благодаря тому, что они созданы. В серверных приложениях Bokeh их нужно поместить в макет и добавить в curdoc. Вы предположительно сделали это:

curdoc.add_root(plot2)

Если вы хотите заменить plot2 в браузере, его нужно заменить на curdoc. plot2, который вы создаете в своем обратном вызове, является просто локальной переменной в функции. Он появляется на время действия функции, существует только внутри функции, а затем отбрасывается, когда функция завершается. Вы на самом деле ничего не сделали с этим. Для фактической замены в curdoc будет проще сохранить график в явном макете:

lauyot = row(plot)
curdoc().add_root(layout)

Затем в вашем обратном вызове вы можете заменить то, что находится в макете:

layout.children[0] = new_plot

Все, что сказано , я бы на самом деле не советовал так поступать. Общая, всегда применимая лучшая практика для Боке:

Всегда вносите минимальные изменения.

График Bokeh содержит дюжину подкомпонентов (диапазоны, оси, глифы, источники данных, инструменты, ...). Выгрузка всего графика - это очень тяжелая операция Вместо того, что вы должны делать , просто обновите источник данных для того графика, который у вас уже есть, чтобы восстановить данные, с которых он начал:

source2.data = original_data_dict  # NOTE: set from plain python dict

Это восстановит бары в их первоначальное состояние, сделав наименьшее возможное изменение. Это использование Bokeh было оптимизировано как с точки зрения эффективной внутренней реализации, так и с точки зрения эффективных API для кодирования.

...