#python-2.7 #bokeh
#python-2.7 #боке
Вопрос:
Я создаю веб-приложение, которое будет отображать изображения как часть конвейера анализа данных. Для этого мне нужно динамически изменять ширину и высоту Figure
объекта в боке.
С помощью следующего кода форма Figure
изменяется, но изменение вступает в силу только после изменения размера окна браузера, даже если размер окна браузера очень мал.
import bokeh.plotting
import bokeh.models
import bokeh.layouts
# set up the interface
fig1 = bokeh.plotting.figure()
button = bokeh.models.Button(label='scramble')
# define a callback and connect it
def callback():
fig1.width = int(fig1.width * .8)
button.on_click(callback)
# add everything to the document
bokeh.plotting.curdoc().add_root(bokeh.layouts.column(button, fig1))
Есть ли какой-нибудь метод обновления, который мне нужно запустить? Я читал о «обратных вызовах следующего тика», но я не понимаю, имеет ли это значение.
Описанное выше поведение происходит как с firefox, так и с chromium в моей системе gnome.
Комментарии:
1. Приведенный выше код был выполнен с помощью ‘bokeh serve’
Ответ №1:
Причина, по которой это происходит, заключается в том, что макет не обновляется. Хотя ваш код изменяет значение свойства фигуры, вам необходимо пересчитать все значения в решателе документов, чтобы произошло фактическое изменение размера.
Вот строка в BokehJS, в которой происходит изменение размера:
https://github.com/bokeh/bokeh/blob/master/bokehjs/src/coffee/document.coffee#L92
После вызова resize на уровне документа объекты resize повторно визуализируются:
https://github.com/bokeh/bokeh/blob/master/bokehjs/src/coffee/models/layouts/layout_dom.coffee#L61
Проблема в том, что в настоящее время, насколько мне известно, нет открытого способа повторного запуска события изменения размера документа.
Однако вы можете сделать это на стороне клиента. Вот рабочий код, использующий CustomJS
:
test.py
from bokeh.io import show
from bokeh.layouts import column
from bokeh.models import Button, CustomJS
from bokeh.plotting import figure
fig = figure()
button = Button(label='scramble')
button.callback = CustomJS(args=dict(fig=fig), code="""
var old_width = fig.width;
var doc = fig.document;
fig.width = old_width * 0.8;
doc.resize();
""")
col = column(button, fig)
show(col)
Это можно запустить с python test.py
помощью .
Обратите внимание, что вы также можете сделать это с помощью bokeh server, заменив последнюю строку show(col)
на curdoc().add_root(col)
, но я не сделал этого, чтобы подчеркнуть, что это решение на стороне клиента.
Комментарии:
1. Это все еще работает в версии Boke версии 1.0.4? Это не так. Это сообщение об ошибке в консоли javascript браузера: Uncaught TypeError: doc.resize не является функцией при t.eval (eval при get (customjs.js:37), <anonymous>:7:9) при t.execute (customjs.js:43) при e.t.change_input (abstract_button.js:56) в e.change_input (button.js:14) в e.t._button_click (abstract_button.js:52) в HTMLButtonElement.<анонимный> (abstract_button.js:42)
2. Первое. Очень, очень скоро выйдет следующий релиз со значительно улучшенным макетом. Это очень старый код, и я бы не ожидал, что он будет работать, но я ожидаю, что новый код будет намного чище. Теперь свойство будет plot_width ( bokeh. pydata.org/en/latest/docs/reference/models /… ). Вам не нужно выполнять никаких запусков. Посмотрите этот потрясающий пример для вдохновения: github.com/bokeh/bokeh/blob/master/examples/plotting/file /…
3. Кроме того, теперь передан bokeh 1.0, API обещают больше не ломаться. Спасибо за ваше терпение.
Ответ №2:
Существует способ динамического изменения размера диаграмм боке со встроенной функциональностью. Например,
fig = plotting.figure(width=1200, height=900, title="Dynamic plot".format(chartType), sizing_mode='scale_width')
Ключевым параметром является sizing_mode='scale_width'
Команды width
и height
служат в качестве начальных значений. Есть и другие варианты sizing_mode
, поэтому я бы изучил это.
Комментарии:
1. Я изучил режимы определения размера, но описанное поведение сохранялось.