import numpy as np import pandas as pd from bokeh.models import Circle, ColumnDataSource, Range1d, HoverTool, CustomJS from bokeh.transform import factor_cmap from bokeh.plotting import figure, show, output_file output_file("hover_linked_samples.html") raw_array=np.random.rand(80,2) fields = ["I", "II", "III", "IV"] samples = np.arange(20) index = pd.MultiIndex.from_product([samples, fields], names=['ID', 'field']) data = pd.DataFrame(data=raw_array, columns=['x', 'y'], index=index) data.reset_index(inplace=True) data['alpha'] = 0.4 source = ColumnDataSource(data) xdr = Range1d(start=-0.05, end=1.05) ydr = Range1d(start=-0.05, end=1.05) s = figure(plot_width=500, plot_height=500, x_range=xdr, y_range=ydr, title="Hover over points", ) cr = s.scatter("x", "y", source=source, legend="field", fill_alpha='alpha', size=20, color=factor_cmap('field', 'Category10_5', fields)) # Add a hover tool, that highlights all fields from the hovered sample. code = """ var cdata = circle.data; var indices = cb_data.index['1d'].indices; for (var i = 0; i < cdata['ID'].length; i++){ cdata['alpha'][i] = 0.4; } for (var j = 0; j < indices.length; j++){ ind0=indices[j]; id = cdata['ID'][ind0]; for (var k = 0; k < cdata['ID'].length; k++){ if (id==cdata['ID'][k]){ cdata['alpha'][k] = 1; } } } circle.data = cdata; circle.change.emit(); """ callback = CustomJS(args={'circle': cr.data_source}, code=code) s.add_tools(HoverTool(tooltips=None, callback=callback, renderers=[cr])) show(s)