Изменение элементов макета фигуры во время подачи боке - PullRequest
0 голосов
/ 07 мая 2019

У меня есть гексограмма, отображающая тепловую карту для моих данных.Для этого я использую ColumnDataSource, содержащий информацию x, y, а также значения и цвет для этого элемента.Дополнительно я добавляю цветовую полосу на шестнадцатеричный график, показывающий информацию, какое значение приведет к какому цвету.Это должно работать для разных наборов данных, однако я не могу обновить цветную полосу в соответствии с минимальными и высокими значениями во время выполнения.

Вот пример кода (простой пример myapp, предоставленный bokeh), где каждыйПри нажатии кнопки следует добавить цветную полосу с различными значениями:

from random import random
from bokeh.layouts import column
from bokeh.models import Button, LinearColorMapper, ColorBar, BasicTicker
from bokeh.palettes import RdYlBu3
from bokeh.plotting import figure, curdoc
from colorcet import CET_L18 as palette

# create a plot and style its properties
p = figure(x_range=(0, 100), y_range=(0, 100), toolbar_location=None)
p.border_fill_color = 'black'
p.background_fill_color = 'black'
p.outline_line_color = None
p.grid.grid_line_color = None

# add a text renderer to our plot (no data yet)
r = p.text(x=[], y=[], text=[], text_color=[], text_font_size="20pt",
           text_baseline="middle", text_align="center")
i = 0

ds = r.data_source
# create a callback that will add a number in a random location
def callback():
    global i

    # BEST PRACTICE --- update .data in one step with a new dict
    new_data = dict()
    new_data['x'] = ds.data['x'] + [random()*70 + 15]
    new_data['y'] = ds.data['y'] + [random()*70 + 15]
    new_data['text_color'] = ds.data['text_color'] + [RdYlBu3[i%3]]
    new_data['text'] = ds.data['text'] + [str(i)]
    ds.data = new_data
    color_mapper = LinearColorMapper(palette=palette, low=0, high=1000*i)

    color_bar = ColorBar(color_mapper=color_mapper, ticker=BasicTicker(),
                         label_standoff=12, border_line_color=None, location=(0, 0), orientation="horizontal")
    p.add_layout(color_bar, 'below')
    i = i + 1

# add a button widget and configure with the call back
button = Button(label="Press Me")
button.on_click(callback)
#show(p)
# put the button and plot in a layout and add to the document
curdoc().add_root(column(button, p))

Однако цветовая полоса не добавляется во время выполнения.Я также попытался добавить это перед рукой, тогда это будет отображено, но не обновлено.Как я могу добавить цветную полосу и / или обновить ее во время выполнения?

1 Ответ

1 голос
/ 08 мая 2019

Во-первых, переместите настройку компоновки за пределы функции обратного вызова для кнопки и сделайте так, чтобы функция обратного вызова только обновляла данные.

Затем используйте функцию linear_cmap из bokeh.transform для построения линейной цветовой карты.Эта функция дает вам преобразователь для получения цвета для значения в цветовой палитре.

Наконец, обновите high значение преобразования в обратном вызове

Полный источник

from random import random
from bokeh.layouts import column
from bokeh.models import Button, ColorBar, BasicTicker
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure, curdoc
from colorcet import CET_L18 as palette
from bokeh.transform import linear_cmap

# create a plot and style its properties
p = figure(x_range=(0, 100), y_range=(0, 100), toolbar_location=None)
p.border_fill_color = 'black'
p.background_fill_color = 'black'
p.outline_line_color = None
p.grid.grid_line_color = None

i = 0

color_mapper = linear_cmap(field_name='text', palette=palette, low=0, high=i)
color_bar = ColorBar(
    color_mapper=color_mapper['transform'], 
    ticker=BasicTicker(),
    label_standoff=12,
    border_line_color='black',
    location=(0, 0),
    orientation="horizontal")

# add a text renderer to our plot (no data yet)
ds = ColumnDataSource(dict(x=[],y=[],text=[]))
r = p.text(x='x', y='y', text='text', text_color=color_mapper, text_font_size="20pt",
           text_baseline="middle", text_align="center", source=ds)
p.add_layout(color_bar, 'below')

# create a callback that will add a number in a random location
def callback():
    global i

    i = i + 1 
    # BEST PRACTICE --- update .data in one step with a new dict
    new_data = dict()
    new_data['x'] = ds.data['x'] + [random()*70 + 15]
    new_data['y'] = ds.data['y'] + [random()*70 + 15]
    new_data['text'] = ds.data['text'] + [i]
    ds.data = new_data
    color_mapper['transform'].high = i

# add a button widget and configure with the call back
button = Button(label="Press Me")
button.on_click(callback)
#show(p)
# put the button and plot in a layout and add to the document
curdoc().add_root(column(button, p))
...