Statistics
| Branch: | Revision:

iof-tools / networkxMiCe / networkx-master / networkx / readwrite / json_graph / node_link.py @ 5cef0f13

History | View | Annotate | Download (5.82 KB)

1
#    Copyright (C) 2011-2019 by
2
#
3
#    Aric Hagberg <hagberg@lanl.gov>
4
#    Dan Schult <dschult@colgate.edu>
5
#    Pieter Swart <swart@lanl.gov>
6
#    Michael E. Rose <Michael.Ernst.Rose@gmail.com>
7
#
8
#    All rights reserved.
9
#    BSD license.
10
from itertools import chain, count
11
import networkx as nx
12
from networkx.utils import make_str, to_tuple
13
__all__ = ['node_link_data', 'node_link_graph']
14

    
15

    
16
_attrs = dict(source='source', target='target', name='id',
17
              key='key', link='links')
18

    
19

    
20
def node_link_data(G, attrs=None):
21
    """Returns data in node-link format that is suitable for JSON serialization
22
    and use in Javascript documents.
23

24
    Parameters
25
    ----------
26
    G : NetworkX graph
27

28
    attrs : dict
29
        A dictionary that contains five keys 'source', 'target', 'name',
30
        'key' and 'link'.  The corresponding values provide the attribute
31
        names for storing NetworkX-internal graph data.  The values should
32
        be unique.  Default value::
33

34
            dict(source='source', target='target', name='id',
35
                 key='key', link='links')
36

37
        If some user-defined graph data use these attribute names as data keys,
38
        they may be silently dropped.
39

40
    Returns
41
    -------
42
    data : dict
43
       A dictionary with node-link formatted data.
44

45
    Raises
46
    ------
47
    NetworkXError
48
        If values in attrs are not unique.
49

50
    Examples
51
    --------
52
    >>> from networkx.readwrite import json_graph
53
    >>> G = nx.Graph([('A', 'B')])
54
    >>> data1 = json_graph.node_link_data(G)
55
    >>> H = nx.gn_graph(2)
56
    >>> data2 = json_graph.node_link_data(H, {'link': 'edges', 'source': 'from', 'target': 'to'})
57

58
    To serialize with json
59

60
    >>> import json
61
    >>> s1 = json.dumps(data1)
62
    >>> s2 = json.dumps(data2, default={'link': 'edges', 'source': 'from', 'target': 'to'})
63

64
    Notes
65
    -----
66
    Graph, node, and link attributes are stored in this format.  Note that
67
    attribute keys will be converted to strings in order to comply with JSON.
68

69
    Attribute 'key' is only used for multigraphs.
70

71
    See Also
72
    --------
73
    node_link_graph, adjacency_data, tree_data
74
    """
75
    multigraph = G.is_multigraph()
76
    # Allow 'attrs' to keep default values.
77
    if attrs is None:
78
        attrs = _attrs
79
    else:
80
        attrs.update({k: v for (k, v) in _attrs.items() if k not in attrs})
81
    name = attrs['name']
82
    source = attrs['source']
83
    target = attrs['target']
84
    links = attrs['link']
85
    # Allow 'key' to be omitted from attrs if the graph is not a multigraph.
86
    key = None if not multigraph else attrs['key']
87
    if len({source, target, key}) < 3:
88
        raise nx.NetworkXError('Attribute names are not unique.')
89
    data = {'directed': G.is_directed(), 'multigraph': multigraph, 'graph': G.graph,
90
            'nodes': [dict(chain(G.nodes[n].items(), [(name, n)])) for n in G]}
91
    if multigraph:
92
        data[links] = [
93
            dict(chain(d.items(),
94
                       [(source, u), (target, v), (key, k)]))
95
            for u, v, k, d in G.edges(keys=True, data=True)]
96
    else:
97
        data[links] = [
98
            dict(chain(d.items(),
99
                       [(source, u), (target, v)]))
100
            for u, v, d in G.edges(data=True)]
101
    return data
102

    
103

    
104
def node_link_graph(data, directed=False, multigraph=True, attrs=None):
105
    """Returns graph from node-link data format.
106

107
    Parameters
108
    ----------
109
    data : dict
110
        node-link formatted graph data
111

112
    directed : bool
113
        If True, and direction not specified in data, return a directed graph.
114

115
    multigraph : bool
116
        If True, and multigraph not specified in data, return a multigraph.
117

118
    attrs : dict
119
        A dictionary that contains five keys 'source', 'target', 'name',
120
        'key' and 'link'.  The corresponding values provide the attribute
121
        names for storing NetworkX-internal graph data.  Default value:
122

123
            dict(source='source', target='target', name='id',
124
                key='key', link='links')
125

126
    Returns
127
    -------
128
    G : NetworkX graph
129
        A NetworkX graph object
130

131
    Examples
132
    --------
133
    >>> from networkx.readwrite import json_graph
134
    >>> G = nx.Graph([('A', 'B')])
135
    >>> data = json_graph.node_link_data(G)
136
    >>> H = json_graph.node_link_graph(data)
137

138
    Notes
139
    -----
140
    Attribute 'key' is only used for multigraphs.
141

142
    See Also
143
    --------
144
    node_link_data, adjacency_data, tree_data
145
    """
146
    # Allow 'attrs' to keep default values.
147
    if attrs is None:
148
        attrs = _attrs
149
    else:
150
        attrs.update({k: v for k, v in _attrs.items() if k not in attrs})
151
    multigraph = data.get('multigraph', multigraph)
152
    directed = data.get('directed', directed)
153
    if multigraph:
154
        graph = nx.MultiGraph()
155
    else:
156
        graph = nx.Graph()
157
    if directed:
158
        graph = graph.to_directed()
159
    name = attrs['name']
160
    source = attrs['source']
161
    target = attrs['target']
162
    links = attrs['link']
163
    # Allow 'key' to be omitted from attrs if the graph is not a multigraph.
164
    key = None if not multigraph else attrs['key']
165
    graph.graph = data.get('graph', {})
166
    c = count()
167
    for d in data['nodes']:
168
        node = to_tuple(d.get(name, next(c)))
169
        nodedata = dict((make_str(k), v) for k, v in d.items() if k != name)
170
        graph.add_node(node, **nodedata)
171
    for d in data[links]:
172
        src = tuple(d[source]) if isinstance(d[source], list) else d[source]
173
        tgt = tuple(d[target]) if isinstance(d[target], list) else d[target]
174
        if not multigraph:
175
            edgedata = dict((make_str(k), v) for k, v in d.items()
176
                            if k != source and k != target)
177
            graph.add_edge(src, tgt, **edgedata)
178
        else:
179
            ky = d.get(key, None)
180
            edgedata = dict((make_str(k), v) for k, v in d.items()
181
                            if k != source and k != target and k != key)
182
            graph.add_edge(src, tgt, ky, **edgedata)
183
    return graph