ColumnDataSourceの内容がインラインで変更されたことを図に知らせる方法があるかどうかは疑問です。私はnumpy配列を含むColumnDataSource
を持っています。図の更新時には、毎回メモリを割り当てるのを節約するためにいくつかのインプレース配列スライスの割り当てをしたいだけです。更新を強制的に表示するには、some_renderer.data_has_changed()
の行に沿って何かを表示してください。次のコードは、realloc=True
、各更新時numpy
アレイを作成するコストで所望の挙動を与え、そしてrealloc=False
パッチを更新しない問題を示す:ColumnDataSourceのnumpy配列の内容を変更するときにBokeh図形が更新されない
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
に設定されている場合、パッチは更新されません。
ご協力いただければ幸いです!
。この例は実際に私のコードの煮詰めのバージョンです。最初の考えは、変更可能なデータをさまざまなレンダラーにバインドしてから、自動的にプロットを更新するか、またはレンダラーのリストをループして更新するように指示することでした。今私のデザインを再考する必要があることがわかります。ありがとう! –
Bokehの "更新することを伝える"ことはあまりありません。新しいプロパティ値を設定するのは一般的に自動的に行われます。 1つの例外は、CDS列*を変更している場合です。このような変更は検出できないため、呼び出すことができる明示的な「トリガ」があります。しかし、それは(おそらく)有用な唯一の時間です。警告は、すべてのCDSカラムは常に同じ長さ*でなければならないということです。そのため、一度に '.data 'をすべて設定するのが最も安全で最も推奨される方法です。 – bigreddot
おそらく興味があるかもしれませんが、[バッチ更新をサポートする]問題は未解決です(https://github.com/bokeh/bokeh/issues/5438) – bigreddot