From 907dbbab47d47acb0dbe91dbacb40504a7a31d9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Sun, 18 Jun 2023 15:17:56 +0200 Subject: [PATCH 1/5] Only merge non_default_params --- holoviews/core/data/util.py | 14 ++++++++++++++ holoviews/operation/datashader.py | 7 ++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/holoviews/core/data/util.py b/holoviews/core/data/util.py index ce7c303f69..03fbf80c05 100644 --- a/holoviews/core/data/util.py +++ b/holoviews/core/data/util.py @@ -67,3 +67,17 @@ def cached(*args, **kwargs): args = (cache,)+args[2:] return getattr(cache.interface, method.__name__)(*args, **kwargs) return cached + + +def compare(value1, value2): + """Compare two values, returning a boolean. + + Will apply the comparison to all elements of an array/dataframe. + """ + try: + check = value1 == value2 + if not isinstance(check, bool) and hasattr(check, "all"): + check = check.all() + return bool(check) + except Exception: + return False diff --git a/holoviews/operation/datashader.py b/holoviews/operation/datashader.py index 15f2d04948..35241380c5 100644 --- a/holoviews/operation/datashader.py +++ b/holoviews/operation/datashader.py @@ -29,6 +29,7 @@ from ..core.data import ( Dataset, PandasInterface, XArrayInterface, DaskInterface, cuDFInterface ) +from ..core.data.util import compare from ..core.util import ( cast_array_to_int64, cftime_types, cftime_to_timestamp, datetime_types, dt_to_int, get_param_values @@ -1378,8 +1379,12 @@ def _process(self, element, key=None): # Potentially needs traverse to find element types first? all_allowed_kws = set() all_supplied_kws = set() + non_default_params = { + k: v for k, v in self.param.values().items() + if not compare(v, self.param[k].default) + } for predicate, transform in self._transforms: - merged_param_values = dict(self.param.values(), **self.p) + merged_param_values = dict(non_default_params, **self.p) # If aggregator or interpolation are 'default', pop parameter so # datashader can choose the default aggregator itself From 32b3f330409723ab2da12a4a69f912fb0fc99e52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Sun, 18 Jun 2023 20:58:55 +0200 Subject: [PATCH 2/5] Change compare to isequal --- holoviews/core/data/util.py | 14 -------------- holoviews/core/util.py | 14 ++++++++++++++ holoviews/operation/datashader.py | 5 ++--- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/holoviews/core/data/util.py b/holoviews/core/data/util.py index 03fbf80c05..ce7c303f69 100644 --- a/holoviews/core/data/util.py +++ b/holoviews/core/data/util.py @@ -67,17 +67,3 @@ def cached(*args, **kwargs): args = (cache,)+args[2:] return getattr(cache.interface, method.__name__)(*args, **kwargs) return cached - - -def compare(value1, value2): - """Compare two values, returning a boolean. - - Will apply the comparison to all elements of an array/dataframe. - """ - try: - check = value1 == value2 - if not isinstance(check, bool) and hasattr(check, "all"): - check = check.all() - return bool(check) - except Exception: - return False diff --git a/holoviews/core/util.py b/holoviews/core/util.py index 3c6c849371..bd10ecac9e 100644 --- a/holoviews/core/util.py +++ b/holoviews/core/util.py @@ -803,6 +803,20 @@ def isnumeric(val): return False +def isequal(value1, value2): + """Compare two values, returning a boolean. + + Will apply the comparison to all elements of an array/dataframe. + """ + try: + check = value1 == value2 + if not isinstance(check, bool) and hasattr(check, "all"): + check = check.all() + return bool(check) + except Exception: + return False + + def asarray(arraylike, strict=True): """ Converts arraylike objects to NumPy ndarray types. Errors if diff --git a/holoviews/operation/datashader.py b/holoviews/operation/datashader.py index 35241380c5..e78c544be6 100644 --- a/holoviews/operation/datashader.py +++ b/holoviews/operation/datashader.py @@ -29,10 +29,9 @@ from ..core.data import ( Dataset, PandasInterface, XArrayInterface, DaskInterface, cuDFInterface ) -from ..core.data.util import compare from ..core.util import ( cast_array_to_int64, cftime_types, cftime_to_timestamp, - datetime_types, dt_to_int, get_param_values + datetime_types, dt_to_int, get_param_values, isequal ) from ..element import (Image, Path, Curve, RGB, Graph, TriMesh, QuadMesh, Contours, Spikes, Area, Rectangles, @@ -1381,7 +1380,7 @@ def _process(self, element, key=None): all_supplied_kws = set() non_default_params = { k: v for k, v in self.param.values().items() - if not compare(v, self.param[k].default) + if not isequal(v, self.param[k].default) } for predicate, transform in self._transforms: merged_param_values = dict(non_default_params, **self.p) From d63d77526f91f90d0c081b862b0c75f8bd41d2dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Mon, 19 Jun 2023 12:20:24 +0200 Subject: [PATCH 3/5] Add unittest --- holoviews/tests/operation/test_datashader.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/holoviews/tests/operation/test_datashader.py b/holoviews/tests/operation/test_datashader.py index 623b36fa41..795c6f8035 100644 --- a/holoviews/tests/operation/test_datashader.py +++ b/holoviews/tests/operation/test_datashader.py @@ -1150,6 +1150,24 @@ def test_rasterize_image_string_aggregator(self): expected = Image(([2., 7.], [0.75, 3.25], [[1, 5], [6, 22]])) self.assertEqual(regridded, expected) + def test_rasterize_image_expand_default(self): + # Should use expand=False by default + assert not regrid.expand + + data = np.arange(100.0).reshape(10, 10) + c = np.arange(10.0) + da = xr.DataArray(data, coords=dict(x=c, y=c)) + rast_input = dict(x_range=(-1, 10), y_range=(-1, 10), precompute=True, dynamic=False) + img = rasterize(Image(da), **rast_input) + output = img.data["z"].to_numpy() + + np.testing.assert_array_equal(output, data.T) + assert not np.isnan(output).any() + + # Setting expand=True with the {x,y}_ranges will expand the data with nan's + img = rasterize(Image(da), expand=True, **rast_input) + output = img.data["z"].to_numpy() + assert np.isnan(output).any() class DatashaderSpreadTests(ComparisonTestCase): From 046c2e0e63445f922f68b36ac025707be2318c4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Mon, 19 Jun 2023 13:58:35 +0200 Subject: [PATCH 4/5] Only pass in instance params --- holoviews/operation/datashader.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/holoviews/operation/datashader.py b/holoviews/operation/datashader.py index e78c544be6..ecd381bf10 100644 --- a/holoviews/operation/datashader.py +++ b/holoviews/operation/datashader.py @@ -31,7 +31,7 @@ ) from ..core.util import ( cast_array_to_int64, cftime_types, cftime_to_timestamp, - datetime_types, dt_to_int, get_param_values, isequal + datetime_types, dt_to_int, get_param_values ) from ..element import (Image, Path, Curve, RGB, Graph, TriMesh, QuadMesh, Contours, Spikes, Area, Rectangles, @@ -1374,16 +1374,23 @@ class rasterize(AggregationOperation): (type(None), shade) # To handle parameters of datashade ] + __instance_params = set() + + @bothmethod + def instance(self_or_cls, **params): + inst = super().instance(**params) + inst.__instance_params = set(params) + return inst + def _process(self, element, key=None): # Potentially needs traverse to find element types first? all_allowed_kws = set() all_supplied_kws = set() - non_default_params = { - k: v for k, v in self.param.values().items() - if not isequal(v, self.param[k].default) + instance_params = { + k: getattr(self, k) for k in self.__instance_params } for predicate, transform in self._transforms: - merged_param_values = dict(non_default_params, **self.p) + merged_param_values = dict(instance_params, **self.p) # If aggregator or interpolation are 'default', pop parameter so # datashader can choose the default aggregator itself From 597cef1ef797dc40857c88ead3bf33323175dd1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Mon, 19 Jun 2023 19:05:32 +0200 Subject: [PATCH 5/5] Update holoviews/core/util.py Co-authored-by: Philipp Rudiger --- holoviews/core/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/holoviews/core/util.py b/holoviews/core/util.py index bd10ecac9e..c5df536e56 100644 --- a/holoviews/core/util.py +++ b/holoviews/core/util.py @@ -809,7 +809,7 @@ def isequal(value1, value2): Will apply the comparison to all elements of an array/dataframe. """ try: - check = value1 == value2 + check = (value1 is value2) or (value1 == value2) if not isinstance(check, bool) and hasattr(check, "all"): check = check.all() return bool(check)