From 50e51cd68dae6d7632aacdc0ad5bc28e55b2dc15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Tue, 5 Dec 2023 13:43:33 +0100 Subject: [PATCH 01/66] Add extra check to detect if we are in jupyterlite (#6007) --- holoviews/pyodide.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/holoviews/pyodide.py b/holoviews/pyodide.py index dfb1b7b56b..493f0c19ee 100644 --- a/holoviews/pyodide.py +++ b/holoviews/pyodide.py @@ -77,7 +77,7 @@ def render_svg(element): def in_jupyterlite(): import js - return hasattr(js, "_JUPYTERLAB") + return hasattr(js, "_JUPYTERLAB") or hasattr(js, "webpackChunk_jupyterlite_pyodide_kernel_extension") or not hasattr(js, "document") #----------------------------------------------------------------------------- # Public API From 91f841ed15766fa67f9c3ebfe6746e0b4bb5a90a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Wed, 6 Dec 2023 15:09:22 +0100 Subject: [PATCH 02/66] Support partial bound function (#6009) --- holoviews/core/spaces.py | 7 +++++-- holoviews/tests/test_streams.py | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/holoviews/core/spaces.py b/holoviews/core/spaces.py index 6653bdc86b..ae99700b82 100644 --- a/holoviews/core/spaces.py +++ b/holoviews/core/spaces.py @@ -1,7 +1,7 @@ import itertools import types from collections import defaultdict -from contextlib import contextmanager +from contextlib import contextmanager, suppress from functools import partial from itertools import groupby from numbers import Number @@ -547,7 +547,10 @@ def __call__(self, *args, **kwargs): kwarg_hash = kwargs.pop('_memoization_hash_', ()) (self.args, self.kwargs) = (args, kwargs) if hasattr(self.callable, 'rx'): - return self.callable.rx.value + with suppress(TypeError): + # If param.bind is used and not all arguments are set + # it will raise TypeError + return self.callable.rx.value if not args and not kwargs and not any(kwarg_hash): return self.callable() inputs = [i for i in self.inputs if isinstance(i, DynamicMap)] streams = [] diff --git a/holoviews/tests/test_streams.py b/holoviews/tests/test_streams.py index 5870d03f1b..17cb93bc30 100644 --- a/holoviews/tests/test_streams.py +++ b/holoviews/tests/test_streams.py @@ -6,8 +6,10 @@ import pandas as pd import param +import pytest from panel.widgets import IntSlider +import holoviews as hv from holoviews.core.spaces import DynamicMap from holoviews.core.util import Version from holoviews.element import Curve, Histogram, Points, Polygons, Scatter @@ -595,6 +597,24 @@ def subscriber_y(**kwargs): self.assertEqual(values_y, [{}]) +@pytest.mark.usefixtures("bokeh_backend") +def test_dynamicmap_partial_bind_and_streams(): + # Ref: https://github.com/holoviz/holoviews/issues/6008 + + def make_plot(z, x_range, y_range): + return Curve([1, 2, 3, 4, z]) + + slider = IntSlider(name='Slider', start=0, end=10) + range_xy = RangeXY() + + dmap = DynamicMap(param.bind(make_plot, z=slider), streams=[range_xy]) + + bk_figure = hv.render(dmap) + + assert bk_figure.renderers[0].data_source.data["y"][-1] == 0 + assert range_xy.x_range == (0, 4) + assert range_xy.y_range == (-0.4, 4.4) + class TestSubscribers(ComparisonTestCase): From 5594e7456da7ff0f8ce99da918927cc9d921b135 Mon Sep 17 00:00:00 2001 From: Seth Russell Date: Mon, 11 Dec 2023 05:59:31 -0700 Subject: [PATCH 03/66] Fixing URLs to bokeh project (#6005) --- examples/gallery/demos/bokeh/legend_example.ipynb | 2 +- examples/gallery/demos/matplotlib/legend_example.ipynb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/gallery/demos/bokeh/legend_example.ipynb b/examples/gallery/demos/bokeh/legend_example.ipynb index 4366be9300..eb1f508f07 100644 --- a/examples/gallery/demos/bokeh/legend_example.ipynb +++ b/examples/gallery/demos/bokeh/legend_example.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/legend.html\n", + "URL: https://docs.bokeh.org/en/latest/docs/examples/basic/annotations/legend.html\n", "\n", "Most examples work across multiple plotting backends, this example is also available for:\n", "\n", diff --git a/examples/gallery/demos/matplotlib/legend_example.ipynb b/examples/gallery/demos/matplotlib/legend_example.ipynb index d24be65353..df3e7b3e99 100644 --- a/examples/gallery/demos/matplotlib/legend_example.ipynb +++ b/examples/gallery/demos/matplotlib/legend_example.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/legend.html\n", + "URL: https://docs.bokeh.org/en/latest/docs/examples/basic/annotations/legend.html\n", "\n", "Most examples work across multiple plotting backends, this example is also available for:\n", "\n", From 291300596bc84bd9c380d1741ecd186408e88497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Mon, 11 Dec 2023 14:31:32 +0100 Subject: [PATCH 04/66] Compability updates with xarray 2023.12 (#6026) --- holoviews/core/data/xarray.py | 12 +++++++++--- holoviews/tests/core/data/test_xarrayinterface.py | 12 ++++++++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/holoviews/core/data/xarray.py b/holoviews/core/data/xarray.py index 18259f3359..823053e590 100644 --- a/holoviews/core/data/xarray.py +++ b/holoviews/core/data/xarray.py @@ -178,12 +178,18 @@ def retrieve_unit_and_label(dim): arrays[vdim.name] = arr data = xr.Dataset(arrays) else: + # Started to warn in xarray 2023.12.0: + # The return type of `Dataset.dims` will be changed to return a + # set of dimension names in future, in order to be more consistent + # with `DataArray.dims`. To access a mapping from dimension names to + # lengths, please use `Dataset.sizes`. + data_info = data.sizes if hasattr(data, "sizes") else data.dims if not data.coords: - data = data.assign_coords(**{k: range(v) for k, v in data.dims.items()}) + data = data.assign_coords(**{k: range(v) for k, v in data_info.items()}) if vdims is None: vdims = list(data.data_vars) if kdims is None: - xrdims = list(data.dims) + xrdims = list(data_info) xrcoords = list(data.coords) kdims = [name for name in data.indexes.keys() if isinstance(data[name].data, np.ndarray)] @@ -636,7 +642,7 @@ def length(cls, dataset): def dframe(cls, dataset, dimensions): import xarray as xr if cls.packed(dataset): - bands = {vd.name: dataset.data[..., i].drop('band') + bands = {vd.name: dataset.data[..., i].drop_vars('band') for i, vd in enumerate(dataset.vdims)} data = xr.Dataset(bands) else: diff --git a/holoviews/tests/core/data/test_xarrayinterface.py b/holoviews/tests/core/data/test_xarrayinterface.py index b30013da4c..fb67f917ac 100644 --- a/holoviews/tests/core/data/test_xarrayinterface.py +++ b/holoviews/tests/core/data/test_xarrayinterface.py @@ -249,8 +249,16 @@ def test_select_dropped_dimensions_restoration(self): coords=dict(chain=range(d.shape[0]), value=range(d.shape[1]))) ds = Dataset(da) t = ds.select(chain=0) - self.assertEqual(t.data.dims , dict(chain=1,value=8)) - self.assertEqual(t.data.stuff.shape , (1,8)) + if hasattr(t.data, "sizes"): + # Started to warn in xarray 2023.12.0: + # The return type of `Dataset.dims` will be changed to return a + # set of dimension names in future, in order to be more consistent + # with `DataArray.dims`. To access a mapping from dimension names to + # lengths, please use `Dataset.sizes`. + assert t.data.sizes == dict(chain=1, value=8) + else: + assert t.data.dims == dict(chain=1, value=8) + assert t.data.stuff.shape == (1, 8) def test_mask_2d_array_transposed(self): array = np.random.rand(4, 3) From 5308bb5acf340f731a1901cf158934835041f423 Mon Sep 17 00:00:00 2001 From: Julian Alberto Giles <87534521+JulianGiles@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:40:04 +0100 Subject: [PATCH 05/66] Add 'norm' in init_artists in holoviews/plotting/mpl/raster.py (#6029) --- holoviews/plotting/mpl/element.py | 4 ++-- holoviews/plotting/mpl/raster.py | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/holoviews/plotting/mpl/element.py b/holoviews/plotting/mpl/element.py index f370dc8d97..7f797ff47e 100644 --- a/holoviews/plotting/mpl/element.py +++ b/holoviews/plotting/mpl/element.py @@ -592,8 +592,8 @@ def init_artists(self, ax, plot_args, plot_kwargs): plot_method = self._plot_methods.get('batched' if self.batched else 'single') plot_fn = getattr(ax, plot_method) if 'norm' in plot_kwargs: # vmin/vmax should now be exclusively in norm - plot_kwargs.pop('vmin', None) - plot_kwargs.pop('vmax', None) + plot_kwargs.pop('vmin', None) + plot_kwargs.pop('vmax', None) with warnings.catch_warnings(): # scatter have a default cmap and with an empty array will emit this warning warnings.filterwarnings('ignore', "No data for colormapping provided via 'c'") diff --git a/holoviews/plotting/mpl/raster.py b/holoviews/plotting/mpl/raster.py index 23b752f09a..890d41d7f5 100644 --- a/holoviews/plotting/mpl/raster.py +++ b/holoviews/plotting/mpl/raster.py @@ -190,6 +190,9 @@ def init_artists(self, ax, plot_args, plot_kwargs): locs = plot_kwargs.pop('locs', None) artist = ax.pcolormesh(*plot_args, **plot_kwargs) colorbar = self.handles.get('cbar') + if 'norm' in plot_kwargs: # vmin/vmax should now be exclusively in norm + plot_kwargs.pop('vmin', None) + plot_kwargs.pop('vmax', None) if colorbar and mpl_version < Version('3.1'): colorbar.set_norm(artist.norm) if hasattr(colorbar, 'set_array'): From e23c3e97bef29d77e9bb6751caf72a1928e60d5f Mon Sep 17 00:00:00 2001 From: Maxime Liquet <35924738+maximlt@users.noreply.github.com> Date: Tue, 12 Dec 2023 17:33:12 +0100 Subject: [PATCH 06/66] Fix linking elements that are transformed by a Compositor (#6003) --- holoviews/plotting/util.py | 2 + holoviews/tests/plotting/bokeh/test_links.py | 39 +++++++++++++++++--- holoviews/util/__init__.py | 10 +++-- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/holoviews/plotting/util.py b/holoviews/plotting/util.py index d9157deca5..d03e9bbe2f 100644 --- a/holoviews/plotting/util.py +++ b/holoviews/plotting/util.py @@ -1129,6 +1129,8 @@ def hex2rgb(hex): class apply_nodata(Operation): + link_inputs = param.Boolean(default=True) + 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 diff --git a/holoviews/tests/plotting/bokeh/test_links.py b/holoviews/tests/plotting/bokeh/test_links.py index cb6efa25ef..ed11ac9a46 100644 --- a/holoviews/tests/plotting/bokeh/test_links.py +++ b/holoviews/tests/plotting/bokeh/test_links.py @@ -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 @@ -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) @@ -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') @@ -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)) @@ -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) diff --git a/holoviews/util/__init__.py b/holoviews/util/__init__.py index 962496927c..34d384e32c 100644 --- a/holoviews/util/__init__.py +++ b/holoviews/util/__init__.py @@ -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 @@ -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]) From 5c76ee00c0047d79dbc0f4a23308c35b15409af8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Thu, 14 Dec 2023 17:32:02 +0100 Subject: [PATCH 07/66] Add lower pin to scipy (#6032) --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index d951f6a232..9d11ef4b6b 100644 --- a/setup.py +++ b/setup.py @@ -52,7 +52,7 @@ 'shapely', 'ffmpeg', 'cftime', - 'scipy', + 'scipy >=1.10', # Python 3.9 + Windows downloads 1.9 'selenium', 'spatialpandas', 'datashader >=0.11.1', From b8dd3d081bca9d08636c0414b052f8f6d77a08fd Mon Sep 17 00:00:00 2001 From: Demetris Roumis Date: Thu, 14 Dec 2023 10:32:47 -0600 Subject: [PATCH 08/66] Override Curve's count aggregator default to `self_intersect=False` (#6030) --- holoviews/operation/datashader.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/holoviews/operation/datashader.py b/holoviews/operation/datashader.py index 441a6d144f..772deb9f7c 100644 --- a/holoviews/operation/datashader.py +++ b/holoviews/operation/datashader.py @@ -444,6 +444,18 @@ def _apply_datashader(self, dfdata, cvs_fn, agg_fn, agg_kwargs, x, y): agg[col] = ((y.name, x.name), val) return agg +class curve_aggregate(aggregate): + """ + Optimized aggregation for Curve objects by setting the default + of the aggregator to self_intersect=False to be more consistent + with the appearance of non-aggregated curves. + """ + aggregator = param.ClassSelector(class_=(rd.Reduction, rd.summary, str), + default=rd.count(self_intersect=False), doc=""" + Datashader reduction function used for aggregating the data. + The aggregator may also define a column to aggregate; if + no column is defined the first value dimension of the element + will be used. May also be defined as a string.""") class overlay_aggregate(aggregate): """ @@ -1457,7 +1469,7 @@ class rasterize(AggregationOperation): (Graph, aggregate), (Scatter, aggregate), (Points, aggregate), - (Curve, aggregate), + (Curve, curve_aggregate), (Path, aggregate), (type(None), shade) # To handle parameters of datashade ] From 41f768f03ed6dcc4ccfebe0e6cd8147824b9a611 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Fri, 15 Dec 2023 14:09:11 +0100 Subject: [PATCH 09/66] Add datetime hover information for selector (#6023) --- holoviews/operation/datashader.py | 2 ++ holoviews/plotting/bokeh/element.py | 7 ++++--- holoviews/plotting/bokeh/raster.py | 18 +++++++++++++--- holoviews/tests/operation/test_datashader.py | 15 +++++++++++++ .../tests/plotting/bokeh/test_rasterplot.py | 21 +++++++++++++++++++ 5 files changed, 57 insertions(+), 6 deletions(-) diff --git a/holoviews/operation/datashader.py b/holoviews/operation/datashader.py index 772deb9f7c..08f2688661 100644 --- a/holoviews/operation/datashader.py +++ b/holoviews/operation/datashader.py @@ -438,6 +438,8 @@ def _apply_datashader(self, dfdata, cvs_fn, agg_fn, agg_kwargs, x, y): val[neg1] = "-" elif val.dtype.kind == "O": val[neg1] = "-" + elif val.dtype.kind == "M": + val[neg1] = np.datetime64("NaT") else: val = val.astype(np.float64) val[neg1] = np.nan diff --git a/holoviews/plotting/bokeh/element.py b/holoviews/plotting/bokeh/element.py index c62c3f06c4..3d54ac005a 100644 --- a/holoviews/plotting/bokeh/element.py +++ b/holoviews/plotting/bokeh/element.py @@ -6,7 +6,6 @@ import bokeh.plotting import numpy as np import param -from bokeh.core.properties import value from bokeh.document.events import ModelChangedEvent from bokeh.models import ( BinnedTicker, @@ -1784,8 +1783,10 @@ def _postprocess_hover(self, renderer, source): if not isinstance(hover.tooltips, str) and 'hv_created' in hover.tags: for k, values in source.data.items(): key = '@{%s}' % k - if ((isinstance(value, np.ndarray) and value.dtype.kind == 'M') or - (len(values) and isinstance(values[0], util.datetime_types))): + if ( + (len(values) and isinstance(values[0], util.datetime_types)) or + (len(values) and isinstance(values[0], np.ndarray) and values[0].dtype.kind == 'M') + ): hover.tooltips = [(l, f+'{%F %T}' if f == key else f) for l, f in hover.tooltips] hover.formatters[key] = "datetime" diff --git a/holoviews/plotting/bokeh/raster.py b/holoviews/plotting/bokeh/raster.py index 463a9a4fb1..1925ddd824 100644 --- a/holoviews/plotting/bokeh/raster.py +++ b/holoviews/plotting/bokeh/raster.py @@ -43,7 +43,7 @@ def _hover_opts(self, element): tooltips.append((vdims[0].pprint_label, '@image')) for vdim in vdims[1:]: vname = dimension_sanitizer(vdim.name) - tooltips.append((vdim.pprint_label, f'@{vname}')) + tooltips.append((vdim.pprint_label, f'@{{{vname}}}')) return tooltips, {} def _postprocess_hover(self, renderer, source): @@ -52,8 +52,6 @@ def _postprocess_hover(self, renderer, source): if not (hover and isinstance(hover.tooltips, list)): return - element = self.current_frame - xdim, ydim = (dimension_sanitizer(kd.name) for kd in element.kdims) xaxis = self.handles['xaxis'] yaxis = self.handles['yaxis'] @@ -73,6 +71,20 @@ def _postprocess_hover(self, renderer, source): formatters['$y'] = yhover formatter += '{custom}' tooltips.append((name, formatter)) + + # https://github.com/bokeh/bokeh/issues/13598 + datetime_code = """ + if (value === -9223372036854776) { + return "NaT" + } else { + const date = new Date(value); + return date.toISOString().slice(0, 19).replace('T', ' ') + } + """ + for key in formatters: + if formatters[key].lower() == "datetime": + formatters[key] = CustomJSHover(code=datetime_code) + hover.tooltips = tooltips hover.formatters = formatters diff --git a/holoviews/tests/operation/test_datashader.py b/holoviews/tests/operation/test_datashader.py index 7ad78dfe27..a630f8cb0d 100644 --- a/holoviews/tests/operation/test_datashader.py +++ b/holoviews/tests/operation/test_datashader.py @@ -1339,6 +1339,21 @@ def test_rasterize_selector(point_plot, sel_fn): np.testing.assert_array_equal(img["Count"], img_count["Count"]) +def test_rasterize_with_datetime_column(): + n = 4 + df = pd.DataFrame({ + "x": np.random.uniform(-180, 180, n), + "y": np.random.uniform(-90, 90, n), + "Timestamp": pd.date_range(start="2023-01-01", periods=n, freq="D"), + "Value": np.random.rand(n) * 100, + }) + point_plot = Points(df) + rast_input = dict(dynamic=False, x_range=(-1, 1), y_range=(-1, 1), width=2, height=2) + img_agg = rasterize(point_plot, selector=ds.first("Value"), **rast_input) + + assert img_agg["Timestamp"].dtype == np.dtype("datetime64[ns]") + + class DatashaderSpreadTests(ComparisonTestCase): diff --git a/holoviews/tests/plotting/bokeh/test_rasterplot.py b/holoviews/tests/plotting/bokeh/test_rasterplot.py index c12f969126..7f1417b165 100644 --- a/holoviews/tests/plotting/bokeh/test_rasterplot.py +++ b/holoviews/tests/plotting/bokeh/test_rasterplot.py @@ -1,6 +1,9 @@ from unittest import SkipTest import numpy as np +import pandas as pd +import pytest +from bokeh.models import CustomJSHover from holoviews.element import RGB, Image, ImageStack, Raster from holoviews.plotting.bokeh.raster import ImageStackPlot @@ -129,6 +132,24 @@ def test_rgb_invert_yaxis(self): assert cdata["dw"] == [1.0] assert cdata["y"] == [-0.5] + def test_image_datetime_hover(self): + xr = pytest.importorskip("xarray") + ts = pd.Timestamp("2020-01-01") + data = xr.Dataset( + coords={"x": [-0.5, 0.5], "y": [-0.5, 0.5]}, + data_vars={ + "Count": (["y", "x"], [[0, 1], [2, 3]]), + "Timestamp": (["y", "x"], [[ts, pd.NaT], [ts, ts]]), + }, + ) + img = Image(data).opts(tools=["hover"]) + plot = bokeh_renderer.get_plot(img) + + hover = plot.handles["hover"] + assert hover.tooltips[-1] == ("Timestamp", "@{Timestamp}{%F %T}") + assert "@{Timestamp}" in hover.formatters + assert isinstance(hover.formatters["@{Timestamp}"], CustomJSHover) + # assert hover.formatters["@{Timestamp}"] == "datetime" # https://github.com/bokeh/bokeh/issues/13598 class _ImageStackBase(TestRasterPlot): __test__ = False From efed87dad741584c6e8d11270aef7c1ce3e3a129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Sat, 16 Dec 2023 11:15:32 +0100 Subject: [PATCH 10/66] Only run test-suite on code change (#6035) --- .github/workflows/test.yaml | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index d6a270b93d..14a4b0b253 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -34,9 +34,31 @@ jobs: steps: - uses: holoviz-dev/holoviz_tasks/pre-commit@v0.1a17 + changes: + name: Check for code changes + runs-on: ubuntu-latest + permissions: + pull-requests: read + outputs: + code: ${{ steps.filter.outputs.code }} + steps: + - uses: actions/checkout@v3 + if: github.event_name != 'pull_request' + - uses: dorny/paths-filter@v2.11.1 + id: filter + with: + filters: | + code: + - 'holoviews/**' + - 'examples/**' + - 'setup.py' + - 'pyproject.toml' + - '.github/workflows/test.yaml' + unit_test_suite: name: Unit tests on Python ${{ matrix.python-version }}, ${{ matrix.os }} - needs: [pre_commit] + needs: [pre_commit, changes] + if: needs.changes.outputs.code == 'true' runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -80,9 +102,11 @@ jobs: run: | conda activate test-environment codecov + ui_test_suite: name: UI tests on Python ${{ matrix.python-version }}, ${{ matrix.os }} - needs: [pre_commit] + needs: [pre_commit, changes] + if: needs.changes.outputs.code == 'true' runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -124,9 +148,11 @@ jobs: files: ./coverage.xml flags: ui-tests fail_ci_if_error: false # optional (default = false) + core_test_suite: name: Core tests on Python ${{ matrix.python-version }}, ${{ matrix.os }} - needs: [pre_commit] + needs: [pre_commit, changes] + if: needs.changes.outputs.code == 'true' runs-on: ${{ matrix.os }} strategy: fail-fast: false From 804d56ba6d4a65eb734765b373694f49ba47bd8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Sat, 16 Dec 2023 12:49:15 +0100 Subject: [PATCH 11/66] Add skip statement to all steps to work with required (#6037) --- .github/workflows/test.yaml | 60 ++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 14a4b0b253..ccdcd0b808 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -5,15 +5,19 @@ on: - main pull_request: branches: - - '*' + - "*" workflow_dispatch: schedule: - - cron: '0 14 * * SUN' + - cron: "0 14 * * SUN" concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true +defaults: + run: + shell: bash -el {0} + env: SETUPTOOLS_ENABLE_FEATURES: "legacy-editable" DISPLAY: ":99.0" @@ -30,9 +34,9 @@ env: jobs: pre_commit: name: Run pre-commit - runs-on: 'ubuntu-latest' + runs-on: "ubuntu-latest" steps: - - uses: holoviz-dev/holoviz_tasks/pre-commit@v0.1a17 + - uses: holoviz-dev/holoviz_tasks/pre-commit@v0.1a19 changes: name: Check for code changes @@ -58,25 +62,22 @@ jobs: unit_test_suite: name: Unit tests on Python ${{ matrix.python-version }}, ${{ matrix.os }} needs: [pre_commit, changes] - if: needs.changes.outputs.code == 'true' runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: ['ubuntu-latest', 'macos-latest', 'windows-latest'] - python-version: ['3.9', '3.11'] + os: ["ubuntu-latest", "macos-latest", "windows-latest"] + python-version: ["3.9", "3.11"] include: - - os: 'ubuntu-latest' - python-version: '3.10' + - os: "ubuntu-latest" + python-version: "3.10" timeout-minutes: 120 - defaults: - run: - shell: bash -el {0} env: DESC: "Python ${{ matrix.python-version }}, ${{ matrix.os }} unit tests" PYTHON_VERSION: ${{ matrix.python-version }} steps: - - uses: holoviz-dev/holoviz_tasks/install@v0.1a17 + - uses: holoviz-dev/holoviz_tasks/install@v0.1a19 + if: needs.changes.outputs.code == 'true' with: name: unit_test_suite python-version: ${{ matrix.python-version }} @@ -87,18 +88,22 @@ jobs: conda-update: true id: install - name: bokeh sampledata + if: needs.changes.outputs.code == 'true' run: | conda activate test-environment bokeh sampledata - name: doit test_unit + if: needs.changes.outputs.code == 'true' run: | conda activate test-environment doit test_unit - name: test examples + if: needs.changes.outputs.code == 'true' run: | conda activate test-environment doit test_examples - name: codecov + if: needs.changes.outputs.code == 'true' run: | conda activate test-environment codecov @@ -106,17 +111,13 @@ jobs: ui_test_suite: name: UI tests on Python ${{ matrix.python-version }}, ${{ matrix.os }} needs: [pre_commit, changes] - if: needs.changes.outputs.code == 'true' runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: ['ubuntu-latest'] - python-version: ['3.9'] + os: ["ubuntu-latest"] + python-version: ["3.9"] timeout-minutes: 60 - defaults: - run: - shell: bash -el {0} env: DESC: "Python ${{ matrix.python-version }}, ${{ matrix.os }} UI tests" PANEL_LOG_LEVEL: info @@ -125,7 +126,8 @@ jobs: # it as one of the sources. PYCTDEV_SELF_CHANNEL: "pyviz/label/dev" steps: - - uses: holoviz-dev/holoviz_tasks/install@v0.1a17 + - uses: holoviz-dev/holoviz_tasks/install@v0.1a19 + if: needs.changes.outputs.code == 'true' with: name: ui_test_suite python-version: ${{ matrix.python-version }} @@ -139,10 +141,12 @@ jobs: conda activate test-environment doit env_capture - name: doit test_ui + if: needs.changes.outputs.code == 'true' run: | conda activate test-environment doit test_ui - name: Upload coverage to Codecov + if: needs.changes.outputs.code == 'true' uses: codecov/codecov-action@v3 with: files: ./coverage.xml @@ -152,23 +156,20 @@ jobs: core_test_suite: name: Core tests on Python ${{ matrix.python-version }}, ${{ matrix.os }} needs: [pre_commit, changes] - if: needs.changes.outputs.code == 'true' runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: ['ubuntu-latest'] - python-version: ['3.12'] + os: ["ubuntu-latest"] + python-version: ["3.12"] timeout-minutes: 120 - defaults: - run: - shell: bash -el {0} env: DESC: "Python ${{ matrix.python-version }}, ${{ matrix.os }} core tests" PYTHON_VERSION: ${{ matrix.python-version }} steps: # Add back when this works on Python 3.12 - # - uses: holoviz-dev/holoviz_tasks/install@v0.1a17 + # - uses: holoviz-dev/holoviz_tasks/install@v0.1a19 + # if: needs.changes.outputs.code == 'true' # with: # name: core_test_suite # python-version: ${{ matrix.python-version }} @@ -182,21 +183,26 @@ jobs: with: fetch-depth: "100" - name: Fetch unshallow + if: needs.changes.outputs.code == 'true' run: git fetch --prune --tags --unshallow -f - uses: actions/setup-python@v4 + if: needs.changes.outputs.code == 'true' with: python-version: 3.12 - run: | python -m pip install -ve '.[tests_core, tests_ci]' - name: bokeh sampledata + if: needs.changes.outputs.code == 'true' run: | # conda activate test-environment bokeh sampledata - name: Check packages latest version + if: needs.changes.outputs.code == 'true' run: | # conda activate test-environment python scripts/check_latest_packages.py - name: doit test_unit + if: needs.changes.outputs.code == 'true' run: | # conda activate test-environment pytest holoviews From ecab267c6df74e4364a007946989c52a9f7eed9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Sat, 16 Dec 2023 13:35:00 +0100 Subject: [PATCH 12/66] Update links and instructions in readme (#6036) --- .github/workflows/test.yaml | 9 ++++----- README.md | 13 ++++--------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index ccdcd0b808..9d5de5265c 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -136,10 +136,6 @@ jobs: cache: true playwright: true id: install - - name: doit env_capture - run: | - conda activate test-environment - doit env_capture - name: doit test_ui if: needs.changes.outputs.code == 'true' run: | @@ -180,6 +176,7 @@ jobs: # conda-update: true # id: install - uses: actions/checkout@v3 + if: needs.changes.outputs.code == 'true' with: fetch-depth: "100" - name: Fetch unshallow @@ -189,7 +186,9 @@ jobs: if: needs.changes.outputs.code == 'true' with: python-version: 3.12 - - run: | + - name: install + if: needs.changes.outputs.code == 'true' + run: | python -m pip install -ve '.[tests_core, tests_ci]' - name: bokeh sampledata if: needs.changes.outputs.code == 'true' diff --git a/README.md b/README.md index b70ff28ccc..7aee1728f1 100644 --- a/README.md +++ b/README.md @@ -59,16 +59,16 @@ Installation ============ HoloViews works with -[Python 3](https://github.com/holoviz/holoviews/actions?query=workflow%3Apytest) +[Python](https://github.com/holoviz/holoviews/actions/workflows/test.yaml) on Linux, Windows, or Mac, and works seamlessly with [Jupyter Notebook and JupyterLab](https://jupyter.org). The recommended way to install HoloViews is using the [conda](https://docs.conda.io/projects/conda/en/latest/index.html) command provided by -[Anaconda](https://docs.anaconda.com/anaconda/install/) or +[Anaconda](https://docs.anaconda.com/free/anaconda/install/) or [Miniconda](https://docs.conda.io/en/latest/miniconda.html): - conda install -c pyviz holoviews bokeh + conda install holoviews This command will install the typical packages most useful with HoloViews, though HoloViews itself depends only on @@ -96,14 +96,9 @@ Now you can launch Jupyter Notebook or JupyterLab to explore them: jupyter lab -If you are working with a JupyterLab version <2.0 you will also need the PyViz JupyterLab -extension: - - jupyter labextension install @pyviz/jupyterlab_pyviz - For more details on setup and configuration see [our website](https://holoviews.org/user_guide/Installing_and_Configuring.html). -For general discussion, we have a [gitter channel](https://gitter.im/pyviz/pyviz). +For general discussion, we have a [discord channel](https://discord.gg/AXRHnJU6sP). If you find any bugs or have any feature suggestions please file a GitHub [issue](https://github.com/holoviz/holoviews/issues) or submit a [pull request](https://help.github.com/articles/about-pull-requests). From 554fcabf1356aa48285768ab1304dc02846201d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Mon, 18 Dec 2023 09:09:07 +0100 Subject: [PATCH 13/66] Fix label 'type: doc' to 'type: docs' --- .github/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/release.yml b/.github/release.yml index cbccb3e8f3..b30419292b 100644 --- a/.github/release.yml +++ b/.github/release.yml @@ -15,7 +15,7 @@ changelog: - "type: compatibility" - title: Documentation labels: - - "type: doc" + - "type: docs" - title: Maintenance labels: - "type: maintenance" From 898c11f655781c2052602070a6dffc5671387544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Mon, 18 Dec 2023 12:05:07 +0100 Subject: [PATCH 14/66] Remove custom datetime hover conversion for Bokeh RasterPlot (#6039) --- holoviews/plotting/bokeh/raster.py | 26 +++++++++---------- holoviews/plotting/bokeh/util.py | 1 + .../tests/plotting/bokeh/test_rasterplot.py | 8 ++++-- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/holoviews/plotting/bokeh/raster.py b/holoviews/plotting/bokeh/raster.py index 1925ddd824..e10c3ecdd9 100644 --- a/holoviews/plotting/bokeh/raster.py +++ b/holoviews/plotting/bokeh/raster.py @@ -11,7 +11,7 @@ from .element import ColorbarPlot, LegendPlot from .selection import BokehOverlaySelectionDisplay from .styles import base_properties, fill_properties, line_properties, mpl_to_bokeh -from .util import bokeh33, colormesh +from .util import bokeh33, bokeh34, colormesh class RasterPlot(ColorbarPlot): @@ -72,18 +72,18 @@ def _postprocess_hover(self, renderer, source): formatter += '{custom}' tooltips.append((name, formatter)) - # https://github.com/bokeh/bokeh/issues/13598 - datetime_code = """ - if (value === -9223372036854776) { - return "NaT" - } else { - const date = new Date(value); - return date.toISOString().slice(0, 19).replace('T', ' ') - } - """ - for key in formatters: - if formatters[key].lower() == "datetime": - formatters[key] = CustomJSHover(code=datetime_code) + if not bokeh34: # https://github.com/bokeh/bokeh/issues/13598 + datetime_code = """ + if (value === -9223372036854776) { + return "NaN" + } else { + const date = new Date(value); + return date.toISOString().slice(0, 19).replace('T', ' ') + } + """ + for key in formatters: + if formatters[key].lower() == "datetime": + formatters[key] = CustomJSHover(code=datetime_code) hover.tooltips = tooltips hover.formatters = formatters diff --git a/holoviews/plotting/bokeh/util.py b/holoviews/plotting/bokeh/util.py index bd54472844..490fbf9035 100644 --- a/holoviews/plotting/bokeh/util.py +++ b/holoviews/plotting/bokeh/util.py @@ -63,6 +63,7 @@ bokeh_version = Version(bokeh.__version__) bokeh32 = bokeh_version >= Version("3.2") bokeh33 = bokeh_version >= Version("3.3") +bokeh34 = bokeh_version >= Version("3.4") TOOL_TYPES = { 'pan': tools.PanTool, diff --git a/holoviews/tests/plotting/bokeh/test_rasterplot.py b/holoviews/tests/plotting/bokeh/test_rasterplot.py index 7f1417b165..36e10bc907 100644 --- a/holoviews/tests/plotting/bokeh/test_rasterplot.py +++ b/holoviews/tests/plotting/bokeh/test_rasterplot.py @@ -7,6 +7,7 @@ from holoviews.element import RGB, Image, ImageStack, Raster from holoviews.plotting.bokeh.raster import ImageStackPlot +from holoviews.plotting.bokeh.util import bokeh34 from .test_plot import TestBokehPlot, bokeh_renderer @@ -148,8 +149,11 @@ def test_image_datetime_hover(self): hover = plot.handles["hover"] assert hover.tooltips[-1] == ("Timestamp", "@{Timestamp}{%F %T}") assert "@{Timestamp}" in hover.formatters - assert isinstance(hover.formatters["@{Timestamp}"], CustomJSHover) - # assert hover.formatters["@{Timestamp}"] == "datetime" # https://github.com/bokeh/bokeh/issues/13598 + + if bokeh34: # https://github.com/bokeh/bokeh/issues/13598 + assert hover.formatters["@{Timestamp}"] == "datetime" + else: + assert isinstance(hover.formatters["@{Timestamp}"], CustomJSHover) class _ImageStackBase(TestRasterPlot): __test__ = False From 3da06798f55288d5da38419af8b1f8c76e6557d6 Mon Sep 17 00:00:00 2001 From: junietoc <64213327+junietoc@users.noreply.github.com> Date: Mon, 18 Dec 2023 07:03:51 -0500 Subject: [PATCH 15/66] Fix to broken urls in example gallery pages (#6038) --- examples/gallery/demos/bokeh/dot_example.ipynb | 9 +-------- examples/gallery/demos/bokeh/histogram_example.ipynb | 4 ++-- examples/gallery/demos/bokeh/iris_example.ipynb | 4 ++-- examples/gallery/demos/bokeh/iris_splom_example.ipynb | 4 ++-- examples/gallery/demos/bokeh/lesmis_example.ipynb | 4 ++-- .../gallery/demos/bokeh/lorenz_attractor_example.ipynb | 4 ++-- examples/gallery/demos/bokeh/step_chart.ipynb | 4 +--- examples/gallery/demos/bokeh/stocks_example.ipynb | 4 ++-- .../gallery/demos/bokeh/texas_choropleth_example.ipynb | 2 +- examples/gallery/demos/bokeh/us_unemployment.ipynb | 4 ++-- .../gallery/demos/matplotlib/histogram_example.ipynb | 4 ++-- examples/gallery/demos/matplotlib/iris_example.ipynb | 4 ++-- .../gallery/demos/matplotlib/iris_splom_example.ipynb | 4 ++-- .../demos/matplotlib/lorenz_attractor_example.ipynb | 4 ++-- examples/gallery/demos/matplotlib/step_chart.ipynb | 2 -- examples/gallery/demos/matplotlib/stocks_example.ipynb | 4 ++-- .../demos/matplotlib/texas_choropleth_example.ipynb | 2 +- examples/gallery/demos/matplotlib/us_unemployment.ipynb | 4 ++-- 18 files changed, 30 insertions(+), 41 deletions(-) diff --git a/examples/gallery/demos/bokeh/dot_example.ipynb b/examples/gallery/demos/bokeh/dot_example.ipynb index 8736404dbf..4949704edf 100644 --- a/examples/gallery/demos/bokeh/dot_example.ipynb +++ b/examples/gallery/demos/bokeh/dot_example.ipynb @@ -1,12 +1,5 @@ { "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/dot.html" - ] - }, { "cell_type": "code", "execution_count": null, @@ -69,5 +62,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/demos/bokeh/histogram_example.ipynb b/examples/gallery/demos/bokeh/histogram_example.ipynb index ac25be0303..461b6941ca 100644 --- a/examples/gallery/demos/bokeh/histogram_example.ipynb +++ b/examples/gallery/demos/bokeh/histogram_example.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/histogram.html\n", + "URL: https://docs.bokeh.org/en/latest/docs/examples/topics/stats/histogram.html\n", "\n", "Most examples work across multiple plotting backends, this example is also available for:\n", "\n", @@ -133,5 +133,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/demos/bokeh/iris_example.ipynb b/examples/gallery/demos/bokeh/iris_example.ipynb index ce80c330b5..d63a4d19b0 100644 --- a/examples/gallery/demos/bokeh/iris_example.ipynb +++ b/examples/gallery/demos/bokeh/iris_example.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/iris.html\n", + "URL: https://docs.bokeh.org/en/2.4.1/docs/gallery/iris.html\n", "\n", "Most examples work across multiple plotting backends, this example is also available for:\n", "\n", @@ -63,5 +63,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/demos/bokeh/iris_splom_example.ipynb b/examples/gallery/demos/bokeh/iris_splom_example.ipynb index da491e2c6c..018dd19717 100644 --- a/examples/gallery/demos/bokeh/iris_splom_example.ipynb +++ b/examples/gallery/demos/bokeh/iris_splom_example.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/iris_splom.html\n", + "URL: https://docs.bokeh.org/en/2.4.1/docs/gallery/iris_splom.html\n", "\n", "Most examples work across multiple plotting backends, this example is also available for:\n", "\n", @@ -68,5 +68,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/demos/bokeh/lesmis_example.ipynb b/examples/gallery/demos/bokeh/lesmis_example.ipynb index bfb7ac5f5c..5b6354634d 100644 --- a/examples/gallery/demos/bokeh/lesmis_example.ipynb +++ b/examples/gallery/demos/bokeh/lesmis_example.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/les_mis.html" + "URL: https://docs.bokeh.org/en/latest/docs/examples/topics/categorical/les_mis.html" ] }, { @@ -104,5 +104,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/demos/bokeh/lorenz_attractor_example.ipynb b/examples/gallery/demos/bokeh/lorenz_attractor_example.ipynb index 49fdb042c9..d209ac2a04 100644 --- a/examples/gallery/demos/bokeh/lorenz_attractor_example.ipynb +++ b/examples/gallery/demos/bokeh/lorenz_attractor_example.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/lorenz.html\n", + "URL: https://docs.bokeh.org/en/latest/docs/examples/basic/lines/lorenz.html\n", "\n", "Most examples work across multiple plotting backends, this example is also available for:\n", "\n", @@ -89,5 +89,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/demos/bokeh/step_chart.ipynb b/examples/gallery/demos/bokeh/step_chart.ipynb index d901f7f34d..75b37c4b84 100644 --- a/examples/gallery/demos/bokeh/step_chart.ipynb +++ b/examples/gallery/demos/bokeh/step_chart.ipynb @@ -4,8 +4,6 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/step_chart.html\n", - "\n", "Most examples work across multiple plotting backends, this example is also available for:\n", "\n", "* [Matplotlib - step_chart example](../bokeh/step_chart_example.ipynb)" @@ -61,7 +59,7 @@ "outputs": [], "source": [ "postage.opts(\n", - " opts.Curve(interpolation='steps-mid', width=400, height=400, \n", + " opts.Curve(interpolation='steps-mid', width=400, height=400,\n", " line_dash=hv.Cycle(values=['dashed', 'solid'])),\n", " opts.Overlay(legend_position='top_left'))" ] diff --git a/examples/gallery/demos/bokeh/stocks_example.ipynb b/examples/gallery/demos/bokeh/stocks_example.ipynb index 7c945e24c6..38d0dea161 100644 --- a/examples/gallery/demos/bokeh/stocks_example.ipynb +++ b/examples/gallery/demos/bokeh/stocks_example.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/stocks.html\n", + "URL: https://docs.bokeh.org/en/2.4.1/docs/gallery/stocks.html\n", "\n", "Most examples work across multiple plotting backends, this example is also available for:\n", "\n", @@ -87,5 +87,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/demos/bokeh/texas_choropleth_example.ipynb b/examples/gallery/demos/bokeh/texas_choropleth_example.ipynb index 4c8964dd43..9fdaefe668 100644 --- a/examples/gallery/demos/bokeh/texas_choropleth_example.ipynb +++ b/examples/gallery/demos/bokeh/texas_choropleth_example.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/texas.html\n", + "URL: https://docs.bokeh.org/en/latest/docs/examples/topics/geo/texas_hover_map.html\n", "\n", "Most examples work across multiple plotting backends, this example is also available for:\n", "\n", diff --git a/examples/gallery/demos/bokeh/us_unemployment.ipynb b/examples/gallery/demos/bokeh/us_unemployment.ipynb index 8c76682bf5..e7fd2c3cf1 100644 --- a/examples/gallery/demos/bokeh/us_unemployment.ipynb +++ b/examples/gallery/demos/bokeh/us_unemployment.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/unemployment.html\n", + "URL: https://docs.bokeh.org/en/latest/docs/examples/topics/categorical/heatmap_unemployment.html\n", "\n", "Most examples work across multiple plotting backends, this example is also available for:\n", "\n", @@ -70,5 +70,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/demos/matplotlib/histogram_example.ipynb b/examples/gallery/demos/matplotlib/histogram_example.ipynb index 9e7f3d7863..50f284718d 100644 --- a/examples/gallery/demos/matplotlib/histogram_example.ipynb +++ b/examples/gallery/demos/matplotlib/histogram_example.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/histogram.html\n", + "URL: https://docs.bokeh.org/en/latest/docs/examples/topics/stats/histogram.html\n", "\n", "Most examples work across multiple plotting backends, this example is also available for:\n", "\n", @@ -134,5 +134,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/demos/matplotlib/iris_example.ipynb b/examples/gallery/demos/matplotlib/iris_example.ipynb index 35bf5915b8..bfecbc944c 100644 --- a/examples/gallery/demos/matplotlib/iris_example.ipynb +++ b/examples/gallery/demos/matplotlib/iris_example.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/iris.html\n", + "URL: https://docs.bokeh.org/en/2.4.1/docs/gallery/iris.html\n", "\n", "Most examples work across multiple plotting backends, this example is also available for:\n", "\n", @@ -65,5 +65,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/demos/matplotlib/iris_splom_example.ipynb b/examples/gallery/demos/matplotlib/iris_splom_example.ipynb index bc5394a480..f78eb8de04 100644 --- a/examples/gallery/demos/matplotlib/iris_splom_example.ipynb +++ b/examples/gallery/demos/matplotlib/iris_splom_example.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/iris_splom.html\n", + "URL: https://docs.bokeh.org/en/2.4.1/docs/gallery/iris_splom.html\n", "\n", "Most examples work across multiple plotting backends, this example is also available for:\n", "\n", @@ -69,5 +69,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/demos/matplotlib/lorenz_attractor_example.ipynb b/examples/gallery/demos/matplotlib/lorenz_attractor_example.ipynb index 6197a1772f..8bfe057c26 100644 --- a/examples/gallery/demos/matplotlib/lorenz_attractor_example.ipynb +++ b/examples/gallery/demos/matplotlib/lorenz_attractor_example.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/lorenz.html\n", + "URL: https://docs.bokeh.org/en/latest/docs/examples/basic/lines/lorenz.html\n", "\n", "Most examples work across multiple plotting backends, this example is also available for:\n", "\n", @@ -88,5 +88,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/demos/matplotlib/step_chart.ipynb b/examples/gallery/demos/matplotlib/step_chart.ipynb index 12ad9e68fd..61d228323a 100644 --- a/examples/gallery/demos/matplotlib/step_chart.ipynb +++ b/examples/gallery/demos/matplotlib/step_chart.ipynb @@ -4,8 +4,6 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/step_chart.html\n", - "\n", "Most examples work across multiple plotting backends, this example is also available for:\n", "\n", "* [Bokeh - step_chart example](../bokeh/step_chart.ipynb)" diff --git a/examples/gallery/demos/matplotlib/stocks_example.ipynb b/examples/gallery/demos/matplotlib/stocks_example.ipynb index 3b6f6cb7ef..adf74df2d3 100644 --- a/examples/gallery/demos/matplotlib/stocks_example.ipynb +++ b/examples/gallery/demos/matplotlib/stocks_example.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/stocks.html\n", + "URL: https://docs.bokeh.org/en/2.4.1/docs/gallery/stocks.html\n", "\n", "Most examples work across multiple plotting backends, this example is also available for:\n", "\n", @@ -94,5 +94,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/gallery/demos/matplotlib/texas_choropleth_example.ipynb b/examples/gallery/demos/matplotlib/texas_choropleth_example.ipynb index eb182b08d8..69db3b5bb5 100644 --- a/examples/gallery/demos/matplotlib/texas_choropleth_example.ipynb +++ b/examples/gallery/demos/matplotlib/texas_choropleth_example.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/texas.html\n", + "URL: https://docs.bokeh.org/en/latest/docs/examples/topics/geo/texas_hover_map.html\n", "\n", "Most examples work across multiple plotting backends, this example is also available for:\n", "\n", diff --git a/examples/gallery/demos/matplotlib/us_unemployment.ipynb b/examples/gallery/demos/matplotlib/us_unemployment.ipynb index 1722631b6b..e971c59360 100644 --- a/examples/gallery/demos/matplotlib/us_unemployment.ipynb +++ b/examples/gallery/demos/matplotlib/us_unemployment.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "URL: http://bokeh.pydata.org/en/latest/docs/gallery/unemployment.html\n", + "URL: https://docs.bokeh.org/en/latest/docs/examples/topics/categorical/heatmap_unemployment.html\n", "\n", "Most examples work across multiple plotting backends, this example is also available for:\n", "\n", @@ -68,5 +68,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } From b30ae90649e688d63ca794175559dabec78497fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Tue, 19 Dec 2023 08:45:24 +0100 Subject: [PATCH 16/66] Add prettier for markdown and yaml (#6040) --- .github/workflows/build.yaml | 14 +- .github/workflows/docs.yaml | 20 +- .github/workflows/downstream_tests.yaml | 2 +- .pre-commit-config.yaml | 19 +- CHANGELOG.md | 2630 ++++++++--------- README.md | 12 +- examples/README.md | 16 +- .../demos/bokeh/nyc_airport_connections.ipynb | 2 +- .../matplotlib/nyc_airport_connections.ipynb | 2 +- examples/reference/streams/bokeh/Tap.ipynb | 2 +- 10 files changed, 1338 insertions(+), 1381 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 69ffbe9516..81563ba20e 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -2,19 +2,19 @@ name: packages on: push: tags: - - 'v[0-9]+.[0-9]+.[0-9]+' - - 'v[0-9]+.[0-9]+.[0-9]+a[0-9]+' - - 'v[0-9]+.[0-9]+.[0-9]+b[0-9]+' - - 'v[0-9]+.[0-9]+.[0-9]+rc[0-9]+' + - "v[0-9]+.[0-9]+.[0-9]+" + - "v[0-9]+.[0-9]+.[0-9]+a[0-9]+" + - "v[0-9]+.[0-9]+.[0-9]+b[0-9]+" + - "v[0-9]+.[0-9]+.[0-9]+rc[0-9]+" # Dry-run only workflow_dispatch: schedule: - - cron: '0 14 * * SUN' + - cron: "0 14 * * SUN" jobs: conda_build: name: Build Conda Packages - runs-on: 'ubuntu-latest' + runs-on: "ubuntu-latest" defaults: run: shell: bash -l {0} @@ -63,7 +63,7 @@ jobs: anaconda --token $CONDA_UPLOAD_TOKEN upload --user pyviz --label=dev --label=main $FILE pip_build: name: Build PyPI Packages - runs-on: 'ubuntu-latest' + runs-on: "ubuntu-latest" defaults: run: shell: bash -l {0} diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 240caafb83..1ccee6aed1 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -2,28 +2,28 @@ name: docs on: push: tags: - - 'v[0-9]+.[0-9]+.[0-9]+' - - 'v[0-9]+.[0-9]+.[0-9]+a[0-9]+' - - 'v[0-9]+.[0-9]+.[0-9]+b[0-9]+' - - 'v[0-9]+.[0-9]+.[0-9]+rc[0-9]+' + - "v[0-9]+.[0-9]+.[0-9]+" + - "v[0-9]+.[0-9]+.[0-9]+a[0-9]+" + - "v[0-9]+.[0-9]+.[0-9]+b[0-9]+" + - "v[0-9]+.[0-9]+.[0-9]+rc[0-9]+" workflow_dispatch: inputs: target: - description: 'Site to build and deploy, or dry-run' + description: "Site to build and deploy, or dry-run" type: choice options: - - dev - - main - - dryrun + - dev + - main + - dryrun required: true default: dryrun schedule: - - cron: '0 14 * * SUN' + - cron: "0 14 * * SUN" jobs: build_docs: name: Documentation - runs-on: 'ubuntu-latest' + runs-on: "ubuntu-latest" timeout-minutes: 120 defaults: run: diff --git a/.github/workflows/downstream_tests.yaml b/.github/workflows/downstream_tests.yaml index b669e08ba4..4ee679e0ce 100644 --- a/.github/workflows/downstream_tests.yaml +++ b/.github/workflows/downstream_tests.yaml @@ -18,6 +18,6 @@ jobs: downstream_tests: uses: holoviz-dev/holoviz_tasks/.github/workflows/run_downstream_tests.yaml@main with: - downstream_repos_as_json: "{\"downstream_repo\":[\"hvplot\", \"geoviews\"]}" + downstream_repos_as_json: '{"downstream_repo":["hvplot", "geoviews"]}' secrets: ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6c59e8a313..1b12bcdfef 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,20 +20,21 @@ repos: - id: check-json - id: detect-private-key - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.1.6 + rev: v0.1.8 hooks: - id: ruff files: holoviews/|scripts/ - repo: https://github.com/hoxbro/clean_notebook - rev: v0.1.13 + rev: v0.1.14 hooks: - id: clean-notebook + args: [--strip-trailing-newlines] - repo: https://github.com/codespell-project/codespell rev: v2.2.6 hooks: - - id: codespell - additional_dependencies: - - tomli + - id: codespell + additional_dependencies: + - tomli - repo: https://github.com/pre-commit/pygrep-hooks rev: v1.10.0 hooks: @@ -44,3 +45,11 @@ repos: rev: v0.9.0.6 hooks: - id: shellcheck + - repo: https://github.com/pre-commit/mirrors-prettier + rev: v4.0.0-alpha.7 + hooks: + - id: prettier + exclude: conda.recipe/meta.yaml + types_or: + - markdown + - yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index a6f9f7cd01..8a9eeb21e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,9 @@ -Version 1.18.1 -============== -**November 8, 2023** +# Version 1.18.1 +**November 8, 2023** This release contains a small number of bug fixes and compatibility updates — many thanks to @philippjfr and @Hoxbro for their contributions. - Bug fixes: - Account for overlaid elements when using `subcoordinates_y` ([#5950](https://github.com/holoviz/holoviews/pull/5950)) @@ -23,16 +21,14 @@ Maintenance: - General maintenance ([#5955](https://github.com/holoviz/holoviews/pull/5955)) +# Version 1.18.0 -Version 1.18.0 -============== **October 18, 2023** This release includes new features, improvements, and bug fixes. Among these are the new elements. First is the `ImageStack` element allows you to easily visualize a 3D array, while the `VLines`, `HLines`, `VSpans`, and `HSpans` elements allow you to visualize vertical and horizontal lines and spans easily. In addition, this release includes support for subcoordinate systems in the y-axis and various other enhancements and bug fixes. This release adds support for the newest Python 3.12 and Bokeh 3.3 and drops support for Python 3.8 and Bokeh 2. Many thanks to the new contributors @MeggyCal, along with our returning contributors @ahuang11, @ianthomas23, @jlstevens, @maximlt, @philippjfr, and @Hoxbro. - New features: - Implementation of `ImageStack` ([#5751](https://github.com/holoviz/holoviews/pull/5751), [#5945](https://github.com/holoviz/holoviews/pull/5945)) @@ -74,7 +70,7 @@ Compatibility: Documentation: -- Add *Linking Bokeh plots* guide to the table of contents ([#5900](https://github.com/holoviz/holoviews/pull/5900)) +- Add _Linking Bokeh plots_ guide to the table of contents ([#5900](https://github.com/holoviz/holoviews/pull/5900)) Maintenance: @@ -86,15 +82,12 @@ Maintenance: - Add sorting of imports ([#5937](https://github.com/holoviz/holoviews/pull/5937)) - Enable Bugbear lint ([#5861](https://github.com/holoviz/holoviews/pull/5861)) +# Version 1.17.1 -Version 1.17.1 -============== **August 16, 2023** - This release contains a small number of important bug fixes and regressions — many thanks to @ianthomas23, @maximlt, @philippjfr, and @Hoxbro for their contributions. - Enhancements: - Improve support for `hv.NdOverlay` and `hv.Overlay` in downsample1d ([#5856](https://github.com/holoviz/holoviews/pull/5856)) @@ -120,9 +113,8 @@ Maintenance: - Update Ruff in pre-commit and report panel communication in `hv.show_versions` ([#5853](https://github.com/holoviz/holoviews/pull/5853)) - Cleanup imports ([#5846](https://github.com/holoviz/holoviews/pull/5846)) +# Version 1.17.0 -Version 1.17.0 -============== **July 24, 2023** This release brings one of the most requested features - interactive twin-axis support! Another feature added in this release is the ability to easily set custom options on plot components with `backend_opts`, making it much easier to customize your plots. Datashaders `where` and `summary` aggregators are now supported, and `rasterize` now has a `selector` option, making it easy to get extra information about your rasterized data. Lastly, Bokeh figures with the same labels will synchronize muteness or visibility across different figures. @@ -142,7 +134,7 @@ Enhancements: - Add option for initial ranges to RangeToolLink ([#5800](https://github.com/holoviz/holoviews/pull/5800)) - Allow resample's `pixel_ratio` to go below 1 ([#5813](https://github.com/holoviz/holoviews/pull/5813), [#5817](https://github.com/holoviz/holoviews/pull/5817)) -Add the ability for `VectorField` to instantiate from UV coordinates ([#5797](https://github.com/holoviz/holoviews/pull/5797)) + Add the ability for `VectorField` to instantiate from UV coordinates ([#5797](https://github.com/holoviz/holoviews/pull/5797)) - Handle the `nodata` option for rasterized RGB image ([#5774](https://github.com/holoviz/holoviews/pull/5774)) Bug fixes: @@ -182,9 +174,8 @@ Maintenance: - Update pre-commit and lint ([#5747](https://github.com/holoviz/holoviews/pull/5747), [#5768](https://github.com/holoviz/holoviews/pull/5768), [#5777](https://github.com/holoviz/holoviews/pull/5777)) - Setup infrastructure for UI tests and add first linked streams tests ([#5764](https://github.com/holoviz/holoviews/pull/5764)) +# Version 1.16.2 -Version 1.16.2 -============== **June 8, 2023** This release includes a breaking change as notebooks will no longer be inlining as default. This change will reduce the size of the notebook files and, more importantly, address an upstream issue in Jupyter where running `hv.extension` would give an error when used in a notebook. @@ -203,16 +194,14 @@ Maintenance: - Fix failing tests ([#5742](https://github.com/holoviz/holoviews/pull/5742)) - Misc. mainteance ([#5717](https://github.com/holoviz/holoviews/pull/5717)) +# Version 1.16.1 -Version 1.16.1 -============== **June 2, 2023** This release contains a small number of important bug fixes and enhancements. Many thanks to @philippjfr and @Hoxbro. This release includes a breaking change as notebooks will no longer be inlining as default. This change will reduce the size of the notebook files and, more importantly, address an upstream issue in Jupyter where running `hv.extension` would give an error when used in a notebook. - Critical bug fixes and compatibility: - Add `enable_mathjax` and set it and inline to `False` ([#5729](https://github.com/holoviz/holoviews/pull/5729)) @@ -224,14 +213,12 @@ Enhancements: - Ignore known model warning in VS Code ([#5734](https://github.com/holoviz/holoviews/pull/5734)) - Add workaround for plots where the objects in a figure would overlap ([#5733](https://github.com/holoviz/holoviews/pull/5733)) - Documentation: - Upgrade to latest `nbsite` and `pydata-sphinx-theme` ([#5724](https://github.com/holoviz/holoviews/pull/5724), [#5735](https://github.com/holoviz/holoviews/pull/5735)) +# Version 1.16.0 -Version 1.16.0 -============== **May 9, 2023** This release includes many new features, improvements, and bug fixes. Among the highlights are support for Bokeh 3.1 and Panel 1.0, both of which come with a wide range of new features and enhancements. Time series support has also been improved, with auto-ranging along one axis, a new downsample algorithm, and having WebGL enabled by default. In addition, the release includes various other enhancements and bug fixes. @@ -241,7 +228,6 @@ We would like to thank the many users who contributed to this release by filing This minor version will be the last to support Python 3.7. The next minor version will require Python 3.8 or higher. In the next release, `holoviews.annotate` will start giving a deprecation warning about its future move to the new package [HoloNote](https://github.com/holoviz/holonote). - New features: - Support for Bokeh 3.1 and Panel 1.0 ([#5388](https://github.com/holoviz/holoviews/pull/5388), [#5620](https://github.com/holoviz/holoviews/pull/5620), [#5640](https://github.com/holoviz/holoviews/pull/5640), [#5679](https://github.com/holoviz/holoviews/pull/5679), [#5683](https://github.com/holoviz/holoviews/pull/5683), [#5692](https://github.com/holoviz/holoviews/pull/5692), [#5703](https://github.com/holoviz/holoviews/pull/5703)) @@ -259,7 +245,6 @@ Enhancements: - Add support for extra `Hovertool` variables in a Bokeh's `quadmesh` with 2D coordinates (with tests) ([#5638](https://github.com/holoviz/holoviews/pull/5638)) - Change `hv.Rectangles` to internally use Bokeh `Quad` and not `Rect` to support logarithmic axis in WebGL ([#5664](https://github.com/holoviz/holoviews/pull/5664), [#5702](https://github.com/holoviz/holoviews/pull/5702)) - Bug fixes: - Ensure `spatial_select` in non-zero indexed DataFrame is applied right ([#5625](https://github.com/holoviz/holoviews/pull/5625)) @@ -280,7 +265,6 @@ Compatibility: - Improve error message for categorical data when used with `datashade` ([#5643](https://github.com/holoviz/holoviews/pull/5643)) - Don't disable Jedi completion by default ([#5701](https://github.com/holoviz/holoviews/pull/5701)) - Documentation: - Fix an incorrect number stated regarding available axis types ([#5623](https://github.com/holoviz/holoviews/pull/5623)) @@ -288,16 +272,14 @@ Documentation: - Fix formatting on FAQ ([#5630](https://github.com/holoviz/holoviews/pull/5630)) - Fix anchor links ([#5677](https://github.com/holoviz/holoviews/pull/5677)) - Maintenance: - Use `clean-notebook`, `codespell`, and `ruff` in `pre-commit` ([#5594](https://github.com/holoviz/holoviews/pull/5594), [#5627](https://github.com/holoviz/holoviews/pull/5627), [#5653](https://github.com/holoviz/holoviews/pull/5653)) - General maintenance ([#5607](https://github.com/holoviz/holoviews/pull/5607), [#5611](https://github.com/holoviz/holoviews/pull/5611), [#5612](https://github.com/holoviz/holoviews/pull/5612), [#5649](https://github.com/holoviz/holoviews/pull/5649)) - Known issues: -- `BoxEditTool` is not yet supported with the new internals of `hv.Rectangle`. +- `BoxEditTool` is not yet supported with the new internals of `hv.Rectangle`. Removals: @@ -305,15 +287,13 @@ Removals: - Remove deprecated tile sources ([#5654](https://github.com/holoviz/holoviews/pull/5654)) - Removed support for `apply_groups` for old option groups signature ([#5497](https://github.com/holoviz/holoviews/pull/5497)) +# Version 1.15.4 -Version 1.15.4 -============== **January 16, 2023** This release contains a small number of enhancements and important bug fixes. Many thanks to our new contributors @mmorys, @jj-github-jj, and @sandhujasmine, but also our returning contributors @droumis, @jlstevens, @MarcSkovMadsen, @maximlt, @philippjfr, @stanwest, and @Hoxbro. - Enhancements: - Make lasso select mask values using a Dask-compatible method ([#5568](https://github.com/holoviz/holoviews/pull/5568)) @@ -353,9 +333,8 @@ Maintenance: - Update binder link and dependency pinning ([#5583](https://github.com/holoviz/holoviews/pull/5583)) - Update copyright to only contain start year ([#5580](https://github.com/holoviz/holoviews/pull/5580)) +# Version 1.15.3 -Version 1.15.3 -============== **December 6, 2022** This release contains a small number of important bug fixes and @@ -364,25 +343,25 @@ adds support for Python 3.11. Many thanks to our maintainers Bug Fixes: - - Fix for empty opts warning and incorrect clearing semantics - ([#5496](https://github.com/holoviz/holoviews/pull/5496)) - - Fix potential race condition in the Options system - ([#5535](https://github.com/holoviz/holoviews/pull/5535)) +- Fix for empty opts warning and incorrect clearing semantics + ([#5496](https://github.com/holoviz/holoviews/pull/5496)) +- Fix potential race condition in the Options system + ([#5535](https://github.com/holoviz/holoviews/pull/5535)) Enhancements: - - Add support to Python 3.11 - ([#5513](https://github.com/holoviz/holoviews/pull/5513)) - - Cleanup the top `__init__` module - ([#5516](https://github.com/holoviz/holoviews/pull/5516)) +- Add support to Python 3.11 + ([#5513](https://github.com/holoviz/holoviews/pull/5513)) +- Cleanup the top `__init__` module + ([#5516](https://github.com/holoviz/holoviews/pull/5516)) Documentation: - - Fixes to release notes and CHANGELOG - ([#5506](https://github.com/holoviz/holoviews/pull/5506)) +- Fixes to release notes and CHANGELOG + ([#5506](https://github.com/holoviz/holoviews/pull/5506)) + +# Version 1.15.2 -Version 1.15.2 -============== **November 3, 2022** This release contains a small number of important bug fixes. Many thanks @@ -419,8 +398,8 @@ be deprecated in future. - Upgrade warning for invalid dataframe column names ([#5472](https://github.com/holoviz/holoviews/pull/5472)) -Version 1.15.1 -============== +# Version 1.15.1 + **October 4, 2022** This release contains a small number of important bug fixes. Many thanks @@ -447,7 +426,7 @@ Enhancements: ([#5455](https://github.com/holoviz/holoviews/pull/5455)) - Add pre-commit hooks to CI actions and fixes to pytest configuration ([#5385](https://github.com/holoviz/holoviews/pull/5385), - [#5440](https://github.com/holoviz/holoviews/pull/5440)) + [#5440](https://github.com/holoviz/holoviews/pull/5440)) Bug Fixes: @@ -472,10 +451,10 @@ Bug Fixes: - Many thanks to @Hoxbro for many miscellaneous plotting fixes, including fixes to plotting of `BoxWhisker`, `VectorField` elements ([#5397](https://github.com/holoviz/holoviews/pull/5397), - [#5450](https://github.com/holoviz/holoviews/pull/5450), - [#5400](https://github.com/holoviz/holoviews/pull/5400), - [#5409](https://github.com/holoviz/holoviews/pull/5409), - [#5460](https://github.com/holoviz/holoviews/pull/5460))) + [#5450](https://github.com/holoviz/holoviews/pull/5450), + [#5400](https://github.com/holoviz/holoviews/pull/5400), + [#5409](https://github.com/holoviz/holoviews/pull/5409), + [#5460](https://github.com/holoviz/holoviews/pull/5460))) - Fixes to documentation building GitHub Action ([#5320](https://github.com/holoviz/holoviews/pull/5456), ([#5320](https://github.com/holoviz/holoviews/pull/5467))) @@ -500,8 +479,8 @@ issuing a `DeprecationWarning` that should not be visible to users. - Issue DeprecationWarning for invalid DataFrame column types ([#5457](https://github.com/holoviz/holoviews/pull/5457)) -Version 1.15.0 -============== +# Version 1.15.0 + **July 6, 2022** This is a major release with a large number of new features and bug @@ -552,7 +531,6 @@ The following new features have been added to the datashader support in HoloViews, mainly focused on Datashader's new support for antialiasing lines as well as the new `rescale_discrete_levels` colormapping option. - - Add automatic categorical legend for datashaded plots ([#4806](https://github.com/holoviz/holoviews/pull/4806)) - Implement `line_width` support when rasterizing spatialpandas paths @@ -576,59 +554,59 @@ New features for the Bokeh plotting backend: - Add `legend_labels` option to allow overriding legend labels ([#5342](https://github.com/holoviz/holoviews/pull/5342)) - Updated sankey algorithm to `d3-sankey-v0.12.3` - ([#4707](https://github.com/holoviz/holoviews/pull/4707)) + ([#4707](https://github.com/holoviz/holoviews/pull/4707)) Other enhancements: - Optimize and clean up options system - ([#4954](https://github.com/holoviz/holoviews/pull/4954)) + ([#4954](https://github.com/holoviz/holoviews/pull/4954)) - Optimize lasso selection by applying box-select first - ([#5061](https://github.com/holoviz/holoviews/pull/5061)) - https://github.com/holoviz/holoviews/pull/5061 + ([#5061](https://github.com/holoviz/holoviews/pull/5061)) + https://github.com/holoviz/holoviews/pull/5061 - Support ibis-framework version 3 - ([#5292](https://github.com/holoviz/holoviews/pull/5292)) + ([#5292](https://github.com/holoviz/holoviews/pull/5292)) - Add `OpenTopoMap` as a tile source - ([#5052](https://github.com/holoviz/holoviews/pull/5052)) + ([#5052](https://github.com/holoviz/holoviews/pull/5052)) - Show all histograms of an `Overlay` -([#5031](https://github.com/holoviz/holoviews/pull/5031)) + ([#5031](https://github.com/holoviz/holoviews/pull/5031)) Bug fixes: - Fix batch watching and linking of parameters in Params stream - ([#4960](https://github.com/holoviz/holoviews/pull/4960), + ([#4960](https://github.com/holoviz/holoviews/pull/4960), [#4956](https://github.com/holoviz/holoviews/pull/4956)) - Ensure `Plot.refresh` is dispatched immediately if possible - ([#5348](https://github.com/holoviz/holoviews/pull/5348)) + ([#5348](https://github.com/holoviz/holoviews/pull/5348)) - Fix datashader empty overlay aggregation - ([#5334](https://github.com/holoviz/holoviews/pull/5334)) + ([#5334](https://github.com/holoviz/holoviews/pull/5334)) - Fixed missing handling of nodata for count aggregator with column - ([#4951](https://github.com/holoviz/holoviews/pull/4951)) + ([#4951](https://github.com/holoviz/holoviews/pull/4951)) - Handle `pd.NA` as missing data in dtype=object column - ([#5323](https://github.com/holoviz/holoviews/pull/5323)) + ([#5323](https://github.com/holoviz/holoviews/pull/5323)) - Forward `DynamicMap.hist` dimension parameter to histogram creation - ([#5037](https://github.com/holoviz/holoviews/pull/5037)) + ([#5037](https://github.com/holoviz/holoviews/pull/5037)) - Remove numpy pin from examples - ([#5285](https://github.com/holoviz/holoviews/pull/5285)) + ([#5285](https://github.com/holoviz/holoviews/pull/5285)) - Fix vmin/vmax deprecation on matplotlib HeatMapPlot - ([#5300](https://github.com/holoviz/holoviews/pull/5300)) + ([#5300](https://github.com/holoviz/holoviews/pull/5300)) - Don't skip each renderer's `load_nb call` when multiple extension - calls are made in a single cell - ([#5302](https://github.com/holoviz/holoviews/pull/5302)) + calls are made in a single cell + ([#5302](https://github.com/holoviz/holoviews/pull/5302)) - Set plotly range correctly for log axis - ([#5272](https://github.com/holoviz/holoviews/pull/5272)) + ([#5272](https://github.com/holoviz/holoviews/pull/5272)) - Sanitize uses of `contextlib.contextmanager` - ([#5018](https://github.com/holoviz/holoviews/pull/5018)) + ([#5018](https://github.com/holoviz/holoviews/pull/5018)) - Ensure `overlay_aggregate` is not applied for anti-aliased lines - ([#5266](https://github.com/holoviz/holoviews/pull/5266)) + ([#5266](https://github.com/holoviz/holoviews/pull/5266)) - Switch to using bokeh `rangesupdate` event for `Range` streams - ([#5265](https://github.com/holoviz/holoviews/pull/5265)) + ([#5265](https://github.com/holoviz/holoviews/pull/5265)) - Fixes for bokeh `Callbacks` - ([#5040](https://github.com/holoviz/holoviews/pull/5040)) + ([#5040](https://github.com/holoviz/holoviews/pull/5040)) - Fix for attribute error in matplotlib `CompositePlot` - ([#4969](https://github.com/holoviz/holoviews/pull/4969)) + ([#4969](https://github.com/holoviz/holoviews/pull/4969)) - Silenced inappropriate deprecation warnings and updated deprecation settings in options system - ([#5345](https://github.com/holoviz/holoviews/pull/5345), + ([#5345](https://github.com/holoviz/holoviews/pull/5345), [#5346](https://github.com/holoviz/holoviews/pull/5346)) Documentation: @@ -636,23 +614,23 @@ Documentation: The following improvements to the documentation have been made: - Fix `hv.help` when pattern is set - ([#5330](https://github.com/holoviz/holoviews/pull/5330)) + ([#5330](https://github.com/holoviz/holoviews/pull/5330)) - Added release dates to changelog and releases - ([#5027](https://github.com/holoviz/holoviews/pull/5027), + ([#5027](https://github.com/holoviz/holoviews/pull/5027), [#5035](https://github.com/holoviz/holoviews/pull/5035)) - Removed unneeded list from dynamic map example - ([#4953](https://github.com/holoviz/holoviews/pull/4953)) + ([#4953](https://github.com/holoviz/holoviews/pull/4953)) - Added FAQ about sharing only a single axis - ([#5278](https://github.com/holoviz/holoviews/pull/5278)) + ([#5278](https://github.com/holoviz/holoviews/pull/5278)) - Miscellaneous fixes to Heatmap reference notebook and Continuous Coordinates user guide - ([#5262](https://github.com/holoviz/holoviews/pull/5262)) + ([#5262](https://github.com/holoviz/holoviews/pull/5262)) - Added example of multiple RGB images as glyphs - ([#5172](https://github.com/holoviz/holoviews/pull/5172)) + ([#5172](https://github.com/holoviz/holoviews/pull/5172)) - Trim trailing whitespaces - ([#5019](https://github.com/holoviz/holoviews/pull/5019)) + ([#5019](https://github.com/holoviz/holoviews/pull/5019)) - Update outdated IOAM references - ([#4985](https://github.com/holoviz/holoviews/pull/4985)) + ([#4985](https://github.com/holoviz/holoviews/pull/4985)) Testing infrastructure: @@ -660,15 +638,14 @@ Many thanks to @maximlt for his work maintaining and fixing the testing infrastructure across too many PRs to list here. - Switch to pytest - ([#4949](https://github.com/holoviz/holoviews/pull/4949)) + ([#4949](https://github.com/holoviz/holoviews/pull/4949)) - Test suite clean up and fix for the pip build - ([#5326](https://github.com/holoviz/holoviews/pull/5326)) + ([#5326](https://github.com/holoviz/holoviews/pull/5326)) - Test updates following release of datashader 0.14.1 - ([#5344](https://github.com/holoviz/holoviews/pull/5344)) + ([#5344](https://github.com/holoviz/holoviews/pull/5344)) +# Version 1.14.9 -Version 1.14.9 -============== **May 6, 2022** This release contains a small number of important bug fixes as well as @@ -682,12 +659,12 @@ Enhancements: JupyterLab when no logo is used and a check to avoid loading unnecessary JavaScript. ([#5216](https://github.com/holoviz/holoviews/pull/5216), - [#5249](https://github.com/holoviz/holoviews/pull/5249)) + [#5249](https://github.com/holoviz/holoviews/pull/5249)) - Add support for setting antialiased line_width on datashader line aggregation as well as pixel_ratio setting ([#5264](https://github.com/holoviz/holoviews/pull/5264), [#5288](https://github.com/holoviz/holoviews/pull/5288)) -- Added options to customize hover line_(width|join|cap|dash) properties +- Added options to customize hover line\_(width|join|cap|dash) properties ([#5211](https://github.com/holoviz/holoviews/pull/5211)) - Restored Python 2 compatibility that lapsed due to lack of CI testing since 1.14.3. This is expected to be the last release with Python 2 support. @@ -715,9 +692,8 @@ Documentation: ([#5267](https://github.com/holoviz/holoviews/pull/5267), [#5290](https://github.com/holoviz/holoviews/pull/5290)) +# Version 1.14.8 -Version 1.14.8 -============== **February 15, 2022** This release contains a small number of important bug fixes as well as @@ -750,8 +726,8 @@ Bug fixes: [#5201](https://github.com/holoviz/holoviews/pull/5201), [#5206](https://github.com/holoviz/holoviews/pull/5206)) -Version 1.14.7 -============== +# Version 1.14.7 + **December 16, 2021** This release contains a small number of important bug fixes. Many thanks @@ -805,16 +781,16 @@ Bug fixes: - Fix for Contours consistent of empty and nonempty paths ([#5162](https://github.com/holoviz/holoviews/pull/5162)) - Fixed docs: - * Fix `fig_bounds` description in Plotting_with_Matplotlib.ipynb - ([#4983](https://github.com/holoviz/holoviews/pull/4983)) - * Fix broken link in Gridded user guide - ([#5098](https://github.com/holoviz/holoviews/pull/5098)) + - Fix `fig_bounds` description in Plotting_with_Matplotlib.ipynb + ([#4983](https://github.com/holoviz/holoviews/pull/4983)) + - Fix broken link in Gridded user guide + ([#5098](https://github.com/holoviz/holoviews/pull/5098)) - Improved docs: - * Switch to the Pydata Sphinx theme - ([#5163](https://github.com/holoviz/holoviews/pull/5163)) + - Switch to the Pydata Sphinx theme + ([#5163](https://github.com/holoviz/holoviews/pull/5163)) + +# Version 1.14.6 -Version 1.14.6 -============== **September 16, 2021** This is a hotfix release with a number of important bug fixes. Most @@ -836,7 +812,7 @@ Bug fixes: - Improvements to linked selections including support for linked selection lasso for cudf and improved warnings ([#5044](https://github.com/holoviz/holoviews/pull/5044), - [#5051](https://github.com/holoviz/holoviews/pull/5051)) + [#5051](https://github.com/holoviz/holoviews/pull/5051)) - Respect apply_ranges at range computation level ([#5081](https://github.com/holoviz/holoviews/pull/5081)) - Keep ordering of kdim when stacking Areas @@ -844,8 +820,8 @@ Bug fixes: - Apply hover postprocessor on updates ([#5039](https://github.com/holoviz/holoviews/pull/5039)) -Version 1.14.5 -============== +# Version 1.14.5 + **July 16, 2021** This is a hotfix release with a number of important bug fixes. Most @@ -863,9 +839,8 @@ Bug fixes: [#5001](https://github.com/holoviz/holoviews/pull/5001), [#5005](https://github.com/holoviz/holoviews/pull/5005)) +# Version 1.14.4 -Version 1.14.4 -============== **May 18, 2021** This release primarily focuses on a number of bug fixes. Many thanks to @@ -893,7 +868,7 @@ Bug fixes: ([#4911](https://github.com/holoviz/holoviews/pull/4911)) - Fix bug using dimensions with label on `Bars` ([#4929](https://github.com/holoviz/holoviews/pull/4929)) -- Do not reverse colormaps with '_r' suffix a second time +- Do not reverse colormaps with '\_r' suffix a second time ([#4931](https://github.com/holoviz/holoviews/pull/4931)) - Fix remapping of `Params` stream parameter names ([#4932](https://github.com/holoviz/holoviews/pull/4932)) @@ -922,8 +897,8 @@ unless `hv.config.raise_deprecated_tilesource_exception` is set to available. Attempting to use these tile sources will result in a deprecation warning. -Version 1.14.3 -============== +# Version 1.14.3 + **April 8, 2021** This release contains a small number of bug fixes, enhancements and @@ -953,8 +928,8 @@ Compatibility: - Support matplotlib versions >=3.4 ([#4878](https://github.com/holoviz/holoviews/pull/4878)) -Version 1.14.2 -============== +# Version 1.14.2 + **March 2, 2021** This release adds support for Bokeh 2.3, introduces a number of minor @@ -976,8 +951,8 @@ Enhancements: [#4809](https://github.com/holoviz/holoviews/pull/4809)) - Supporting dictionary streams parameter in DynamicMaps and operations ([#4787](https://github.com/holoviz/holoviews/pull/4787), - [#4818](https://github.com/holoviz/holoviews/pull/4818), - [#4822](https://github.com/holoviz/holoviews/pull/4822)) + [#4818](https://github.com/holoviz/holoviews/pull/4818), + [#4822](https://github.com/holoviz/holoviews/pull/4822)) - Support spatialpandas DaskGeoDataFrame ([#4792](https://github.com/holoviz/holoviews/pull/4792)) - Disable zoom on axis for geographic plots @@ -1023,8 +998,8 @@ Documentation: [#4844](https://github.com/holoviz/holoviews/pull/4844), [#4811](https://github.com/holoviz/holoviews/pull/4811)) -Version 1.14.1 -============== +# Version 1.14.1 + **December 28, 2020** This release contains a small number of bug fixes addressing @@ -1048,8 +1023,8 @@ Documentation: - Warn about disabled interactive features on website ([#4762](https://github.com/holoviz/holoviews/pull/4762)) -Version 1.14.0 -============== +# Version 1.14.0 + **December 1, 2020** This release brings a number of major features including a new @@ -1061,7 +1036,7 @@ suggestions. Specifically, we would like to thank @philippjfr, @jonmmease, and @tonyfast for their work on the IbisInterface and @jonmmease for improving Plotly support, as well as @kcpevey, @Hoxbro, @marckassay, @mcepl, and @ceball for various other enhancements, -improvements to documentation and testing infrastructure. In +improvements to documentation and testing infrastructure. In addition, thanks to the maintainers @jbednar, @jlstevens and @philippjfr for contributing to this release. This version includes a large number of new features, enhancements, and bug fixes. @@ -1154,8 +1129,8 @@ Compatibility: set to 'kbc_r' for consistency and can be set back to the old value of 'RdYlBu_r' via `hv.config.default_heatmap_cmap`. -Version 1.13.5 -============== +# Version 1.13.5 + **October 23, 2020** This version contains numerous bug fixes and a number of enhancements. @@ -1197,8 +1172,8 @@ Documentation: - Various documentation fixes ([#4628](https://github.com/holoviz/holoviews/pull/4628)) -Version 1.13.4 -============== +# Version 1.13.4 + **September 8, 2020** This version fixes a large number of bugs particularly relating to @@ -1269,8 +1244,8 @@ Enhancements: - Allow rendering to pgf in matplotlib ([#4577](https://github.com/holoviz/holoviews/pull/4577)) -Version 1.13.3 -============== +# Version 1.13.3 + **June 23, 2020** This version introduces a number of enhancements of existing @@ -1339,8 +1314,8 @@ Bug fixes: - Handle missing categories on split Violin plot ([#4482](https://github.com/holoviz/holoviews/pull/4482)) -Version 1.13.2 -============== +# Version 1.13.2 + **April 2, 2020** This is a minor patch release fixing a number of regressions @@ -1366,8 +1341,8 @@ Bug fixes: - Fix handling of document in server mode ([#4355](https://github.com/holoviz/holoviews/pull/4355)) -Version 1.13.1 -============== +# Version 1.13.1 + **March 25, 2020** This is a minor patch release to fix issues compatibility with the @@ -1412,8 +1387,8 @@ Documentation: - Update API reference manual ([#4316](https://github.com/holoviz/holoviews/pull/4316)) -Version 1.13.0 -============== +# Version 1.13.0 + **March 20, 2020** This release is packed full of features and includes a general @@ -1424,7 +1399,7 @@ suggestions. Specifically we would like to thank @poplarShift, @jonmease, @flothesof, @julioasotodv, @ltalirz, @DancingQuanta, @ahuang, @kcpevey, @Jacob-Barkhak, @nluetts, @harmbuisman, @ceball, @mgsnuno, @srp3003, @jsignell as well as the maintainers @jbednar, @jlstevens and -@philippjfr for contributing to this release. This version includes the +@philippjfr for contributing to this release. This version includes the addition of a large number of features, enhancements and bug fixes: Major features: @@ -1530,7 +1505,6 @@ Bug fixes: [#3027](https://github.com/holoviz/holoviews/pull/3027), [#3777](https://github.com/holoviz/holoviews/pull/3777)) - Library compatibility: - Better support for Pandas 1.0 @@ -1563,9 +1537,8 @@ Migration notes: - `hv.output` `filename` argument is deprecated; use `hv.save` instead ([#3985](https://github.com/holoviz/holoviews/pull/3985)) +# Version 1.12.7 -Version 1.12.7 -============== **November 22, 2019** This a very minor hotfix release fixing an important bug related to @@ -1583,9 +1556,8 @@ Bug fixes: - Fixed shared_axes/axiswise regression ([#4097](https://github.com/holoviz/holoviews/pull/4097)) +# Version 1.12.6 -Version 1.12.6 -============== **October 8, 2019** This is a minor release containing a large number of bug fixes thanks @@ -1601,7 +1573,7 @@ Enhancements: ([#3952](https://github.com/pyviz/holoviews/issues/3952)) - Add support for dependent functions in dynamic operations ([#3975](https://github.com/pyviz/holoviews/issues/3975), - [#3980](https://github.com/pyviz/holoviews/issues/3980)) + [#3980](https://github.com/pyviz/holoviews/issues/3980)) - Add support for fast QuadMesh rasterization with datashader >= 0.8 ([#4020](https://github.com/pyviz/holoviews/issues/4020)) - Allow passing Panel widgets as operation parameter @@ -1619,7 +1591,7 @@ Bug fixes: ([#3981](https://github.com/pyviz/holoviews/issues/3981)) - Ensure .apply work correctly on HoloMaps ([#3989](https://github.com/pyviz/holoviews/issues/3989), - [#4025](https://github.com/pyviz/holoviews/issues/4025)) + [#4025](https://github.com/pyviz/holoviews/issues/4025)) - Ensure Grid axes are always aligned in bokeh ([#3916](https://github.com/pyviz/holoviews/issues/3916)) - Fix hover tool on Image and Raster plots with inverted axis @@ -1650,8 +1622,8 @@ Compatibility: - Ensure compatibility with new legend options in bokeh 1.4.0 ([#4036](https://github.com/pyviz/holoviews/issues/4036)) -Version 1.12.5 -============== +# Version 1.12.5 + **August 14, 2019** This is a very minor bug fix release ensuring compatibility with recent @@ -1665,8 +1637,8 @@ Compatibility: - Fix for rendering Scatter3D with matplotlib 3.1 ([#3898](https://github.com/pyviz/holoviews/issues/3898)) -Version 1.12.4 -============== +# Version 1.12.4 + **August 4, 2019** This is a minor release with a number of bug and compatibility fixes @@ -1734,8 +1706,8 @@ Backwards incompatible changes: box-whisker plots was fixed resulting in different results going forward. -Version 1.12.3 -============== +# Version 1.12.3 + **May 20, 2019** This is a minor release primarily focused on a number of important bug @@ -1769,8 +1741,8 @@ Bug fixes: - Ensure that param streams handle subobjects ([#3728](https://github.com/pyviz/holoviews/pull/3728)) -Version 1.12.2 -============== +# Version 1.12.2 + **May 1, 2019** This is a minor release with a number of important bug fixes and a @@ -1807,7 +1779,7 @@ Bug fixes: ([#3564](https://github.com/pyviz/holoviews/pull/3564)) - Fixed handling of datetimes on Path plots ([#3464](https://github.com/pyviz/holoviews/pull/3464), - [#3662](https://github.com/pyviz/holoviews/pull/3662)) + [#3662](https://github.com/pyviz/holoviews/pull/3662)) - Ensure that resampling operations do not cause event loops ([#3614](https://github.com/pyviz/holoviews/issues/3614)) @@ -1816,8 +1788,8 @@ Backward compatibility: - Added color cycles on Violin and BoxWhisker elements due to earlier regression ([#3592](https://github.com/pyviz/holoviews/pull/3592)) -Version 1.12.1 -============== +# Version 1.12.1 + **April 10, 2019** This is a minor release that pins to the newly released Bokeh 1.1 and @@ -1828,8 +1800,8 @@ Enhancements: - Add support for passing in parameter instances as streams ([#3616](https://github.com/pyviz/holoviews/pull/3616)) -Version 1.12.0 -============== +# Version 1.12.0 + **April 2, 2019** This release provides a number of exciting new features as well as a set @@ -1870,19 +1842,18 @@ Bug fixes: ([#3572](https://github.com/pyviz/holoviews/pull/3572), [#3590](https://github.com/pyviz/holoviews/pull/3590)) - Other miscellaneous fixes -([#3530](https://github.com/pyviz/holoviews/pull/3530), -[#3536](https://github.com/pyviz/holoviews/pull/3536), -[#3546](https://github.com/pyviz/holoviews/pull/3546), -[#3560](https://github.com/pyviz/holoviews/pull/3560), -[#3571](https://github.com/pyviz/holoviews/pull/3571), -[#3580](https://github.com/pyviz/holoviews/pull/3580), -[#3584](https://github.com/pyviz/holoviews/pull/3584), -[#3585](https://github.com/pyviz/holoviews/pull/3585), -[#3594](https://github.com/pyviz/holoviews/pull/3594)) - - -Version 1.11.3 -============== + ([#3530](https://github.com/pyviz/holoviews/pull/3530), + [#3536](https://github.com/pyviz/holoviews/pull/3536), + [#3546](https://github.com/pyviz/holoviews/pull/3546), + [#3560](https://github.com/pyviz/holoviews/pull/3560), + [#3571](https://github.com/pyviz/holoviews/pull/3571), + [#3580](https://github.com/pyviz/holoviews/pull/3580), + [#3584](https://github.com/pyviz/holoviews/pull/3584), + [#3585](https://github.com/pyviz/holoviews/pull/3585), + [#3594](https://github.com/pyviz/holoviews/pull/3594)) + +# Version 1.11.3 + **February 25, 2019** This is the last micro-release in the 1.11 series providing a number @@ -1926,8 +1897,8 @@ Enhancements: - Added Tiles element from GeoViews ([#3515](https://github.com/pyviz/holoviews/pull/3515)) -Version 1.11.2 -============== +# Version 1.11.2 + **January 28, 2019** This is a minor bug fix release with a number of small but important @@ -1951,9 +1922,8 @@ Enhancements: - Improvements for handling graph attributes in Graph.from_networkx ([#3432](https://github.com/pyviz/holoviews/pull/3432)) +# Version 1.11.1 -Version 1.11.1 -============== **January 17, 2019** This is a minor bug fix release with a number of important bug fixes, @@ -1992,11 +1962,10 @@ Documentation: - Completed updates from .options to .opts API in the documentation ([#3364]((https://github.com/pyviz/holoviews/pull/3364), - [#3367]((https://github.com/pyviz/holoviews/pull/3367)) + [#3367](<(https://github.com/pyviz/holoviews/pull/3367)>) +# Version 1.11.0 -Version 1.11.0 -============== **December 24, 2018** This is a major release containing a large number of features and API @@ -2097,12 +2066,10 @@ Deprecations: marked for deprecation ([#3128](https://github.com/pyviz/holoviews/pull/3128)) +# Version 1.10.8 -Version 1.10.8 -============== **October 29, 2018** - This a likely the last hotfix release in the 1.10.x series containing fixes for compatibility with bokeh 1.0 and matplotlib 3.0. It also contains a wide array of fixes contributed and reported by users: @@ -2174,8 +2141,8 @@ Documentation: [#2959](https://github.com/pyviz/holoviews/pull/2959), [#3025](https://github.com/pyviz/holoviews/pull/3025)) -Version 1.10.7 -============== +# Version 1.10.7 + **July 8, 2018** This a very minor hotfix release mostly containing fixes for datashader @@ -2193,9 +2160,8 @@ Fixes: - Fixed ticks on log Colorbar if low value <= 0 ([#2865](https://github.com/pyviz/holoviews/pull/2865)) +# Version 1.10.6 -Version 1.10.6 -============== **June 29, 2018** This another minor bug fix release in the 1.10 series and likely the @@ -2226,9 +2192,8 @@ Fixes: zero range ([#2829](https://github.com/pyviz/holoviews/pull/2829), [#2842](https://github.com/pyviz/holoviews/pull/2842)) +# Version 1.10.5 -Version 1.10.5 -============== **June 5, 2018** This is a minor bug fix release containing a mixture of small @@ -2246,7 +2211,7 @@ Enhancements: ([#2719](https://github.com/pyviz/holoviews/pull/2719)) - Legends on NdOverlay containing overlays now supported ([#2755](https://github.com/pyviz/holoviews/pull/2755)) -- Dataframe indexes may now be referenced in ``.to`` conversion +- Dataframe indexes may now be referenced in `.to` conversion ([#2739](https://github.com/pyviz/holoviews/pull/2739)) - Reindexing a gridded Dataset without arguments now behaves consistently with NdMapping types and drops scalar dimensions making @@ -2272,9 +2237,8 @@ Compatibility: [#2725](https://github.com/pyviz/holoviews/pull/2725), [#2767](https://github.com/pyviz/holoviews/pull/2767)) +# Version 1.10.4 -Version 1.10.4 -============== **May 14, 2018** This is a minor bug fix release including a number of crucial fixes @@ -2294,8 +2258,8 @@ Fixes: - Fixed bug slicing xarray with tuples ([#2674](https://github.com/pyviz/holoviews/pull/2674)) -Version 1.10.3 -============== +# Version 1.10.3 + **May 8, 2018** This is a minor bug fix release including a number of crucial fixes @@ -2309,14 +2273,14 @@ Enhancement: Fixes: -- Fix for ``labelled`` plot option +- Fix for `labelled` plot option ([#2643](https://github.com/pyviz/holoviews/pull/2643)) - Optimized initialization of dynamic plots specifying a large parameter space ([#2646](https://github.com/pyviz/holoviews/pull/2646)) - Fixed unicode and reversed axis slicing issues in XArrayInterface ([#2658](https://github.com/pyviz/holoviews/issues/2658), - [#2653](https://github.com/pyviz/holoviews/pull/2653)) + [#2653](https://github.com/pyviz/holoviews/pull/2653)) - Fixed widget sorting issues when applying dynamic groupby ([#2641](https://github.com/pyviz/holoviews/issues/2641)) @@ -2329,8 +2293,8 @@ API: keys for consistency ([#2650](https://github.com/pyviz/holoviews/issues/2650)) -Version 1.10.2 -============== +# Version 1.10.2 + **April 30, 2018** This is a minor bug fix release with a number of small fixes for @@ -2358,13 +2322,12 @@ Fixes: Deprecations: -- BoxWhisker and Bars ``width`` bokeh style options and Arrow - matplotlib ``fontsize`` option are deprecated +- BoxWhisker and Bars `width` bokeh style options and Arrow + matplotlib `fontsize` option are deprecated ([#2411](https://github.com/pyviz/holoviews/issues/2411)) +# Version 1.10.1 -Version 1.10.1 -============== **April 20, 2018** This is a minor bug fix release with a number of fixes for regressions @@ -2381,9 +2344,8 @@ Fixes: - Fixed Selection1D stream on bokeh server after changes in bokeh 0.12.15 ([#2586](https://github.com/pyviz/holoviews/pull/2586)) +# Version 1.10.0 -Version 1.10.0 -============== **April 17, 2018** This is a major release with a large number of new features and bug @@ -2392,7 +2354,6 @@ numerous users who filed bug reports, tested development versions, and contributed a number of new features and bug fixes, including special thanks to @mansenfranzen, @ea42gh, @drs251 and @jakirkham. - JupyterLab support: - Full compatibility with JupyterLab when installing the @@ -2401,42 +2362,42 @@ JupyterLab support: New components: -- Added [``Sankey`` element](http://holoviews.org/reference/elements/bokeh/Sankey.html) +- Added [`Sankey` element](http://holoviews.org/reference/elements/bokeh/Sankey.html) to plot directed flow graphs ([#1123](https://github.com/pyviz/holoviews/issues/1123)) -- Added [``TriMesh`` element](http://holoviews.org/reference/elements/bokeh/TriMesh.html) +- Added [`TriMesh` element](http://holoviews.org/reference/elements/bokeh/TriMesh.html) and datashading operation to plot small and large irregular meshes ([#2143](https://github.com/pyviz/holoviews/issues/2143)) -- Added a [``Chord`` element](http://holoviews.org/reference/elements/bokeh/Chord.html) +- Added a [`Chord` element](http://holoviews.org/reference/elements/bokeh/Chord.html) to draw flow graphs between different nodes ([#2137](https://github.com/pyviz/holoviews/issues/2137), [#2143](https://github.com/pyviz/holoviews/pull/2143)) -- Added [``HexTiles`` element](http://holoviews.org/reference/elements/bokeh/HexTiles.html) +- Added [`HexTiles` element](http://holoviews.org/reference/elements/bokeh/HexTiles.html) to plot data binned into a hexagonal grid ([#1141](https://github.com/pyviz/holoviews/issues/1141)) -- Added [``Labels`` element](http://holoviews.org/reference/elements/bokeh/Labels.html) +- Added [`Labels` element](http://holoviews.org/reference/elements/bokeh/Labels.html) to plot a large number of text labels at once (as data rather than as annotations) ([#1837](https://github.com/pyviz/holoviews/issues/1837)) -- Added [``Div`` element](http://holoviews.org/reference/elements/bokeh/Div.html) +- Added [`Div` element](http://holoviews.org/reference/elements/bokeh/Div.html) to add arbitrary HTML elements to a Bokeh layout ([#2221](https://github.com/pyviz/holoviews/issues/2221)) - Added - [``PointDraw``](http://holoviews.org/reference/streams/bokeh/PointDraw.html), - [``PolyDraw``](http://holoviews.org/reference/streams/bokeh/PolyDraw.html), - [``BoxEdit``](http://holoviews.org/reference/streams/bokeh/BoxEdit.html), and - [``PolyEdit``](http://holoviews.org/reference/streams/bokeh/PolyEdit.html) + [`PointDraw`](http://holoviews.org/reference/streams/bokeh/PointDraw.html), + [`PolyDraw`](http://holoviews.org/reference/streams/bokeh/PolyDraw.html), + [`BoxEdit`](http://holoviews.org/reference/streams/bokeh/BoxEdit.html), and + [`PolyEdit`](http://holoviews.org/reference/streams/bokeh/PolyEdit.html) streams to allow drawing, editing, and annotating glyphs on a Bokeh plot, and syncing the resulting data to Python ([#2268](https://github.com/pyviz/holoviews/issues/2459)) Features: -- Added [radial ``HeatMap``](http://holoviews.org/reference/elements/bokeh/RadialHeatMap.html) +- Added [radial `HeatMap`](http://holoviews.org/reference/elements/bokeh/RadialHeatMap.html) option to allow plotting heatmaps with a cyclic x-axis ([#2139](https://github.com/pyviz/holoviews/pull/2139)) - All elements now support declaring bin edges as well as centers - allowing ``Histogram`` and ``QuadMesh`` to become first class - ``Dataset`` types + allowing `Histogram` and `QuadMesh` to become first class + `Dataset` types ([#547](https://github.com/pyviz/holoviews/issues/547)) - When using widgets, their initial or default value can now be set via the `Dimension.default` parameter @@ -2452,7 +2413,7 @@ Enhancements: - Improvements to exceptions ([#1127](https://github.com/pyviz/holoviews/issues/1127)) -- Toolbar position and merging (via a new ``merge_toolbar`` +- Toolbar position and merging (via a new `merge_toolbar` option) can now be controlled for Layout and Grid plots ([#1977](https://github.com/pyviz/holoviews/issues/1977)) - Bokeh themes can now be applied at the renderer level @@ -2460,8 +2421,8 @@ Enhancements: - Dataframe and Series index can now be referenced by name when constructing an element ([#2000](https://github.com/pyviz/holoviews/issues/2000)) -- Option-setting methods such as ``.opts``, ``.options`` and - ``hv.opts`` now allow specifying the backend instead of defaulting +- Option-setting methods such as `.opts`, `.options` and + `hv.opts` now allow specifying the backend instead of defaulting to the current backend ([#1801](https://github.com/pyviz/holoviews/issues/1801)) - Handled API changes in streamz 0.3.0 in Buffer stream @@ -2469,23 +2430,23 @@ Enhancements: - Supported GIF output on windows using new Matplotlib pillow animation support ([#385](https://github.com/pyviz/holoviews/issues/385)) -- Provided simplified interface to ``rasterize`` most element types +- Provided simplified interface to `rasterize` most element types using datashader ([#2465](https://github.com/pyviz/holoviews/pull/2465)) -- ``Bivariate`` element now support ``levels`` as a plot option +- `Bivariate` element now support `levels` as a plot option ([#2099](https://github.com/pyviz/holoviews/issues/2099)) -- ``NdLayout`` and ``GridSpace`` now consistently support ``*`` +- `NdLayout` and `GridSpace` now consistently support `*` overlay operation ([#2075](https://github.com/pyviz/holoviews/issues/2075)) - The Bokeh backend no longer has a hard dependency on Matplotlib ([#829](https://github.com/pyviz/holoviews/issues/829)) -- ``DynamicMap`` may now return (``Nd``)``Overlay`` with varying +- `DynamicMap` may now return (`Nd`)`Overlay` with varying number of elements ([#1388](https://github.com/pyviz/holoviews/issues/1388)) - In the notebook, deleting or re-executing a cell will now delete the plot and clean up any attached streams ([#2141](https://github.com/pyviz/holoviews/issues/2141)) -- Added ``color_levels`` plot option to set discrete number of levels +- Added `color_levels` plot option to set discrete number of levels during colormapping ([#2483](https://github.com/pyviz/holoviews/pull/2483)) - Expanded the [Large Data](http://holoviews.org/user_guide/Large_Data.html) @@ -2494,27 +2455,26 @@ Enhancements: Fixes: -- ``Layout`` and ``Overlay`` objects no longer create lower-case nodes +- `Layout` and `Overlay` objects no longer create lower-case nodes on attribute access ([#2331](https://github.com/pyviz/holoviews/pull/2331)) -- ``Dimension.step`` now correctly respects both integer and float +- `Dimension.step` now correctly respects both integer and float steps ([#1707](https://github.com/pyviz/holoviews/issues/1707)) - Fixed timezone issues when using linked streams on datetime axes ([#2459](https://github.com/pyviz/holoviews/issues/2459)) - Changes affecting backwards compatibility: - Image elements now expect and validate regular sampling ([#1869](https://github.com/pyviz/holoviews/issues/1869)); for genuinely irregularly sampled data QuadMesh should be used. -- Tabular elements will no longer default to use ``ArrayInterface``, +- Tabular elements will no longer default to use `ArrayInterface`, instead preferring pandas and dictionary data formats ([#1236](https://github.com/pyviz/holoviews/issues/1236)) -- ``Cycle``/``Palette`` values are no longer zipped together; instead +- `Cycle`/`Palette` values are no longer zipped together; instead they now cycle independently ([#2333](https://github.com/pyviz/holoviews/pull/2333)) -- The default color ``Cycle`` was expanded to provide more unique colors +- The default color `Cycle` was expanded to provide more unique colors ([#2483](https://github.com/pyviz/holoviews/pull/2483)) - Categorical colormapping was made consistent across backends, changing the behavior of categorical Matplotlib colormaps @@ -2523,9 +2483,8 @@ Changes affecting backwards compatibility: single column is supplied no integer index column is added automatically ([#2522](https://github.com/pyviz/holoviews/pull/2522)) +# Version 1.9.5 -Version 1.9.5 -============= **March 2, 2018** This release includes a very small number of minor bugfixes and a new @@ -2533,37 +2492,35 @@ feature to simplify setting options in python: Enhancements: -- Added .options method for simplified options setting. - ([\#2306](https://github.com/pyviz/holoviews/pull/2306)) +- Added .options method for simplified options setting. + ([\#2306](https://github.com/pyviz/holoviews/pull/2306)) Fixes: -- Allow plotting bytes datausing the Bokeh backend in python3 - ([\#2357](https://github.com/pyviz/holoviews/pull/2357)) -- Allow .range to work on data with heterogeneous types in Python 3 - ([\#2345](https://github.com/pyviz/holoviews/pull/2345)) -- Fixed bug streaming data containing datetimes using bokeh>=0.12.14 - ([\#2383](https://github.com/pyviz/holoviews/pull/2383)) +- Allow plotting bytes datausing the Bokeh backend in python3 + ([\#2357](https://github.com/pyviz/holoviews/pull/2357)) +- Allow .range to work on data with heterogeneous types in Python 3 + ([\#2345](https://github.com/pyviz/holoviews/pull/2345)) +- Fixed bug streaming data containing datetimes using bokeh>=0.12.14 + ([\#2383](https://github.com/pyviz/holoviews/pull/2383)) +# Version 1.9.4 -Version 1.9.4 -============= **February 16, 2018** This release contains a small number of important bug fixes: -- Compatibility with recent versions of Dask and pandas - ([\#2329](https://github.com/pyviz/holoviews/pull/2329)) -- Fixed bug referencing columns containing non-alphanumeric characters - in Bokeh Tables ([\#2336](https://github.com/pyviz/holoviews/pull/2336)) -- Fixed issue in regrid operation - ([2337](https://github.com/pyviz/holoviews/pull/2337)) -- Fixed issue when using datetimes with datashader when processing - ranges ([\#2344](https://github.com/pyviz/holoviews/pull/2344)) +- Compatibility with recent versions of Dask and pandas + ([\#2329](https://github.com/pyviz/holoviews/pull/2329)) +- Fixed bug referencing columns containing non-alphanumeric characters + in Bokeh Tables ([\#2336](https://github.com/pyviz/holoviews/pull/2336)) +- Fixed issue in regrid operation + ([2337](https://github.com/pyviz/holoviews/pull/2337)) +- Fixed issue when using datetimes with datashader when processing + ranges ([\#2344](https://github.com/pyviz/holoviews/pull/2344)) +# Version 1.9.3 -Version 1.9.3 -============= **February 11, 2018** This release contains a number of important bug fixes and minor @@ -2574,53 +2531,51 @@ number of fixes and improvements to the documentation. Enhancements: -- Optimized rendering of stream based OverlayPlots - ([\#2253](https://github.com/pyviz/holoviews/pull/2253)) -- Added ``merge_toolbars`` and ``toolbar`` options to control - toolbars on ``Layout`` and Grid plots - ([\#2289](https://github.com/pyviz/holoviews/pull/2289)) -- Optimized rendering of ``VectorField`` - ([\#2314](https://github.com/pyviz/holoviews/pull/2289)) -- Improvements to documentation - ([\#2198](https://github.com/pyviz/holoviews/pull/2198), - [\#2220](https://github.com/pyviz/holoviews/pull/2220), - [\#2233](https://github.com/pyviz/holoviews/pull/2233), - [\#2235](https://github.com/pyviz/holoviews/pull/2235), - [\#2316](https://github.com/pyviz/holoviews/pull/2316)) -- Improved Bokeh ``Table`` formatting - ([\#2267](https://github.com/pyviz/holoviews/pull/2267)) -- Added support for handling datetime.date types - ([\#2267](https://github.com/pyviz/holoviews/pull/2267)) -- Add support for pre- and post-process hooks on operations - ([\#2246](https://github.com/pyviz/holoviews/pull/2246), - [\#2334](https://github.com/pyviz/holoviews/pull/2334)) +- Optimized rendering of stream based OverlayPlots + ([\#2253](https://github.com/pyviz/holoviews/pull/2253)) +- Added `merge_toolbars` and `toolbar` options to control + toolbars on `Layout` and Grid plots + ([\#2289](https://github.com/pyviz/holoviews/pull/2289)) +- Optimized rendering of `VectorField` + ([\#2314](https://github.com/pyviz/holoviews/pull/2289)) +- Improvements to documentation + ([\#2198](https://github.com/pyviz/holoviews/pull/2198), + [\#2220](https://github.com/pyviz/holoviews/pull/2220), + [\#2233](https://github.com/pyviz/holoviews/pull/2233), + [\#2235](https://github.com/pyviz/holoviews/pull/2235), + [\#2316](https://github.com/pyviz/holoviews/pull/2316)) +- Improved Bokeh `Table` formatting + ([\#2267](https://github.com/pyviz/holoviews/pull/2267)) +- Added support for handling datetime.date types + ([\#2267](https://github.com/pyviz/holoviews/pull/2267)) +- Add support for pre- and post-process hooks on operations + ([\#2246](https://github.com/pyviz/holoviews/pull/2246), + [\#2334](https://github.com/pyviz/holoviews/pull/2334)) Fixes: -- Fix for Bokeh server widgets - ([\#2218](https://github.com/pyviz/holoviews/pull/2218)) -- Fix using event based streams on Bokeh server - ([\#2239](https://github.com/pyviz/holoviews/pull/2239), - [\#2256](https://github.com/pyviz/holoviews/pull/2256)) -- Switched to drawing ``Distribution``, ``Area`` and ``Spread`` - using patch glyphs in Bokeh fixing legends - ([\#2225](https://github.com/pyviz/holoviews/pull/2225)) -- Fixed categorical coloring of ``Polygons``/``Path`` elements in - Matplotlib ([\#2259](https://github.com/pyviz/holoviews/pull/2259)) -- Fixed bug computing categorical datashader aggregates - ([\#2295](https://github.com/pyviz/holoviews/pull/2295)) -- Allow using ``Empty`` object in ``AdjointLayout`` - ([\#2275](https://github.com/pyviz/holoviews/pull/2275)) - +- Fix for Bokeh server widgets + ([\#2218](https://github.com/pyviz/holoviews/pull/2218)) +- Fix using event based streams on Bokeh server + ([\#2239](https://github.com/pyviz/holoviews/pull/2239), + [\#2256](https://github.com/pyviz/holoviews/pull/2256)) +- Switched to drawing `Distribution`, `Area` and `Spread` + using patch glyphs in Bokeh fixing legends + ([\#2225](https://github.com/pyviz/holoviews/pull/2225)) +- Fixed categorical coloring of `Polygons`/`Path` elements in + Matplotlib ([\#2259](https://github.com/pyviz/holoviews/pull/2259)) +- Fixed bug computing categorical datashader aggregates + ([\#2295](https://github.com/pyviz/holoviews/pull/2295)) +- Allow using `Empty` object in `AdjointLayout` + ([\#2275](https://github.com/pyviz/holoviews/pull/2275)) API Changes: -- Renamed ``Trisurface`` to ``TriSurface`` for future consistency - ([\#2219](https://github.com/pyviz/holoviews/pull/2219)) +- Renamed `Trisurface` to `TriSurface` for future consistency + ([\#2219](https://github.com/pyviz/holoviews/pull/2219)) +# Version 1.9.2 -Version 1.9.2 -============= **December 11, 2017** This release is a minor bug fix release patching various issues @@ -2628,34 +2583,33 @@ which were found in the 1.9.1 release. Enhancements: -- Improved the Graph element, optimizing the constructor - and adding support for defining a `edge_color_index` - ([\#2145](https://github.com/pyviz/holoviews/pull/2145)) -- Added support for adding jitter to Bokeh Scatter and Points plots - ([e56208](https://github.com/pyviz/holoviews/commit/e56208e1eb6e1e4af67b6a3ffbb5a925bfc37e14)) +- Improved the Graph element, optimizing the constructor + and adding support for defining a `edge_color_index` + ([\#2145](https://github.com/pyviz/holoviews/pull/2145)) +- Added support for adding jitter to Bokeh Scatter and Points plots + ([e56208](https://github.com/pyviz/holoviews/commit/e56208e1eb6e1e4af67b6a3ffbb5a925bfc37e14)) Fixes: -- Ensure dimensions, group and label are inherited when casting - Image to QuadMesh - ([\#2144](https://github.com/pyviz/holoviews/pull/2144)) -- Handle compatibility for Bokeh version >= 0.12.11 - ([\#2159](https://github.com/pyviz/holoviews/pull/2159)) -- Fixed broken Bokeh ArrowPlot - ([\#2172](https://github.com/pyviz/holoviews/pull/2172)) -- Fixed Pointer based streams on datetime axes - ([\#2179](https://github.com/pyviz/holoviews/pull/2179)) -- Allow constructing and plotting of empty Distribution and - Bivariate elements - ([\#2190](https://github.com/pyviz/holoviews/pull/2190)) -- Added support for hover info on Bokeh BoxWhisker plots - ([\#2187](https://github.com/pyviz/holoviews/pull/2187)) -- Fixed bug attaching streams to (Nd)Overlay types - ([\#2194](https://github.com/pyviz/holoviews/pull/2194)) - - -Version 1.9.1 -============= +- Ensure dimensions, group and label are inherited when casting + Image to QuadMesh + ([\#2144](https://github.com/pyviz/holoviews/pull/2144)) +- Handle compatibility for Bokeh version >= 0.12.11 + ([\#2159](https://github.com/pyviz/holoviews/pull/2159)) +- Fixed broken Bokeh ArrowPlot + ([\#2172](https://github.com/pyviz/holoviews/pull/2172)) +- Fixed Pointer based streams on datetime axes + ([\#2179](https://github.com/pyviz/holoviews/pull/2179)) +- Allow constructing and plotting of empty Distribution and + Bivariate elements + ([\#2190](https://github.com/pyviz/holoviews/pull/2190)) +- Added support for hover info on Bokeh BoxWhisker plots + ([\#2187](https://github.com/pyviz/holoviews/pull/2187)) +- Fixed bug attaching streams to (Nd)Overlay types + ([\#2194](https://github.com/pyviz/holoviews/pull/2194)) + +# Version 1.9.1 + **November 13, 2017** This release is a minor bug fix release patching various issues @@ -2663,25 +2617,25 @@ which were found in the 1.9.0 release. Enhancements: -- Exposed min_alpha parameter on datashader shade and datashade - operations ([\#2109](https://github.com/pyviz/holoviews/pull/2109)) +- Exposed min_alpha parameter on datashader shade and datashade + operations ([\#2109](https://github.com/pyviz/holoviews/pull/2109)) Fixes: -- Fixed broken Bokeh server linked stream throttling - ([\#2112](https://github.com/pyviz/holoviews/pull/2112)) -- Fixed bug in Bokeh callbacks preventing linked streams using - Bokeh's on_event callbacks from working - ([\#2112](https://github.com/pyviz/holoviews/pull/2112)) -- Fixed insufficient validation issue for Image and bugs when - applying regrid operation to xarray based Images - ([\#2117](https://github.com/pyviz/holoviews/pull/2117)) -- Fixed handling of dimensions and empty elements in univariate_kde - and bivariate_kde operations - ([\#2103](https://github.com/pyviz/holoviews/pull/2103)) - -Version 1.9.0 -============= +- Fixed broken Bokeh server linked stream throttling + ([\#2112](https://github.com/pyviz/holoviews/pull/2112)) +- Fixed bug in Bokeh callbacks preventing linked streams using + Bokeh's on_event callbacks from working + ([\#2112](https://github.com/pyviz/holoviews/pull/2112)) +- Fixed insufficient validation issue for Image and bugs when + applying regrid operation to xarray based Images + ([\#2117](https://github.com/pyviz/holoviews/pull/2117)) +- Fixed handling of dimensions and empty elements in univariate_kde + and bivariate_kde operations + ([\#2103](https://github.com/pyviz/holoviews/pull/2103)) + +# Version 1.9.0 + **November 3, 2017** This release includes a large number of long awaited features, @@ -2694,81 +2648,80 @@ issues and submitted pull requests. Features: -- The kdim and vdim keyword arguments are now positional making the - declaration of elements less verbose (e.g. Scatter(data, 'x', - 'y')) ([\#1946](https://github.com/pyviz/holoviews/pull/1946)) -- Added Graph, Nodes, and EdgePaths elements adding support for - plotting network graphs - ([\#1829](https://github.com/pyviz/holoviews/pull/1829)) -- Added datashader based regrid operation for fast Image and RGB - regridding ([\#1773](https://github.com/pyviz/holoviews/pull/1773)) -- Added support for binary transport when plotting with Bokeh, - providing huge speedups for dynamic plots - ([\#1894](https://github.com/pyviz/holoviews/pull/1894), - [\#1896](https://github.com/pyviz/holoviews/pull/1896)) -- Added Pipe and Buffer streams for streaming data support - ([\#2011](https://github.com/pyviz/holoviews/pull/2011)) -- Add support for datetime axes on Image, RGB and when applying - datashading and regridding operations - ([\#2023](https://github.com/pyviz/holoviews/pull/2023)) -- Added Distribution and Bivariate as first class elements which can - be plotted with Matplotlib and Bokeh without depending on seaborn - ([\#1985](https://github.com/pyviz/holoviews/pull/1985)) -- Completely overhauled support for plotting geometries with Path, - Contours and Polygons elements including support for coloring - individual segments and paths by value - ([\#1991](https://github.com/pyviz/holoviews/pull/1991)) +- The kdim and vdim keyword arguments are now positional making the + declaration of elements less verbose (e.g. Scatter(data, 'x', + 'y')) ([\#1946](https://github.com/pyviz/holoviews/pull/1946)) +- Added Graph, Nodes, and EdgePaths elements adding support for + plotting network graphs + ([\#1829](https://github.com/pyviz/holoviews/pull/1829)) +- Added datashader based regrid operation for fast Image and RGB + regridding ([\#1773](https://github.com/pyviz/holoviews/pull/1773)) +- Added support for binary transport when plotting with Bokeh, + providing huge speedups for dynamic plots + ([\#1894](https://github.com/pyviz/holoviews/pull/1894), + [\#1896](https://github.com/pyviz/holoviews/pull/1896)) +- Added Pipe and Buffer streams for streaming data support + ([\#2011](https://github.com/pyviz/holoviews/pull/2011)) +- Add support for datetime axes on Image, RGB and when applying + datashading and regridding operations + ([\#2023](https://github.com/pyviz/holoviews/pull/2023)) +- Added Distribution and Bivariate as first class elements which can + be plotted with Matplotlib and Bokeh without depending on seaborn + ([\#1985](https://github.com/pyviz/holoviews/pull/1985)) +- Completely overhauled support for plotting geometries with Path, + Contours and Polygons elements including support for coloring + individual segments and paths by value + ([\#1991](https://github.com/pyviz/holoviews/pull/1991)) Enhancements: -- Add support for adjoining all elements on Matplotlib plots - ([\#1033](https://github.com/pyviz/holoviews/pull/1033)) -- Improved exception handling for data interfaces - ([\#2041](https://github.com/pyviz/holoviews/pull/2041)) -- Add groupby argument to histogram operation - ([\#1725](https://github.com/pyviz/holoviews/pull/1725)) -- Add support for reverse sort on Dataset elements - ([\#1843](https://github.com/pyviz/holoviews/pull/1843)) -- Added support for invert_x/yaxis on all elements - ([\#1872](https://github.com/pyviz/holoviews/pull/1872), - [\#1919](https://github.com/pyviz/holoviews/pull/1919)) +- Add support for adjoining all elements on Matplotlib plots + ([\#1033](https://github.com/pyviz/holoviews/pull/1033)) +- Improved exception handling for data interfaces + ([\#2041](https://github.com/pyviz/holoviews/pull/2041)) +- Add groupby argument to histogram operation + ([\#1725](https://github.com/pyviz/holoviews/pull/1725)) +- Add support for reverse sort on Dataset elements + ([\#1843](https://github.com/pyviz/holoviews/pull/1843)) +- Added support for invert_x/yaxis on all elements + ([\#1872](https://github.com/pyviz/holoviews/pull/1872), + [\#1919](https://github.com/pyviz/holoviews/pull/1919)) Fixes: -- Fixed a bug in Matplotlib causing the first frame in gif and mp4 - getting stuck - ([\#1922](https://github.com/pyviz/holoviews/pull/1922)) -- Fixed various issues with support for new nested categorical axes - in Bokeh ([\#1933](https://github.com/pyviz/holoviews/pull/1933)) -- A large range of other bug fixes too long to list here. +- Fixed a bug in Matplotlib causing the first frame in gif and mp4 + getting stuck + ([\#1922](https://github.com/pyviz/holoviews/pull/1922)) +- Fixed various issues with support for new nested categorical axes + in Bokeh ([\#1933](https://github.com/pyviz/holoviews/pull/1933)) +- A large range of other bug fixes too long to list here. Changes affecting backwards compatibility: -- The contours operation no longer overlays the contours on top of - the supplied Image by default and returns a single - Contours/Polygons rather than an NdOverlay of them - ([\#1991](https://github.com/pyviz/holoviews/pull/1991)) -- The values of the Distribution element should now be defined as a - key dimension - ([\#1985](https://github.com/pyviz/holoviews/pull/1985)) -- The seaborn interface was removed in its entirety being replaced - by first class support for statistics elements such as - Distribution and Bivariate - ([\#1985](https://github.com/pyviz/holoviews/pull/1985)) -- Since kdims and vdims can now be passed as positional arguments - the bounds argument on Image is no longer positional - ([\#1946](https://github.com/pyviz/holoviews/pull/1946)). -- The datashade and shade cmap was reverted back to blue due to issues - with the fire cmap against a white background. - ([\#2078](https://github.com/pyviz/holoviews/pull/2078)) -- Dropped all support for Bokeh versions older than 0.12.10 -- histogram operation now returns Histogram elements with less - generic value dimension and customizable label - ([\#1836](https://github.com/pyviz/holoviews/pull/1836)) - - -Version 1.8.4 -============= +- The contours operation no longer overlays the contours on top of + the supplied Image by default and returns a single + Contours/Polygons rather than an NdOverlay of them + ([\#1991](https://github.com/pyviz/holoviews/pull/1991)) +- The values of the Distribution element should now be defined as a + key dimension + ([\#1985](https://github.com/pyviz/holoviews/pull/1985)) +- The seaborn interface was removed in its entirety being replaced + by first class support for statistics elements such as + Distribution and Bivariate + ([\#1985](https://github.com/pyviz/holoviews/pull/1985)) +- Since kdims and vdims can now be passed as positional arguments + the bounds argument on Image is no longer positional + ([\#1946](https://github.com/pyviz/holoviews/pull/1946)). +- The datashade and shade cmap was reverted back to blue due to issues + with the fire cmap against a white background. + ([\#2078](https://github.com/pyviz/holoviews/pull/2078)) +- Dropped all support for Bokeh versions older than 0.12.10 +- histogram operation now returns Histogram elements with less + generic value dimension and customizable label + ([\#1836](https://github.com/pyviz/holoviews/pull/1836)) + +# Version 1.8.4 + **September 13, 2017** This bugfix release includes a number of critical fixes for compatibility @@ -2777,25 +2730,24 @@ users for various detailed bug reports, feedback and contributions. Fixes: -- Fixes to register BoundsXY stream. - ([\#1826](https://github.com/pyviz/holoviews/pull/1826)) -- Fix for Bounds streams on Bokeh server. - ([\#1883](https://github.com/pyviz/holoviews/pull/1883)) -- Compatibility with Matplotlib 2.1 - ([\#1842](https://github.com/pyviz/holoviews/pull/1842)) -- Fixed bug in scrubber widget and support for scrubbing discrete - DynamicMaps ([\#1832](https://github.com/pyviz/holoviews/pull/1832)) -- Various fixes for compatibility with Bokeh 0.12.9 - ([\#1849](https://github.com/pyviz/holoviews/pull/1849), - [\#1866](https://github.com/pyviz/holoviews/pull/1886)) -- Fixes for setting QuadMesh ranges. - ([\#1876](https://github.com/pyviz/holoviews/pull/1876)) -- Fixes for inverting Image/RGB/Raster axes in Bokeh. - ([\#1872](https://github.com/pyviz/holoviews/pull/1872)) - - -Version 1.8.3 -============= +- Fixes to register BoundsXY stream. + ([\#1826](https://github.com/pyviz/holoviews/pull/1826)) +- Fix for Bounds streams on Bokeh server. + ([\#1883](https://github.com/pyviz/holoviews/pull/1883)) +- Compatibility with Matplotlib 2.1 + ([\#1842](https://github.com/pyviz/holoviews/pull/1842)) +- Fixed bug in scrubber widget and support for scrubbing discrete + DynamicMaps ([\#1832](https://github.com/pyviz/holoviews/pull/1832)) +- Various fixes for compatibility with Bokeh 0.12.9 + ([\#1849](https://github.com/pyviz/holoviews/pull/1849), + [\#1866](https://github.com/pyviz/holoviews/pull/1886)) +- Fixes for setting QuadMesh ranges. + ([\#1876](https://github.com/pyviz/holoviews/pull/1876)) +- Fixes for inverting Image/RGB/Raster axes in Bokeh. + ([\#1872](https://github.com/pyviz/holoviews/pull/1872)) + +# Version 1.8.3 + **August 21, 2017** This bugfix release fixes a number of minor issues identified since the @@ -2803,27 +2755,26 @@ last release: Features: -- Add support for setting the Bokeh sizing_mode as a plot option - ([\#1813](https://github.com/pyviz/holoviews/pull/1813)) +- Add support for setting the Bokeh sizing_mode as a plot option + ([\#1813](https://github.com/pyviz/holoviews/pull/1813)) Fixes: -- Handle StopIteration on DynamicMap correctly. - ([\#1792](https://github.com/pyviz/holoviews/pull/1792)) -- Fix bug with linked streams on empty source element - ([\#1725](https://github.com/pyviz/holoviews/pull/1806)) -- Compatibility with latest datashader 0.6.0 release - ([\#1773](https://github.com/pyviz/holoviews/pull/1773)) -- Fixed missing HTML closing tag in extension - ([\#1797](https://github.com/pyviz/holoviews/issues/1797), - [\#1809](https://github.com/pyviz/holoviews/pull/1809)) -- Various fixes and improvements for documentation - ([\#1664](https://github.com/pyviz/holoviews/pull/1664), - [\#1796](https://github.com/pyviz/holoviews/pull/1796)) - - -Version 1.8.2 -============= +- Handle StopIteration on DynamicMap correctly. + ([\#1792](https://github.com/pyviz/holoviews/pull/1792)) +- Fix bug with linked streams on empty source element + ([\#1725](https://github.com/pyviz/holoviews/pull/1806)) +- Compatibility with latest datashader 0.6.0 release + ([\#1773](https://github.com/pyviz/holoviews/pull/1773)) +- Fixed missing HTML closing tag in extension + ([\#1797](https://github.com/pyviz/holoviews/issues/1797), + [\#1809](https://github.com/pyviz/holoviews/pull/1809)) +- Various fixes and improvements for documentation + ([\#1664](https://github.com/pyviz/holoviews/pull/1664), + [\#1796](https://github.com/pyviz/holoviews/pull/1796)) + +# Version 1.8.2 + **August 4, 2017** This bugfix release addresses a number of minor issues identified since @@ -2831,26 +2782,26 @@ the 1.8.1 release: Feature: -- Added support for groupby to histogram operation. - ([\#1725](https://github.com/pyviz/holoviews/pull/1725)) +- Added support for groupby to histogram operation. + ([\#1725](https://github.com/pyviz/holoviews/pull/1725)) Fixes: -- Fixed problem with HTML export due to new extension logos. - ([\#1778](https://github.com/pyviz/holoviews/pull/1778)) -- Replaced deprecated ``__call__`` usage with opts method throughout codebase. - ([\#1759](https://github.com/pyviz/holoviews/pull/1759), - [\#1763](https://github.com/pyviz/holoviews/pull/1763), - [\#1779](https://github.com/pyviz/holoviews/pull/1779)) -- Fixed pip installation. - ([\#1782](https://github.com/pyviz/holoviews/pull/1782)) -- Fixed miscellaneous bugs - ([\#1724](https://github.com/pyviz/holoviews/pull/1724), - [\#1739](https://github.com/pyviz/holoviews/pull/1739), - [\#1711](https://github.com/pyviz/holoviews/pull/1711)) - -Version 1.8.1 -============= +- Fixed problem with HTML export due to new extension logos. + ([\#1778](https://github.com/pyviz/holoviews/pull/1778)) +- Replaced deprecated `__call__` usage with opts method throughout codebase. + ([\#1759](https://github.com/pyviz/holoviews/pull/1759), + [\#1763](https://github.com/pyviz/holoviews/pull/1763), + [\#1779](https://github.com/pyviz/holoviews/pull/1779)) +- Fixed pip installation. + ([\#1782](https://github.com/pyviz/holoviews/pull/1782)) +- Fixed miscellaneous bugs + ([\#1724](https://github.com/pyviz/holoviews/pull/1724), + [\#1739](https://github.com/pyviz/holoviews/pull/1739), + [\#1711](https://github.com/pyviz/holoviews/pull/1711)) + +# Version 1.8.1 + **July 7, 2017** This bugfix release addresses a number of minor issues identified since @@ -2858,40 +2809,40 @@ the 1.8 release: Feature: -- All enabled plotting extension logos now shown - ([\#1694](https://github.com/pyviz/holoviews/pull/1694)) +- All enabled plotting extension logos now shown + ([\#1694](https://github.com/pyviz/holoviews/pull/1694)) Fixes: -- Updated search ordering when looking for holoviews.rc - ([\#1700](https://github.com/pyviz/holoviews/pull/1700)) -- Fixed lower bound inclusivity bug when no upper bound supplied - ([\#1686](https://github.com/pyviz/holoviews/pull/1686)) -- Raise SkipRendering error when plotting nested layouts - ([\#1687](https://github.com/pyviz/holoviews/pull/1687)) -- Added safety margin for grid axis constraint issue - ([\#1695](https://github.com/pyviz/holoviews/pull/1685)) -- Fixed bug when using +framewise - ([\#1685](https://github.com/pyviz/holoviews/pull/1685)) -- Fixed handling of Spacer models in sparse grid - ([\#1682](https://github.com/pyviz/holoviews/pull/)) -- Renamed Bounds to BoundsXY for consistency - ([\#1672](https://github.com/pyviz/holoviews/pull/1672)) -- Fixed Bokeh log axes with axis lower bound <=0 - ([\#1691](https://github.com/pyviz/holoviews/pull/1691)) -- Set default datashader cmap to fire - ([\#1697](https://github.com/pyviz/holoviews/pull/1697)) -- Set SpikesPlot color index to None by default - ([\#1671](https://github.com/pyviz/holoviews/pull/1671)) -- Documentation fixes - ([\#1662](https://github.com/pyviz/holoviews/pull/1662), - [\#1665](https://github.com/pyviz/holoviews/pull/1665), - [\#1690](https://github.com/pyviz/holoviews/pull/1690), - [\#1692](https://github.com/pyviz/holoviews/pull/1692), - [\#1658](https://github.com/pyviz/holoviews/pull/1658)) - -Version 1.8.0 -============= +- Updated search ordering when looking for holoviews.rc + ([\#1700](https://github.com/pyviz/holoviews/pull/1700)) +- Fixed lower bound inclusivity bug when no upper bound supplied + ([\#1686](https://github.com/pyviz/holoviews/pull/1686)) +- Raise SkipRendering error when plotting nested layouts + ([\#1687](https://github.com/pyviz/holoviews/pull/1687)) +- Added safety margin for grid axis constraint issue + ([\#1695](https://github.com/pyviz/holoviews/pull/1685)) +- Fixed bug when using +framewise + ([\#1685](https://github.com/pyviz/holoviews/pull/1685)) +- Fixed handling of Spacer models in sparse grid + ([\#1682](https://github.com/pyviz/holoviews/pull/)) +- Renamed Bounds to BoundsXY for consistency + ([\#1672](https://github.com/pyviz/holoviews/pull/1672)) +- Fixed Bokeh log axes with axis lower bound <=0 + ([\#1691](https://github.com/pyviz/holoviews/pull/1691)) +- Set default datashader cmap to fire + ([\#1697](https://github.com/pyviz/holoviews/pull/1697)) +- Set SpikesPlot color index to None by default + ([\#1671](https://github.com/pyviz/holoviews/pull/1671)) +- Documentation fixes + ([\#1662](https://github.com/pyviz/holoviews/pull/1662), + [\#1665](https://github.com/pyviz/holoviews/pull/1665), + [\#1690](https://github.com/pyviz/holoviews/pull/1690), + [\#1692](https://github.com/pyviz/holoviews/pull/1692), + [\#1658](https://github.com/pyviz/holoviews/pull/1658)) + +# Version 1.8.0 + **June 29, 2017** This release includes a complete and long awaited overhaul of the @@ -2903,116 +2854,116 @@ new contributors for providing feedback, bug reports, and pull requests. Major features: -- Completely overhauled the documentation and website - ([\#1384](https://github.com/pyviz/holoviews/pull/1384), - [\#1473](https://github.com/pyviz/holoviews/pull/1473), - [\#1476](https://github.com/pyviz/holoviews/pull/1476), - [\#1473](https://github.com/pyviz/holoviews/pull/1473), - [\#1537](https://github.com/pyviz/holoviews/pull/1537), - [\#1585](https://github.com/pyviz/holoviews/pull/1585), - [\#1628](https://github.com/pyviz/holoviews/pull/1628), - [\#1636](https://github.com/pyviz/holoviews/pull/1636)) -- Replaced dependency on bkcharts with new Bokeh bar plot - ([\#1416](https://github.com/pyviz/holoviews/pull/1416)) and Bokeh - BoxWhisker plot - ([\#1604](https://github.com/pyviz/holoviews/pull/1604)) -- Added support for drawing the `Arrow` annotation in Bokeh - ([\#1608](https://github.com/pyviz/holoviews/pull/1608)) -- Added periodic method DynamicMap to schedule recurring events - ([\#1429](https://github.com/pyviz/holoviews/pull/1429)) -- Cleaned up the API for deploying to Bokeh server - ([\#1444](https://github.com/pyviz/holoviews/pull/1444), - [\#1469](https://github.com/pyviz/holoviews/pull/1469), - [\#1486](https://github.com/pyviz/holoviews/pull/1486)) -- Validation of invalid backend specific options - ([\#1465](https://github.com/pyviz/holoviews/pull/1465)) -- Added utilities and entry points to convert notebooks to scripts - including magics - ([\#1491](https://github.com/pyviz/holoviews/pull/1491)) -- Added support for rendering to png in Bokeh backend - ([\#1493](https://github.com/pyviz/holoviews/pull/1493)) -- Made Matplotlib and Bokeh styling more consistent and dropped custom - Matplotlib rc file - ([\#1518](https://github.com/pyviz/holoviews/pull/1518)) -- Added `iloc` and `ndloc` method to allow integer based indexing on - tabular and gridded datasets - ([\#1435](https://github.com/pyviz/holoviews/pull/1435)) -- Added option to restore case sensitive completion order by setting - `hv.extension.case_sensitive_completion=True` in python or via - holoviews.rc file - ([\#1613](https://github.com/pyviz/holoviews/pull/1613)) +- Completely overhauled the documentation and website + ([\#1384](https://github.com/pyviz/holoviews/pull/1384), + [\#1473](https://github.com/pyviz/holoviews/pull/1473), + [\#1476](https://github.com/pyviz/holoviews/pull/1476), + [\#1473](https://github.com/pyviz/holoviews/pull/1473), + [\#1537](https://github.com/pyviz/holoviews/pull/1537), + [\#1585](https://github.com/pyviz/holoviews/pull/1585), + [\#1628](https://github.com/pyviz/holoviews/pull/1628), + [\#1636](https://github.com/pyviz/holoviews/pull/1636)) +- Replaced dependency on bkcharts with new Bokeh bar plot + ([\#1416](https://github.com/pyviz/holoviews/pull/1416)) and Bokeh + BoxWhisker plot + ([\#1604](https://github.com/pyviz/holoviews/pull/1604)) +- Added support for drawing the `Arrow` annotation in Bokeh + ([\#1608](https://github.com/pyviz/holoviews/pull/1608)) +- Added periodic method DynamicMap to schedule recurring events + ([\#1429](https://github.com/pyviz/holoviews/pull/1429)) +- Cleaned up the API for deploying to Bokeh server + ([\#1444](https://github.com/pyviz/holoviews/pull/1444), + [\#1469](https://github.com/pyviz/holoviews/pull/1469), + [\#1486](https://github.com/pyviz/holoviews/pull/1486)) +- Validation of invalid backend specific options + ([\#1465](https://github.com/pyviz/holoviews/pull/1465)) +- Added utilities and entry points to convert notebooks to scripts + including magics + ([\#1491](https://github.com/pyviz/holoviews/pull/1491)) +- Added support for rendering to png in Bokeh backend + ([\#1493](https://github.com/pyviz/holoviews/pull/1493)) +- Made Matplotlib and Bokeh styling more consistent and dropped custom + Matplotlib rc file + ([\#1518](https://github.com/pyviz/holoviews/pull/1518)) +- Added `iloc` and `ndloc` method to allow integer based indexing on + tabular and gridded datasets + ([\#1435](https://github.com/pyviz/holoviews/pull/1435)) +- Added option to restore case sensitive completion order by setting + `hv.extension.case_sensitive_completion=True` in python or via + holoviews.rc file + ([\#1613](https://github.com/pyviz/holoviews/pull/1613)) Other new features and improvements: -- Optimized datashading of `NdOverlay` - ([\#1430](https://github.com/pyviz/holoviews/pull/1430)) -- Expose last `DynamicMap` args and kwargs on Callable - ([\#1453](https://github.com/pyviz/holoviews/pull/1453)) -- Allow colormapping `Contours` Element - ([\#1499](https://github.com/pyviz/holoviews/pull/1499)) -- Add support for fixed ticks with labels in Bokeh backend - ([\#1503](https://github.com/pyviz/holoviews/pull/1503)) -- Added a `clim` parameter to datashade controlling the color range - ([\#1508](https://github.com/pyviz/holoviews/pull/1508)) -- Add support for wrapping xarray DataArrays containing Dask arrays - ([\#1512](https://github.com/pyviz/holoviews/pull/1512)) -- Added support for aggregating to target `Image` dimensions in - datashader `aggregate` operation - ([\#1513](https://github.com/pyviz/holoviews/pull/1513)) -- Added top-level hv.extension and `hv.renderer` utilities - ([\#1517](https://github.com/pyviz/holoviews/pull/1517)) -- Added support for `Splines` defining multiple cubic splines in Bokeh - ([\#1529](https://github.com/pyviz/holoviews/pull/1529)) -- Add support for redim.label to quickly define dimension labels - ([\#1541](https://github.com/pyviz/holoviews/pull/1541)) -- Add `BoundsX` and `BoundsY` streams - ([\#1554](https://github.com/pyviz/holoviews/pull/1554)) -- Added support for adjoining empty plots - ([\#1561](https://github.com/pyviz/holoviews/pull/1561)) -- Handle zero-values correctly when using `logz` colormapping option - in Matplotlib - ([\#1576](https://github.com/pyviz/holoviews/pull/1576)) -- Define a number of `Cycle` and `Palette` defaults across backends - ([\#1605](https://github.com/pyviz/holoviews/pull/1605)) -- Many other small improvements and fixes - ([\#1399](https://github.com/pyviz/holoviews/pull/1399), - [\#1400](https://github.com/pyviz/holoviews/pull/1400), - [\#1405](https://github.com/pyviz/holoviews/pull/1405), - [\#1412](https://github.com/pyviz/holoviews/pull/1412), - [\#1413](https://github.com/pyviz/holoviews/pull/1413), - [\#1418](https://github.com/pyviz/holoviews/pull/1418), - [\#1439](https://github.com/pyviz/holoviews/pull/1439), - [\#1442](https://github.com/pyviz/holoviews/pull/1442), - [\#1443](https://github.com/pyviz/holoviews/pull/1443), - [\#1467](https://github.com/pyviz/holoviews/pull/1467), - [\#1485](https://github.com/pyviz/holoviews/pull/1485), - [\#1505](https://github.com/pyviz/holoviews/pull/1505), - [\#1493](https://github.com/pyviz/holoviews/pull/1493), - [\#1509](https://github.com/pyviz/holoviews/pull/1509), - [\#1524](https://github.com/pyviz/holoviews/pull/1524), - [\#1543](https://github.com/pyviz/holoviews/pull/1543), - [\#1547](https://github.com/pyviz/holoviews/pull/1547), - [\#1560](https://github.com/pyviz/holoviews/pull/1560), - [\#1603](https://github.com/pyviz/holoviews/pull/1603)) +- Optimized datashading of `NdOverlay` + ([\#1430](https://github.com/pyviz/holoviews/pull/1430)) +- Expose last `DynamicMap` args and kwargs on Callable + ([\#1453](https://github.com/pyviz/holoviews/pull/1453)) +- Allow colormapping `Contours` Element + ([\#1499](https://github.com/pyviz/holoviews/pull/1499)) +- Add support for fixed ticks with labels in Bokeh backend + ([\#1503](https://github.com/pyviz/holoviews/pull/1503)) +- Added a `clim` parameter to datashade controlling the color range + ([\#1508](https://github.com/pyviz/holoviews/pull/1508)) +- Add support for wrapping xarray DataArrays containing Dask arrays + ([\#1512](https://github.com/pyviz/holoviews/pull/1512)) +- Added support for aggregating to target `Image` dimensions in + datashader `aggregate` operation + ([\#1513](https://github.com/pyviz/holoviews/pull/1513)) +- Added top-level hv.extension and `hv.renderer` utilities + ([\#1517](https://github.com/pyviz/holoviews/pull/1517)) +- Added support for `Splines` defining multiple cubic splines in Bokeh + ([\#1529](https://github.com/pyviz/holoviews/pull/1529)) +- Add support for redim.label to quickly define dimension labels + ([\#1541](https://github.com/pyviz/holoviews/pull/1541)) +- Add `BoundsX` and `BoundsY` streams + ([\#1554](https://github.com/pyviz/holoviews/pull/1554)) +- Added support for adjoining empty plots + ([\#1561](https://github.com/pyviz/holoviews/pull/1561)) +- Handle zero-values correctly when using `logz` colormapping option + in Matplotlib + ([\#1576](https://github.com/pyviz/holoviews/pull/1576)) +- Define a number of `Cycle` and `Palette` defaults across backends + ([\#1605](https://github.com/pyviz/holoviews/pull/1605)) +- Many other small improvements and fixes + ([\#1399](https://github.com/pyviz/holoviews/pull/1399), + [\#1400](https://github.com/pyviz/holoviews/pull/1400), + [\#1405](https://github.com/pyviz/holoviews/pull/1405), + [\#1412](https://github.com/pyviz/holoviews/pull/1412), + [\#1413](https://github.com/pyviz/holoviews/pull/1413), + [\#1418](https://github.com/pyviz/holoviews/pull/1418), + [\#1439](https://github.com/pyviz/holoviews/pull/1439), + [\#1442](https://github.com/pyviz/holoviews/pull/1442), + [\#1443](https://github.com/pyviz/holoviews/pull/1443), + [\#1467](https://github.com/pyviz/holoviews/pull/1467), + [\#1485](https://github.com/pyviz/holoviews/pull/1485), + [\#1505](https://github.com/pyviz/holoviews/pull/1505), + [\#1493](https://github.com/pyviz/holoviews/pull/1493), + [\#1509](https://github.com/pyviz/holoviews/pull/1509), + [\#1524](https://github.com/pyviz/holoviews/pull/1524), + [\#1543](https://github.com/pyviz/holoviews/pull/1543), + [\#1547](https://github.com/pyviz/holoviews/pull/1547), + [\#1560](https://github.com/pyviz/holoviews/pull/1560), + [\#1603](https://github.com/pyviz/holoviews/pull/1603)) Changes affecting backwards compatibility: -- Renamed `ElementOperation` to `Operation` - ([\#1421](https://github.com/pyviz/holoviews/pull/1421)) -- Removed `stack_area` operation in favor of `Area.stack` classmethod - ([\#1515](https://github.com/pyviz/holoviews/pull/1515)) -- Removed all mpld3 support - ([\#1516](https://github.com/pyviz/holoviews/pull/1516)) -- Added `opts` method on all types, replacing the now-deprecated - `__call__` syntax to set options - ([\#1589](https://github.com/pyviz/holoviews/pull/1589)) -- Styling changes for both Matplotlib and Bokeh, which can be reverted - for a notebook with the `config` option of `hv.extension`. For - instance, `hv.extension('bokeh', config=dict(style_17=True))` - ([\#1518](https://github.com/pyviz/holoviews/pull/1518)) - -Version 1.7.0 -============= +- Renamed `ElementOperation` to `Operation` + ([\#1421](https://github.com/pyviz/holoviews/pull/1421)) +- Removed `stack_area` operation in favor of `Area.stack` classmethod + ([\#1515](https://github.com/pyviz/holoviews/pull/1515)) +- Removed all mpld3 support + ([\#1516](https://github.com/pyviz/holoviews/pull/1516)) +- Added `opts` method on all types, replacing the now-deprecated + `__call__` syntax to set options + ([\#1589](https://github.com/pyviz/holoviews/pull/1589)) +- Styling changes for both Matplotlib and Bokeh, which can be reverted + for a notebook with the `config` option of `hv.extension`. For + instance, `hv.extension('bokeh', config=dict(style_17=True))` + ([\#1518](https://github.com/pyviz/holoviews/pull/1518)) + +# Version 1.7.0 + **April 25, 2017** This version is a major new release incorporating seven months of work @@ -3028,421 +2979,421 @@ in the run-up to HoloViews 2.0. Major features and improvements: -- Interactive Streams API (PR - [\#832](https://github.com/pyviz/holoviews/pull/832), - [\#838](https://github.com/pyviz/holoviews/pull/838), - [\#842](https://github.com/pyviz/holoviews/pull/842), - [\#844](https://github.com/pyviz/holoviews/pull/844), - [\#845](https://github.com/pyviz/holoviews/pull/845), - [\#846](https://github.com/pyviz/holoviews/pull/846), - [\#858](https://github.com/pyviz/holoviews/pull/858), - [\#860](https://github.com/pyviz/holoviews/pull/860), - [\#889](https://github.com/pyviz/holoviews/pull/889), - [\#904](https://github.com/pyviz/holoviews/pull/904), - [\#913](https://github.com/pyviz/holoviews/pull/913), - [\#933](https://github.com/pyviz/holoviews/pull/933), - [\#962](https://github.com/pyviz/holoviews/pull/962), - [\#964](https://github.com/pyviz/holoviews/pull/964), - [\#1094](https://github.com/pyviz/holoviews/pull/1094), - [\#1256](https://github.com/pyviz/holoviews/pull/1256), - [\#1274](https://github.com/pyviz/holoviews/pull/1274), - [\#1297](https://github.com/pyviz/holoviews/pull/1297), - [\#1301](https://github.com/pyviz/holoviews/pull/1301), - [\#1303](https://github.com/pyviz/holoviews/pull/1303)). -- Dynamic Callable API (PR - [\#951](https://github.com/pyviz/holoviews/pull/951), - [\#1103](https://github.com/pyviz/holoviews/pull/1103), - [\#1029](https://github.com/pyviz/holoviews/pull/1029), - [\#968](https://github.com/pyviz/holoviews/pull/968), - [\#935](https://github.com/pyviz/holoviews/pull/935), - [\#1063](https://github.com/pyviz/holoviews/pull/1063), - [\#1260](https://github.com/pyviz/holoviews/pull/1260)). -- Simpler and more powerful DynamicMap (PR - [\#1238](https://github.com/pyviz/holoviews/pull/1238), - [\#1240](https://github.com/pyviz/holoviews/pull/1240), - [\#1243](https://github.com/pyviz/holoviews/pull/1243), - [\#1257](https://github.com/pyviz/holoviews/pull/1257), - [\#1267](https://github.com/pyviz/holoviews/pull/1267), - [\#1302](https://github.com/pyviz/holoviews/pull/1302), - [\#1304](https://github.com/pyviz/holoviews/pull/1304), - [\#1305](https://github.com/pyviz/holoviews/pull/1305)). -- Fully general support for Bokeh events (PR - [\#892](https://github.com/pyviz/holoviews/pull/892), - [\#1148](https://github.com/pyviz/holoviews/pull/1148), - [\#1235](https://github.com/pyviz/holoviews/pull/1235)). -- Datashader operations (PR - [\#894](https://github.com/pyviz/holoviews/pull/894), - [\#907](https://github.com/pyviz/holoviews/pull/907), - [\#963](https://github.com/pyviz/holoviews/pull/963), - [\#1125](https://github.com/pyviz/holoviews/pull/1125), - [\#1281](https://github.com/pyviz/holoviews/pull/1281), - [\#1306](https://github.com/pyviz/holoviews/pull/1306)). -- Support for Bokeh apps and Bokeh Server (PR - [\#959](https://github.com/pyviz/holoviews/pull/959), - [\#1283](https://github.com/pyviz/holoviews/pull/1283)). -- Working with renderers interactively outside the notebook (PR - [\#1214](https://github.com/pyviz/holoviews/pull/1214)). -- Support for Matplotlib 2.0 (PR - [\#867](https://github.com/pyviz/holoviews/pull/867), - [\#868](https://github.com/pyviz/holoviews/pull/868), - [\#1131](https://github.com/pyviz/holoviews/pull/1131), - [\#1264](https://github.com/pyviz/holoviews/pull/1264), - [\#1266](https://github.com/pyviz/holoviews/pull/1266)). -- Support for Bokeh 0.12.2, 0.12.3, 0.12.4, and 0.12.5 (PR - [\#899](https://github.com/pyviz/holoviews/pull/899), - [\#900](https://github.com/pyviz/holoviews/pull/900), - [\#1007](https://github.com/pyviz/holoviews/pull/1007), - [\#1036](https://github.com/pyviz/holoviews/pull/1036), - [\#1116](https://github.com/pyviz/holoviews/pull/1116)). -- Many new features for the Bokeh backend: widgets editable (PR - [\#1247](https://github.com/pyviz/holoviews/pull/1247)), selection - colors and interactive legends (PR - [\#1220](https://github.com/pyviz/holoviews/pull/1220)), GridSpace - axes (PR [\#1150](https://github.com/pyviz/holoviews/pull/1150)), - categorical axes and colormapping (PR - [\#1089](https://github.com/pyviz/holoviews/pull/1089), - [\#1137](https://github.com/pyviz/holoviews/pull/1137)), computing - plot size (PR - [\#1140](https://github.com/pyviz/holoviews/pull/1140)), GridSpaces - inside Layouts (PR - [\#1104](https://github.com/pyviz/holoviews/pull/1104)), Layout/Grid - titles (PR [\#1017](https://github.com/pyviz/holoviews/pull/1017)), - histogram with live colormapping (PR - [\#928](https://github.com/pyviz/holoviews/pull/928)), colorbars (PR - [\#861](https://github.com/pyviz/holoviews/pull/861)), - finalize\_hooks (PR - [\#1040](https://github.com/pyviz/holoviews/pull/1040)), labelled and - show\_frame options (PR - [\#863](https://github.com/pyviz/holoviews/pull/863), - [\#1013](https://github.com/pyviz/holoviews/pull/1013)), styling - hover glyphs (PR - [\#1286](https://github.com/pyviz/holoviews/pull/1286)), hiding - legends on BarPlot (PR - [\#837](https://github.com/pyviz/holoviews/pull/837)), VectorField - plot (PR [\#1196](https://github.com/pyviz/holoviews/pull/1196)), - Histograms now have same color cycle as mpl - ([\#1008](https://github.com/pyviz/holoviews/pull/1008)). -- Implemented convenience redim methods to easily set dimension - ranges, values etc. (PR - [\#1302](https://github.com/pyviz/holoviews/pull/1302)) -- Made methods on and operations applied to DynamicMap lazy - ([\#422](https://github.com/pyviz/holoviews/pull/422), - [\#588](https://github.com/pyviz/holoviews/pull/588), - [\#1188](https://github.com/pyviz/holoviews/pull/1188), - [\#1240](https://github.com/pyviz/holoviews/pull/1240), - [\#1227](https://github.com/pyviz/holoviews/pull/1227)) -- Improved documentation (PR - [\#936](https://github.com/pyviz/holoviews/pull/936), - [\#1070](https://github.com/pyviz/holoviews/pull/1070), - [\#1242](https://github.com/pyviz/holoviews/pull/1242), - [\#1273](https://github.com/pyviz/holoviews/pull/1273), - [\#1280](https://github.com/pyviz/holoviews/pull/1280)). -- Improved error handling (PR - [\#906](https://github.com/pyviz/holoviews/pull/906), - [\#932](https://github.com/pyviz/holoviews/pull/932), - [\#939](https://github.com/pyviz/holoviews/pull/939), - [\#949](https://github.com/pyviz/holoviews/pull/949), - [\#1011](https://github.com/pyviz/holoviews/pull/1011), - [\#1290](https://github.com/pyviz/holoviews/pull/1290), - [\#1262](https://github.com/pyviz/holoviews/pull/1262), - [\#1295](https://github.com/pyviz/holoviews/pull/1295)), including - re-enabling option system keyword validation (PR - [\#1277](https://github.com/pyviz/holoviews/pull/1277)). -- Improved testing (PR - [\#834](https://github.com/pyviz/holoviews/pull/834), - [\#871](https://github.com/pyviz/holoviews/pull/871), - [\#881](https://github.com/pyviz/holoviews/pull/881), - [\#941](https://github.com/pyviz/holoviews/pull/941), - [\#1117](https://github.com/pyviz/holoviews/pull/1117), - [\#1153](https://github.com/pyviz/holoviews/pull/1153), - [\#1171](https://github.com/pyviz/holoviews/pull/1171), - [\#1207](https://github.com/pyviz/holoviews/pull/1207), - [\#1246](https://github.com/pyviz/holoviews/pull/1246), - [\#1259](https://github.com/pyviz/holoviews/pull/1259), - [\#1287](https://github.com/pyviz/holoviews/pull/1287)). +- Interactive Streams API (PR + [\#832](https://github.com/pyviz/holoviews/pull/832), + [\#838](https://github.com/pyviz/holoviews/pull/838), + [\#842](https://github.com/pyviz/holoviews/pull/842), + [\#844](https://github.com/pyviz/holoviews/pull/844), + [\#845](https://github.com/pyviz/holoviews/pull/845), + [\#846](https://github.com/pyviz/holoviews/pull/846), + [\#858](https://github.com/pyviz/holoviews/pull/858), + [\#860](https://github.com/pyviz/holoviews/pull/860), + [\#889](https://github.com/pyviz/holoviews/pull/889), + [\#904](https://github.com/pyviz/holoviews/pull/904), + [\#913](https://github.com/pyviz/holoviews/pull/913), + [\#933](https://github.com/pyviz/holoviews/pull/933), + [\#962](https://github.com/pyviz/holoviews/pull/962), + [\#964](https://github.com/pyviz/holoviews/pull/964), + [\#1094](https://github.com/pyviz/holoviews/pull/1094), + [\#1256](https://github.com/pyviz/holoviews/pull/1256), + [\#1274](https://github.com/pyviz/holoviews/pull/1274), + [\#1297](https://github.com/pyviz/holoviews/pull/1297), + [\#1301](https://github.com/pyviz/holoviews/pull/1301), + [\#1303](https://github.com/pyviz/holoviews/pull/1303)). +- Dynamic Callable API (PR + [\#951](https://github.com/pyviz/holoviews/pull/951), + [\#1103](https://github.com/pyviz/holoviews/pull/1103), + [\#1029](https://github.com/pyviz/holoviews/pull/1029), + [\#968](https://github.com/pyviz/holoviews/pull/968), + [\#935](https://github.com/pyviz/holoviews/pull/935), + [\#1063](https://github.com/pyviz/holoviews/pull/1063), + [\#1260](https://github.com/pyviz/holoviews/pull/1260)). +- Simpler and more powerful DynamicMap (PR + [\#1238](https://github.com/pyviz/holoviews/pull/1238), + [\#1240](https://github.com/pyviz/holoviews/pull/1240), + [\#1243](https://github.com/pyviz/holoviews/pull/1243), + [\#1257](https://github.com/pyviz/holoviews/pull/1257), + [\#1267](https://github.com/pyviz/holoviews/pull/1267), + [\#1302](https://github.com/pyviz/holoviews/pull/1302), + [\#1304](https://github.com/pyviz/holoviews/pull/1304), + [\#1305](https://github.com/pyviz/holoviews/pull/1305)). +- Fully general support for Bokeh events (PR + [\#892](https://github.com/pyviz/holoviews/pull/892), + [\#1148](https://github.com/pyviz/holoviews/pull/1148), + [\#1235](https://github.com/pyviz/holoviews/pull/1235)). +- Datashader operations (PR + [\#894](https://github.com/pyviz/holoviews/pull/894), + [\#907](https://github.com/pyviz/holoviews/pull/907), + [\#963](https://github.com/pyviz/holoviews/pull/963), + [\#1125](https://github.com/pyviz/holoviews/pull/1125), + [\#1281](https://github.com/pyviz/holoviews/pull/1281), + [\#1306](https://github.com/pyviz/holoviews/pull/1306)). +- Support for Bokeh apps and Bokeh Server (PR + [\#959](https://github.com/pyviz/holoviews/pull/959), + [\#1283](https://github.com/pyviz/holoviews/pull/1283)). +- Working with renderers interactively outside the notebook (PR + [\#1214](https://github.com/pyviz/holoviews/pull/1214)). +- Support for Matplotlib 2.0 (PR + [\#867](https://github.com/pyviz/holoviews/pull/867), + [\#868](https://github.com/pyviz/holoviews/pull/868), + [\#1131](https://github.com/pyviz/holoviews/pull/1131), + [\#1264](https://github.com/pyviz/holoviews/pull/1264), + [\#1266](https://github.com/pyviz/holoviews/pull/1266)). +- Support for Bokeh 0.12.2, 0.12.3, 0.12.4, and 0.12.5 (PR + [\#899](https://github.com/pyviz/holoviews/pull/899), + [\#900](https://github.com/pyviz/holoviews/pull/900), + [\#1007](https://github.com/pyviz/holoviews/pull/1007), + [\#1036](https://github.com/pyviz/holoviews/pull/1036), + [\#1116](https://github.com/pyviz/holoviews/pull/1116)). +- Many new features for the Bokeh backend: widgets editable (PR + [\#1247](https://github.com/pyviz/holoviews/pull/1247)), selection + colors and interactive legends (PR + [\#1220](https://github.com/pyviz/holoviews/pull/1220)), GridSpace + axes (PR [\#1150](https://github.com/pyviz/holoviews/pull/1150)), + categorical axes and colormapping (PR + [\#1089](https://github.com/pyviz/holoviews/pull/1089), + [\#1137](https://github.com/pyviz/holoviews/pull/1137)), computing + plot size (PR + [\#1140](https://github.com/pyviz/holoviews/pull/1140)), GridSpaces + inside Layouts (PR + [\#1104](https://github.com/pyviz/holoviews/pull/1104)), Layout/Grid + titles (PR [\#1017](https://github.com/pyviz/holoviews/pull/1017)), + histogram with live colormapping (PR + [\#928](https://github.com/pyviz/holoviews/pull/928)), colorbars (PR + [\#861](https://github.com/pyviz/holoviews/pull/861)), + finalize_hooks (PR + [\#1040](https://github.com/pyviz/holoviews/pull/1040)), labelled and + show_frame options (PR + [\#863](https://github.com/pyviz/holoviews/pull/863), + [\#1013](https://github.com/pyviz/holoviews/pull/1013)), styling + hover glyphs (PR + [\#1286](https://github.com/pyviz/holoviews/pull/1286)), hiding + legends on BarPlot (PR + [\#837](https://github.com/pyviz/holoviews/pull/837)), VectorField + plot (PR [\#1196](https://github.com/pyviz/holoviews/pull/1196)), + Histograms now have same color cycle as mpl + ([\#1008](https://github.com/pyviz/holoviews/pull/1008)). +- Implemented convenience redim methods to easily set dimension + ranges, values etc. (PR + [\#1302](https://github.com/pyviz/holoviews/pull/1302)) +- Made methods on and operations applied to DynamicMap lazy + ([\#422](https://github.com/pyviz/holoviews/pull/422), + [\#588](https://github.com/pyviz/holoviews/pull/588), + [\#1188](https://github.com/pyviz/holoviews/pull/1188), + [\#1240](https://github.com/pyviz/holoviews/pull/1240), + [\#1227](https://github.com/pyviz/holoviews/pull/1227)) +- Improved documentation (PR + [\#936](https://github.com/pyviz/holoviews/pull/936), + [\#1070](https://github.com/pyviz/holoviews/pull/1070), + [\#1242](https://github.com/pyviz/holoviews/pull/1242), + [\#1273](https://github.com/pyviz/holoviews/pull/1273), + [\#1280](https://github.com/pyviz/holoviews/pull/1280)). +- Improved error handling (PR + [\#906](https://github.com/pyviz/holoviews/pull/906), + [\#932](https://github.com/pyviz/holoviews/pull/932), + [\#939](https://github.com/pyviz/holoviews/pull/939), + [\#949](https://github.com/pyviz/holoviews/pull/949), + [\#1011](https://github.com/pyviz/holoviews/pull/1011), + [\#1290](https://github.com/pyviz/holoviews/pull/1290), + [\#1262](https://github.com/pyviz/holoviews/pull/1262), + [\#1295](https://github.com/pyviz/holoviews/pull/1295)), including + re-enabling option system keyword validation (PR + [\#1277](https://github.com/pyviz/holoviews/pull/1277)). +- Improved testing (PR + [\#834](https://github.com/pyviz/holoviews/pull/834), + [\#871](https://github.com/pyviz/holoviews/pull/871), + [\#881](https://github.com/pyviz/holoviews/pull/881), + [\#941](https://github.com/pyviz/holoviews/pull/941), + [\#1117](https://github.com/pyviz/holoviews/pull/1117), + [\#1153](https://github.com/pyviz/holoviews/pull/1153), + [\#1171](https://github.com/pyviz/holoviews/pull/1171), + [\#1207](https://github.com/pyviz/holoviews/pull/1207), + [\#1246](https://github.com/pyviz/holoviews/pull/1246), + [\#1259](https://github.com/pyviz/holoviews/pull/1259), + [\#1287](https://github.com/pyviz/holoviews/pull/1287)). Other new features and improvements: -- Operations for timeseries (PR - [\#1172](https://github.com/pyviz/holoviews/pull/1172)), - downsample\_columns (PR - [\#903](https://github.com/pyviz/holoviews/pull/903)), - interpolate\_curve (PR - [\#1097](https://github.com/pyviz/holoviews/pull/1097)), and stacked - area (PR [\#1193](https://github.com/pyviz/holoviews/pull/1193)). -- Dataset types can be declared as empty by passing an empty list (PR - [\#1355](https://github.com/pyviz/holoviews/pull/1355)) -- Plot or style options for Curve interpolation (PR - [\#1097](https://github.com/pyviz/holoviews/pull/1097)), transposing - layouts (PR [\#1100](https://github.com/pyviz/holoviews/pull/1100)), - multiple paths (PR - [\#997](https://github.com/pyviz/holoviews/pull/997)), and norm for - ColorbarPlot (PR - [\#957](https://github.com/pyviz/holoviews/pull/957)). -- Improved options inheritance for more intuitive behavior (PR - [\#1275](https://github.com/pyviz/holoviews/pull/1275)). -- Image interface providing similar functionality for Image and - non-Image types (making GridImage obsolete) (PR - [\#994](https://github.com/pyviz/holoviews/pull/994)). -- Dask data interface (PR - [\#974](https://github.com/pyviz/holoviews/pull/974), - [\#991](https://github.com/pyviz/holoviews/pull/991)). -- xarray aggregate/reduce (PR - [\#1192](https://github.com/pyviz/holoviews/pull/1192)). -- Indicate color clipping and control clipping colors (PR - [\#686](https://github.com/pyviz/holoviews/pull/686)). -- Better datetime handling (PR - [\#1098](https://github.com/pyviz/holoviews/pull/1098)). -- Gridmatrix diagonal types (PR - [\#1194](https://github.com/pyviz/holoviews/pull/1194), - [\#1027](https://github.com/pyviz/holoviews/pull/1027)). -- log option for histogram operation (PR - [\#929](https://github.com/pyviz/holoviews/pull/929)). -- Perceptually uniform fire colormap (PR - [\#943](https://github.com/pyviz/holoviews/pull/943)). -- Support for adjoining overlays (PR - [\#1213](https://github.com/pyviz/holoviews/pull/1213)). -- coloring weighted average in SideHistogram (PR - [\#1087](https://github.com/pyviz/holoviews/pull/1087)). -- HeatMap allows displaying multiple values on hover (PR - [\#849](https://github.com/pyviz/holoviews/pull/849)). -- Allow casting Image to QuadMesh (PR - [\#1282](https://github.com/pyviz/holoviews/pull/1282)). -- Unused columns are now preserved in gridded groupby (PR - [\#1154](https://github.com/pyviz/holoviews/pull/1154)). -- Optimizations and fixes for constructing Layout/Overlay types (PR - [\#952](https://github.com/pyviz/holoviews/pull/952)). -- DynamicMap fixes (PR - [\#848](https://github.com/pyviz/holoviews/pull/848), - [\#883](https://github.com/pyviz/holoviews/pull/883), - [\#911](https://github.com/pyviz/holoviews/pull/911), - [\#922](https://github.com/pyviz/holoviews/pull/922), - [\#923](https://github.com/pyviz/holoviews/pull/923), - [\#927](https://github.com/pyviz/holoviews/pull/927), - [\#944](https://github.com/pyviz/holoviews/pull/944), - [\#1170](https://github.com/pyviz/holoviews/pull/1170), - [\#1227](https://github.com/pyviz/holoviews/pull/1227), - [\#1270](https://github.com/pyviz/holoviews/pull/1270)). -- Bokeh-backend fixes including handling of empty frames - ([\#835](https://github.com/pyviz/holoviews/pull/835)), faster - updates ([\#905](https://github.com/pyviz/holoviews/pull/905)), hover - tool fixes ([\#1004](https://github.com/pyviz/holoviews/pull/1004), - [\#1178](https://github.com/pyviz/holoviews/pull/1178), - [\#1092](https://github.com/pyviz/holoviews/pull/1092), - [\#1250](https://github.com/pyviz/holoviews/pull/1250)) and many more - (PR [\#537](https://github.com/pyviz/holoviews/pull/537), - [\#851](https://github.com/pyviz/holoviews/pull/851), - [\#852](https://github.com/pyviz/holoviews/pull/852), - [\#854](https://github.com/pyviz/holoviews/pull/854), - [\#880](https://github.com/pyviz/holoviews/pull/880), - [\#896](https://github.com/pyviz/holoviews/pull/896), - [\#898](https://github.com/pyviz/holoviews/pull/898), - [\#921](https://github.com/pyviz/holoviews/pull/921), - [\#934](https://github.com/pyviz/holoviews/pull/934), - [\#1004](https://github.com/pyviz/holoviews/pull/1004), - [\#1010](https://github.com/pyviz/holoviews/pull/1010), - [\#1014](https://github.com/pyviz/holoviews/pull/1014), - [\#1030](https://github.com/pyviz/holoviews/pull/1030), - [\#1069](https://github.com/pyviz/holoviews/pull/1069), - [\#1072](https://github.com/pyviz/holoviews/pull/1072), - [\#1085](https://github.com/pyviz/holoviews/pull/1085), - [\#1157](https://github.com/pyviz/holoviews/pull/1157), - [\#1086](https://github.com/pyviz/holoviews/pull/1086), - [\#1169](https://github.com/pyviz/holoviews/pull/1169), - [\#1195](https://github.com/pyviz/holoviews/pull/1195), - [\#1263](https://github.com/pyviz/holoviews/pull/1263)). -- Matplotlib-backend fixes and improvements (PR - [\#864](https://github.com/pyviz/holoviews/pull/864), - [\#873](https://github.com/pyviz/holoviews/pull/873), - [\#954](https://github.com/pyviz/holoviews/pull/954), - [\#1037](https://github.com/pyviz/holoviews/pull/1037), - [\#1068](https://github.com/pyviz/holoviews/pull/1068), - [\#1128](https://github.com/pyviz/holoviews/pull/1128), - [\#1132](https://github.com/pyviz/holoviews/pull/1132), - [\#1143](https://github.com/pyviz/holoviews/pull/1143), - [\#1163](https://github.com/pyviz/holoviews/pull/1163), - [\#1209](https://github.com/pyviz/holoviews/pull/1209), - [\#1211](https://github.com/pyviz/holoviews/pull/1211), - [\#1225](https://github.com/pyviz/holoviews/pull/1225), - [\#1269](https://github.com/pyviz/holoviews/pull/1269), - [\#1300](https://github.com/pyviz/holoviews/pull/1300)). -- Many other small improvements and fixes (PR - [\#830](https://github.com/pyviz/holoviews/pull/830), - [\#840](https://github.com/pyviz/holoviews/pull/840), - [\#841](https://github.com/pyviz/holoviews/pull/841), - [\#850](https://github.com/pyviz/holoviews/pull/850), - [\#855](https://github.com/pyviz/holoviews/pull/855), - [\#856](https://github.com/pyviz/holoviews/pull/856), - [\#859](https://github.com/pyviz/holoviews/pull/859), - [\#865](https://github.com/pyviz/holoviews/pull/865), - [\#893](https://github.com/pyviz/holoviews/pull/893), - [\#897](https://github.com/pyviz/holoviews/pull/897), - [\#902](https://github.com/pyviz/holoviews/pull/902), - [\#912](https://github.com/pyviz/holoviews/pull/912), - [\#916](https://github.com/pyviz/holoviews/pull/916), - [\#925](https://github.com/pyviz/holoviews/pull/925), - [\#938](https://github.com/pyviz/holoviews/pull/938), - [\#940](https://github.com/pyviz/holoviews/pull/940), - [\#948](https://github.com/pyviz/holoviews/pull/948), - [\#950](https://github.com/pyviz/holoviews/pull/950), - [\#955](https://github.com/pyviz/holoviews/pull/955), - [\#956](https://github.com/pyviz/holoviews/pull/956), - [\#967](https://github.com/pyviz/holoviews/pull/967), - [\#970](https://github.com/pyviz/holoviews/pull/970), - [\#972](https://github.com/pyviz/holoviews/pull/972), - [\#973](https://github.com/pyviz/holoviews/pull/973), - [\#981](https://github.com/pyviz/holoviews/pull/981), - [\#992](https://github.com/pyviz/holoviews/pull/992), - [\#998](https://github.com/pyviz/holoviews/pull/998), - [\#1009](https://github.com/pyviz/holoviews/pull/1009), - [\#1012](https://github.com/pyviz/holoviews/pull/1012), - [\#1016](https://github.com/pyviz/holoviews/pull/1016), - [\#1023](https://github.com/pyviz/holoviews/pull/1023), - [\#1034](https://github.com/pyviz/holoviews/pull/1034), - [\#1043](https://github.com/pyviz/holoviews/pull/1043), - [\#1045](https://github.com/pyviz/holoviews/pull/1045), - [\#1046](https://github.com/pyviz/holoviews/pull/1046), - [\#1048](https://github.com/pyviz/holoviews/pull/1048), - [\#1050](https://github.com/pyviz/holoviews/pull/1050), - [\#1051](https://github.com/pyviz/holoviews/pull/1051), - [\#1054](https://github.com/pyviz/holoviews/pull/1054), - [\#1060](https://github.com/pyviz/holoviews/pull/1060), - [\#1062](https://github.com/pyviz/holoviews/pull/1062), - [\#1074](https://github.com/pyviz/holoviews/pull/1074), - [\#1082](https://github.com/pyviz/holoviews/pull/1082), - [\#1084](https://github.com/pyviz/holoviews/pull/1084), - [\#1088](https://github.com/pyviz/holoviews/pull/1088), - [\#1093](https://github.com/pyviz/holoviews/pull/1093), - [\#1099](https://github.com/pyviz/holoviews/pull/1099), - [\#1115](https://github.com/pyviz/holoviews/pull/1115), - [\#1119](https://github.com/pyviz/holoviews/pull/1119), - [\#1121](https://github.com/pyviz/holoviews/pull/1121), - [\#1130](https://github.com/pyviz/holoviews/pull/1130), - [\#1133](https://github.com/pyviz/holoviews/pull/1133), - [\#1151](https://github.com/pyviz/holoviews/pull/1151), - [\#1152](https://github.com/pyviz/holoviews/pull/1152), - [\#1155](https://github.com/pyviz/holoviews/pull/1155), - [\#1156](https://github.com/pyviz/holoviews/pull/1156), - [\#1158](https://github.com/pyviz/holoviews/pull/1158), - [\#1162](https://github.com/pyviz/holoviews/pull/1162), - [\#1164](https://github.com/pyviz/holoviews/pull/1164), - [\#1174](https://github.com/pyviz/holoviews/pull/1174), - [\#1175](https://github.com/pyviz/holoviews/pull/1175), - [\#1180](https://github.com/pyviz/holoviews/pull/1180), - [\#1187](https://github.com/pyviz/holoviews/pull/1187), - [\#1197](https://github.com/pyviz/holoviews/pull/1197), - [\#1202](https://github.com/pyviz/holoviews/pull/1202), - [\#1205](https://github.com/pyviz/holoviews/pull/1205), - [\#1206](https://github.com/pyviz/holoviews/pull/1206), - [\#1210](https://github.com/pyviz/holoviews/pull/1210), - [\#1217](https://github.com/pyviz/holoviews/pull/1217), - [\#1219](https://github.com/pyviz/holoviews/pull/1219), - [\#1228](https://github.com/pyviz/holoviews/pull/1228), - [\#1232](https://github.com/pyviz/holoviews/pull/1232), - [\#1241](https://github.com/pyviz/holoviews/pull/1241), - [\#1244](https://github.com/pyviz/holoviews/pull/1244), - [\#1245](https://github.com/pyviz/holoviews/pull/1245), - [\#1249](https://github.com/pyviz/holoviews/pull/1249), - [\#1254](https://github.com/pyviz/holoviews/pull/1254), - [\#1255](https://github.com/pyviz/holoviews/pull/1255), - [\#1271](https://github.com/pyviz/holoviews/pull/1271), - [\#1276](https://github.com/pyviz/holoviews/pull/1276), - [\#1278](https://github.com/pyviz/holoviews/pull/1278), - [\#1285](https://github.com/pyviz/holoviews/pull/1285), - [\#1288](https://github.com/pyviz/holoviews/pull/1288), - [\#1289](https://github.com/pyviz/holoviews/pull/1289)). +- Operations for timeseries (PR + [\#1172](https://github.com/pyviz/holoviews/pull/1172)), + downsample_columns (PR + [\#903](https://github.com/pyviz/holoviews/pull/903)), + interpolate_curve (PR + [\#1097](https://github.com/pyviz/holoviews/pull/1097)), and stacked + area (PR [\#1193](https://github.com/pyviz/holoviews/pull/1193)). +- Dataset types can be declared as empty by passing an empty list (PR + [\#1355](https://github.com/pyviz/holoviews/pull/1355)) +- Plot or style options for Curve interpolation (PR + [\#1097](https://github.com/pyviz/holoviews/pull/1097)), transposing + layouts (PR [\#1100](https://github.com/pyviz/holoviews/pull/1100)), + multiple paths (PR + [\#997](https://github.com/pyviz/holoviews/pull/997)), and norm for + ColorbarPlot (PR + [\#957](https://github.com/pyviz/holoviews/pull/957)). +- Improved options inheritance for more intuitive behavior (PR + [\#1275](https://github.com/pyviz/holoviews/pull/1275)). +- Image interface providing similar functionality for Image and + non-Image types (making GridImage obsolete) (PR + [\#994](https://github.com/pyviz/holoviews/pull/994)). +- Dask data interface (PR + [\#974](https://github.com/pyviz/holoviews/pull/974), + [\#991](https://github.com/pyviz/holoviews/pull/991)). +- xarray aggregate/reduce (PR + [\#1192](https://github.com/pyviz/holoviews/pull/1192)). +- Indicate color clipping and control clipping colors (PR + [\#686](https://github.com/pyviz/holoviews/pull/686)). +- Better datetime handling (PR + [\#1098](https://github.com/pyviz/holoviews/pull/1098)). +- Gridmatrix diagonal types (PR + [\#1194](https://github.com/pyviz/holoviews/pull/1194), + [\#1027](https://github.com/pyviz/holoviews/pull/1027)). +- log option for histogram operation (PR + [\#929](https://github.com/pyviz/holoviews/pull/929)). +- Perceptually uniform fire colormap (PR + [\#943](https://github.com/pyviz/holoviews/pull/943)). +- Support for adjoining overlays (PR + [\#1213](https://github.com/pyviz/holoviews/pull/1213)). +- coloring weighted average in SideHistogram (PR + [\#1087](https://github.com/pyviz/holoviews/pull/1087)). +- HeatMap allows displaying multiple values on hover (PR + [\#849](https://github.com/pyviz/holoviews/pull/849)). +- Allow casting Image to QuadMesh (PR + [\#1282](https://github.com/pyviz/holoviews/pull/1282)). +- Unused columns are now preserved in gridded groupby (PR + [\#1154](https://github.com/pyviz/holoviews/pull/1154)). +- Optimizations and fixes for constructing Layout/Overlay types (PR + [\#952](https://github.com/pyviz/holoviews/pull/952)). +- DynamicMap fixes (PR + [\#848](https://github.com/pyviz/holoviews/pull/848), + [\#883](https://github.com/pyviz/holoviews/pull/883), + [\#911](https://github.com/pyviz/holoviews/pull/911), + [\#922](https://github.com/pyviz/holoviews/pull/922), + [\#923](https://github.com/pyviz/holoviews/pull/923), + [\#927](https://github.com/pyviz/holoviews/pull/927), + [\#944](https://github.com/pyviz/holoviews/pull/944), + [\#1170](https://github.com/pyviz/holoviews/pull/1170), + [\#1227](https://github.com/pyviz/holoviews/pull/1227), + [\#1270](https://github.com/pyviz/holoviews/pull/1270)). +- Bokeh-backend fixes including handling of empty frames + ([\#835](https://github.com/pyviz/holoviews/pull/835)), faster + updates ([\#905](https://github.com/pyviz/holoviews/pull/905)), hover + tool fixes ([\#1004](https://github.com/pyviz/holoviews/pull/1004), + [\#1178](https://github.com/pyviz/holoviews/pull/1178), + [\#1092](https://github.com/pyviz/holoviews/pull/1092), + [\#1250](https://github.com/pyviz/holoviews/pull/1250)) and many more + (PR [\#537](https://github.com/pyviz/holoviews/pull/537), + [\#851](https://github.com/pyviz/holoviews/pull/851), + [\#852](https://github.com/pyviz/holoviews/pull/852), + [\#854](https://github.com/pyviz/holoviews/pull/854), + [\#880](https://github.com/pyviz/holoviews/pull/880), + [\#896](https://github.com/pyviz/holoviews/pull/896), + [\#898](https://github.com/pyviz/holoviews/pull/898), + [\#921](https://github.com/pyviz/holoviews/pull/921), + [\#934](https://github.com/pyviz/holoviews/pull/934), + [\#1004](https://github.com/pyviz/holoviews/pull/1004), + [\#1010](https://github.com/pyviz/holoviews/pull/1010), + [\#1014](https://github.com/pyviz/holoviews/pull/1014), + [\#1030](https://github.com/pyviz/holoviews/pull/1030), + [\#1069](https://github.com/pyviz/holoviews/pull/1069), + [\#1072](https://github.com/pyviz/holoviews/pull/1072), + [\#1085](https://github.com/pyviz/holoviews/pull/1085), + [\#1157](https://github.com/pyviz/holoviews/pull/1157), + [\#1086](https://github.com/pyviz/holoviews/pull/1086), + [\#1169](https://github.com/pyviz/holoviews/pull/1169), + [\#1195](https://github.com/pyviz/holoviews/pull/1195), + [\#1263](https://github.com/pyviz/holoviews/pull/1263)). +- Matplotlib-backend fixes and improvements (PR + [\#864](https://github.com/pyviz/holoviews/pull/864), + [\#873](https://github.com/pyviz/holoviews/pull/873), + [\#954](https://github.com/pyviz/holoviews/pull/954), + [\#1037](https://github.com/pyviz/holoviews/pull/1037), + [\#1068](https://github.com/pyviz/holoviews/pull/1068), + [\#1128](https://github.com/pyviz/holoviews/pull/1128), + [\#1132](https://github.com/pyviz/holoviews/pull/1132), + [\#1143](https://github.com/pyviz/holoviews/pull/1143), + [\#1163](https://github.com/pyviz/holoviews/pull/1163), + [\#1209](https://github.com/pyviz/holoviews/pull/1209), + [\#1211](https://github.com/pyviz/holoviews/pull/1211), + [\#1225](https://github.com/pyviz/holoviews/pull/1225), + [\#1269](https://github.com/pyviz/holoviews/pull/1269), + [\#1300](https://github.com/pyviz/holoviews/pull/1300)). +- Many other small improvements and fixes (PR + [\#830](https://github.com/pyviz/holoviews/pull/830), + [\#840](https://github.com/pyviz/holoviews/pull/840), + [\#841](https://github.com/pyviz/holoviews/pull/841), + [\#850](https://github.com/pyviz/holoviews/pull/850), + [\#855](https://github.com/pyviz/holoviews/pull/855), + [\#856](https://github.com/pyviz/holoviews/pull/856), + [\#859](https://github.com/pyviz/holoviews/pull/859), + [\#865](https://github.com/pyviz/holoviews/pull/865), + [\#893](https://github.com/pyviz/holoviews/pull/893), + [\#897](https://github.com/pyviz/holoviews/pull/897), + [\#902](https://github.com/pyviz/holoviews/pull/902), + [\#912](https://github.com/pyviz/holoviews/pull/912), + [\#916](https://github.com/pyviz/holoviews/pull/916), + [\#925](https://github.com/pyviz/holoviews/pull/925), + [\#938](https://github.com/pyviz/holoviews/pull/938), + [\#940](https://github.com/pyviz/holoviews/pull/940), + [\#948](https://github.com/pyviz/holoviews/pull/948), + [\#950](https://github.com/pyviz/holoviews/pull/950), + [\#955](https://github.com/pyviz/holoviews/pull/955), + [\#956](https://github.com/pyviz/holoviews/pull/956), + [\#967](https://github.com/pyviz/holoviews/pull/967), + [\#970](https://github.com/pyviz/holoviews/pull/970), + [\#972](https://github.com/pyviz/holoviews/pull/972), + [\#973](https://github.com/pyviz/holoviews/pull/973), + [\#981](https://github.com/pyviz/holoviews/pull/981), + [\#992](https://github.com/pyviz/holoviews/pull/992), + [\#998](https://github.com/pyviz/holoviews/pull/998), + [\#1009](https://github.com/pyviz/holoviews/pull/1009), + [\#1012](https://github.com/pyviz/holoviews/pull/1012), + [\#1016](https://github.com/pyviz/holoviews/pull/1016), + [\#1023](https://github.com/pyviz/holoviews/pull/1023), + [\#1034](https://github.com/pyviz/holoviews/pull/1034), + [\#1043](https://github.com/pyviz/holoviews/pull/1043), + [\#1045](https://github.com/pyviz/holoviews/pull/1045), + [\#1046](https://github.com/pyviz/holoviews/pull/1046), + [\#1048](https://github.com/pyviz/holoviews/pull/1048), + [\#1050](https://github.com/pyviz/holoviews/pull/1050), + [\#1051](https://github.com/pyviz/holoviews/pull/1051), + [\#1054](https://github.com/pyviz/holoviews/pull/1054), + [\#1060](https://github.com/pyviz/holoviews/pull/1060), + [\#1062](https://github.com/pyviz/holoviews/pull/1062), + [\#1074](https://github.com/pyviz/holoviews/pull/1074), + [\#1082](https://github.com/pyviz/holoviews/pull/1082), + [\#1084](https://github.com/pyviz/holoviews/pull/1084), + [\#1088](https://github.com/pyviz/holoviews/pull/1088), + [\#1093](https://github.com/pyviz/holoviews/pull/1093), + [\#1099](https://github.com/pyviz/holoviews/pull/1099), + [\#1115](https://github.com/pyviz/holoviews/pull/1115), + [\#1119](https://github.com/pyviz/holoviews/pull/1119), + [\#1121](https://github.com/pyviz/holoviews/pull/1121), + [\#1130](https://github.com/pyviz/holoviews/pull/1130), + [\#1133](https://github.com/pyviz/holoviews/pull/1133), + [\#1151](https://github.com/pyviz/holoviews/pull/1151), + [\#1152](https://github.com/pyviz/holoviews/pull/1152), + [\#1155](https://github.com/pyviz/holoviews/pull/1155), + [\#1156](https://github.com/pyviz/holoviews/pull/1156), + [\#1158](https://github.com/pyviz/holoviews/pull/1158), + [\#1162](https://github.com/pyviz/holoviews/pull/1162), + [\#1164](https://github.com/pyviz/holoviews/pull/1164), + [\#1174](https://github.com/pyviz/holoviews/pull/1174), + [\#1175](https://github.com/pyviz/holoviews/pull/1175), + [\#1180](https://github.com/pyviz/holoviews/pull/1180), + [\#1187](https://github.com/pyviz/holoviews/pull/1187), + [\#1197](https://github.com/pyviz/holoviews/pull/1197), + [\#1202](https://github.com/pyviz/holoviews/pull/1202), + [\#1205](https://github.com/pyviz/holoviews/pull/1205), + [\#1206](https://github.com/pyviz/holoviews/pull/1206), + [\#1210](https://github.com/pyviz/holoviews/pull/1210), + [\#1217](https://github.com/pyviz/holoviews/pull/1217), + [\#1219](https://github.com/pyviz/holoviews/pull/1219), + [\#1228](https://github.com/pyviz/holoviews/pull/1228), + [\#1232](https://github.com/pyviz/holoviews/pull/1232), + [\#1241](https://github.com/pyviz/holoviews/pull/1241), + [\#1244](https://github.com/pyviz/holoviews/pull/1244), + [\#1245](https://github.com/pyviz/holoviews/pull/1245), + [\#1249](https://github.com/pyviz/holoviews/pull/1249), + [\#1254](https://github.com/pyviz/holoviews/pull/1254), + [\#1255](https://github.com/pyviz/holoviews/pull/1255), + [\#1271](https://github.com/pyviz/holoviews/pull/1271), + [\#1276](https://github.com/pyviz/holoviews/pull/1276), + [\#1278](https://github.com/pyviz/holoviews/pull/1278), + [\#1285](https://github.com/pyviz/holoviews/pull/1285), + [\#1288](https://github.com/pyviz/holoviews/pull/1288), + [\#1289](https://github.com/pyviz/holoviews/pull/1289)). Changes affecting backwards compatibility: -- Automatic coloring and sizing on Points now disabled (PR - [\#748](https://github.com/pyviz/holoviews/pull/748)). -- Deprecated max\_branches output magic option (PR - [\#1293](https://github.com/pyviz/holoviews/pull/1293)). -- Deprecated GridImage (PR - [\#1292](https://github.com/pyviz/holoviews/pull/1292), - [\#1223](https://github.com/pyviz/holoviews/pull/1223)). -- Deprecated NdElement (PR - [\#1191](https://github.com/pyviz/holoviews/pull/1191)). -- Deprecated DFrame conversion methods (PR - [\#1065](https://github.com/pyviz/holoviews/pull/1065)). -- Banner text removed from notebook\_extension() (PR - [\#1231](https://github.com/pyviz/holoviews/pull/1231), - [\#1291](https://github.com/pyviz/holoviews/pull/1291)). -- Bokeh's Matplotlib compatibility module removed (PR - [\#1239](https://github.com/pyviz/holoviews/pull/1239)). -- ls as Matplotlib linestyle alias dropped (PR - [\#1203](https://github.com/pyviz/holoviews/pull/1203)). -- mdims argument of conversion interface renamed to groupby (PR - [\#1066](https://github.com/pyviz/holoviews/pull/1066)). -- Replaced global alias state with Dimension.label - ([\#1083](https://github.com/pyviz/holoviews/pull/1083)). -- DynamicMap only update ranges when set to framewise -- Deprecated DynamicMap sampled, bounded, open and generator modes - ([\#969](https://github.com/pyviz/holoviews/pull/969), - [\#1305](https://github.com/pyviz/holoviews/pull/1305)) -- Layout.display method is now deprecated - ([\#1026](https://github.com/pyviz/holoviews/pull/1026)) -- Layout fix for Matplotlib figures with non-square aspects introduced - in 1.6.2 (PR [\#826](https://github.com/pyviz/holoviews/pull/826)), - now enabled by default. - -Version 1.6.2 -============= +- Automatic coloring and sizing on Points now disabled (PR + [\#748](https://github.com/pyviz/holoviews/pull/748)). +- Deprecated max_branches output magic option (PR + [\#1293](https://github.com/pyviz/holoviews/pull/1293)). +- Deprecated GridImage (PR + [\#1292](https://github.com/pyviz/holoviews/pull/1292), + [\#1223](https://github.com/pyviz/holoviews/pull/1223)). +- Deprecated NdElement (PR + [\#1191](https://github.com/pyviz/holoviews/pull/1191)). +- Deprecated DFrame conversion methods (PR + [\#1065](https://github.com/pyviz/holoviews/pull/1065)). +- Banner text removed from notebook_extension() (PR + [\#1231](https://github.com/pyviz/holoviews/pull/1231), + [\#1291](https://github.com/pyviz/holoviews/pull/1291)). +- Bokeh's Matplotlib compatibility module removed (PR + [\#1239](https://github.com/pyviz/holoviews/pull/1239)). +- ls as Matplotlib linestyle alias dropped (PR + [\#1203](https://github.com/pyviz/holoviews/pull/1203)). +- mdims argument of conversion interface renamed to groupby (PR + [\#1066](https://github.com/pyviz/holoviews/pull/1066)). +- Replaced global alias state with Dimension.label + ([\#1083](https://github.com/pyviz/holoviews/pull/1083)). +- DynamicMap only update ranges when set to framewise +- Deprecated DynamicMap sampled, bounded, open and generator modes + ([\#969](https://github.com/pyviz/holoviews/pull/969), + [\#1305](https://github.com/pyviz/holoviews/pull/1305)) +- Layout.display method is now deprecated + ([\#1026](https://github.com/pyviz/holoviews/pull/1026)) +- Layout fix for Matplotlib figures with non-square aspects introduced + in 1.6.2 (PR [\#826](https://github.com/pyviz/holoviews/pull/826)), + now enabled by default. + +# Version 1.6.2 + **August 23, 2016** Bug fix release with various fixes for gridded data backends and optimizations for Bokeh. -- Optimized Bokeh event messaging, reducing the average json payload - by 30-50% (PR [\#807](https://github.com/pyviz/holoviews/pull/807)). -- Fixes for correctly handling NdOverlay types returned by DynamicMaps - (PR [\#814](https://github.com/pyviz/holoviews/pull/814)). -- Added support for datetime64 handling in Matplotlib and support for - datetime formatters on Dimension.type\_formatters (PR - [\#816](https://github.com/pyviz/holoviews/pull/816)). -- Fixed handling of constant dimensions when slicing xarray datasets - (PR [\#817](https://github.com/pyviz/holoviews/pull/817)). -- Fixed support for passing custom dimensions to iris Datasets (PR - [\#818](https://github.com/pyviz/holoviews/pull/818)). -- Fixed support for add\_dimension on xarray interface (PR - [\#820](https://github.com/pyviz/holoviews/pull/820)). -- Improved extents computation on Matplotlib SpreadPlot (PR - [\#821](https://github.com/pyviz/holoviews/pull/821)). -- Bokeh backend avoids sending data for static frames and empty events - (PR [\#822](https://github.com/pyviz/holoviews/pull/822)). -- Added major layout fix for figures with non-square aspects, reducing - the amount of unnecessary whitespace (PR - [\#826](https://github.com/pyviz/holoviews/pull/826)). Disabled by - default until 1.7 release but can be enabled with: - -``` {.sourceCode .python} +- Optimized Bokeh event messaging, reducing the average json payload + by 30-50% (PR [\#807](https://github.com/pyviz/holoviews/pull/807)). +- Fixes for correctly handling NdOverlay types returned by DynamicMaps + (PR [\#814](https://github.com/pyviz/holoviews/pull/814)). +- Added support for datetime64 handling in Matplotlib and support for + datetime formatters on Dimension.type_formatters (PR + [\#816](https://github.com/pyviz/holoviews/pull/816)). +- Fixed handling of constant dimensions when slicing xarray datasets + (PR [\#817](https://github.com/pyviz/holoviews/pull/817)). +- Fixed support for passing custom dimensions to iris Datasets (PR + [\#818](https://github.com/pyviz/holoviews/pull/818)). +- Fixed support for add_dimension on xarray interface (PR + [\#820](https://github.com/pyviz/holoviews/pull/820)). +- Improved extents computation on Matplotlib SpreadPlot (PR + [\#821](https://github.com/pyviz/holoviews/pull/821)). +- Bokeh backend avoids sending data for static frames and empty events + (PR [\#822](https://github.com/pyviz/holoviews/pull/822)). +- Added major layout fix for figures with non-square aspects, reducing + the amount of unnecessary whitespace (PR + [\#826](https://github.com/pyviz/holoviews/pull/826)). Disabled by + default until 1.7 release but can be enabled with: + +```{.sourceCode .python} from holoviews.plotting.mpl import LayoutPlot LayoutPlot.v17_layout_format = True LayoutPlot.vspace = 0.3 ``` -Version 1.6.1 -============= +# Version 1.6.1 + **July 27, 2016** Bug fix release following the 1.6 major release with major bug fixes for the grid data interfaces and improvements to the options system. -- Ensured that style options incompatible with active backend are - ignored (PR [\#802](https://github.com/pyviz/holoviews/pull/802)). -- Added support for placing legends outside the plot area in Bokeh (PR - [\#801](https://github.com/pyviz/holoviews/pull/801)). -- Fix to ensure Bokeh backend does not depend on pandas (PR - [\#792](https://github.com/pyviz/holoviews/pull/792)). -- Fixed option system to ensure correct inheritance when redefining - options (PR [\#796](https://github.com/pyviz/holoviews/pull/796)). -- Major refactor and fixes for the grid based data backends (iris, - xarray and arrays with coordinates) ensuring the data is oriented - and transposed correctly (PR - [\#794](https://github.com/pyviz/holoviews/pull/794)). - -Version 1.6 -=========== +- Ensured that style options incompatible with active backend are + ignored (PR [\#802](https://github.com/pyviz/holoviews/pull/802)). +- Added support for placing legends outside the plot area in Bokeh (PR + [\#801](https://github.com/pyviz/holoviews/pull/801)). +- Fix to ensure Bokeh backend does not depend on pandas (PR + [\#792](https://github.com/pyviz/holoviews/pull/792)). +- Fixed option system to ensure correct inheritance when redefining + options (PR [\#796](https://github.com/pyviz/holoviews/pull/796)). +- Major refactor and fixes for the grid based data backends (iris, + xarray and arrays with coordinates) ensuring the data is oriented + and transposed correctly (PR + [\#794](https://github.com/pyviz/holoviews/pull/794)). + +# Version 1.6 + **July 14, 2016** A major release with an optional new data interface based on xarray, @@ -3451,30 +3402,30 @@ support for Bokeh 0.12 and various other fixes and improvements. Features and improvements: -- Made VectorFieldPlot more general with support for independent - coloring and scaling (PR - [\#701](https://github.com/pyviz/holoviews/pull/701)). -- Iris interface now allows tuple and dict formats in the constructor - (PR [\#709](https://github.com/pyviz/holoviews/pull/709). -- Added support for dynamic groupby on all data interfaces (PR - [\#711](https://github.com/pyviz/holoviews/pull/711)). -- Added an xarray data interface (PR - [\#713](https://github.com/pyviz/holoviews/pull/713)). -- Added the redim method to all Dimensioned objects making it easy to - quickly change dimension names and attributes on nested objects - [\#715](https://github.com/pyviz/holoviews/pull/715)). -- Added support for batching plots (PR - [\#715](https://github.com/pyviz/holoviews/pull/717)). -- Support for Bokeh 0.12 release (PR - [\#725](https://github.com/pyviz/holoviews/pull/725)). -- Added support for logz option on Bokeh Raster plots (PR - [\#729](https://github.com/pyviz/holoviews/pull/729)). -- Bokeh plots now support custom tick formatters specified via - Dimension value\_format (PR - [\#728](https://github.com/pyviz/holoviews/pull/728)). - -Version 1.5 -=========== +- Made VectorFieldPlot more general with support for independent + coloring and scaling (PR + [\#701](https://github.com/pyviz/holoviews/pull/701)). +- Iris interface now allows tuple and dict formats in the constructor + (PR [\#709](https://github.com/pyviz/holoviews/pull/709). +- Added support for dynamic groupby on all data interfaces (PR + [\#711](https://github.com/pyviz/holoviews/pull/711)). +- Added an xarray data interface (PR + [\#713](https://github.com/pyviz/holoviews/pull/713)). +- Added the redim method to all Dimensioned objects making it easy to + quickly change dimension names and attributes on nested objects + [\#715](https://github.com/pyviz/holoviews/pull/715)). +- Added support for batching plots (PR + [\#715](https://github.com/pyviz/holoviews/pull/717)). +- Support for Bokeh 0.12 release (PR + [\#725](https://github.com/pyviz/holoviews/pull/725)). +- Added support for logz option on Bokeh Raster plots (PR + [\#729](https://github.com/pyviz/holoviews/pull/729)). +- Bokeh plots now support custom tick formatters specified via + Dimension value_format (PR + [\#728](https://github.com/pyviz/holoviews/pull/728)). + +# Version 1.5 + **May 12, 2016** A major release with a large number of new features including new data @@ -3483,93 +3434,93 @@ large number of bug fixes. Features and improvements: -- Added a grid based data interface to explore n-dimensional gridded - data easily (PR - [\#562](https://github.com/pyviz/holoviews/pull/542)). -- Added data interface based on [iris - Cubes](http://scitools.org.uk/iris/docs/v1.9.2/index.html) (PR - [\#624](https://github.com/pyviz/holoviews/pull/624)). -- Added support for dynamic operations and overlaying of DynamicMaps - (PR [\#588](https://github.com/pyviz/holoviews/pull/588)). -- Added support for applying groupby operations to DynamicMaps (PR - [\#667](https://github.com/pyviz/holoviews/pull/667)). -- Added dimension value formatting in widgets (PR - [\#562](https://github.com/pyviz/holoviews/issues/562)). -- Added support for indexing and slicing with a function (PR - [\#619](https://github.com/pyviz/holoviews/pull/619)). -- Improved throttling behavior on widgets (PR - [\#596](https://github.com/pyviz/holoviews/pull/596)). -- Major refactor of Matplotlib plotting classes to simplify - implementing new Element plots (PR - [\#438](https://github.com/pyviz/holoviews/pull/438)). -- Added Renderer.last\_plot attribute to allow easily debugging or - modifying the last displayed plot (PR - [\#538](https://github.com/pyviz/holoviews/pull/538)). -- Added Bokeh QuadMeshPlot (PR - [\#661](https://github.com/pyviz/holoviews/pull/661)). +- Added a grid based data interface to explore n-dimensional gridded + data easily (PR + [\#562](https://github.com/pyviz/holoviews/pull/542)). +- Added data interface based on [iris + Cubes](http://scitools.org.uk/iris/docs/v1.9.2/index.html) (PR + [\#624](https://github.com/pyviz/holoviews/pull/624)). +- Added support for dynamic operations and overlaying of DynamicMaps + (PR [\#588](https://github.com/pyviz/holoviews/pull/588)). +- Added support for applying groupby operations to DynamicMaps (PR + [\#667](https://github.com/pyviz/holoviews/pull/667)). +- Added dimension value formatting in widgets (PR + [\#562](https://github.com/pyviz/holoviews/issues/562)). +- Added support for indexing and slicing with a function (PR + [\#619](https://github.com/pyviz/holoviews/pull/619)). +- Improved throttling behavior on widgets (PR + [\#596](https://github.com/pyviz/holoviews/pull/596)). +- Major refactor of Matplotlib plotting classes to simplify + implementing new Element plots (PR + [\#438](https://github.com/pyviz/holoviews/pull/438)). +- Added Renderer.last_plot attribute to allow easily debugging or + modifying the last displayed plot (PR + [\#538](https://github.com/pyviz/holoviews/pull/538)). +- Added Bokeh QuadMeshPlot (PR + [\#661](https://github.com/pyviz/holoviews/pull/661)). Bug fixes: -- Fixed overlaying of 3D Element types (PR - [\#504](https://github.com/pyviz/holoviews/pull/504)). -- Fix for Bokeh hovertools with dimensions with special characters (PR - [\#524](https://github.com/pyviz/holoviews/pull/524)). -- Fixed bugs in seaborn Distribution Element (PR - [\#630](https://github.com/pyviz/holoviews/pull/630)). -- Fix for inverted Raster.reduce method (PR - [\#672](https://github.com/pyviz/holoviews/pull/672)). -- Fixed Store.add\_style\_opts method (PR - [\#587](https://github.com/pyviz/holoviews/pull/587)). -- Fixed bug preventing simultaneous logx and logy plot options (PR - [\#554](https://github.com/pyviz/holoviews/pull/554)). +- Fixed overlaying of 3D Element types (PR + [\#504](https://github.com/pyviz/holoviews/pull/504)). +- Fix for Bokeh hovertools with dimensions with special characters (PR + [\#524](https://github.com/pyviz/holoviews/pull/524)). +- Fixed bugs in seaborn Distribution Element (PR + [\#630](https://github.com/pyviz/holoviews/pull/630)). +- Fix for inverted Raster.reduce method (PR + [\#672](https://github.com/pyviz/holoviews/pull/672)). +- Fixed Store.add_style_opts method (PR + [\#587](https://github.com/pyviz/holoviews/pull/587)). +- Fixed bug preventing simultaneous logx and logy plot options (PR + [\#554](https://github.com/pyviz/holoviews/pull/554)). Backwards compatibility: -- Renamed `Columns` type to `Dataset` (PR - [\#620](https://github.com/pyviz/holoviews/issues/620)). +- Renamed `Columns` type to `Dataset` (PR + [\#620](https://github.com/pyviz/holoviews/issues/620)). + +# Version 1.4.3 -Version 1.4.3 -============= **February 11, 2016** A minor bugfix release to patch a number of small but important issues. Fixes and improvements: -- Added a [DynamicMap - Tutorial](http://holoviews.org/Tutorials/Dynamic_Map.html) to - explain how to explore very large or continuous parameter spaces in - HoloViews ([PR - \#470](https://github.com/pyviz/holoviews/issues/470)). -- Various fixes and improvements for DynamicMaps including slicing - ([PR \#488](https://github.com/pyviz/holoviews/issues/488)) and - validation ([PR - \#483](https://github.com/pyviz/holoviews/issues/478)) and - serialization ([PR - \#483](https://github.com/pyviz/holoviews/issues/478)) -- Widgets containing Matplotlib plots now display the first frame from - cache providing at least the initial frame when exporting - DynamicMaps ([PR - \#486](https://github.com/pyviz/holoviews/issues/483)) -- Fixed plotting Bokeh plots using widgets in live mode, after changes - introduced in latest Bokeh version (commit - [1b87c91e9](https://github.com/pyviz/holoviews/commit/1b87c91e9e7cf35b267344ccd4a2fa91dd052890)). -- Fixed issue in coloring Point/Scatter objects by values ([Issue - \#467](https://github.com/pyviz/holoviews/issues/467)). +- Added a [DynamicMap + Tutorial](http://holoviews.org/Tutorials/Dynamic_Map.html) to + explain how to explore very large or continuous parameter spaces in + HoloViews ([PR + \#470](https://github.com/pyviz/holoviews/issues/470)). +- Various fixes and improvements for DynamicMaps including slicing + ([PR \#488](https://github.com/pyviz/holoviews/issues/488)) and + validation ([PR + \#483](https://github.com/pyviz/holoviews/issues/478)) and + serialization ([PR + \#483](https://github.com/pyviz/holoviews/issues/478)) +- Widgets containing Matplotlib plots now display the first frame from + cache providing at least the initial frame when exporting + DynamicMaps ([PR + \#486](https://github.com/pyviz/holoviews/issues/483)) +- Fixed plotting Bokeh plots using widgets in live mode, after changes + introduced in latest Bokeh version (commit + [1b87c91e9](https://github.com/pyviz/holoviews/commit/1b87c91e9e7cf35b267344ccd4a2fa91dd052890)). +- Fixed issue in coloring Point/Scatter objects by values ([Issue + \#467](https://github.com/pyviz/holoviews/issues/467)). Backwards compatibility: -- The behavior of the `scaling_factor` on Point and Scatter plots has - changed now simply multiplying `area` or `width` (as defined by the - `scaling_method`). To disable scaling points by a dimension set - `size_index=None`. -- Removed hooks to display 3D Elements using the `BokehMPLRawWrapper` - in Bokeh ([PR \#477](https://github.com/pyviz/holoviews/pull/477)) -- Renamed the DynamicMap mode `closed` to `bounded` ([PR - \#477](https://github.com/pyviz/holoviews/pull/485)) - -Version 1.4.2 -============= +- The behavior of the `scaling_factor` on Point and Scatter plots has + changed now simply multiplying `area` or `width` (as defined by the + `scaling_method`). To disable scaling points by a dimension set + `size_index=None`. +- Removed hooks to display 3D Elements using the `BokehMPLRawWrapper` + in Bokeh ([PR \#477](https://github.com/pyviz/holoviews/pull/477)) +- Renamed the DynamicMap mode `closed` to `bounded` ([PR + \#477](https://github.com/pyviz/holoviews/pull/485)) + +# Version 1.4.2 + **February 7, 2016** Over the past month since the 1.4.1 release, we have improved our @@ -3578,44 +3529,44 @@ made several additional usability improvements. Documentation changes: -- Major overhaul of website and notebook building making it much - easier to test user contributions ([Issue - \#180](https://github.com/pyviz/holoviews/issues/180), [PR - \#429](https://github.com/pyviz/holoviews/pull/429)) -- Major rewrite of the documentation ([PR - \#401](https://github.com/pyviz/holoviews/pull/401), [PR - \#411](https://github.com/pyviz/holoviews/pull/411)) -- Added Columnar Data Tutorial and removed most of Pandas Conversions - as it is now supported by the core. +- Major overhaul of website and notebook building making it much + easier to test user contributions ([Issue + \#180](https://github.com/pyviz/holoviews/issues/180), [PR + \#429](https://github.com/pyviz/holoviews/pull/429)) +- Major rewrite of the documentation ([PR + \#401](https://github.com/pyviz/holoviews/pull/401), [PR + \#411](https://github.com/pyviz/holoviews/pull/411)) +- Added Columnar Data Tutorial and removed most of Pandas Conversions + as it is now supported by the core. Fixes and improvements: -- Major improvement for grid based layouts with varying aspects ([PR - \#457](https://github.com/pyviz/holoviews/pull/457)) -- Fix for interleaving %matplotline inline and holoviews plots ([Issue - \#179](https://github.com/pyviz/holoviews/issues/179)) -- Matplotlib legend z-orders and updating fixed ([Issue - \#304](https://github.com/pyviz/holoviews/issues/304), [Issue - \#305](https://github.com/pyviz/holoviews/issues/305)) -- `color_index` and `size_index` plot options support specifying - dimension by name ([Issue - \#391](https://github.com/pyviz/holoviews/issues/391)) -- Added `Area` Element type for drawing area under or between Curves. - ([PR \#427](https://github.com/pyviz/holoviews/pull/427)) -- Fixed issues where slicing would remove styles applied to - an Element. ([Issue - \#423](https://github.com/pyviz/holoviews/issues/423), [PR - \#439](https://github.com/pyviz/holoviews/pull/439)) -- Updated the `title_format` plot option to support a `{dimensions}` - formatter ([PR \#436](https://github.com/pyviz/holoviews/pull/436)) -- Improvements to Renderer API to allow JS and CSS requirements for - exporting standalone widgets ([PR - \#426](https://github.com/pyviz/holoviews/pull/426)) -- Compatibility with the latest Bokeh 0.11 release ([PR - \#393](https://github.com/pyviz/holoviews/pull/393)) - -Version 1.4.1 -============= +- Major improvement for grid based layouts with varying aspects ([PR + \#457](https://github.com/pyviz/holoviews/pull/457)) +- Fix for interleaving %matplotline inline and holoviews plots ([Issue + \#179](https://github.com/pyviz/holoviews/issues/179)) +- Matplotlib legend z-orders and updating fixed ([Issue + \#304](https://github.com/pyviz/holoviews/issues/304), [Issue + \#305](https://github.com/pyviz/holoviews/issues/305)) +- `color_index` and `size_index` plot options support specifying + dimension by name ([Issue + \#391](https://github.com/pyviz/holoviews/issues/391)) +- Added `Area` Element type for drawing area under or between Curves. + ([PR \#427](https://github.com/pyviz/holoviews/pull/427)) +- Fixed issues where slicing would remove styles applied to + an Element. ([Issue + \#423](https://github.com/pyviz/holoviews/issues/423), [PR + \#439](https://github.com/pyviz/holoviews/pull/439)) +- Updated the `title_format` plot option to support a `{dimensions}` + formatter ([PR \#436](https://github.com/pyviz/holoviews/pull/436)) +- Improvements to Renderer API to allow JS and CSS requirements for + exporting standalone widgets ([PR + \#426](https://github.com/pyviz/holoviews/pull/426)) +- Compatibility with the latest Bokeh 0.11 release ([PR + \#393](https://github.com/pyviz/holoviews/pull/393)) + +# Version 1.4.1 + **December 22, 2015** Over the past two weeks since the 1.4 release, we have implemented @@ -3624,46 +3575,46 @@ improvements. New features: -- Improved help system. It is now possible to recursively list all the - applicable documentation for a composite object. In addition, the - documentation may now be filtered using a regular - expression pattern. ([PR - \#370](https://github.com/pyviz/holoviews/pull/370)) -- HoloViews now supports multiple active display hooks making it - easier to use nbconvert. For instance, PNG data will be embedded in - the notebook if the argument display\_formats=\['html','png'\] is - supplied to the notebook\_extension. ([PR - \#355](https://github.com/pyviz/holoviews/pull/355)) -- Improvements to the display of DynamicMaps as well as many new - improvements to the Bokeh backend including better VLines/HLines and - support for the Bars element. ([PR - \#367](https://github.com/pyviz/holoviews/pull/367) , [PR - \#362](https://github.com/pyviz/holoviews/pull/362), [PR - \#339](https://github.com/pyviz/holoviews/pull/339)). -- New Spikes and BoxWhisker elements suitable for representing - distributions as a sequence of lines or as a box-and-whisker plot. - ([PR \#346](https://github.com/pyviz/holoviews/pull/346), [PR - \#339](https://github.com/pyviz/holoviews/pull/339)) -- Improvements to the notebook\_extension. For instance, - executing hv.notebook\_extension('bokeh') will now load BokehJS and - automatically activate the Bokeh backend (if available). -- Significant performance improvements when using the groupby - operation on HoloMaps and when working with highly - nested datastructures. ([PR - \#349](https://github.com/pyviz/holoviews/pull/349), [PR - \#359](https://github.com/pyviz/holoviews/pull/359)) +- Improved help system. It is now possible to recursively list all the + applicable documentation for a composite object. In addition, the + documentation may now be filtered using a regular + expression pattern. ([PR + \#370](https://github.com/pyviz/holoviews/pull/370)) +- HoloViews now supports multiple active display hooks making it + easier to use nbconvert. For instance, PNG data will be embedded in + the notebook if the argument display_formats=\['html','png'\] is + supplied to the notebook_extension. ([PR + \#355](https://github.com/pyviz/holoviews/pull/355)) +- Improvements to the display of DynamicMaps as well as many new + improvements to the Bokeh backend including better VLines/HLines and + support for the Bars element. ([PR + \#367](https://github.com/pyviz/holoviews/pull/367) , [PR + \#362](https://github.com/pyviz/holoviews/pull/362), [PR + \#339](https://github.com/pyviz/holoviews/pull/339)). +- New Spikes and BoxWhisker elements suitable for representing + distributions as a sequence of lines or as a box-and-whisker plot. + ([PR \#346](https://github.com/pyviz/holoviews/pull/346), [PR + \#339](https://github.com/pyviz/holoviews/pull/339)) +- Improvements to the notebook_extension. For instance, + executing hv.notebook_extension('bokeh') will now load BokehJS and + automatically activate the Bokeh backend (if available). +- Significant performance improvements when using the groupby + operation on HoloMaps and when working with highly + nested datastructures. ([PR + \#349](https://github.com/pyviz/holoviews/pull/349), [PR + \#359](https://github.com/pyviz/holoviews/pull/359)) Notable bug fixes: -- DynamicMaps are now properly integrated into the style system and - can be customized in the same way as HoloMaps. ([PR - \#368](https://github.com/pyviz/holoviews/pull/368)) -- Widgets now work correctly when unicode is used in the dimension - labels and values ([PR - \#376](https://github.com/pyviz/holoviews/pull/376)). +- DynamicMaps are now properly integrated into the style system and + can be customized in the same way as HoloMaps. ([PR + \#368](https://github.com/pyviz/holoviews/pull/368)) +- Widgets now work correctly when unicode is used in the dimension + labels and values ([PR + \#376](https://github.com/pyviz/holoviews/pull/376)). + +# Version 1.4.0 -Version 1.4.0 -============= **December 4, 2015** Over the past few months we have added several major new features and @@ -3673,89 +3624,89 @@ commits. Major new features: -- Data API: The new data API brings an extensible system of to add new - data interfaces to column based Element types. These interfaces - allow applying powerful operations on the data independently of the - data format. The currently supported datatypes include NumPy, pandas - dataframes and a simple dictionary format. ([PR - \#284](https://github.com/pyviz/holoviews/pull/284)) -- Backend API: In this release we completely refactored the rendering, - plotting and IPython display system to make it easy to add new - plotting backends. Data may be styled and pickled for each backend - independently and renderers now support exporting all plotting data - including widgets as standalone HTML files or with separate - JSON data. -- Bokeh backend: The first new plotting backend added via the new - backend API. Bokeh plots allow for much faster plotting and - greater interactivity. Supports most Element types and layouts and - provides facilities for sharing axes across plots and linked - brushing across plots. ([PR - \#250](https://github.com/pyviz/holoviews/pull/250)) -- DynamicMap: The new DynamicMap class allows HoloMap data to be - generated on-the-fly while running a Jupyter IPython - notebook kernel. Allows visualization of unbounded data streams and - smooth exploration of large continuous parameter spaces. ([PR - \#278](https://github.com/pyviz/holoviews/pull/278)) +- Data API: The new data API brings an extensible system of to add new + data interfaces to column based Element types. These interfaces + allow applying powerful operations on the data independently of the + data format. The currently supported datatypes include NumPy, pandas + dataframes and a simple dictionary format. ([PR + \#284](https://github.com/pyviz/holoviews/pull/284)) +- Backend API: In this release we completely refactored the rendering, + plotting and IPython display system to make it easy to add new + plotting backends. Data may be styled and pickled for each backend + independently and renderers now support exporting all plotting data + including widgets as standalone HTML files or with separate + JSON data. +- Bokeh backend: The first new plotting backend added via the new + backend API. Bokeh plots allow for much faster plotting and + greater interactivity. Supports most Element types and layouts and + provides facilities for sharing axes across plots and linked + brushing across plots. ([PR + \#250](https://github.com/pyviz/holoviews/pull/250)) +- DynamicMap: The new DynamicMap class allows HoloMap data to be + generated on-the-fly while running a Jupyter IPython + notebook kernel. Allows visualization of unbounded data streams and + smooth exploration of large continuous parameter spaces. ([PR + \#278](https://github.com/pyviz/holoviews/pull/278)) Other features: -- Easy definition of custom aliases for group, label and Dimension - names, allowing easier use of LaTeX. -- New Trisurface and QuadMesh elements. -- Widgets now allow expressing hierarchical relationships - between dimensions. -- Added GridMatrix container for heterogeneous Elements and gridmatrix - operation to generate scatter matrix showing relationship - between dimensions. -- Filled contour regions can now be generated using the - contours operation. -- Consistent indexing semantics for all Elements and support for - boolean indexing for Columns and NdMapping types. -- New hv.notebook\_extension function offers a more flexible - alternative to %load\_ext, e.g. for loading other - extensions hv.notebook\_extension(bokeh=True). +- Easy definition of custom aliases for group, label and Dimension + names, allowing easier use of LaTeX. +- New Trisurface and QuadMesh elements. +- Widgets now allow expressing hierarchical relationships + between dimensions. +- Added GridMatrix container for heterogeneous Elements and gridmatrix + operation to generate scatter matrix showing relationship + between dimensions. +- Filled contour regions can now be generated using the + contours operation. +- Consistent indexing semantics for all Elements and support for + boolean indexing for Columns and NdMapping types. +- New hv.notebook_extension function offers a more flexible + alternative to %load_ext, e.g. for loading other + extensions hv.notebook_extension(bokeh=True). Experimental features: -- Bokeh callbacks allow adding interactivity by communicating between - BokehJS tools and the IPython kernel, e.g. allowing downsampling - based on the zoom level. +- Bokeh callbacks allow adding interactivity by communicating between + BokehJS tools and the IPython kernel, e.g. allowing downsampling + based on the zoom level. Notable bug fixes: -- Major speedup rendering large HoloMaps (\~ 2-3 times faster). -- Colorbars now consistent for all plot configurations. -- Style pickling now works correctly. +- Major speedup rendering large HoloMaps (\~ 2-3 times faster). +- Colorbars now consistent for all plot configurations. +- Style pickling now works correctly. API Changes: -- Dimension formatter parameter now deprecated in favor - of value\_format. -- Types of Chart and Table Element data now dependent on - selected interface. -- DFrame conversion interface deprecated in favor of Columns - pandas interface. +- Dimension formatter parameter now deprecated in favor + of value_format. +- Types of Chart and Table Element data now dependent on + selected interface. +- DFrame conversion interface deprecated in favor of Columns + pandas interface. + +# Version 1.3.2 -Version 1.3.2 -============= **July 6, 2015** Minor bugfix release to address a small number of issues: Features: -- Added support for colorbars on Surface Element (1cd5281). -- Added linewidth style option to SurfacePlot (9b6ccc5). +- Added support for colorbars on Surface Element (1cd5281). +- Added linewidth style option to SurfacePlot (9b6ccc5). Bug fixes: -- Fixed inversion inversion of y-range during sampling (6ff81bb). -- Fixed overlaying of 3D elements (787d511). -- Ensuring that underscore.js is loaded in widgets (f2f6378). -- Fixed Python3 issue in Overlay.get (8ceabe3). +- Fixed inversion inversion of y-range during sampling (6ff81bb). +- Fixed overlaying of 3D elements (787d511). +- Ensuring that underscore.js is loaded in widgets (f2f6378). +- Fixed Python3 issue in Overlay.get (8ceabe3). + +# Version 1.3.1 -Version 1.3.1 -============= **July 1, 2015** Minor bugfix release to address a number of issues that weren't caught @@ -3764,21 +3715,21 @@ features: Features: -- Introduced new `Spread` element to plot errors and confidence - intervals (30d3184). -- `ErrorBars` and `Spread` elements now allow most Chart constructor - types (f013deb). +- Introduced new `Spread` element to plot errors and confidence + intervals (30d3184). +- `ErrorBars` and `Spread` elements now allow most Chart constructor + types (f013deb). Bug fixes: -- Fixed unicode handling for dimension labels (061e9af). -- Handling of invalid dimension label characters in widgets (a101b9e). -- Fixed setting of fps option for MPLRenderer video output (c61b9df). -- Fix for multiple and animated colorbars (5e1e4b5). -- Fix to Chart slices starting or ending at zero (edd0039). +- Fixed unicode handling for dimension labels (061e9af). +- Handling of invalid dimension label characters in widgets (a101b9e). +- Fixed setting of fps option for MPLRenderer video output (c61b9df). +- Fix for multiple and animated colorbars (5e1e4b5). +- Fix to Chart slices starting or ending at zero (edd0039). + +# Version 1.3.0 -Version 1.3.0 -============= **June 27, 2015** Since the last release we closed over 34 issues and have made 380 @@ -3792,58 +3743,58 @@ number of important bugs. Highlights/Features: -- Allowed display of data structures which do not match the - recommended nesting hierarchy (67b28f3, fbd89c3). -- Dimensions now sanitized for `.select`, `.sample` and `.reduce` - calls (6685633, 00b5a66). -- Added `holoviews.ipython.display` function to render (and display) - any HoloViews object, useful for IPython interact widgets (0fa49cd). -- Table column widths now adapt to cell contents (be90a54). -- Defaulting to Matplotlib ticking behavior (62e1e58). -- Allowed specifying fixed figure sizes to Matplotlib via `fig_inches` - tuples using (width, None) and (None, height) formats (632facd). -- Constructors of `Chart`, `Path` and `Histogram` classes now support - additional data formats (2297375). -- `ScrubberWidget` now supports all figure formats (c317db4). -- Allowed customizing legend positions on `Bars` Elements (5a12882). -- Support for multiple colorbars on one axis (aac7b92). -- `.reindex` on `NdElement` types now support converting between key - and value dimensions allowing more powerful conversions. (03ac3ce) -- Improved support for casting between `Element` types (cdaab4e, - b2ad91b, ce7fe2d, 865b4d5). -- The `%%opts` cell magic may now be used multiple times in the same - cell (2a77fd0) -- Matplotlib rcParams can now be set correctly per figure (751210f). -- Improved `OptionTree` repr which now works with eval (2f824c1). -- Refactor of rendering system and IPython extension to allow easy - swapping of plotting backend (\#141) -- Large plotting optimization by computing tight `bbox_inches` - once (e34e339). -- Widgets now cache frames in the DOM, avoiding flickering in some - browsers and make use of jinja2 template inheritance. (fc7dd2b) -- Calling a HoloViews object without arguments now clears any - associated custom styles. (9e8c343) +- Allowed display of data structures which do not match the + recommended nesting hierarchy (67b28f3, fbd89c3). +- Dimensions now sanitized for `.select`, `.sample` and `.reduce` + calls (6685633, 00b5a66). +- Added `holoviews.ipython.display` function to render (and display) + any HoloViews object, useful for IPython interact widgets (0fa49cd). +- Table column widths now adapt to cell contents (be90a54). +- Defaulting to Matplotlib ticking behavior (62e1e58). +- Allowed specifying fixed figure sizes to Matplotlib via `fig_inches` + tuples using (width, None) and (None, height) formats (632facd). +- Constructors of `Chart`, `Path` and `Histogram` classes now support + additional data formats (2297375). +- `ScrubberWidget` now supports all figure formats (c317db4). +- Allowed customizing legend positions on `Bars` Elements (5a12882). +- Support for multiple colorbars on one axis (aac7b92). +- `.reindex` on `NdElement` types now support converting between key + and value dimensions allowing more powerful conversions. (03ac3ce) +- Improved support for casting between `Element` types (cdaab4e, + b2ad91b, ce7fe2d, 865b4d5). +- The `%%opts` cell magic may now be used multiple times in the same + cell (2a77fd0) +- Matplotlib rcParams can now be set correctly per figure (751210f). +- Improved `OptionTree` repr which now works with eval (2f824c1). +- Refactor of rendering system and IPython extension to allow easy + swapping of plotting backend (\#141) +- Large plotting optimization by computing tight `bbox_inches` + once (e34e339). +- Widgets now cache frames in the DOM, avoiding flickering in some + browsers and make use of jinja2 template inheritance. (fc7dd2b) +- Calling a HoloViews object without arguments now clears any + associated custom styles. (9e8c343) API Changes -- Renamed key\_dimensions and value\_dimensions to kdims and vdims - respectively, while providing backward compatibility for passing and - accessing the long names (8feb7d2). -- Combined x/y/zticker plot options into x/y/zticks parameters which - now accept an explicit number of ticks, an explicit list of tick - positions (and labels), and a Matplotlib tick locator. -- Changed backend options in %output magic, `nbagg` and `d3` are now - modes of the Matplotlib backend and can be selected with - `backend='matplotlib:nbagg'` and - `backend='matplotlib:mpld3'` respectively. The 'd3' and 'nbagg' - options remain supported but will be deprecated in future. -- Customizations should no longer be applied directly to - `Store.options`; the `Store.options(backend='matplotlib')` object - should be customized instead. There is no longer a need to call the - deprecated `Store.register_plots` method. - -Version 1.2.0 -============= +- Renamed key_dimensions and value_dimensions to kdims and vdims + respectively, while providing backward compatibility for passing and + accessing the long names (8feb7d2). +- Combined x/y/zticker plot options into x/y/zticks parameters which + now accept an explicit number of ticks, an explicit list of tick + positions (and labels), and a Matplotlib tick locator. +- Changed backend options in %output magic, `nbagg` and `d3` are now + modes of the Matplotlib backend and can be selected with + `backend='matplotlib:nbagg'` and + `backend='matplotlib:mpld3'` respectively. The 'd3' and 'nbagg' + options remain supported but will be deprecated in future. +- Customizations should no longer be applied directly to + `Store.options`; the `Store.options(backend='matplotlib')` object + should be customized instead. There is no longer a need to call the + deprecated `Store.register_plots` method. + +# Version 1.2.0 + **May 27, 2015** Since the last release we closed over 20 issues and have made 334 @@ -3856,104 +3807,105 @@ range of problems. Highlights/Features: -- Added new `ErrorBars` Element (f2b276b) -- Added `Empty` pseudo-Element to define empty placeholders in - Layouts (35bac9f1d) -- Added support for changing font sizes easily (0f54bea) -- Support for holoviews.rc file (79076c8) -- Many major speed optimizations for working with and plotting - HoloViews data structures (fe87b4c, 7578c51, 5876fe6, 8863333) -- Support for `GridSpace` with inner axes (93295c8) -- New `aspect_weight` and `tight` Layout plot options for more - customizability of Layout arrangements (4b1f03d, e6a76b7) -- Added `bgcolor` plot option to easily set axis background - color (92eb95c) -- Improved widget layout (f51af02) -- New `OutputMagic` css option to style html output (9d42dc2) -- Experimental support for PDF output (1e8a59b) -- Added support for 3D interactivity with nbagg (781bc25) -- Added ability to support deprecated plot options in %%opts magic. -- Added `DrawPlot` simplifying the implementation of custom - plots (38e9d44) +- Added new `ErrorBars` Element (f2b276b) +- Added `Empty` pseudo-Element to define empty placeholders in + Layouts (35bac9f1d) +- Added support for changing font sizes easily (0f54bea) +- Support for holoviews.rc file (79076c8) +- Many major speed optimizations for working with and plotting + HoloViews data structures (fe87b4c, 7578c51, 5876fe6, 8863333) +- Support for `GridSpace` with inner axes (93295c8) +- New `aspect_weight` and `tight` Layout plot options for more + customizability of Layout arrangements (4b1f03d, e6a76b7) +- Added `bgcolor` plot option to easily set axis background + color (92eb95c) +- Improved widget layout (f51af02) +- New `OutputMagic` css option to style html output (9d42dc2) +- Experimental support for PDF output (1e8a59b) +- Added support for 3D interactivity with nbagg (781bc25) +- Added ability to support deprecated plot options in %%opts magic. +- Added `DrawPlot` simplifying the implementation of custom + plots (38e9d44) API changes: -- `Path` and `Histogram` support new constructors (7138ef4, 03b5d38) -- New depth argument on the relabel method (f89b89f) -- Interface to Pandas improved (1a7cd3d) -- Removed `xlim`, `ylim` and `zlim` to eliminate redundancy. -- Renaming of various plot and style options including: +- `Path` and `Histogram` support new constructors (7138ef4, 03b5d38) +- New depth argument on the relabel method (f89b89f) +- Interface to Pandas improved (1a7cd3d) +- Removed `xlim`, `ylim` and `zlim` to eliminate redundancy. +- Renaming of various plot and style options including: + + - `figure_*` to `fig_*` + - `vertical_spacing` and `horizontal_spacing` to `vspace` and + `hspace` respectively - - `figure_*` to `fig_*` - - `vertical_spacing` and `horizontal_spacing` to `vspace` and - `hspace` respectively + \* Deprecation of confusing `origin` style option on RasterPlot - \* Deprecation of confusing `origin` style option on RasterPlot -- `Overlay.__getitem__` no longer supports integer indexing (use `get` - method instead) +- `Overlay.__getitem__` no longer supports integer indexing (use `get` + method instead) Important bug fixes: -- Important fixes to inheritance in the options system - (d34a931, 71c1f3a7) -- Fixes to the select method (df839bea5) -- Fixes to normalization system (c3ef40b) -- Fixes to `Raster` and `Image` extents, `__getitem__` and sampling. -- Fixed bug with disappearing adjoined plots (2360972) -- Fixed plot ordering of overlaid elements across a - `HoloMap` (c4f1685) - -Version 1.1.0 -============= +- Important fixes to inheritance in the options system + (d34a931, 71c1f3a7) +- Fixes to the select method (df839bea5) +- Fixes to normalization system (c3ef40b) +- Fixes to `Raster` and `Image` extents, `__getitem__` and sampling. +- Fixed bug with disappearing adjoined plots (2360972) +- Fixed plot ordering of overlaid elements across a + `HoloMap` (c4f1685) + +# Version 1.1.0 + **April 15, 2015** Highlights: -- Support for nbagg as a backend (09eab4f1) -- New .hvz file format for saving HoloViews objects (bfd5f7af) -- New `Polygon` element type (d1ec8ec8) -- Greatly improved Unicode support throughout, including support for - unicode characters in Python 3 attribute names (609a8454) -- Regular SelectionWidget now supports live rendering (eb5bf8b6) -- Supports a list of objects in Layout and Overlay - constructors (5ba1866e) -- Polar projections now supported (3801b76e) +- Support for nbagg as a backend (09eab4f1) +- New .hvz file format for saving HoloViews objects (bfd5f7af) +- New `Polygon` element type (d1ec8ec8) +- Greatly improved Unicode support throughout, including support for + unicode characters in Python 3 attribute names (609a8454) +- Regular SelectionWidget now supports live rendering (eb5bf8b6) +- Supports a list of objects in Layout and Overlay + constructors (5ba1866e) +- Polar projections now supported (3801b76e) API changes (not backward compatible): -- `xlim`, `ylim`, `zlim`, `xlabel`, `ylabel` and `zlabel` have been - deprecated (081d4123) -- Plotting options `show_xaxis` and `show_yaxis` renamed to `xaxis` - and `yaxis`, respectively (13393f2a). -- Deprecated IPySelectionWidget (f59c34c0) +- `xlim`, `ylim`, `zlim`, `xlabel`, `ylabel` and `zlabel` have been + deprecated (081d4123) +- Plotting options `show_xaxis` and `show_yaxis` renamed to `xaxis` + and `yaxis`, respectively (13393f2a). +- Deprecated IPySelectionWidget (f59c34c0) In addition to the above improvements, many miscellaneous bug fixes were made. -Version 1.0.1 -============= +# Version 1.0.1 + **March 26, 2015** Minor release addressing bugs and issues with 1.0.0. Highlights: -- New separate Pandas Tutorial (8455abc3) -- Silenced warnings when loading the IPython extension in IPython - 3 (aaa6861b) -- Added more useful installation options via `setup.py` (72ece4db) -- Improvements and bug-fixes for the `%%opts` magic - tab-completion (e0ad7108) -- `DFrame` now supports standard constructor for pandas - dataframes (983825c5) -- `Tables` are now correctly formatted using the appropriate - `Dimension` formatter (588bc2a3) -- Support for unlimited alphabetical subfigure labelling (e039d00b) -- Miscellaneous bug fixes, including Python 3 - compatibility improvements. - -Version 1.0.0 -============= +- New separate Pandas Tutorial (8455abc3) +- Silenced warnings when loading the IPython extension in IPython + 3 (aaa6861b) +- Added more useful installation options via `setup.py` (72ece4db) +- Improvements and bug-fixes for the `%%opts` magic + tab-completion (e0ad7108) +- `DFrame` now supports standard constructor for pandas + dataframes (983825c5) +- `Tables` are now correctly formatted using the appropriate + `Dimension` formatter (588bc2a3) +- Support for unlimited alphabetical subfigure labelling (e039d00b) +- Miscellaneous bug fixes, including Python 3 + compatibility improvements. + +# Version 1.0.0 + **March 16, 2015** First public release available on GitHub and PyPI. diff --git a/README.md b/README.md index 7aee1728f1..bc5e6237d2 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ **Stop plotting your data - annotate your data and let it visualize itself.** + | | | | --- | --- | | Build Status | [![Build Status](https://github.com/holoviz/holoviews/workflows/tests/badge.svg?query=branch:main)](https://github.com/holoviz/holoviews/actions/workflows/test.yaml?query=branch%3Amain) | @@ -14,9 +15,7 @@ itself.** | Binder | [![Binder](https://img.shields.io/badge/Launch%20JupyterLab-v1.15.4-579ACA.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFkAAABZCAMAAABi1XidAAAB8lBMVEX///9XmsrmZYH1olJXmsr1olJXmsrmZYH1olJXmsr1olJXmsrmZYH1olL1olJXmsr1olJXmsrmZYH1olL1olJXmsrmZYH1olJXmsr1olL1olJXmsrmZYH1olL1olJXmsrmZYH1olL1olL0nFf1olJXmsrmZYH1olJXmsq8dZb1olJXmsrmZYH1olJXmspXmspXmsr1olL1olJXmsrmZYH1olJXmsr1olL1olJXmsrmZYH1olL1olLeaIVXmsrmZYH1olL1olL1olJXmsrmZYH1olLna31Xmsr1olJXmsr1olJXmsrmZYH1olLqoVr1olJXmsr1olJXmsrmZYH1olL1olKkfaPobXvviGabgadXmsqThKuofKHmZ4Dobnr1olJXmsr1olJXmspXmsr1olJXmsrfZ4TuhWn1olL1olJXmsqBi7X1olJXmspZmslbmMhbmsdemsVfl8ZgmsNim8Jpk8F0m7R4m7F5nLB6jbh7jbiDirOEibOGnKaMhq+PnaCVg6qWg6qegKaff6WhnpKofKGtnomxeZy3noG6dZi+n3vCcpPDcpPGn3bLb4/Mb47UbIrVa4rYoGjdaIbeaIXhoWHmZYHobXvpcHjqdHXreHLroVrsfG/uhGnuh2bwj2Hxk17yl1vzmljzm1j0nlX1olL3AJXWAAAAbXRSTlMAEBAQHx8gICAuLjAwMDw9PUBAQEpQUFBXV1hgYGBkcHBwcXl8gICAgoiIkJCQlJicnJ2goKCmqK+wsLC4usDAwMjP0NDQ1NbW3Nzg4ODi5+3v8PDw8/T09PX29vb39/f5+fr7+/z8/Pz9/v7+zczCxgAABC5JREFUeAHN1ul3k0UUBvCb1CTVpmpaitAGSLSpSuKCLWpbTKNJFGlcSMAFF63iUmRccNG6gLbuxkXU66JAUef/9LSpmXnyLr3T5AO/rzl5zj137p136BISy44fKJXuGN/d19PUfYeO67Znqtf2KH33Id1psXoFdW30sPZ1sMvs2D060AHqws4FHeJojLZqnw53cmfvg+XR8mC0OEjuxrXEkX5ydeVJLVIlV0e10PXk5k7dYeHu7Cj1j+49uKg7uLU61tGLw1lq27ugQYlclHC4bgv7VQ+TAyj5Zc/UjsPvs1sd5cWryWObtvWT2EPa4rtnWW3JkpjggEpbOsPr7F7EyNewtpBIslA7p43HCsnwooXTEc3UmPmCNn5lrqTJxy6nRmcavGZVt/3Da2pD5NHvsOHJCrdc1G2r3DITpU7yic7w/7Rxnjc0kt5GC4djiv2Sz3Fb2iEZg41/ddsFDoyuYrIkmFehz0HR2thPgQqMyQYb2OtB0WxsZ3BeG3+wpRb1vzl2UYBog8FfGhttFKjtAclnZYrRo9ryG9uG/FZQU4AEg8ZE9LjGMzTmqKXPLnlWVnIlQQTvxJf8ip7VgjZjyVPrjw1te5otM7RmP7xm+sK2Gv9I8Gi++BRbEkR9EBw8zRUcKxwp73xkaLiqQb+kGduJTNHG72zcW9LoJgqQxpP3/Tj//c3yB0tqzaml05/+orHLksVO+95kX7/7qgJvnjlrfr2Ggsyx0eoy9uPzN5SPd86aXggOsEKW2Prz7du3VID3/tzs/sSRs2w7ovVHKtjrX2pd7ZMlTxAYfBAL9jiDwfLkq55Tm7ifhMlTGPyCAs7RFRhn47JnlcB9RM5T97ASuZXIcVNuUDIndpDbdsfrqsOppeXl5Y+XVKdjFCTh+zGaVuj0d9zy05PPK3QzBamxdwtTCrzyg/2Rvf2EstUjordGwa/kx9mSJLr8mLLtCW8HHGJc2R5hS219IiF6PnTusOqcMl57gm0Z8kanKMAQg0qSyuZfn7zItsbGyO9QlnxY0eCuD1XL2ys/MsrQhltE7Ug0uFOzufJFE2PxBo/YAx8XPPdDwWN0MrDRYIZF0mSMKCNHgaIVFoBbNoLJ7tEQDKxGF0kcLQimojCZopv0OkNOyWCCg9XMVAi7ARJzQdM2QUh0gmBozjc3Skg6dSBRqDGYSUOu66Zg+I2fNZs/M3/f/Grl/XnyF1Gw3VKCez0PN5IUfFLqvgUN4C0qNqYs5YhPL+aVZYDE4IpUk57oSFnJm4FyCqqOE0jhY2SMyLFoo56zyo6becOS5UVDdj7Vih0zp+tcMhwRpBeLyqtIjlJKAIZSbI8SGSF3k0pA3mR5tHuwPFoa7N7reoq2bqCsAk1HqCu5uvI1n6JuRXI+S1Mco54YmYTwcn6Aeic+kssXi8XpXC4V3t7/ADuTNKaQJdScAAAAAElFTkSuQmCC)](https://mybinder.org/v2/gh/holoviz/holoviews/v1.15.4?urlpath=lab/tree/examples) | | Support | [![Discourse](https://img.shields.io/discourse/status?server=https%3A%2F%2Fdiscourse.holoviz.org)](https://discourse.holoviz.org/) | - -HoloViews is an -[open-source](https://github.com/holoviz/holoviews/blob/main/LICENSE.txt) +HoloViews is an [open-source](https://github.com/holoviz/holoviews/blob/main/LICENSE.txt) Python library designed to make data analysis and visualization seamless and simple. With HoloViews, you can usually express what you want to do in very few lines of code, letting you focus on what you are trying to @@ -54,9 +53,7 @@ Check out the [HoloViews web site](http://holoviews.org) for extensive examples - -Installation -============ +# Installation HoloViews works with [Python](https://github.com/holoviz/holoviews/actions/workflows/test.yaml) @@ -82,8 +79,7 @@ You can also clone holoviews directly from GitHub and install it with: cd holoviews pip install -e . -Usage ------ +## Usage Once you've installed HoloViews, you can get a copy of all the examples shown on this website: diff --git a/examples/README.md b/examples/README.md index 3db37a2720..e4d1b36b69 100644 --- a/examples/README.md +++ b/examples/README.md @@ -5,20 +5,20 @@ This directory contains all the notebooks built as part of the ## Directory structure -* ``assets``: Files used by the examples. -* ``gallery``: Examples shown on the [gallery page](http://holoviews.org/gallery/index.html). -* ``getting_started``: Notebooks used in the [getting started](http://holoviews.org/getting_started/index.html) guide. -* `reference`: Notebooks shown in the website [reference gallery](http://holoviews.org/reference/index.html) -* ``topics``: Notebooks shown in the [showcase](http://holoviews.org/reference/showcase/index.html) -* ``user_guide``: Notebooks used in the [user guide](http://holoviews.org/user_guide/index.html). +- `assets`: Files used by the examples. +- `gallery`: Examples shown on the [gallery page](http://holoviews.org/gallery/index.html). +- `getting_started`: Notebooks used in the [getting started](http://holoviews.org/getting_started/index.html) guide. +- `reference`: Notebooks shown in the website [reference gallery](http://holoviews.org/reference/index.html) +- `topics`: Notebooks shown in the [showcase](http://holoviews.org/reference/showcase/index.html) +- `user_guide`: Notebooks used in the [user guide](http://holoviews.org/user_guide/index.html). ## Contributing to examples If you have improvements to suggest regarding the existing set of notebooks, please tell us on [gitter](https://gitter.im/pyviz/pyviz) or submit a pull request. We are happy to consider user submissions for -``/topics`` so if you have an interesting notebook using HoloViews that -isn't too long and about a domain not already in ``/topics``, please +`/topics` so if you have an interesting notebook using HoloViews that +isn't too long and about a domain not already in `/topics`, please consider submitting a PR. Lastly, if you find a particular notebook that does not seem to be diff --git a/examples/gallery/demos/bokeh/nyc_airport_connections.ipynb b/examples/gallery/demos/bokeh/nyc_airport_connections.ipynb index 6c0f5a0462..8b4f4bb3ab 100644 --- a/examples/gallery/demos/bokeh/nyc_airport_connections.ipynb +++ b/examples/gallery/demos/bokeh/nyc_airport_connections.ipynb @@ -52,7 +52,7 @@ "# Lay out graph weighting and weight by the number of connections\n", "np.random.seed(14)\n", "graph = layout_nodes(nyc_graph, layout=nx.layout.fruchterman_reingold_layout, kwargs={'weight': 'connections'})\n", - "labels = hv.Labels(graph.nodes, ['x', 'y'], ['IATA', 'City'])\n" + "labels = hv.Labels(graph.nodes, ['x', 'y'], ['IATA', 'City'])" ] }, { diff --git a/examples/gallery/demos/matplotlib/nyc_airport_connections.ipynb b/examples/gallery/demos/matplotlib/nyc_airport_connections.ipynb index ae34495676..fc3acb1cd2 100644 --- a/examples/gallery/demos/matplotlib/nyc_airport_connections.ipynb +++ b/examples/gallery/demos/matplotlib/nyc_airport_connections.ipynb @@ -52,7 +52,7 @@ "# Lay out graph weighting and weight by the number of connections\n", "np.random.seed(14)\n", "graph = layout_nodes(nyc_graph, layout=nx.layout.fruchterman_reingold_layout, kwargs={'weight': 'connections'})\n", - "labels = hv.Labels(graph.nodes, ['x', 'y'], ['IATA', 'City'])\n" + "labels = hv.Labels(graph.nodes, ['x', 'y'], ['IATA', 'City'])" ] }, { diff --git a/examples/reference/streams/bokeh/Tap.ipynb b/examples/reference/streams/bokeh/Tap.ipynb index 542afe6cd9..31d8e106c3 100644 --- a/examples/reference/streams/bokeh/Tap.ipynb +++ b/examples/reference/streams/bokeh/Tap.ipynb @@ -137,7 +137,7 @@ " fontsize={'xticks': '6pt'}, height=500, logz=True,\n", " tools=['hover'], width=700, xrotation=90,\n", " )\n", - ")\n" + ")" ] }, { From 03eeb82f19fa3a7a66db3e36aed11f55a5297086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Wed, 20 Dec 2023 13:38:40 +0100 Subject: [PATCH 17/66] Only evaluate `rx` if it is an Reactive Expression (#6014) Co-authored-by: Philipp Rudiger --- holoviews/core/spaces.py | 12 ++-- holoviews/tests/core/test_dynamic.py | 19 +++++ holoviews/tests/ui/bokeh/test_callback.py | 88 +++++++++++++++-------- holoviews/tests/ui/bokeh/test_layout.py | 29 -------- 4 files changed, 82 insertions(+), 66 deletions(-) delete mode 100644 holoviews/tests/ui/bokeh/test_layout.py diff --git a/holoviews/core/spaces.py b/holoviews/core/spaces.py index ae99700b82..cd9cac8b39 100644 --- a/holoviews/core/spaces.py +++ b/holoviews/core/spaces.py @@ -1,7 +1,7 @@ import itertools import types from collections import defaultdict -from contextlib import contextmanager, suppress +from contextlib import contextmanager from functools import partial from itertools import groupby from numbers import Number @@ -546,12 +546,10 @@ def __call__(self, *args, **kwargs): # Nothing to do for callbacks that accept no arguments kwarg_hash = kwargs.pop('_memoization_hash_', ()) (self.args, self.kwargs) = (args, kwargs) - if hasattr(self.callable, 'rx'): - with suppress(TypeError): - # If param.bind is used and not all arguments are set - # it will raise TypeError - return self.callable.rx.value - if not args and not kwargs and not any(kwarg_hash): return self.callable() + if util.param_version >= util.Version('2.0.0') and isinstance(self.callable, param.rx): + return self.callable.rx.value + elif not args and not kwargs and not any(kwarg_hash): + return self.callable() inputs = [i for i in self.inputs if isinstance(i, DynamicMap)] streams = [] for stream in [s for i in inputs for s in get_nested_streams(i)]: diff --git a/holoviews/tests/core/test_dynamic.py b/holoviews/tests/core/test_dynamic.py index 0dd9dd7373..65646f6802 100644 --- a/holoviews/tests/core/test_dynamic.py +++ b/holoviews/tests/core/test_dynamic.py @@ -16,6 +16,7 @@ from holoviews.streams import ( Buffer, LinkedStream, + Params, PointerX, PointerXY, PointerY, @@ -846,6 +847,24 @@ def history_callback(x): self.assertEqual(dmap[()], Curve([1, 1, 1, 2, 2, 2])) +class DynamicMapRX(ComparisonTestCase): + + def test_dynamic_rx(self): + freq = param.rx(1) + rx_curve = param.rx(sine_array)(0, freq).rx.pipe(Curve) + dmap = DynamicMap(rx_curve) + assert len(dmap.streams) == 1 + pstream = dmap.streams[0] + assert isinstance(pstream, Params) + assert len(pstream.parameters) == 2 + fn_param, freq_param = pstream.parameters + assert getattr(fn_param.owner, fn_param.name) == sine_array + assert getattr(freq_param.owner, freq_param.name) == 1 + self.assertEqual(dmap[()], Curve(sine_array(0, 1))) + freq.rx.value = 2 + self.assertEqual(dmap[()], Curve(sine_array(0, 2))) + + class StreamSubscribersAddandClear(ComparisonTestCase): def setUp(self): diff --git a/holoviews/tests/ui/bokeh/test_callback.py b/holoviews/tests/ui/bokeh/test_callback.py index d29c2ebb55..936a7859ed 100644 --- a/holoviews/tests/ui/bokeh/test_callback.py +++ b/holoviews/tests/ui/bokeh/test_callback.py @@ -10,28 +10,26 @@ pytestmark = pytest.mark.ui -from panel.io.server import serve +import panel as pn from panel.pane.holoviews import HoloViews -from panel.tests.util import wait_until +from panel.tests.util import serve_and_wait, wait_until -from holoviews import Curve, Scatter -from holoviews.plotting.bokeh import BokehRenderer +import holoviews as hv +from holoviews import Curve, DynamicMap, Scatter from holoviews.streams import BoundsXY, Lasso, RangeXY +@pytest.mark.usefixtures("bokeh_backend") def test_box_select(page, port): hv_scatter = Scatter([1, 2, 3]).opts( - backend='bokeh', tools=['box_select'], active_tools=['box_select'] + tools=['box_select'], active_tools=['box_select'] ) bounds = BoundsXY(source=hv_scatter) - pn_scatter = HoloViews(hv_scatter, renderer=BokehRenderer) - - serve(pn_scatter, port=port, threaded=True, show=False) - - time.sleep(0.5) + pn_scatter = HoloViews(hv_scatter) + serve_and_wait(pn_scatter, port=port) page.goto(f"http://localhost:{port}") hv_plot = page.locator('.bk-events') @@ -50,20 +48,17 @@ def test_box_select(page, port): wait_until(lambda: bounds.bounds == expected_bounds, page) - +@pytest.mark.usefixtures("bokeh_backend") def test_lasso_select(page, port): hv_scatter = Scatter([1, 2, 3]).opts( - backend='bokeh', tools=['lasso_select'], active_tools=['lasso_select'] + tools=['lasso_select'], active_tools=['lasso_select'] ) lasso = Lasso(source=hv_scatter) - pn_scatter = HoloViews(hv_scatter, renderer=BokehRenderer) - - serve(pn_scatter, port=port, threaded=True, show=False) - - time.sleep(0.5) + pn_scatter = HoloViews(hv_scatter) + serve_and_wait(pn_scatter, port=port) page.goto(f"http://localhost:{port}") hv_plot = page.locator('.bk-events') @@ -96,18 +91,15 @@ def test_lasso_select(page, port): ]) np.testing.assert_almost_equal(lasso.geometry, expected_array) - +@pytest.mark.usefixtures("bokeh_backend") def test_rangexy(page, port): - hv_scatter = Scatter([1, 2, 3]).opts(backend='bokeh', active_tools=['box_zoom']) + hv_scatter = Scatter([1, 2, 3]).opts(active_tools=['box_zoom']) rangexy = RangeXY(source=hv_scatter) - pn_scatter = HoloViews(hv_scatter, renderer=BokehRenderer) - - serve(pn_scatter, port=port, threaded=True, show=False) - - time.sleep(0.5) + pn_scatter = HoloViews(hv_scatter) + serve_and_wait(pn_scatter, port=port) page.goto(f"http://localhost:{port}") hv_plot = page.locator('.bk-events') @@ -126,20 +118,18 @@ def test_rangexy(page, port): expected_yrange = (1.8285714285714285, 2.3183673469387758) wait_until(lambda: rangexy.x_range == expected_xrange and rangexy.y_range == expected_yrange, page) +@pytest.mark.usefixtures("bokeh_backend") def test_multi_axis_rangexy(page, port): c1 = Curve(np.arange(100).cumsum(), vdims='y') c2 = Curve(-np.arange(100).cumsum(), vdims='y2') s1 = RangeXY(source=c1) s2 = RangeXY(source=c2) - overlay = (c1 * c2).opts(backend='bokeh', multi_y=True) + overlay = (c1 * c2).opts(multi_y=True) - pn_scatter = HoloViews(overlay, renderer=BokehRenderer) - - serve(pn_scatter, port=port, threaded=True, show=False) - - time.sleep(0.5) + pn_scatter = HoloViews(overlay) + serve_and_wait(pn_scatter, port=port) page.goto(f"http://localhost:{port}") hv_plot = page.locator('.bk-events') @@ -162,3 +152,41 @@ def test_multi_axis_rangexy(page, port): s1.y_range == expected_yrange1 and s2.y_range == expected_yrange2 ), page) + + +@pytest.mark.usefixtures("bokeh_backend") +def test_bind_trigger(page, port): + # Regression test for https://github.com/holoviz/holoviews/issues/6013 + + BOUND_COUNT, RANGE_COUNT = [0], [0] + + def bound_function(): + BOUND_COUNT[0] += 1 + return Curve([]) + + + def range_function(x_range, y_range): + RANGE_COUNT[0] += 1 + return Curve([]) + + range_dmap = DynamicMap(range_function, streams=[hv.streams.RangeXY()]) + bind_dmap = DynamicMap(pn.bind(bound_function)) + widget = pn.pane.HoloViews(bind_dmap * range_dmap) + + serve_and_wait(widget, port=port) + page.goto(f"http://localhost:{port}") + + hv_plot = page.locator('.bk-events') + expect(hv_plot).to_have_count(1) + + bbox = hv_plot.bounding_box() + hv_plot.click() + + page.mouse.move(bbox['x']+100, bbox['y']+100) + page.mouse.down() + page.mouse.move(bbox['x']+150, bbox['y']+150, steps=5) + page.mouse.up() + + wait_until(lambda: RANGE_COUNT[0] > 2, page) + + assert BOUND_COUNT[0] == 1 diff --git a/holoviews/tests/ui/bokeh/test_layout.py b/holoviews/tests/ui/bokeh/test_layout.py deleted file mode 100644 index d7d08e11dd..0000000000 --- a/holoviews/tests/ui/bokeh/test_layout.py +++ /dev/null @@ -1,29 +0,0 @@ -import time - -import pytest - -pytestmark = pytest.mark.ui - -from panel.io.server import serve -from panel.widgets import Button - - -def test_button_click(page, port): - button = Button(name='Click') - - events = [] - def cb(event): - events.append(event) - button.on_click(cb) - - serve(button, port=port, threaded=True, show=False) - - time.sleep(0.2) - - page.goto(f"http://localhost:{port}") - - page.click('.bk-btn') - - time.sleep(0.1) - - assert len(events) == 1 From aed62039f535efd202eef7bf82fb0be7b966965e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Thu, 21 Dec 2023 08:51:36 +0100 Subject: [PATCH 18/66] Dynamic generate unit test matrix (#6042) --- .github/workflows/test.yaml | 90 +++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 29 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 9d5de5265c..c0e81fa548 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -7,6 +7,14 @@ on: branches: - "*" workflow_dispatch: + target: + description: "How much of the test suite to run" + type: choice + options: + - default + - full + - downstream + schedule: - cron: "0 14 * * SUN" @@ -38,17 +46,19 @@ jobs: steps: - uses: holoviz-dev/holoviz_tasks/pre-commit@v0.1a19 - changes: - name: Check for code changes + setup: + name: Setup workflow runs-on: ubuntu-latest permissions: pull-requests: read outputs: - code: ${{ steps.filter.outputs.code }} + code_change: ${{ steps.filter.outputs.code }} + matrix: ${{ env.MATRIX }} steps: - uses: actions/checkout@v3 if: github.event_name != 'pull_request' - - uses: dorny/paths-filter@v2.11.1 + - name: Check for code changes + uses: dorny/paths-filter@v2.11.1 id: filter with: filters: | @@ -58,26 +68,48 @@ jobs: - 'setup.py' - 'pyproject.toml' - '.github/workflows/test.yaml' + - name: Set test matrix with 'default' option + if: github.event_name != 'workflow_dispatch' || (github.event_name == 'workflow_dispatch' && github.event.inputs.target == 'default') + run: | + MATRIX=$(jq -nsc '{ + "os": ["ubuntu-latest", "macos-latest", "windows-latest"], + "python-version": ["3.9", "3.11"], + "include": [ + {"os": "ubuntu-latest", "python-version": "3.10"} + ] + }') + echo "MATRIX=$MATRIX" >> $GITHUB_ENV + - name: Set test matrix with 'full' option + if: github.event_name == 'workflow_dispatch' && github.event.inputs.target == 'full' + run: | + MATRIX=$(jq -nsc '{ + "os": ["ubuntu-latest", "macos-latest", "windows-latest"], + "python-version": ["3.9", "3.10", "3.11"] + }') + echo "MATRIX=$MATRIX" >> $GITHUB_ENV + - name: Set test matrix with 'downstream' option + if: github.event_name == 'workflow_dispatch' && github.event.inputs.target == 'downstream' + run: | + MATRIX=$(jq -nsc '{ + "os": ["ubuntu-latest"], + "python-version": ["3.10"] + }') + echo "MATRIX=$MATRIX" >> $GITHUB_ENV unit_test_suite: name: Unit tests on Python ${{ matrix.python-version }}, ${{ matrix.os }} - needs: [pre_commit, changes] + needs: [pre_commit, setup] runs-on: ${{ matrix.os }} strategy: fail-fast: false - matrix: - os: ["ubuntu-latest", "macos-latest", "windows-latest"] - python-version: ["3.9", "3.11"] - include: - - os: "ubuntu-latest" - python-version: "3.10" + matrix: ${{ fromJson(needs.setup.outputs.matrix) }} timeout-minutes: 120 env: DESC: "Python ${{ matrix.python-version }}, ${{ matrix.os }} unit tests" PYTHON_VERSION: ${{ matrix.python-version }} steps: - uses: holoviz-dev/holoviz_tasks/install@v0.1a19 - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' with: name: unit_test_suite python-version: ${{ matrix.python-version }} @@ -88,29 +120,29 @@ jobs: conda-update: true id: install - name: bokeh sampledata - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: | conda activate test-environment bokeh sampledata - name: doit test_unit - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: | conda activate test-environment doit test_unit - name: test examples - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: | conda activate test-environment doit test_examples - name: codecov - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: | conda activate test-environment codecov ui_test_suite: name: UI tests on Python ${{ matrix.python-version }}, ${{ matrix.os }} - needs: [pre_commit, changes] + needs: [pre_commit, setup] runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -127,7 +159,7 @@ jobs: PYCTDEV_SELF_CHANNEL: "pyviz/label/dev" steps: - uses: holoviz-dev/holoviz_tasks/install@v0.1a19 - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' with: name: ui_test_suite python-version: ${{ matrix.python-version }} @@ -137,12 +169,12 @@ jobs: playwright: true id: install - name: doit test_ui - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: | conda activate test-environment doit test_ui - name: Upload coverage to Codecov - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' uses: codecov/codecov-action@v3 with: files: ./coverage.xml @@ -151,7 +183,7 @@ jobs: core_test_suite: name: Core tests on Python ${{ matrix.python-version }}, ${{ matrix.os }} - needs: [pre_commit, changes] + needs: [pre_commit, setup] runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -165,7 +197,7 @@ jobs: steps: # Add back when this works on Python 3.12 # - uses: holoviz-dev/holoviz_tasks/install@v0.1a19 - # if: needs.changes.outputs.code == 'true' + # if: needs.setup.outputs.code_change == 'true' # with: # name: core_test_suite # python-version: ${{ matrix.python-version }} @@ -176,32 +208,32 @@ jobs: # conda-update: true # id: install - uses: actions/checkout@v3 - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' with: fetch-depth: "100" - name: Fetch unshallow - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: git fetch --prune --tags --unshallow -f - uses: actions/setup-python@v4 - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' with: python-version: 3.12 - name: install - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: | python -m pip install -ve '.[tests_core, tests_ci]' - name: bokeh sampledata - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: | # conda activate test-environment bokeh sampledata - name: Check packages latest version - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: | # conda activate test-environment python scripts/check_latest_packages.py - name: doit test_unit - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: | # conda activate test-environment pytest holoviews From 0cca7847a5cd3769c1fb2e3cde1e094f760c9dac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Thu, 21 Dec 2023 16:03:54 +0100 Subject: [PATCH 19/66] Revert "Dynamic generate unit test matrix" (#6045) --- .github/workflows/test.yaml | 90 ++++++++++++------------------------- 1 file changed, 29 insertions(+), 61 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index c0e81fa548..9d5de5265c 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -7,14 +7,6 @@ on: branches: - "*" workflow_dispatch: - target: - description: "How much of the test suite to run" - type: choice - options: - - default - - full - - downstream - schedule: - cron: "0 14 * * SUN" @@ -46,19 +38,17 @@ jobs: steps: - uses: holoviz-dev/holoviz_tasks/pre-commit@v0.1a19 - setup: - name: Setup workflow + changes: + name: Check for code changes runs-on: ubuntu-latest permissions: pull-requests: read outputs: - code_change: ${{ steps.filter.outputs.code }} - matrix: ${{ env.MATRIX }} + code: ${{ steps.filter.outputs.code }} steps: - uses: actions/checkout@v3 if: github.event_name != 'pull_request' - - name: Check for code changes - uses: dorny/paths-filter@v2.11.1 + - uses: dorny/paths-filter@v2.11.1 id: filter with: filters: | @@ -68,48 +58,26 @@ jobs: - 'setup.py' - 'pyproject.toml' - '.github/workflows/test.yaml' - - name: Set test matrix with 'default' option - if: github.event_name != 'workflow_dispatch' || (github.event_name == 'workflow_dispatch' && github.event.inputs.target == 'default') - run: | - MATRIX=$(jq -nsc '{ - "os": ["ubuntu-latest", "macos-latest", "windows-latest"], - "python-version": ["3.9", "3.11"], - "include": [ - {"os": "ubuntu-latest", "python-version": "3.10"} - ] - }') - echo "MATRIX=$MATRIX" >> $GITHUB_ENV - - name: Set test matrix with 'full' option - if: github.event_name == 'workflow_dispatch' && github.event.inputs.target == 'full' - run: | - MATRIX=$(jq -nsc '{ - "os": ["ubuntu-latest", "macos-latest", "windows-latest"], - "python-version": ["3.9", "3.10", "3.11"] - }') - echo "MATRIX=$MATRIX" >> $GITHUB_ENV - - name: Set test matrix with 'downstream' option - if: github.event_name == 'workflow_dispatch' && github.event.inputs.target == 'downstream' - run: | - MATRIX=$(jq -nsc '{ - "os": ["ubuntu-latest"], - "python-version": ["3.10"] - }') - echo "MATRIX=$MATRIX" >> $GITHUB_ENV unit_test_suite: name: Unit tests on Python ${{ matrix.python-version }}, ${{ matrix.os }} - needs: [pre_commit, setup] + needs: [pre_commit, changes] runs-on: ${{ matrix.os }} strategy: fail-fast: false - matrix: ${{ fromJson(needs.setup.outputs.matrix) }} + matrix: + os: ["ubuntu-latest", "macos-latest", "windows-latest"] + python-version: ["3.9", "3.11"] + include: + - os: "ubuntu-latest" + python-version: "3.10" timeout-minutes: 120 env: DESC: "Python ${{ matrix.python-version }}, ${{ matrix.os }} unit tests" PYTHON_VERSION: ${{ matrix.python-version }} steps: - uses: holoviz-dev/holoviz_tasks/install@v0.1a19 - if: needs.setup.outputs.code_change == 'true' + if: needs.changes.outputs.code == 'true' with: name: unit_test_suite python-version: ${{ matrix.python-version }} @@ -120,29 +88,29 @@ jobs: conda-update: true id: install - name: bokeh sampledata - if: needs.setup.outputs.code_change == 'true' + if: needs.changes.outputs.code == 'true' run: | conda activate test-environment bokeh sampledata - name: doit test_unit - if: needs.setup.outputs.code_change == 'true' + if: needs.changes.outputs.code == 'true' run: | conda activate test-environment doit test_unit - name: test examples - if: needs.setup.outputs.code_change == 'true' + if: needs.changes.outputs.code == 'true' run: | conda activate test-environment doit test_examples - name: codecov - if: needs.setup.outputs.code_change == 'true' + if: needs.changes.outputs.code == 'true' run: | conda activate test-environment codecov ui_test_suite: name: UI tests on Python ${{ matrix.python-version }}, ${{ matrix.os }} - needs: [pre_commit, setup] + needs: [pre_commit, changes] runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -159,7 +127,7 @@ jobs: PYCTDEV_SELF_CHANNEL: "pyviz/label/dev" steps: - uses: holoviz-dev/holoviz_tasks/install@v0.1a19 - if: needs.setup.outputs.code_change == 'true' + if: needs.changes.outputs.code == 'true' with: name: ui_test_suite python-version: ${{ matrix.python-version }} @@ -169,12 +137,12 @@ jobs: playwright: true id: install - name: doit test_ui - if: needs.setup.outputs.code_change == 'true' + if: needs.changes.outputs.code == 'true' run: | conda activate test-environment doit test_ui - name: Upload coverage to Codecov - if: needs.setup.outputs.code_change == 'true' + if: needs.changes.outputs.code == 'true' uses: codecov/codecov-action@v3 with: files: ./coverage.xml @@ -183,7 +151,7 @@ jobs: core_test_suite: name: Core tests on Python ${{ matrix.python-version }}, ${{ matrix.os }} - needs: [pre_commit, setup] + needs: [pre_commit, changes] runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -197,7 +165,7 @@ jobs: steps: # Add back when this works on Python 3.12 # - uses: holoviz-dev/holoviz_tasks/install@v0.1a19 - # if: needs.setup.outputs.code_change == 'true' + # if: needs.changes.outputs.code == 'true' # with: # name: core_test_suite # python-version: ${{ matrix.python-version }} @@ -208,32 +176,32 @@ jobs: # conda-update: true # id: install - uses: actions/checkout@v3 - if: needs.setup.outputs.code_change == 'true' + if: needs.changes.outputs.code == 'true' with: fetch-depth: "100" - name: Fetch unshallow - if: needs.setup.outputs.code_change == 'true' + if: needs.changes.outputs.code == 'true' run: git fetch --prune --tags --unshallow -f - uses: actions/setup-python@v4 - if: needs.setup.outputs.code_change == 'true' + if: needs.changes.outputs.code == 'true' with: python-version: 3.12 - name: install - if: needs.setup.outputs.code_change == 'true' + if: needs.changes.outputs.code == 'true' run: | python -m pip install -ve '.[tests_core, tests_ci]' - name: bokeh sampledata - if: needs.setup.outputs.code_change == 'true' + if: needs.changes.outputs.code == 'true' run: | # conda activate test-environment bokeh sampledata - name: Check packages latest version - if: needs.setup.outputs.code_change == 'true' + if: needs.changes.outputs.code == 'true' run: | # conda activate test-environment python scripts/check_latest_packages.py - name: doit test_unit - if: needs.setup.outputs.code_change == 'true' + if: needs.changes.outputs.code == 'true' run: | # conda activate test-environment pytest holoviews From 647b2ca5cd1d4b8bd2c8372f3d5450114f489db7 Mon Sep 17 00:00:00 2001 From: Maxime Liquet <35924738+maximlt@users.noreply.github.com> Date: Fri, 22 Dec 2023 14:38:52 +0100 Subject: [PATCH 20/66] Replace Google Analytics with GoatCounter (#6048) --- doc/conf.py | 6 +++++- setup.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 11ae7bf5b2..63fe74c028 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -51,7 +51,6 @@ "copyright", "last-updated", ], - "analytics": {"google_analytics_id": 'G-91EZMMHSF7'} } nbbuild_cell_timeout = 360 @@ -59,8 +58,13 @@ extensions += [ 'nbsite.gallery', 'sphinx_copybutton', + 'nbsite.analytics', ] +nbsite_analytics = { + 'goatcounter_holoviz': True, +} + nbsite_gallery_conf = { 'backends': ['bokeh', 'matplotlib', 'plotly'], 'galleries': {}, diff --git a/setup.py b/setup.py index 9d11ef4b6b..b824702a31 100644 --- a/setup.py +++ b/setup.py @@ -107,7 +107,7 @@ extras_require["unit_tests"] = extras_require["examples"] + extras_require["tests"] + extras_require['lint'] extras_require['doc'] = extras_require['examples'] + [ - 'nbsite >=0.8.2,<0.9.0', + 'nbsite >=0.8.4,<0.9.0', 'myst-nb <1', 'graphviz', 'bokeh >=3.1', From f46e512fbbf08640d736f2b2cd2b8d9277a75f29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Fri, 22 Dec 2023 16:18:47 +0100 Subject: [PATCH 21/66] Dynamic generate unit test matrix and add cache option (#6043) --- .github/workflows/test.yaml | 114 ++++++++++++++++++++++++++---------- 1 file changed, 82 insertions(+), 32 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 9d5de5265c..9b9f82f19f 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -7,6 +7,20 @@ on: branches: - "*" workflow_dispatch: + inputs: + target: + description: "How much of the test suite to run" + type: choice + default: default + options: + - default + - full + - downstream + cache: + description: "Use cache" + type: boolean + default: true + schedule: - cron: "0 14 * * SUN" @@ -38,17 +52,19 @@ jobs: steps: - uses: holoviz-dev/holoviz_tasks/pre-commit@v0.1a19 - changes: - name: Check for code changes + setup: + name: Setup workflow runs-on: ubuntu-latest permissions: pull-requests: read outputs: - code: ${{ steps.filter.outputs.code }} + code_change: ${{ steps.filter.outputs.code }} + matrix: ${{ env.MATRIX }} steps: - uses: actions/checkout@v3 if: github.event_name != 'pull_request' - - uses: dorny/paths-filter@v2.11.1 + - name: Check for code changes + uses: dorny/paths-filter@v2.11.1 id: filter with: filters: | @@ -58,59 +74,93 @@ jobs: - 'setup.py' - 'pyproject.toml' - '.github/workflows/test.yaml' + - name: Set matrix option + run: | + if [[ '${{ github.event_name }}' == 'workflow_dispatch' ]]; then + OPTION=${{ github.event.inputs.target }} + elif [[ '${{ github.event_name }}' == 'schedule' ]]; then + OPTION="full" + elif [[ '${{ github.event_name }}' == 'push' && '${{ github.ref_type }}' == 'tag' ]]; then + OPTION="full" + else + OPTION="default" + fi + echo "MATRIX_OPTION=$OPTION" >> $GITHUB_ENV + - name: Set test matrix with 'default' option + if: env.MATRIX_OPTION == 'default' + run: | + MATRIX=$(jq -nsc '{ + "os": ["ubuntu-latest", "macos-latest", "windows-latest"], + "python-version": ["3.9", "3.11"], + "include": [ + {"os": "ubuntu-latest", "python-version": "3.10"} + ] + }') + echo "MATRIX=$MATRIX" >> $GITHUB_ENV + - name: Set test matrix with 'full' option + if: env.MATRIX_OPTION == 'full' + run: | + MATRIX=$(jq -nsc '{ + "os": ["ubuntu-latest", "macos-latest", "windows-latest"], + "python-version": ["3.9", "3.10", "3.11"] + }') + echo "MATRIX=$MATRIX" >> $GITHUB_ENV + - name: Set test matrix with 'downstream' option + if: env.MATRIX_OPTION == 'downstream' + run: | + MATRIX=$(jq -nsc '{ + "os": ["ubuntu-latest"], + "python-version": ["3.11"] + }') + echo "MATRIX=$MATRIX" >> $GITHUB_ENV unit_test_suite: name: Unit tests on Python ${{ matrix.python-version }}, ${{ matrix.os }} - needs: [pre_commit, changes] + needs: [pre_commit, setup] runs-on: ${{ matrix.os }} strategy: fail-fast: false - matrix: - os: ["ubuntu-latest", "macos-latest", "windows-latest"] - python-version: ["3.9", "3.11"] - include: - - os: "ubuntu-latest" - python-version: "3.10" + matrix: ${{ fromJson(needs.setup.outputs.matrix) }} timeout-minutes: 120 env: DESC: "Python ${{ matrix.python-version }}, ${{ matrix.os }} unit tests" PYTHON_VERSION: ${{ matrix.python-version }} steps: - uses: holoviz-dev/holoviz_tasks/install@v0.1a19 - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' with: name: unit_test_suite python-version: ${{ matrix.python-version }} channel-priority: strict channels: pyviz/label/dev,conda-forge,nodefaults envs: "-o flakes -o tests -o examples_tests -o tests_ci" - cache: true + cache: ${{ github.event.inputs.cache }} conda-update: true id: install - name: bokeh sampledata - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: | conda activate test-environment bokeh sampledata - name: doit test_unit - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: | conda activate test-environment doit test_unit - name: test examples - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: | conda activate test-environment doit test_examples - name: codecov - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: | conda activate test-environment codecov ui_test_suite: name: UI tests on Python ${{ matrix.python-version }}, ${{ matrix.os }} - needs: [pre_commit, changes] + needs: [pre_commit, setup] runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -127,22 +177,22 @@ jobs: PYCTDEV_SELF_CHANNEL: "pyviz/label/dev" steps: - uses: holoviz-dev/holoviz_tasks/install@v0.1a19 - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' with: name: ui_test_suite python-version: ${{ matrix.python-version }} channels: pyviz/label/dev,bokeh,conda-forge,nodefaults envs: "-o recommended -o tests -o build -o tests_ci" - cache: true + cache: ${{ github.event.inputs.cache }} playwright: true id: install - name: doit test_ui - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: | conda activate test-environment doit test_ui - name: Upload coverage to Codecov - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' uses: codecov/codecov-action@v3 with: files: ./coverage.xml @@ -151,7 +201,7 @@ jobs: core_test_suite: name: Core tests on Python ${{ matrix.python-version }}, ${{ matrix.os }} - needs: [pre_commit, changes] + needs: [pre_commit, setup] runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -165,43 +215,43 @@ jobs: steps: # Add back when this works on Python 3.12 # - uses: holoviz-dev/holoviz_tasks/install@v0.1a19 - # if: needs.changes.outputs.code == 'true' + # if: needs.setup.outputs.code_change == 'true' # with: # name: core_test_suite # python-version: ${{ matrix.python-version }} # # channel-priority: strict # channels: pyviz/label/dev,conda-forge,nodefaults # envs: "-o tests_core -o tests_ci" - # cache: true + # cache: ${{ github.event.inputs.cache }} # conda-update: true # id: install - uses: actions/checkout@v3 - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' with: fetch-depth: "100" - name: Fetch unshallow - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: git fetch --prune --tags --unshallow -f - uses: actions/setup-python@v4 - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' with: python-version: 3.12 - name: install - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: | python -m pip install -ve '.[tests_core, tests_ci]' - name: bokeh sampledata - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: | # conda activate test-environment bokeh sampledata - name: Check packages latest version - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: | # conda activate test-environment python scripts/check_latest_packages.py - name: doit test_unit - if: needs.changes.outputs.code == 'true' + if: needs.setup.outputs.code_change == 'true' run: | # conda activate test-environment pytest holoviews From 62b7f1ea47461173253a123765a7d555a0c239ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Fri, 22 Dec 2023 18:39:00 +0100 Subject: [PATCH 22/66] Default to true if inputs.cache is not set (#6050) --- .github/workflows/test.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 9b9f82f19f..ad67149396 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -134,7 +134,7 @@ jobs: channel-priority: strict channels: pyviz/label/dev,conda-forge,nodefaults envs: "-o flakes -o tests -o examples_tests -o tests_ci" - cache: ${{ github.event.inputs.cache }} + cache: ${{ github.event.inputs.cache || github.event.inputs.cache == '' }} conda-update: true id: install - name: bokeh sampledata @@ -183,7 +183,7 @@ jobs: python-version: ${{ matrix.python-version }} channels: pyviz/label/dev,bokeh,conda-forge,nodefaults envs: "-o recommended -o tests -o build -o tests_ci" - cache: ${{ github.event.inputs.cache }} + cache: ${{ github.event.inputs.cache || github.event.inputs.cache == '' }} playwright: true id: install - name: doit test_ui @@ -222,7 +222,7 @@ jobs: # # channel-priority: strict # channels: pyviz/label/dev,conda-forge,nodefaults # envs: "-o tests_core -o tests_ci" - # cache: ${{ github.event.inputs.cache }} + # cache: ${{ github.event.inputs.cache || github.event.inputs.cache == '' }} # conda-update: true # id: install - uses: actions/checkout@v3 From 4672b044cee1b60f7e76935a3d01b9f38dfa821f Mon Sep 17 00:00:00 2001 From: Maxime Liquet <35924738+maximlt@users.noreply.github.com> Date: Mon, 15 Jan 2024 13:49:28 +0100 Subject: [PATCH 23/66] Skip Deploying_Bokeh_Apps.ipynb on Windows (#6070) --- examples/conftest.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/conftest.py b/examples/conftest.py index c02fc8d16c..b33cbeff2f 100644 --- a/examples/conftest.py +++ b/examples/conftest.py @@ -40,6 +40,11 @@ "user_guide/16-Streaming_Data.ipynb", ] +# 2024-01-15: See https://github.com/holoviz/holoviews/issues/6069 +if system == "Windows": + collect_ignore_glob += [ + "user_guide/Deploying_Bokeh_Apps.ipynb", + ] # First available in Bokeh 3.2.0 if Version(bokeh.__version__) < Version("3.2.0"): From 307b1fb563fe1100f81ec233fce8030f8a9682b1 Mon Sep 17 00:00:00 2001 From: Maxime Liquet <35924738+maximlt@users.noreply.github.com> Date: Mon, 15 Jan 2024 15:05:02 +0100 Subject: [PATCH 24/66] Zoom tools automatically vertically scaled on subcoordinate_y overlays (#6051) --- holoviews/plotting/bokeh/element.py | 61 +++++++++++++++++-- .../tests/plotting/bokeh/test_subcoordy.py | 48 +++++++++++++++ 2 files changed, 104 insertions(+), 5 deletions(-) diff --git a/holoviews/plotting/bokeh/element.py b/holoviews/plotting/bokeh/element.py index 3d54ac005a..2d49588b7e 100644 --- a/holoviews/plotting/bokeh/element.py +++ b/holoviews/plotting/bokeh/element.py @@ -322,16 +322,32 @@ def _init_tools(self, element, callbacks=None): tool = tools.HoverTool( tooltips=tooltips, tags=['hv_created'], mode=tool, **hover_opts ) - elif bokeh32 and tool in ['wheel_zoom', 'xwheel_zoom', 'ywheel_zoom']: - if tool.startswith('x'): + elif bokeh32 and isinstance(tool, str) and tool.endswith( + ('wheel_zoom', 'zoom_in', 'zoom_out') + ): + zoom_kwargs = {} + tags = ['hv_created'] + if self.subcoordinate_y and not tool.startswith('x'): + zoom_dims = 'height' + zoom_kwargs['level'] = 1 + tags.append(tool) + elif tool.startswith('x'): zoom_dims = 'width' elif tool.startswith('y'): zoom_dims = 'height' else: zoom_dims = 'both' - tool = tools.WheelZoomTool( - zoom_together='none', dimensions=zoom_dims, tags=['hv_created'] - ) + zoom_kwargs['dimensions'] = zoom_dims + zoom_kwargs['tags'] = tags + if tool.endswith('wheel_zoom'): + # Setting `zoom_together` for multi-y axis support. + zoom_kwargs['zoom_together'] = 'none' + zoom_type = tools.WheelZoomTool + elif tool.endswith('zoom_in'): + zoom_type = tools.ZoomInTool + elif tool.endswith('zoom_out'): + zoom_type = tools.ZoomOutTool + tool = zoom_type(**zoom_kwargs) tool_list.append(tool) copied_tools = [] @@ -350,6 +366,15 @@ def _init_tools(self, element, callbacks=None): if hover: self.handles['hover'] = hover + if self.subcoordinate_y: + zoom_tools = {} + _zoom_types = (tools.WheelZoomTool, tools.ZoomInTool, tools.ZoomOutTool) + for t in copied_tools: + if isinstance(t, _zoom_types) and 'hv_created' in t.tags and len(t.tags) == 2: + zoom_tools[t.tags[1]] = t + if zoom_tools: + self.handles['zooms_subcoordy'] = zoom_tools + box_tools = [t for t in copied_tools if isinstance(t, tools.BoxSelectTool)] if box_tools: self.handles['box_select'] = box_tools[0] @@ -1828,6 +1853,14 @@ def _init_glyphs(self, plot, element, ranges, source): self._postprocess_hover(renderer, source) + zooms_subcoordy = self.handles.get('zooms_subcoordy') + if zooms_subcoordy is not None: + for zoom in zooms_subcoordy.values(): + # The default renderer is 'auto', instead we want to + # store the subplot renderer to aggregate them and set + # the final tool with a list of all the renderers. + zoom.renderers = [renderer] + # Update plot, source and glyph with abbreviated_exception(): self._update_glyph(renderer, properties, mapping, glyph, source, source.data) @@ -2777,6 +2810,8 @@ def _init_tools(self, element, callbacks=None): if callbacks is None: callbacks = [] hover_tools = {} + zooms_subcoordy = {} + _zoom_types = (tools.WheelZoomTool, tools.ZoomInTool, tools.ZoomOutTool) init_tools, tool_types = [], [] for key, subplot in self.subplots.items(): el = element.get(key) @@ -2793,6 +2828,15 @@ def _init_tools(self, element, callbacks=None): continue else: hover_tools[tooltips] = tool + elif ( + self.subcoordinate_y and isinstance(tool, _zoom_types) + and 'hv_created' in tool.tags and len(tool.tags) == 2 + ): + if tool.tags[1] in zooms_subcoordy: + continue + else: + zooms_subcoordy[tool.tags[1]] = tool + self.handles['zooms_subcoordy'] = zooms_subcoordy elif tool_type in tool_types: continue else: @@ -2822,6 +2866,13 @@ def _merge_tools(self, subplot): tool.renderers = list(util.unique_iterator(renderers)) if 'hover' not in self.handles: self.handles['hover'] = tool + if 'zooms_subcoordy' in subplot.handles and 'zooms_subcoordy' in self.handles: + for subplot_zoom, overlay_zoom in zip( + subplot.handles['zooms_subcoordy'].values(), + self.handles['zooms_subcoordy'].values(), + ): + renderers = list(util.unique_iterator(subplot_zoom.renderers + overlay_zoom.renderers)) + overlay_zoom.renderers = renderers def _get_dimension_factors(self, overlay, ranges, dimension): factors = [] diff --git a/holoviews/tests/plotting/bokeh/test_subcoordy.py b/holoviews/tests/plotting/bokeh/test_subcoordy.py index a6af6a4664..0009d00950 100644 --- a/holoviews/tests/plotting/bokeh/test_subcoordy.py +++ b/holoviews/tests/plotting/bokeh/test_subcoordy.py @@ -1,5 +1,6 @@ import numpy as np import pytest +from bokeh.models.tools import WheelZoomTool, ZoomInTool, ZoomOutTool from holoviews.core import Overlay from holoviews.element import Curve @@ -202,3 +203,50 @@ def test_same_label_error(self): match='Elements wrapped in a subcoordinate_y overlay must all have a unique label', ): bokeh_renderer.get_plot(overlay) + + def test_tools_default_wheel_zoom_configured(self): + overlay = Overlay([Curve(range(10), label=f'Data {i}').opts(subcoordinate_y=True) for i in range(2)]) + plot = bokeh_renderer.get_plot(overlay) + zoom_subcoordy = plot.handles['zooms_subcoordy']['wheel_zoom'] + assert len(zoom_subcoordy.renderers) == 2 + assert len(set(zoom_subcoordy.renderers)) == 2 + assert zoom_subcoordy.dimensions == 'height' + assert zoom_subcoordy.level == 1 + + def test_tools_string_zoom_in_out_configured(self): + for zoom in ['zoom_in', 'zoom_out', 'yzoom_in', 'yzoom_out', 'ywheel_zoom']: + overlay = Overlay([Curve(range(10), label=f'Data {i}').opts(subcoordinate_y=True, tools=[zoom]) for i in range(2)]) + plot = bokeh_renderer.get_plot(overlay) + zoom_subcoordy = plot.handles['zooms_subcoordy'][zoom] + assert len(zoom_subcoordy.renderers) == 2 + assert len(set(zoom_subcoordy.renderers)) == 2 + assert zoom_subcoordy.dimensions == 'height' + assert zoom_subcoordy.level == 1 + + def test_tools_string_x_zoom_untouched(self): + for zoom, zoom_type in [ + ('xzoom_in', ZoomInTool), + ('xzoom_out', ZoomOutTool), + ('xwheel_zoom', WheelZoomTool), + ]: + overlay = Overlay([Curve(range(10), label=f'Data {i}').opts(subcoordinate_y=True, tools=[zoom]) for i in range(2)]) + plot = bokeh_renderer.get_plot(overlay) + for tool in plot.state.tools: + if isinstance(tool, zoom_type) and tool.tags == ['hv_created']: + assert tool.level == 0 + assert tool.dimensions == 'width' + break + else: + raise AssertionError('Provided zoom not found.') + + def test_tools_instance_zoom_untouched(self): + for zoom in [WheelZoomTool(), ZoomInTool(), ZoomOutTool()]: + overlay = Overlay([Curve(range(10), label=f'Data {i}').opts(subcoordinate_y=True, tools=[zoom]) for i in range(2)]) + plot = bokeh_renderer.get_plot(overlay) + for tool in plot.state.tools: + if isinstance(tool, type(zoom)) and 'hv_created' not in tool.tags: + assert tool.level == 0 + assert tool.dimensions == 'both' + break + else: + raise AssertionError('Provided zoom not found.') From ee80117148b1b5a3bf3550373b8a0c2bf90af1a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Tue, 16 Jan 2024 09:47:44 +0100 Subject: [PATCH 25/66] Use importlib.version to remove import from show_versions (#6072) --- holoviews/util/_versions.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/holoviews/util/_versions.py b/holoviews/util/_versions.py index 3ee6d299e7..1617d2c74f 100644 --- a/holoviews/util/_versions.py +++ b/holoviews/util/_versions.py @@ -1,5 +1,6 @@ import platform import sys +from importlib.metadata import version __all__ = ("show_versions",) @@ -36,6 +37,7 @@ # Misc "panel", "param", + "pyviz_comms", ] @@ -52,8 +54,7 @@ def show_versions(): def _package_version(p): try: - __import__(p) - print(f"{p:20}: {sys.modules[p].__version__}") + print(f"{p:20}: {version(p)}") except ImportError: print(f"{p:20}: -") From 10433e68b55ce9bb57721316c3f036d99950b72e Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Wed, 17 Jan 2024 09:47:00 +0100 Subject: [PATCH 26/66] Use tsdownsample library for downsampling if available (#6059) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Simon Høxbro Hansen --- holoviews/operation/downsample.py | 82 ++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 11 deletions(-) diff --git a/holoviews/operation/downsample.py b/holoviews/operation/downsample.py index f7b2e75c82..f75379e9e2 100644 --- a/holoviews/operation/downsample.py +++ b/holoviews/operation/downsample.py @@ -41,6 +41,7 @@ def _argmax_area(prev_x, prev_y, avg_next_x, avg_next_y, x_bucket, y_bucket): """Vectorized triangular area argmax computation. + Parameters ---------- prev_x : float @@ -99,9 +100,11 @@ def _lttb_inner(x, y, n_out, sampled_x, offset): ) -def _lttb(x, y, n_out): +def _lttb(x, y, n_out, **kwargs): """ - Downsample the data using the LTTB algorithm (python implementation). + Downsample the data using the LTTB algorithm. + + Will use a Python/Numpy implementation if tsdownsample is not available. Args: x (np.ndarray): The x-values of the data. @@ -110,6 +113,14 @@ def _lttb(x, y, n_out): Returns: np.array: The indexes of the selected datapoints. """ + try: + from tsdownsample import LTTBDownsampler + return LTTBDownsampler().downsample(x, y, n_out=n_out, **kwargs) + except ModuleNotFoundError: + pass + except Exception as e: + raise e + # Bucket size. Leave room for start and end data points block_size = (y.shape[0] - 2) / (n_out - 2) # Note this 'astype' cast must take place after array creation (and not with the @@ -132,8 +143,7 @@ def _lttb(x, y, n_out): return sampled_x - -def _nth_point(x, y, n_out): +def _nth_point(x, y, n_out, **kwargs): """ Downsampling by selecting every n-th datapoint @@ -147,24 +157,71 @@ def _nth_point(x, y, n_out): n_samples = len(x) return np.arange(0, n_samples, max(1, math.ceil(n_samples / n_out))) +def _min_max(x, y, n_out, **kwargs): + try: + from tsdownsample import MinMaxDownsampler + except ModuleNotFoundError: + raise NotImplementedError( + 'The min-max downsampling algorithm requires the tsdownsampler ' + 'library to be installed.' + ) from None + return MinMaxDownsampler().downsample(x, y, n_out=n_out, **kwargs) + +def _min_max_lttb(x, y, n_out, **kwargs): + try: + from tsdownsample import MinMaxLTTBDownsampler + except ModuleNotFoundError: + raise NotImplementedError( + 'The minmax-lttb downsampling algorithm requires the tsdownsampler ' + 'library to be installed.' + ) from None + return MinMaxLTTBDownsampler().downsample(x, y, n_out=n_out, **kwargs) + +def _m4(x, y, n_out, **kwargs): + try: + from tsdownsample import M4Downsampler + except ModuleNotFoundError: + raise NotImplementedError( + 'The m4 downsampling algorithm requires the tsdownsampler ' + 'library to be installed.' + ) from None + return M4Downsampler().downsample(x, y, n_out=n_out, **kwargs) + _ALGORITHMS = { 'lttb': _lttb, - 'nth': _nth_point + 'nth': _nth_point, + 'minmax': _min_max, + 'minmax-lttb': _min_max_lttb, + 'm4': _m4, } - class downsample1d(ResampleOperation1D): """ Implements downsampling of a regularly sampled 1D dataset. - Supports multiple algorithms: + If available uses the `tsdownsampler` library to perform massively + accelerated downsampling. + """ + + algorithm = param.Selector(default='lttb', objects=list(_ALGORITHMS), doc=""" + The algorithm to use for downsampling: - `lttb`: Largest Triangle Three Buckets downsample algorithm - `nth`: Selects every n-th point. - """ + - `minmax`: Selects the min and max value in each bin (requires tsdownsampler). + - `m4`: Selects the min, max, first and last value in each bin (requires tsdownsampler). + - `minmax-lttb`: First selects n_out * minmax_ratio min and max values, + then further reduces these to n_out values using the + Largest Triangle Three Buckets algorithm. (requires tsdownsampler)""") + + parallel = param.Boolean(default=False, doc=""" + The number of threads to use (if tsdownsampler is available).""") - algorithm = param.Selector(default='lttb', objects=['lttb', 'nth']) + minmax_ratio = param.Integer(default=4, bounds=(0, None), doc=""" + For the minmax-lttb algorithm determines the ratio of candidate + values to generate with the minmax algorithm before further + downsampling with LTTB.""") def _process(self, element, key=None): if isinstance(element, (Overlay, NdOverlay)): @@ -183,9 +240,12 @@ def _process(self, element, key=None): if ys.dtype == np.bool_: ys = ys.astype(np.int8) downsample = _ALGORITHMS[self.p.algorithm] - if self.p.algorithm == "lttb" and isinstance(element, Area): + kwargs = {} + if "lttb" in self.p.algorithm and isinstance(element, Area): raise NotImplementedError( "LTTB algorithm is not implemented for hv.Area" ) - samples = downsample(xs, ys, self.p.width) + elif self.p.algorithm == "minmax-lttb": + kwargs['minmax_ratio'] = self.p.minmax_ratio + samples = downsample(xs, ys, self.p.width, parallel=self.p.parallel, **kwargs) return element.iloc[samples] From dbab2b763ccd7b7169b2c62e39a075998980d40f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Fri, 19 Jan 2024 12:49:33 +0100 Subject: [PATCH 27/66] Update to work with Pandas 2.2 release candidate (#6074) --- holoviews/core/data/xarray.py | 2 +- holoviews/element/selection.py | 41 ++++++++++++------- .../tests/core/data/test_pandasinterface.py | 2 +- holoviews/tests/core/test_apply.py | 14 ++++--- holoviews/tests/element/test_selection.py | 37 +++++++++++++---- holoviews/tests/operation/test_datashader.py | 6 +-- .../tests/plotting/bokeh/test_callbacks.py | 7 +++- pyproject.toml | 2 + 8 files changed, 76 insertions(+), 35 deletions(-) diff --git a/holoviews/core/data/xarray.py b/holoviews/core/data/xarray.py index 823053e590..c1cad1a16e 100644 --- a/holoviews/core/data/xarray.py +++ b/holoviews/core/data/xarray.py @@ -343,7 +343,7 @@ def groupby(cls, dataset, dimensions, container_type, group_type, **kwargs): group_by = [d.name for d in index_dims] data = [] if len(dimensions) == 1: - for k, v in dataset.data.groupby(index_dims[0].name): + for k, v in dataset.data.groupby(index_dims[0].name, squeeze=False): if drop_dim: v = v.to_dataframe().reset_index() data.append((k, group_type(v, **group_kwargs))) diff --git a/holoviews/element/selection.py b/holoviews/element/selection.py index 21c4311960..25d448e127 100644 --- a/holoviews/element/selection.py +++ b/holoviews/element/selection.py @@ -4,6 +4,7 @@ """ import sys +from importlib.util import find_spec import numpy as np import pandas as pd @@ -79,7 +80,7 @@ def spatial_select_gridded(xvals, yvals, geometry): sel_mask = spatial_select_columnar(xvals.flatten(), yvals.flatten(), geometry) return sel_mask.reshape(xvals.shape) -def spatial_select_columnar(xvals, yvals, geometry): +def spatial_select_columnar(xvals, yvals, geometry, geom_method=None): if 'cudf' in sys.modules: import cudf if isinstance(xvals, cudf.Series): @@ -119,20 +120,16 @@ def spatial_select_columnar(xvals, yvals, geometry): sel_mask = (xvals>=x0) & (xvals<=x1) & (yvals>=y0) & (yvals<=y1) masked_xvals = xvals[sel_mask] masked_yvals = yvals[sel_mask] - try: - from spatialpandas.geometry import PointArray, Polygon - points = PointArray((masked_xvals.astype('float'), masked_yvals.astype('float'))) - poly = Polygon([np.concatenate([geometry, geometry[:1]]).flatten()]) - geom_mask = points.intersects(poly) - except ImportError: - try: - from shapely.geometry import Point, Polygon - points = (Point(x, y) for x, y in zip(masked_xvals, masked_yvals)) - poly = Polygon(geometry) - geom_mask = np.array([poly.contains(p) for p in points]) - except ImportError: - raise ImportError("Lasso selection on tabular data requires " - "either spatialpandas or shapely to be available.") from None + if geom_method is None: + if find_spec("spatialpandas") is not None: + geom_method = "spatialpandas" + elif find_spec("shapely") is not None: + geom_method = "shapely" + else: + msg = "Lasso selection on tabular data requires either spatialpandas or shapely to be available." + raise ImportError(msg) from None + geom_function = {"spatialpandas": _mask_spatialpandas, "shapely": _mask_shapely}[geom_method] + geom_mask = geom_function(masked_xvals, masked_yvals, geometry) if isinstance(xvals, pd.Series): sel_mask[sel_mask.index[np.where(sel_mask)[0]]] = geom_mask else: @@ -140,6 +137,20 @@ def spatial_select_columnar(xvals, yvals, geometry): return sel_mask +def _mask_spatialpandas(masked_xvals, masked_yvals, geometry): + from spatialpandas.geometry import PointArray, Polygon + points = PointArray((masked_xvals.astype('float'), masked_yvals.astype('float'))) + poly = Polygon([np.concatenate([geometry, geometry[:1]]).flatten()]) + return points.intersects(poly) + + +def _mask_shapely(masked_xvals, masked_yvals, geometry): + from shapely.geometry import Point, Polygon + points = (Point(x, y) for x, y in zip(masked_xvals, masked_yvals)) + poly = Polygon(geometry) + return np.array([poly.contains(p) for p in points], dtype=bool) + + def spatial_select(xvals, yvals, geometry): if xvals.ndim > 1: return spatial_select_gridded(xvals, yvals, geometry) diff --git a/holoviews/tests/core/data/test_pandasinterface.py b/holoviews/tests/core/data/test_pandasinterface.py index 37b7c0ae28..415ec6acce 100644 --- a/holoviews/tests/core/data/test_pandasinterface.py +++ b/holoviews/tests/core/data/test_pandasinterface.py @@ -172,7 +172,7 @@ class PandasInterfaceTests(BasePandasInterfaceTests): __test__ = True def test_data_with_tz(self): - dates = pd.date_range("2018-01-01", periods=3, freq="H") + dates = pd.date_range("2018-01-01", periods=3, freq="h") dates_tz = dates.tz_localize("UTC") df = pd.DataFrame({"dates": dates_tz}) data = Dataset(df).dimension_values("dates") diff --git a/holoviews/tests/core/test_apply.py b/holoviews/tests/core/test_apply.py index 974b5a10fa..6f38635187 100644 --- a/holoviews/tests/core/test_apply.py +++ b/holoviews/tests/core/test_apply.py @@ -11,6 +11,10 @@ from holoviews.streams import ParamMethod, Params +def makeDataFrame(): + data = np.random.default_rng(2).standard_normal((30, 4)) + return pd.DataFrame(data, columns=list('ABCD')) + class ParamClass(param.Parameterized): label = param.String(default='Test') @@ -280,7 +284,7 @@ def test_dmap_apply_dynamic_with_param_method(self): def test_nested_widgets(): - df = pd._testing.makeDataFrame() + df = makeDataFrame() column = RadioButtonGroup(value="A", options=list("ABC")) ds = Dataset(df) transform = util.transform.df_dim("*").groupby(["D", column]).mean() @@ -295,7 +299,7 @@ def test_nested_widgets(): def test_slice_iloc(): - df = pd._testing.makeDataFrame() + df = makeDataFrame() column = IntSlider(start=10, end=40) ds = Dataset(df) transform = util.transform.df_dim("*").iloc[:column].mean(axis=0) @@ -310,7 +314,7 @@ def test_slice_iloc(): def test_slice_loc(): - df = pd._testing.makeDataFrame() + df = makeDataFrame() df.index = np.arange(5, len(df) + 5) column = IntSlider(start=10, end=40) ds = Dataset(df) @@ -330,7 +334,7 @@ def test_slice_loc(): def test_int_iloc(): - df = pd._testing.makeDataFrame() + df = makeDataFrame() column = IntSlider(start=10, end=40) ds = Dataset(df) transform = util.transform.df_dim("*").iloc[column] @@ -345,7 +349,7 @@ def test_int_iloc(): def test_int_loc(): - df = pd._testing.makeDataFrame() + df = makeDataFrame() df.index = np.arange(5, len(df) + 5) column = IntSlider(start=10, end=40) ds = Dataset(df) diff --git a/holoviews/tests/element/test_selection.py b/holoviews/tests/element/test_selection.py index 05235b995d..7e92b475b6 100644 --- a/holoviews/tests/element/test_selection.py +++ b/holoviews/tests/element/test_selection.py @@ -616,8 +616,10 @@ def test_poly_geom_selection_inverted(self): self.assertEqual(region, Rectangles([]) * Path([list(geom)+[(0.2, -0.15)]])) -@pytest.mark.skipif(shapely is None and spd is None, reason='Neither shapely nor spatialpandas are available') class TestSpatialSelectColumnar: + __test__ = False + method = None + geometry_encl = np.array([ [-1, 0.5], [ 1, 0.5], @@ -660,25 +662,42 @@ def pandas_df(self): def dask_df(self, pandas_df): return dd.from_pandas(pandas_df, npartitions=2) + @pytest.fixture(scope="function") + def _method(self): + return self.method + @pytest.mark.parametrize("geometry,pt_mask", [(geometry_encl, pt_mask_encl),(geometry_noencl, pt_mask_noencl)]) class TestSpatialSelectColumnarPtMask: - def test_pandas(self, geometry, pt_mask, pandas_df): - mask = spatial_select_columnar(pandas_df.x, pandas_df.y, geometry) + + def test_pandas(self, geometry, pt_mask, pandas_df, _method): + mask = spatial_select_columnar(pandas_df.x, pandas_df.y, geometry, _method) assert np.array_equal(mask, pt_mask) @dd_available - def test_dask(self, geometry, pt_mask, dask_df): - mask = spatial_select_columnar(dask_df.x, dask_df.y, geometry) + def test_dask(self, geometry, pt_mask, dask_df, _method): + mask = spatial_select_columnar(dask_df.x, dask_df.y, geometry, _method) assert np.array_equal(mask.compute(), pt_mask) - def test_numpy(self, geometry, pt_mask, pandas_df): - mask = spatial_select_columnar(pandas_df.x.to_numpy(copy=True), pandas_df.y.to_numpy(copy=True), geometry) + def test_numpy(self, geometry, pt_mask, pandas_df, _method): + mask = spatial_select_columnar(pandas_df.x.to_numpy(copy=True), pandas_df.y.to_numpy(copy=True), geometry, _method) assert np.array_equal(mask, pt_mask) @pytest.mark.parametrize("geometry", [geometry_encl, geometry_noencl]) class TestSpatialSelectColumnarDaskMeta: @dd_available - def test_meta_dtype(self, geometry, dask_df): - mask = spatial_select_columnar(dask_df.x, dask_df.y, geometry) + def test_meta_dtype(self, geometry, dask_df, _method): + mask = spatial_select_columnar(dask_df.x, dask_df.y, geometry, _method) assert mask._meta.dtype == np.bool_ + + +@pytest.mark.skipif(shapely is None, reason='Shapely not available') +class TestSpatialSelectColumnarShapely(TestSpatialSelectColumnar): + __test__ = True + method = 'shapely' + + +@pytest.mark.skipif(spd is None, reason='Spatialpandas not available') +class TestSpatialSelectColumnarSpatialpandas(TestSpatialSelectColumnar): + __test__ = True + method = 'spatialpandas' diff --git a/holoviews/tests/operation/test_datashader.py b/holoviews/tests/operation/test_datashader.py index a630f8cb0d..ee4302649b 100644 --- a/holoviews/tests/operation/test_datashader.py +++ b/holoviews/tests/operation/test_datashader.py @@ -221,7 +221,7 @@ def test_aggregate_curve_datetimes(self): def test_aggregate_curve_datetimes_dask(self): df = pd.DataFrame( data=np.arange(1000), columns=['a'], - index=pd.date_range('2019-01-01', freq='1T', periods=1000), + index=pd.date_range('2019-01-01', freq='1min', periods=1000), ) ddf = dd.from_pandas(df, npartitions=4) curve = Curve(ddf, kdims=['index'], vdims=['a']) @@ -270,7 +270,7 @@ def test_aggregate_ndoverlay_count_cat_datetimes_microsecond_timebase(self): self.assertEqual(imgs[1], expected2) def test_aggregate_dt_xaxis_constant_yaxis(self): - df = pd.DataFrame({'y': np.ones(100)}, index=pd.date_range('1980-01-01', periods=100, freq='1T')) + df = pd.DataFrame({'y': np.ones(100)}, index=pd.date_range('1980-01-01', periods=100, freq='1min')) img = rasterize(Curve(df), dynamic=False, width=3) xs = np.array(['1980-01-01T00:16:30.000000', '1980-01-01T00:49:30.000000', '1980-01-01T01:22:30.000000'], dtype='datetime64[us]') @@ -868,7 +868,7 @@ def test_shade_categorical_images_grid(self): self.assertEqual(shaded, expected) def test_shade_dt_xaxis_constant_yaxis(self): - df = pd.DataFrame({'y': np.ones(100)}, index=pd.date_range('1980-01-01', periods=100, freq='1T')) + df = pd.DataFrame({'y': np.ones(100)}, index=pd.date_range('1980-01-01', periods=100, freq='1min')) rgb = shade(rasterize(Curve(df), dynamic=False, width=3)) xs = np.array(['1980-01-01T00:16:30.000000', '1980-01-01T00:49:30.000000', '1980-01-01T01:22:30.000000'], dtype='datetime64[us]') diff --git a/holoviews/tests/plotting/bokeh/test_callbacks.py b/holoviews/tests/plotting/bokeh/test_callbacks.py index 85ed947659..889740757c 100644 --- a/holoviews/tests/plotting/bokeh/test_callbacks.py +++ b/holoviews/tests/plotting/bokeh/test_callbacks.py @@ -422,7 +422,12 @@ def test_cds_resolves(self): 'value': points.columns()}) def test_rangexy_datetime(self): - curve = Curve(pd._testing.makeTimeDataFrame(), 'index', 'C') + df = pd.DataFrame( + data = np.random.default_rng(2).standard_normal((30, 4)), + columns=list('ABCD'), + index=pd.date_range('2018-01-01', freq='D', periods=30), + ) + curve = Curve(df, 'index', 'C') stream = RangeXY(source=curve) plot = bokeh_server_renderer.get_plot(curve) callback = plot.callbacks[0] diff --git a/pyproject.toml b/pyproject.toml index cf88cf6cc1..aa620a8351 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,6 +45,8 @@ filterwarnings = [ "ignore:datetime.datetime.utcfromtimestamp():DeprecationWarning:dateutil.tz.tz", # https://github.com/dateutil/dateutil/pull/1285 "ignore:datetime.datetime.utcfromtimestamp():DeprecationWarning:bokeh", # https://github.com/bokeh/bokeh/issues/13125 "ignore:datetime.datetime.utcnow():DeprecationWarning:bokeh", # https://github.com/bokeh/bokeh/issues/13125 + # 2024-01: Pandas 2.2 problems in Dask + "ignore:When grouping with a length-1 list::dask.dataframe.groupby", # https://github.com/dask/dask/issues/10572 ] [tool.coverage] From c0e60646a442dcf2a5092daa0537e26a90f8b404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Fri, 19 Jan 2024 15:12:41 +0100 Subject: [PATCH 28/66] Disable always on warnings (#6077) --- holoviews/util/warnings.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/holoviews/util/warnings.py b/holoviews/util/warnings.py index 6136ee7814..c24a13f254 100644 --- a/holoviews/util/warnings.py +++ b/holoviews/util/warnings.py @@ -81,7 +81,3 @@ class HoloviewsUserWarning(UserWarning): """A Holoviews-specific ``UserWarning`` subclass. Used to selectively filter Holoviews warnings for unconditional display. """ - - -warnings.simplefilter("always", HoloviewsDeprecationWarning) -warnings.simplefilter("always", HoloviewsUserWarning) From 6aa6c9ddb7c9308531753efae41cbd0873c975a3 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Fri, 19 Jan 2024 15:22:37 +0100 Subject: [PATCH 29/66] Add Comm on_open handler to initialize the server comm (#6076) --- holoviews/plotting/renderer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/holoviews/plotting/renderer.py b/holoviews/plotting/renderer.py index 484be8b87d..04f86b5b48 100644 --- a/holoviews/plotting/renderer.py +++ b/holoviews/plotting/renderer.py @@ -408,7 +408,8 @@ def _render_panel(self, plot, embed=False, comm=True): client_comm = self.comm_manager.get_client_comm( on_msg=partial(plot._on_msg, ref, manager), on_error=partial(plot._on_error, ref), - on_stdout=partial(plot._on_stdout, ref) + on_stdout=partial(plot._on_stdout, ref), + on_open=lambda _: comm.init() ) manager.client_comm_id = client_comm.id return render_mimebundle(model, doc, comm, manager) From d4491bda2836f2f221c8bdc3d53de877d67e12e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Tue, 23 Jan 2024 13:04:57 +0100 Subject: [PATCH 30/66] Fix tests suite because of Pandas 2.2 release (#6078) --- .pre-commit-config.yaml | 4 ++-- README.md | 2 +- holoviews/__init__.py | 4 ++-- holoviews/element/graphs.py | 2 +- holoviews/tests/plotting/bokeh/test_renderer.py | 4 ++++ pyproject.toml | 4 +++- 6 files changed, 13 insertions(+), 7 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1b12bcdfef..59692581c1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,7 @@ repos: - id: check-json - id: detect-private-key - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.1.8 + rev: v0.1.14 hooks: - id: ruff files: holoviews/|scripts/ @@ -46,7 +46,7 @@ repos: hooks: - id: shellcheck - repo: https://github.com/pre-commit/mirrors-prettier - rev: v4.0.0-alpha.7 + rev: v3.1.0 hooks: - id: prettier exclude: conda.recipe/meta.yaml diff --git a/README.md b/README.md index bc5e6237d2..35bffa3f16 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ itself.** | | | | --- | --- | -| Build Status | [![Build Status](https://github.com/holoviz/holoviews/workflows/tests/badge.svg?query=branch:main)](https://github.com/holoviz/holoviews/actions/workflows/test.yaml?query=branch%3Amain) | +| Build Status | [![Build Status](https://github.com/holoviz/holoviews/actions/workflows/test.yaml/badge.svg?branch=main)](https://github.com/holoviz/holoviews/actions/workflows/test.yaml?query=branch%3Amain) | | Coverage | [![codecov](https://codecov.io/gh/holoviz/holoviews/branch/main/graph/badge.svg)](https://codecov.io/gh/holoviz/holoviews) | | Latest dev release | [![Github tag](https://img.shields.io/github/tag/holoviz/holoviews.svg?label=tag&colorB=11ccbb)](https://github.com/holoviz/holoviews/tags) [![dev-site](https://img.shields.io/website-up-down-green-red/http/dev.holoviews.org.svg?label=dev%20website)](http://dev.holoviews.org) | | Latest release | [![Github release](https://img.shields.io/github/release/holoviz/holoviews.svg?label=tag&colorB=11ccbb)](https://github.com/holoviz/holoviews/releases) [![PyPI version](https://img.shields.io/pypi/v/holoviews.svg?colorB=cc77dd)](https://pypi.python.org/pypi/holoviews) [![holoviews version](https://img.shields.io/conda/v/pyviz/holoviews.svg?colorB=4488ff&style=flat)](https://anaconda.org/pyviz/holoviews) [![conda-forge version](https://img.shields.io/conda/v/conda-forge/holoviews.svg?label=conda%7Cconda-forge&colorB=4488ff)](https://anaconda.org/conda-forge/holoviews) [![defaults version](https://img.shields.io/conda/v/anaconda/holoviews.svg?label=conda%7Cdefaults&style=flat&colorB=4488ff)](https://anaconda.org/anaconda/holoviews) | diff --git a/holoviews/__init__.py b/holoviews/__init__.py index c90aa18dcd..eaf4a5ccba 100644 --- a/holoviews/__init__.py +++ b/holoviews/__init__.py @@ -113,10 +113,10 @@ if "IPython" in sys.modules: from .ipython import notebook_extension - extension = notebook_extension # noqa (name remapping) + extension = notebook_extension else: class notebook_extension(param.ParameterizedFunction): - def __call__(self, *args, **opts): # noqa (dummy signature) + def __call__(self, *args, **kwargs): raise Exception("Jupyter notebook not available: use hv.extension instead.") if '_pyodide' in sys.modules: diff --git a/holoviews/element/graphs.py b/holoviews/element/graphs.py index 048d8b2103..e46fc14f42 100644 --- a/holoviews/element/graphs.py +++ b/holoviews/element/graphs.py @@ -269,7 +269,7 @@ def select(self, selection_expr=None, selection_specs=None, selection_mode='edge index_dim = self.nodes.kdims[2].name dimensions = self.kdims+self.vdims - node_selection = {index_dim: v for k, v in selection.items() + node_selection = {index_dim: v for k, v in selection.items() # noqa: RUF011 if k in self.kdims} if selection_expr: mask = selection_expr.apply(self.nodes, compute=False, keep_index=True) diff --git a/holoviews/tests/plotting/bokeh/test_renderer.py b/holoviews/tests/plotting/bokeh/test_renderer.py index bf601f5c81..2e69a49906 100644 --- a/holoviews/tests/plotting/bokeh/test_renderer.py +++ b/holoviews/tests/plotting/bokeh/test_renderer.py @@ -4,6 +4,7 @@ import numpy as np import panel as pn import param +import pytest from bokeh.io import curdoc from bokeh.themes.theme import Theme from panel.widgets import DiscreteSlider, FloatSlider, Player @@ -154,6 +155,7 @@ def test_render_holomap_individual_widget_position(self): self.assertEqual(obj.widget_location, 'top') self.assertEqual(obj.widget_type, 'individual') + @pytest.mark.filterwarnings('ignore:Attempted to send message over Jupyter Comm') def test_render_dynamicmap_with_dims(self): dmap = DynamicMap(lambda y: Curve([1, 2, y]), kdims=['y']).redim.range(y=(0.1, 5)) obj, _ = self.renderer._validate(dmap, None) @@ -166,6 +168,7 @@ def test_render_dynamicmap_with_dims(self): slider.value = 3.1 self.assertEqual(cds.data['y'][2], 3.1) + @pytest.mark.filterwarnings('ignore:Attempted to send message over Jupyter Comm') def test_render_dynamicmap_with_stream(self): stream = Stream.define('Custom', y=2)() dmap = DynamicMap(lambda y: Curve([1, 2, y]), kdims=['y'], streams=[stream]) @@ -178,6 +181,7 @@ def test_render_dynamicmap_with_stream(self): stream.event(y=3) self.assertEqual(cds.data['y'][2], 3) + @pytest.mark.filterwarnings('ignore:Attempted to send message over Jupyter Comm') def test_render_dynamicmap_with_stream_dims(self): stream = Stream.define('Custom', y=2)() dmap = DynamicMap(lambda x, y: Curve([x, 1, y]), kdims=['x', 'y'], diff --git a/pyproject.toml b/pyproject.toml index aa620a8351..c57f5dd737 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,8 +45,10 @@ filterwarnings = [ "ignore:datetime.datetime.utcfromtimestamp():DeprecationWarning:dateutil.tz.tz", # https://github.com/dateutil/dateutil/pull/1285 "ignore:datetime.datetime.utcfromtimestamp():DeprecationWarning:bokeh", # https://github.com/bokeh/bokeh/issues/13125 "ignore:datetime.datetime.utcnow():DeprecationWarning:bokeh", # https://github.com/bokeh/bokeh/issues/13125 - # 2024-01: Pandas 2.2 problems in Dask + # 2024-01: Pandas 2.2 "ignore:When grouping with a length-1 list::dask.dataframe.groupby", # https://github.com/dask/dask/issues/10572 + "ignore:\\s*Pyarrow will become a required dependency of pandas:DeprecationWarning", # Will go away by itself in Pandas 3.0 + "ignore:Passing a (SingleBlockManager|BlockManager) to (Series|GeoSeries|DataFrame|GeoDataFrame) is deprecated:DeprecationWarning", # https://github.com/holoviz/spatialpandas/issues/137 ] [tool.coverage] From 6dc23ae3e5e8a6cf4374ced5f0270228147602ed Mon Sep 17 00:00:00 2001 From: Theom <49269671+TheoMathurin@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:11:50 +0100 Subject: [PATCH 31/66] Ensure partial methods can be used as dmap callables (#6063) --- holoviews/core/util.py | 2 ++ holoviews/tests/core/test_callable.py | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/holoviews/core/util.py b/holoviews/core/util.py index 8664d0bb50..0baab34c3d 100644 --- a/holoviews/core/util.py +++ b/holoviews/core/util.py @@ -445,6 +445,8 @@ def argspec(callable_obj): arglen = len(callable_obj.args) spec = inspect.getfullargspec(callable_obj.func) args = [arg for arg in spec.args[arglen:] if arg not in callable_obj.keywords] + if inspect.ismethod(callable_obj.func): + args = args[1:] elif inspect.ismethod(callable_obj): # instance and class methods spec = inspect.getfullargspec(callable_obj) args = spec.args[1:] diff --git a/holoviews/tests/core/test_callable.py b/holoviews/tests/core/test_callable.py index 1e01d1b0eb..713c984ee6 100644 --- a/holoviews/tests/core/test_callable.py +++ b/holoviews/tests/core/test_callable.py @@ -24,6 +24,9 @@ def somestaticmethod(): pass @classmethod def someclsmethod(cls): pass + def someinstancemethod(self, x, y): + return x + y + def __call__(self, *testargs): return sum(testargs) @@ -66,6 +69,9 @@ def test_callable_class_name(self): def test_callable_class_call_method(self): self.assertEqual(Callable(CallableClass().__call__).name, 'CallableClass') + def test_callable_instance_method(self): + assert Callable(CallableClass().someinstancemethod).name == 'CallableClass.someinstancemethod' + def test_classmethod_name(self): self.assertEqual(Callable(CallableClass().someclsmethod).name, 'CallableClass.someclsmethod') @@ -116,6 +122,12 @@ def test_callable_partial(self): def test_callable_class(self): self.assertEqual(Callable(CallableClass())(1,2,3,4), 10) + def test_callable_instance_method(self): + assert Callable(CallableClass().someinstancemethod)(1, 2) == 3 + + def test_callable_partial_instance_method(self): + assert Callable(partial(CallableClass().someinstancemethod, x=1))(2) == 3 + def test_callable_paramfunc(self): self.assertEqual(Callable(ParamFunc)(3,b=5), 15) @@ -143,6 +155,14 @@ def test_callable_class_argspec(self): self.assertEqual(Callable(CallableClass()).argspec.keywords, None) self.assertEqual(Callable(CallableClass()).argspec.varargs, 'testargs') + def test_callable_instance_method(self): + assert Callable(CallableClass().someinstancemethod).argspec.args == ['x', 'y'] + assert Callable(CallableClass().someinstancemethod).argspec.keywords is None + + def test_callable_partial_instance_method(self): + assert Callable(partial(CallableClass().someinstancemethod, x=1)).argspec.args == ['y'] + assert Callable(partial(CallableClass().someinstancemethod, x=1)).argspec.keywords is None + def test_callable_paramfunc_argspec(self): self.assertEqual(Callable(ParamFunc).argspec.args, ['a']) self.assertEqual(Callable(ParamFunc).argspec.keywords, 'params') @@ -170,6 +190,12 @@ def test_callable_lambda(self): def test_callable_partial(self): self.assertEqual(Callable(partial(lambda x,y: x+y,x=4))(y=5), 9) + def test_callable_instance_method(self): + assert Callable(CallableClass().someinstancemethod)(x=1, y=2) == 3 + + def test_callable_partial_instance_method(self): + assert Callable(partial(CallableClass().someinstancemethod, x=1))(y=2) == 3 + def test_callable_paramfunc(self): self.assertEqual(Callable(ParamFunc)(a=3,b=5), 15) From 48aa328462dd864f89c05d947903769db81551e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Wed, 24 Jan 2024 13:20:29 +0100 Subject: [PATCH 32/66] Update show_versions to use package name (#6081) --- holoviews/util/_versions.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/holoviews/util/_versions.py b/holoviews/util/_versions.py index 1617d2c74f..731dff2217 100644 --- a/holoviews/util/_versions.py +++ b/holoviews/util/_versions.py @@ -8,7 +8,7 @@ # Data "cudf", "dask", - "ibis", + "ibis-framework", "networkx", "numpy", "pandas", @@ -18,8 +18,9 @@ "xarray", # Processing "numba", - "skimage", + "scikit-image", "scipy", + "tsdownsample", # Plotting "bokeh", "colorcet", @@ -27,7 +28,7 @@ "geoviews", "hvplot", "matplotlib", - "PIL", + "pillow", "plotly", # Jupyter "IPython", @@ -63,3 +64,7 @@ def _panel_comms(): import panel as pn print(f"{'Panel comms':20}: {pn.config.comms}") + + +if __name__ == "__main__": + show_versions() From 30044d458201a84bf10143102736ba940eccbccf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Mon, 29 Jan 2024 10:08:42 +0100 Subject: [PATCH 33/66] Add test for downsample algorithms (#6083) --- holoviews/tests/conftest.py | 18 +++++++++++ holoviews/tests/element/test_selection.py | 2 +- holoviews/tests/operation/test_downsample.py | 32 +++++++++++++++++++- setup.py | 4 +++ 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/holoviews/tests/conftest.py b/holoviews/tests/conftest.py index 899d834f92..f4d9533400 100644 --- a/holoviews/tests/conftest.py +++ b/holoviews/tests/conftest.py @@ -1,4 +1,6 @@ import contextlib +import sys +from collections.abc import Callable import pytest from panel.tests.conftest import ( # noqa @@ -80,3 +82,19 @@ def plotly_backend(): hv.Store.current_backend = 'plotly' yield hv.Store.current_backend = prev_backend + +@pytest.fixture +def unimport(monkeypatch: pytest.MonkeyPatch) -> Callable[[str], None]: + """ + Return a function for unimporting modules and preventing reimport. + + This will block any new modules from being imported. + """ + + def unimport_module(modname: str) -> None: + # Remove if already imported + monkeypatch.delitem(sys.modules, modname, raising=False) + # Prevent import: + monkeypatch.setattr(sys, "path", []) + + return unimport_module diff --git a/holoviews/tests/element/test_selection.py b/holoviews/tests/element/test_selection.py index 7e92b475b6..4586371262 100644 --- a/holoviews/tests/element/test_selection.py +++ b/holoviews/tests/element/test_selection.py @@ -657,7 +657,7 @@ def pandas_df(self): -1,-1,-1] }, dtype=float) - @dd_available + @pytest.fixture(scope="function") def dask_df(self, pandas_df): return dd.from_pandas(pandas_df, npartitions=2) diff --git a/holoviews/tests/operation/test_downsample.py b/holoviews/tests/operation/test_downsample.py index d82813b1d0..c3057df92c 100644 --- a/holoviews/tests/operation/test_downsample.py +++ b/holoviews/tests/operation/test_downsample.py @@ -1,7 +1,13 @@ +import numpy as np import pytest import holoviews as hv -from holoviews.operation.downsample import downsample1d +from holoviews.operation.downsample import _ALGORITHMS, downsample1d + +try: + import tsdownsample +except ImportError: + tsdownsample = None @pytest.mark.parametrize("plottype", ["overlay", "ndoverlay"]) @@ -18,3 +24,27 @@ def test_downsample1d_multi(plottype): for n in figure_values: for value in n.data.values(): assert value.size == downsample1d.width + + +@pytest.mark.parametrize("algorithm", _ALGORITHMS.values(), ids=_ALGORITHMS) +def test_downsample_algorithm(algorithm, unimport): + unimport("tsdownsample") + x = np.arange(1000) + y = np.random.rand(1000) + width = 20 + try: + result = algorithm(x, y, width) + except NotImplementedError: + pytest.skip("not testing tsdownsample algorithms") + else: + assert result.size == width + + +@pytest.mark.skipif(not tsdownsample, reason="tsdownsample not installed") +@pytest.mark.parametrize("algorithm", _ALGORITHMS.values(), ids=_ALGORITHMS) +def test_downsample_algorithm_with_tsdownsample(algorithm): + x = np.arange(1000) + y = np.random.rand(1000) + width = 20 + result = algorithm(x, y, width) + assert result.size == width diff --git a/setup.py b/setup.py index b824702a31..de313564de 100644 --- a/setup.py +++ b/setup.py @@ -59,6 +59,10 @@ 'dash >=1.16', ] +if os.name != "nt": + # Currently not available on Windows on conda-forge + extras_require['tests'] += ['tsdownsample'] + extras_require['tests_ci'] = [ 'codecov', "pytest-github-actions-annotate-failures", From 231cd718d3834a3456a41056ec9409d3f9fcf3f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Tue, 30 Jan 2024 16:56:15 +0100 Subject: [PATCH 34/66] Try fix failing Windows tests (#6087) --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index de313564de..108ad5d51e 100644 --- a/setup.py +++ b/setup.py @@ -76,7 +76,7 @@ extras_require['ui'] = ['playwright', 'pytest-playwright'] # Notebook dependencies -extras_require["notebook"] = ["ipython >=5.4.0", "notebook"] +extras_require["notebook"] = ["ipython >=5.4.0", "notebook >=7.0"] # IPython Notebook + pandas + matplotlib + bokeh extras_require["recommended"] = extras_require["notebook"] + [ From c800e525aa7a1ffea1d8779642113b3f21dd9440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Tue, 30 Jan 2024 17:44:54 +0100 Subject: [PATCH 35/66] Add viewport downsample algorithm (#6017) Co-authored-by: Philipp Rudiger --- holoviews/core/data/cudf.py | 12 ++++++ holoviews/core/data/dask.py | 20 +++++++++ holoviews/core/data/ibis.py | 12 ++++++ holoviews/core/data/interface.py | 15 +++++++ holoviews/operation/downsample.py | 42 ++++++++++++++++--- holoviews/plotting/bokeh/callbacks.py | 7 ++++ holoviews/plotting/bokeh/plot.py | 3 -- holoviews/streams.py | 8 ++++ holoviews/tests/core/data/base.py | 6 +++ .../tests/core/data/test_cudfinterface.py | 7 ++++ .../tests/core/data/test_ibisinterface.py | 7 ++++ holoviews/tests/operation/test_downsample.py | 10 ++++- 12 files changed, 139 insertions(+), 10 deletions(-) diff --git a/holoviews/core/data/cudf.py b/holoviews/core/data/cudf.py index 36af1ac49e..455a177183 100644 --- a/holoviews/core/data/cudf.py +++ b/holoviews/core/data/cudf.py @@ -231,6 +231,18 @@ def select_mask(cls, dataset, selection): mask &= new_mask return mask + @classmethod + def _select_mask_neighbor(cls, dataset, selection): + """Runs select mask and expand the True values to include its neighbors + + Example + + select_mask = [False, False, True, True, False, False] + select_mask_neighbor = [False, True, True, True, True, False] + + """ + raise NotImplementedError + @classmethod def select(cls, dataset, selection_mask=None, **selection): df = dataset.data diff --git a/holoviews/core/data/dask.py b/holoviews/core/data/dask.py index 5b1160220b..ebffe3519d 100644 --- a/holoviews/core/data/dask.py +++ b/holoviews/core/data/dask.py @@ -154,6 +154,9 @@ def select_mask(cls, dataset, selection): def select(cls, dataset, selection_mask=None, **selection): df = dataset.data if selection_mask is not None: + import dask.array as da + if isinstance(selection_mask, da.Array): + return df.loc[selection_mask] return df[selection_mask] selection_mask = cls.select_mask(dataset, selection) indexed = cls.indexed(dataset, selection) @@ -162,6 +165,23 @@ def select(cls, dataset, selection_mask=None, **selection): return df[dataset.vdims[0].name].compute().iloc[0] return df + @classmethod + def _select_mask_neighbor(cls, dataset, selection): + """Runs select mask and expand the True values to include its neighbors + + Example + + select_mask = [False, False, True, True, False, False] + select_mask_neighbor = [False, True, True, True, True, False] + + """ + mask = cls.select_mask(dataset, selection) + mask = mask.to_dask_array().compute_chunk_sizes() + extra = mask[1:] ^ mask[:-1] + mask[1:] |= extra + mask[:-1] |= extra + return mask + @classmethod def groupby(cls, dataset, dimensions, container_type, group_type, **kwargs): index_dims = [dataset.get_dimension(d) for d in dimensions] diff --git a/holoviews/core/data/ibis.py b/holoviews/core/data/ibis.py index 691a55d26c..f904995d07 100644 --- a/holoviews/core/data/ibis.py +++ b/holoviews/core/data/ibis.py @@ -427,6 +427,18 @@ def select_mask(cls, dataset, selection): predicates.append(column == object) return predicates + @classmethod + def _select_mask_neighbor(cls, dataset, selection): + """Runs select mask and expand the True values to include its neighbors + + Example + + select_mask = [False, False, True, True, False, False] + select_mask_neighbor = [False, True, True, True, True, False] + + """ + raise NotImplementedError + @classmethod def sample(cls, dataset, samples=None): import ibis diff --git a/holoviews/core/data/interface.py b/holoviews/core/data/interface.py index 0a60552f9b..cdd3e151a2 100644 --- a/holoviews/core/data/interface.py +++ b/holoviews/core/data/interface.py @@ -377,6 +377,21 @@ def select_mask(cls, dataset, selection): mask &= index_mask return mask + @classmethod + def _select_mask_neighbor(cls, dataset, selection): + """Runs select mask and expand the True values to include its neighbors + + Example + + select_mask = [False, False, True, True, False, False] + select_mask_neighbor = [False, True, True, True, True, False] + + """ + mask = cls.select_mask(dataset, selection) + extra = mask[1:] ^ mask[:-1] + mask[1:] |= extra + mask[:-1] |= extra + return mask @classmethod def indexed(cls, dataset, selection): diff --git a/holoviews/operation/downsample.py b/holoviews/operation/downsample.py index f75379e9e2..9ffdd3e896 100644 --- a/holoviews/operation/downsample.py +++ b/holoviews/operation/downsample.py @@ -152,10 +152,13 @@ def _nth_point(x, y, n_out, **kwargs): y (np.ndarray): The y-values of the data. n_out (int): The number of output points. Returns: - np.array: The indexes of the selected datapoints. + slice: The slice of selected datapoints. """ n_samples = len(x) - return np.arange(0, n_samples, max(1, math.ceil(n_samples / n_out))) + return slice(0, n_samples, max(1, math.ceil(n_samples / n_out))) + +def _viewport(x, y, n_out, **kwargs): + return slice(len(x)) def _min_max(x, y, n_out, **kwargs): try: @@ -191,6 +194,7 @@ def _m4(x, y, n_out, **kwargs): _ALGORITHMS = { 'lttb': _lttb, 'nth': _nth_point, + 'viewport': _viewport, 'minmax': _min_max, 'minmax-lttb': _min_max_lttb, 'm4': _m4, @@ -207,13 +211,14 @@ class downsample1d(ResampleOperation1D): algorithm = param.Selector(default='lttb', objects=list(_ALGORITHMS), doc=""" The algorithm to use for downsampling: - - `lttb`: Largest Triangle Three Buckets downsample algorithm + - `lttb`: Largest Triangle Three Buckets downsample algorithm. - `nth`: Selects every n-th point. + - `viewport`: Selects all points in a given viewport. - `minmax`: Selects the min and max value in each bin (requires tsdownsampler). - `m4`: Selects the min, max, first and last value in each bin (requires tsdownsampler). - `minmax-lttb`: First selects n_out * minmax_ratio min and max values, then further reduces these to n_out values using the - Largest Triangle Three Buckets algorithm. (requires tsdownsampler)""") + Largest Triangle Three Buckets algorithm (requires tsdownsampler).""") parallel = param.Boolean(default=False, doc=""" The number of threads to use (if tsdownsampler is available).""") @@ -223,6 +228,10 @@ class downsample1d(ResampleOperation1D): values to generate with the minmax algorithm before further downsampling with LTTB.""") + neighbor_points = param.Boolean(default=None, doc=""" + Whether to add the neighbor points to the range before downsampling. + By default this is only enabled for the viewport algorithm.""") + def _process(self, element, key=None): if isinstance(element, (Overlay, NdOverlay)): _process = partial(self._process, key=key) @@ -233,7 +242,8 @@ def _process(self, element, key=None): return element.clone(elements) if self.p.x_range: - element = element[slice(*self.p.x_range)] + mask = self._compute_mask(element) + element = element[mask] if len(element) <= self.p.width: return element xs, ys = (element.dimension_values(i) for i in range(2)) @@ -249,3 +259,25 @@ def _process(self, element, key=None): kwargs['minmax_ratio'] = self.p.minmax_ratio samples = downsample(xs, ys, self.p.width, parallel=self.p.parallel, **kwargs) return element.iloc[samples] + + def _compute_mask(self, element): + """ + Computes the mask to apply to the element before downsampling. + """ + neighbor_enabled = ( + self.p.neighbor_points + if self.p.neighbor_points is not None + else self.p.algorithm == "viewport" + ) + if not neighbor_enabled: + return slice(*self.p.x_range) + try: + mask = element.dataset.interface._select_mask_neighbor( + element.dataset, {element.kdims[0]: self.p.x_range} + ) + except NotImplementedError: + mask = slice(*self.p.x_range) + except Exception as e: + self.param.warning(f"Could not apply neighbor mask to downsample1d: {e}") + mask = slice(*self.p.x_range) + return mask diff --git a/holoviews/plotting/bokeh/callbacks.py b/holoviews/plotting/bokeh/callbacks.py index 8cf7639e38..6a1bdd638c 100644 --- a/holoviews/plotting/bokeh/callbacks.py +++ b/holoviews/plotting/bokeh/callbacks.py @@ -404,6 +404,7 @@ def set_callback(self, handle): if self.on_changes: change_handler = lambda attr, old, new: ( asyncio.create_task(self.on_change(attr, old, new)) + if self.plot.document else None ) for change in self.on_changes: if change in ['patching', 'streaming']: @@ -645,6 +646,12 @@ class RangeXYCallback(Callback): 'y1': 'cb_obj.y1', } + def initialize(self, plot_id=None): + super().initialize(plot_id) + for stream in self.streams: + msg = self._process_msg({}) + stream.update(**msg) + def _process_msg(self, msg): if self.plot.state.x_range is not self.plot.handles['x_range']: x_range = self.plot.handles['x_range'] diff --git a/holoviews/plotting/bokeh/plot.py b/holoviews/plotting/bokeh/plot.py index 7e3814df76..37771afb1b 100644 --- a/holoviews/plotting/bokeh/plot.py +++ b/holoviews/plotting/bokeh/plot.py @@ -173,9 +173,6 @@ def _update_datasource(self, source, data): """ Update datasource with data for a new frame. """ - if not self.document: - return - data = self._postprocess_data(data) empty = all(len(v) == 0 for v in data.values()) if (self.streaming and self.streaming[0].data is self.current_frame.data diff --git a/holoviews/streams.py b/holoviews/streams.py index 309b4ac153..75f66af7af 100644 --- a/holoviews/streams.py +++ b/holoviews/streams.py @@ -1480,6 +1480,10 @@ class RangeX(LinkedStream): x_range = param.Tuple(default=None, length=2, constant=True, doc=""" Range of the x-axis of a plot in data coordinates""") + def _set_stream_parameters(self, **kwargs): + kwargs.pop("y_range", None) + super()._set_stream_parameters(**kwargs) + class RangeY(LinkedStream): """ @@ -1489,6 +1493,10 @@ class RangeY(LinkedStream): y_range = param.Tuple(default=None, length=2, constant=True, doc=""" Range of the y-axis of a plot in data coordinates""") + def _set_stream_parameters(self, **kwargs): + kwargs.pop("x_range", None) + super()._set_stream_parameters(**kwargs) + class BoundsXY(LinkedStream): """ diff --git a/holoviews/tests/core/data/base.py b/holoviews/tests/core/data/base.py index ed8121688e..34bd776c0f 100644 --- a/holoviews/tests/core/data/base.py +++ b/holoviews/tests/core/data/base.py @@ -858,6 +858,12 @@ def test_dataset_transform_add_ht(self): kdims=self.kdims, vdims=self.vdims+['combined']) self.assertEqual(transformed, expected) + def test_select_with_neighbor(self): + select = self.table.interface.select_mask(self.table.dataset, {"Weight": 18}) + select_neighbor = self.table.interface._select_mask_neighbor(self.table.dataset, dict(Weight=18)) + + np.testing.assert_almost_equal(select, [False, True, False]) + np.testing.assert_almost_equal(select_neighbor, [True, True, True]) class ScalarColumnTests: diff --git a/holoviews/tests/core/data/test_cudfinterface.py b/holoviews/tests/core/data/test_cudfinterface.py index cdb6c19014..87cb469190 100644 --- a/holoviews/tests/core/data/test_cudfinterface.py +++ b/holoviews/tests/core/data/test_cudfinterface.py @@ -104,3 +104,10 @@ def test_dataset_groupby_second_dim(self): def test_dataset_aggregate_string_types_size(self): raise SkipTest("cuDF does not support variance aggregation") + + def test_select_with_neighbor(self): + try: + # Not currently supported by CuDF + super().test_select_with_neighbor() + except NotImplementedError: + raise SkipTest("Not supported") diff --git a/holoviews/tests/core/data/test_ibisinterface.py b/holoviews/tests/core/data/test_ibisinterface.py index 3f0b4d1773..2b488ec7a6 100644 --- a/holoviews/tests/core/data/test_ibisinterface.py +++ b/holoviews/tests/core/data/test_ibisinterface.py @@ -256,6 +256,13 @@ def test_aggregation_operations(self): self.compare_dataset(expected, result, msg=str(agg)) + def test_select_with_neighbor(self): + try: + # Not currently supported by Ibis + super().test_select_with_neighbor() + except NotImplementedError: + raise SkipTest("Not supported") + if not IbisInterface.has_rowid(): def test_dataset_iloc_slice_rows_slice_cols(self): diff --git a/holoviews/tests/operation/test_downsample.py b/holoviews/tests/operation/test_downsample.py index c3057df92c..02b491e567 100644 --- a/holoviews/tests/operation/test_downsample.py +++ b/holoviews/tests/operation/test_downsample.py @@ -9,6 +9,8 @@ except ImportError: tsdownsample = None +algorithms = _ALGORITHMS.copy() +algorithms.pop('viewport', None) # viewport return slice(len(data)) no matter the width @pytest.mark.parametrize("plottype", ["overlay", "ndoverlay"]) def test_downsample1d_multi(plottype): @@ -26,7 +28,7 @@ def test_downsample1d_multi(plottype): assert value.size == downsample1d.width -@pytest.mark.parametrize("algorithm", _ALGORITHMS.values(), ids=_ALGORITHMS) +@pytest.mark.parametrize("algorithm", algorithms.values(), ids=algorithms) def test_downsample_algorithm(algorithm, unimport): unimport("tsdownsample") x = np.arange(1000) @@ -37,14 +39,18 @@ def test_downsample_algorithm(algorithm, unimport): except NotImplementedError: pytest.skip("not testing tsdownsample algorithms") else: + if isinstance(result, slice): + result = x[result] assert result.size == width @pytest.mark.skipif(not tsdownsample, reason="tsdownsample not installed") -@pytest.mark.parametrize("algorithm", _ALGORITHMS.values(), ids=_ALGORITHMS) +@pytest.mark.parametrize("algorithm", algorithms.values(), ids=algorithms) def test_downsample_algorithm_with_tsdownsample(algorithm): x = np.arange(1000) y = np.random.rand(1000) width = 20 result = algorithm(x, y, width) + if isinstance(result, slice): + result = x[result] assert result.size == width From c7b98de035d46885205f2c5d18a4312ab8907adf Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Tue, 30 Jan 2024 22:18:59 +0100 Subject: [PATCH 36/66] Optimize downsample1d when data is shared between layers (#6075) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Simon Høxbro Hansen --- holoviews/operation/downsample.py | 17 ++++++-- holoviews/tests/operation/test_downsample.py | 44 +++++++++++++++++++- 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/holoviews/operation/downsample.py b/holoviews/operation/downsample.py index 9ffdd3e896..616434d386 100644 --- a/holoviews/operation/downsample.py +++ b/holoviews/operation/downsample.py @@ -232,9 +232,11 @@ class downsample1d(ResampleOperation1D): Whether to add the neighbor points to the range before downsampling. By default this is only enabled for the viewport algorithm.""") - def _process(self, element, key=None): + def _process(self, element, key=None, shared_data=None): if isinstance(element, (Overlay, NdOverlay)): - _process = partial(self._process, key=key) + # Shared data is so we only slice the given data once + kwargs = {'key': key, 'shared_data': {}} + _process = partial(self._process, **kwargs) if isinstance(element, Overlay): elements = [v.map(_process) for v in element] else: @@ -242,8 +244,15 @@ def _process(self, element, key=None): return element.clone(elements) if self.p.x_range: - mask = self._compute_mask(element) - element = element[mask] + key = (id(element.data), str(element.kdims[0])) + if shared_data is not None and key in shared_data: + element = element.clone(shared_data[key]) + else: + mask = self._compute_mask(element) + element = element[mask] + if shared_data is not None: + shared_data[key] = element.data + if len(element) <= self.p.width: return element xs, ys = (element.dimension_values(i) for i in range(2)) diff --git a/holoviews/tests/operation/test_downsample.py b/holoviews/tests/operation/test_downsample.py index 02b491e567..066a0dd6b8 100644 --- a/holoviews/tests/operation/test_downsample.py +++ b/holoviews/tests/operation/test_downsample.py @@ -1,4 +1,5 @@ import numpy as np +import pandas as pd import pytest import holoviews as hv @@ -10,7 +11,8 @@ tsdownsample = None algorithms = _ALGORITHMS.copy() -algorithms.pop('viewport', None) # viewport return slice(len(data)) no matter the width +algorithms.pop("viewport", None) # viewport return slice(len(data)) no matter the width + @pytest.mark.parametrize("plottype", ["overlay", "ndoverlay"]) def test_downsample1d_multi(plottype): @@ -28,6 +30,46 @@ def test_downsample1d_multi(plottype): assert value.size == downsample1d.width +def test_downsample1d_shared_data(): + runs = [0] + + class mocksample(downsample1d): + def _compute_mask(self, element): + # Use _compute_mask as this should only be called once + # and then it should be cloned. + runs[0] += 1 + return super()._compute_mask(element) + + N = 1000 + df = pd.DataFrame({c: range(N) for c in "xyz"}) + figure = hv.Overlay([hv.Curve(df, kdims="x", vdims=c) for c in "yz"]) + + # We set x_range to trigger _compute_mask + mocksample(figure, dynamic=False, x_range=(0, 500)) + assert runs[0] == 1 + + +# Should be fixed when https://github.com/holoviz/holoviews/pull/6061 is merged +@pytest.mark.xfail(reason="This will make a copy of the data") +def test_downsample1d_shared_data_index(): + runs = [0] + + class mocksample(downsample1d): + def _compute_mask(self, element): + # Use _compute_mask as this should only be called once + # and then it should be cloned. + runs[0] += 1 + return super()._compute_mask(element) + + N = 1000 + df = pd.DataFrame({c: range(N) for c in "xyz"}) + figure = hv.Overlay([hv.Curve(df, kdims="index", vdims=c) for c in "xyz"]) + + # We set x_range to trigger _compute_mask + mocksample(figure, dynamic=False, x_range=(0, 500)) + assert runs[0] == 1 + + @pytest.mark.parametrize("algorithm", algorithms.values(), ids=algorithms) def test_downsample_algorithm(algorithm, unimport): unimport("tsdownsample") From 90b88161bb81d038c41f638b688900fee51d1fa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Tue, 30 Jan 2024 22:19:11 +0100 Subject: [PATCH 37/66] Del frame after stack level is found (#6085) --- holoviews/util/warnings.py | 20 ++++++++++++-------- scripts/check_latest_packages.py | 3 ++- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/holoviews/util/warnings.py b/holoviews/util/warnings.py index c24a13f254..2bf6366ebb 100644 --- a/holoviews/util/warnings.py +++ b/holoviews/util/warnings.py @@ -34,14 +34,18 @@ def find_stack_level(): param_dir = os.path.dirname(param.__file__) frame = inspect.currentframe() - stacklevel = 0 - while frame: - fname = inspect.getfile(frame) - if fname.startswith((pkg_dir, param_dir)) and not fname.startswith(test_dir): - frame = frame.f_back - stacklevel += 1 - else: - break + try: + stacklevel = 0 + while frame: + fname = inspect.getfile(frame) + if fname.startswith((pkg_dir, param_dir)) and not fname.startswith(test_dir): + frame = frame.f_back + stacklevel += 1 + else: + break + finally: + # See: https://docs.python.org/3/library/inspect.html#inspect.Traceback + del frame return stacklevel diff --git a/scripts/check_latest_packages.py b/scripts/check_latest_packages.py index 9fcada6001..5e4f378425 100644 --- a/scripts/check_latest_packages.py +++ b/scripts/check_latest_packages.py @@ -1,5 +1,6 @@ import sys from datetime import date, datetime, timedelta +from importlib.metadata import version import requests from packaging.version import Version @@ -13,7 +14,7 @@ def main(*packages): url = f"https://pypi.org/pypi/{package}/json" resp = requests.get(url, timeout=20).json() latest = resp["info"]["version"] - current = __import__(package).__version__ + current = version(package) latest_release_date = datetime.fromisoformat( resp["releases"][latest][0]["upload_time_iso_8601"] From eebc6c1e4c40ef541211c6df49ee7192cc8e68fd Mon Sep 17 00:00:00 2001 From: Andrew <15331990+ahuang11@users.noreply.github.com> Date: Tue, 30 Jan 2024 13:20:46 -0800 Subject: [PATCH 38/66] Add downloads badges (#6088) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 35bffa3f16..eaf2ec464e 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ itself.** | | | | --- | --- | +| Downloads | ![https://pypistats.org/packages/holoviews](https://img.shields.io/pypi/dm/holoviews?label=pypi) ![https://anaconda.org/pyviz/holoviews](https://pyviz.org/_static/cache/holoviews_conda_downloads_badge.svg) | Build Status | [![Build Status](https://github.com/holoviz/holoviews/actions/workflows/test.yaml/badge.svg?branch=main)](https://github.com/holoviz/holoviews/actions/workflows/test.yaml?query=branch%3Amain) | | Coverage | [![codecov](https://codecov.io/gh/holoviz/holoviews/branch/main/graph/badge.svg)](https://codecov.io/gh/holoviz/holoviews) | | Latest dev release | [![Github tag](https://img.shields.io/github/tag/holoviz/holoviews.svg?label=tag&colorB=11ccbb)](https://github.com/holoviz/holoviews/tags) [![dev-site](https://img.shields.io/website-up-down-green-red/http/dev.holoviews.org.svg?label=dev%20website)](http://dev.holoviews.org) | From ef094fb2cc32788e087ce6747e53007f98c1cd82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Fri, 2 Feb 2024 10:06:17 +0100 Subject: [PATCH 39/66] Update ruff in pre-commit (#6091) --- .pre-commit-config.yaml | 2 +- holoviews/core/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 59692581c1..c0da1e2c85 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,7 @@ repos: - id: check-json - id: detect-private-key - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.1.14 + rev: v0.2.0 hooks: - id: ruff files: holoviews/|scripts/ diff --git a/holoviews/core/util.py b/holoviews/core/util.py index 0baab34c3d..b389c884e9 100644 --- a/holoviews/core/util.py +++ b/holoviews/core/util.py @@ -1314,7 +1314,7 @@ def dimension_sort(odict, kdims, vdims, key_index): def is_number(obj): if isinstance(obj, numbers.Number): return True elif isinstance(obj, np.str_): return False - elif np.__version__[0] < "2" and isinstance(obj, np.unicode_): return False + elif np.__version__[0] < "2" and isinstance(obj, np.unicode_): return False # noqa: NPY201 # The extra check is for classes that behave like numbers, such as those # found in numpy, gmpy, etc. elif (hasattr(obj, '__int__') and hasattr(obj, '__add__')): return True From 8936f44926b4ca64b25f2146c530f1bd30f56fe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Fri, 2 Feb 2024 18:01:35 +0100 Subject: [PATCH 40/66] Add v1.18.2 to changelog (#6094) --- CHANGELOG.md | 55 +++++++++++++++++++++++++++ doc/releases.rst | 97 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a9eeb21e5..f1b300e42f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,58 @@ +# Version 1.18.2 + +**February 5, 2024** + +This minor release includes a number of bug fixes and documentation updates, as well as compatibility updates for xarray 2023.12 and Pandas 2.2. +Many thanks to the new contributors @junietoc, @JulianGiles, and @magic-lantern, as well as the returning contributors @ianthomas23, @maximlt, @TheoMathurin, @philippjfr, @ahuang11, and @Hoxbro. + +Enhancements: + +- Update contour line calculations to use ContourPy's `LineType.ChunkCombinedNan` ([#5985](https://github.com/holoviz/holoviews/pull/5985)) +- Use sys.executable for `check_output` ([#5983](https://github.com/holoviz/holoviews/pull/5983)) +- Updates to `show_versions` ([(#6072)](https://github.com/holoviz/holoviews/pull/6072), [(#6081)](https://github.com/holoviz/holoviews/pull/6081)) + +Bug fixes: + +- Support `color_key` in `datashade` when intermediate step is an `ImageStack` ([#5994](https://github.com/holoviz/holoviews/pull/5994)) +- Fix hist on overlay ([#5995](https://github.com/holoviz/holoviews/pull/5995)) +- Set proper context before triggering streams ([#6000](https://github.com/holoviz/holoviews/pull/6000)) +- Support partial bound function ([#6009](https://github.com/holoviz/holoviews/pull/6009)) +- Add `norm` in `init_artists` in holoviews/plotting/mpl/raster.py ([#6029](https://github.com/holoviz/holoviews/pull/6029)) +- Fix linking elements that are transformed by a Compositor ([#6003](https://github.com/holoviz/holoviews/pull/6003)) +- Add datetime hover information for selector ([#6023](https://github.com/holoviz/holoviews/pull/6023), [(#6039)](https://github.com/holoviz/holoviews/pull/6039)) +- Only evaluate `rx` if it is an Reactive Expression ([(#6014)](https://github.com/holoviz/holoviews/pull/6014)) +- Ensure partial methods can be used as dmap callables ([(#6063)](https://github.com/holoviz/holoviews/pull/6063)) +- Del frame after stack level is found in `deprecated` ([(#6085)](https://github.com/holoviz/holoviews/pull/6085)) + +Compatibility: + +- Compatibility updates with xarray 2023.12 ([#6026](https://github.com/holoviz/holoviews/pull/6026)) +- Add extra check to detect if we are in jupyterlite ([#6007](https://github.com/holoviz/holoviews/pull/6007)) +- Compatibility updates with Pandas 2.2 ([(#6074)](https://github.com/holoviz/holoviews/pull/6074), [(#6078)](https://github.com/holoviz/holoviews/pull/6078)) +- Add Comm `on_open` handler to initialize the server comm ([(#6076)](https://github.com/holoviz/holoviews/pull/6076)) + +Documentation: + +- Fix docs ([#5996](https://github.com/holoviz/holoviews/pull/5996)) +- Fix Param usage in the Plot and Renderers guide ([#6001](https://github.com/holoviz/holoviews/pull/6001)) +- Fixing URLs to bokeh project ([#6005](https://github.com/holoviz/holoviews/pull/6005)) +- Fix to broken urls in example gallery pages ([(#6038)](https://github.com/holoviz/holoviews/pull/6038)) +- Replace Google Analytics with GoatCounter ([(#6048)](https://github.com/holoviz/holoviews/pull/6048)) +- Add downloads badges ([(#6088)](https://github.com/holoviz/holoviews/pull/6088)) + +Maintenance: + +- Change to pytest-rerunfailures ([#5984](https://github.com/holoviz/holoviews/pull/5984)) +- Holoviews maintenance ([#5987](https://github.com/holoviz/holoviews/pull/5987)) +- Add `log_cli_level = "INFO"` to pytest ([#5989](https://github.com/holoviz/holoviews/pull/5989)) +- Add shell pre-commit hook ([#5991](https://github.com/holoviz/holoviews/pull/5991)) +- Enable Bugbear 904 ([#5992](https://github.com/holoviz/holoviews/pull/5992)) +- Part 1, modernize test suite ([#5954](https://github.com/holoviz/holoviews/pull/5954)) +- Enforce labels ([#5996](https://github.com/holoviz/holoviews/pull/5997)) +- Add lower pin to scipy ([#6032](https://github.com/holoviz/holoviews/pull/6032)) +- Skip Deploying_Bokeh_Apps.ipynb on Windows ([(#6070)](https://github.com/holoviz/holoviews/pull/6070)) +- Fix failing Windows tests ([(#6087)](https://github.com/holoviz/holoviews/pull/6087)) + # Version 1.18.1 **November 8, 2023** diff --git a/doc/releases.rst b/doc/releases.rst index 911d38faf0..15b9bf422a 100644 --- a/doc/releases.rst +++ b/doc/releases.rst @@ -4,6 +4,103 @@ Releases Version 1.18 ~~~~~~~~~~~~ +Version 1.18.2 +************** + +**February 5, 2024** + +This minor release includes a number of bug fixes and documentation +updates, as well as compatibility updates for xarray 2023.12 and Pandas +2.2. Many thanks to the new contributors @junietoc, @JulianGiles, and +@magic-lantern, as well as the returning contributors @ianthomas23, +@maximlt, @TheoMathurin, @philippjfr, @ahuang11, and @Hoxbro. + +Enhancements: + +- Update contour line calculations to use ContourPy’s + ``LineType.ChunkCombinedNan`` + (`#5985 `__) +- Use sys.executable for ``check_output`` + (`#5983 `__) +- Updates to ``show_versions`` + (`(#6072) `__, + `(#6081) `__) + +Bug fixes: + +- Support ``color_key`` in ``datashade`` when intermediate step is an + ``ImageStack`` + (`#5994 `__) +- Fix hist on overlay + (`#5995 `__) +- Set proper context before triggering streams + (`#6000 `__) +- Support partial bound function + (`#6009 `__) +- Add ``norm`` in ``init_artists`` in holoviews/plotting/mpl/raster.py + (`#6029 `__) +- Fix linking elements that are transformed by a Compositor + (`#6003 `__) +- Add datetime hover information for selector + (`#6023 `__, + `(#6039) `__) +- Only evaluate ``rx`` if it is an Reactive Expression + (`(#6014) `__) +- Ensure partial methods can be used as dmap callables + (`(#6063) `__) +- Del frame after stack level is found in ``deprecated`` + (`(#6085) `__) + +Compatibility: + +- Compatibility updates with xarray 2023.12 + (`#6026 `__) +- Add extra check to detect if we are in jupyterlite + (`#6007 `__) +- Compatibility updates with Pandas 2.2 + (`(#6074) `__, + `(#6078) `__) +- Add Comm ``on_open`` handler to initialize the server comm + (`(#6076) `__) + +Documentation: + +- Fix docs (`#5996 `__) +- Fix Param usage in the Plot and Renderers guide + (`#6001 `__) +- Fixing URLs to bokeh project + (`#6005 `__) +- Fix to broken urls in example gallery pages + (`(#6038) `__) +- Replace Google Analytics with GoatCounter + (`(#6048) `__) +- Add downloads badges + (`(#6088) `__) + +Maintenance: + +- Change to pytest-rerunfailures + (`#5984 `__) +- Holoviews maintenance + (`#5987 `__) +- Add ``log_cli_level = "INFO"`` to pytest + (`#5989 `__) +- Add shell pre-commit hook + (`#5991 `__) +- Enable Bugbear 904 + (`#5992 `__) +- Part 1, modernize test suite + (`#5954 `__) +- Enforce labels + (`#5996 `__) +- Add lower pin to scipy + (`#6032 `__) +- Skip Deploying_Bokeh_Apps.ipynb on Windows + (`(#6070) `__) +- Fix failing Windows tests + (`(#6087) `__) + + Version 1.18.1 ************** From f81533a4619f689bf4216f6c4013f25b6e9997d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Tue, 6 Feb 2024 09:46:32 +0100 Subject: [PATCH 41/66] Fix BoundsX and BoundsY regression (#6099) --- holoviews/plotting/bokeh/callbacks.py | 4 ++-- holoviews/tests/ui/bokeh/test_callback.py | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/holoviews/plotting/bokeh/callbacks.py b/holoviews/plotting/bokeh/callbacks.py index 6a1bdd638c..521970a0a3 100644 --- a/holoviews/plotting/bokeh/callbacks.py +++ b/holoviews/plotting/bokeh/callbacks.py @@ -833,7 +833,7 @@ class BoundsXCallback(Callback): models = ['plot'] on_events = ['selectiongeometry'] - skip_events = [lambda event: event.geometry['type'] != 'quad', + skip_events = [lambda event: event.geometry['type'] != 'rect', lambda event: not event.final] def _process_msg(self, msg): @@ -856,7 +856,7 @@ class BoundsYCallback(Callback): models = ['plot'] on_events = ['selectiongeometry'] - skip_events = [lambda event: event.geometry['type'] != 'quad', + skip_events = [lambda event: event.geometry['type'] != 'rect', lambda event: not event.final] def _process_msg(self, msg): diff --git a/holoviews/tests/ui/bokeh/test_callback.py b/holoviews/tests/ui/bokeh/test_callback.py index 936a7859ed..09e0dbfd5b 100644 --- a/holoviews/tests/ui/bokeh/test_callback.py +++ b/holoviews/tests/ui/bokeh/test_callback.py @@ -16,16 +16,24 @@ import holoviews as hv from holoviews import Curve, DynamicMap, Scatter -from holoviews.streams import BoundsXY, Lasso, RangeXY +from holoviews.streams import BoundsX, BoundsXY, BoundsY, Lasso, RangeXY @pytest.mark.usefixtures("bokeh_backend") -def test_box_select(page, port): +@pytest.mark.parametrize( + ["BoundsTool", "bound_slice", "bound_attr"], + [ + (BoundsXY, slice(None), "bounds"), + (BoundsX, slice(0, None, 2), "boundsx"), + (BoundsY, slice(1, None, 2), "boundsy"), + ], +) +def test_box_select(page, port, BoundsTool, bound_slice, bound_attr): hv_scatter = Scatter([1, 2, 3]).opts( tools=['box_select'], active_tools=['box_select'] ) - bounds = BoundsXY(source=hv_scatter) + bounds = BoundsTool(source=hv_scatter) pn_scatter = HoloViews(hv_scatter) @@ -45,7 +53,7 @@ def test_box_select(page, port): page.mouse.up() expected_bounds = (0.32844036697247725, 1.8285714285714285, 0.8788990825688077, 2.3183673469387758) - wait_until(lambda: bounds.bounds == expected_bounds, page) + wait_until(lambda: getattr(bounds, bound_attr) == expected_bounds[bound_slice], page) @pytest.mark.usefixtures("bokeh_backend") From 9ac5d350b2c711e498d9075832045f538c975757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Tue, 6 Feb 2024 17:13:34 +0100 Subject: [PATCH 42/66] Fix rasterize regression (#6102) --- holoviews/plotting/bokeh/raster.py | 3 ++- holoviews/tests/plotting/bokeh/test_rasterplot.py | 13 ++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/holoviews/plotting/bokeh/raster.py b/holoviews/plotting/bokeh/raster.py index e10c3ecdd9..9245bc86b6 100644 --- a/holoviews/plotting/bokeh/raster.py +++ b/holoviews/plotting/bokeh/raster.py @@ -82,7 +82,8 @@ def _postprocess_hover(self, renderer, source): } """ for key in formatters: - if formatters[key].lower() == "datetime": + formatter = formatters[key] + if isinstance(formatter, str) and formatter.lower() == "datetime": formatters[key] = CustomJSHover(code=datetime_code) hover.tooltips = tooltips diff --git a/holoviews/tests/plotting/bokeh/test_rasterplot.py b/holoviews/tests/plotting/bokeh/test_rasterplot.py index 36e10bc907..56dd684f90 100644 --- a/holoviews/tests/plotting/bokeh/test_rasterplot.py +++ b/holoviews/tests/plotting/bokeh/test_rasterplot.py @@ -3,7 +3,7 @@ import numpy as np import pandas as pd import pytest -from bokeh.models import CustomJSHover +from bokeh.models import CustomJSHover, HoverTool from holoviews.element import RGB, Image, ImageStack, Raster from holoviews.plotting.bokeh.raster import ImageStackPlot @@ -155,6 +155,17 @@ def test_image_datetime_hover(self): else: assert isinstance(hover.formatters["@{Timestamp}"], CustomJSHover) + def test_image_hover_with_custom_js(self): + # Regression for https://github.com/holoviz/holoviews/issues/6101 + hover_tool = HoverTool( + tooltips=[("x", "$x{custom}")], formatters={"x": CustomJSHover(code="return value + '2'")} + ) + img = Image(np.ones(100).reshape(10, 10)).opts(tools=[hover_tool]) + plot = bokeh_renderer.get_plot(img) + + hover = plot.handles["hover"] + assert hover.formatters == hover_tool.formatters + class _ImageStackBase(TestRasterPlot): __test__ = False From b639f172010b7f534dc10da6b8dc824f853a44d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Mon, 12 Feb 2024 10:55:07 +0100 Subject: [PATCH 43/66] Move notebook pin (#6108) --- pyproject.toml | 2 ++ setup.py | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c57f5dd737..4338a5e691 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,6 +49,8 @@ filterwarnings = [ "ignore:When grouping with a length-1 list::dask.dataframe.groupby", # https://github.com/dask/dask/issues/10572 "ignore:\\s*Pyarrow will become a required dependency of pandas:DeprecationWarning", # Will go away by itself in Pandas 3.0 "ignore:Passing a (SingleBlockManager|BlockManager) to (Series|GeoSeries|DataFrame|GeoDataFrame) is deprecated:DeprecationWarning", # https://github.com/holoviz/spatialpandas/issues/137 + # 2024-02 + "ignore:The current Dask DataFrame implementation is deprecated:DeprecationWarning", # https://github.com/dask/dask/issues/10917 ] [tool.coverage] diff --git a/setup.py b/setup.py index 108ad5d51e..10fd2ea55d 100644 --- a/setup.py +++ b/setup.py @@ -76,7 +76,7 @@ extras_require['ui'] = ['playwright', 'pytest-playwright'] # Notebook dependencies -extras_require["notebook"] = ["ipython >=5.4.0", "notebook >=7.0"] +extras_require["notebook"] = ["ipython >=5.4.0", "notebook"] # IPython Notebook + pandas + matplotlib + bokeh extras_require["recommended"] = extras_require["notebook"] + [ @@ -102,6 +102,7 @@ "pyarrow", "pooch", "datashader >=0.11.1", + "notebook >=7.0", ] From bde86c36ae9db140471dfd98d13bd51856cc92c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Mon, 12 Feb 2024 11:52:57 +0100 Subject: [PATCH 44/66] Fix link selection for empty Layout (#6110) --- holoviews/plotting/plot.py | 2 +- holoviews/tests/test_selection.py | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/holoviews/plotting/plot.py b/holoviews/plotting/plot.py index c3ab171864..d8b4c94d5b 100644 --- a/holoviews/plotting/plot.py +++ b/holoviews/plotting/plot.py @@ -859,7 +859,7 @@ def _compute_group_range(cls, group, elements, ranges, framewise, # Filter out ranges of updated elements and append new ranges merged = {} for g, drange in dranges['values'].items(): - filtered = [r for i, r in zip(ids, values[g]) if i not in prev_ids] + filtered = [r for i, r in zip(ids, values.get(g, [])) if i not in prev_ids] filtered += drange merged[g] = filtered prev_ranges[d] = cls._merge_group_ranges(merged) diff --git a/holoviews/tests/test_selection.py b/holoviews/tests/test_selection.py index 1cdc3fc7ba..570491b092 100644 --- a/holoviews/tests/test_selection.py +++ b/holoviews/tests/test_selection.py @@ -1,6 +1,7 @@ from unittest import skip, skipIf import pandas as pd +import panel as pn import holoviews as hv from holoviews.core.options import Cycle, Store @@ -757,3 +758,19 @@ def test_overlay_points_errorbars(self): @skip("Bokeh ErrorBars selection not yet supported") def test_overlay_points_errorbars_dynamic(self): pass + + def test_empty_layout(self): + # Test for https://github.com/holoviz/holoviews/issues/6106 + df = pd.DataFrame({"x": [1, 2], "y": [1, 2], "cat": ["A", "B"]}) + + checkboxes = pn.widgets.CheckBoxGroup(options=['A', 'B']) + + def func(check): + return hv.Scatter(df[df['cat'].isin(check)]) + + ls = hv.link_selections.instance() + a = ls(hv.DynamicMap(pn.bind(func, checkboxes))) + b = ls(hv.DynamicMap(pn.bind(func, checkboxes))) + + hv.renderer('bokeh').get_plot(a + b) + checkboxes.value = ['A'] From c0b08061e153e1ad8bc50fad32d7fcaa0a5edc28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Mon, 12 Feb 2024 12:55:29 +0100 Subject: [PATCH 45/66] Changelog 1.18.3 (#6111) --- CHANGELOG.md | 15 ++++++++++++++- doc/releases.rst | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1b300e42f..e1ce1bd4ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,21 @@ +# Version 1.18.3 + +**February 12, 2024** + +This micro release includes bug fixes. + +Bug fixes: + +- Fix BoundsX and BoundsY regression ([#6099](https://github.com/holoviz/holoviews/pull/6099)) +- Fix rasterize regression ([#6102](https://github.com/holoviz/holoviews/pull/6102)) +- Fix link selection for empty Layout ([#6110](https://github.com/holoviz/holoviews/pull/6110)) +- Don't pin notebook in conda recipe for pyviz channel ([#6108](https://github.com/holoviz/holoviews/pull/6108)) + # Version 1.18.2 **February 5, 2024** -This minor release includes a number of bug fixes and documentation updates, as well as compatibility updates for xarray 2023.12 and Pandas 2.2. +This micro release includes a number of bug fixes and documentation updates, as well as compatibility updates for xarray 2023.12 and Pandas 2.2. Many thanks to the new contributors @junietoc, @JulianGiles, and @magic-lantern, as well as the returning contributors @ianthomas23, @maximlt, @TheoMathurin, @philippjfr, @ahuang11, and @Hoxbro. Enhancements: diff --git a/doc/releases.rst b/doc/releases.rst index 15b9bf422a..da0a174802 100644 --- a/doc/releases.rst +++ b/doc/releases.rst @@ -4,6 +4,25 @@ Releases Version 1.18 ~~~~~~~~~~~~ +Version 1.18.3 +************** + +**February 12, 2024** + +This micro release includes bug fixes. + +Bug fixes: + +- Fix BoundsX and BoundsY regression + (`#6099 `__) +- Fix rasterize regression + (`#6102 `__) +- Fix link selection for empty Layout + (`#6110 `__) +- Don’t pin notebook in conda recipe for pyviz channel + (`#6108 `__) + + Version 1.18.2 ************** From c3c211e0101318d676820c404cf85a04ba42554d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Mon, 12 Feb 2024 15:23:16 +0100 Subject: [PATCH 46/66] Fix changelog for 1.18.2 release (#6114) --- CHANGELOG.md | 24 ++++++++++++------------ doc/releases.rst | 32 ++++++++++++++++---------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1ce1bd4ca..e42d6f75da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ Enhancements: - Update contour line calculations to use ContourPy's `LineType.ChunkCombinedNan` ([#5985](https://github.com/holoviz/holoviews/pull/5985)) - Use sys.executable for `check_output` ([#5983](https://github.com/holoviz/holoviews/pull/5983)) -- Updates to `show_versions` ([(#6072)](https://github.com/holoviz/holoviews/pull/6072), [(#6081)](https://github.com/holoviz/holoviews/pull/6081)) +- Updates to `show_versions` ([#6072](https://github.com/holoviz/holoviews/pull/6072), [#6081](https://github.com/holoviz/holoviews/pull/6081)) Bug fixes: @@ -32,26 +32,26 @@ Bug fixes: - Support partial bound function ([#6009](https://github.com/holoviz/holoviews/pull/6009)) - Add `norm` in `init_artists` in holoviews/plotting/mpl/raster.py ([#6029](https://github.com/holoviz/holoviews/pull/6029)) - Fix linking elements that are transformed by a Compositor ([#6003](https://github.com/holoviz/holoviews/pull/6003)) -- Add datetime hover information for selector ([#6023](https://github.com/holoviz/holoviews/pull/6023), [(#6039)](https://github.com/holoviz/holoviews/pull/6039)) -- Only evaluate `rx` if it is an Reactive Expression ([(#6014)](https://github.com/holoviz/holoviews/pull/6014)) -- Ensure partial methods can be used as dmap callables ([(#6063)](https://github.com/holoviz/holoviews/pull/6063)) -- Del frame after stack level is found in `deprecated` ([(#6085)](https://github.com/holoviz/holoviews/pull/6085)) +- Add datetime hover information for selector ([#6023](https://github.com/holoviz/holoviews/pull/6023), [#6039](https://github.com/holoviz/holoviews/pull/6039)) +- Only evaluate `rx` if it is a Reactive Expression ([#6014](https://github.com/holoviz/holoviews/pull/6014)) +- Ensure partial methods can be used as dmap callables ([#6063](https://github.com/holoviz/holoviews/pull/6063)) +- Del frame after stack level is found in `deprecated` ([#6085](https://github.com/holoviz/holoviews/pull/6085)) Compatibility: - Compatibility updates with xarray 2023.12 ([#6026](https://github.com/holoviz/holoviews/pull/6026)) - Add extra check to detect if we are in jupyterlite ([#6007](https://github.com/holoviz/holoviews/pull/6007)) -- Compatibility updates with Pandas 2.2 ([(#6074)](https://github.com/holoviz/holoviews/pull/6074), [(#6078)](https://github.com/holoviz/holoviews/pull/6078)) -- Add Comm `on_open` handler to initialize the server comm ([(#6076)](https://github.com/holoviz/holoviews/pull/6076)) +- Compatibility updates with Pandas 2.2 ([#6074](https://github.com/holoviz/holoviews/pull/6074), [#6078](https://github.com/holoviz/holoviews/pull/6078)) +- Add Comm `on_open` handler to initialize the server comm ([#6076](https://github.com/holoviz/holoviews/pull/6076)) Documentation: - Fix docs ([#5996](https://github.com/holoviz/holoviews/pull/5996)) - Fix Param usage in the Plot and Renderers guide ([#6001](https://github.com/holoviz/holoviews/pull/6001)) - Fixing URLs to bokeh project ([#6005](https://github.com/holoviz/holoviews/pull/6005)) -- Fix to broken urls in example gallery pages ([(#6038)](https://github.com/holoviz/holoviews/pull/6038)) -- Replace Google Analytics with GoatCounter ([(#6048)](https://github.com/holoviz/holoviews/pull/6048)) -- Add downloads badges ([(#6088)](https://github.com/holoviz/holoviews/pull/6088)) +- Fix to broken urls in example gallery pages ([#6038](https://github.com/holoviz/holoviews/pull/6038)) +- Replace Google Analytics with GoatCounter ([#6048](https://github.com/holoviz/holoviews/pull/6048)) +- Add downloads badges ([#6088](https://github.com/holoviz/holoviews/pull/6088)) Maintenance: @@ -63,8 +63,8 @@ Maintenance: - Part 1, modernize test suite ([#5954](https://github.com/holoviz/holoviews/pull/5954)) - Enforce labels ([#5996](https://github.com/holoviz/holoviews/pull/5997)) - Add lower pin to scipy ([#6032](https://github.com/holoviz/holoviews/pull/6032)) -- Skip Deploying_Bokeh_Apps.ipynb on Windows ([(#6070)](https://github.com/holoviz/holoviews/pull/6070)) -- Fix failing Windows tests ([(#6087)](https://github.com/holoviz/holoviews/pull/6087)) +- Skip Deploying_Bokeh_Apps.ipynb on Windows ([#6070](https://github.com/holoviz/holoviews/pull/6070)) +- Fix failing Windows tests ([#6087](https://github.com/holoviz/holoviews/pull/6087)) # Version 1.18.1 diff --git a/doc/releases.rst b/doc/releases.rst index da0a174802..216b89a563 100644 --- a/doc/releases.rst +++ b/doc/releases.rst @@ -28,7 +28,7 @@ Version 1.18.2 **February 5, 2024** -This minor release includes a number of bug fixes and documentation +This micro release includes a number of bug fixes and documentation updates, as well as compatibility updates for xarray 2023.12 and Pandas 2.2. Many thanks to the new contributors @junietoc, @JulianGiles, and @magic-lantern, as well as the returning contributors @ianthomas23, @@ -42,8 +42,8 @@ Enhancements: - Use sys.executable for ``check_output`` (`#5983 `__) - Updates to ``show_versions`` - (`(#6072) `__, - `(#6081) `__) + (`#6072 `__, + `#6081 `__) Bug fixes: @@ -62,13 +62,13 @@ Bug fixes: (`#6003 `__) - Add datetime hover information for selector (`#6023 `__, - `(#6039) `__) -- Only evaluate ``rx`` if it is an Reactive Expression - (`(#6014) `__) + `#6039 `__) +- Only evaluate ``rx`` if it is a Reactive Expression + (`#6014 `__) - Ensure partial methods can be used as dmap callables - (`(#6063) `__) + (`#6063 `__) - Del frame after stack level is found in ``deprecated`` - (`(#6085) `__) + (`#6085 `__) Compatibility: @@ -77,10 +77,10 @@ Compatibility: - Add extra check to detect if we are in jupyterlite (`#6007 `__) - Compatibility updates with Pandas 2.2 - (`(#6074) `__, - `(#6078) `__) + (`#6074 `__, + `#6078 `__) - Add Comm ``on_open`` handler to initialize the server comm - (`(#6076) `__) + (`#6076 `__) Documentation: @@ -90,11 +90,11 @@ Documentation: - Fixing URLs to bokeh project (`#6005 `__) - Fix to broken urls in example gallery pages - (`(#6038) `__) + (`#6038 `__) - Replace Google Analytics with GoatCounter - (`(#6048) `__) + (`#6048 `__) - Add downloads badges - (`(#6088) `__) + (`#6088 `__) Maintenance: @@ -115,9 +115,9 @@ Maintenance: - Add lower pin to scipy (`#6032 `__) - Skip Deploying_Bokeh_Apps.ipynb on Windows - (`(#6070) `__) + (`#6070 `__) - Fix failing Windows tests - (`(#6087) `__) + (`#6087 `__) Version 1.18.1 From a66eb55f29218241088e952196d7eba31603ed0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Fri, 23 Feb 2024 15:40:38 +0100 Subject: [PATCH 47/66] Don't show figures toolbar on GridSpace (#6127) --- holoviews/plotting/bokeh/plot.py | 3 +- holoviews/plotting/bokeh/util.py | 4 +- holoviews/tests/conftest.py | 38 +++++++++++----- holoviews/tests/ui/__init__.py | 8 ++++ holoviews/tests/ui/bokeh/__init__.py | 0 holoviews/tests/ui/bokeh/test_callback.py | 55 +++++++---------------- holoviews/tests/ui/bokeh/test_layout.py | 24 ++++++++++ 7 files changed, 77 insertions(+), 55 deletions(-) create mode 100644 holoviews/tests/ui/__init__.py create mode 100644 holoviews/tests/ui/bokeh/__init__.py create mode 100644 holoviews/tests/ui/bokeh/test_layout.py diff --git a/holoviews/plotting/bokeh/plot.py b/holoviews/plotting/bokeh/plot.py index 37771afb1b..6a97643d63 100644 --- a/holoviews/plotting/bokeh/plot.py +++ b/holoviews/plotting/bokeh/plot.py @@ -614,8 +614,7 @@ def initialize_plot(self, ranges=None, plots=None): sync_legends(plot) plot = self._make_axes(plot) if hasattr(plot, "toolbar") and self.merge_tools: - plot.toolbar = merge_tools(plots) - + plot.toolbar = merge_tools(plots, hide_toolbar=True) title = self._get_title_div(self.keys[-1]) if title: plot = Column(title, plot) diff --git a/holoviews/plotting/bokeh/util.py b/holoviews/plotting/bokeh/util.py index 490fbf9035..542957d75d 100644 --- a/holoviews/plotting/bokeh/util.py +++ b/holoviews/plotting/bokeh/util.py @@ -384,7 +384,7 @@ def compute_layout_properties( return aspect_info, dimension_info -def merge_tools(plot_grid, disambiguation_properties=None): +def merge_tools(plot_grid, *, disambiguation_properties=None, hide_toolbar=False): """ Merges tools defined on a grid of plots into a single toolbar. All tools of the same type are merged unless they define one @@ -397,6 +397,8 @@ def merge_tools(plot_grid, disambiguation_properties=None): if isinstance(item, LayoutDOM): for p in item.select(dict(type=Plot)): tools.extend(p.toolbar.tools) + if hide_toolbar and hasattr(item, 'toolbar_location'): + item.toolbar_location = None if isinstance(item, GridPlot): item.toolbar_location = None diff --git a/holoviews/tests/conftest.py b/holoviews/tests/conftest.py index f4d9533400..b6b02d9296 100644 --- a/holoviews/tests/conftest.py +++ b/holoviews/tests/conftest.py @@ -2,14 +2,18 @@ import sys from collections.abc import Callable +import panel as pn import pytest -from panel.tests.conftest import ( # noqa +from panel.tests.conftest import ( # noqa: F401 optional_markers, port, pytest_addoption, pytest_configure, server_cleanup, ) +from panel.tests.util import serve_and_wait + +import holoviews as hv def pytest_collection_modifyitems(config, items): @@ -32,13 +36,15 @@ def pytest_collection_modifyitems(config, items): with contextlib.suppress(ImportError): import matplotlib as mpl - mpl.use('agg') + + mpl.use("agg") with contextlib.suppress(Exception): # From Dask 2023.7,1 they now automatic convert strings # https://docs.dask.org/en/stable/changelog.html#v2023-7-1 import dask + dask.config.set({"dataframe.convert-string": False}) @@ -49,40 +55,38 @@ def ibis_sqlite_backend(): except ImportError: yield None else: - ibis.set_backend('sqlite') + ibis.set_backend("sqlite") yield ibis.set_backend(None) @pytest.fixture def bokeh_backend(): - import holoviews as hv - hv.renderer('bokeh') + hv.renderer("bokeh") prev_backend = hv.Store.current_backend - hv.Store.current_backend = 'bokeh' + hv.Store.current_backend = "bokeh" yield hv.Store.current_backend = prev_backend @pytest.fixture def mpl_backend(): - import holoviews as hv - hv.renderer('matplotlib') + hv.renderer("matplotlib") prev_backend = hv.Store.current_backend - hv.Store.current_backend = 'matplotlib' + hv.Store.current_backend = "matplotlib" yield hv.Store.current_backend = prev_backend @pytest.fixture def plotly_backend(): - import holoviews as hv - hv.renderer('plotly') + hv.renderer("plotly") prev_backend = hv.Store.current_backend - hv.Store.current_backend = 'plotly' + hv.Store.current_backend = "plotly" yield hv.Store.current_backend = prev_backend + @pytest.fixture def unimport(monkeypatch: pytest.MonkeyPatch) -> Callable[[str], None]: """ @@ -98,3 +102,13 @@ def unimport_module(modname: str) -> None: monkeypatch.setattr(sys, "path", []) return unimport_module + + +@pytest.fixture +def serve_hv(page, port): # noqa: F811 + def serve_and_return_page(hv_obj): + serve_and_wait(pn.pane.HoloViews(hv_obj), port=port) + page.goto(f"http://localhost:{port}") + return page + + return serve_and_return_page diff --git a/holoviews/tests/ui/__init__.py b/holoviews/tests/ui/__init__.py new file mode 100644 index 0000000000..36c5bd8d9f --- /dev/null +++ b/holoviews/tests/ui/__init__.py @@ -0,0 +1,8 @@ +try: + from playwright.sync_api import expect +except ImportError: + expect = None + +from panel.tests.util import wait_until + +__all__ = ("expect", "wait_until") diff --git a/holoviews/tests/ui/bokeh/__init__.py b/holoviews/tests/ui/bokeh/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/holoviews/tests/ui/bokeh/test_callback.py b/holoviews/tests/ui/bokeh/test_callback.py index 09e0dbfd5b..ffd3d3bc00 100644 --- a/holoviews/tests/ui/bokeh/test_callback.py +++ b/holoviews/tests/ui/bokeh/test_callback.py @@ -1,23 +1,17 @@ import time import numpy as np -import pytest - -try: - from playwright.sync_api import expect -except ImportError: - pytestmark = pytest.mark.skip('playwright not available') - -pytestmark = pytest.mark.ui - import panel as pn -from panel.pane.holoviews import HoloViews -from panel.tests.util import serve_and_wait, wait_until +import pytest import holoviews as hv from holoviews import Curve, DynamicMap, Scatter from holoviews.streams import BoundsX, BoundsXY, BoundsY, Lasso, RangeXY +from .. import expect, wait_until + +pytestmark = pytest.mark.ui + @pytest.mark.usefixtures("bokeh_backend") @pytest.mark.parametrize( @@ -28,18 +22,14 @@ (BoundsY, slice(1, None, 2), "boundsy"), ], ) -def test_box_select(page, port, BoundsTool, bound_slice, bound_attr): +def test_box_select(serve_hv, BoundsTool, bound_slice, bound_attr): hv_scatter = Scatter([1, 2, 3]).opts( tools=['box_select'], active_tools=['box_select'] ) bounds = BoundsTool(source=hv_scatter) - pn_scatter = HoloViews(hv_scatter) - - serve_and_wait(pn_scatter, port=port) - page.goto(f"http://localhost:{port}") - + page = serve_hv(hv_scatter) hv_plot = page.locator('.bk-events') expect(hv_plot).to_have_count(1) @@ -57,18 +47,14 @@ def test_box_select(page, port, BoundsTool, bound_slice, bound_attr): @pytest.mark.usefixtures("bokeh_backend") -def test_lasso_select(page, port): +def test_lasso_select(serve_hv): hv_scatter = Scatter([1, 2, 3]).opts( tools=['lasso_select'], active_tools=['lasso_select'] ) lasso = Lasso(source=hv_scatter) - pn_scatter = HoloViews(hv_scatter) - - serve_and_wait(pn_scatter, port=port) - page.goto(f"http://localhost:{port}") - + page = serve_hv(hv_scatter) hv_plot = page.locator('.bk-events') expect(hv_plot).to_have_count(1) @@ -100,16 +86,12 @@ def test_lasso_select(page, port): np.testing.assert_almost_equal(lasso.geometry, expected_array) @pytest.mark.usefixtures("bokeh_backend") -def test_rangexy(page, port): +def test_rangexy(serve_hv): hv_scatter = Scatter([1, 2, 3]).opts(active_tools=['box_zoom']) rangexy = RangeXY(source=hv_scatter) - pn_scatter = HoloViews(hv_scatter) - - serve_and_wait(pn_scatter, port=port) - page.goto(f"http://localhost:{port}") - + page = serve_hv(hv_scatter) hv_plot = page.locator('.bk-events') expect(hv_plot).to_have_count(1) @@ -127,7 +109,7 @@ def test_rangexy(page, port): wait_until(lambda: rangexy.x_range == expected_xrange and rangexy.y_range == expected_yrange, page) @pytest.mark.usefixtures("bokeh_backend") -def test_multi_axis_rangexy(page, port): +def test_multi_axis_rangexy(serve_hv): c1 = Curve(np.arange(100).cumsum(), vdims='y') c2 = Curve(-np.arange(100).cumsum(), vdims='y2') s1 = RangeXY(source=c1) @@ -135,11 +117,7 @@ def test_multi_axis_rangexy(page, port): overlay = (c1 * c2).opts(multi_y=True) - pn_scatter = HoloViews(overlay) - - serve_and_wait(pn_scatter, port=port) - page.goto(f"http://localhost:{port}") - + page = serve_hv(overlay) hv_plot = page.locator('.bk-events') expect(hv_plot).to_have_count(1) @@ -163,7 +141,7 @@ def test_multi_axis_rangexy(page, port): @pytest.mark.usefixtures("bokeh_backend") -def test_bind_trigger(page, port): +def test_bind_trigger(serve_hv): # Regression test for https://github.com/holoviz/holoviews/issues/6013 BOUND_COUNT, RANGE_COUNT = [0], [0] @@ -179,11 +157,8 @@ def range_function(x_range, y_range): range_dmap = DynamicMap(range_function, streams=[hv.streams.RangeXY()]) bind_dmap = DynamicMap(pn.bind(bound_function)) - widget = pn.pane.HoloViews(bind_dmap * range_dmap) - - serve_and_wait(widget, port=port) - page.goto(f"http://localhost:{port}") + page = serve_hv(bind_dmap * range_dmap) hv_plot = page.locator('.bk-events') expect(hv_plot).to_have_count(1) diff --git a/holoviews/tests/ui/bokeh/test_layout.py b/holoviews/tests/ui/bokeh/test_layout.py new file mode 100644 index 0000000000..114ea37fa6 --- /dev/null +++ b/holoviews/tests/ui/bokeh/test_layout.py @@ -0,0 +1,24 @@ +import numpy as np +import pytest + +import holoviews as hv + +from .. import expect + +pytestmark = pytest.mark.ui + + +@pytest.mark.usefixtures("bokeh_backend") +def test_gridspace_toolbar(serve_hv): + def sine_curve(phase, freq): + xvals = [0.1 * i for i in range(100)] + return hv.Curve((xvals, [np.sin(phase + freq * x) for x in xvals])) + + phases = [0, np.pi / 2, np.pi, 3 * np.pi / 2] + frequencies = [0.5, 0.75, 1.0, 1.25] + curve_dict_2D = {(p, f): sine_curve(p, f) for p in phases for f in frequencies} + gridspace = hv.GridSpace(curve_dict_2D, kdims=["phase", "frequency"]) + + page = serve_hv(gridspace) + bokeh_logo = page.locator(".bk-logo") + expect(bokeh_logo).to_have_count(1) From 9e5f904f39ecd0ea025dd93147a7498ac1c32f32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Tue, 27 Feb 2024 19:08:31 +0100 Subject: [PATCH 48/66] Update tests for Bokeh 3.4 (#6130) --- .github/workflows/test.yaml | 13 ++-- holoviews/plotting/bokeh/util.py | 2 +- .../plotting/bokeh/test_annotationplot.py | 6 +- holoviews/tests/ui/bokeh/test_callback.py | 60 ++++++++++++------- scripts/check_latest_packages.py | 7 ++- setup.py | 2 +- 6 files changed, 59 insertions(+), 31 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index ad67149396..7ebd070827 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -131,12 +131,17 @@ jobs: with: name: unit_test_suite python-version: ${{ matrix.python-version }} - channel-priority: strict - channels: pyviz/label/dev,conda-forge,nodefaults + channel-priority: flexible + channels: pyviz/label/dev,bokeh/label/dev,conda-forge,nodefaults envs: "-o flakes -o tests -o examples_tests -o tests_ci" cache: ${{ github.event.inputs.cache || github.event.inputs.cache == '' }} conda-update: true id: install + # - name: Check packages latest version + # if: needs.setup.outputs.code_change == 'true' + # run: | + # conda activate test-environment + # python scripts/check_latest_packages.py panel bokeh - name: bokeh sampledata if: needs.setup.outputs.code_change == 'true' run: | @@ -181,7 +186,7 @@ jobs: with: name: ui_test_suite python-version: ${{ matrix.python-version }} - channels: pyviz/label/dev,bokeh,conda-forge,nodefaults + channels: pyviz/label/dev,bokeh/label/dev,conda-forge,nodefaults envs: "-o recommended -o tests -o build -o tests_ci" cache: ${{ github.event.inputs.cache || github.event.inputs.cache == '' }} playwright: true @@ -249,7 +254,7 @@ jobs: if: needs.setup.outputs.code_change == 'true' run: | # conda activate test-environment - python scripts/check_latest_packages.py + python scripts/check_latest_packages.py numpy pandas - name: doit test_unit if: needs.setup.outputs.code_change == 'true' run: | diff --git a/holoviews/plotting/bokeh/util.py b/holoviews/plotting/bokeh/util.py index 542957d75d..12c369d45a 100644 --- a/holoviews/plotting/bokeh/util.py +++ b/holoviews/plotting/bokeh/util.py @@ -60,7 +60,7 @@ from ...util.warnings import warn from ..util import dim_axis_label -bokeh_version = Version(bokeh.__version__) +bokeh_version = Version(Version(bokeh.__version__).base_version) bokeh32 = bokeh_version >= Version("3.2") bokeh33 = bokeh_version >= Version("3.3") bokeh34 = bokeh_version >= Version("3.4") diff --git a/holoviews/tests/plotting/bokeh/test_annotationplot.py b/holoviews/tests/plotting/bokeh/test_annotationplot.py index ab955a8131..4a60a3e823 100644 --- a/holoviews/tests/plotting/bokeh/test_annotationplot.py +++ b/holoviews/tests/plotting/bokeh/test_annotationplot.py @@ -17,7 +17,7 @@ VSpan, VSpans, ) -from holoviews.plotting.bokeh.util import bokeh32, bokeh33 +from holoviews.plotting.bokeh.util import bokeh32, bokeh33, bokeh34 from .test_plot import TestBokehPlot, bokeh_renderer @@ -29,7 +29,9 @@ VStrip as BkVStrip, ) -if bokeh33: +if bokeh34: + from bokeh.models import Node +elif bokeh33: from bokeh.models.coordinates import Node diff --git a/holoviews/tests/ui/bokeh/test_callback.py b/holoviews/tests/ui/bokeh/test_callback.py index ffd3d3bc00..f08e056744 100644 --- a/holoviews/tests/ui/bokeh/test_callback.py +++ b/holoviews/tests/ui/bokeh/test_callback.py @@ -1,11 +1,10 @@ -import time - import numpy as np import panel as pn import pytest import holoviews as hv from holoviews import Curve, DynamicMap, Scatter +from holoviews.plotting.bokeh.util import bokeh34 from holoviews.streams import BoundsX, BoundsXY, BoundsY, Lasso, RangeXY from .. import expect, wait_until @@ -68,22 +67,41 @@ def test_lasso_select(serve_hv): page.mouse.move(bbox['x']+50, bbox['y']+150, steps=5) page.mouse.up() - time.sleep(1) - - expected_array = np.array([ - [ 3.28440367e-01, 2.31836735e+00], - [ 5.48623853e-01, 2.12244898e+00], - [ 6.58715596e-01, 2.02448980e+00], - [ 7.68807339e-01, 1.92653061e+00], - [ 8.78899083e-01, 1.82857143e+00], - [ 6.58715596e-01, 1.82857143e+00], - [ 4.38532110e-01, 1.82857143e+00], - [ 2.18348624e-01, 1.82857143e+00], - [-1.83486239e-03, 1.82857143e+00], - [-2.00000000e-01, 1.82857143e+00], - [-2.00000000e-01, 1.82857143e+00] - ]) - np.testing.assert_almost_equal(lasso.geometry, expected_array) + if bokeh34: + expected_array = np.array([ + [3.28440367e-01, 2.31836735e00], + [4.38532110e-01, 2.22040816e00], + [5.48623853e-01, 2.12244898e00], + [6.58715596e-01, 2.02448980e00], + [7.68807339e-01, 1.92653061e00], + [8.78899083e-01, 1.82857143e00], + [6.58715596e-01, 1.82857143e00], + [4.38532110e-01, 1.82857143e00], + [2.18348624e-01, 1.82857143e00], + [-1.83486239e-03, 1.82857143e00], + [-2.00000000e-01, 1.82857143e00], + ]) + else: + expected_array = np.array([ + [ 3.28440367e-01, 2.31836735e+00], + [ 5.48623853e-01, 2.12244898e+00], + [ 6.58715596e-01, 2.02448980e+00], + [ 7.68807339e-01, 1.92653061e+00], + [ 8.78899083e-01, 1.82857143e+00], + [ 6.58715596e-01, 1.82857143e+00], + [ 4.38532110e-01, 1.82857143e+00], + [ 2.18348624e-01, 1.82857143e+00], + [-1.83486239e-03, 1.82857143e+00], + [-2.00000000e-01, 1.82857143e+00], + [-2.00000000e-01, 1.82857143e+00] + ]) + + def compare_array(): + if lasso.geometry is None: + return False + np.testing.assert_almost_equal(lasso.geometry, expected_array) + + wait_until(compare_array, page) @pytest.mark.usefixtures("bokeh_backend") def test_rangexy(serve_hv): @@ -134,9 +152,9 @@ def test_multi_axis_rangexy(serve_hv): expected_yrange1 = (717.2448979591848, 6657.244897959185) expected_yrange2 = (-4232.7551020408155, 1707.2448979591848) wait_until(lambda: ( - s1.x_range == expected_xrange and - s1.y_range == expected_yrange1 and - s2.y_range == expected_yrange2 + np.testing.assert_almost_equal(s1.x_range, expected_xrange) and + np.testing.assert_almost_equal(s1.y_range, expected_yrange1) and + np.testing.assert_almost_equal(s2.y_range, expected_yrange2) ), page) diff --git a/scripts/check_latest_packages.py b/scripts/check_latest_packages.py index 5e4f378425..7fcf658f8c 100644 --- a/scripts/check_latest_packages.py +++ b/scripts/check_latest_packages.py @@ -5,10 +5,13 @@ import requests from packaging.version import Version +if sys.stdout.isatty(): + GREEN, RED, RESET = "\033[92m", "\033[91m", "\033[0m" +else: + GREEN = RED = RESET = "" def main(*packages): allowed_date = date.today() - timedelta(days=5) - GREEN, RED, RESET = "\033[92m", "\033[91m", "\033[0m" all_latest = True for package in sorted(packages): url = f"https://pypi.org/pypi/{package}/json" @@ -38,4 +41,4 @@ def main(*packages): if __name__ == "__main__": - main("numpy", "pandas") + main(*sys.argv[1:]) diff --git a/setup.py b/setup.py index 10fd2ea55d..d25e1c47ef 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ install_requires = [ "param >=1.12.0,<3.0", "numpy >=1.0", - "pyviz_comms >=0.7.4", + "pyviz_comms >=2.1", "panel >=1.0", "colorcet", "packaging", From 4e01bee01722f33f3f134a21eb74d87539de33c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Mon, 4 Mar 2024 12:46:27 +0100 Subject: [PATCH 49/66] General maintenance (#6144) --- .github/workflows/docs.yaml | 4 ++-- .github/workflows/test.yaml | 35 +++++++++++++++++++------------- .pre-commit-config.yaml | 2 +- scripts/check_latest_packages.py | 9 +++++--- scripts/download_data.sh | 17 ++++++++++++++++ setup.py | 2 +- 6 files changed, 48 insertions(+), 21 deletions(-) create mode 100755 scripts/download_data.sh diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 1ccee6aed1..03779a1689 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -52,10 +52,10 @@ jobs: - name: Set output id: vars run: echo "tag=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT - - name: bokeh sampledata + - name: Download data run: | conda activate test-environment - bokeh sampledata + bash scripts/download_data.sh - name: generate rst run: | conda activate test-environment diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 7ebd070827..cbf2bd1ade 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -91,10 +91,7 @@ jobs: run: | MATRIX=$(jq -nsc '{ "os": ["ubuntu-latest", "macos-latest", "windows-latest"], - "python-version": ["3.9", "3.11"], - "include": [ - {"os": "ubuntu-latest", "python-version": "3.10"} - ] + "python-version": ["3.9", "3.11"] }') echo "MATRIX=$MATRIX" >> $GITHUB_ENV - name: Set test matrix with 'full' option @@ -137,16 +134,21 @@ jobs: cache: ${{ github.event.inputs.cache || github.event.inputs.cache == '' }} conda-update: true id: install - # - name: Check packages latest version - # if: needs.setup.outputs.code_change == 'true' - # run: | - # conda activate test-environment - # python scripts/check_latest_packages.py panel bokeh - - name: bokeh sampledata + - name: suppress warning + if: needs.setup.outputs.code_change == 'true' + run: | + conda activate test-environment + touch ${CONDA_PREFIX}/etc/OpenCL/vendors/mute || true # https://github.com/conda-forge/ocl-icd-feedstock/issues/29 + - name: Check packages latest version if: needs.setup.outputs.code_change == 'true' run: | conda activate test-environment - bokeh sampledata + python scripts/check_latest_packages.py bokeh # panel + - name: Download data + if: needs.setup.outputs.code_change == 'true' + run: | + conda activate test-environment + bash scripts/download_data.sh - name: doit test_unit if: needs.setup.outputs.code_change == 'true' run: | @@ -191,6 +193,11 @@ jobs: cache: ${{ github.event.inputs.cache || github.event.inputs.cache == '' }} playwright: true id: install + - name: suppress warning + if: needs.setup.outputs.code_change == 'true' + run: | + conda activate test-environment + touch ${CONDA_PREFIX}/etc/OpenCL/vendors/mute || true # https://github.com/conda-forge/ocl-icd-feedstock/issues/29 - name: doit test_ui if: needs.setup.outputs.code_change == 'true' run: | @@ -245,16 +252,16 @@ jobs: if: needs.setup.outputs.code_change == 'true' run: | python -m pip install -ve '.[tests_core, tests_ci]' - - name: bokeh sampledata + - name: Download data if: needs.setup.outputs.code_change == 'true' run: | # conda activate test-environment - bokeh sampledata + bash scripts/download_data.sh - name: Check packages latest version if: needs.setup.outputs.code_change == 'true' run: | # conda activate test-environment - python scripts/check_latest_packages.py numpy pandas + python scripts/check_latest_packages.py numpy pandas bokeh panel - name: doit test_unit if: needs.setup.outputs.code_change == 'true' run: | diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c0da1e2c85..7e752370a6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,7 @@ repos: - id: check-json - id: detect-private-key - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.2.0 + rev: v0.3.0 hooks: - id: ruff files: holoviews/|scripts/ diff --git a/scripts/check_latest_packages.py b/scripts/check_latest_packages.py index 7fcf658f8c..407f24a2a0 100644 --- a/scripts/check_latest_packages.py +++ b/scripts/check_latest_packages.py @@ -1,3 +1,4 @@ +import os import sys from datetime import date, datetime, timedelta from importlib.metadata import version @@ -5,11 +6,12 @@ import requests from packaging.version import Version -if sys.stdout.isatty(): +if sys.stdout.isatty() or os.environ.get("GITHUB_ACTIONS"): GREEN, RED, RESET = "\033[92m", "\033[91m", "\033[0m" else: GREEN = RED = RESET = "" + def main(*packages): allowed_date = date.today() - timedelta(days=5) all_latest = True @@ -19,11 +21,12 @@ def main(*packages): latest = resp["info"]["version"] current = version(package) + # Remove suffix because older Python versions does not support it latest_release_date = datetime.fromisoformat( - resp["releases"][latest][0]["upload_time_iso_8601"] + resp["releases"][latest][0]["upload_time_iso_8601"].removesuffix("Z") ).date() current_release_date = datetime.fromisoformat( - resp["releases"][current][0]["upload_time_iso_8601"] + resp["releases"][current][0]["upload_time_iso_8601"].removesuffix("Z") ).date() version_check = Version(current) >= Version(latest) diff --git a/scripts/download_data.sh b/scripts/download_data.sh new file mode 100755 index 0000000000..16754fee73 --- /dev/null +++ b/scripts/download_data.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -euxo pipefail + +bokeh sampledata + +python -c " +try: + import pooch + import scipy + import xarray as xr +except ImportError: + pass +else: + xr.tutorial.open_dataset('air_temperature') + xr.tutorial.open_dataset('rasm') +" diff --git a/setup.py b/setup.py index d25e1c47ef..b5a810703c 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ # Test requirements extras_require['tests_core'] = [ - 'pytest', + 'pytest <8.1', # https://github.com/computationalmodelling/nbval/issues/202 'pytest-cov', 'pytest-xdist', 'pytest-rerunfailures', From 34157fd592331b777c977fb0e61630f30e864593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Thu, 7 Mar 2024 14:50:00 +0100 Subject: [PATCH 50/66] Update merge_tool (#6141) --- holoviews/plotting/bokeh/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/holoviews/plotting/bokeh/util.py b/holoviews/plotting/bokeh/util.py index 12c369d45a..1bc7427fa2 100644 --- a/holoviews/plotting/bokeh/util.py +++ b/holoviews/plotting/bokeh/util.py @@ -417,7 +417,7 @@ def merge(tool, group): if p not in disambiguation_properties: ignore.add(p) - return Toolbar(tools=group_tools(tools, merge=merge, ignore=ignore) if merge_tools else tools) + return Toolbar(tools=group_tools(tools, merge=merge, ignore=ignore)) if tools else Toolbar() def sync_legends(bokeh_layout): From 1b51771e1c823a0ae81b547056c6af9bb30a6ac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Thu, 7 Mar 2024 19:22:33 +0100 Subject: [PATCH 51/66] General maintenance (#6146) --- .github/workflows/docs.yaml | 2 +- .github/workflows/test.yaml | 18 ++++++++++++++++-- setup.py | 2 +- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 03779a1689..5708d371c8 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -44,7 +44,7 @@ jobs: with: name: Documentation python-version: "3.10" - channel-priority: strict + channel-priority: flexible channels: pyviz/label/dev,conda-forge,nodefaults envs: "-o doc" cache: true diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index cbf2bd1ade..d6e6e61875 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -139,11 +139,18 @@ jobs: run: | conda activate test-environment touch ${CONDA_PREFIX}/etc/OpenCL/vendors/mute || true # https://github.com/conda-forge/ocl-icd-feedstock/issues/29 + - name: Force latest Panel and Bokeh dev releases + if: needs.setup.outputs.code_change == 'true' + run: | + conda activate test-environment + conda uninstall panel bokeh --force --offline -y || true + pip install 'bokeh>=3.4.0rc1' 'panel>=1.4.0b1' + echo "Installing dev releases of Panel and Bokeh" >> $GITHUB_STEP_SUMMARY - name: Check packages latest version if: needs.setup.outputs.code_change == 'true' run: | conda activate test-environment - python scripts/check_latest_packages.py bokeh # panel + python scripts/check_latest_packages.py bokeh panel param datashader - name: Download data if: needs.setup.outputs.code_change == 'true' run: | @@ -198,6 +205,13 @@ jobs: run: | conda activate test-environment touch ${CONDA_PREFIX}/etc/OpenCL/vendors/mute || true # https://github.com/conda-forge/ocl-icd-feedstock/issues/29 + - name: Force latest Panel and Bokeh dev releases + if: needs.setup.outputs.code_change == 'true' + run: | + conda activate test-environment + conda uninstall panel bokeh --force --offline -y || true + pip install 'bokeh>=3.4.0rc1' 'panel>=1.4.0b1' + echo "Installing dev releases of Panel and Bokeh" >> $GITHUB_STEP_SUMMARY - name: doit test_ui if: needs.setup.outputs.code_change == 'true' run: | @@ -261,7 +275,7 @@ jobs: if: needs.setup.outputs.code_change == 'true' run: | # conda activate test-environment - python scripts/check_latest_packages.py numpy pandas bokeh panel + python scripts/check_latest_packages.py numpy pandas bokeh panel param - name: doit test_unit if: needs.setup.outputs.code_change == 'true' run: | diff --git a/setup.py b/setup.py index b5a810703c..d25e1c47ef 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ # Test requirements extras_require['tests_core'] = [ - 'pytest <8.1', # https://github.com/computationalmodelling/nbval/issues/202 + 'pytest', 'pytest-cov', 'pytest-xdist', 'pytest-rerunfailures', From 075ae6ef9ea09d3313ce5264b08be8b7a1461565 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Fri, 8 Mar 2024 09:29:02 +0100 Subject: [PATCH 52/66] Simplify dev pull (#6147) --- .github/workflows/test.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index d6e6e61875..151127c47a 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -144,7 +144,7 @@ jobs: run: | conda activate test-environment conda uninstall panel bokeh --force --offline -y || true - pip install 'bokeh>=3.4.0rc1' 'panel>=1.4.0b1' + pip install bokeh panel --pre echo "Installing dev releases of Panel and Bokeh" >> $GITHUB_STEP_SUMMARY - name: Check packages latest version if: needs.setup.outputs.code_change == 'true' @@ -210,7 +210,7 @@ jobs: run: | conda activate test-environment conda uninstall panel bokeh --force --offline -y || true - pip install 'bokeh>=3.4.0rc1' 'panel>=1.4.0b1' + pip install bokeh panel --pre echo "Installing dev releases of Panel and Bokeh" >> $GITHUB_STEP_SUMMARY - name: doit test_ui if: needs.setup.outputs.code_change == 'true' From 3b4a21416b2919d6d30e58a540c8f062d6718a34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Thu, 14 Mar 2024 10:39:27 +0100 Subject: [PATCH 53/66] Add dask setting to disable query-planning for now (#6149) --- holoviews/tests/conftest.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/holoviews/tests/conftest.py b/holoviews/tests/conftest.py index b6b02d9296..7d79f2379b 100644 --- a/holoviews/tests/conftest.py +++ b/holoviews/tests/conftest.py @@ -41,11 +41,14 @@ def pytest_collection_modifyitems(config, items): with contextlib.suppress(Exception): - # From Dask 2023.7,1 they now automatic convert strings + # From Dask 2023.7.1 they now automatically convert strings # https://docs.dask.org/en/stable/changelog.html#v2023-7-1 + # From Dask 2024.3.0 they now use `dask_expr` by default + # https://github.com/dask/dask/issues/10995 import dask dask.config.set({"dataframe.convert-string": False}) + dask.config.set({"dataframe.query-planning": False}) @pytest.fixture From baa69b10a452c92ec98623c6d22435b151e991d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Fri, 15 Mar 2024 09:31:27 +0100 Subject: [PATCH 54/66] Bump ruff and remove Bokeh rc workarounds (#6152) --- .github/workflows/test.yaml | 27 ++++++++++----------------- .pre-commit-config.yaml | 2 +- holoviews/core/dimension.py | 10 ++++++---- holoviews/core/io.py | 3 +-- holoviews/element/raster.py | 20 ++++++++++++-------- holoviews/ipython/archive.py | 3 +-- holoviews/operation/datashader.py | 7 ++++--- holoviews/plotting/bokeh/element.py | 12 +++++------- holoviews/plotting/plot.py | 5 +++-- holoviews/plotting/plotly/element.py | 23 +++++++++-------------- holoviews/plotting/util.py | 12 ++++++------ holoviews/streams.py | 7 ++++--- holoviews/tests/utils.py | 6 ++---- holoviews/util/__init__.py | 10 ++++------ scripts/check_latest_packages.py | 2 +- 15 files changed, 69 insertions(+), 80 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 151127c47a..4b2486c528 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -129,7 +129,7 @@ jobs: name: unit_test_suite python-version: ${{ matrix.python-version }} channel-priority: flexible - channels: pyviz/label/dev,bokeh/label/dev,conda-forge,nodefaults + channels: pyviz/label/dev,conda-forge,nodefaults envs: "-o flakes -o tests -o examples_tests -o tests_ci" cache: ${{ github.event.inputs.cache || github.event.inputs.cache == '' }} conda-update: true @@ -138,14 +138,8 @@ jobs: if: needs.setup.outputs.code_change == 'true' run: | conda activate test-environment - touch ${CONDA_PREFIX}/etc/OpenCL/vendors/mute || true # https://github.com/conda-forge/ocl-icd-feedstock/issues/29 - - name: Force latest Panel and Bokeh dev releases - if: needs.setup.outputs.code_change == 'true' - run: | - conda activate test-environment - conda uninstall panel bokeh --force --offline -y || true - pip install bokeh panel --pre - echo "Installing dev releases of Panel and Bokeh" >> $GITHUB_STEP_SUMMARY + # https://github.com/conda-forge/ocl-icd-feedstock/issues/29 + touch ${CONDA_PREFIX}/etc/OpenCL/vendors/mute || true - name: Check packages latest version if: needs.setup.outputs.code_change == 'true' run: | @@ -195,7 +189,7 @@ jobs: with: name: ui_test_suite python-version: ${{ matrix.python-version }} - channels: pyviz/label/dev,bokeh/label/dev,conda-forge,nodefaults + channels: pyviz/label/dev,conda-forge,nodefaults envs: "-o recommended -o tests -o build -o tests_ci" cache: ${{ github.event.inputs.cache || github.event.inputs.cache == '' }} playwright: true @@ -205,13 +199,6 @@ jobs: run: | conda activate test-environment touch ${CONDA_PREFIX}/etc/OpenCL/vendors/mute || true # https://github.com/conda-forge/ocl-icd-feedstock/issues/29 - - name: Force latest Panel and Bokeh dev releases - if: needs.setup.outputs.code_change == 'true' - run: | - conda activate test-environment - conda uninstall panel bokeh --force --offline -y || true - pip install bokeh panel --pre - echo "Installing dev releases of Panel and Bokeh" >> $GITHUB_STEP_SUMMARY - name: doit test_ui if: needs.setup.outputs.code_change == 'true' run: | @@ -266,6 +253,12 @@ jobs: if: needs.setup.outputs.code_change == 'true' run: | python -m pip install -ve '.[tests_core, tests_ci]' + - name: install panel pre + if: needs.setup.outputs.code_change == 'true' + run: | + python -m pip install panel --pre --upgrade + python -m pip install bokeh --upgrade + echo "Installing dev release of Panel" >> $GITHUB_STEP_SUMMARY - name: Download data if: needs.setup.outputs.code_change == 'true' run: | diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7e752370a6..cd84663faf 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,7 @@ repos: - id: check-json - id: detect-private-key - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.3.0 + rev: v0.3.2 hooks: - id: ruff files: holoviews/|scripts/ diff --git a/holoviews/core/dimension.py b/holoviews/core/dimension.py index 6ff601295c..59218185f9 100644 --- a/holoviews/core/dimension.py +++ b/holoviews/core/dimension.py @@ -109,10 +109,12 @@ def process_dimensions(kdims, vdims): elif isinstance(dims, (tuple, str, Dimension, dict)): dims = [dims] elif not isinstance(dims, list): - raise ValueError("{} argument expects a Dimension or list of dimensions, " - "specified as tuples, strings, dictionaries or Dimension " - "instances, not a {} type. Ensure you passed the data as the " - "first argument.".format(group, type(dims).__name__)) + raise ValueError( + f"{group} argument expects a Dimension or list of dimensions, " + "specified as tuples, strings, dictionaries or Dimension " + f"instances, not a {type(dims).__name__} type. " + "Ensure you passed the data as the first argument." + ) dimensions[group] = [asdim(d) for d in dims] return dimensions diff --git a/holoviews/core/io.py b/holoviews/core/io.py index 13ddd9b45e..774238ece4 100644 --- a/holoviews/core/io.py +++ b/holoviews/core/io.py @@ -370,8 +370,7 @@ def save(self_or_cls, obj, filename, key=None, info=None, **kwargs): components = list(obj.data.values()) entries = entries if len(entries) > 1 else [entries[0]+'(L)'] else: - entries = ['{}.{}'.format(group_sanitizer(obj.group, False), - label_sanitizer(obj.label, False))] + entries = [f'{group_sanitizer(obj.group, False)}.{label_sanitizer(obj.label, False)}'] components = [obj] for component, entry in zip(components, entries): diff --git a/holoviews/element/raster.py b/holoviews/element/raster.py index 19cf97e28e..8075bfff3b 100644 --- a/holoviews/element/raster.py +++ b/holoviews/element/raster.py @@ -278,10 +278,12 @@ def __init__(self, data, kdims=None, vdims=None, bounds=None, extents=None, Dataset.__init__(self, data, kdims=kdims, vdims=vdims, extents=extents, **params) if not self.interface.gridded: - raise DataError("{} type expects gridded data, {} is columnar. " - "To display columnar data as gridded use the HeatMap " - "element or aggregate the data (e.g. using rasterize " - "or np.histogram2d).".format(type(self).__name__, self.interface.__name__)) + raise DataError( + f"{type(self).__name__} type expects gridded data, " + f"{self.interface.__name__} is columnar. " + "To display columnar data as gridded use the HeatMap " + "element or aggregate the data (e.g. using np.histogram2d)." + ) dim2, dim1 = self.interface.shape(self, gridded=True)[:2] if bounds is None: @@ -800,10 +802,12 @@ def __init__(self, data, kdims=None, vdims=None, **params): data = ([], [], np.zeros((0, 0))) super().__init__(data, kdims, vdims, **params) if not self.interface.gridded: - raise DataError("{} type expects gridded data, {} is columnar. " - "To display columnar data as gridded use the HeatMap " - "element or aggregate the data (e.g. using " - "np.histogram2d).".format(type(self).__name__, self.interface.__name__)) + raise DataError( + f"{type(self).__name__} type expects gridded data, " + f"{self.interface.__name__} is columnar. " + "To display columnar data as gridded use the HeatMap " + "element or aggregate the data (e.g. using np.histogram2d)." + ) def trimesh(self): """ diff --git a/holoviews/ipython/archive.py b/holoviews/ipython/archive.py index 5eefa4f873..e6acd4d67f 100644 --- a/holoviews/ipython/archive.py +++ b/holoviews/ipython/archive.py @@ -147,8 +147,7 @@ def export(self, timestamp=None): tstamp = time.strftime(self.timestamp_format, self._timestamp) export_name = self._format(self.export_name, {'timestamp':tstamp, 'notebook':self.notebook_name}) - print(('Export name: {!r}\nDirectory {!r}'.format(export_name, - os.path.join(os.path.abspath(self.root)))) + print((f'Export name: {export_name!r}\nDirectory {os.path.join(os.path.abspath(self.root))!r}') + '\n\nIf no output appears, please check holoviews.archive.last_export_status()') display(Javascript(cmd)) diff --git a/holoviews/operation/datashader.py b/holoviews/operation/datashader.py index 08f2688661..d527d689fd 100644 --- a/holoviews/operation/datashader.py +++ b/holoviews/operation/datashader.py @@ -194,9 +194,10 @@ def _get_agg_params(self, element, x, y, agg_fn, bounds): elif column: dims = [d for d in element.dimensions('ranges') if d == column] if not dims: - raise ValueError("Aggregation column '{}' not found on '{}' element. " - "Ensure the aggregator references an existing " - "dimension.".format(column,element)) + raise ValueError( + f"Aggregation column '{column}' not found on '{element}' element. " + "Ensure the aggregator references an existing dimension." + ) if isinstance(agg_fn, (ds.count, ds.count_cat)): if vdim_prefix: vdim_name = f'{vdim_prefix}{column} Count' diff --git a/holoviews/plotting/bokeh/element.py b/holoviews/plotting/bokeh/element.py index 2d49588b7e..05972603ec 100644 --- a/holoviews/plotting/bokeh/element.py +++ b/holoviews/plotting/bokeh/element.py @@ -1577,14 +1577,12 @@ def _apply_transforms(self, element, data, ranges, style, group=None): if not util.isscalar(val): if k in self._nonvectorized_styles: element = type(element).__name__ - raise ValueError('Mapping a dimension to the "{style}" ' + raise ValueError(f'Mapping a dimension to the "{k}" ' 'style option is not supported by the ' - '{element} element using the {backend} ' - 'backend. To map the "{dim}" dimension ' - 'to the {style} use a groupby operation ' - 'to overlay your data along the dimension.'.format( - style=k, dim=v.dimension, element=element, - backend=self.renderer.backend)) + f'{element} element using the {self.renderer.backend} ' + f'backend. To map the "{v.dimension}" dimension ' + f'to the {k} use a groupby operation ' + 'to overlay your data along the dimension.') elif data and len(val) != len(next(iter(data.values()))): if isinstance(element, VectorField): val = np.tile(val, 3) diff --git a/holoviews/plotting/plot.py b/holoviews/plotting/plot.py index d8b4c94d5b..7df8aa5e64 100644 --- a/holoviews/plotting/plot.py +++ b/holoviews/plotting/plot.py @@ -1828,8 +1828,9 @@ def _create_subplot(self, key, obj, streams, ranges): plottype = registry.get(vtype, None) if plottype is None: self.param.warning( - "No plotting class for {} type and {} backend " - "found. ".format(vtype.__name__, self.renderer.backend)) + f"No plotting class for {vtype.__name__} type " + f"and {self.renderer.backend} backend found. " + ) return None # Get zorder and style counter diff --git a/holoviews/plotting/plotly/element.py b/holoviews/plotting/plotly/element.py index 504c7dcdea..564f67139f 100644 --- a/holoviews/plotting/plotly/element.py +++ b/holoviews/plotting/plotly/element.py @@ -174,11 +174,8 @@ def generate_plot(self, key, ranges, element=None, is_geo=False): ] if unsupported_opts: raise ValueError( - "The following {typ} style options are not supported by the Plotly " - "backend when overlaid on Tiles:\n" - " {unsupported_opts}".format( - typ=type(element).__name__, unsupported_opts=unsupported_opts - ) + f"The following {type(element).__name__} style options are not supported by the Plotly " + f"backend when overlaid on Tiles:\n {unsupported_opts}" ) # Get data and options and merge them @@ -352,8 +349,8 @@ def _apply_transforms(self, element, ranges, style): continue elif (not v.applies(element) and v.dimension not in self.overlay_dims): new_style.pop(k) - self.param.warning('Specified {} dim transform {!r} could not be applied, as not all ' - 'dimensions could be resolved.'.format(k, v)) + self.param.warning(f'Specified {k} dim transform {v!r} could not be applied, as not all ' + 'dimensions could be resolved.') continue if len(v.ops) == 0 and v.dimension in self.overlay_dims: @@ -368,14 +365,12 @@ def _apply_transforms(self, element, ranges, style): if not util.isscalar(val): if k in self._nonvectorized_styles: element = type(element).__name__ - raise ValueError('Mapping a dimension to the "{style}" ' + raise ValueError(f'Mapping a dimension to the "{k}" ' 'style option is not supported by the ' - '{element} element using the {backend} ' - 'backend. To map the "{dim}" dimension ' - 'to the {style} use a groupby operation ' - 'to overlay your data along the dimension.'.format( - style=k, dim=v.dimension, element=element, - backend=self.renderer.backend)) + f'{element} element using the {self.renderer.backend} ' + f'backend. To map the "{v.dimension}" dimension ' + f'to the {k} use a groupby operation ' + 'to overlay your data along the dimension.') # If color is not valid colorspec add colormapper numeric = isinstance(val, np.ndarray) and val.dtype.kind in 'uifMm' diff --git a/holoviews/plotting/util.py b/holoviews/plotting/util.py index d03e9bbe2f..3cc2947bae 100644 --- a/holoviews/plotting/util.py +++ b/holoviews/plotting/util.py @@ -83,12 +83,12 @@ def collate(obj): return obj.collate() if isinstance(obj, HoloMap): display_warning.param.warning( - "Nesting {0}s within a {1} makes it difficult to access " - "your data or control how it appears; we recommend " - "calling .collate() on the {1} in order to follow the " - "recommended nesting structure shown in the Composing " - "Data user guide (https://goo.gl/2YS8LJ)".format( - obj.type.__name__, type(obj).__name__)) + f"Nesting {obj.type.__name__}s within a {type(obj).__name__} " + "makes it difficult to access your data or control how it appears; " + f"we recommend calling .collate() on the {type(obj).__name__} " + "in order to follow the recommended nesting structure shown " + "in the Composing Data user guide (https://goo.gl/2YS8LJ)" + ) return obj.collate() elif isinstance(obj, (Layout, NdLayout)): try: diff --git a/holoviews/streams.py b/holoviews/streams.py index 75f66af7af..7a61a00cdf 100644 --- a/holoviews/streams.py +++ b/holoviews/streams.py @@ -240,12 +240,13 @@ def _process_streams(cls, streams): if overlap: pname = type(s.parameterized).__name__ param.main.param.warning( - 'The {} parameter(s) on the {} object have ' + f'The {sorted([p.name for p in overlap])} parameter(s) ' + f'on the {pname} object have ' 'already been supplied in another stream. ' 'Ensure that the supplied streams only specify ' 'each parameter once, otherwise multiple ' - 'events will be triggered when the parameter ' - 'changes.'.format(sorted([p.name for p in overlap]), pname)) + 'events will be triggered when the parameter changes.' + ) parameterizeds[pid] |= set(s.parameters) valid.append(s) return valid, invalid diff --git a/holoviews/tests/utils.py b/holoviews/tests/utils.py index c763122272..35c5670886 100644 --- a/holoviews/tests/utils.py +++ b/holoviews/tests/utils.py @@ -59,8 +59,7 @@ def assertEndsWith(self, level, substring): msg='\n\n{method}: {last_line}\ndoes not end with:\n{substring}' last_line = self.tail(level, n=1) if len(last_line) == 0: - raise AssertionError('Missing {method} output: {substring}'.format( - method=self.param_methods[level], substring=repr(substring))) + raise AssertionError(f'Missing {self.param_methods[level]} output: {substring!r}') if not last_line[0].endswith(substring): raise AssertionError(msg.format(method=self.param_methods[level], last_line=repr(last_line[0]), @@ -77,8 +76,7 @@ def assertContains(self, level, substring): msg='\n\n{method}: {last_line}\ndoes not contain:\n{substring}' last_line = self.tail(level, n=1) if len(last_line) == 0: - raise AssertionError('Missing {method} output: {substring}'.format( - method=self.param_methods[level], substring=repr(substring))) + raise AssertionError(f'Missing {self.param_methods[level]} output: {substring!r}') if substring not in last_line[0]: raise AssertionError(msg.format(method=self.param_methods[level], last_line=repr(last_line[0]), diff --git a/holoviews/util/__init__.py b/holoviews/util/__init__.py index 34d384e32c..fd11c49441 100644 --- a/holoviews/util/__init__.py +++ b/holoviews/util/__init__.py @@ -139,9 +139,7 @@ def _group_kwargs_to_options(cls, obj, kwargs): # Not targets specified - add current object as target sanitized_group = util.group_sanitizer(obj.group) if obj.label: - identifier = ('{}.{}.{}'.format( - obj.__class__.__name__, sanitized_group, - util.label_sanitizer(obj.label))) + identifier = (f'{obj.__class__.__name__}.{sanitized_group}.{util.label_sanitizer(obj.label)}') elif sanitized_group != obj.__class__.__name__: identifier = f'{obj.__class__.__name__}.{sanitized_group}' else: @@ -333,10 +331,10 @@ def _expand_options(cls, options, backend=None): "holoviews.plotting before applying any " "options.") elif current_backend not in Store.renderers: - raise ValueError("Currently selected plotting extension {ext} " + raise ValueError(f"Currently selected plotting extension {current_backend!r} " "has not been loaded, ensure you load it " - "with hv.extension({ext}) before setting " - "options".format(ext=repr(current_backend))) + f"with hv.extension({current_backend!r}) before setting " + "options") try: backend_options = Store.options(backend=backend or current_backend) diff --git a/scripts/check_latest_packages.py b/scripts/check_latest_packages.py index 407f24a2a0..e99f485efd 100644 --- a/scripts/check_latest_packages.py +++ b/scripts/check_latest_packages.py @@ -30,7 +30,7 @@ def main(*packages): ).date() version_check = Version(current) >= Version(latest) - date_check = current_release_date >= allowed_date + date_check = latest_release_date >= allowed_date is_latest = version_check or date_check all_latest &= is_latest From 6a7fedc07b5c270dbd82e9184897260075d921e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Mon, 18 Mar 2024 11:56:53 +0100 Subject: [PATCH 55/66] Don't raise KeyError if options don't contain None (#6153) --- holoviews/plotting/plot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/holoviews/plotting/plot.py b/holoviews/plotting/plot.py index 7df8aa5e64..612091659c 100644 --- a/holoviews/plotting/plot.py +++ b/holoviews/plotting/plot.py @@ -925,7 +925,7 @@ def lookup(x): for opt, v in opts.items(): if opt not in options[key]: options[key][opt] = v - return options if keyfn else options[None] + return options if keyfn else options.get(None, {}) def _get_projection(cls, obj): """ From 48d376c7d1de4b87af686b6d38377af42c568cb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Tue, 19 Mar 2024 16:03:06 +0100 Subject: [PATCH 56/66] Force vdims to strings for ImageStack (#6155) --- holoviews/operation/datashader.py | 2 +- holoviews/tests/operation/test_datashader.py | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/holoviews/operation/datashader.py b/holoviews/operation/datashader.py index d527d689fd..cd7ac77a2a 100644 --- a/holoviews/operation/datashader.py +++ b/holoviews/operation/datashader.py @@ -406,7 +406,7 @@ def _process(self, element, key=None): eldata = agg if ds_version > Version('0.5.0') else (xs, ys, agg.data) return self.p.element_type(eldata, **params) else: - params['vdims'] = list(agg.coords[agg_fn.column].data) + params['vdims'] = list(map(str, agg.coords[agg_fn.column].data)) return ImageStack(agg, **params) def _apply_datashader(self, dfdata, cvs_fn, agg_fn, agg_kwargs, x, y): diff --git a/holoviews/tests/operation/test_datashader.py b/holoviews/tests/operation/test_datashader.py index ee4302649b..531d869a09 100644 --- a/holoviews/tests/operation/test_datashader.py +++ b/holoviews/tests/operation/test_datashader.py @@ -1560,3 +1560,10 @@ def test_imagestack_datashader_color_key(): color_key=cc.glasbey_light, ) render(op) # should not error out + + +def test_imagestack_datashade_count_cat(): + # Test for https://github.com/holoviz/holoviews/issues/6154 + df = pd.DataFrame({"x": range(3), "y": range(3), "c": range(3)}) + op = datashade(Points(df), aggregator=ds.count_cat("c")) + render(op) # should not error out From 014783700dea87fc384ec978145bbaba0d544585 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Tue, 19 Mar 2024 20:20:56 +0100 Subject: [PATCH 57/66] Package update - build and publish (#6031) --- .github/workflows/build.yaml | 183 +++++++++++++++++++++-------------- conda.recipe/meta.yaml | 7 ++ scripts/build_conda.sh | 4 +- 3 files changed, 117 insertions(+), 77 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 81563ba20e..519e489f61 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -6,107 +6,140 @@ on: - "v[0-9]+.[0-9]+.[0-9]+a[0-9]+" - "v[0-9]+.[0-9]+.[0-9]+b[0-9]+" - "v[0-9]+.[0-9]+.[0-9]+rc[0-9]+" - # Dry-run only workflow_dispatch: schedule: - cron: "0 14 * * SUN" +defaults: + run: + shell: bash -el {0} + +env: + SETUPTOOLS_ENABLE_FEATURES: "legacy-editable" + PYTHON_VERSION: "3.11" + PACKAGE: "holoviews" + jobs: + waiting_room: + name: Waiting Room + runs-on: ubuntu-latest + needs: [conda_build, pip_install] + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') + environment: + name: publish + steps: + - run: echo "All builds have finished, have been approved, and ready to publish" + conda_build: - name: Build Conda Packages + name: Build Conda runs-on: "ubuntu-latest" - defaults: - run: - shell: bash -l {0} - env: - CHANS_DEV: "-c pyviz/label/dev -c bokeh" - PKG_TEST_PYTHON: "--test-python=py39" - PYTHON_VERSION: "3.9" - CHANS: "-c pyviz" - MPLBACKEND: "Agg" - CONDA_UPLOAD_TOKEN: ${{ secrets.CONDA_UPLOAD_TOKEN }} - SETUPTOOLS_ENABLE_FEATURES: "legacy-editable" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: "100" - - uses: conda-incubator/setup-miniconda@v2 - with: - miniconda-version: "latest" - python-version: ${{ env.PYTHON_VERSION }} - name: Fetch unshallow run: git fetch --prune --tags --unshallow -f - - name: Set output - id: vars - run: echo "tag=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT + - uses: conda-incubator/setup-miniconda@v3 + with: + miniconda-version: "latest" - name: conda setup run: | - conda config --set always_yes True - conda config --append channels pyviz/label/dev - conda config --append channels conda-forge # pyct is for running setup.py - conda install -y conda-build anaconda-client build pyct + conda install -y conda-build build pyct -c pyviz/label/dev - name: conda build run: | - bash ./scripts/build_conda.sh + source ./scripts/build_conda.sh + echo "CONDA_FILE="$CONDA_PREFIX/conda-bld/noarch/$PACKAGE-$VERSION-py_0.tar.bz2"" >> $GITHUB_ENV + - uses: actions/upload-artifact@v4 + if: always() + with: + name: conda + path: ${{ env.CONDA_FILE }} + if-no-files-found: error + + conda_publish: + name: Publish Conda + runs-on: ubuntu-latest + needs: [conda_build, waiting_room] + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') + steps: + - uses: actions/download-artifact@v4 + with: + name: conda + path: dist/ + - name: Set environment variables + run: | + echo "TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + echo "CONDA_FILE=$(ls dist/*.tar.bz2)" >> $GITHUB_ENV + - uses: conda-incubator/setup-miniconda@v3 + with: + miniconda-version: "latest" + - name: conda setup + run: | + conda install -y anaconda-client - name: conda dev upload - if: (github.event_name == 'push' && (contains(steps.vars.outputs.tag, 'a') || contains(steps.vars.outputs.tag, 'b') || contains(steps.vars.outputs.tag, 'rc'))) + if: contains(env.TAG, 'a') || contains(env.TAG, 'b') || contains(env.TAG, 'rc') run: | - VERSION="$(echo "$(ls dist/*.whl)" | cut -d- -f2)" - FILE="$CONDA_PREFIX/conda-bld/noarch/holoviews-$VERSION-py_0.tar.bz2" - anaconda --token $CONDA_UPLOAD_TOKEN upload --user pyviz --label=dev $FILE + anaconda --token ${{ secrets.CONDA_UPLOAD_TOKEN }} upload --user pyviz --label=dev $CONDA_FILE - name: conda main upload - if: (github.event_name == 'push' && !(contains(steps.vars.outputs.tag, 'a') || contains(steps.vars.outputs.tag, 'b') || contains(steps.vars.outputs.tag, 'rc'))) + if: (!(contains(env.TAG, 'a') || contains(env.TAG, 'b') || contains(env.TAG, 'rc'))) run: | - VERSION="$(echo "$(ls dist/*.whl)" | cut -d- -f2)" - FILE="$CONDA_PREFIX/conda-bld/noarch/holoviews-$VERSION-py_0.tar.bz2" - anaconda --token $CONDA_UPLOAD_TOKEN upload --user pyviz --label=dev --label=main $FILE + anaconda --token ${{ secrets.CONDA_UPLOAD_TOKEN }} upload --user pyviz --label=dev --label=main $CONDA_FILE + pip_build: - name: Build PyPI Packages + name: Build PyPI runs-on: "ubuntu-latest" - defaults: - run: - shell: bash -l {0} - env: - CHANS_DEV: "-c pyviz/label/dev -c bokeh" - PKG_TEST_PYTHON: "--test-python=py39" - PYTHON_VERSION: "3.9" - CHANS: "-c pyviz" - MPLBACKEND: "Agg" - PPU: ${{ secrets.PPU }} - PPP: ${{ secrets.PPP }} - PYPI: "https://upload.pypi.org/legacy/" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: "100" - - uses: conda-incubator/setup-miniconda@v2 - with: - miniconda-version: "latest" - python-version: 3.9 - name: Fetch unshallow run: git fetch --prune --tags --unshallow -f - - name: conda setup - run: | - conda install -c pyviz "pyctdev>=0.5" - doit ecosystem_setup - doit env_create $CHANS_DEV --python=$PYTHON_VERSION - - name: env setup - run: | - conda activate test-environment - doit develop_install $CHANS_DEV - pip uninstall -y holoviews - doit pip_on_conda - - name: doit env_capture - run: | - conda activate test-environment - doit env_capture - - name: pip build - run: | - conda activate test-environment - doit ecosystem=pip package_build --test-group=simple - - name: pip upload - if: github.event_name == 'push' + - uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + - name: Install build run: | - conda activate test-environment - doit ecosystem=pip package_upload -u $PPU -p $PPP -r $PYPI + python -m pip install build + - name: Build package + run: python -m build . + - uses: actions/upload-artifact@v4 + if: always() + with: + name: pip + path: dist/ + if-no-files-found: error + + pip_install: + name: Install PyPI + runs-on: "ubuntu-latest" + needs: [pip_build] + steps: + - uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + - uses: actions/download-artifact@v4 + with: + name: pip + path: dist/ + - name: Install package + run: python -m pip install dist/*.whl + - name: Test package + run: python -c "import $PACKAGE; print($PACKAGE.__version__)" + + pip_publish: + name: Publish PyPI + runs-on: ubuntu-latest + needs: [pip_build, waiting_room] + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') + steps: + - uses: actions/download-artifact@v4 + with: + name: pip + path: dist/ + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + user: ${{ secrets.PPU }} + password: ${{ secrets.PPP }} + repository-url: "https://upload.pypi.org/legacy/" diff --git a/conda.recipe/meta.yaml b/conda.recipe/meta.yaml index 24f412d2a7..087efe849e 100644 --- a/conda.recipe/meta.yaml +++ b/conda.recipe/meta.yaml @@ -32,6 +32,13 @@ requirements: - {{ dep }} {% endfor %} +test: + imports: + - {{ sdata['name'] }} + commands: + - pip check + requires: + - pip about: home: https://holoviews.org diff --git a/scripts/build_conda.sh b/scripts/build_conda.sh index 50f97422b8..4b47650355 100755 --- a/scripts/build_conda.sh +++ b/scripts/build_conda.sh @@ -5,10 +5,10 @@ set -euxo pipefail git status export SETUPTOOLS_ENABLE_FEATURES="legacy-editable" -python -m build . +python -m build -w . git diff --exit-code VERSION=$(find dist -name "*.whl" -exec basename {} \; | cut -d- -f2) export VERSION -conda build conda.recipe/ --no-test --no-anaconda-upload --no-verify +conda build conda.recipe/ --no-anaconda-upload --no-verify From dcef38a0e96a81faa986ac37000819b56d6ee268 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Wed, 20 Mar 2024 05:37:29 -0400 Subject: [PATCH 58/66] Update server tests to simulate loaded event (#6157) --- holoviews/tests/plotting/bokeh/test_callbacks.py | 4 ++++ holoviews/tests/plotting/bokeh/test_server.py | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/holoviews/tests/plotting/bokeh/test_callbacks.py b/holoviews/tests/plotting/bokeh/test_callbacks.py index 889740757c..d2c4d0950c 100644 --- a/holoviews/tests/plotting/bokeh/test_callbacks.py +++ b/holoviews/tests/plotting/bokeh/test_callbacks.py @@ -447,6 +447,10 @@ def test_rangexy_framewise_reset(self): self.assertEqual(stream.y_range, None) def test_rangexy_framewise_not_reset_if_triggering(self): + import panel as pn + from packaging.version import Version + if Version(pn.__version__) == Version("1.4.0rc3"): + raise SkipTest('This test fails with Panel 1.4.0rc3') stream = RangeXY(x_range=(0, 2), y_range=(0, 1)) curve = DynamicMap(lambda z, x_range, y_range: Curve([1, 2, z]), kdims=['z'], streams=[stream]).redim.range(z=(0, 3)) diff --git a/holoviews/tests/plotting/bokeh/test_server.py b/holoviews/tests/plotting/bokeh/test_server.py index 4f9f21cf8e..5686bfbff3 100644 --- a/holoviews/tests/plotting/bokeh/test_server.py +++ b/holoviews/tests/plotting/bokeh/test_server.py @@ -163,6 +163,9 @@ def test_server_dynamicmap_with_stream(self): cds = session.document.roots[0].select_one({'type': ColumnDataSource}) self.assertEqual(cds.data['y'][2], 2) + def loaded(): + state._schedule_on_load(doc, None) + doc.add_next_tick_callback(loaded) def run(): stream.event(y=3) doc.add_next_tick_callback(run) @@ -180,6 +183,9 @@ def test_server_dynamicmap_with_stream_dims(self): orig_cds = session.document.roots[0].select_one({'type': ColumnDataSource}) self.assertEqual(orig_cds.data['y'][2], 2) + def loaded(): + state._schedule_on_load(doc, None) + doc.add_next_tick_callback(loaded) def run(): stream.event(y=3) doc.add_next_tick_callback(run) From 40606925986972ab201537f490da9dca7614afa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Wed, 20 Mar 2024 18:01:36 +0100 Subject: [PATCH 59/66] Update test ci (#6160) --- .github/workflows/test.yaml | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 4b2486c528..5a15a009b5 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -64,7 +64,7 @@ jobs: - uses: actions/checkout@v3 if: github.event_name != 'pull_request' - name: Check for code changes - uses: dorny/paths-filter@v2.11.1 + uses: dorny/paths-filter@v3 id: filter with: filters: | @@ -134,12 +134,6 @@ jobs: cache: ${{ github.event.inputs.cache || github.event.inputs.cache == '' }} conda-update: true id: install - - name: suppress warning - if: needs.setup.outputs.code_change == 'true' - run: | - conda activate test-environment - # https://github.com/conda-forge/ocl-icd-feedstock/issues/29 - touch ${CONDA_PREFIX}/etc/OpenCL/vendors/mute || true - name: Check packages latest version if: needs.setup.outputs.code_change == 'true' run: | @@ -194,11 +188,6 @@ jobs: cache: ${{ github.event.inputs.cache || github.event.inputs.cache == '' }} playwright: true id: install - - name: suppress warning - if: needs.setup.outputs.code_change == 'true' - run: | - conda activate test-environment - touch ${CONDA_PREFIX}/etc/OpenCL/vendors/mute || true # https://github.com/conda-forge/ocl-icd-feedstock/issues/29 - name: doit test_ui if: needs.setup.outputs.code_change == 'true' run: | From e2dfa227268515025a776a558b42276071582768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Thu, 21 Mar 2024 15:47:03 +0100 Subject: [PATCH 60/66] Support dictionary cmaps for ImageStack (#6025) Co-authored-by: Andrew Huang --- holoviews/plotting/bokeh/raster.py | 24 ++++++++++++++-- .../tests/plotting/bokeh/test_rasterplot.py | 28 +++++++++++++++++++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/holoviews/plotting/bokeh/raster.py b/holoviews/plotting/bokeh/raster.py index 9245bc86b6..8f281cc12b 100644 --- a/holoviews/plotting/bokeh/raster.py +++ b/holoviews/plotting/bokeh/raster.py @@ -258,13 +258,31 @@ def _get_cmapper_opts(self, low, high, factors, colors): def _get_colormapper(self, eldim, element, ranges, style, factors=None, colors=None, group=None, name='color_mapper'): + indices = None + vdims = element.vdims + if isinstance(style.get("cmap"), dict): + dict_cmap = style["cmap"] + missing = [vd.name for vd in vdims if vd.name not in dict_cmap] + if missing: + missing_str = "', '".join(sorted(missing)) + raise ValueError( + "The supplied cmap dictionary must have the same " + f"value dimensions as the element. Missing: '{missing_str}'" + ) + keys, values = zip(*dict_cmap.items()) + style["cmap"] = list(values) + indices = [keys.index(vd.name) for vd in vdims] + cmapper = super()._get_colormapper( eldim, element, ranges, style, factors=factors, colors=colors, group=group, name=name ) - num_elements = len(element.vdims) - step_size = len(cmapper.palette) // num_elements - indices = np.arange(num_elements) * step_size + + if indices is None: + num_elements = len(vdims) + step_size = len(cmapper.palette) // num_elements + indices = np.arange(num_elements) * step_size + cmapper.palette = np.array(cmapper.palette)[indices].tolist() return cmapper diff --git a/holoviews/tests/plotting/bokeh/test_rasterplot.py b/holoviews/tests/plotting/bokeh/test_rasterplot.py index 56dd684f90..c5c404f6f9 100644 --- a/holoviews/tests/plotting/bokeh/test_rasterplot.py +++ b/holoviews/tests/plotting/bokeh/test_rasterplot.py @@ -408,6 +408,34 @@ def test_image_stack_tuple_single_3darray(self): assert source.data["dh"][0] == self.ysize assert isinstance(plot, ImageStackPlot) + def test_image_stack_dict_cmap(self): + x = np.arange(0, 3) + y = np.arange(5, 8) + a = np.array([[np.nan, np.nan, 1], [np.nan] * 3, [np.nan] * 3]) + b = np.array([[np.nan] * 3, [1, 1, np.nan], [np.nan] * 3]) + c = np.array([[np.nan] * 3, [np.nan] * 3, [1, 1, 1]]) + + img_stack = ImageStack((x, y, a, b, c), kdims=["x", "y"], vdims=["b", "a", "c"]) + img_stack.opts(cmap={"c": "yellow", "a": "red", "b": "green"}) + plot = bokeh_renderer.get_plot(img_stack) + source = plot.handles["source"] + np.testing.assert_equal(source.data["image"][0][:, :, 0], a) + np.testing.assert_equal(source.data["image"][0][:, :, 1], b) + np.testing.assert_equal(source.data["image"][0][:, :, 2], c) + assert plot.handles["color_mapper"].palette == ["green", "red", "yellow"] + + def test_image_stack_dict_cmap_missing(self): + x = np.arange(0, 3) + y = np.arange(5, 8) + a = np.array([[np.nan, np.nan, 1], [np.nan] * 3, [np.nan] * 3]) + b = np.array([[np.nan] * 3, [1, 1, np.nan], [np.nan] * 3]) + c = np.array([[np.nan] * 3, [np.nan] * 3, [1, 1, 1]]) + + img_stack = ImageStack((x, y, a, b, c), kdims=["x", "y"], vdims=["b", "a", "c"]) + with pytest.raises(ValueError, match="must have the same value dimensions"): + img_stack.opts(cmap={"c": "yellow", "a": "red"}) + bokeh_renderer.get_plot(img_stack) + class TestImageStackEven(_ImageStackBase): __test__ = True From 0eeb0fc4d6ff977475b23d798262886372db0b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Wed, 27 Mar 2024 18:31:53 +0100 Subject: [PATCH 61/66] Update holoviz_tasks version (#6163) --- .github/workflows/docs.yaml | 2 +- .github/workflows/test.yaml | 8 ++++---- .pre-commit-config.yaml | 4 ++-- examples/conftest.py | 7 +++++++ holoviews/tests/plotting/matplotlib/test_renderer.py | 4 ++++ 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 5708d371c8..578df685c2 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -40,7 +40,7 @@ jobs: PANEL_EMBED_JSON: "true" PANEL_EMBED_JSON_PREFIX: "json" steps: - - uses: holoviz-dev/holoviz_tasks/install@v0.1a19 + - uses: holoviz-dev/holoviz_tasks/install@v0 with: name: Documentation python-version: "3.10" diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 5a15a009b5..4bc48f4e89 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -50,7 +50,7 @@ jobs: name: Run pre-commit runs-on: "ubuntu-latest" steps: - - uses: holoviz-dev/holoviz_tasks/pre-commit@v0.1a19 + - uses: holoviz-dev/holoviz_tasks/pre-commit@v0 setup: name: Setup workflow @@ -123,7 +123,7 @@ jobs: DESC: "Python ${{ matrix.python-version }}, ${{ matrix.os }} unit tests" PYTHON_VERSION: ${{ matrix.python-version }} steps: - - uses: holoviz-dev/holoviz_tasks/install@v0.1a19 + - uses: holoviz-dev/holoviz_tasks/install@v0 if: needs.setup.outputs.code_change == 'true' with: name: unit_test_suite @@ -178,7 +178,7 @@ jobs: # it as one of the sources. PYCTDEV_SELF_CHANNEL: "pyviz/label/dev" steps: - - uses: holoviz-dev/holoviz_tasks/install@v0.1a19 + - uses: holoviz-dev/holoviz_tasks/install@v0 if: needs.setup.outputs.code_change == 'true' with: name: ui_test_suite @@ -216,7 +216,7 @@ jobs: PYTHON_VERSION: ${{ matrix.python-version }} steps: # Add back when this works on Python 3.12 - # - uses: holoviz-dev/holoviz_tasks/install@v0.1a19 + # - uses: holoviz-dev/holoviz_tasks/install@v0 # if: needs.setup.outputs.code_change == 'true' # with: # name: core_test_suite diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cd84663faf..602951f640 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,7 @@ repos: - id: check-json - id: detect-private-key - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.3.2 + rev: v0.3.4 hooks: - id: ruff files: holoviews/|scripts/ @@ -42,7 +42,7 @@ repos: - id: rst-directive-colons - id: rst-inline-touching-normal - repo: https://github.com/shellcheck-py/shellcheck-py - rev: v0.9.0.6 + rev: v0.10.0.1 hooks: - id: shellcheck - repo: https://github.com/pre-commit/mirrors-prettier diff --git a/examples/conftest.py b/examples/conftest.py index b33cbeff2f..22dced7136 100644 --- a/examples/conftest.py +++ b/examples/conftest.py @@ -1,3 +1,4 @@ +import os import platform import sys @@ -55,6 +56,12 @@ "reference/elements/bokeh/VSpans.ipynb", ] +# 2024-03-27: ffmpeg errors on Windows CI +if system == "Windows" and os.environ.get("GITHUB_RUN_ID"): + collect_ignore_glob += [ + "user_guide/Plotting_with_Matplotlib.ipynb", + ] + def pytest_runtest_makereport(item, call): """ diff --git a/holoviews/tests/plotting/matplotlib/test_renderer.py b/holoviews/tests/plotting/matplotlib/test_renderer.py index 07d7523ebf..0c8f55aa26 100644 --- a/holoviews/tests/plotting/matplotlib/test_renderer.py +++ b/holoviews/tests/plotting/matplotlib/test_renderer.py @@ -1,12 +1,15 @@ """ Test cases for rendering exporters """ +import os import subprocess +import sys from unittest import SkipTest import numpy as np import panel as pn import param +import pytest from matplotlib import style from panel.widgets import DiscreteSlider, FloatSlider, Player from pyviz_comms import CommManager @@ -80,6 +83,7 @@ def test_render_gif(self): data, metadata = self.renderer.components(self.map1, 'gif') self.assertIn(" Date: Thu, 4 Apr 2024 09:32:20 +0200 Subject: [PATCH 62/66] Bump CI tests to use Python 3.12 (#5978) --- .github/workflows/test.yaml | 42 +++++++++++++------------------------ 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 4bc48f4e89..6a6cb2dab7 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -91,7 +91,7 @@ jobs: run: | MATRIX=$(jq -nsc '{ "os": ["ubuntu-latest", "macos-latest", "windows-latest"], - "python-version": ["3.9", "3.11"] + "python-version": ["3.9", "3.12"] }') echo "MATRIX=$MATRIX" >> $GITHUB_ENV - name: Set test matrix with 'full' option @@ -99,7 +99,7 @@ jobs: run: | MATRIX=$(jq -nsc '{ "os": ["ubuntu-latest", "macos-latest", "windows-latest"], - "python-version": ["3.9", "3.10", "3.11"] + "python-version": ["3.9", "3.10", "3.11", "3.12"] }') echo "MATRIX=$MATRIX" >> $GITHUB_ENV - name: Set test matrix with 'downstream' option @@ -215,18 +215,16 @@ jobs: DESC: "Python ${{ matrix.python-version }}, ${{ matrix.os }} core tests" PYTHON_VERSION: ${{ matrix.python-version }} steps: - # Add back when this works on Python 3.12 - # - uses: holoviz-dev/holoviz_tasks/install@v0 - # if: needs.setup.outputs.code_change == 'true' - # with: - # name: core_test_suite - # python-version: ${{ matrix.python-version }} - # # channel-priority: strict - # channels: pyviz/label/dev,conda-forge,nodefaults - # envs: "-o tests_core -o tests_ci" - # cache: ${{ github.event.inputs.cache || github.event.inputs.cache == '' }} - # conda-update: true - # id: install + - uses: holoviz-dev/holoviz_tasks/install@v0 + if: needs.setup.outputs.code_change == 'true' + with: + name: core_test_suite + python-version: ${{ matrix.python-version }} + # channel-priority: strict + channels: pyviz/label/dev,conda-forge,nodefaults + envs: "-o tests_core -o tests_ci" + cache: ${{ github.event.inputs.cache || github.event.inputs.cache == '' }} + id: install - uses: actions/checkout@v3 if: needs.setup.outputs.code_change == 'true' with: @@ -234,32 +232,22 @@ jobs: - name: Fetch unshallow if: needs.setup.outputs.code_change == 'true' run: git fetch --prune --tags --unshallow -f - - uses: actions/setup-python@v4 - if: needs.setup.outputs.code_change == 'true' - with: - python-version: 3.12 - name: install if: needs.setup.outputs.code_change == 'true' run: | python -m pip install -ve '.[tests_core, tests_ci]' - - name: install panel pre - if: needs.setup.outputs.code_change == 'true' - run: | - python -m pip install panel --pre --upgrade - python -m pip install bokeh --upgrade - echo "Installing dev release of Panel" >> $GITHUB_STEP_SUMMARY - name: Download data if: needs.setup.outputs.code_change == 'true' run: | - # conda activate test-environment + conda activate test-environment bash scripts/download_data.sh - name: Check packages latest version if: needs.setup.outputs.code_change == 'true' run: | - # conda activate test-environment + conda activate test-environment python scripts/check_latest_packages.py numpy pandas bokeh panel param - name: doit test_unit if: needs.setup.outputs.code_change == 'true' run: | - # conda activate test-environment + conda activate test-environment pytest holoviews From fef3219430a3472203aa869cc56c33d08876a480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Fri, 5 Apr 2024 14:42:09 +0200 Subject: [PATCH 63/66] Fixes to Bokeh BoxWhisker (#6169) --- holoviews/plotting/bokeh/stats.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/holoviews/plotting/bokeh/stats.py b/holoviews/plotting/bokeh/stats.py index 4251e4ddda..cc2adcccbb 100644 --- a/holoviews/plotting/bokeh/stats.py +++ b/holoviews/plotting/bokeh/stats.py @@ -72,6 +72,9 @@ class BoxWhiskerPlot(MultiDistributionMixin, CompositeElementPlot, ColorbarPlot, show_legend = param.Boolean(default=False, doc=""" Whether to show legend for the plot.""") + outlier_radius = param.Number(default=0.01, doc=""" + The radius of the circle marker for the outliers.""") + # Deprecated options color_index = param.ClassSelector(default=None, class_=(str, int), @@ -191,11 +194,11 @@ def get_data(self, element, ranges, style): if self.invert_axes: vbar_map = {'y': 'index', 'left': 'top', 'right': 'bottom', 'height': width} seg_map = {'y0': 'x0', 'y1': 'x1', 'x0': 'y0', 'x1': 'y1'} - out_map = {'y': 'index', 'x': vdim} + out_map = {'y': 'index', 'x': vdim, 'radius': self.outlier_radius} else: vbar_map = {'x': 'index', 'top': 'top', 'bottom': 'bottom', 'width': width} seg_map = {'x0': 'x0', 'x1': 'x1', 'y0': 'y0', 'y1': 'y1'} - out_map = {'x': 'index', 'y': vdim} + out_map = {'x': 'index', 'y': vdim, 'radius': self.outlier_radius} vbar2_map = dict(vbar_map) # Get color values @@ -206,7 +209,7 @@ def get_data(self, element, ranges, style): cdim, cidx = None, None factors = [] - vdim = element.vdims[0].name + vdim = dimension_sanitizer(element.vdims[0].name) for key, g in groups.items(): # Compute group label if element.kdims: From f5913b562a74118d95e1b2e1e51c37957095ba55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Fri, 5 Apr 2024 15:35:07 +0200 Subject: [PATCH 64/66] Expose hit_dilation in PointPlot (#6121) --- holoviews/plotting/bokeh/chart.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/holoviews/plotting/bokeh/chart.py b/holoviews/plotting/bokeh/chart.py index 0f481f2940..db03780ef5 100644 --- a/holoviews/plotting/bokeh/chart.py +++ b/holoviews/plotting/bokeh/chart.py @@ -61,7 +61,7 @@ class PointPlot(LegendPlot, ColorbarPlot): selection_display = BokehOverlaySelectionDisplay() - style_opts = (['cmap', 'palette', 'marker', 'size', 'angle'] + + style_opts = (['cmap', 'palette', 'marker', 'size', 'angle', 'hit_dilation'] + base_properties + line_properties + fill_properties) _plot_methods = dict(single='scatter', batched='scatter') From 4208e7368757880d2fa6ebe8c36c5de64f2e5a5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Fri, 5 Apr 2024 15:44:45 +0200 Subject: [PATCH 65/66] Improve groupby behavior for operation histogram (#6172) --- holoviews/operation/element.py | 36 +++++++++++------ holoviews/tests/operation/test_operation.py | 43 +++++++++++++++++++++ 2 files changed, 67 insertions(+), 12 deletions(-) diff --git a/holoviews/operation/element.py b/holoviews/operation/element.py index 0d8bc13246..131a14a08d 100644 --- a/holoviews/operation/element.py +++ b/holoviews/operation/element.py @@ -3,6 +3,7 @@ examples. """ import warnings +from functools import partial import numpy as np import param @@ -754,6 +755,9 @@ class histogram(Operation): groupby = param.ClassSelector(default=None, class_=(str, Dimension), doc=""" Defines a dimension to group the Histogram returning an NdOverlay of Histograms.""") + groupby_range = param.Selector(default="shared", objects=["shared", "separated"], doc=""" + Whether to group the histograms along the same range or separate them.""") + log = param.Boolean(default=False, doc=""" Whether to use base 10 logarithmic samples for the bin edges.""") @@ -781,15 +785,7 @@ class histogram(Operation): style_prefix = param.String(default=None, allow_None=None, doc=""" Used for setting a common style for histograms in a HoloMap or AdjointLayout.""") - def _process(self, element, key=None): - if self.p.groupby: - if not isinstance(element, Dataset): - raise ValueError('Cannot use histogram groupby on non-Dataset Element') - grouped = element.groupby(self.p.groupby, group_type=Dataset, container_type=NdOverlay) - self.p.groupby = None - return grouped.map(self._process, Dataset) - - normed = False if self.p.mean_weighted and self.p.weight_dimension else self.p.normed + def _get_dim_and_data(self, element): if self.p.dimension: selected_dim = self.p.dimension else: @@ -800,6 +796,21 @@ def _process(self, element, key=None): data = element.interface.values(element, selected_dim, compute=False) else: data = element.dimension_values(selected_dim) + return dim, data + + def _process(self, element, key=None, groupby=False): + if self.p.groupby: + if not isinstance(element, Dataset): + raise ValueError('Cannot use histogram groupby on non-Dataset Element') + grouped = element.groupby(self.p.groupby, group_type=Dataset, container_type=NdOverlay) + if self.p.groupby_range == 'shared' and not self.p.bin_range: + _, data = self._get_dim_and_data(element) + self.p.bin_range = (data.min(), data.max()) + self.p.groupby = None + return grouped.map(partial(self._process, groupby=True), Dataset) + + normed = False if self.p.mean_weighted and self.p.weight_dimension else self.p.normed + dim, data = self._get_dim_and_data(element) is_datetime = isdatetime(data) if is_datetime: @@ -859,7 +870,7 @@ def _process(self, element, key=None): if isdatetime(edges): edges = edges.astype('datetime64[ns]').astype('int64') else: - hist_range = self.p.bin_range or element.range(selected_dim) + hist_range = self.p.bin_range or element.range(dim) # Suppress a warning emitted by Numpy when datetime or timedelta scalars # are compared. See https://github.com/numpy/numpy/issues/10095 and # https://github.com/numpy/numpy/issues/9210. @@ -939,8 +950,9 @@ def _process(self, element, key=None): # Save off the computed bin edges so that if this operation instance # is used to compute another histogram, it will default to the same # bin edges. - self.bins = list(edges) - return Histogram((edges, hist), kdims=[element.get_dimension(selected_dim)], + if not groupby: + self.bins = list(edges) + return Histogram((edges, hist), kdims=[dim], label=element.label, **params) diff --git a/holoviews/tests/operation/test_operation.py b/holoviews/tests/operation/test_operation.py index 0746560418..763c5f81ad 100644 --- a/holoviews/tests/operation/test_operation.py +++ b/holoviews/tests/operation/test_operation.py @@ -331,6 +331,49 @@ def test_dataset_histogram_empty_explicit_bins(self): hist = Histogram(([0, 1, 2], [0, 0]), vdims=('x_count', 'Count')) self.assertEqual(op_hist, hist) + def test_dataset_histogram_groupby_range_shared(self): + x = np.arange(10) + y = np.arange(10) + 10 + xy = np.concatenate([x, y]) + label = ["x"] * 10 + ["y"] * 10 + + ds = Dataset(pd.DataFrame([xy, label], index=["xy", "label"]).T, vdims=["xy", "label"]) + hist = histogram(ds, groupby="label", groupby_range="shared") + exp = np.linspace(0, 19, 21) + for k, v in hist.items(): + np.testing.assert_equal(exp, v.data["xy"]) + sel = np.asarray(label) == k + assert sel.sum() == 10 + assert (v.data["xy_count"][sel] == 1).all() + assert (v.data["xy_count"][~sel] == 0).all() + + def test_dataset_histogram_groupby_range_separated(self): + x = np.arange(10) + y = np.arange(10) + 10 + xy = np.concatenate([x, y]) + label = ["x"] * 10 + ["y"] * 10 + + ds = Dataset(pd.DataFrame([xy, label], index=["xy", "label"]).T, vdims=["xy", "label"]) + hist = histogram(ds, groupby="label", groupby_range="separated") + + for idx, v in enumerate(hist): + exp = np.linspace(idx * 10, 10 * idx + 9, 21) + np.testing.assert_equal(exp, v.data["xy"]) + assert v.data["xy_count"].sum() == 10 + + def test_dataset_histogram_groupby_datetime(self): + x = pd.date_range("2020-01-01", periods=100) + y = pd.date_range("2020-01-01", periods=100) + xy = np.concatenate([x, y]) + label = ["x"] * 100 + ["y"] * 100 + ds = Dataset(pd.DataFrame([xy, label], index=["xy", "label"]).T, vdims=["xy", "label"]) + hist = histogram(ds, groupby="label") + + exp = pd.date_range("2020-01-01", '2020-04-09', periods=21) + for h in hist: + np.testing.assert_equal(exp, h.data["xy"]) + assert (h.data["xy_count"] == 5).all() + @da_skip def test_dataset_histogram_dask(self): import dask.array as da From bf4592ed84ff05585f8613b393474f1713efe6f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20H=C3=B8xbro=20Hansen?= Date: Sat, 6 Apr 2024 08:33:05 +0200 Subject: [PATCH 66/66] Improve autocompletion for lazy module (#6174) --- .github/workflows/test.yaml | 11 ----------- holoviews/__init__.py | 12 +++++++++++- holoviews/tests/plotting/bokeh/test_callbacks.py | 4 ---- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 6a6cb2dab7..57e3226018 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -225,17 +225,6 @@ jobs: envs: "-o tests_core -o tests_ci" cache: ${{ github.event.inputs.cache || github.event.inputs.cache == '' }} id: install - - uses: actions/checkout@v3 - if: needs.setup.outputs.code_change == 'true' - with: - fetch-depth: "100" - - name: Fetch unshallow - if: needs.setup.outputs.code_change == 'true' - run: git fetch --prune --tags --unshallow -f - - name: install - if: needs.setup.outputs.code_change == 'true' - run: | - python -m pip install -ve '.[tests_core, tests_ci]' - name: Download data if: needs.setup.outputs.code_change == 'true' run: | diff --git a/holoviews/__init__.py b/holoviews/__init__.py index eaf4a5ccba..e3231dece9 100644 --- a/holoviews/__init__.py +++ b/holoviews/__init__.py @@ -173,6 +173,8 @@ def help(obj, visualization=True, ansi=True, backend=None, pydoc.help(obj) +del os, rcfile, warnings + def __getattr__(name): if name == "annotate": # Lazy loading Panel @@ -180,5 +182,13 @@ def __getattr__(name): return annotate raise AttributeError(f"module {__name__!r} has no attribute {name!r}") +__all__ = [k for k in locals() if not k.startswith('_')] +__all__ += ['annotate', '__version__'] -del os, rcfile, warnings +def __dir__(): + return __all__ + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from .annotators import annotate diff --git a/holoviews/tests/plotting/bokeh/test_callbacks.py b/holoviews/tests/plotting/bokeh/test_callbacks.py index d2c4d0950c..889740757c 100644 --- a/holoviews/tests/plotting/bokeh/test_callbacks.py +++ b/holoviews/tests/plotting/bokeh/test_callbacks.py @@ -447,10 +447,6 @@ def test_rangexy_framewise_reset(self): self.assertEqual(stream.y_range, None) def test_rangexy_framewise_not_reset_if_triggering(self): - import panel as pn - from packaging.version import Version - if Version(pn.__version__) == Version("1.4.0rc3"): - raise SkipTest('This test fails with Panel 1.4.0rc3') stream = RangeXY(x_range=(0, 2), y_range=(0, 1)) curve = DynamicMap(lambda z, x_range, y_range: Curve([1, 2, z]), kdims=['z'], streams=[stream]).redim.range(z=(0, 3))