From b3b3327d6970524df7e345f5c2f39971b0a40f57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Tue, 15 Aug 2023 15:11:06 +0200 Subject: [PATCH 1/4] Improve support for NdOverlay and Overlay in downsample1d --- holoviews/operation/downsample.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/holoviews/operation/downsample.py b/holoviews/operation/downsample.py index aa6391d4e2..1f95a7d297 100644 --- a/holoviews/operation/downsample.py +++ b/holoviews/operation/downsample.py @@ -29,11 +29,13 @@ """ import math +from functools import partial import numpy as np import param from .resample import ResampleOperation1D +from ..core.overlay import NdOverlay, Overlay from ..element.chart import Area @@ -165,6 +167,16 @@ class downsample1d(ResampleOperation1D): algorithm = param.Selector(default='lttb', objects=['lttb', 'nth']) def _process(self, element, key=None): + if isinstance(element, (Overlay, NdOverlay)): + _process = partial(self._process, key=key) + _opts = element.opts.get().kwargs + if isinstance(element, Overlay): + elements = [v.map(_process) for v in element] + return Overlay(elements).opts(**_opts) + else: + elements = {k: v.map(_process) for k, v in element.items()} + return NdOverlay(elements).opts(**_opts) + if self.p.x_range: element = element[slice(*self.p.x_range)] if len(element) <= self.p.width: From 4d3bf19f8e607b6cd991e28b3ae9ebdd36f02e26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Tue, 15 Aug 2023 17:13:50 +0200 Subject: [PATCH 2/4] Add safe guard when hv.extension haven't run --- holoviews/operation/downsample.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/holoviews/operation/downsample.py b/holoviews/operation/downsample.py index 1f95a7d297..a62d5f3452 100644 --- a/holoviews/operation/downsample.py +++ b/holoviews/operation/downsample.py @@ -35,7 +35,7 @@ import param from .resample import ResampleOperation1D -from ..core.overlay import NdOverlay, Overlay +from ..core import NdOverlay, Overlay, Store from ..element.chart import Area @@ -169,7 +169,7 @@ class downsample1d(ResampleOperation1D): def _process(self, element, key=None): if isinstance(element, (Overlay, NdOverlay)): _process = partial(self._process, key=key) - _opts = element.opts.get().kwargs + _opts = element.opts.get().kwargs if Store._options else {} if isinstance(element, Overlay): elements = [v.map(_process) for v in element] return Overlay(elements).opts(**_opts) From 808f5d7083aa8518de069a688bb45db7a51b4474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Tue, 15 Aug 2023 17:16:22 +0200 Subject: [PATCH 3/4] Add unittest to downsample1d multi --- holoviews/tests/operation/test_downsample.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 holoviews/tests/operation/test_downsample.py diff --git a/holoviews/tests/operation/test_downsample.py b/holoviews/tests/operation/test_downsample.py new file mode 100644 index 0000000000..d82813b1d0 --- /dev/null +++ b/holoviews/tests/operation/test_downsample.py @@ -0,0 +1,20 @@ +import pytest + +import holoviews as hv +from holoviews.operation.downsample import downsample1d + + +@pytest.mark.parametrize("plottype", ["overlay", "ndoverlay"]) +def test_downsample1d_multi(plottype): + N = 1000 + assert N > downsample1d.width + + if plottype == "overlay": + figure = hv.Overlay([hv.Curve(range(N)), hv.Curve(range(N))]) + elif plottype == "ndoverlay": + figure = hv.NdOverlay({"A": hv.Curve(range(N)), "B": hv.Curve(range(N))}) + + figure_values = downsample1d(figure, dynamic=False).data.values() + for n in figure_values: + for value in n.data.values(): + assert value.size == downsample1d.width From 76a17bb41eca1bad05b4b84fed5561cf429f268e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Tue, 15 Aug 2023 21:52:41 +0200 Subject: [PATCH 4/4] Use clone --- holoviews/operation/downsample.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/holoviews/operation/downsample.py b/holoviews/operation/downsample.py index a62d5f3452..1ed44d5aa2 100644 --- a/holoviews/operation/downsample.py +++ b/holoviews/operation/downsample.py @@ -35,7 +35,7 @@ import param from .resample import ResampleOperation1D -from ..core import NdOverlay, Overlay, Store +from ..core import NdOverlay, Overlay from ..element.chart import Area @@ -169,13 +169,11 @@ class downsample1d(ResampleOperation1D): def _process(self, element, key=None): if isinstance(element, (Overlay, NdOverlay)): _process = partial(self._process, key=key) - _opts = element.opts.get().kwargs if Store._options else {} if isinstance(element, Overlay): elements = [v.map(_process) for v in element] - return Overlay(elements).opts(**_opts) else: elements = {k: v.map(_process) for k, v in element.items()} - return NdOverlay(elements).opts(**_opts) + return element.clone(elements) if self.p.x_range: element = element[slice(*self.p.x_range)]