hvplot icon indicating copy to clipboard operation
hvplot copied to clipboard

Exception: "None of the available storage backends were able to support the supplied data format."

Open johann-petrak opened this issue 5 years ago • 2 comments

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?

johann-petrak avatar May 28 '20 21:05 johann-petrak

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.

philippjfr avatar Jun 01 '20 21:06 philippjfr

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.

johann-petrak avatar Jun 02 '20 13:06 johann-petrak