From 0e76dceae7f9254c5ba4c9979547cd436b6e3e3f Mon Sep 17 00:00:00 2001 From: Andrew Huang Date: Fri, 8 Sep 2023 17:05:38 -0700 Subject: [PATCH 1/6] WIP overlaying rasterized --- hvplot/converter.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/hvplot/converter.py b/hvplot/converter.py index 6eb4a7249..8dbb668cf 100644 --- a/hvplot/converter.py +++ b/hvplot/converter.py @@ -468,7 +468,10 @@ def __init__( # By type self.subplots = subplots - self._by_type = NdLayout if subplots else NdOverlay + if subplots: + self._by_type = NdLayout + else: + self._by_type = NdOverlay self._backend = Store.current_backend if hvplot_extension.compatibility is None: @@ -1330,11 +1333,12 @@ def method_wrapper(ds, x, y): opts['rescale_discrete_levels'] = self._plot_opts['rescale_discrete_levels'] else: operation = rasterize - eltype = 'Image' + eltype = 'ImageStack' if self.by else 'Image' if 'cmap' in self._style_opts: style['cmap'] = self._style_opts['cmap'] if self._dim_ranges.get('c', (None, None)) != (None, None): style['clim'] = self._dim_ranges['c'] + print(style) processed = operation(obj, **opts) @@ -1510,10 +1514,12 @@ def single_chart(self, element, x, y, data=None): cur_opts = { element.name: cur_el_opts, 'NdOverlay': filter_opts('NdOverlay', dict(self._overlay_opts, batched=False), backend='bokeh'), + 'ImageStack': filter_opts('ImageStack', dict(self._overlay_opts, batched=False), backend='bokeh'), } compat_opts = { element.name: compat_el_opts, 'NdOverlay': filter_opts('NdOverlay', dict(self._overlay_opts), backend=self._backend_compat), + 'ImageStack': filter_opts('ImageStack', dict(self._overlay_opts), backend=self._backend_compat), } ys = [y] @@ -1537,6 +1543,7 @@ def single_chart(self, element, x, y, data=None): chart = Dataset(data, self.by+kdims, vdims).to( element, kdims, vdims, self.by).relabel(**self._relabel) chart = chart.layout() if self.subplots else chart.overlay(sort=False) + print(type(chart), "PROBLEM ABOVE ^^^") else: chart = element(data, kdims, vdims).relabel(**self._relabel) return (chart.redim(**self._redim) From 4fd67e527702db85b2f8da8e12afef28c59f20b8 Mon Sep 17 00:00:00 2001 From: Andrew Huang Date: Fri, 8 Sep 2023 18:10:57 -0700 Subject: [PATCH 2/6] Clean up --- hvplot/converter.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/hvplot/converter.py b/hvplot/converter.py index 8dbb668cf..35d6a0faf 100644 --- a/hvplot/converter.py +++ b/hvplot/converter.py @@ -468,10 +468,7 @@ def __init__( # By type self.subplots = subplots - if subplots: - self._by_type = NdLayout - else: - self._by_type = NdOverlay + self._by_type = NdLayout if subplots else NdOverlay self._backend = Store.current_backend if hvplot_extension.compatibility is None: @@ -1338,7 +1335,6 @@ def method_wrapper(ds, x, y): style['cmap'] = self._style_opts['cmap'] if self._dim_ranges.get('c', (None, None)) != (None, None): style['clim'] = self._dim_ranges['c'] - print(style) processed = operation(obj, **opts) @@ -1514,12 +1510,10 @@ def single_chart(self, element, x, y, data=None): cur_opts = { element.name: cur_el_opts, 'NdOverlay': filter_opts('NdOverlay', dict(self._overlay_opts, batched=False), backend='bokeh'), - 'ImageStack': filter_opts('ImageStack', dict(self._overlay_opts, batched=False), backend='bokeh'), } compat_opts = { element.name: compat_el_opts, 'NdOverlay': filter_opts('NdOverlay', dict(self._overlay_opts), backend=self._backend_compat), - 'ImageStack': filter_opts('ImageStack', dict(self._overlay_opts), backend=self._backend_compat), } ys = [y] @@ -1543,7 +1537,6 @@ def single_chart(self, element, x, y, data=None): chart = Dataset(data, self.by+kdims, vdims).to( element, kdims, vdims, self.by).relabel(**self._relabel) chart = chart.layout() if self.subplots else chart.overlay(sort=False) - print(type(chart), "PROBLEM ABOVE ^^^") else: chart = element(data, kdims, vdims).relabel(**self._relabel) return (chart.redim(**self._redim) From 9fd8db35b63c30e13438282febeac4dfe0022c2a Mon Sep 17 00:00:00 2001 From: Andrew Huang Date: Wed, 13 Sep 2023 12:48:06 -0700 Subject: [PATCH 3/6] Add rasterize to check for categorical --- hvplot/converter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hvplot/converter.py b/hvplot/converter.py index 35d6a0faf..e79f09906 100644 --- a/hvplot/converter.py +++ b/hvplot/converter.py @@ -582,7 +582,7 @@ def __init__( symmetric = self._process_symmetric(symmetric, clim, check_symmetric_max) if self._style_opts.get('cmap') is None: # Default to categorical camp if we detect categorical shading - if (self.datashade and (self.aggregator is None or 'count_cat' in str(self.aggregator)) and + if ((self.datashade or self.rasterize) and (self.aggregator is None or 'count_cat' in str(self.aggregator)) and ((self.by and not self.subplots) or (isinstance(self.y, list) or (self.y is None and len(set(self.variables) - set(self.indexes)) > 1)))): self._style_opts['cmap'] = self._default_cmaps['categorical'] From 12cc2b829a8f79a4952989a7b7efcb0447242400 Mon Sep 17 00:00:00 2001 From: Andrew Huang Date: Wed, 13 Sep 2023 14:37:04 -0700 Subject: [PATCH 4/6] Add test --- hvplot/tests/testoperations.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/hvplot/tests/testoperations.py b/hvplot/tests/testoperations.py index c2abd4cde..f3f303e04 100644 --- a/hvplot/tests/testoperations.py +++ b/hvplot/tests/testoperations.py @@ -3,12 +3,13 @@ from unittest import SkipTest from parameterized import parameterized +import colorcet as cc import hvplot.pandas # noqa import numpy as np import pandas as pd from holoviews import Store -from holoviews.element import Image, QuadMesh +from holoviews.element import Image, QuadMesh, ImageStack from holoviews.element.comparison import ComparisonTestCase from hvplot.converter import HoloViewsConverter @@ -194,6 +195,11 @@ def test_datashade_rescale_discrete_levels_default_True(self): actual = plot.callback.inputs[0].callback.operation.p['rescale_discrete_levels'] assert actual is expected + def test_rasterize_by(self): + expected = 'category' + plot = self.df.hvplot(x='x', y='y', by=expected, rasterize=True, dynamic=False) + assert isinstance(plot, ImageStack) + assert plot.opts["cmap"] == cc.palette['glasbey_category10'] class TestChart2D(ComparisonTestCase): From c1015466144e69cdeaf9c340fcfb964491db0f69 Mon Sep 17 00:00:00 2001 From: Andrew Huang Date: Mon, 18 Sep 2023 11:09:39 -0700 Subject: [PATCH 5/6] Add version check --- hvplot/converter.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hvplot/converter.py b/hvplot/converter.py index e79f09906..73173c5db 100644 --- a/hvplot/converter.py +++ b/hvplot/converter.py @@ -1330,7 +1330,10 @@ def method_wrapper(ds, x, y): opts['rescale_discrete_levels'] = self._plot_opts['rescale_discrete_levels'] else: operation = rasterize - eltype = 'ImageStack' if self.by else 'Image' + if hv.__version__ < '1.18.0': + eltype = 'Image' + else: + eltype = 'ImageStack' if self.by else 'Image' if 'cmap' in self._style_opts: style['cmap'] = self._style_opts['cmap'] if self._dim_ranges.get('c', (None, None)) != (None, None): From c892111448918da3d9c92f5931dd57e1b9d477d3 Mon Sep 17 00:00:00 2001 From: Andrew <15331990+ahuang11@users.noreply.github.com> Date: Tue, 19 Sep 2023 07:42:31 -0700 Subject: [PATCH 6/6] Update hvplot/converter.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Simon Høxbro Hansen --- hvplot/converter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hvplot/converter.py b/hvplot/converter.py index 73173c5db..f17e81f56 100644 --- a/hvplot/converter.py +++ b/hvplot/converter.py @@ -1330,7 +1330,7 @@ def method_wrapper(ds, x, y): opts['rescale_discrete_levels'] = self._plot_opts['rescale_discrete_levels'] else: operation = rasterize - if hv.__version__ < '1.18.0': + if Version(hv.__version__) < Version('1.18.0a1'): eltype = 'Image' else: eltype = 'ImageStack' if self.by else 'Image'