Package networkx :: Package readwrite :: Module gml
[hide private]
[frames] | no frames]

Source Code for Module networkx.readwrite.gml

  1  """ 
  2  Read graphs in GML format. 
  3  See http://www.infosun.fim.uni-passau.de/Graphlet/GML/gml-tr.html 
  4  for format specification. 
  5   
  6  Example graphs in GML format: 
  7  http://www-personal.umich.edu/~mejn/netdata/ 
  8   
  9  """ 
 10  __author__ = """Aric Hagberg (hagberg@lanl.gov)""" 
 11  #    Copyright (C) 2008 by  
 12  #    Aric Hagberg <hagberg@lanl.gov> 
 13  #    Dan Schult <dschult@colgate.edu> 
 14  #    Pieter Swart <swart@lanl.gov> 
 15  #    Distributed under the terms of the GNU Lesser General Public License 
 16  #    http://www.gnu.org/copyleft/lesser.html 
 17   
 18  import sys 
 19  import time 
 20  import networkx 
 21  from networkx.exception import NetworkXException, NetworkXError 
 22  from networkx.utils import _get_fh, is_string_like 
 23   
 24           
25 -def read_gml(path):
26 """Read graph in GML format from path. 27 Returns an XGraph or XDiGraph. 28 29 This doesn't implement the complete GML specification for 30 nested attributes for graphs, edges, and nodes. 31 32 """ 33 fh=_get_fh(path,mode='r') 34 G=parse_gml(fh) 35 return G
36 37
38 -def parse_gml(lines):
39 """Parse GML format from string or iterable. 40 Returns an XGraph or XDiGraph. 41 42 This doesn't implement the complete GML specification for 43 nested attributes for graphs, edges, and nodes. 44 """ 45 try: 46 from pyparsing import ParseException 47 except ImportError: 48 raise ImportError, \ 49 "Import Error: not able to import pyparsing: http://pyparsing.wikispaces.com/" 50 51 try: 52 data = "".join(lines) 53 gml = pyparse_gml() 54 tokens =gml.parseString(data) 55 except ParseException, err: 56 print err.line 57 print " "*(err.column-1) + "^" 58 print err 59 60 graph_attr=tokens.asDict() 61 # determine directed or undirected and init corresponding NX class 62 directed=graph_attr.get('directed',0) 63 if directed==1: 64 G=networkx.XDiGraph() 65 else: 66 G=networkx.XGraph() 67 G.node_attr={} # store node attributes here 68 G.graph_attr=graph_attr 69 70 # first pass, nodes and labels 71 label={} 72 for item in tokens: 73 if item[0]=='node': 74 d=item.asDict() 75 id=d['id'] 76 if 'label'in d: 77 label[id]=d['label'] 78 del d['label'] 79 else: 80 label[id]=id 81 del d['id'] 82 G.add_node(label[id]) 83 if len(d)==0: 84 d=None 85 G.node_attr[label[id]]=d 86 87 # second pass, edges 88 for item in tokens: 89 if item[0]=='edge': 90 d=item.asDict() 91 source=d['source'] 92 target=d['target'] 93 del d['source'] 94 del d['target'] 95 if len(d)==0: 96 d=None 97 G.add_edge(label[source],label[target],d) 98 return G
99 100 graph = None
101 -def pyparse_gml():
102 """pyparser tokenizer for GML graph format 103 104 This doesn't implement the complete GML specification for 105 nested attributes for graphs, edges, and nodes. 106 107 """ 108 global graph 109 110 try: 111 from pyparsing import \ 112 Literal, CaselessLiteral,Word,\ 113 ZeroOrMore, Group, Dict, Optional, Combine,\ 114 ParseException, restOfLine, White, alphanums, nums,\ 115 OneOrMore,quotedString,removeQuotes,dblQuotedString 116 except ImportError: 117 raise ImportError, \ 118 "Import Error: not able to import pyparsing: http://pyparsing.wikispaces.com/" 119 120 if not graph: 121 graphkey = Literal("graph").suppress() 122 lbrack = Literal("[").suppress() 123 rbrack = Literal("]").suppress() 124 pound = ("#") 125 comment = pound + Optional( restOfLine ) 126 white = White(" \t\n") 127 point = Literal(".") 128 e = CaselessLiteral("E") 129 integer = Word(nums).setParseAction(lambda s,l,t:[ int(t[0])]) 130 real = Combine( Word("+-"+nums, nums )+ 131 Optional(point+Optional(Word(nums)))+ 132 Optional(e+Word("+-"+nums, nums))).setParseAction( 133 lambda s,l,t:[ float(t[0]) ]) 134 key=Word(alphanums) 135 value=integer^real^Word(alphanums)^quotedString.setParseAction(removeQuotes) 136 keyvalue = Dict(Group(key+OneOrMore(white).suppress()\ 137 +value+OneOrMore(white).suppress())) 138 node = Group(Literal("node") + lbrack + OneOrMore(keyvalue) + rbrack) 139 edge = Group(Literal("edge") + lbrack + OneOrMore(keyvalue) + rbrack) 140 graph = graphkey + lbrack + OneOrMore(edge|node|keyvalue) + rbrack 141 graph.ignore(comment) 142 143 return graph
144
145 -def write_gml(G, path):
146 """ 147 Write the graph G in GML format to the file or file handle path. 148 149 >>> write_gml(G,"file.gml") 150 151 path can be a filehandle or a string with the name of the file. 152 153 >>> fh=open("file.gml") 154 >>> write_multiline_adjlist(G,fh) 155 156 Filenames ending in .gz or .bz2 will be compressed. 157 158 >>> write_multiline_adjlist(G,"file.gml.gz") 159 160 161 The output file will use the default text encoding on your system. 162 It is possible to write files in other encodings by opening 163 the file with the codecs module. See doc/examples/unicode.py 164 for hints. 165 166 >>> import codecs 167 >>> fh=codecs.open("file.edgelist",encoding='iso8859-1')# use iso8859-1 168 >>> write_edgelist(G,fh) 169 170 GML specifications indicate that the file should only use 171 7bit ASCII text encoding.iso8859-1 (latin-1). 172 173 Only a single level of attributes for graphs, nodes, and edges, 174 is supported. 175 176 """ 177 fh=_get_fh(path,mode='w') 178 # comments="#" 179 # pargs=comments+" "+' '.join(sys.argv) 180 # fh.write("%s\n" % (pargs)) 181 # fh.write(comments+" GMT %s\n" % (time.asctime(time.gmtime()))) 182 # fh.write(comments+" %s\n" % (G.name)) 183 184 # check for attributes or assign empty dict 185 if hasattr(G,'graph_attr'): 186 graph_attr=G.graph_attr 187 else: 188 graph_attr={} 189 if hasattr(G,'node_attr'): 190 node_attr=G.node_attr 191 else: 192 node_attr={} 193 194 indent=2*' ' 195 count=iter(range(G.number_of_nodes())) 196 node_id={} 197 198 fh.write("graph [\n") 199 # write graph attributes 200 for k,v in graph_attr.items(): 201 if is_string_like(v): 202 v='"'+v+'"' 203 fh.write(indent+"%s %s\n"%(k,v)) 204 # write nodes 205 for n in G: 206 fh.write(indent+"node [\n") 207 # get id or assign number 208 if n in node_attr: 209 nid=node_attr[n].get('id',count.next()) 210 else: 211 nid=count.next() 212 node_id[n]=nid 213 fh.write(2*indent+"id %s\n"%nid) 214 fh.write(2*indent+"label \"%s\"\n"%n) 215 if n in node_attr: 216 for k,v in node_attr[n].items(): 217 if is_string_like(v): v='"'+v+'"' 218 if k=='id': continue 219 fh.write(2*indent+"%s %s\n"%(k,v)) 220 fh.write(indent+"]\n") 221 # write edges 222 for e in G.edges_iter(): 223 if len(e)==3: 224 u,v,d=e 225 # try to guess what is on the edge and do something reasonable 226 edgedata={} 227 if d is None: # no data 228 pass 229 elif hasattr(d,'iteritems'): # try dict-like 230 edgedata=dict(d.iteritems()) 231 elif hasattr(d,'__iter__'): # some kind of container 232 edgedata['data']=d.__repr__() 233 else: # something else - string, number 234 edgedata['data']=d 235 else: 236 u,v=e 237 edgedata={} 238 fh.write(indent+"edge [\n") 239 fh.write(2*indent+"source %s\n"%node_id[u]) 240 fh.write(2*indent+"target %s\n"%node_id[v]) 241 for k,v in edgedata.items(): 242 if k=='source': continue 243 if k=='target': continue 244 if is_string_like(v): v='"'+v+'"' 245 fh.write(2*indent+"%s %s\n"%(k,v)) 246 fh.write(indent+"]\n") 247 fh.write("]\n")
248 249
250 -def _test_suite():
251 import doctest 252 suite = doctest.DocFileSuite('tests/readwrite/gml.txt', 253 package='networkx') 254 return suite
255 256 if __name__ == "__main__": 257 import os 258 import sys 259 import unittest 260 if sys.version_info[:2] < (2, 4): 261 print "Python version 2.4 or later required for tests (%d.%d detected)." % sys.version_info[:2] 262 sys.exit(-1) 263 # directory of networkx package (relative to this) 264 nxbase=sys.path[0]+os.sep+os.pardir 265 sys.path.insert(0,nxbase) # prepend to search path 266 unittest.TextTestRunner().run(_test_suite()) 267