Using github copilot I managed to come to this example code
import pandas as pd
import numpy as np
import holoviews as hv
from bokeh.models import HoverTool, CustomJS
x_vals = np.linspace(-10, 10, 100)
y_vals = np.linspace(-10, 10, 100)
X, Y = np.meshgrid(x_vals, y_vals)
Z = np.sin(np.sqrt(X**2 + Y**2))
gradient = np.gradient(Z)
category = np.where(Z > 0, 'Positive', 'Negative')
data = {'x':x_vals, 'y':y_vals, 'z':Z.T,
'gradient_x':gradient[0].T,
'gradient_y':gradient[1].T,
'category':category.T}
image = hv.Image((x_vals, y_vals, Z), vdims=['z'])
def add_hover_callback(plot, element):
bokeh_plot = plot.state
data_source = bokeh_plot.renderers[0].data_source
callback = CustomJS(args=dict(source=data_source, data=data), code="""
const x = cb_data.geometry.x;
const y = cb_data.geometry.y;
const xs = data.x;
const ys = data.y;
const zs = data.z;
const gradients_x = data.gradient_x;
const gradients_y = data.gradient_y;
const categories = data.category;
let closestXIndex = -1;
let closestYIndex = -1;
let minDistanceX = Infinity;
let minDistanceY = Infinity;
for (let i = 0; i < xs.length; i++) {
const dx = Math.abs(xs[i] - x);
if (dx < minDistanceX) {
minDistanceX = dx;
closestXIndex = i;
}
}
for (let j = 0; j < ys.length; j++) {
const dy = Math.abs(ys[i] - y);
if (dy < minDistanceY) {
minDistanceY = dy;
closestYIndex = j;
}
}
if (closestXIndex !== -1 && closestYIndex !== -1) {
source.data['x'] = [xs[closestXIndex]];
source.data['y'] = [ys[closestYIndex]];
source.data['image'] = [zs[closestXIndex][closestYIndex]]*100.0;
source.data['gradient_x'] = [gradients_x[closestXIndex][closestYIndex]];
source.data['gradient_y'] = [gradients_y[closestXIndex][closestYIndex]];
source.data['category'] = [categories[closestXIndex][closestYIndex]];
source.change.emit();
}
""")
hover = HoverTool(
tooltips=[
("X", "$x"),
("Y", "$y"),
("Z", "@image"),
("Gradient X", "@gradient_x"),
("Gradient Y", "@gradient_y"),
("Category", "@category")
],
callback=callback,
mode='mouse'
)
bokeh_plot.add_tools(hover)
image.opts(hooks=[add_hover_callback], tools=['hover'])
hv.output(image)
The problem is that the callback appear to not be working, since only the ā@imageā tag appears to be working with the original values and not with the modified ones (scaled by 100) and also the other categories only appears as ???.
Any help would be appreciated