我想知道是否有办法让一个数字知道ColumnDataSource的内容已内联更改。我有一个ColumnDataSource
包含一个numpy数组,在图更新中我只想做一些就地数组切片分配,以便每次都节省分配内存。沿some_renderer.data_has_changed()
行的某些内容强制更新可见。以下代码显示了此问题,其中realloc=True
以每次更新时创建numpy
数组为代价提供了所需的行为,并且realloc=False
未更新修补程序:
import numpy as np
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource
from bokeh.layouts import column
from bokeh.io import curdoc
from bokeh.models.widgets import Select
class AppData:
def __init__(self, n, realloc=False):
self.p_source = None
self.c_source = None
self.x = np.linspace(0, 10, 20)
self.n = n
self.ys = [np.sin(self.x) - i for i in range(self.n)]
self.realloc = realloc
self.line = None
self.patch = None
def update_module(self, a, b):
assert b - a == 5
p_data = dict()
c_data = dict()
if self.p_source is not None:
p_data.update(self.p_source.data)
if self.c_source is not None:
c_data.update(self.c_source.data)
ys = [self.ys[j] for j in range(a, b)]
if "x" not in c_data or self.realloc:
c_data["x"] = self.x
if "x" not in p_data or self.realloc:
p_data["x"] = np.array(c_data["x"].tolist() + c_data["x"][::-1].tolist())
n_r = len(ys[0])
n_p = 2*n_r
if "ys" not in p_data or self.realloc:
p_data["ys"] = np.empty((n_p))
p_data["ys"][:n_r] = ys[0]
p_data["ys"][n_r:] = np.flipud(ys[-1])
c_data["y"] = ys[2]
if self.p_source is None:
self.p_source = ColumnDataSource(data=p_data)
else:
self.p_source.data = p_data
if self.c_source is None:
self.c_source = ColumnDataSource(data=c_data)
else:
self.c_source.data = c_data
if self.line is not None:
print(max(self.line.data_source.data["y"]))
print(max(self.patch.data_source.data["ys"])) # The value changes, but the figure does not!
# initialize
realloc = False # Not updating figure - set to True to get the expected behaviour
app_data = AppData(10, realloc=realloc)
app_data.update_module(4, 4 + 5)
s1 = figure(width=500, plot_height=125, title=None, toolbar_location="above")
app_data.line = s1.line("x", "y", source=app_data.c_source)
app_data.patch = s1.patch("x", "ys", source=app_data.p_source, alpha=0.3, line_width=0)
select = Select(title="Case", options=[str(i) for i in range(5)], value="4")
def select_case(attrname, old, new):
a = int(select.value)
app_data.update_module(a, a + 5)
select.on_change('value', select_case)
layout = column(select, s1)
curdoc().add_root(layout)
curdoc().title = "Example of patches {}being updated".format("not " if not realloc else "")
上面的代码应该使用bokeh serve --show example.py
运行,给定bokeh
版本0.12.3,并且脚本保存为example.py
。
所需的绘图应移动彩色色块,使得线始终位于其中间,但如果realloc
设置为True
,则不会更新色块。
非常感谢任何帮助!
答案 0 :(得分:0)
最终必须将数据序列化并通过网络发送,然后在BokehJS客户端库中进行反序列化。通过尝试切片聪明几乎肯定没有节省,这将超过其他步骤的开销。
导致更新数据源以使绘图更新的推荐和演示方法是一次性更新数据源的.data
属性。举个例子,来自sliders demo:
# Generate the new curve
x = np.linspace(0, 4*np.pi, N)
y = a*np.sin(k*x + w) + b
# This causes the plot to change -- nothing else needed
source.data = dict(x=x, y=y)