Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Highlighting multiple hex_tiles by hovering in bokeh

Tags:

python

bokeh

I try to visualize my data in a hex map. For this I use python bokeh and the corresponding hex_tile function in the figure class. My data belongs to one of 8 different classes, each having a different color. The image below shows the current visualization:

Current Visualization I would like to add the possibility to change the color of the element (and ideally all its class members) when the mouse hovers over it.

I know, that it is somewhat possible, as bokeh themselves provide the following example: https://docs.bokeh.org/en/latest/docs/gallery/hexbin.html

However, I do not know how to implement this myself (as this seems to be a feature for the hexbin function and not the simple hex_tile function)

Currently I provide my data in a ColumnDataSource:

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

where "ipc_class" describes one of the 8 classes the element belongs to. For the mouse hover tooltip I used the following code:

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

and then I visualized everything with:

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')

I would like the visualization to add a function, where hovering over one element will result in one of the following: 1. Highlight the current element by changing its color 2. Highlight multiple elements of the same class when one is hovered over by changing its color 3. Change the color of the outer line of the hex_tile element (or complete class) when the element is hovered over

Which of these features is possible with bokeh and how would I go about it?

EDIT: After trying to reimplement the suggestion by Tony, all elements will turn pink as soon as my mouse hits the graph and the color won´t turn back. My code looks like this:

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)

basically, I removed the tooltips from the figure function and put them down to the hover tool. As I already have red in my graph, I replaced the hover color to "pink". As I am not quite sure what each line in the "code" variable is supposed to do, I am quite helpless with this. I think one mistake may be, that my ColumnDataSource looks somewhat different from Tony's and I do not know what was done to "classifiy" the first and third element, as well as the second and fourth element together. For me, it would be perfect, if the classification would be done by the "ipc_class" variable.

like image 559
Daniel Töws Avatar asked Oct 31 '25 12:10

Daniel Töws


1 Answers

Maybe something like this to start with (Bokeh 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)

Result:

enter image description here

like image 177
Tony Avatar answered Nov 02 '25 02:11

Tony



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!