Make bokeh's custom TapTool work for holoviews

282 views Asked by At

I would like to use bokeh's TapTool to open a different URL when clicking on each of some holoviews.Polygons. An perfect example of how this works in bokeh is in the bokeh docs for point data. However, when I try to use it in holoviews, it doesn't seem to work. The closest thing I could get to work is this:

import geoviews as gv
from bokeh.models import OpenURL, TapTool


url = 'https://google.@domain'
taptool = TapTool()
taptool.callback = OpenURL(url=url)
p = gv.Polygons(data, vdims=['Area', 'domain'], crs=ccrs.PlateCarree).options(alpha=1, tools=['hover', taptool])
p

The plot shows up nicely, and also the triggering of the URL opening works fine, however the parsing of the "@domain" doesn't work and the URL is "google.???" What is wrong here?

2

There are 2 answers

0
James A. Bednar On BEST ANSWER

Not sure; seems to work when I do it for this nonsensical example:

import holoviews as hv, numpy as np
hv.extension("bokeh")

def rectangle(x=0, y=0, width=.05, height=.05):
    return np.array([(x,y), (x+width, y), (x+width, y+height), (x, y+height)])

polys = hv.Polygons([{('x', 'y'): rectangle(x, y), 'level': z}
                     for x, y, z in np.random.rand(100, 3)], vdims='level')

url = 'https://google.@level'
taptool = TapTool()
taptool.callback = OpenURL(url=url)
polys.opts(color='level', line_width=1, tools=['hover', taptool])
1
danwild On

You can access the bokeh figure in holoviews using the hook option, described in the HoloViews docs here.

With access to the bokeh figure, you can then do things like wire up arbitrary callbacks. For example, access cursor coords in a python callback, or handle Tap events:

import holoviews as hv
from bokeh.events import MouseMove, Tap

def hook(plot, element):
  # allows access to the bokeh `figure` object
  # so we can bind figure interaction events
  plot.state.on_event(MouseMove, on_mouse_move)
  plot.state.on_event(Tap, on_click)   

  # The handles contain common plot objects
  # plot.handles

def on_mouse_move(event):
  # do something

def on_click(event):
   # do something

my_hv_plot = hv.Points([])
my_hv_plot.opts(hooks=[hook])