Exception: "None of the available storage backends were able to support the supplied data format."
I try to use hvplot.networkx from hvplot version 0.5.2 with bokeh to visualize a network graph.
This is code that works: a simple graph is created using networkx, and some attributes are added to the graph nodes, then hvplot is used to show the graph and show hover tooltips from the attributes:
import networkx as nx
import hvplot.networkx as hvnx
nodes = [1,2,3,4,5,6,7,8,9,10]
edges = [(1,2), (1,3), (1,4), (4,5), (4,3), (8,9), (8,7), (7,6)]
nxg1 = nx.Graph()
nxg1.add_nodes_from(nodes)
nxg1.add_edges_from(edges)
pos = nx.spring_layout(nxg1)
# some attributes for the nodes
for node in nxg1.nodes:
nxg1.nodes[node]["label"] = f"Node{node}"
nxg1.nodes[node]["desc"] = "some description"
hvnx.draw(nxg1, pos, hover_cols="all")
The following code throws the exception: here the node has an attribute "x" (or "y", but "z" is ok):
import networkx as nx
import hvplot.networkx as hvnx
nodes = [1,2,3,4,5,6,7,8,9,10]
edges = [(1,2), (1,3), (1,4), (4,5), (4,3), (8,9), (8,7), (7,6)]
nxg1 = nx.Graph()
nxg1.add_nodes_from(nodes)
nxg1.add_edges_from(edges)
pos = nx.spring_layout(nxg1)
# some attributes for the nodes
for node in nxg1.nodes:
nxg1.nodes[node]["label"] = f"Node{node}"
nxg1.nodes[node]["desc"] = "some description"
nxg1.nodes[node]["x"] = pos[node][0]
nxg1.nodes[node]["y"] = pos[node][1]
hvnx.draw(nxg1, pos, hover_cols="all")
Exception:
DataError Traceback (most recent call last)
<ipython-input-7-930eafbe4a1f> in <module>
16 nxg1.nodes[node]["x"] = pos[node][0]
17 nxg1.nodes[node]["x"] = pos[node][1]
---> 18 hvnx.draw(nxg1, pos, hover_cols="all")
~/software/anaconda/envs/polads/lib/python3.6/site-packages/hvplot/networkx.py in draw(G, pos, **kwargs)
223
224 # Construct Graph object
--> 225 g = _from_networkx(G, pos, **params)
226
227 if 'nodelist' in kwargs:
~/software/anaconda/envs/polads/lib/python3.6/site-packages/hvplot/networkx.py in _from_networkx(G, positions, nodes, cls, **kwargs)
107 dim = col
108 vdims.append(dim)
--> 109 nodes = cls.node_type(node_data, vdims=vdims)
110
111 # Construct graph
~/software/anaconda/envs/polads/lib/python3.6/site-packages/holoviews/core/data/__init__.py in __init__(self, data, kdims, vdims, **kwargs)
337 validate_vdims = kwargs.pop('_validate_vdims', True)
338 initialized = Interface.initialize(type(self), data, kdims, vdims,
--> 339 datatype=kwargs.get('datatype'))
340 (data, self.interface, dims, extra_kws) = initialized
341 super(Dataset, self).__init__(data, **dict(kwargs, **dict(dims, **extra_kws)))
~/software/anaconda/envs/polads/lib/python3.6/site-packages/holoviews/core/data/interface.py in initialize(cls, eltype, data, kdims, vdims, datatype)
290 error = ' '.join([error, priority_error])
291 raise six.reraise(DataError, DataError(error, intfc), sys.exc_info()[2])
--> 292 raise DataError(error)
293
294 return data, interface, dims, extra_kws
DataError: None of the available storage backends were able to support the supplied data format.
Why is "x" or "y" not usable as an attribute, are there other names that would not work and if there are reserved names, could the error message be more informative?
This will require some thought your intuition about the cause here is correct in that 'x' and 'y' are the default dimensions describing the positions of the nodes and are therefore reserved by default. We will have to consider where to add a better error and/or whether to use default dimension names which are not going to clash.
As the example shows, the values of the x and y attributes actually are the positions that would get pased on as pos to the draw function. So in this case, the draw function could just use the x and y attributes and it seems natural to do this, so it would be good to allow something like pos=("x","y") to retrieve the positions directly from the nodes instead of from a separate data structure.
If the draw function needs to use some names for x and y for the internal data structure which should not clash with names derived from the nodes, then some scheme for reserved names would be good, e.g. "__x" and "__y" or "__name" in general. It could then be documented that attributes starting with a double underscore cannot be used.