Setting DynamicMap as stream source

21 Views Asked by At

In the following MWE, clicking on a point of the scatter plot should show its index in the "debug" textbox. It does when the layout is scatter * dmap, it doesn’t when the layout is simply dmap. Indeed, scatter being the source of the Selection1D stream, its points are selected, not the points of the DynamicMap. Setting source=dmap doesn’t seem to help.

This is not satisfying because in my real use case I need the scatter plot to be updated after the first click (then a click on the second scatter plot to be registered), hence the DynamicMap.

How do I get rid of scatter in layout so that dmap is the actual source of events ?

import numpy as np
import holoviews as hv
import panel as pn

data = np.random.randn(100, 2)
scatter = hv.Scatter(
    data
).opts(
    tools = ["tap"]
)

debug = pn.widgets.TextInput(name="debug", value="")

def on_click(index):
    if index is None:
        return scatter
    debug.value = str(index)
    
    return scatter

stream = hv.streams.Selection1D(source=scatter)

dmap = hv.DynamicMap(on_click, streams=[stream])

#layout = scatter * dmap  # works
layout = dmap             # doesn’t work
pn.Column(
    debug,
    layout
)
1

There are 1 best solutions below

0
Skippy le Grand Gourou On

I found my way out discarding DynamicMap :

import numpy as np
import holoviews as hv
import panel as pn
hv.extension('bokeh')

data = np.random.randn(100, 2)
scatter = hv.Scatter(
    data
).opts(
    tools = ["tap"]
)

debug = pn.widgets.TextInput(name="debug", value="")

def on_click(index):
    debug.value = str(index)
    
stream = hv.streams.Selection1D(source=scatter)
stream.add_subscriber(on_click)
## alternative using SingleTap :
#stream = hv.streams.SingleTap(source=scatter)
#stream.add_subscriber(lambda x,y: on_click([x,y]))

pn.Column(
    debug,
    scatter
)

No need for DynamicMap for my "switch plots" use case either thanks to pn.bind :

import numpy as np
import holoviews as hv
import panel as pn
hv.extension('bokeh')

data = np.random.randn(100, 2)
data2 = np.random.randn(100, 2)

scatter_a = hv.Scatter(data).opts(
  tools = ["tap"],
  active_tools = ["tap"],
  size = 5,
  color = "green"
)
scatter_b = hv.Scatter(data2).opts(
  tools = ["tap"],
  active_tools = ["tap"],
  size = 5,
  color = "red"
)

current_plot = "A"
text_input = pn.widgets.TextInput(name='Current plot', value=current_plot)

def switch_graph(index):
    global current_plot
    return scatter_b if current_plot == "B" else scatter_a

def update_text(index):
    global current_plot
    current_plot = "B" if current_plot == "A" else "A"
    text_input.value = current_plot

tap_stream_a = hv.streams.Selection1D(source=scatter_a)
tap_stream_b = hv.streams.Selection1D(source=scatter_b)

tap_stream_a.add_subscriber(update_text)
tap_stream_b.add_subscriber(update_text)

pn.Column(
    text_input,
    pn.bind(switch_graph, text_input.param.value)
)