python - 在散景服务期间更改图形布局元素
问题描述
我有一个十六进制图,显示我的数据的热图。为此,我使用一个包含 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))
但是,在运行时不会添加颜色条。我也试过事先添加它,然后它会显示但不会更新。如何在运行时添加彩条和/或更新彩条?
解决方案
首先,将布局设置移到按钮的回调之外,并让回调只更新数据。
接下来,使用linear_cmap
函数 frombokeh.transform
构建线性颜色图。此函数为您提供了一个转换器来获取调色板中某个值的颜色。
最后,high
在回调中更新transform的值
完整来源
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))
推荐阅读
- tmux - 命令完成时停止 tmux 分离会话关闭
- build - 有没有一种快速的方法可以在 Qt Creator 中构建所有目标?
- iterator - 在 Rust 中生成排序地图
- javascript - D3嵌套追加更新,选择问题
- android - 清除语音引导队列
- angularjs - 从 AngularJS 站点中删除 # 前缀而不破坏链接
- python-2.7 - 我应该能够将 moto SNS 通知订阅到 moto SQS 队列吗?
- python - 这是预期的 csrf 失败吗?
- keras - keras 上的 ResourceExhaustedError
- r - 将具有取决于另一列的值的列添加到数据框中