Использование обратного вызова Bokeh для обновления изображения на основе выбора - PullRequest
0 голосов
/ 30 октября 2019

Я использую 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, или я должен действовать по-другому?

1

...