HyperNetX + Graphistry = 💪💪💪

HyperNetX + Graphistry = 💪💪💪#

You can quickly explore HyperNetX graphs using Graphistry through the below sample class.

PNNL’s HyperNetX is a new Python library for manipulating hypergraphs: graphs where an edge may connect any number of nodes. The below helper class converts HyperNetX graphs into 2-edge graphs (node/edge property tables as Panda dataframes ) in two different modes:

  • hypernetx_to_graphistry_bipartite(hnx_graph):

    • Turn every hyperedge and hypernode into nodes. They form a bipartite graph: whenever a hyperedge includes a hypernode, create an edge from the hyperedge’s node to the hypernode’s node.

    • ex: Hyperedge 0: ['a', 'b', 'c'] => edge (0, 'a'), edge (0, 'b'), edge (0, 'c')

  • hypernetx_to_graphistry_nodes(hnx_graph):

    • Turn every hypernode into a node, and whenever two hypernodes share the same hyperedge, create an edge between their corresponding nodes

    • To emphasize that edges are undirect, the library sets the edge curvature to 0 (straight)

    • ex: Hyperedge 0: ['a', 'b', 'c'] => edge ('a', 'b'), edge ('a', 'c'), edge ('b', 'c')

Install#

Dependencies already preinstalled in Graphistry Core distributions

[1]:
# ! pip install hypernetx -q
# ! pip install graphistry -q

Lib#

[2]:
import pandas as pd

class HyperNetXG:

    def __init__(self, graphistry):
        self.graphistry = graphistry

    def normalize_id(self, id):
        t = type(id)
        if t == float or t == int:
            return '__id__' + str(id)
        return str(id)


    def hypernetx_to_graphistry_bipartite(self, h):

        nodes_df = pd.concat(
            [pd.DataFrame({
                'node': [self.normalize_id(x) for x in list(H.nodes)],
                'type': 'hypernode'}),
             pd.DataFrame({
                 'node': [self.normalize_id(x) for x in H.edges],
                 'type': 'hyperedge'})],
            ignore_index=True,
            sort=False)

        edges_df = pd.concat(
            [ pd.DataFrame({'src': [], 'dst': []}) ] +
            [
                pd.DataFrame({
                    'src': self.normalize_id(k),
                    'dst': [self.normalize_id(x) for x in list(es)]
                })
                for k, es in H.incidence_dict.items()
            ], ignore_index=True, sort=False)

        return self.graphistry.bind(
              source='src',
              destination='dst',
              node='node').nodes(nodes_df).edges(edges_df)


    def __hyperedge_to_graph(self, k, es):
        lst = list(es)
        edges_df = pd.concat([
              pd.DataFrame({'src': [], 'dst': [], 'hyperedge': []})] + [
              pd.DataFrame({
                  'src': self.normalize_id(lst[i]),
                  'dst': [self.normalize_id(x) for x in lst[i+1:]],
                  'hyperedge': self.normalize_id(k)})
              for i in range(0, len(lst))
          ], ignore_index=True, sort=False)
        return edges_df

    def hypernetx_to_graphistry_nodes(self, h):
        hg = self.hypernetx_to_graphistry_bipartite(h)
        nodes_df = pd.DataFrame({
              'node': [self.normalize_id(x) for x in list(h.nodes)],
              'type': 'hypernode'})
        edges_df = pd.concat(
              [pd.DataFrame({'src': [], 'dst': [], 'hyperedge': []})] +
              [
                  self.__hyperedge_to_graph(k, es)
                  for (k, es) in h.incidence_dict.items()
              ])
        return self.graphistry.bind(
              source='src',
              destination='dst',
              node='node').settings(url_params={'edgeCurvature': 0}).nodes(nodes_df).edges(edges_df)

Demo#

Init#

[3]:
import hypernetx as hnx
import graphistry

# To specify Graphistry account & server, use:
# graphistry.register(api=3, username='...', password='...', protocol='https', server='hub.graphistry.com')
# For more options, see https://github.com/graphistry/pygraphistry#configure

scenes = [
    ('FN', 'TH'),
    ('TH', 'JV'),
    ('BM', 'FN', 'JA'),
    ('JV', 'JU', 'CH', 'BM'),
    ('JU', 'CH', 'BR', 'CN', 'CC', 'JV', 'BM'),
    ('TH', 'GP'),
    ('GP', 'MP'),
    ('MA', 'GP')
]

H = hnx.Hypergraph(dict(enumerate(scenes)))
hg = HyperNetXG(graphistry)

hypernetx_to_graphistry_bipartite#

Flatten to Pandas Dataframes / Graphistry and inspect:

[4]:
g = hg.hypernetx_to_graphistry_bipartite(H)
g._nodes.sample(3)
[4]:
node type
18 __id__5 hyperedge
17 __id__4 hyperedge
15 __id__2 hyperedge
[5]:
g._edges.sample(3)
[5]:
src dst
18 __id__5 TH
20 __id__6 MP
10 __id__3 CH
[6]:
g.plot()
[6]:
[7]:
hg.hypernetx_to_graphistry_bipartite(H.dual())._edges.sample(3)
[7]:
src dst
16 __id__4 CN
17 __id__4 BR
14 __id__4 BM
[8]:
hg.hypernetx_to_graphistry_bipartite(H.dual()).plot()
[8]:

hypernetx_to_graphistry_nodes#

[9]:
g = hg.hypernetx_to_graphistry_nodes(H)
g._edges.sample(3)
[9]:
src dst hyperedge
16 BM CN __id__4
0 JA BM __id__2
2 JU CH __id__3
[10]:
hg.hypernetx_to_graphistry_nodes(H).plot()
[10]:
[11]:
hg.hypernetx_to_graphistry_nodes(H.dual()).plot()
[11]: