diff --git a/holoviews/plotting/bokeh/element.py b/holoviews/plotting/bokeh/element.py index 527d996b4d..5069a33945 100644 --- a/holoviews/plotting/bokeh/element.py +++ b/holoviews/plotting/bokeh/element.py @@ -378,6 +378,8 @@ def _axes_props(self, plots, subplots, element, ranges): # Get the bottom layer and range element el = element.traverse(lambda x: x, [lambda el: isinstance(el, Element) and not isinstance(el, (Annotation, Tiles))]) el = el[0] if el else element + if isinstance(el, Graph): + el = el.nodes dims = self._get_axis_dims(el) xlabel, ylabel, zlabel = self._get_axis_labels(dims) @@ -424,10 +426,7 @@ def _axes_props(self, plots, subplots, element, ranges): x_axis_type = 'auto' categorical_x = True else: - if isinstance(el, Graph): - xtype = el.nodes.get_dimension_type(xdims[0]) - else: - xtype = el.get_dimension_type(xdims[0]) + xtype = el.get_dimension_type(xdims[0]) if ((xtype is np.object_ and issubclass(type(l), util.datetime_types)) or xtype in util.datetime_types): x_axis_type = 'datetime' diff --git a/holoviews/plotting/bokeh/graphs.py b/holoviews/plotting/bokeh/graphs.py index e893e6abbd..2a493af3e3 100644 --- a/holoviews/plotting/bokeh/graphs.py +++ b/holoviews/plotting/bokeh/graphs.py @@ -4,12 +4,15 @@ import param import numpy as np -from bokeh.models import (StaticLayoutProvider, NodesAndLinkedEdges, - EdgesAndLinkedNodes, Patches, Bezier, ColumnDataSource) +from bokeh.models import ( + StaticLayoutProvider, NodesAndLinkedEdges, EdgesAndLinkedNodes, + Patches, Bezier, ColumnDataSource, NodesOnly +) from ...core.data import Dataset from ...core.options import Cycle, abbreviated_exception from ...core.util import basestring, dimension_sanitizer, unique_array +from ...element import Graph from ...util.transform import dim from ..mixins import ChordMixin from ..util import process_cmap, get_directed_graph_paths @@ -99,7 +102,9 @@ def get_extents(self, element, ranges, range_type='combined'): def _get_axis_dims(self, element): - return element.nodes.dimensions()[:2] + if isinstance(element, Graph): + element = element.nodes + return element.dimensions()[:2] def _get_edge_colors(self, element, ranges, edge_data, edge_mapping, style): @@ -328,14 +333,14 @@ def _set_interaction_policies(self, renderer): elif self.selection_policy == 'edges': renderer.selection_policy = EdgesAndLinkedNodes() else: - renderer.selection_policy = None + renderer.selection_policy = NodesOnly() if self.inspection_policy == 'nodes': renderer.inspection_policy = NodesAndLinkedEdges() elif self.inspection_policy == 'edges': renderer.inspection_policy = EdgesAndLinkedNodes() else: - renderer.inspection_policy = None + renderer.inspection_policy = NodesOnly() def _init_glyphs(self, plot, element, ranges, source): # Get data and initialize data source diff --git a/holoviews/tests/plotting/bokeh/testgraphplot.py b/holoviews/tests/plotting/bokeh/testgraphplot.py index 63bad0ec50..fe2d1f18c7 100644 --- a/holoviews/tests/plotting/bokeh/testgraphplot.py +++ b/holoviews/tests/plotting/bokeh/testgraphplot.py @@ -2,11 +2,11 @@ import numpy as np from holoviews.core.data import Dataset -from holoviews.element import Graph, Nodes, TriMesh, Chord, circular_layout +from holoviews.element import Graph, Nodes, TriMesh, Chord, VLine, circular_layout from holoviews.util.transform import dim try: - from bokeh.models import (NodesAndLinkedEdges, EdgesAndLinkedNodes, Patches) + from bokeh.models import (NodesAndLinkedEdges, EdgesAndLinkedNodes, NodesOnly, Patches) from bokeh.models.mappers import CategoricalColorMapper, LinearColorMapper except: pass @@ -42,6 +42,15 @@ def test_plot_simple_graph(self): layout = {str(int(z)): (x, y) for x, y, z in self.graph.nodes.array()} self.assertEqual(layout_source.graph_layout, layout) + def test_plot_graph_annotation_overlay(self): + plot = bokeh_renderer.get_plot(VLine(0) * self.graph) + x_range = plot.handles['x_range'] + y_range = plot.handles['x_range'] + self.assertEqual(x_range.start, -1) + self.assertEqual(x_range.end, 1) + self.assertEqual(y_range.start, -1) + self.assertEqual(y_range.end, 1) + def test_plot_graph_with_paths(self): graph = self.graph.clone((self.graph.data, self.graph.nodes, self.graph.edgepaths)) plot = bokeh_renderer.get_plot(graph) @@ -85,7 +94,7 @@ def test_graph_inspection_policy_edges_non_default_names(self): def test_graph_inspection_policy_none(self): plot = bokeh_renderer.get_plot(self.graph.opts(plot=dict(inspection_policy=None))) renderer = plot.handles['glyph_renderer'] - self.assertIs(renderer.inspection_policy, None) + self.assertIsInstance(renderer.inspection_policy, NodesOnly) def test_graph_selection_policy_nodes(self): plot = bokeh_renderer.get_plot(self.graph) @@ -104,7 +113,7 @@ def test_graph_selection_policy_edges(self): def test_graph_selection_policy_none(self): plot = bokeh_renderer.get_plot(self.graph.opts(plot=dict(selection_policy=None))) renderer = plot.handles['glyph_renderer'] - self.assertIs(renderer.selection_policy, None) + self.assertIsInstance(renderer.selection_policy, NodesOnly) def test_graph_nodes_categorical_colormapped(self): g = self.graph2.opts(plot=dict(color_index='Label'), style=dict(cmap='Set1'))