Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix linking elements that are transformed by a Compositor #6003

Merged
merged 9 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions holoviews/plotting/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -1129,6 +1129,8 @@ def hex2rgb(hex):

class apply_nodata(Operation):

link_inputs = param.Boolean(default=True)
hoxbro marked this conversation as resolved.
Show resolved Hide resolved

nodata = param.Integer(default=None, doc="""
Optional missing-data value for integer data.
If non-None, data with this value will be replaced with NaN so
Expand Down
39 changes: 34 additions & 5 deletions holoviews/tests/plotting/bokeh/test_links.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import numpy as np
import pytest
from bokeh.models import ColumnDataSource
from bokeh.models import ColumnDataSource, RangeTool

from holoviews.core.spaces import DynamicMap
from holoviews.element import Curve, Image, Path, Points, Polygons, Scatter, Table
Expand All @@ -12,7 +12,6 @@
class TestLinkCallbacks(TestBokehPlot):

def test_range_tool_link_callback_single_axis(self):
from bokeh.models import RangeTool
array = np.random.rand(100, 2)
src = Curve(array)
target = Scatter(array)
Expand All @@ -26,7 +25,6 @@ def test_range_tool_link_callback_single_axis(self):
self.assertIs(range_tool.y_range, None)

def test_range_tool_link_callback_single_axis_overlay_target(self):
from bokeh.models import RangeTool
array = np.random.rand(100, 2)
src = Curve(array)
target = Scatter(array, label='a') * Scatter(array, label='b')
Expand All @@ -40,7 +38,6 @@ def test_range_tool_link_callback_single_axis_overlay_target(self):
self.assertIs(range_tool.y_range, None)

def test_range_tool_link_callback_single_axis_overlay_target_image_source(self):
from bokeh.models import RangeTool
data = np.random.rand(50, 50)
target = Curve(data) * Curve(data)
source = Image(np.random.rand(50, 50), bounds=(0, 0, 1, 1))
Expand All @@ -53,8 +50,40 @@ def test_range_tool_link_callback_single_axis_overlay_target_image_source(self):
self.assertEqual(range_tool.x_range, tgt_plot.handles['x_range'])
self.assertIs(range_tool.y_range, None)

def test_range_tool_link_callback_single_axis_curve_target_image_dmap_source(self):
# Choosing Image to exert the apply_nodata compositor
src = DynamicMap(
lambda a: Image(a*np.random.random((20, 20)), bounds=[0, 0, 9, 9]),
kdims=['a']
).redim.range(a=(0.1,1))
target = Curve(np.arange(10))
RangeToolLink(src, target)
layout = target + src
plot = bokeh_renderer.get_plot(layout)
tgt_plot = plot.subplots[(0, 0)].subplots['main']
src_plot = plot.subplots[(0, 1)].subplots['main']
range_tool = src_plot.state.select_one({'type': RangeTool})
assert range_tool.x_range == tgt_plot.handles['x_range']
assert range_tool.y_range is None

def test_range_tool_link_callback_single_axis_overlay_target_image_dmap_source(self):
# Choosing Image to exert the apply_nodata compositor
src = DynamicMap(
lambda a: Image(a*np.random.random((20, 20)), bounds=[0, 0, 9, 9]),
kdims=['a']
).redim.range(a=(0.1,1))
data = np.random.rand(50, 50)
target = Curve(data) * Curve(data)
RangeToolLink(src, target)
layout = target + src
plot = bokeh_renderer.get_plot(layout)
tgt_plot = plot.subplots[(0, 0)].subplots['main']
src_plot = plot.subplots[(0, 1)].subplots['main']
range_tool = src_plot.state.select_one({'type': RangeTool})
assert range_tool.x_range == tgt_plot.handles['x_range']
assert range_tool.y_range is None

def test_range_tool_link_callback_both_axes(self):
from bokeh.models import RangeTool
array = np.random.rand(100, 2)
src = Curve(array)
target = Scatter(array)
Expand Down
10 changes: 7 additions & 3 deletions holoviews/util/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -872,7 +872,7 @@ class Dynamic(param.ParameterizedFunction):

link_inputs = param.Boolean(default=True, doc="""
If Dynamic is applied to another DynamicMap, determines whether
linked streams attached to its Callable inputs are
linked streams and links attached to its Callable inputs are
transferred to the output of the utility.

For example if the Dynamic utility is applied to a DynamicMap
Expand Down Expand Up @@ -900,8 +900,12 @@ def __call__(self, map_obj, **params):
callback = self._dynamic_operation(map_obj)
streams = self._get_streams(map_obj, watch)
if isinstance(map_obj, DynamicMap):
dmap = map_obj.clone(callback=callback, shared_data=self.p.shared_data,
streams=streams)
kwargs = dict(
shared_data=self.p.shared_data, callback=callback, streams=streams
)
if self.p.link_inputs:
kwargs['plot_id'] = map_obj._plot_id
dmap = map_obj.clone(**kwargs)
if self.p.shared_data:
dmap.data = dict([(k, callback.callable(*k))
for k, v in dmap.data])
Expand Down