Я использую Bokeh для отображения диаграммы рассеяния и изображения. Я хочу обновить изображение на основе точек, выбранных на диаграмме рассеяния. Я делаю это с помощью обратного вызова javascript, но это, кажется, не имеет никакого эффекта.
У меня есть диаграмма рассеяния p1
, где каждое наблюдение хранится в s1
и также имеет координаты (x, y)как связанное изображение:
from bokeh.io import show, output_notebook
from bokeh.layouts import gridplot
from bokeh.models import ColumnDataSource, CustomJS
from bokeh.plotting import figure
output_notebook()
x = [0, 1, 2]
y = [abs(xx) for xx in x]
img = [[[1, 0], [1, 0]], [[1, 1], [1, 0]], [[1, 0], [1, 0]]]
s1 = ColumnDataSource(data=dict(x=x, y=y, i=img))
# Scatter plot on which point should be selected
p1 = figure(
tools='lasso_select', plot_width=600, plot_height=600,
title="A few points to select"
)
p1.circle('x', 'y', source=s1)
Цель состоит в том, чтобы на другом графике p2
отобразилось изображение, которое является средним значением всех изображений из выбранных точек в s1
. Я использую второй источник s2
для хранения этого усредненного изображения:
# s2 is initialised with an empty image
s2 = ColumnDataSource(
data=dict(avg=[[[0, 0], [0, 0]]],
xmin=[0], ymin=[0], dw=[2], dh=[2])
)
# Image which should change based on selection in p1
p2 = figure(title="Image affected by selection", plot_width=300,
plot_height=300, x_range = [0, 2], y_range = [0, 2]
)
p2.image(image="avg", x="xmin", y="ymin",
dw="dw", dh="dh", palette="Spectral11", source=s2
)
Я хочу обновить это среднее значение с помощью обратного вызова JS для обновления s2
на основе индексов, выбранных в s1:
# Update s2 based on data selected in s1
s1.selected.js_on_change('indices', CustomJS(args=dict(s1=s1, s2=s2), code="""
var inds = cb_obj.indices;
var d1 = s1.data;
var d2 = s2.data;
var cmat = new Array(2);
for (var i = 0; i < cmat.length; i++) {
cmat[i] = new Array(2);
}
for (x=0; x < 2; x++){
for (y=0; y < 2; y++){
for (i=0; i < inds.length; i++){
cmat[x][y] = d1['img'][inds[i]][x][y]
}
}
cmat[x][y] /= inds.length
}
d2['avg'] = []
d2['avg'].push(cmat);
d2.change.emit();
"""))
p = gridplot([[p1, p2]])
show(p)
Однако обратный вызов, похоже, не имеет никакого эффекта. Я успешно использовал обратные вызовы, чтобы повлиять на отображение на диаграмме рассеяния раньше, но я не могу заставить его работать с изображениями.
Когда я выбираю точки, изображение остается пустым. Есть ли хороший способ манипулировать массивами в обратных вызовах JS, или я должен действовать по-другому?