comparison env/lib/python3.7/site-packages/networkx/readwrite/pajek.py @ 5:9b1c78e6ba9c draft default tip

"planemo upload commit 6c0a8142489327ece472c84e558c47da711a9142"
author shellac
date Mon, 01 Jun 2020 08:59:25 -0400
parents 79f47841a781
children
comparison
equal deleted inserted replaced
4:79f47841a781 5:9b1c78e6ba9c
1 # Copyright (C) 2008-2014 by
2 # Aric Hagberg <hagberg@lanl.gov>
3 # Dan Schult <dschult@colgate.edu>
4 # Pieter Swart <swart@lanl.gov>
5 # All rights reserved.
6 # BSD license.
7 #
8 # Authors: Aric Hagberg (hagberg@lanl.gov)
9 """
10 *****
11 Pajek
12 *****
13 Read graphs in Pajek format.
14
15 This implementation handles directed and undirected graphs including
16 those with self loops and parallel edges.
17
18 Format
19 ------
20 See http://vlado.fmf.uni-lj.si/pub/networks/pajek/doc/draweps.htm
21 for format information.
22
23 """
24
25 import warnings
26
27 import networkx as nx
28 from networkx.utils import is_string_like, open_file, make_str
29
30 __all__ = ['read_pajek', 'parse_pajek', 'generate_pajek', 'write_pajek']
31
32
33 def generate_pajek(G):
34 """Generate lines in Pajek graph format.
35
36 Parameters
37 ----------
38 G : graph
39 A Networkx graph
40
41 References
42 ----------
43 See http://vlado.fmf.uni-lj.si/pub/networks/pajek/doc/draweps.htm
44 for format information.
45 """
46 if G.name == '':
47 name = 'NetworkX'
48 else:
49 name = G.name
50 # Apparently many Pajek format readers can't process this line
51 # So we'll leave it out for now.
52 # yield '*network %s'%name
53
54 # write nodes with attributes
55 yield '*vertices %s' % (G.order())
56 nodes = list(G)
57 # make dictionary mapping nodes to integers
58 nodenumber = dict(zip(nodes, range(1, len(nodes) + 1)))
59 for n in nodes:
60 # copy node attributes and pop mandatory attributes
61 # to avoid duplication.
62 na = G.nodes.get(n, {}).copy()
63 x = na.pop('x', 0.0)
64 y = na.pop('y', 0.0)
65 id = int(na.pop('id', nodenumber[n]))
66 nodenumber[n] = id
67 shape = na.pop('shape', 'ellipse')
68 s = ' '.join(map(make_qstr, (id, n, x, y, shape)))
69 # only optional attributes are left in na.
70 for k, v in na.items():
71 if is_string_like(v) and v.strip() != '':
72 s += ' %s %s' % (make_qstr(k), make_qstr(v))
73 else:
74 warnings.warn('Node attribute %s is not processed. %s.' %
75 (k,
76 'Empty attribute' if is_string_like(v) else
77 'Non-string attribute'))
78 yield s
79
80 # write edges with attributes
81 if G.is_directed():
82 yield '*arcs'
83 else:
84 yield '*edges'
85 for u, v, edgedata in G.edges(data=True):
86 d = edgedata.copy()
87 value = d.pop('weight', 1.0) # use 1 as default edge value
88 s = ' '.join(map(make_qstr, (nodenumber[u], nodenumber[v], value)))
89 for k, v in d.items():
90 if is_string_like(v) and v.strip() != '':
91 s += ' %s %s' % (make_qstr(k), make_qstr(v))
92 else:
93 warnings.warn('Edge attribute %s is not processed. %s.' %
94 (k,
95 'Empty attribute' if is_string_like(v) else
96 'Non-string attribute'))
97 yield s
98
99
100 @open_file(1, mode='wb')
101 def write_pajek(G, path, encoding='UTF-8'):
102 """Write graph in Pajek format to path.
103
104 Parameters
105 ----------
106 G : graph
107 A Networkx graph
108 path : file or string
109 File or filename to write.
110 Filenames ending in .gz or .bz2 will be compressed.
111
112 Examples
113 --------
114 >>> G=nx.path_graph(4)
115 >>> nx.write_pajek(G, "test.net")
116
117 Warnings
118 --------
119 Optional node attributes and edge attributes must be non-empty strings.
120 Otherwise it will not be written into the file. You will need to
121 convert those attributes to strings if you want to keep them.
122
123 References
124 ----------
125 See http://vlado.fmf.uni-lj.si/pub/networks/pajek/doc/draweps.htm
126 for format information.
127 """
128 for line in generate_pajek(G):
129 line += '\n'
130 path.write(line.encode(encoding))
131
132
133 @open_file(0, mode='rb')
134 def read_pajek(path, encoding='UTF-8'):
135 """Read graph in Pajek format from path.
136
137 Parameters
138 ----------
139 path : file or string
140 File or filename to write.
141 Filenames ending in .gz or .bz2 will be uncompressed.
142
143 Returns
144 -------
145 G : NetworkX MultiGraph or MultiDiGraph.
146
147 Examples
148 --------
149 >>> G=nx.path_graph(4)
150 >>> nx.write_pajek(G, "test.net")
151 >>> G=nx.read_pajek("test.net")
152
153 To create a Graph instead of a MultiGraph use
154
155 >>> G1=nx.Graph(G)
156
157 References
158 ----------
159 See http://vlado.fmf.uni-lj.si/pub/networks/pajek/doc/draweps.htm
160 for format information.
161 """
162 lines = (line.decode(encoding) for line in path)
163 return parse_pajek(lines)
164
165
166 def parse_pajek(lines):
167 """Parse Pajek format graph from string or iterable.
168
169 Parameters
170 ----------
171 lines : string or iterable
172 Data in Pajek format.
173
174 Returns
175 -------
176 G : NetworkX graph
177
178 See Also
179 --------
180 read_pajek()
181
182 """
183 import shlex
184 # multigraph=False
185 if is_string_like(lines):
186 lines = iter(lines.split('\n'))
187 lines = iter([line.rstrip('\n') for line in lines])
188 G = nx.MultiDiGraph() # are multiedges allowed in Pajek? assume yes
189 labels = [] # in the order of the file, needed for matrix
190 while lines:
191 try:
192 l = next(lines)
193 except: # EOF
194 break
195 if l.lower().startswith("*network"):
196 try:
197 label, name = l.split(None, 1)
198 except ValueError:
199 # Line was not of the form: *network NAME
200 pass
201 else:
202 G.graph['name'] = name
203 elif l.lower().startswith("*vertices"):
204 nodelabels = {}
205 l, nnodes = l.split()
206 for i in range(int(nnodes)):
207 l = next(lines)
208 try:
209 splitline = [x.decode('utf-8') for x in
210 shlex.split(make_str(l).encode('utf-8'))]
211 except AttributeError:
212 splitline = shlex.split(str(l))
213 id, label = splitline[0:2]
214 labels.append(label)
215 G.add_node(label)
216 nodelabels[id] = label
217 G.nodes[label]['id'] = id
218 try:
219 x, y, shape = splitline[2:5]
220 G.nodes[label].update({'x': float(x),
221 'y': float(y),
222 'shape': shape})
223 except:
224 pass
225 extra_attr = zip(splitline[5::2], splitline[6::2])
226 G.nodes[label].update(extra_attr)
227 elif l.lower().startswith("*edges") or l.lower().startswith("*arcs"):
228 if l.lower().startswith("*edge"):
229 # switch from multidigraph to multigraph
230 G = nx.MultiGraph(G)
231 if l.lower().startswith("*arcs"):
232 # switch to directed with multiple arcs for each existing edge
233 G = G.to_directed()
234 for l in lines:
235 try:
236 splitline = [x.decode('utf-8') for x in
237 shlex.split(make_str(l).encode('utf-8'))]
238 except AttributeError:
239 splitline = shlex.split(str(l))
240
241 if len(splitline) < 2:
242 continue
243 ui, vi = splitline[0:2]
244 u = nodelabels.get(ui, ui)
245 v = nodelabels.get(vi, vi)
246 # parse the data attached to this edge and put in a dictionary
247 edge_data = {}
248 try:
249 # there should always be a single value on the edge?
250 w = splitline[2:3]
251 edge_data.update({'weight': float(w[0])})
252 except:
253 pass
254 # if there isn't, just assign a 1
255 # edge_data.update({'value':1})
256 extra_attr = zip(splitline[3::2], splitline[4::2])
257 edge_data.update(extra_attr)
258 # if G.has_edge(u,v):
259 # multigraph=True
260 G.add_edge(u, v, **edge_data)
261 elif l.lower().startswith("*matrix"):
262 G = nx.DiGraph(G)
263 adj_list = ((labels[row], labels[col], {'weight': int(data)})
264 for (row, line) in enumerate(lines)
265 for (col, data) in enumerate(line.split())
266 if int(data) != 0)
267 G.add_edges_from(adj_list)
268
269 return G
270
271
272 def make_qstr(t):
273 """Returns the string representation of t.
274 Add outer double-quotes if the string has a space.
275 """
276 if not is_string_like(t):
277 t = str(t)
278 if " " in t:
279 t = r'"%s"' % t
280 return t
281
282
283 # fixture for pytest
284 def teardown_module(module):
285 import os
286 os.unlink('test.net')