Mercurial > repos > shellac > sam_consensus_v3
comparison env/lib/python3.9/site-packages/networkx/readwrite/multiline_adjlist.py @ 0:4f3585e2f14b draft default tip
"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author | shellac |
---|---|
date | Mon, 22 Mar 2021 18:12:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4f3585e2f14b |
---|---|
1 """ | |
2 ************************* | |
3 Multi-line Adjacency List | |
4 ************************* | |
5 Read and write NetworkX graphs as multi-line adjacency lists. | |
6 | |
7 The multi-line adjacency list format is useful for graphs with | |
8 nodes that can be meaningfully represented as strings. With this format | |
9 simple edge data can be stored but node or graph data is not. | |
10 | |
11 Format | |
12 ------ | |
13 The first label in a line is the source node label followed by the node degree | |
14 d. The next d lines are target node labels and optional edge data. | |
15 That pattern repeats for all nodes in the graph. | |
16 | |
17 The graph with edges a-b, a-c, d-e can be represented as the following | |
18 adjacency list (anything following the # in a line is a comment):: | |
19 | |
20 # example.multiline-adjlist | |
21 a 2 | |
22 b | |
23 c | |
24 d 1 | |
25 e | |
26 """ | |
27 | |
28 __all__ = [ | |
29 "generate_multiline_adjlist", | |
30 "write_multiline_adjlist", | |
31 "parse_multiline_adjlist", | |
32 "read_multiline_adjlist", | |
33 ] | |
34 | |
35 from networkx.utils import open_file | |
36 import networkx as nx | |
37 | |
38 | |
39 def generate_multiline_adjlist(G, delimiter=" "): | |
40 """Generate a single line of the graph G in multiline adjacency list format. | |
41 | |
42 Parameters | |
43 ---------- | |
44 G : NetworkX graph | |
45 | |
46 delimiter : string, optional | |
47 Separator for node labels | |
48 | |
49 Returns | |
50 ------- | |
51 lines : string | |
52 Lines of data in multiline adjlist format. | |
53 | |
54 Examples | |
55 -------- | |
56 >>> G = nx.lollipop_graph(4, 3) | |
57 >>> for line in nx.generate_multiline_adjlist(G): | |
58 ... print(line) | |
59 0 3 | |
60 1 {} | |
61 2 {} | |
62 3 {} | |
63 1 2 | |
64 2 {} | |
65 3 {} | |
66 2 1 | |
67 3 {} | |
68 3 1 | |
69 4 {} | |
70 4 1 | |
71 5 {} | |
72 5 1 | |
73 6 {} | |
74 6 0 | |
75 | |
76 See Also | |
77 -------- | |
78 write_multiline_adjlist, read_multiline_adjlist | |
79 """ | |
80 if G.is_directed(): | |
81 if G.is_multigraph(): | |
82 for s, nbrs in G.adjacency(): | |
83 nbr_edges = [ | |
84 (u, data) | |
85 for u, datadict in nbrs.items() | |
86 for key, data in datadict.items() | |
87 ] | |
88 deg = len(nbr_edges) | |
89 yield str(s) + delimiter + str(deg) | |
90 for u, d in nbr_edges: | |
91 if d is None: | |
92 yield str(u) | |
93 else: | |
94 yield str(u) + delimiter + str(d) | |
95 else: # directed single edges | |
96 for s, nbrs in G.adjacency(): | |
97 deg = len(nbrs) | |
98 yield str(s) + delimiter + str(deg) | |
99 for u, d in nbrs.items(): | |
100 if d is None: | |
101 yield str(u) | |
102 else: | |
103 yield str(u) + delimiter + str(d) | |
104 else: # undirected | |
105 if G.is_multigraph(): | |
106 seen = set() # helper dict used to avoid duplicate edges | |
107 for s, nbrs in G.adjacency(): | |
108 nbr_edges = [ | |
109 (u, data) | |
110 for u, datadict in nbrs.items() | |
111 if u not in seen | |
112 for key, data in datadict.items() | |
113 ] | |
114 deg = len(nbr_edges) | |
115 yield str(s) + delimiter + str(deg) | |
116 for u, d in nbr_edges: | |
117 if d is None: | |
118 yield str(u) | |
119 else: | |
120 yield str(u) + delimiter + str(d) | |
121 seen.add(s) | |
122 else: # undirected single edges | |
123 seen = set() # helper dict used to avoid duplicate edges | |
124 for s, nbrs in G.adjacency(): | |
125 nbr_edges = [(u, d) for u, d in nbrs.items() if u not in seen] | |
126 deg = len(nbr_edges) | |
127 yield str(s) + delimiter + str(deg) | |
128 for u, d in nbr_edges: | |
129 if d is None: | |
130 yield str(u) | |
131 else: | |
132 yield str(u) + delimiter + str(d) | |
133 seen.add(s) | |
134 | |
135 | |
136 @open_file(1, mode="wb") | |
137 def write_multiline_adjlist(G, path, delimiter=" ", comments="#", encoding="utf-8"): | |
138 """ Write the graph G in multiline adjacency list format to path | |
139 | |
140 Parameters | |
141 ---------- | |
142 G : NetworkX graph | |
143 | |
144 comments : string, optional | |
145 Marker for comment lines | |
146 | |
147 delimiter : string, optional | |
148 Separator for node labels | |
149 | |
150 encoding : string, optional | |
151 Text encoding. | |
152 | |
153 Examples | |
154 -------- | |
155 >>> G = nx.path_graph(4) | |
156 >>> nx.write_multiline_adjlist(G, "test.adjlist") | |
157 | |
158 The path can be a file handle or a string with the name of the file. If a | |
159 file handle is provided, it has to be opened in 'wb' mode. | |
160 | |
161 >>> fh = open("test.adjlist", "wb") | |
162 >>> nx.write_multiline_adjlist(G, fh) | |
163 | |
164 Filenames ending in .gz or .bz2 will be compressed. | |
165 | |
166 >>> nx.write_multiline_adjlist(G, "test.adjlist.gz") | |
167 | |
168 See Also | |
169 -------- | |
170 read_multiline_adjlist | |
171 """ | |
172 import sys | |
173 import time | |
174 | |
175 pargs = comments + " ".join(sys.argv) | |
176 header = ( | |
177 f"{pargs}\n" | |
178 + comments | |
179 + f" GMT {time.asctime(time.gmtime())}\n" | |
180 + comments | |
181 + f" {G.name}\n" | |
182 ) | |
183 path.write(header.encode(encoding)) | |
184 | |
185 for multiline in generate_multiline_adjlist(G, delimiter): | |
186 multiline += "\n" | |
187 path.write(multiline.encode(encoding)) | |
188 | |
189 | |
190 def parse_multiline_adjlist( | |
191 lines, comments="#", delimiter=None, create_using=None, nodetype=None, edgetype=None | |
192 ): | |
193 """Parse lines of a multiline adjacency list representation of a graph. | |
194 | |
195 Parameters | |
196 ---------- | |
197 lines : list or iterator of strings | |
198 Input data in multiline adjlist format | |
199 | |
200 create_using : NetworkX graph constructor, optional (default=nx.Graph) | |
201 Graph type to create. If graph instance, then cleared before populated. | |
202 | |
203 nodetype : Python type, optional | |
204 Convert nodes to this type. | |
205 | |
206 comments : string, optional | |
207 Marker for comment lines | |
208 | |
209 delimiter : string, optional | |
210 Separator for node labels. The default is whitespace. | |
211 | |
212 Returns | |
213 ------- | |
214 G: NetworkX graph | |
215 The graph corresponding to the lines in multiline adjacency list format. | |
216 | |
217 Examples | |
218 -------- | |
219 >>> lines = [ | |
220 ... "1 2", | |
221 ... "2 {'weight':3, 'name': 'Frodo'}", | |
222 ... "3 {}", | |
223 ... "2 1", | |
224 ... "5 {'weight':6, 'name': 'Saruman'}", | |
225 ... ] | |
226 >>> G = nx.parse_multiline_adjlist(iter(lines), nodetype=int) | |
227 >>> list(G) | |
228 [1, 2, 3, 5] | |
229 | |
230 """ | |
231 from ast import literal_eval | |
232 | |
233 G = nx.empty_graph(0, create_using) | |
234 for line in lines: | |
235 p = line.find(comments) | |
236 if p >= 0: | |
237 line = line[:p] | |
238 if not line: | |
239 continue | |
240 try: | |
241 (u, deg) = line.strip().split(delimiter) | |
242 deg = int(deg) | |
243 except BaseException as e: | |
244 raise TypeError(f"Failed to read node and degree on line ({line})") from e | |
245 if nodetype is not None: | |
246 try: | |
247 u = nodetype(u) | |
248 except BaseException as e: | |
249 raise TypeError( | |
250 f"Failed to convert node ({u}) to " f"type {nodetype}" | |
251 ) from e | |
252 G.add_node(u) | |
253 for i in range(deg): | |
254 while True: | |
255 try: | |
256 line = next(lines) | |
257 except StopIteration as e: | |
258 msg = f"Failed to find neighbor for node ({u})" | |
259 raise TypeError(msg) from e | |
260 p = line.find(comments) | |
261 if p >= 0: | |
262 line = line[:p] | |
263 if line: | |
264 break | |
265 vlist = line.strip().split(delimiter) | |
266 numb = len(vlist) | |
267 if numb < 1: | |
268 continue # isolated node | |
269 v = vlist.pop(0) | |
270 data = "".join(vlist) | |
271 if nodetype is not None: | |
272 try: | |
273 v = nodetype(v) | |
274 except BaseException as e: | |
275 raise TypeError( | |
276 f"Failed to convert node ({v}) " f"to type {nodetype}" | |
277 ) from e | |
278 if edgetype is not None: | |
279 try: | |
280 edgedata = {"weight": edgetype(data)} | |
281 except BaseException as e: | |
282 raise TypeError( | |
283 f"Failed to convert edge data ({data}) " f"to type {edgetype}" | |
284 ) from e | |
285 else: | |
286 try: # try to evaluate | |
287 edgedata = literal_eval(data) | |
288 except: | |
289 edgedata = {} | |
290 G.add_edge(u, v, **edgedata) | |
291 | |
292 return G | |
293 | |
294 | |
295 @open_file(0, mode="rb") | |
296 def read_multiline_adjlist( | |
297 path, | |
298 comments="#", | |
299 delimiter=None, | |
300 create_using=None, | |
301 nodetype=None, | |
302 edgetype=None, | |
303 encoding="utf-8", | |
304 ): | |
305 """Read graph in multi-line adjacency list format from path. | |
306 | |
307 Parameters | |
308 ---------- | |
309 path : string or file | |
310 Filename or file handle to read. | |
311 Filenames ending in .gz or .bz2 will be uncompressed. | |
312 | |
313 create_using : NetworkX graph constructor, optional (default=nx.Graph) | |
314 Graph type to create. If graph instance, then cleared before populated. | |
315 | |
316 nodetype : Python type, optional | |
317 Convert nodes to this type. | |
318 | |
319 edgetype : Python type, optional | |
320 Convert edge data to this type. | |
321 | |
322 comments : string, optional | |
323 Marker for comment lines | |
324 | |
325 delimiter : string, optional | |
326 Separator for node labels. The default is whitespace. | |
327 | |
328 Returns | |
329 ------- | |
330 G: NetworkX graph | |
331 | |
332 Examples | |
333 -------- | |
334 >>> G = nx.path_graph(4) | |
335 >>> nx.write_multiline_adjlist(G, "test.adjlist") | |
336 >>> G = nx.read_multiline_adjlist("test.adjlist") | |
337 | |
338 The path can be a file or a string with the name of the file. If a | |
339 file s provided, it has to be opened in 'rb' mode. | |
340 | |
341 >>> fh = open("test.adjlist", "rb") | |
342 >>> G = nx.read_multiline_adjlist(fh) | |
343 | |
344 Filenames ending in .gz or .bz2 will be compressed. | |
345 | |
346 >>> nx.write_multiline_adjlist(G, "test.adjlist.gz") | |
347 >>> G = nx.read_multiline_adjlist("test.adjlist.gz") | |
348 | |
349 The optional nodetype is a function to convert node strings to nodetype. | |
350 | |
351 For example | |
352 | |
353 >>> G = nx.read_multiline_adjlist("test.adjlist", nodetype=int) | |
354 | |
355 will attempt to convert all nodes to integer type. | |
356 | |
357 The optional edgetype is a function to convert edge data strings to | |
358 edgetype. | |
359 | |
360 >>> G = nx.read_multiline_adjlist("test.adjlist") | |
361 | |
362 The optional create_using parameter is a NetworkX graph container. | |
363 The default is Graph(), an undirected graph. To read the data as | |
364 a directed graph use | |
365 | |
366 >>> G = nx.read_multiline_adjlist("test.adjlist", create_using=nx.DiGraph) | |
367 | |
368 Notes | |
369 ----- | |
370 This format does not store graph, node, or edge data. | |
371 | |
372 See Also | |
373 -------- | |
374 write_multiline_adjlist | |
375 """ | |
376 lines = (line.decode(encoding) for line in path) | |
377 return parse_multiline_adjlist( | |
378 lines, | |
379 comments=comments, | |
380 delimiter=delimiter, | |
381 create_using=create_using, | |
382 nodetype=nodetype, | |
383 edgetype=edgetype, | |
384 ) |