在bokeh服务期间更改人物布局元素

时间:2019-05-07 09:18:27

标签: python bokeh

我有一个六边形图,显示我的数据的热图。为此,我使用了包含x,y信息以及该项目的值和颜色的ColumnDataSource。另外,我在六角图上提供了一个彩条,显示了哪些值将导致哪种颜色的信息。这应该适用于不同的数据集,但是我无法在运行时根据最小值和最大值来更新颜色栏。

这是示例代码(由bokeh提供的简单myapp示例),其中每按一次按钮都应添加一个具有不同值的色条:

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 个答案:

答案 0 :(得分:1)

首先,将布局的设置移到按钮的回调之外,并使回调仅更新数据。

接下来,使用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))