From 231cdf8af9067ec29940bb6a305bd3f507f52bb8 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Mon, 14 Sep 2020 11:28:53 -0400 Subject: [PATCH 01/11] HoloViews 1.13.4 documentation fixes [doc-build] (#4608) * Fix LesMis example log colormapping * Ensure Plotly is registered as loaded extension * Disable inline resources * Update holoviews/plotting/plotly/renderer.py --- doc/conf.py | 5 +++-- examples/gallery/demos/bokeh/lesmis_example.ipynb | 5 ++--- holoviews/plotting/plotly/renderer.py | 2 ++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index f16cb52082..81433840c7 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -4,8 +4,8 @@ # Declare information specific to this project. project = u'HoloViews' -authors = u'PyViz developers' -copyright = u'2019 ' + authors +authors = u'HoloViz developers' +copyright = u'2020 ' + authors description = 'Stop plotting your data - annotate your data and let it visualize itself.' import param @@ -16,6 +16,7 @@ import holoviews version = release = holoviews.__version__ +holoviews.extension.inline = False html_theme = 'sphinx_holoviz_theme' html_static_path += ['_static'] diff --git a/examples/gallery/demos/bokeh/lesmis_example.ipynb b/examples/gallery/demos/bokeh/lesmis_example.ipynb index 71bfb97d0e..bfb7ac5f5c 100644 --- a/examples/gallery/demos/bokeh/lesmis_example.ipynb +++ b/examples/gallery/demos/bokeh/lesmis_example.ipynb @@ -78,10 +78,9 @@ "\n", "combined = hv.Overlay([o.opts(cmap=cm).sort() for o, cm in zip(overlaid, cmaps)], label='LesMis Occurences')\n", "styled = combined.opts(\n", - " opts.HeatMap(logz=True, clipping_colors={'NaN':(1,1,1,0.)},\n", - " xaxis='top', xrotation=90,\n", + " opts.HeatMap(logz=True, clim=(0.1, None), clipping_colors={'NaN':(1,1,1,0.)}, xaxis='top', xrotation=90,\n", " fontsize={'ticks': '7pt', 'title': '18pt'}, invert_xaxis=True, tools=['hover'],\n", - " labelled=[],),\n", + " labelled=[], axiswise=True),\n", " opts.Overlay(height=800, width=800)\n", ")\n", "styled" diff --git a/holoviews/plotting/plotly/renderer.py b/holoviews/plotting/plotly/renderer.py index 505b632199..723946a1e0 100644 --- a/holoviews/plotting/plotly/renderer.py +++ b/holoviews/plotting/plotly/renderer.py @@ -159,6 +159,8 @@ def load_nb(cls, inline=True): """ import panel.models.plotly # noqa cls._loaded = True + if 'plotly' not in getattr(pn.extension, '_loaded_extensions', ['plotly']): + pn.extension._loaded_extensions.append('plotly') def _activate_plotly_backend(renderer): From b7b37de7bfc337ee9019ce142ee5ab778dae23b5 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Tue, 15 Sep 2020 11:15:51 +0200 Subject: [PATCH 02/11] Clean up doc build env [doc-build] --- .travis.yml | 2 -- setup.py | 4 +++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index b86d322a95..f2719ea991 100644 --- a/.travis.yml +++ b/.travis.yml @@ -89,7 +89,6 @@ jobs: stage: docs_dev env: DESC="docs" HV_DOC_GALLERY="false" HV_DOC_REF_GALLERY="true" HV_REQUIREMENTS="doc" PANEL_EMBED="true" PANEL_EMBED_JSON="true" PANEL_EMBED_JSON_PREFIX="json" CHANS_DEV="-c pyviz/label/dev -c bokeh -c conda-forge" script: - - conda install $CHANS_DEV firefox geckodriver mpl_sample_data - bokeh sampledata - nbsite generate-rst --org pyviz --project-name holoviews --skip ^reference - python ./doc/generate_modules.py holoviews -d ./doc/reference_manual -n holoviews -e tests @@ -102,7 +101,6 @@ jobs: stage: gallery_dev env: DESC="gallery" HV_DOC_GALLERY="true" HV_DOC_REF_GALLERY="false" BUCKET="dev." HV_REQUIREMENTS="doc" PANEL_EMBED="true" PANEL_EMBED_JSON="true" PANEL_EMBED_JSON_PREFIX="json" CHANS_DEV="-c pyviz/label/dev -c bokeh -c conda-forge" script: - - conda install $CHANS_DEV firefox geckodriver mpl_sample_data - bokeh sampledata - aws s3 sync --quiet s3://holoviews-doc-builds/$TRAVIS_BUILD_NUMBER ./ - git reset --hard --recurse-submodule diff --git a/setup.py b/setup.py index fa71017e4d..662362ea52 100644 --- a/setup.py +++ b/setup.py @@ -103,7 +103,9 @@ 'selenium', 'bokeh <2.2', 'firefox', - 'geckodriver' + 'geckodriver', + 'nbconvert <6.0', + 'mpl_sample_data' ] extras_require['build'] = [ From d0689fd86f85d11b5dbc78aadccb2d1c3756e276 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Tue, 15 Sep 2020 10:02:58 -0400 Subject: [PATCH 03/11] Fixed handling of factors for Violin plots (#4613) --- holoviews/plotting/bokeh/stats.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/holoviews/plotting/bokeh/stats.py b/holoviews/plotting/bokeh/stats.py index 1cfe233640..3c1998d427 100644 --- a/holoviews/plotting/bokeh/stats.py +++ b/holoviews/plotting/bokeh/stats.py @@ -548,6 +548,8 @@ def get_data(self, element, ranges, style): kde_data, line_data, seg_data, bar_data, scatter_data = (defaultdict(list) for i in range(5)) for i, (key, g) in enumerate(groups.items()): key = decode_bytes(key) + if element.kdims: + key = tuple(d.pprint_value(k) for d, k in zip(element.kdims, key)) kde, line, segs, bars, scatter = self._kde_data(element, g, key, split_dim, split_cats, **kwargs) for k, v in segs.items(): seg_data[k] += v From e09581f2f21eba9be1a4010dca60dcd98383461f Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Wed, 16 Sep 2020 11:16:08 -0400 Subject: [PATCH 04/11] Fix doc building [doc-build] (#4614) * Rehash after install hoping it will discover firefox [doc-build] * Add firefox to travis build [doc-build] * Try to switch to chromedriver [doc-build] * Try different chromedriver [doc-build] * Start chrome headless [doc-build] * Install firefox [doc-build] * Removed chromedriver [doc-build] --- .travis.yml | 7 +++++++ setup.py | 3 --- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index f2719ea991..d06d27e7b5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,9 @@ os: dist: xenial +addons: + firefox: latest + notifications: email: on_failure: change # [always|never|change] default: always @@ -23,6 +26,7 @@ env: - CHANS="-c pyviz" - MPLBACKEND="Agg" - PYTHON_VERSION=3.7 + - MOZ_HEADLESS=1 stages: - test @@ -66,6 +70,7 @@ jobs: - source activate test-environment - travis_wait 30 doit develop_install $CHANS_DEV -o $HV_REQUIREMENTS - doit env_capture + - hash -r script: - doit test_all_recommended after_success: coveralls @@ -88,6 +93,8 @@ jobs: <<: *default stage: docs_dev env: DESC="docs" HV_DOC_GALLERY="false" HV_DOC_REF_GALLERY="true" HV_REQUIREMENTS="doc" PANEL_EMBED="true" PANEL_EMBED_JSON="true" PANEL_EMBED_JSON_PREFIX="json" CHANS_DEV="-c pyviz/label/dev -c bokeh -c conda-forge" + before-script: + - conda install -c conda-forge geckodriver selenium script: - bokeh sampledata - nbsite generate-rst --org pyviz --project-name holoviews --skip ^reference diff --git a/setup.py b/setup.py index 662362ea52..93c94f1136 100644 --- a/setup.py +++ b/setup.py @@ -100,10 +100,7 @@ 'awscli', 'pscript', 'graphviz', - 'selenium', 'bokeh <2.2', - 'firefox', - 'geckodriver', 'nbconvert <6.0', 'mpl_sample_data' ] From 6d20a0662b566079be7fa39cc6d47e79a99769e9 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Thu, 17 Sep 2020 06:24:14 -0400 Subject: [PATCH 05/11] Resolve other widget types (#4617) --- holoviews/core/util.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/holoviews/core/util.py b/holoviews/core/util.py index 10f34d74d6..fdd6024532 100644 --- a/holoviews/core/util.py +++ b/holoviews/core/util.py @@ -1544,10 +1544,16 @@ def resolve_dependent_value(value): A new dictionary where any parameter dependencies have been resolved. """ + range_widget = False if 'panel' in sys.modules: - from panel.widgets.base import Widget - if isinstance(value, Widget): - value = value.param.value + from panel.widgets import RangeSlider, Widget + range_widget = isinstance(value, RangeSlider) + try: + from panel.depends import param_value_if_widget + value = param_value_if_widget(value) + except Exception: + if isinstance(value, Widget): + value = value.param.value if is_param_method(value, has_deps=True): value = value() elif isinstance(value, param.Parameter) and isinstance(value.owner, param.Parameterized): @@ -1557,6 +1563,8 @@ def resolve_dependent_value(value): args = (getattr(p.owner, p.name) for p in deps.get('dependencies', [])) kwargs = {k: getattr(p.owner, p.name) for k, p in deps.get('kw', {}).items()} value = value(*args, **kwargs) + if isinstance(value, tuple) and range_widget: + value = slice(*value) return value From aa62f4da9bbd85b2c989869a986b398c0535e479 Mon Sep 17 00:00:00 2001 From: Jonathan deWerd Date: Thu, 17 Sep 2020 06:26:33 -0400 Subject: [PATCH 06/11] Do not reset removed handles (#4616) Co-authored-by: Jonathan deWerd --- holoviews/plotting/bokeh/callbacks.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/holoviews/plotting/bokeh/callbacks.py b/holoviews/plotting/bokeh/callbacks.py index 3fb83a63eb..02605f2900 100644 --- a/holoviews/plotting/bokeh/callbacks.py +++ b/holoviews/plotting/bokeh/callbacks.py @@ -111,6 +111,8 @@ def reset(self): if self.handle_ids: handles = self._init_plot_handles() for handle_name in self.models: + if not (handle_name in handles): + continue handle = handles[handle_name] cb_hash = (id(handle), id(type(self))) self._callbacks.pop(cb_hash, None) From 1548563a24b4c913e368b2a5dc0db123d6cd194a Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Thu, 17 Sep 2020 13:29:29 +0200 Subject: [PATCH 07/11] Initialize links on ElementPlot when it is top-level --- holoviews/plotting/bokeh/element.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/holoviews/plotting/bokeh/element.py b/holoviews/plotting/bokeh/element.py index 66f6a29dec..5bd65de50d 100644 --- a/holoviews/plotting/bokeh/element.py +++ b/holoviews/plotting/bokeh/element.py @@ -1380,6 +1380,9 @@ def initialize_plot(self, ranges=None, plot=None, plots=None, source=None): for cb in self.callbacks: cb.initialize() + if self.top_level: + self.init_links() + if not self.overlaid: self._set_active_tools(plot) self._process_legend() From f2fb5d4e3847dd220c508de04a98eecb6de07d64 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Fri, 18 Sep 2020 12:38:38 +0200 Subject: [PATCH 08/11] Add ability to listen to dataset linked_selection (#4547) * Add ability to listen to dataset linked_selection * Renamed to selection_param --- holoviews/selection.py | 61 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/holoviews/selection.py b/holoviews/selection.py index b6ac849250..098a920899 100644 --- a/holoviews/selection.py +++ b/holoviews/selection.py @@ -5,12 +5,13 @@ from param.parameterized import bothmethod +from .core.data import Dataset from .core.dimension import OrderedDict from .core.element import Element, Layout from .core.options import CallbackError, Store from .core.overlay import NdOverlay, Overlay from .core.spaces import GridSpace -from .streams import SelectionExpr, PlotReset, Stream, SelectMode +from .streams import SelectionExpr, Pipe, PlotReset, Stream, SelectMode from .util import DynamicMap from .util.transform import dim @@ -135,7 +136,7 @@ def _selection_transform(self, hvobj, operations=()): chart = Store.registry[Store.current_backend][hvobj.type] return chart.selection_display(hvobj).build_selection( self._selection_streams, hvobj, operations, - self._region_streams.get(hvobj, None), + self._region_streams.get(hvobj, None), cache=self._cache ) else: # This is a DynamicMap that we don't know how to recurse into. @@ -148,7 +149,7 @@ def _selection_transform(self, hvobj, operations=()): self._register(element) return chart.selection_display(element).build_selection( self._selection_streams, element, operations, - self._region_streams.get(element, None), + self._region_streams.get(element, None), cache=self._cache ) return hvobj elif isinstance(hvobj, (Layout, Overlay, NdOverlay, GridSpace)): @@ -246,8 +247,47 @@ def instance(self_or_cls, **params): inst._obj_regions = {} inst._reset_regions = True + # _datasets caches + inst._datasets = [] + inst._cache = {} + return inst + @param.depends('selection_expr', watch=True) + def _update_pipes(self): + sel_expr = self.selection_expr + for pipe, ds, raw in self._datasets: + ref = ds._plot_id + self._cache[ref] = ds_cache = self._cache.get(ref, {}) + if sel_expr in ds_cache: + data = ds_cache[sel_expr] + return pipe.event(data=data.data) + else: + ds_cache.clear() + sel_ds = SelectionDisplay._select(ds, sel_expr, self._cache) + ds_cache[sel_expr] = sel_ds + pipe.event(data=sel_ds.data if raw else sel_ds) + + def selection_param(self, data): + """ + Returns a parameter which reflects the current selection + when applied to the supplied data, making it easy to create + a callback which depends on the current selection. + + Args: + data: A Dataset type or data which can be cast to a Dataset + + Returns: + A parameter which reflects the current selection + """ + raw = False + if not isinstance(data, Dataset): + raw = True + data = Dataset(data) + pipe = Pipe(data=data.data) + self._datasets.append((pipe, data, raw)) + return pipe.param.data + @classmethod def _build_selection_streams(cls, inst): # Colors stream @@ -382,7 +422,7 @@ class SelectionDisplay(object): def __call__(self, element): return self - def build_selection(self, selection_streams, hvobj, operations, region_stream=None): + def build_selection(self, selection_streams, hvobj, operations, region_stream=None, cache={}): raise NotImplementedError() @staticmethod @@ -455,13 +495,12 @@ def __init__(self, color_prop='color', is_cmap=False, supports_region=True): self.color_props = color_prop self.is_cmap = is_cmap self.supports_region = supports_region - self._cache = {} def _get_color_kwarg(self, color): return {color_prop: [color] if self.is_cmap else color for color_prop in self.color_props} - def build_selection(self, selection_streams, hvobj, operations, region_stream=None): + def build_selection(self, selection_streams, hvobj, operations, region_stream=None, cache=None): from .element import Histogram num_layers = len(selection_streams.style_stream.colors) @@ -475,7 +514,7 @@ def build_selection(self, selection_streams, hvobj, operations, region_stream=No cmap_stream = selection_streams.cmap_streams[layer_number] layer = obj.apply( self._build_layer_callback, streams=[cmap_stream]+streams, - layer_number=layer_number, per_element=True + layer_number=layer_number, cache=cache, per_element=True ) layers.append(layer) @@ -516,8 +555,8 @@ def _inject_cmap_in_pipeline(cls, pipeline, cmap): operations.append(op) return pipeline.instance(operations=operations) - def _build_layer_callback(self, element, exprs, layer_number, cmap, **kwargs): - selection = self._select(element, exprs[layer_number], self._cache) + def _build_layer_callback(self, element, exprs, layer_number, cmap, cache, **kwargs): + selection = self._select(element, exprs[layer_number], cache) pipeline = element.pipeline if cmap is not None: pipeline = self._inject_cmap_in_pipeline(pipeline, cmap) @@ -555,7 +594,7 @@ def __init__(self, color_prop='color', alpha_prop='alpha', backend=None): self.alpha_props = [alpha_prop] self.backend = backend - def build_selection(self, selection_streams, hvobj, operations, region_stream=None): + def build_selection(self, selection_streams, hvobj, operations, region_stream=None, cache={}): def _build_selection(el, colors, alpha, exprs, **kwargs): from .plotting.util import linear_gradient ds = el.dataset @@ -582,7 +621,7 @@ def _build_selection(el, colors, alpha, exprs, **kwargs): return el.pipeline(ds).opts(backend=self.backend, clone=True, **color_opts) sel_streams = [selection_streams.style_stream, selection_streams.exprs_stream] - hvobj = hvobj.apply(_build_selection, streams=sel_streams, per_element=True) + hvobj = hvobj.apply(_build_selection, streams=sel_streams, per_element=True, cache=cache) for op in operations: hvobj = op(hvobj) From d67e2c5c5f64699d56baad2fcfbc0bafd94ade5b Mon Sep 17 00:00:00 2001 From: Bryan Van de Ven Date: Thu, 24 Sep 2020 08:18:20 -0700 Subject: [PATCH 09/11] CuDF Series is not iterable (#4624) --- holoviews/core/data/cudf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/holoviews/core/data/cudf.py b/holoviews/core/data/cudf.py index bc801e2b88..0f5687b8e5 100644 --- a/holoviews/core/data/cudf.py +++ b/holoviews/core/data/cudf.py @@ -163,7 +163,7 @@ def groupby(cls, dataset, dimensions, container_type, group_type, **kwargs): group_kwargs['dataset'] = dataset.dataset # Find all the keys along supplied dimensions - keys = product(*(dataset.data[dimensions[0]].unique() for d in dimensions)) + keys = product(*(dataset.data[dimensions[0]].unique().values_host for d in dimensions)) # Iterate over the unique entries applying selection masks grouped_data = [] From b1f1179a29cce368fb1f61566b18a2447405b5fe Mon Sep 17 00:00:00 2001 From: "James A. Bednar" Date: Thu, 24 Sep 2020 11:00:35 -0500 Subject: [PATCH 10/11] Fixes for various small docs and messages issues (#4628) * Fixed outdated pyviz references * Replaced old .options calls with .opts * Fixed typo * Removed stray markup and added QuadMesh to Continuous Coords * Clarified gridded error message --- .travis.yml | 2 +- doc/FAQ.rst | 14 +++++++------- examples/reference/elements/bokeh/Spread.ipynb | 2 +- .../reference/elements/matplotlib/Spread.ipynb | 2 +- examples/reference/elements/plotly/Spread.ipynb | 2 +- examples/user_guide/Continuous_Coordinates.ipynb | 4 +++- holoviews/element/raster.py | 10 ++++++---- 7 files changed, 20 insertions(+), 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index d06d27e7b5..c058b7d4f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -97,7 +97,7 @@ jobs: - conda install -c conda-forge geckodriver selenium script: - bokeh sampledata - - nbsite generate-rst --org pyviz --project-name holoviews --skip ^reference + - nbsite generate-rst --org holoviz --project-name holoviews --skip ^reference - python ./doc/generate_modules.py holoviews -d ./doc/reference_manual -n holoviews -e tests - nbsite build --what=html --output=builtdocs after_success: diff --git a/doc/FAQ.rst b/doc/FAQ.rst index f4bc86bb0e..f7aa290c60 100644 --- a/doc/FAQ.rst +++ b/doc/FAQ.rst @@ -62,7 +62,7 @@ set the ``xlim`` and ``ylim`` plot options: .. code:: python - hv.Curve(df, 'x_col', 'y_col').options(xlim=(0, None), ylim=(0, 10)) + hv.Curve(df, 'x_col', 'y_col').opts(xlim=(0, None), ylim=(0, 10)) This approach allows you to customize objects easily as a final step, but note that the values won't be applied to the underlying data, and thus won't be inherited if this object is subsequently used in an operation or data selection command. @@ -118,10 +118,10 @@ determine the appropriate axis range yourself and set that, e.g. with .. code:: python # for matplotlib: - hv_obj = hv_obj.options(fig_size=500) + hv_obj = hv_obj.opts(fig_size=500) # for bokeh: - hv_obj = hv_obj.options(width=1000, height=500) + hv_obj = hv_obj.opts(width=1000, height=500) **Q: How do I get a legend on my overlay figure?** @@ -184,7 +184,7 @@ plotted, instead consider that it is possible to write so called ``hooks``: # artist, axis, legend and in bokeh x_range, y_range, glyph, cds etc. plot.handles - hv.Curve(df, 'x_col', 'y_col').options(hooks=[hook]) + hv.Curve(df, 'x_col', 'y_col').opts(hooks=[hook]) These hooks can modify the backend specific representation, e.g. the matplotlib figure, before it is displayed, allowing arbitrary customizations to be @@ -229,7 +229,7 @@ for that HoloViews object: b.axis[0].ticker = FixedTicker(ticks=list(range(0, 10))) h = hv.Curve([1,2,7], 'x_col', 'y_col') - h = h.options(hooks=[update_axis]) + h = h.opts(hooks=[update_axis]) h Here, you've wrapped your Bokeh-API calls into a function, then @@ -360,7 +360,7 @@ they don't get applied until the object is returned (during IPython's "display hooks" processing). So to make sure that options get applied, (a) return the object from a cell, and then (b) access it (e.g. for exporting) after the object has been returned. -To avoid confusion, you may prefer to use .options() directly on the +To avoid confusion, you may prefer to use .opts() directly on the object to ensure that the options have been applied before exporting. Example code below: @@ -451,7 +451,7 @@ element: hv.extension('matplotlib') Store.add_style_opts(hv.Image, ['filternorm'], backend='matplotlib') -Now you can freely use ``'filternorm'`` in ``.options()`` and in the +Now you can freely use ``'filternorm'`` in ``.opts()`` and in the ``%opts`` line/cell magic, including tab-completion! diff --git a/examples/reference/elements/bokeh/Spread.ipynb b/examples/reference/elements/bokeh/Spread.ipynb index 2b3d8253b5..0b70f1c228 100644 --- a/examples/reference/elements/bokeh/Spread.ipynb +++ b/examples/reference/elements/bokeh/Spread.ipynb @@ -33,7 +33,7 @@ "source": [ "``Spread`` elements have the same data format as the [``ErrorBars``](ErrorBars.ipynb) element, namely x- and y-values with associated symmetric or asymmetric errors, but are interpreted as samples from a continuous distribution (just as ``Curve`` is the continuous version of ``Scatter``). These are often paired with an overlaid ``Curve`` to show an average trend along with a corresponding spread of values; see the [Tabular Datasets](../../../user_guide/08-Tabular_Datasets.ipynb) user guide for examples. \n", "\n", - "Note that as the ``Spread`` element is used to add information to a plot (typically a ``Curve``) the default alpha value is less that one, making it partially transparent. \n", + "Note that as the ``Spread`` element is used to add information to a plot (typically a ``Curve``) the default alpha value is less than one, making it partially transparent. \n", "\n", "\n", "##### Symmetric" diff --git a/examples/reference/elements/matplotlib/Spread.ipynb b/examples/reference/elements/matplotlib/Spread.ipynb index cf2c028093..8a1a0b9bd5 100644 --- a/examples/reference/elements/matplotlib/Spread.ipynb +++ b/examples/reference/elements/matplotlib/Spread.ipynb @@ -33,7 +33,7 @@ "source": [ "``Spread`` elements have the same data format as the [``ErrorBars``](ErrorBars.ipynb) element, namely x- and y-values with associated symmetric or asymmetric errors, but are interpreted as samples from a continuous distribution (just as ``Curve`` is the continuous version of ``Scatter``). These are often paired with an overlaid ``Curve`` to show an average trend along with a corresponding spread of values; see the [Tabular Datasets](../../../user_guide/07-Tabular_Datasets.ipynb) user guide for examples.\n", "\n", - "Note that as the ``Spread`` element is used to add information to a plot (typically a ``Curve``) the default alpha value is less that one, making it partially transparent. \n", + "Note that as the ``Spread`` element is used to add information to a plot (typically a ``Curve``) the default alpha value is less than one, making it partially transparent. \n", "\n", "##### Symmetric" ] diff --git a/examples/reference/elements/plotly/Spread.ipynb b/examples/reference/elements/plotly/Spread.ipynb index b1b701579a..1b95e61c29 100644 --- a/examples/reference/elements/plotly/Spread.ipynb +++ b/examples/reference/elements/plotly/Spread.ipynb @@ -30,7 +30,7 @@ "source": [ "``Spread`` elements have the same data format as the [``ErrorBars``](ErrorBars.ipynb) element, namely x- and y-values with associated symmetric or asymmetric errors, but are interpreted as samples from a continuous distribution (just as ``Curve`` is the continuous version of ``Scatter``). These are often paired with an overlaid ``Curve`` to show an average trend along with a corresponding spread of values; see the [Tabular Datasets](../../../user_guide/08-Tabular_Datasets.ipynb) user guide for examples. \n", "\n", - "Note that as the ``Spread`` element is used to add information to a plot (typically a ``Curve``) the default alpha value is less that one, making it partially transparent. \n", + "Note that as the ``Spread`` element is used to add information to a plot (typically a ``Curve``) the default alpha value is less than one, making it partially transparent. \n", "\n", "\n", "##### Symmetric" diff --git a/examples/user_guide/Continuous_Coordinates.ipynb b/examples/user_guide/Continuous_Coordinates.ipynb index 47a069a5b8..2684232c43 100644 --- a/examples/user_guide/Continuous_Coordinates.ipynb +++ b/examples/user_guide/Continuous_Coordinates.ipynb @@ -53,7 +53,7 @@ "|||\n", "|:--------------:|:----------------|\n", "| **``f(x,y)``** | a simple function that accepts a location in a 2D plane specified in millimeters (mm) |\n", - "| **``region``** | a 1mm×1mm square region of this 2D plane, centered at the origin, and |\n", + "| **``region``** | a 1mm×1mm square region of this 2D plane, centered at the origin, and |\n", "| **``coords``** | a function returning a square (s×s) grid of (x,y) coordinates regularly sampling the region in the given bounds, at the centers of each grid cell |\n", "||||\n", "\n" @@ -332,6 +332,8 @@ "\n", "They also work the same for the n-dimensional coordinates and slicing supported by the [container](Containers) types ``HoloMap``, ``NdLayout``, and ``NdOverlay``, implemented in ``holoviews.core.dimension.Dimensioned`` and again allowing arbitrary irregular spacing. \n", "\n", + "``QuadMesh`` elements are similar but allow more general types of mapping between the underlying array and the continuous space, with arbitrary spacing along each of the axes or even over the entire array. See the ``QuadMesh`` element for more details.\n", + "\n", "Together, these powerful continuous-coordinate indexing and slicing operations allow you to work naturally and simply in the full *n*-dimensional space that characterizes your data and parameter values." ] }, diff --git a/holoviews/element/raster.py b/holoviews/element/raster.py index 1069b047a0..fc3e2e6f9e 100644 --- a/holoviews/element/raster.py +++ b/holoviews/element/raster.py @@ -291,9 +291,10 @@ 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("%s type expects gridded data, %s is columnar." + raise DataError("%s type expects gridded data, %s is columnar. " "To display columnar data as gridded use the HeatMap " - "element or aggregate the data." % + "element or aggregate the data (e.g. using rasterize " + "or np.histogram2d)." % (type(self).__name__, self.interface.__name__)) dim2, dim1 = self.interface.shape(self, gridded=True)[:2] @@ -783,9 +784,10 @@ def __init__(self, data, kdims=None, vdims=None, **params): data = ([], [], np.zeros((0, 0))) super(QuadMesh, self).__init__(data, kdims, vdims, **params) if not self.interface.gridded: - raise DataError("%s type expects gridded data, %s is columnar." + raise DataError("%s type expects gridded data, %s is columnar. " "To display columnar data as gridded use the HeatMap " - "element or aggregate the data." % + "element or aggregate the data (e.g. using " + "np.histogram2d)." % (type(self).__name__, self.interface.__name__)) From 8f7c67f70d401cf901889a2909206f582f8e8c61 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Fri, 25 Sep 2020 12:56:14 +0200 Subject: [PATCH 11/11] Fixed deserialization of polygon/multi_line CDS data in bokeh (#4631) --- holoviews/plotting/bokeh/callbacks.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/holoviews/plotting/bokeh/callbacks.py b/holoviews/plotting/bokeh/callbacks.py index 02605f2900..9eb35b157d 100644 --- a/holoviews/plotting/bokeh/callbacks.py +++ b/holoviews/plotting/bokeh/callbacks.py @@ -1200,8 +1200,14 @@ def _process_msg(self, msg): new_values = [] for vals in values: if isinstance(vals, dict): + + shape = vals.pop('shape', None) + dtype = vals.pop('dtype', None) + vals.pop('dimension', None) vals = sorted([(int(k), v) for k, v in vals.items()]) vals = [v for k, v in vals] + if dtype is not None: + vals = np.array(vals, dtype=dtype).reshape(shape) new_values.append(vals) values = new_values elif any(isinstance(v, (int, float)) for v in values):