Выделение нескольких hex_tiles путем наведения на боке - PullRequest
0 голосов
/ 02 мая 2019

Я пытаюсь визуализировать свои данные в шестнадцатеричной карте. Для этого я использую python bokeh и соответствующую функцию hex_tile в классе figure. Мои данные принадлежат одному из 8 разных классов, каждый из которых имеет свой цвет. Изображение ниже показывает текущую визуализацию:

Current Visualization Я хотел бы добавить возможность изменять цвет элемента (и в идеале всех его членов класса), когда на него наведена мышь.

Я знаю, что это несколько возможно, поскольку сами боке приводят следующий пример: https://bokeh.pydata.org/en/latest/docs/gallery/hexbin.html Тем не менее, я не знаю, как реализовать это сам (так как это, кажется, функция для функции hexbin, а не простая функция hex_tile)

В настоящее время я предоставляю свои данные в ColumnDataSource:

source = ColumnDataSource(data=dict(
r=x_row,
q=y_col,
color=colors_array,
ipc_class=ipc_array
))

где ipc_class описывает один из 8 классов, к которым принадлежит элемент. Для всплывающей подсказки мыши использовался следующий код:

TOOLTIPS = [
("index", "$index"),
("(r,q)", "(@r, @q)"),
("ipc_class", "@ipc_class")
]

и затем я все визуализировал с помощью:

p = figure(plot_width=1600, plot_height=1000, title="Ipc to Hexes with colors", match_aspect=True,
       tools="wheel_zoom,reset,pan", background_fill_color='#440154', tooltips=TOOLTIPS)
p.grid.visible = False
p.hex_tile('q', 'r', source=source, fill_color='color')

Я бы хотел, чтобы в визуализации была добавлена ​​функция, при которой наведение на один элемент приведет к одному из следующих действий: 1. Выделите текущий элемент, изменив его цвет 2. Выделите несколько элементов одного и того же класса при наведении на них, изменив его цвет 3. Измените цвет внешней линии элемента hex_tile (или завершенного класса), когда элемент наведен на

Какая из этих функций возможна с боке и как мне это сделать?

EDIT: После попытки переопределить предложение Тони все элементы станут розовыми, как только моя мышь коснется графика, и цвет не вернется. Мой код выглядит так:

source = ColumnDataSource(data=dict(
    x=x_row,
    y=y_col,
    color=colors_array,
    ipc_class=ipc_array
))

p = figure(plot_width=800, plot_height=800, title="Ipc to Square with colors", match_aspect=True,
           tools="wheel_zoom,reset,pan", background_fill_color='#440154')
p.grid.visible = False
p.hex_tile('x', 'y', source=source, fill_color='color')

###################################

code = ''' 
for (i in cb_data.renderer.data_source.data['color'])
    cb_data.renderer.data_source.data['color'][i] = colors[i];

if (cb_data.index.indices != null) {
    hovered_index = cb_data.index.indices[0];
    hovered_color = cb_data.renderer.data_source.data['color'][hovered_index];
    for (i = 0; i < cb_data.renderer.data_source.data['color'].length; i++) {
        if (cb_data.renderer.data_source.data['color'][i] == hovered_color)
            cb_data.renderer.data_source.data['color'][i] = 'pink';
    }
}
cb_data.renderer.data_source.change.emit();
'''

TOOLTIPS = [
    ("index", "$index"),
    ("(x,y)", "(@x, @y)"),
    ("ipc_class", "@ipc_class")
]

callback = CustomJS(args=dict(colors=colors), code=code)
hover = HoverTool(tooltips=TOOLTIPS, callback=callback)
p.add_tools(hover)
########################################

output_file("hexbin.html")

show(p)

В основном я удалил подсказки из функции рисунка и поместил их в инструмент для наведения. Поскольку у меня уже есть красный на графике, я заменил цвет при наведении на «розовый». Поскольку я не совсем уверен, что должна делать каждая строка в переменной «code», я совершенно беспомощен в этом. Я думаю, что одна ошибка может заключаться в том, что мой ColumnDataSource выглядит несколько иначе, чем у Тони, и я не знаю, что было сделано для «классификации» первого и третьего элемента, а также второго и четвертого элемента вместе. Для меня было бы идеально, если бы классификация производилась по переменной «ipc_class».

Ответы [ 2 ]

1 голос
/ 02 мая 2019

После обсуждения из предыдущего поста здесь приводится решение, предназначенное для кода OP (Bokeh v1.1.0).Я сделал следующее:

1) Добавил HoverTool

2) Добавил обратный вызов JS к HoverTool, который:

  • Сбрасывает шестнадцатеричные цвета к исходным(colors_array передано в обратном вызове)
  • Проверяет индекс текущего гексагона (hovered_index)
  • Получает ip_class текущего гексагона на данный момент (hovered_ip_class)
  • Проходит по data_source.data['ip_class'] и находит все шестиугольники с тем же ip_class, что и у зависшего, и устанавливает для него новый цвет (pink)
  • Отправка сигнала source.change.emit() BokehJS дляобновить модель

код:

from bokeh.plotting import figure, show, output_file
from bokeh.models import ColumnDataSource, CustomJS, HoverTool

colors_array = ["green", "green", "blue", "blue"]
x_row = [0, 1, 2, 3]
y_col = [1, 1, 1, 1]
ipc_array = ['A', 'B', 'A', 'B']

source = ColumnDataSource(data = dict(
    x = x_row,
    y = y_col,
    color = colors_array,
    ipc_class = ipc_array
))

p = figure(plot_width = 800, plot_height = 800, title = "Ipc to Square with colors", match_aspect = True,
           tools = "wheel_zoom,reset,pan", background_fill_color = '#440154')
p.grid.visible = False
p.hex_tile('x', 'y', source = source, fill_color = 'color')

###################################
code = ''' 
for (i in cb_data.renderer.data_source.data['color'])
    cb_data.renderer.data_source.data['color'][i] = colors[i];

if (cb_data.index.indices != null) {
    hovered_index = cb_data.index.indices[0];
    hovered_ipc_class = cb_data.renderer.data_source.data['ipc_class'][hovered_index];
    for (i = 0; i < cb_data.renderer.data_source.data['ipc_class'].length; i++) {
        if (cb_data.renderer.data_source.data['ipc_class'][i] == hovered_ipc_class)
            cb_data.renderer.data_source.data['color'][i] = 'pink';
    }
}
cb_data.renderer.data_source.change.emit();
'''

TOOLTIPS = [
    ("index", "$index"),
    ("(x,y)", "(@x, @y)"),
    ("ipc_class", "@ipc_class")
]

callback = CustomJS(args = dict(ipc_array = ipc_array, colors = colors_array), code = code)
hover = HoverTool(tooltips = TOOLTIPS, callback = callback)
p.add_tools(hover)
########################################

output_file("hexbin.html")

show(p)

Результат:

enter image description here

1 голос
/ 02 мая 2019

Может быть, что-то вроде этого (Боке v1.1.0):

from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource, CustomJS, HoverTool

colors = ["green", "blue", "green", "blue"]
source = ColumnDataSource(dict(r = [0, 1, 2, 3], q = [1, 1, 1, 1], color = colors))
plot = figure(plot_width = 300, plot_height = 300, match_aspect = True)
plot.hex_tile('r', 'q', fill_color = 'color', source = source)

code = ''' 
for (i in cb_data.renderer.data_source.data['color'])
    cb_data.renderer.data_source.data['color'][i] = colors[i];

if (cb_data.index.indices != null) {
    hovered_index = cb_data.index.indices[0];
    hovered_color = cb_data.renderer.data_source.data['color'][hovered_index];
    for (i = 0; i < cb_data.renderer.data_source.data['color'].length; i++) {
        if (cb_data.renderer.data_source.data['color'][i] == hovered_color)
            cb_data.renderer.data_source.data['color'][i] = 'red';
    }
}
cb_data.renderer.data_source.change.emit();
'''
callback = CustomJS(args = dict(colors = colors), code = code)
hover = HoverTool(tooltips = [('R', '@r')], callback = callback)
plot.add_tools(hover)
show(plot)

Результат:

enter image description here

...