Как переключаться между фигурами, используя выпадающее меню в Bokeh? - PullRequest
0 голосов
/ 22 апреля 2019

У меня есть фигура, где я уже добавил кнопки для отображения разных графиков. Как добавить еще пару фигур, каждая из которых имеет разные наборы графиков, и переключаться между фигурами с помощью раскрывающегося меню? Я стараюсь максимально сжать код, чтобы не переписывать одни и те же функции для каждой фигуры. Каков наилучший способ сделать это? В приведенном ниже примере кода я не включил ползунок и три кнопки для второй фигуры, но хотел бы, чтобы все цифры имели их

import numpy as np
import pandas as pd
import warnings
from bokeh.layouts import widgetbox
from bokeh.plotting import figure, show, output_file, output_notebook
from bokeh.palettes import Spectral11, colorblind, Inferno, BuGn, brewer
from bokeh.models import HoverTool, value, LabelSet, Legend, ColumnDataSource, LinearColorMapper, BasicTicker, PrintfTickFormatter, ColorBar
from bokeh.models.widgets import DateRangeSlider, CheckboxButtonGroup
from bokeh.models import CustomJS, ColumnDataSource
from bokeh.layouts import column, row
from json import loads
import ast
import datetime as dt

warnings.filterwarnings('ignore')

TOOLS = 'save,pan,box_zoom,reset,wheel_zoom'
p = figure(title="data", plot_height=400, tools=TOOLS, plot_width=1300)

start_date = dt.datetime.strptime('2019 04 15', '%Y %m %d')
end_date = dt.datetime.strptime('2019 04 18', '%Y %m %d')
t = np.arange(0.0, 2.0, 0.01)
dates = np.arange(start_date, end_date, np.timedelta64(1, 'h'),
                  dtype='datetime64')

x = np.sin(3*np.pi*t)[:72]
y = np.cos(3*np.pi*t)[:72]
z = np.cos(6*np.pi*t)[:72]

for c in [x, y, z]:
    c[40:50] = np.nan

source = ColumnDataSource(data={'Date': dates, 'x': x, 'y': y, 'z': z})

p.xaxis.axis_label = 'Date'
p.yaxis.axis_label = 'Position (m)'


def add_plot(y, color):
    new_plot = p.line(x='Date', y=y, line_width=1, color=color, source=source)
    return new_plot


x = add_plot('x', 'red')
y = add_plot('y', 'green')
z = add_plot('z', 'blue')

checkbox = CheckboxButtonGroup(labels=['x', 'y', 'z'], active=[0, 1, 2])
checkbox.callback = CustomJS(args=dict(x=x, y=y, z=z), code="""
    //console.log(cb_obj.active);
    x.visible = false;
    y.visible = false;
    z.visible = false;
    for (i in cb_obj.active) {
        //console.log(cb_obj.active[i]);
        if (cb_obj.active[i] == 0) {
            x.visible = true;
        } else if (cb_obj.active[i] == 1) {
            y.visible = true;
        } else if (cb_obj.active[i] == 2) {
            z.visible = true;
        }
    }
""")

callback = CustomJS(args=dict(p=p), code="""
    var a = cb_obj.value;
    p.x_range.start = a[0];
    p.x_range.end = a[1];
""")

range_slider = DateRangeSlider(start=start_date, end=end_date,
                               value=(start_date, end_date), step=1)
range_slider.js_on_change('value', callback)


def get_hovertools():
    hovers = {'x': x, 'y': y, 'z': z}
    for k, v in hovers.items():
        hovers[k] = HoverTool(mode='vline', renderers=[v])
        hovers[k].tooltips = [('Date', '@Date{%F %H:%M:%S.%u}'),
                              (k, '@{'+k+'}{%0.2f}m')]
        hovers[k].formatters = {'Date': 'datetime', k: 'printf'}
        p.add_tools(hovers[k])


get_hovertools()
# --------------------- second figure here --------------------------
p2 = figure(title="data", plot_height=400, tools=TOOLS, plot_width=1300)

start_date = dt.datetime.strptime('2019 04 15', '%Y %m %d')
end_date = dt.datetime.strptime('2019 04 18', '%Y %m %d')
t = np.arange(0.0, 2.0, 0.01)
dates = np.arange(start_date, end_date, np.timedelta64(1, 'h'),
                  dtype='datetime64')

x2 = [1]*72
y2 = [2]*72
z2 = [3]*72

source = ColumnDataSource(data={'Date': dates, 'x': x2, 'y': y2, 'z': z2})


def add_plot(y, color):
    new_plot = p2.line(x='Date', y=y, line_width=1, color=color, source=source)
    return new_plot


x2 = add_plot('x', 'red')
y2 = add_plot('y', 'green')
z2 = add_plot('z', 'blue')

layout = column(p, widgetbox(checkbox), widgetbox(range_slider),
                p2)

show(layout)

1 Ответ

1 голос
/ 23 апреля 2019

В этом примере показано, как добавить и удалить рисунок из документа Bokeh (Bokeh v1.1.0).Для ясности он не включает виджеты, но вы можете добавить свои виджеты туда же, используя тот же подход.

Однако, возможно, вы могли бы рассмотреть вкладки как вариант.При использовании вкладок вам не нужно удалять / добавлять корневые элементы, они постоянно присутствуют на отдельных вкладках, которые пользователь может переключать.Вы можете найти примеры вкладок здесь

from bokeh.models import Select, Row, ColumnDataSource
from bokeh.plotting import figure, curdoc
import numpy as np

x = np.linspace(0, 4 * np.pi, 100)
source = ColumnDataSource(dict(x = x, y = np.cos(x)))
glyphs = ["line", "scatter"]
select = Select(title = "Select plot:", value = "", options = [""] + glyphs)
curdoc().add_root(Row(select, name = 'root'))

def callback(attr, old, new):
    layouts = curdoc().get_model_by_name('root').children
    for glyph in glyphs:
        plot = curdoc().get_model_by_name(glyph)
        if plot:
            layouts.remove(plot)
    if new:
        p = figure(name = new)
        exec(new + ' = p.' + new + '("x", "y", source = source)')
        layouts.append(p)

select.on_change('value', callback)

Результат:

enter image description here

...